You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
457 lines
13 KiB
457 lines
13 KiB
/*************************************************************************** |
|
* Copyright (C) 2008 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., * |
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
|
***************************************************************************/ |
|
|
|
#include "status_checker.h" |
|
#include "helpers.h" |
|
#include "settings.h" |
|
|
|
#define FOR_EACH_MPD_DATA(x) for (; (x); (x) = mpd_data_get_next(x)) |
|
|
|
extern MpdObj *conn; |
|
extern MpdData *playlist; |
|
|
|
extern ncmpcpp_config Config; |
|
|
|
extern Menu *mPlaylist; |
|
extern Menu *mBrowser; |
|
extern Menu *wCurrent; |
|
extern Menu *mSearcher; |
|
extern Menu *mLibArtists; |
|
extern Menu *mLibAlbums; |
|
extern Menu *mLibSongs; |
|
extern Window *wHeader; |
|
extern Window *wFooter; |
|
|
|
extern vector<Song *> vPlaylist; |
|
extern vector<Song> vSearched; |
|
extern vector<BrowsedItem> vBrowser; |
|
|
|
extern vector<string> vArtists; |
|
|
|
extern time_t block_delay; |
|
extern time_t timer; |
|
extern time_t now; |
|
|
|
extern int now_playing; |
|
extern int playing_song_scroll_begin; |
|
|
|
extern int block_statusbar_update_delay; |
|
|
|
extern string browsed_dir; |
|
|
|
extern string player_state; |
|
extern string volume_state; |
|
extern string switch_state; |
|
|
|
extern string mpd_repeat; |
|
extern string mpd_random; |
|
extern string mpd_crossfade; |
|
extern string mpd_db_updating; |
|
|
|
extern CurrScreen current_screen; |
|
|
|
extern bool header_update_status; |
|
|
|
extern bool dont_change_now_playing; |
|
extern bool allow_statusbar_unblock; |
|
extern bool block_progressbar_update; |
|
extern bool block_statusbar_update; |
|
extern bool block_playlist_update; |
|
extern bool block_library_update; |
|
|
|
extern bool redraw_me; |
|
|
|
long long playlist_old_id = -1; |
|
|
|
int old_playing; |
|
|
|
string playlist_stats; |
|
|
|
void TraceMpdStatus() |
|
{ |
|
mpd_status_update(conn); |
|
now = time(NULL); |
|
|
|
if (now == timer+Config.playlist_disable_highlight_delay && current_screen == csPlaylist) |
|
mPlaylist->Highlighting(!Config.playlist_disable_highlight_delay); |
|
|
|
if (block_statusbar_update_delay > 0) |
|
{ |
|
if (now >= block_delay+block_statusbar_update_delay) |
|
block_statusbar_update_delay = 0; |
|
} |
|
|
|
if (!block_statusbar_update_delay) |
|
{ |
|
block_statusbar_update_delay = -1; |
|
|
|
if (Config.statusbar_visibility) |
|
block_statusbar_update = !allow_statusbar_unblock; |
|
else |
|
block_progressbar_update = !allow_statusbar_unblock; |
|
|
|
switch (mpd_player_get_state(conn)) |
|
{ |
|
case MPD_PLAYER_STOP: |
|
NcmpcppStatusChanged(conn, MPD_CST_STATE); |
|
break; |
|
case MPD_PLAYER_PLAY: case MPD_PLAYER_PAUSE: |
|
NcmpcppStatusChanged(conn, MPD_CST_ELAPSED_TIME); // restore status |
|
break; |
|
} |
|
} |
|
//wHeader->WriteXY(0,1, IntoStr(now_playing), 1); |
|
} |
|
|
|
void NcmpcppErrorCallback(MpdObj *conn, int errorid, char *msg, void *userdata) |
|
{ |
|
ShowMessage(msg); |
|
} |
|
|
|
void NcmpcppStatusChanged(MpdObj *conn, ChangedStatusType what) |
|
{ |
|
int sx, sy; |
|
wFooter->DisableBB(); |
|
wFooter->AutoRefresh(0); |
|
wFooter->Bold(1); |
|
wFooter->GetXY(sx, sy); |
|
|
|
if ((now_playing != mpd_player_get_current_song_pos(conn) || what & MPD_CST_SONGID) && !dont_change_now_playing) |
|
{ |
|
old_playing = now_playing; |
|
now_playing = mpd_player_get_current_song_pos(conn); |
|
mPlaylist->BoldOption(old_playing+1, 0); |
|
mPlaylist->BoldOption(now_playing+1, 1); |
|
} |
|
|
|
if (what & MPD_CST_PLAYLIST) |
|
{ |
|
playlist_old_id = mpd_playlist_get_old_playlist_id(conn); |
|
|
|
if (!block_playlist_update) |
|
{ |
|
int playlist_length = mpd_playlist_get_playlist_length(conn); |
|
|
|
if (playlist_length != vPlaylist.size()) |
|
{ |
|
if (playlist_length < vPlaylist.size()) |
|
{ |
|
mPlaylist->Clear(!playlist_length && current_screen == csPlaylist); |
|
for (vector<Song *>::iterator it = vPlaylist.begin(); it != vPlaylist.end(); it++) |
|
delete *it; |
|
vPlaylist.clear(); |
|
playlist = mpd_playlist_get_changes(conn, -1); |
|
} |
|
else |
|
playlist = mpd_playlist_get_changes(conn, playlist_old_id); |
|
|
|
vPlaylist.reserve(playlist_length); |
|
|
|
FOR_EACH_MPD_DATA(playlist) |
|
{ |
|
Song *s = new Song(playlist->song); |
|
vPlaylist.push_back(s); |
|
if (now_playing != s->GetPosition()) |
|
mPlaylist->AddOption(DisplaySong(*s)); |
|
else |
|
mPlaylist->AddBoldOption(DisplaySong(*s)); |
|
} |
|
mpd_data_free(playlist); |
|
|
|
if (current_screen == csPlaylist) |
|
{ |
|
if (!playlist_length || mPlaylist->MaxChoice() < mPlaylist->GetHeight()) |
|
mPlaylist->Hide(); |
|
mPlaylist->Refresh(1); |
|
} |
|
} |
|
else |
|
{ |
|
int i = 1; |
|
|
|
mPlaylist->BoldOption(old_playing+1, 0); |
|
mPlaylist->BoldOption(now_playing+1, 1); |
|
|
|
playlist = mpd_playlist_get_changes(conn, -1); |
|
|
|
for (vector<Song *>::iterator it = vPlaylist.begin(); it != vPlaylist.end(); it++, i++) |
|
{ |
|
Song ss = playlist->song; |
|
ss.GetEmptyFields(1); |
|
(*it)->GetEmptyFields(1); |
|
if (**it != ss) |
|
{ |
|
(*it)->GetEmptyFields(0); |
|
ss.GetEmptyFields(0); |
|
**it = ss; |
|
mPlaylist->UpdateOption(i, DisplaySong(ss)); |
|
} |
|
playlist = mpd_data_get_next(playlist); |
|
} |
|
mpd_data_free(playlist); |
|
} |
|
} |
|
|
|
if (vPlaylist.empty()) |
|
{ |
|
playlist_stats.clear(); |
|
mPlaylist->Reset(); |
|
ShowMessage("Cleared playlist!"); |
|
} |
|
else |
|
playlist_stats = "(" + IntoStr(vPlaylist.size()) + (vPlaylist.size() == 1 ? " song" : " songs") + ", length: " + TotalPlaylistLength() + ")"; |
|
|
|
if (current_screen == csBrowser) |
|
{ |
|
bool bold = 0; |
|
for (int i = 0; i < vBrowser.size(); i++) |
|
{ |
|
if (vBrowser[i].type == MPD_DATA_TYPE_SONG) |
|
{ |
|
for (vector<Song *>::const_iterator it = vPlaylist.begin(); it != vPlaylist.end(); it++) |
|
{ |
|
if ((*it)->GetHash() == vBrowser[i].hash) |
|
{ |
|
bold = 1; |
|
break; |
|
} |
|
} |
|
mBrowser->BoldOption(i+1, bold); |
|
bold = 0; |
|
} |
|
} |
|
} |
|
if (current_screen == csSearcher) |
|
{ |
|
bool bold = 0; |
|
int i = search_engine_static_option; |
|
for (vector<Song>::const_iterator it = vSearched.begin(); it != vSearched.end(); it++, i++) |
|
{ |
|
for (vector<Song *>::const_iterator j = vPlaylist.begin(); j != vPlaylist.end(); j++) |
|
{ |
|
if ((*j)->GetHash() == it->GetHash()) |
|
{ |
|
bold = 1; |
|
break; |
|
} |
|
} |
|
mSearcher->BoldOption(i+1, bold); |
|
bold = 0; |
|
} |
|
} |
|
block_library_update = 0; |
|
} |
|
if(what & MPD_CST_DATABASE) |
|
{ |
|
GetDirectory(browsed_dir); |
|
if (!mLibArtists->Empty()) |
|
{ |
|
ShowMessage("Updating artists' list..."); |
|
mLibArtists->Clear(0); |
|
vArtists.clear(); |
|
MpdData *data = mpd_database_get_artists(conn); |
|
FOR_EACH_MPD_DATA(data) |
|
vArtists.push_back(data->tag); |
|
mpd_data_free(data); |
|
sort(vArtists.begin(), vArtists.end(), CaseInsensitiveComparison); |
|
for (vector<string>::const_iterator it = vArtists.begin(); it != vArtists.end(); it++) |
|
mLibArtists->AddOption(*it); |
|
if (current_screen == csLibrary) |
|
{ |
|
mLibArtists->Hide(); |
|
mLibArtists->Display(); |
|
} |
|
ShowMessage("List updated!"); |
|
} |
|
block_library_update = 0; |
|
} |
|
if (what & MPD_CST_STATE) |
|
{ |
|
int mpd_state = mpd_player_get_state(conn); |
|
switch (mpd_state) |
|
{ |
|
case MPD_PLAYER_PLAY: |
|
{ |
|
Song &s = *vPlaylist[now_playing]; |
|
player_state = "Playing: "; |
|
mPlaylist->BoldOption(now_playing+1, 1); |
|
break; |
|
} |
|
case MPD_PLAYER_PAUSE: |
|
{ |
|
player_state = "[Paused] "; |
|
break; |
|
} |
|
case MPD_PLAYER_STOP: |
|
{ |
|
WindowTitle("ncmpc++ ver. "VERSION); |
|
wFooter->SetColor(Config.progressbar_color); |
|
mvwhline(wFooter->RawWin(), 0, 0, 0, wFooter->GetWidth()); |
|
wFooter->SetColor(Config.statusbar_color); |
|
mPlaylist->BoldOption(old_playing+1, 0); |
|
now_playing = -1; |
|
player_state.clear(); |
|
break; |
|
} |
|
} |
|
if (!block_statusbar_update && Config.statusbar_visibility) |
|
wFooter->WriteXY(0, 1, player_state, player_state.empty()); |
|
} |
|
if ((what & MPD_CST_ELAPSED_TIME)) |
|
{ |
|
mpd_Song *current = mpd_playlist_get_current_song(conn); |
|
if (!player_state.empty() && current) |
|
{ |
|
Song s = current; |
|
|
|
WindowTitle(DisplaySong(s, Config.song_window_title_format)); |
|
|
|
int elapsed = mpd_status_get_elapsed_song_time(conn); |
|
|
|
if (!block_statusbar_update && Config.statusbar_visibility) |
|
{ |
|
string tracklength; |
|
if (s.GetTotalLength() > 0) |
|
tracklength = " [" + ShowTime(elapsed) + "/" + s.GetLength() + "]"; |
|
else |
|
tracklength = " [" + ShowTime(elapsed) + "]"; |
|
ncmpcpp_string_t playing_song = NCMPCPP_TO_WSTRING(OmitBBCodes(DisplaySong(s, Config.song_status_format))); |
|
|
|
int max_length_without_scroll = wFooter->GetWidth()-player_state.length()-tracklength.length(); |
|
|
|
wFooter->WriteXY(0, 1, player_state); |
|
wFooter->Bold(0); |
|
if (playing_song.length() > max_length_without_scroll) |
|
{ |
|
# ifdef UTF8_ENABLED |
|
playing_song += L" ** "; |
|
# else |
|
playing_song += " ** "; |
|
# endif |
|
const int scrollsize = max_length_without_scroll+playing_song.length(); |
|
ncmpcpp_string_t part = playing_song.substr(playing_song_scroll_begin++, scrollsize); |
|
if (part.length() < scrollsize) |
|
part += playing_song.substr(0, scrollsize-part.length()); |
|
wFooter->WriteXY(player_state.length(), 1, part); |
|
if (playing_song_scroll_begin >= playing_song.length()) |
|
playing_song_scroll_begin = 0; |
|
} |
|
else |
|
wFooter->WriteXY(player_state.length(), 1, OmitBBCodes(DisplaySong(s, Config.song_status_format)), 1); |
|
wFooter->Bold(1); |
|
|
|
wFooter->WriteXY(wFooter->GetWidth()-tracklength.length(), 1, tracklength); |
|
} |
|
if (!block_progressbar_update) |
|
{ |
|
double progressbar_size = (double)elapsed/(s.GetMinutesLength()*60+s.GetSecondsLength()); |
|
int howlong = wFooter->GetWidth()*progressbar_size; |
|
wFooter->SetColor(Config.progressbar_color); |
|
mvwhline(wFooter->RawWin(), 0, 0, 0, wFooter->GetWidth()); |
|
mvwhline(wFooter->RawWin(), 0, 0, '=',howlong); |
|
mvwaddch(wFooter->RawWin(), 0, howlong, '>'); |
|
wFooter->SetColor(Config.statusbar_color); |
|
} |
|
} |
|
else |
|
{ |
|
if (!block_statusbar_update && Config.statusbar_visibility) |
|
wFooter->WriteXY(0, 1, "", 1); |
|
} |
|
} |
|
if (what & MPD_CST_REPEAT) |
|
{ |
|
mpd_repeat = (mpd_player_get_repeat(conn) ? "r" : ""); |
|
ShowMessage("Repeat is " + (string)(mpd_repeat.empty() ? "off" : "on")); |
|
header_update_status = 1; |
|
|
|
} |
|
if (what & MPD_CST_RANDOM) |
|
{ |
|
mpd_random = mpd_player_get_random(conn) ? "z" : ""; |
|
ShowMessage("Random is " + (string)(mpd_random.empty() ? "off" : "on")); |
|
header_update_status = 1; |
|
} |
|
if (what & MPD_CST_CROSSFADE) |
|
{ |
|
int crossfade = mpd_status_get_crossfade(conn); |
|
mpd_crossfade = crossfade ? "x" : ""; |
|
ShowMessage("Crossfade set to " + IntoStr(crossfade) + " seconds"); |
|
header_update_status = 1; |
|
} |
|
if (what & MPD_CST_UPDATING) |
|
{ |
|
mpd_db_updating = mpd_status_db_is_updating(conn) ? "U" : ""; |
|
ShowMessage(mpd_db_updating.empty() ? "Database update finished!" : "Database update started!"); |
|
header_update_status = 1; |
|
} |
|
if (header_update_status && Config.header_visibility) |
|
{ |
|
switch_state = mpd_repeat + mpd_random + mpd_crossfade + mpd_db_updating; |
|
|
|
wHeader->DisableBB(); |
|
wHeader->Bold(1); |
|
wHeader->SetColor(Config.state_line_color); |
|
mvwhline(wHeader->RawWin(), 1, 0, 0, wHeader->GetWidth()); |
|
if (!switch_state.empty()) |
|
{ |
|
wHeader->WriteXY(wHeader->GetWidth()-switch_state.length()-3, 1, "["); |
|
wHeader->SetColor(Config.state_flags_color); |
|
wHeader->WriteXY(wHeader->GetWidth()-switch_state.length()-2, 1, switch_state); |
|
wHeader->SetColor(Config.state_line_color); |
|
wHeader->WriteXY(wHeader->GetWidth()-2, 1, "]"); |
|
} |
|
wHeader->Refresh(); |
|
wHeader->SetColor(Config.header_color); |
|
wHeader->Bold(0); |
|
wHeader->EnableBB(); |
|
header_update_status = 0; |
|
} |
|
if (what & MPD_CST_SONGID) |
|
{ |
|
if (!vPlaylist.empty() && now_playing >= 0) |
|
{ |
|
if (!mPlaylist->Empty()) |
|
{ |
|
if (old_playing >= 0) |
|
mPlaylist->BoldOption(old_playing+1, 0); |
|
mPlaylist->BoldOption(now_playing+1, 1); |
|
} |
|
if (!mpd_status_get_elapsed_song_time(conn)) |
|
mvwhline(wFooter->RawWin(), 0, 0, 0, wFooter->GetWidth()); |
|
} |
|
playing_song_scroll_begin = 0; |
|
} |
|
if ((what & MPD_CST_VOLUME) && Config.header_visibility) |
|
{ |
|
int vol = mpd_status_get_volume(conn); |
|
volume_state = " Volume: " + IntoStr(vol) + "%"; |
|
wHeader->SetColor(Config.volume_color); |
|
wHeader->WriteXY(wHeader->GetWidth()-volume_state.length(), 0, volume_state); |
|
wHeader->SetColor(Config.header_color); |
|
} |
|
wFooter->Bold(0); |
|
wFooter->GotoXY(sx, sy); |
|
wFooter->Refresh(); |
|
wFooter->AutoRefresh(1); |
|
wFooter->EnableBB(); |
|
wCurrent->Refresh(); |
|
} |
|
|
|
|