/*************************************************************************** * 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 vPlaylist; extern vector vSearched; extern vector vBrowser; extern vector 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::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::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::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::const_iterator it = vSearched.begin(); it != vSearched.end(); it++, i++) { for (vector::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::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(); }