new screen: mpd server info

This commit is contained in:
Andrzej Rybczak
2009-10-11 17:03:00 +02:00
parent aebc5db0e1
commit 03f6fd904f
14 changed files with 322 additions and 52 deletions

View File

@@ -62,6 +62,8 @@
# #
#key_clock = '0' 274 #key_clock = '0' 274
# #
#key_server_info = '@'
#
#key_stop = 's' #key_stop = 's'
# #
#key_pause = 'P' #key_pause = 'P'

View File

@@ -2,8 +2,8 @@ bin_PROGRAMS = ncmpcpp
ncmpcpp_SOURCES = browser.cpp charset.cpp clock.cpp conv.cpp display.cpp \ ncmpcpp_SOURCES = browser.cpp charset.cpp clock.cpp conv.cpp display.cpp \
error.cpp help.cpp helpers.cpp info.cpp lyrics.cpp media_library.cpp menu.cpp \ error.cpp help.cpp helpers.cpp info.cpp lyrics.cpp media_library.cpp menu.cpp \
misc.cpp mpdpp.cpp ncmpcpp.cpp outputs.cpp playlist.cpp playlist_editor.cpp \ misc.cpp mpdpp.cpp ncmpcpp.cpp outputs.cpp playlist.cpp playlist_editor.cpp \
scrollpad.cpp search_engine.cpp settings.cpp song.cpp status.cpp tag_editor.cpp \ scrollpad.cpp search_engine.cpp server_info.cpp settings.cpp song.cpp status.cpp \
tiny_tag_editor.cpp visualizer.cpp window.cpp tag_editor.cpp tiny_tag_editor.cpp visualizer.cpp window.cpp
# set the include path found by configure # set the include path found by configure
INCLUDES= $(all_includes) INCLUDES= $(all_includes)
@@ -11,6 +11,7 @@ INCLUDES= $(all_includes)
# the library search path. # the library search path.
ncmpcpp_LDFLAGS = $(all_libraries) ncmpcpp_LDFLAGS = $(all_libraries)
noinst_HEADERS = browser.h charset.h clock.h conv.h display.h error.h global.h \ noinst_HEADERS = browser.h charset.h clock.h conv.h display.h error.h global.h \
help.h helpers.h home.h info.h lyrics.h media_library.h menu.h misc.h mpdpp.h \ help.h helpers.h home.h info.h lyrics.h media_library.h menu.h misc.h \
outputs.h playlist_editor.h screen.h scrollpad.h search_engine.h settings.h \ mpdpp.h outputs.h playlist_editor.h screen.h scrollpad.h search_engine.h \
song.h tag_editor.h tiny_tag_editor.h visualizer.h window.h server_info.h settings.h song.h tag_editor.h tiny_tag_editor.h visualizer.h \
window.h

View File

@@ -153,7 +153,8 @@ void Help::GetKeybindings()
# ifdef ENABLE_CLOCK # ifdef ENABLE_CLOCK
*w << DisplayKeys(Key.Clock) << "Clock screen\n"; *w << DisplayKeys(Key.Clock) << "Clock screen\n";
# endif // ENABLE_CLOCK # endif // ENABLE_CLOCK
*w << "\n";
*w << DisplayKeys(Key.ServerInfo) << "MPD server info\n";
*w << "\n\n " << fmtBold << "Keys - Global\n -----------------------------------------\n" << fmtBoldEnd; *w << "\n\n " << fmtBold << "Keys - Global\n -----------------------------------------\n" << fmtBoldEnd;
*w << DisplayKeys(Key.Stop) << "Stop\n"; *w << DisplayKeys(Key.Stop) << "Stop\n";

View File

@@ -244,6 +244,14 @@ bool CaseInsensitiveSorting::operator()(const Item &a, const Item &b)
return a.type < b.type; return a.type < b.type;
} }
std::string Timestamp(time_t t)
{
char result[32];
tm info;
result[strftime(result, 31, "%x %X", localtime_r(&t, &info))] = 0;
return result;
}
void UpdateSongList(Menu<Song> *menu) void UpdateSongList(Menu<Song> *menu)
{ {
bool bold = 0; bool bold = 0;

View File

@@ -162,6 +162,49 @@ template <typename C> void String2Buffer(const std::basic_string<C> &s, basic_bu
} }
} }
template <typename T> void ShowTime(T &buf, size_t length, bool short_names)
{
const unsigned MINUTE = 60;
const unsigned HOUR = 60*MINUTE;
const unsigned DAY = 24*HOUR;
const unsigned YEAR = 365*DAY;
unsigned years = length/YEAR;
if (years)
{
buf << years << (short_names ? "y" : (years == 1 ? " year" : " years"));
length -= years*YEAR;
if (length)
buf << ", ";
}
unsigned days = length/DAY;
if (days)
{
buf << days << (short_names ? "d" : (days == 1 ? " day" : " days"));
length -= days*DAY;
if (length)
buf << ", ";
}
unsigned hours = length/HOUR;
if (hours)
{
buf << hours << (short_names ? "h" : (hours == 1 ? " hour" : " hours"));
length -= hours*HOUR;
if (length)
buf << ", ";
}
unsigned minutes = length/MINUTE;
if (minutes)
{
buf << minutes << (short_names ? "m" : (minutes == 1 ? " minute" : " minutes"));
length -= minutes*MINUTE;
if (length)
buf << ", ";
}
if (length)
buf << length << (short_names ? "s" : (length == 1 ? " second" : " seconds"));
}
template <typename T> void ShowTag(T &buf, const std::string &tag) template <typename T> void ShowTag(T &buf, const std::string &tag)
{ {
if (tag.empty()) if (tag.empty())
@@ -175,6 +218,8 @@ inline bool Keypressed(int in, const int *key)
return in == key[0] || in == key[1]; return in == key[0] || in == key[1];
} }
std::string Timestamp(time_t t);
void UpdateSongList(Menu<MPD::Song> *); void UpdateSongList(Menu<MPD::Song> *);
#ifdef HAVE_TAGLIB_H #ifdef HAVE_TAGLIB_H

View File

@@ -41,6 +41,7 @@ Connection::Connection() : itsConnection(0),
itsTimeout(15), itsTimeout(15),
itsCurrentStatus(0), itsCurrentStatus(0),
itsOldStatus(0), itsOldStatus(0),
itsStats(0),
itsUpdater(0), itsUpdater(0),
itsErrorHandler(0) itsErrorHandler(0)
{ {
@@ -50,6 +51,8 @@ Connection::~Connection()
{ {
if (itsConnection) if (itsConnection)
mpd_connection_free(itsConnection); mpd_connection_free(itsConnection);
if (itsStats)
mpd_stats_free(itsStats);
if (itsOldStatus) if (itsOldStatus)
mpd_status_free(itsOldStatus); mpd_status_free(itsOldStatus);
if (itsCurrentStatus) if (itsCurrentStatus)
@@ -77,6 +80,8 @@ void Connection::Disconnect()
{ {
if (itsConnection) if (itsConnection)
mpd_connection_free(itsConnection); mpd_connection_free(itsConnection);
if (itsStats)
mpd_stats_free(itsStats);
if (itsOldStatus) if (itsOldStatus)
mpd_status_free(itsOldStatus); mpd_status_free(itsOldStatus);
if (itsCurrentStatus) if (itsCurrentStatus)
@@ -84,6 +89,7 @@ void Connection::Disconnect()
itsConnection = 0; itsConnection = 0;
itsCurrentStatus = 0; itsCurrentStatus = 0;
itsOldStatus = 0; itsOldStatus = 0;
itsStats = 0;
isCommandsListEnabled = 0; isCommandsListEnabled = 0;
itsMaxPlaylistLength = -1; itsMaxPlaylistLength = -1;
} }
@@ -187,6 +193,15 @@ void Connection::UpdateStatus()
} }
} }
void Connection::UpdateStats()
{
if (!itsConnection)
return;
if (itsStats)
mpd_stats_free(itsStats);
itsStats = mpd_run_stats(itsConnection);
}
bool Connection::UpdateDirectory(const std::string &path) bool Connection::UpdateDirectory(const std::string &path)
{ {
if (!itsConnection) if (!itsConnection)
@@ -729,6 +744,32 @@ bool Connection::DisableOutput(int id)
return mpd_run_disable_output(itsConnection, id); return mpd_run_disable_output(itsConnection, id);
} }
void Connection::GetURLHandlers(TagList &v) const
{
if (!itsConnection)
return;
mpd_send_list_url_schemes(itsConnection);
while (mpd_pair *handler = mpd_recv_pair_named(itsConnection, "handler"))
{
v.push_back(handler->value);
mpd_return_pair(itsConnection, handler);
}
mpd_response_finish(itsConnection);
}
void Connection::GetTagTypes(TagList &v) const
{
if (!itsConnection)
return;
mpd_send_list_tag_types(itsConnection);
while (mpd_pair *tag_type = mpd_recv_pair_named(itsConnection, "tagtype"))
{
v.push_back(tag_type->value);
mpd_return_pair(itsConnection, tag_type);
}
mpd_response_finish(itsConnection);
}
int Connection::CheckForErrors() int Connection::CheckForErrors()
{ {
if ((itsErrorCode = mpd_connection_get_error(itsConnection)) != MPD_ERROR_SUCCESS) if ((itsErrorCode = mpd_connection_get_error(itsConnection)) != MPD_ERROR_SUCCESS)

View File

@@ -101,6 +101,7 @@ namespace MPD
void SetStatusUpdater(StatusUpdater, void *); void SetStatusUpdater(StatusUpdater, void *);
void SetErrorHandler(ErrorHandler, void *); void SetErrorHandler(ErrorHandler, void *);
void UpdateStatus(); void UpdateStatus();
void UpdateStats();
bool UpdateDirectory(const std::string &); bool UpdateDirectory(const std::string &);
void Play() const; void Play() const;
@@ -133,6 +134,14 @@ namespace MPD
int GetTotalTime() const { return itsCurrentStatus ? mpd_status_get_total_time(itsCurrentStatus) : 0; } int GetTotalTime() const { return itsCurrentStatus ? mpd_status_get_total_time(itsCurrentStatus) : 0; }
unsigned GetBitrate() const { return itsCurrentStatus ? mpd_status_get_kbit_rate(itsCurrentStatus) : 0; } unsigned GetBitrate() const { return itsCurrentStatus ? mpd_status_get_kbit_rate(itsCurrentStatus) : 0; }
unsigned NumberOfArtists() const { return itsStats ? mpd_stats_get_number_of_artists(itsStats) : 0; }
unsigned NumberOfAlbums() const { return itsStats ? mpd_stats_get_number_of_albums(itsStats) : 0; }
unsigned NumberOfSongs() const { return itsStats ? mpd_stats_get_number_of_songs(itsStats) : 0; }
unsigned long Uptime() const { return itsStats ? mpd_stats_get_uptime(itsStats) : 0; }
unsigned long DBUpdateTime() const { return itsStats ? mpd_stats_get_db_update_time(itsStats) : 0; }
unsigned long PlayTime() const { return itsStats ? mpd_stats_get_play_time(itsStats) : 0; }
unsigned long DBPlayTime() const { return itsStats ? mpd_stats_get_db_play_time(itsStats) : 0; }
size_t GetMaxPlaylistLength() const { return itsMaxPlaylistLength; } size_t GetMaxPlaylistLength() const { return itsMaxPlaylistLength; }
size_t GetPlaylistLength() const { return itsCurrentStatus ? mpd_status_get_queue_length(itsCurrentStatus) : 0; } size_t GetPlaylistLength() const { return itsCurrentStatus ? mpd_status_get_queue_length(itsCurrentStatus) : 0; }
void GetPlaylistChanges(unsigned, SongList &) const; void GetPlaylistChanges(unsigned, SongList &) const;
@@ -188,6 +197,9 @@ namespace MPD
bool EnableOutput(int); bool EnableOutput(int);
bool DisableOutput(int); bool DisableOutput(int);
void GetURLHandlers(TagList &v) const;
void GetTagTypes(TagList &v) const;
private: private:
int CheckForErrors(); int CheckForErrors();
@@ -205,6 +217,7 @@ namespace MPD
mpd_status *itsCurrentStatus; mpd_status *itsCurrentStatus;
mpd_status *itsOldStatus; mpd_status *itsOldStatus;
mpd_stats *itsStats;
StatusChanges itsChanges; StatusChanges itsChanges;

View File

@@ -40,6 +40,7 @@
#include "helpers.h" #include "helpers.h"
#include "media_library.h" #include "media_library.h"
#include "misc.h" #include "misc.h"
#include "server_info.h"
#include "lyrics.h" #include "lyrics.h"
#include "playlist.h" #include "playlist.h"
#include "playlist_editor.h" #include "playlist_editor.h"
@@ -1933,6 +1934,10 @@ int main(int argc, char *argv[])
myClock->SwitchTo(); myClock->SwitchTo();
} }
# endif // ENABLE_CLOCK # endif // ENABLE_CLOCK
else if (Keypressed(input, Key.ServerInfo))
{
myServerInfo->SwitchTo();
}
// key mapping end // key mapping end
} }
return 0; return 0;

View File

@@ -361,60 +361,17 @@ std::string Playlist::TotalLength()
if (itsTotalLength) if (itsTotalLength)
{ {
result << ", length: "; result << ", length: ";
ShowTime(result, itsTotalLength); ShowTime(result, itsTotalLength, 0);
} }
if (Config.playlist_show_remaining_time && itsRemainingTime && !Items->isFiltered() && Items->Size() > 1) if (Config.playlist_show_remaining_time && itsRemainingTime && !Items->isFiltered() && Items->Size() > 1)
{ {
result << " :: remaining: "; result << " :: remaining: ";
ShowTime(result, itsRemainingTime); ShowTime(result, itsRemainingTime, 0);
} }
result << ')'; result << ')';
return result.str(); return result.str();
} }
void Playlist::ShowTime(std::ostringstream &result, size_t length)
{
const int MINUTE = 60;
const int HOUR = 60*MINUTE;
const int DAY = 24*HOUR;
const int YEAR = 365*DAY;
int years = length/YEAR;
if (years)
{
result << years << (years == 1 ? " year" : " years");
length -= years*YEAR;
if (length)
result << ", ";
}
int days = length/DAY;
if (days)
{
result << days << (days == 1 ? " day" : " days");
length -= days*DAY;
if (length)
result << ", ";
}
int hours = length/HOUR;
if (hours)
{
result << hours << (hours == 1 ? " hour" : " hours");
length -= hours*HOUR;
if (length)
result << ", ";
}
int minutes = length/MINUTE;
if (minutes)
{
result << minutes << (minutes == 1 ? " minute" : " minutes");
length -= minutes*MINUTE;
if (length)
result << ", ";
}
if (length)
result << length << (length == 1 ? " second" : " seconds");
}
const MPD::Song *Playlist::NowPlayingSong() const MPD::Song *Playlist::NowPlayingSong()
{ {
bool was_filtered = Items->isFiltered(); bool was_filtered = Items->isFiltered();

View File

@@ -94,7 +94,6 @@ class Playlist : public Screen<Window>
time_t itsTimer; time_t itsTimer;
static void ShowTime(std::ostringstream &, size_t);
static bool Sorting(MPD::Song *a, MPD::Song *b); static bool Sorting(MPD::Song *a, MPD::Song *b);
static Menu< std::pair<std::string, MPD::Song::GetFunction> > *SortDialog; static Menu< std::pair<std::string, MPD::Song::GetFunction> > *SortDialog;

134
src/server_info.cpp Normal file
View File

@@ -0,0 +1,134 @@
/***************************************************************************
* Copyright (C) 2008-2009 by Andrzej Rybczak *
* electricityispower@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include <iomanip>
#include "global.h"
#include "server_info.h"
using Global::MainHeight;
using Global::MainStartY;
using Global::myScreen;
using Global::myOldScreen;
ServerInfo *myServerInfo = new ServerInfo;
void ServerInfo::Init()
{
SetDimensions();
w = new Scrollpad((COLS-itsWidth)/2, (MainHeight-itsHeight)/2+MainStartY, itsWidth, itsHeight, "MPD server info", Config.main_color, Config.window_border);
w->SetTimeout(ncmpcpp_window_timeout);
Mpd.GetURLHandlers(itsURLHandlers);
Mpd.GetTagTypes(itsTagTypes);
isInitialized = 1;
}
void ServerInfo::SwitchTo()
{
if (myScreen == this)
{
myOldScreen->SwitchTo();
return;
}
if (MainHeight < 5)
{
ShowMessage("Screen is too small to display this window!");
return;
}
if (!isInitialized)
Init();
// Resize() can fall back to old screen, so we need it updated
myOldScreen = myScreen;
if (hasToBeResized)
Resize();
myScreen = this;
w->Window::Clear();
}
void ServerInfo::Resize()
{
SetDimensions();
if (itsHeight < 5) // screen too low to display this window
return myOldScreen->SwitchTo();
w->Resize(itsWidth, itsHeight);
w->MoveTo((COLS-itsWidth)/2, (MainHeight-itsHeight)/2+MainStartY);
if (myOldScreen && myOldScreen->hasToBeResized) // resize background window
{
myOldScreen->Resize();
myOldScreen->Refresh();
}
hasToBeResized = 0;
}
std::basic_string<my_char_t> ServerInfo::Title()
{
return myOldScreen->Title();
}
void ServerInfo::Update()
{
static time_t now = 0, past;
time(&past);
if (past <= now)
return;
time(&now);
Mpd.UpdateStats();
w->Clear(0);
*w << fmtBold << U("Version: ") << fmtBoldEnd << U("0.") << std::fixed << std::setprecision(1) << Mpd.Version() << '\n';
*w << fmtBold << U("Uptime: ") << fmtBoldEnd;
ShowTime(*w, Mpd.Uptime(), 1);
*w << '\n';
*w << fmtBold << U("Time playing: ") << fmtBoldEnd << MPD::Song::ShowTime(Mpd.PlayTime()) << '\n';
*w << '\n';
*w << fmtBold << U("Total playtime: ") << fmtBoldEnd;
ShowTime(*w, Mpd.DBPlayTime(), 1);
*w << '\n';
*w << fmtBold << U("Number of artists: ") << fmtBoldEnd << Mpd.NumberOfArtists() << '\n';
*w << fmtBold << U("Number of albums: ") << fmtBoldEnd << Mpd.NumberOfAlbums() << '\n';
*w << fmtBold << U("Number of songs: ") << fmtBoldEnd << Mpd.NumberOfSongs() << '\n';
*w << '\n';
*w << fmtBold << U("Last DB update: ") << fmtBoldEnd << Timestamp(Mpd.DBUpdateTime()) << '\n';
*w << '\n';
*w << fmtBold << U("URL Handlers:") << fmtBoldEnd;
for (MPD::TagList::const_iterator it = itsURLHandlers.begin(); it != itsURLHandlers.end(); ++it)
*w << (it != itsURLHandlers.begin() ? U(", ") : U(" ")) << *it;
*w << U("\n\n");
*w << fmtBold << U("Tag Types:") << fmtBoldEnd;
for (MPD::TagList::const_iterator it = itsTagTypes.begin(); it != itsTagTypes.end(); ++it)
*w << (it != itsTagTypes.begin() ? U(", ") : U(" ")) << *it;
w->Flush();
w->Refresh();
}
void ServerInfo::SetDimensions()
{
itsWidth = COLS*0.6;
itsHeight = std::min(size_t(LINES*0.7), MainHeight);
}

59
src/server_info.h Normal file
View File

@@ -0,0 +1,59 @@
/***************************************************************************
* Copyright (C) 2008-2009 by Andrzej Rybczak *
* electricityispower@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef _SERVER_INFO
#define _SERVER_INFO
#include "screen.h"
class ServerInfo : public Screen<Scrollpad>
{
public:
virtual void SwitchTo();
virtual void Resize();
virtual std::basic_string<my_char_t> Title();
virtual void Update();
virtual void EnterPressed() { }
virtual void SpacePressed() { }
virtual bool allowsSelection() { return false; }
virtual List *GetList() { return 0; }
protected:
virtual void Init();
private:
void SetDimensions();
MPD::TagList itsURLHandlers;
MPD::TagList itsTagTypes;
size_t itsWidth;
size_t itsHeight;
};
extern ServerInfo *myServerInfo;
#endif

View File

@@ -123,6 +123,7 @@ void DefaultKeys(ncmpcpp_keys &keys)
keys.Outputs[0] = '8'; keys.Outputs[0] = '8';
keys.Visualizer[0] = '9'; keys.Visualizer[0] = '9';
keys.Clock[0] = '0'; keys.Clock[0] = '0';
keys.ServerInfo[0] = '@';
keys.Stop[0] = 's'; keys.Stop[0] = 's';
keys.Pause[0] = 'P'; keys.Pause[0] = 'P';
keys.Next[0] = '>'; keys.Next[0] = '>';
@@ -194,6 +195,7 @@ void DefaultKeys(ncmpcpp_keys &keys)
keys.Outputs[1] = 272; keys.Outputs[1] = 272;
keys.Visualizer[1] = 273; keys.Visualizer[1] = 273;
keys.Clock[1] = 274; keys.Clock[1] = 274;
keys.ServerInfo[1] = null_key;
keys.Stop[1] = null_key; keys.Stop[1] = null_key;
keys.Pause[1] = null_key; keys.Pause[1] = null_key;
keys.Next[1] = null_key; keys.Next[1] = null_key;
@@ -388,6 +390,8 @@ void ReadKeys(ncmpcpp_keys &keys)
GetKeys(key, keys.Visualizer); GetKeys(key, keys.Visualizer);
else if (key.find("key_clock ") != std::string::npos) else if (key.find("key_clock ") != std::string::npos)
GetKeys(key, keys.Clock); GetKeys(key, keys.Clock);
else if (key.find("key_server_info ") != std::string::npos)
GetKeys(key, keys.ServerInfo);
else if (key.find("key_stop ") != std::string::npos) else if (key.find("key_stop ") != std::string::npos)
GetKeys(key, keys.Stop); GetKeys(key, keys.Stop);
else if (key.find("key_pause ") != std::string::npos) else if (key.find("key_pause ") != std::string::npos)

View File

@@ -74,6 +74,7 @@ struct ncmpcpp_keys
int Outputs[2]; int Outputs[2];
int Visualizer[2]; int Visualizer[2];
int Clock[2]; int Clock[2];
int ServerInfo[2];
int Stop[2]; int Stop[2];
int Pause[2]; int Pause[2];
int Next[2]; int Next[2];