rewrite communication system with mpd

This commit is contained in:
Andrzej Rybczak
2013-04-06 19:01:27 +02:00
parent 153e843774
commit 6a3eb73a49
25 changed files with 1039 additions and 1470 deletions

View File

@@ -255,11 +255,20 @@ void setWindowsDimensions()
bool connectToMPD() bool connectToMPD()
{ {
if (!Mpd.Connect()) try
{
Mpd.Connect();
if (Mpd.Version() < 16)
{
std::cout << "MPD < 0.16.0 is not supported, please upgrade\n";
return false;
}
}
catch (std::exception &e)
{ {
std::cout << "Couldn't connect to MPD "; std::cout << "Couldn't connect to MPD ";
std::cout << "(host = " << Mpd.GetHostname() << ", port = " << Mpd.GetPort() << ")"; std::cout << "(host = " << Mpd.GetHostname() << ", port = " << Mpd.GetPort() << ")";
std::cout << ": " << Mpd.GetErrorMessage() << std::endl; std::cout << ": " << e.what() << std::endl;
return false; return false;
} }
return true; return true;
@@ -341,13 +350,13 @@ void MouseEvent::run()
&& m_mouse_event.y == LINES-(Config.statusbar_visibility ? 2 : 1) && m_mouse_event.y == LINES-(Config.statusbar_visibility ? 2 : 1)
) // progressbar ) // progressbar
{ {
if (!Mpd.isPlaying()) if (MpdStatus.playerState() == MPD::psStop)
return; return;
Mpd.Seek(Mpd.GetTotalTime()*m_mouse_event.x/double(COLS)); Mpd.Seek(MpdStatus.totalTime()*m_mouse_event.x/double(COLS));
} }
else if (m_mouse_event.bstate & BUTTON1_PRESSED else if (m_mouse_event.bstate & BUTTON1_PRESSED
&& (Config.statusbar_visibility || Config.new_design) && (Config.statusbar_visibility || Config.new_design)
&& Mpd.isPlaying() && MpdStatus.playerState() != MPD::psStop
&& m_mouse_event.y == (Config.new_design ? 1 : LINES-1) && m_mouse_event.x < 9 && m_mouse_event.y == (Config.new_design ? 1 : LINES-1) && m_mouse_event.x < 9
) // playing/paused ) // playing/paused
{ {
@@ -359,9 +368,9 @@ void MouseEvent::run()
) // volume ) // volume
{ {
if (m_mouse_event.bstate & BUTTON2_PRESSED) if (m_mouse_event.bstate & BUTTON2_PRESSED)
Mpd.SetVolume(Mpd.GetVolume()-2); Mpd.SetVolume(MpdStatus.volume()-2);
else else
Mpd.SetVolume(Mpd.GetVolume()+2); Mpd.SetVolume(MpdStatus.volume()+2);
} }
else if (m_mouse_event.bstate & (BUTTON1_PRESSED | BUTTON2_PRESSED | BUTTON3_PRESSED | BUTTON4_PRESSED)) else if (m_mouse_event.bstate & (BUTTON1_PRESSED | BUTTON2_PRESSED | BUTTON3_PRESSED | BUTTON4_PRESSED))
myScreen->mouseButtonPressed(m_mouse_event); myScreen->mouseButtonPressed(m_mouse_event);
@@ -503,8 +512,8 @@ void ToggleInterface::run()
Progressbar::unlock(); Progressbar::unlock();
Statusbar::unlock(); Statusbar::unlock();
resizeScreen(false); resizeScreen(false);
if (!Mpd.isPlaying()) Status::Changes::mixer();
Status::Changes::mixer(); Status::Changes::elapsedTime();
Statusbar::msg("User interface: %s", Config.new_design ? "Alternative" : "Classic"); Statusbar::msg("User interface: %s", Config.new_design ? "Alternative" : "Classic");
} }
@@ -615,13 +624,13 @@ void SlaveScreen::run()
void VolumeUp::run() void VolumeUp::run()
{ {
int volume = std::min(Mpd.GetVolume()+Config.volume_change_step, 100); int volume = std::min(MpdStatus.volume()+Config.volume_change_step, 100);
Mpd.SetVolume(volume); Mpd.SetVolume(volume);
} }
void VolumeDown::run() void VolumeDown::run()
{ {
int volume = std::max(Mpd.GetVolume()-Config.volume_change_step, 0); int volume = std::max(MpdStatus.volume()-Config.volume_change_step, 0);
Mpd.SetVolume(volume); Mpd.SetVolume(volume);
} }
@@ -637,16 +646,16 @@ void DeletePlaylistItems::run()
{ {
Statusbar::msg("Deleting items..."); Statusbar::msg("Deleting items...");
auto delete_fun = std::bind(&MPD::Connection::Delete, _1, _2); auto delete_fun = std::bind(&MPD::Connection::Delete, _1, _2);
if (deleteSelectedSongs(myPlaylist->main(), delete_fun)) deleteSelectedSongs(myPlaylist->main(), delete_fun);
Statusbar::msg("Item(s) deleted"); Statusbar::msg("Item(s) deleted");
} }
else if (myScreen->isActiveWindow(myPlaylistEditor->Content)) else if (myScreen->isActiveWindow(myPlaylistEditor->Content))
{ {
std::string playlist = myPlaylistEditor->Playlists.current().value(); std::string playlist = myPlaylistEditor->Playlists.current().value();
auto delete_fun = std::bind(&MPD::Connection::PlaylistDelete, _1, playlist, _2); auto delete_fun = std::bind(&MPD::Connection::PlaylistDelete, _1, playlist, _2);
Statusbar::msg("Deleting items..."); Statusbar::msg("Deleting items...");
if (deleteSelectedSongs(myPlaylistEditor->Content, delete_fun)) deleteSelectedSongs(myPlaylistEditor->Content, delete_fun);
Statusbar::msg("Item(s) deleted"); Statusbar::msg("Item(s) deleted");
} }
} }
@@ -730,8 +739,8 @@ void DeleteStoredPlaylist::run()
Mpd.StartCommandsList(); Mpd.StartCommandsList();
for (auto it = list.begin(); it != list.end(); ++it) for (auto it = list.begin(); it != list.end(); ++it)
Mpd.DeletePlaylist((*it)->value()); Mpd.DeletePlaylist((*it)->value());
if (Mpd.CommitCommandsList()) Mpd.CommitCommandsList();
Statusbar::msg("Playlist%s deleted", list.size() == 1 ? "" : "s"); Statusbar::msg("Playlist%s deleted", list.size() == 1 ? "" : "s");
} }
else else
Statusbar::msg("Aborted"); Statusbar::msg("Aborted");
@@ -739,7 +748,7 @@ void DeleteStoredPlaylist::run()
void ReplaySong::run() void ReplaySong::run()
{ {
if (Mpd.isPlaying()) if (MpdStatus.playerState() != MPD::psStop)
Mpd.Seek(0); Mpd.Seek(0);
} }
@@ -779,29 +788,33 @@ void SavePlaylist::run()
for (size_t i = 0; i < myPlaylist->main().size(); ++i) for (size_t i = 0; i < myPlaylist->main().size(); ++i)
Mpd.AddToPlaylist(playlist_name, myPlaylist->main()[i].value()); Mpd.AddToPlaylist(playlist_name, myPlaylist->main()[i].value());
Mpd.CommitCommandsList(); Mpd.CommitCommandsList();
if (Mpd.GetErrorMessage().empty()) Statusbar::msg("Filtered items added to playlist \"%s\"", playlist_name.c_str());
Statusbar::msg("Filtered items added to playlist \"%s\"", playlist_name.c_str());
} }
else else
{ {
int result = Mpd.SavePlaylist(playlist_name); try
if (result == MPD_ERROR_SUCCESS)
{ {
Mpd.SavePlaylist(playlist_name);
Statusbar::msg("Playlist saved as \"%s\"", playlist_name.c_str()); Statusbar::msg("Playlist saved as \"%s\"", playlist_name.c_str());
} }
else if (result == MPD_SERVER_ERROR_EXIST) catch (MPD::ServerError &e)
{ {
bool yes = askYesNoQuestion("Playlist \"" + playlist_name + "\" already exists, overwrite?", Status::trace); if (e.code() == MPD_SERVER_ERROR_EXIST)
if (yes)
{ {
Mpd.DeletePlaylist(playlist_name); bool yes = askYesNoQuestion("Playlist \"" + playlist_name + "\" already exists, overwrite?", Status::trace);
if (Mpd.SavePlaylist(playlist_name) == MPD_ERROR_SUCCESS) if (yes)
{
Mpd.DeletePlaylist(playlist_name);
Mpd.SavePlaylist(playlist_name);
Statusbar::msg("Playlist overwritten"); Statusbar::msg("Playlist overwritten");
}
else
Statusbar::msg("Aborted");
if (myScreen == myPlaylist)
myPlaylist->EnableHighlighting();
} }
else else
Statusbar::msg("Aborted"); throw e;
if (myScreen == myPlaylist)
myPlaylist->EnableHighlighting();
} }
} }
} }
@@ -964,7 +977,7 @@ void Add::run()
bool SeekForward::canBeRun() const bool SeekForward::canBeRun() const
{ {
return Mpd.isPlaying() && Mpd.GetTotalTime() > 0; return MpdStatus.playerState() != MPD::psStop && MpdStatus.totalTime() > 0;
} }
void SeekForward::run() void SeekForward::run()
@@ -974,7 +987,7 @@ void SeekForward::run()
bool SeekBackward::canBeRun() const bool SeekBackward::canBeRun() const
{ {
return Mpd.isPlaying() && Mpd.GetTotalTime() > 0; return MpdStatus.playerState() != MPD::psStop && MpdStatus.totalTime() > 0;
} }
void SeekBackward::run() void SeekBackward::run()
@@ -1079,8 +1092,10 @@ void TogglePlayingSongCentering::run()
{ {
Config.autocenter_mode = !Config.autocenter_mode; Config.autocenter_mode = !Config.autocenter_mode;
Statusbar::msg("Centering playing song: %s", Config.autocenter_mode ? "On" : "Off"); Statusbar::msg("Centering playing song: %s", Config.autocenter_mode ? "On" : "Off");
if (Config.autocenter_mode && Mpd.isPlaying() && !myPlaylist->main().isFiltered()) if (Config.autocenter_mode
myPlaylist->main().highlight(Mpd.GetCurrentSongPos()); && MpdStatus.playerState() != MPD::psStop
&& !myPlaylist->main().isFiltered())
myPlaylist->main().highlight(MpdStatus.currentSongPosition());
} }
void UpdateDatabase::run() void UpdateDatabase::run()
@@ -1100,13 +1115,13 @@ bool JumpToPlayingSong::canBeRun() const
return ((myScreen == myPlaylist && !myPlaylist->isFiltered()) return ((myScreen == myPlaylist && !myPlaylist->isFiltered())
|| myScreen == myBrowser || myScreen == myBrowser
|| myScreen == myLibrary) || myScreen == myLibrary)
&& Mpd.isPlaying(); && MpdStatus.playerState() != MPD::psStop;
} }
void JumpToPlayingSong::run() void JumpToPlayingSong::run()
{ {
if (myScreen == myPlaylist) if (myScreen == myPlaylist)
myPlaylist->main().highlight(Mpd.GetCurrentSongPos()); myPlaylist->main().highlight(MpdStatus.currentSongPosition());
else if (myScreen == myBrowser) else if (myScreen == myBrowser)
{ {
myBrowser->LocateSong(myPlaylist->nowPlayingSong()); myBrowser->LocateSong(myPlaylist->nowPlayingSong());
@@ -1120,7 +1135,7 @@ void JumpToPlayingSong::run()
void ToggleRepeat::run() void ToggleRepeat::run()
{ {
Mpd.SetRepeat(!Mpd.GetRepeat()); Mpd.SetRepeat(!MpdStatus.repeat());
} }
void Shuffle::run() void Shuffle::run()
@@ -1130,7 +1145,7 @@ void Shuffle::run()
void ToggleRandom::run() void ToggleRandom::run()
{ {
Mpd.SetRandom(!Mpd.GetRandom()); Mpd.SetRandom(!MpdStatus.random());
} }
bool StartSearching::canBeRun() const bool StartSearching::canBeRun() const
@@ -1175,17 +1190,17 @@ void SaveTagChanges::run()
void ToggleSingle::run() void ToggleSingle::run()
{ {
Mpd.SetSingle(!Mpd.GetSingle()); Mpd.SetSingle(!MpdStatus.single());
} }
void ToggleConsume::run() void ToggleConsume::run()
{ {
Mpd.SetConsume(!Mpd.GetConsume()); Mpd.SetConsume(!MpdStatus.consume());
} }
void ToggleCrossfade::run() void ToggleCrossfade::run()
{ {
Mpd.SetCrossfade(Mpd.GetCrossfade() ? 0 : Config.crossfade_time); Mpd.SetCrossfade(MpdStatus.crossfade() ? 0 : Config.crossfade_time);
} }
void SetCrossfade::run() void SetCrossfade::run()
@@ -1215,8 +1230,8 @@ void SetVolume::run()
int volume = boost::lexical_cast<int>(strvolume); int volume = boost::lexical_cast<int>(strvolume);
if (volume >= 0 && volume <= 100) if (volume >= 0 && volume <= 100)
{ {
if (Mpd.SetVolume(volume)) Mpd.SetVolume(volume);
Statusbar::msg("Volume set to %d%%", volume); Statusbar::msg("Volume set to %d%%", volume);
} }
} }
@@ -1451,13 +1466,11 @@ void EditPlaylistName::run()
Statusbar::unlock(); Statusbar::unlock();
if (!new_name.empty() && new_name != old_name) if (!new_name.empty() && new_name != old_name)
{ {
if (Mpd.Rename(old_name, new_name)) Mpd.Rename(old_name, new_name);
{ const char msg[] = "Playlist renamed to \"%ls\"";
const char msg[] = "Playlist renamed to \"%ls\""; Statusbar::msg(msg, wideShorten(ToWString(new_name), COLS-const_strlen(msg)).c_str());
Statusbar::msg(msg, wideShorten(ToWString(new_name), COLS-const_strlen(msg)).c_str()); if (!myBrowser->isLocal())
if (!myBrowser->isLocal()) myBrowser->GetDirectory("/");
myBrowser->GetDirectory("/");
}
} }
} }
@@ -1562,7 +1575,7 @@ void JumpToTagEditor::run()
bool JumpToPositionInSong::canBeRun() const bool JumpToPositionInSong::canBeRun() const
{ {
return Mpd.isPlaying() && Mpd.GetTotalTime() > 0; return MpdStatus.playerState() != MPD::psStop && MpdStatus.totalTime() > 0;
} }
void JumpToPositionInSong::run() void JumpToPositionInSong::run()
@@ -1579,12 +1592,12 @@ void JumpToPositionInSong::run()
if (position.empty()) if (position.empty())
return; return;
int newpos = 0; unsigned newpos = 0;
if (position.find(':') != std::string::npos) // probably time in mm:ss if (position.find(':') != std::string::npos) // probably time in mm:ss
{ {
newpos = boost::lexical_cast<int>(position)*60 newpos = boost::lexical_cast<int>(position)*60
+ boost::lexical_cast<int>(position.substr(position.find(':')+1)); + boost::lexical_cast<int>(position.substr(position.find(':')+1));
if (newpos >= 0 && newpos <= Mpd.GetTotalTime()) if (newpos <= MpdStatus.totalTime())
Mpd.Seek(newpos); Mpd.Seek(newpos);
else else
Statusbar::msg("Out of bounds, 0:00-%s possible for mm:ss, %s given", s.getLength().c_str(), MPD::Song::ShowTime(newpos).c_str()); Statusbar::msg("Out of bounds, 0:00-%s possible for mm:ss, %s given", s.getLength().c_str(), MPD::Song::ShowTime(newpos).c_str());
@@ -1592,7 +1605,7 @@ void JumpToPositionInSong::run()
else if (position.find('s') != std::string::npos) // probably position in seconds else if (position.find('s') != std::string::npos) // probably position in seconds
{ {
newpos = boost::lexical_cast<int>(position); newpos = boost::lexical_cast<int>(position);
if (newpos >= 0 && newpos <= Mpd.GetTotalTime()) if (newpos <= MpdStatus.totalTime())
Mpd.Seek(newpos); Mpd.Seek(newpos);
else else
Statusbar::msg("Out of bounds, 0-%d possible for seconds, %d given", s.getDuration(), newpos); Statusbar::msg("Out of bounds, 0-%d possible for seconds, %d given", s.getDuration(), newpos);
@@ -1600,8 +1613,8 @@ void JumpToPositionInSong::run()
else else
{ {
newpos = boost::lexical_cast<int>(position); newpos = boost::lexical_cast<int>(position);
if (newpos >= 0 && newpos <= 100) if (newpos <= 100)
Mpd.Seek(Mpd.GetTotalTime()*newpos/100.0); Mpd.Seek(MpdStatus.totalTime()*newpos/100.0);
else else
Statusbar::msg("Out of bounds, 0-100 possible for %%, %d given", newpos); Statusbar::msg("Out of bounds, 0-100 possible for %%, %d given", newpos);
} }
@@ -1689,8 +1702,8 @@ void CropMainPlaylist::run()
if (yes) if (yes)
{ {
Statusbar::msg("Cropping playlist..."); Statusbar::msg("Cropping playlist...");
if (cropPlaylist(myPlaylist->main(), std::bind(&MPD::Connection::Delete, _1, _2))) cropPlaylist(myPlaylist->main(), std::bind(&MPD::Connection::Delete, _1, _2));
Statusbar::msg("Cropping playlist..."); Statusbar::msg("Cropping playlist...");
} }
} }
@@ -1710,8 +1723,8 @@ void CropPlaylist::run()
{ {
auto delete_fun = std::bind(&MPD::Connection::PlaylistDelete, _1, playlist, _2); auto delete_fun = std::bind(&MPD::Connection::PlaylistDelete, _1, playlist, _2);
Statusbar::msg("Cropping playlist \"%s\"...", playlist.c_str()); Statusbar::msg("Cropping playlist \"%s\"...", playlist.c_str());
if (cropPlaylist(myPlaylistEditor->Content, delete_fun)) cropPlaylist(myPlaylistEditor->Content, delete_fun);
Statusbar::msg("Playlist \"%s\" cropped", playlist.c_str()); Statusbar::msg("Playlist \"%s\" cropped", playlist.c_str());
} }
} }
@@ -1725,8 +1738,8 @@ void ClearMainPlaylist::run()
auto delete_fun = std::bind(&MPD::Connection::Delete, _1, _2); auto delete_fun = std::bind(&MPD::Connection::Delete, _1, _2);
auto clear_fun = std::bind(&MPD::Connection::ClearMainPlaylist, _1); auto clear_fun = std::bind(&MPD::Connection::ClearMainPlaylist, _1);
Statusbar::msg("Deleting items..."); Statusbar::msg("Deleting items...");
if (clearPlaylist(myPlaylist->main(), delete_fun, clear_fun)) clearPlaylist(myPlaylist->main(), delete_fun, clear_fun);
Statusbar::msg("Items deleted"); Statusbar::msg("Items deleted");
} }
} }
@@ -1747,8 +1760,8 @@ void ClearPlaylist::run()
auto delete_fun = std::bind(&MPD::Connection::PlaylistDelete, _1, playlist, _2); auto delete_fun = std::bind(&MPD::Connection::PlaylistDelete, _1, playlist, _2);
auto clear_fun = std::bind(&MPD::Connection::ClearPlaylist, _1, playlist); auto clear_fun = std::bind(&MPD::Connection::ClearPlaylist, _1, playlist);
Statusbar::msg("Deleting items from \"%s\"...", playlist.c_str()); Statusbar::msg("Deleting items from \"%s\"...", playlist.c_str());
if (clearPlaylist(myPlaylistEditor->Content, delete_fun, clear_fun)) clearPlaylist(myPlaylistEditor->Content, delete_fun, clear_fun);
Statusbar::msg("Items deleted from \"%s\"", playlist.c_str()); Statusbar::msg("Items deleted from \"%s\"", playlist.c_str());
} }
} }
@@ -2578,7 +2591,7 @@ void seek()
using Global::Timer; using Global::Timer;
using Global::SeekingInProgress; using Global::SeekingInProgress;
if (!Mpd.GetTotalTime()) if (!MpdStatus.totalTime())
{ {
Statusbar::msg("Unknown item length"); Statusbar::msg("Unknown item length");
return; return;
@@ -2587,7 +2600,7 @@ void seek()
Progressbar::lock(); Progressbar::lock();
Statusbar::lock(); Statusbar::lock();
int songpos = Mpd.GetElapsedTime(); unsigned songpos = MpdStatus.elapsedTime();
timeval t = Timer; timeval t = Timer;
int old_timeout = wFooter->getTimeout(); int old_timeout = wFooter->getTimeout();
@@ -2602,7 +2615,7 @@ void seek()
Status::trace(); Status::trace();
myPlaylist->UpdateTimer(); myPlaylist->UpdateTimer();
int howmuch = Config.incremental_seeking ? (Timer.tv_sec-t.tv_sec)/2+Config.seek_time : Config.seek_time; unsigned howmuch = Config.incremental_seeking ? (Timer.tv_sec-t.tv_sec)/2+Config.seek_time : Config.seek_time;
Key input = Key::read(*wFooter); Key input = Key::read(*wFooter);
auto k = Bindings.get(input); auto k = Bindings.get(input);
@@ -2611,20 +2624,17 @@ void seek()
auto a = k.first->action(); auto a = k.first->action();
if (a == seekForward) if (a == seekForward)
{ {
if (songpos < Mpd.GetTotalTime()) if (songpos < MpdStatus.totalTime())
{ songpos = std::min(songpos + howmuch, MpdStatus.totalTime());
songpos += howmuch;
if (songpos > Mpd.GetTotalTime())
songpos = Mpd.GetTotalTime();
}
} }
else if (a == seekBackward) else if (a == seekBackward)
{ {
if (songpos > 0) if (songpos > 0)
{ {
songpos -= howmuch; if (songpos < howmuch)
if (songpos < 0)
songpos = 0; songpos = 0;
else
songpos -= howmuch;
} }
} }
else else
@@ -2637,12 +2647,12 @@ void seek()
if (Config.display_remaining_time) if (Config.display_remaining_time)
{ {
tracklength = "-"; tracklength = "-";
tracklength += MPD::Song::ShowTime(Mpd.GetTotalTime()-songpos); tracklength += MPD::Song::ShowTime(MpdStatus.totalTime()-songpos);
} }
else else
tracklength = MPD::Song::ShowTime(songpos); tracklength = MPD::Song::ShowTime(songpos);
tracklength += "/"; tracklength += "/";
tracklength += MPD::Song::ShowTime(Mpd.GetTotalTime()); tracklength += MPD::Song::ShowTime(MpdStatus.totalTime());
*wHeader << NC::XY(0, 0) << tracklength << " "; *wHeader << NC::XY(0, 0) << tracklength << " ";
wHeader->refresh(); wHeader->refresh();
} }
@@ -2652,17 +2662,17 @@ void seek()
if (Config.display_remaining_time) if (Config.display_remaining_time)
{ {
tracklength += "-"; tracklength += "-";
tracklength += MPD::Song::ShowTime(Mpd.GetTotalTime()-songpos); tracklength += MPD::Song::ShowTime(MpdStatus.totalTime()-songpos);
} }
else else
tracklength += MPD::Song::ShowTime(songpos); tracklength += MPD::Song::ShowTime(songpos);
tracklength += "/"; tracklength += "/";
tracklength += MPD::Song::ShowTime(Mpd.GetTotalTime()); tracklength += MPD::Song::ShowTime(MpdStatus.totalTime());
tracklength += "]"; tracklength += "]";
*wFooter << NC::XY(wFooter->getWidth()-tracklength.length(), 1) << tracklength; *wFooter << NC::XY(wFooter->getWidth()-tracklength.length(), 1) << tracklength;
} }
*wFooter << NC::Format::NoBold; *wFooter << NC::Format::NoBold;
Progressbar::draw(songpos, Mpd.GetTotalTime()); Progressbar::draw(songpos, MpdStatus.totalTime());
wFooter->refresh(); wFooter->refresh();
} }
SeekingInProgress = false; SeekingInProgress = false;

View File

@@ -74,9 +74,6 @@ Browser::Browser() : itsBrowseLocally(0), itsScrollBeginning(0), itsBrowsedDir("
w.setSelectedPrefix(Config.selected_item_prefix); w.setSelectedPrefix(Config.selected_item_prefix);
w.setSelectedSuffix(Config.selected_item_suffix); w.setSelectedSuffix(Config.selected_item_suffix);
w.setItemDisplayer(std::bind(Display::Items, _1, proxySongList())); w.setItemDisplayer(std::bind(Display::Items, _1, proxySongList()));
if (SupportedExtensions.empty())
Mpd.GetSupportedExtensions(SupportedExtensions);
} }
void Browser::resize() void Browser::resize()
@@ -136,11 +133,9 @@ void Browser::enterPressed()
} }
case itPlaylist: case itPlaylist:
{ {
if (Mpd.LoadPlaylist(item.name)) Mpd.LoadPlaylist(item.name);
{ Statusbar::msg("Playlist \"%s\" loaded", item.name.c_str());
Statusbar::msg("Playlist \"%s\" loaded", item.name.c_str()); myPlaylist->PlayNewlyAddedSongs();
myPlaylist->PlayNewlyAddedSongs();
}
} }
} }
} }
@@ -168,7 +163,6 @@ void Browser::spacePressed()
{ {
case itDirectory: case itDirectory:
{ {
bool result;
# ifndef WIN32 # ifndef WIN32
if (isLocal()) if (isLocal())
{ {
@@ -179,13 +173,12 @@ void Browser::spacePressed()
list.reserve(items.size()); list.reserve(items.size());
for (MPD::ItemList::const_iterator it = items.begin(); it != items.end(); ++it) for (MPD::ItemList::const_iterator it = items.begin(); it != items.end(); ++it)
list.push_back(*it->song); list.push_back(*it->song);
result = addSongsToPlaylist(list, false, -1); addSongsToPlaylist(list, false, -1);
} }
else else
# endif // !WIN32 # endif // !WIN32
result = Mpd.Add(item.name); Mpd.Add(item.name);
if (result) Statusbar::msg("Directory \"%s\" added", item.name.c_str());
Statusbar::msg("Directory \"%s\" added", item.name.c_str());
break; break;
} }
case itSong: case itSong:
@@ -195,8 +188,8 @@ void Browser::spacePressed()
} }
case itPlaylist: case itPlaylist:
{ {
if (Mpd.LoadPlaylist(item.name)) Mpd.LoadPlaylist(item.name);
Statusbar::msg("Playlist \"%s\" loaded", item.name.c_str()); Statusbar::msg("Playlist \"%s\" loaded", item.name.c_str());
break; break;
} }
} }
@@ -363,6 +356,12 @@ MPD::SongList Browser::getSelectedSongs()
return result; return result;
} }
void Browser::fetchSupportedExtensions()
{
SupportedExtensions.clear();
Mpd.GetSupportedExtensions(SupportedExtensions);
}
void Browser::LocateSong(const MPD::Song &s) void Browser::LocateSong(const MPD::Song &s)
{ {
if (s.getDirectory().empty()) if (s.getDirectory().empty())
@@ -580,7 +579,7 @@ bool Browser::deleteItem(const MPD::Item &item)
// playlist created by mpd // playlist created by mpd
if (!isLocal() && item.type == itPlaylist && CurrentDir() == "/") if (!isLocal() && item.type == itPlaylist && CurrentDir() == "/")
return Mpd.DeletePlaylist(item.name); Mpd.DeletePlaylist(item.name);
std::string path; std::string path;
if (!isLocal()) if (!isLocal())

View File

@@ -65,6 +65,8 @@ struct Browser: Screen<NC::Menu<MPD::Item>>, Filterable, HasSongs, Searchable, T
// private members // private members
const std::string &CurrentDir() { return itsBrowsedDir; } const std::string &CurrentDir() { return itsBrowsedDir; }
void fetchSupportedExtensions();
bool isLocal() { return itsBrowseLocally; } bool isLocal() { return itsBrowseLocally; }
void LocateSong(const MPD::Song &); void LocateSong(const MPD::Song &);
void GetDirectory(std::string, std::string = "/"); void GetDirectory(std::string, std::string = "/");

View File

@@ -117,13 +117,11 @@ void ParseArgv(int argc, char **argv)
<< " -s, --screen <name> specify the startup screen\n" << " -s, --screen <name> specify the startup screen\n"
<< " -?, --help show help message\n" << " -?, --help show help message\n"
<< " -v, --version display version information\n" << " -v, --version display version information\n"
<< " --now-playing display now playing song [" << now_playing_format << "]\n"
; ;
exit(0); exit(0);
} }
if (!Actions::connectToMPD()) Actions::connectToMPD();
exit(1);
if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--screen")) if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--screen"))
{ {
@@ -164,34 +162,6 @@ void ParseArgv(int argc, char **argv)
exit(1); exit(1);
} }
} }
else if (!strcmp(argv[i], "--now-playing"))
{
Mpd.UpdateStatus();
if (!Mpd.GetErrorMessage().empty())
{
std::cerr << "MPD error: " << Mpd.GetErrorMessage() << std::endl;
exit(1);
}
if (Mpd.isPlaying())
{
if (argc > ++i)
{
if (MPD::Song::isFormatOk("now-playing format", argv[i]))
{
// apply additional pair of braces
now_playing_format = "{";
now_playing_format += argv[i];
now_playing_format += "}";
boost::replace_all(now_playing_format, "\\n", "\n");
boost::replace_all(now_playing_format, "\\t", "\t");
}
}
std::string np = Mpd.GetCurrentlyPlayingSong().toString(
now_playing_format, Config.tags_separator);
std::cout << Charset::utf8ToLocale(np) << "\n";
}
exit(0);
}
else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")) else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config"))
{ {
// this is used in Configuration::CheckForCommandLineConfigFilePath, ignoring here. // this is used in Configuration::CheckForCommandLineConfigFilePath, ignoring here.
@@ -202,10 +172,5 @@ void ParseArgv(int argc, char **argv)
std::cerr << "Invalid option: " << argv[i] << std::endl; std::cerr << "Invalid option: " << argv[i] << std::endl;
exit(1); exit(1);
} }
if (!Mpd.GetErrorMessage().empty())
{
std::cerr << "Error: " << Mpd.GetErrorMessage() << std::endl;
exit(1);
}
} }
} }

View File

@@ -97,8 +97,8 @@ void setProperties(NC::Menu<T> &menu, const MPD::Song &s, const ProxySongList &p
discard_colors = Config.discard_colors_if_item_is_selected && is_selected; discard_colors = Config.discard_colors_if_item_is_selected && is_selected;
int song_pos = menu.isFiltered() ? s.getPosition() : drawn_pos; int song_pos = menu.isFiltered() ? s.getPosition() : drawn_pos;
is_now_playing = Mpd.isPlaying() && myPlaylist->isActiveWindow(menu) is_now_playing = MpdStatus.playerState() != MPD::psStop && myPlaylist->isActiveWindow(menu)
&& song_pos == Mpd.GetCurrentSongPos(); && song_pos == MpdStatus.currentSongPosition();
if (is_now_playing) if (is_now_playing)
menu << Config.now_playing_prefix; menu << Config.now_playing_prefix;
} }

View File

@@ -24,8 +24,6 @@
#include <string> #include <string>
#include "gcc.h" #include "gcc.h"
#define Error(msg) std::cerr << "ncmpcpp: " << msg;
void FatalError(const std::string &msg) GNUC_NORETURN; void FatalError(const std::string &msg) GNUC_NORETURN;
#endif // NCMPCPP_ERROR_H #endif // NCMPCPP_ERROR_H

View File

@@ -49,9 +49,6 @@ extern size_t MainStartY;
// height of main window // height of main window
extern size_t MainHeight; extern size_t MainHeight;
// indicates whether messages from Statusbar::msg function should be shown
extern bool ShowMessages;
// indicates whether seeking action in currently in progress // indicates whether seeking action in currently in progress
extern bool SeekingInProgress; extern bool SeekingInProgress;

View File

@@ -49,7 +49,7 @@ bool addSongToPlaylist(const MPD::Song &s, bool play, size_t position)
} }
else else
{ {
position = std::min(position, Mpd.GetPlaylistLength()); position = std::min(position, myPlaylist->main().size());
int id = Mpd.AddSong(s, position); int id = Mpd.AddSong(s, position);
if (id >= 0) if (id >= 0)
{ {
@@ -64,18 +64,18 @@ bool addSongToPlaylist(const MPD::Song &s, bool play, size_t position)
return result; return result;
} }
bool addSongsToPlaylist(const MPD::SongList &list, bool play, size_t position) void addSongsToPlaylist(const MPD::SongList &list, bool play, size_t position)
{ {
if (list.empty()) if (list.empty())
return false; return;
position = std::min(position, Mpd.GetPlaylistLength()); position = std::min(position, myPlaylist->main().size());
Mpd.StartCommandsList(); Mpd.StartCommandsList();
for (auto s = list.rbegin(); s != list.rend(); ++s) for (auto s = list.rbegin(); s != list.rend(); ++s)
if (Mpd.AddSong(*s, position) < 0) if (Mpd.AddSong(*s, position) < 0)
break; break;
if (play) if (play)
Mpd.Play(position); Mpd.Play(position);
return Mpd.CommitCommandsList(); Mpd.CommitCommandsList();
} }
std::string Timestamp(time_t t) std::string Timestamp(time_t t)

View File

@@ -152,24 +152,22 @@ void moveSelectedItemsUp(NC::Menu<MPD::Song> &m, F swap_fun)
Mpd.StartCommandsList(); Mpd.StartCommandsList();
for (auto it = list.begin(); it != list.end(); ++it) for (auto it = list.begin(); it != list.end(); ++it)
swap_fun(Mpd, *it - begin, *it - begin - 1); swap_fun(Mpd, *it - begin, *it - begin - 1);
if (Mpd.CommitCommandsList()) Mpd.CommitCommandsList();
if (list.size() > 1)
{ {
if (list.size() > 1) for (auto it = list.begin(); it != list.end(); ++it)
{ {
for (auto it = list.begin(); it != list.end(); ++it) (*it)->setSelected(false);
{ (*it-1)->setSelected(true);
(*it)->setSelected(false);
(*it-1)->setSelected(true);
}
m.highlight(list[(list.size())/2] - begin - 1);
}
else
{
// if we move only one item, do not select it. however, if single item
// was selected prior to move, it'll deselect it. oh well.
list[0]->setSelected(false);
m.scroll(NC::Scroll::Up);
} }
m.highlight(list[(list.size())/2] - begin - 1);
}
else
{
// if we move only one item, do not select it. however, if single item
// was selected prior to move, it'll deselect it. oh well.
list[0]->setSelected(false);
m.scroll(NC::Scroll::Up);
} }
} }
} }
@@ -186,24 +184,22 @@ void moveSelectedItemsDown(NC::Menu<MPD::Song> &m, F swap_fun)
Mpd.StartCommandsList(); Mpd.StartCommandsList();
for (auto it = list.begin(); it != list.end(); ++it) for (auto it = list.begin(); it != list.end(); ++it)
swap_fun(Mpd, it->base() - begin, it->base() - begin + 1); swap_fun(Mpd, it->base() - begin, it->base() - begin + 1);
if (Mpd.CommitCommandsList()) Mpd.CommitCommandsList();
if (list.size() > 1)
{ {
if (list.size() > 1) for (auto it = list.begin(); it != list.end(); ++it)
{ {
for (auto it = list.begin(); it != list.end(); ++it) (*it)->setSelected(false);
{ (*it-1)->setSelected(true);
(*it)->setSelected(false);
(*it-1)->setSelected(true);
}
m.highlight(list[(list.size())/2].base() - begin + 1);
}
else
{
// if we move only one item, do not select it. however, if single item
// was selected prior to move, it'll deselect it. oh well.
list[0]->setSelected(false);
m.scroll(NC::Scroll::Down);
} }
m.highlight(list[(list.size())/2].base() - begin + 1);
}
else
{
// if we move only one item, do not select it. however, if single item
// was selected prior to move, it'll deselect it. oh well.
list[0]->setSelected(false);
m.scroll(NC::Scroll::Down);
} }
} }
} }
@@ -236,14 +232,12 @@ void moveSelectedItemsTo(NC::Menu<MPD::Song> &m, F move_fun)
size_t i = list.size()-1; size_t i = list.size()-1;
for (auto it = list.rbegin(); it != list.rend(); ++it, --i) for (auto it = list.rbegin(); it != list.rend(); ++it, --i)
move_fun(Mpd, *it - begin, pos+i); move_fun(Mpd, *it - begin, pos+i);
if (Mpd.CommitCommandsList()) Mpd.CommitCommandsList();
i = list.size()-1;
for (auto it = list.rbegin(); it != list.rend(); ++it, --i)
{ {
i = list.size()-1; (*it)->setSelected(false);
for (auto it = list.rbegin(); it != list.rend(); ++it, --i) m[pos+i].setSelected(true);
{
(*it)->setSelected(false);
m[pos+i].setSelected(true);
}
} }
} }
else if (diff < 0) // move up else if (diff < 0) // move up
@@ -251,23 +245,20 @@ void moveSelectedItemsTo(NC::Menu<MPD::Song> &m, F move_fun)
size_t i = 0; size_t i = 0;
for (auto it = list.begin(); it != list.end(); ++it, ++i) for (auto it = list.begin(); it != list.end(); ++it, ++i)
move_fun(Mpd, *it - begin, pos+i); move_fun(Mpd, *it - begin, pos+i);
if (Mpd.CommitCommandsList()) Mpd.CommitCommandsList();
i = 0;
for (auto it = list.begin(); it != list.end(); ++it, ++i)
{ {
i = 0; (*it)->setSelected(false);
for (auto it = list.begin(); it != list.end(); ++it, ++i) m[pos+i].setSelected(true);
{
(*it)->setSelected(false);
m[pos+i].setSelected(true);
}
} }
} }
}); });
} }
template <typename F> template <typename F>
bool deleteSelectedSongs(NC::Menu<MPD::Song> &m, F delete_fun) void deleteSelectedSongs(NC::Menu<MPD::Song> &m, F delete_fun)
{ {
bool result = false;
selectCurrentIfNoneSelected(m); selectCurrentIfNoneSelected(m);
// ok, this is tricky. we need to operate on whole playlist // ok, this is tricky. we need to operate on whole playlist
// to get positions right, but at the same time we need to // to get positions right, but at the same time we need to
@@ -298,31 +289,27 @@ bool deleteSelectedSongs(NC::Menu<MPD::Song> &m, F delete_fun)
++cur_filtered; ++cur_filtered;
} }
} }
if (Mpd.CommitCommandsList()) Mpd.CommitCommandsList();
result = true;
return result;
} }
template <typename F> template <typename F>
bool cropPlaylist(NC::Menu<MPD::Song> &m, F delete_fun) void cropPlaylist(NC::Menu<MPD::Song> &m, F delete_fun)
{ {
reverseSelectionHelper(m.begin(), m.end()); reverseSelectionHelper(m.begin(), m.end());
return deleteSelectedSongs(m, delete_fun); deleteSelectedSongs(m, delete_fun);
} }
template <typename F, typename G> template <typename F, typename G>
bool clearPlaylist(NC::Menu<MPD::Song> &m, F delete_fun, G clear_fun) void clearPlaylist(NC::Menu<MPD::Song> &m, F delete_fun, G clear_fun)
{ {
bool result = false;
if (m.isFiltered()) if (m.isFiltered())
{ {
for (auto it = m.begin(); it != m.end(); ++it) for (auto it = m.begin(); it != m.end(); ++it)
it->setSelected(true); it->setSelected(true);
result = deleteSelectedSongs(m, delete_fun); deleteSelectedSongs(m, delete_fun);
} }
else else
result = clear_fun(Mpd); clear_fun(Mpd);
return result;
} }
template <typename Iterator> std::string getSharedDirectory(Iterator first, Iterator last) template <typename Iterator> std::string getSharedDirectory(Iterator first, Iterator last)
@@ -471,7 +458,7 @@ template <typename BufferT> void ShowTag(BufferT &buf, const std::string &tag)
} }
bool addSongToPlaylist(const MPD::Song &s, bool play, size_t position = -1); bool addSongToPlaylist(const MPD::Song &s, bool play, size_t position = -1);
bool addSongsToPlaylist(const MPD::SongList &list, bool play, size_t position = -1); void addSongsToPlaylist(const MPD::SongList &list, bool play, size_t position = -1);
std::string Timestamp(time_t t); std::string Timestamp(time_t t);

View File

@@ -191,7 +191,7 @@ void Lastfm::Save(const std::string &data)
output.close(); output.close();
} }
else else
Error("couldn't save file \"" << itsFilename << "\""); std::cerr << "ncmpcpp: couldn't save file \"" << itsFilename << "\"\n";
} }
void Lastfm::Refetch() void Lastfm::Refetch()

View File

@@ -249,8 +249,6 @@ std::wstring MediaLibrary::title()
void MediaLibrary::update() void MediaLibrary::update()
{ {
Mpd.BlockIdle(true);
if (hasTwoColumns) if (hasTwoColumns)
{ {
if (Albums.reallyEmpty() || m_albums_update_request) if (Albums.reallyEmpty() || m_albums_update_request)
@@ -407,8 +405,6 @@ void MediaLibrary::update()
}); });
Songs.refresh(); Songs.refresh();
} }
Mpd.BlockIdle(false);
} }
void MediaLibrary::enterPressed() void MediaLibrary::enterPressed()
@@ -969,20 +965,18 @@ void MediaLibrary::AddToPlaylist(bool add_n_play)
addSongToPlaylist(Songs.current().value(), add_n_play); addSongToPlaylist(Songs.current().value(), add_n_play);
else else
{ {
auto list = getSelectedSongs(); addSongsToPlaylist(getSelectedSongs(), add_n_play);
if (addSongsToPlaylist(list, add_n_play)) if ((!Tags.empty() && isActiveWindow(Tags))
|| (isActiveWindow(Albums) && Albums.current().value().isAllTracksEntry()))
{ {
if ((!Tags.empty() && isActiveWindow(Tags)) std::string tag_type = boost::locale::to_lower(
|| (isActiveWindow(Albums) && Albums.current().value().isAllTracksEntry())) tagTypeToString(Config.media_lib_primary_tag));
{ Statusbar::msg("Songs with %s = \"%s\" added",
std::string tag_type = boost::locale::to_lower( tag_type.c_str(), Tags.current().value().tag().c_str());
tagTypeToString(Config.media_lib_primary_tag));
Statusbar::msg("Songs with %s = \"%s\" added", tag_type.c_str(), Tags.current().value().tag().c_str());
}
else if (isActiveWindow(Albums))
Statusbar::msg("Songs from album \"%s\" added",
Albums.current().value().entry().album().c_str());
} }
else if (isActiveWindow(Albums))
Statusbar::msg("Songs from album \"%s\" added",
Albums.current().value().entry().album().c_str());
} }
if (!add_n_play) if (!add_n_play)

File diff suppressed because it is too large Load Diff

View File

@@ -22,6 +22,7 @@
#define NCMPCPP_MPDPP_H #define NCMPCPP_MPDPP_H
#include <cassert> #include <cassert>
#include <exception>
#include <set> #include <set>
#include <vector> #include <vector>
@@ -34,6 +35,36 @@ enum ItemType { itDirectory, itSong, itPlaylist };
enum PlayerState { psUnknown, psStop, psPlay, psPause }; enum PlayerState { psUnknown, psStop, psPlay, psPause };
enum ReplayGainMode { rgmOff, rgmTrack, rgmAlbum }; enum ReplayGainMode { rgmOff, rgmTrack, rgmAlbum };
struct ClientError: public std::exception
{
ClientError(mpd_error code_, std::string msg, bool clearable_)
: m_code(code_), m_msg(msg), m_clearable(clearable_) { }
virtual const char *what() const noexcept { return m_msg.c_str(); }
mpd_error code() const { return m_code; }
bool clearable() const { return m_clearable; }
private:
mpd_error m_code;
std::string m_msg;
bool m_clearable;
};
struct ServerError: public std::exception
{
ServerError(mpd_server_error code_, std::string msg, bool clearable_)
: m_code(code_), m_msg(msg), m_clearable(clearable_) { }
virtual const char *what() const noexcept { return m_msg.c_str(); }
mpd_server_error code() const { return m_code; }
bool clearable() const { return m_clearable; }
private:
mpd_server_error m_code;
std::string m_msg;
bool m_clearable;
};
struct Statistics struct Statistics
{ {
friend class Connection; friend class Connection;
@@ -54,6 +85,40 @@ private:
std::shared_ptr<mpd_stats> m_stats; std::shared_ptr<mpd_stats> m_stats;
}; };
struct Status
{
friend class Connection;
Status() { }
void clear();
bool empty() const;
int volume() const;
bool repeat() const;
bool random() const;
bool single() const;
bool consume() const;
unsigned playlistLength() const;
unsigned playlistVersion() const;
PlayerState playerState() const;
unsigned crossfade() const;
int currentSongPosition() const;
int currentSongID() const;
int nextSongPosition() const;
int nextSongID() const;
unsigned elapsedTime() const;
unsigned totalTime() const;
unsigned kbps() const;
unsigned updateID() const;
const char *error() const;
private:
Status(mpd_status *status) : m_status(status, mpd_status_free) { }
std::shared_ptr<mpd_status> m_status;
};
struct Item struct Item
{ {
std::shared_ptr<Song> song; std::shared_ptr<Song> song;
@@ -61,26 +126,6 @@ struct Item
std::string name; std::string name;
}; };
struct StatusChanges
{
StatusChanges() : Playlist(0), StoredPlaylists(0), SongID(0), Database(0), DBUpdating(0), Volume(0), ElapsedTime(0), Crossfade(0), Random(0), Repeat(0), Single(0), Consume(0), PlayerState(0), StatusFlags(0), Outputs(0) { }
bool Playlist:1;
bool StoredPlaylists:1;
bool SongID:1;
bool Database:1;
bool DBUpdating:1;
bool Volume:1;
bool ElapsedTime:1;
bool Crossfade:1;
bool Random:1;
bool Repeat:1;
bool Single:1;
bool Consume:1;
bool PlayerState:1;
bool StatusFlags:1;
bool Outputs:1;
};
struct Output struct Output
{ {
Output(const std::string &name_, bool enabled) : m_name(name_), m_enabled(enabled) { } Output(const std::string &name_, bool enabled) : m_name(name_), m_enabled(enabled) { }
@@ -99,7 +144,6 @@ typedef std::vector<Output> OutputList;
class Connection class Connection
{ {
typedef void (*StatusUpdater) (Connection *, StatusChanges, void *);
typedef void (*ErrorHandler) (Connection *, int, const char *, void *); typedef void (*ErrorHandler) (Connection *, int, const char *, void *);
typedef std::function<void(Item &&)> ItemConsumer; typedef std::function<void(Item &&)> ItemConsumer;
@@ -111,33 +155,27 @@ public:
Connection(); Connection();
~Connection(); ~Connection();
bool Connect(); void Connect();
bool Connected() const; bool Connected() const;
void Disconnect(); void Disconnect();
const std::string & GetHostname() { return itsHost; } const std::string &GetHostname() { return m_host; }
int GetPort() { return itsPort; } int GetPort() { return m_port; }
unsigned Version() const; unsigned Version() const;
void SetIdleEnabled(bool val) { isIdleEnabled = val; } int GetFD() const { return m_fd; }
void BlockIdle(bool val) { itsIdleBlocked = val; }
bool SupportsIdle() const { return supportsIdle; }
void OrderDataFetching() { hasData = 1; }
int GetFD() const { return itsFD; }
void SetHostname(const std::string &); void SetHostname(const std::string &);
void SetPort(int port) { itsPort = port; } void SetPort(int port) { m_port = port; }
void SetTimeout(int timeout) { itsTimeout = timeout; } void SetTimeout(int timeout) { m_timeout = timeout; }
void SetPassword(const std::string &password) { itsPassword = password; } void SetPassword(const std::string &password) { m_password = password; }
bool SendPassword(); void SendPassword();
Statistics getStatistics(); Statistics getStatistics();
Status getStatus();
void SetStatusUpdater(StatusUpdater, void *); void UpdateDirectory(const std::string &);
void SetErrorHandler(ErrorHandler, void *);
void UpdateStatus();
bool UpdateDirectory(const std::string &);
void Play(); void Play();
void Play(int); void Play(int);
@@ -147,36 +185,15 @@ public:
void Stop(); void Stop();
void Next(); void Next();
void Prev(); void Prev();
bool Move(unsigned, unsigned); void Move(unsigned int from, unsigned int to);
void Swap(unsigned, unsigned); void Swap(unsigned, unsigned);
void Seek(unsigned); void Seek(unsigned);
void Shuffle(); void Shuffle();
bool ClearMainPlaylist(); void ClearMainPlaylist();
bool isPlaying() const { return GetState() > psStop; }
PlayerState GetState() const { return itsCurrentStatus ? PlayerState(mpd_status_get_state(itsCurrentStatus)) : psUnknown; }
PlayerState GetOldState() const { return itsOldStatus ? PlayerState(mpd_status_get_state(itsOldStatus)) : psUnknown; }
bool GetRepeat() const { return itsCurrentStatus ? mpd_status_get_repeat(itsCurrentStatus) : 0; }
bool GetRandom() const { return itsCurrentStatus ? mpd_status_get_random(itsCurrentStatus) : 0; }
bool GetSingle() const { return itsCurrentStatus ? mpd_status_get_single(itsCurrentStatus) : 0; }
bool GetConsume() const { return itsCurrentStatus ? mpd_status_get_consume(itsCurrentStatus) : 0; }
bool GetDBIsUpdating() const { return itsCurrentStatus ? mpd_status_get_update_id(itsCurrentStatus) : 0; }
int GetVolume() const { return itsCurrentStatus ? mpd_status_get_volume(itsCurrentStatus) : -1; }
unsigned GetCrossfade() const { return itsCurrentStatus ? mpd_status_get_crossfade(itsCurrentStatus) : 0; }
unsigned GetPlaylistID() const { return itsCurrentStatus ? mpd_status_get_queue_version(itsCurrentStatus) : 0; }
unsigned GetOldPlaylistID() const { return itsOldStatus ? mpd_status_get_queue_version(itsOldStatus) : 0; }
unsigned GetElapsedTime() const { return itsCurrentStatus ? itsElapsed : 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; }
size_t GetPlaylistLength() const { return itsCurrentStatus ? mpd_status_get_queue_length(itsCurrentStatus) : 0; }
void GetPlaylistChanges(unsigned, SongConsumer f); void GetPlaylistChanges(unsigned, SongConsumer f);
const std::string &GetErrorMessage() const { return itsErrorMessage; }
Song GetCurrentlyPlayingSong(); Song GetCurrentlyPlayingSong();
int GetCurrentSongPos() const;
Song GetSong(const std::string &); Song GetSong(const std::string &);
void GetPlaylistContent(const std::string &name, SongConsumer f); void GetPlaylistContent(const std::string &name, SongConsumer f);
@@ -187,36 +204,35 @@ public:
void SetSingle(bool); void SetSingle(bool);
void SetConsume(bool); void SetConsume(bool);
void SetCrossfade(unsigned); void SetCrossfade(unsigned);
bool SetVolume(unsigned); void SetVolume(unsigned int vol);
std::string GetReplayGainMode(); std::string GetReplayGainMode();
void SetReplayGainMode(ReplayGainMode); void SetReplayGainMode(ReplayGainMode);
bool SetPriority(const Song &s, int prio); void SetPriority(const MPD::Song &s, int prio);
int AddSong(const std::string &, int = -1); // returns id of added song int AddSong(const std::string &, int = -1); // returns id of added song
int AddSong(const Song &, int = -1); // returns id of added song int AddSong(const Song &, int = -1); // returns id of added song
bool AddRandomTag(mpd_tag_type, size_t); bool AddRandomTag(mpd_tag_type, size_t);
bool AddRandomSongs(size_t); bool AddRandomSongs(size_t);
bool Add(const std::string &path); void Add(const std::string &path);
bool Delete(unsigned); void Delete(unsigned int pos);
bool DeleteID(unsigned); void PlaylistDelete(const std::string &playlist, unsigned int pos);
bool PlaylistDelete(const std::string &, unsigned);
void StartCommandsList(); void StartCommandsList();
bool CommitCommandsList(); void CommitCommandsList();
bool DeletePlaylist(const std::string &); void DeletePlaylist(const std::string &name);
bool LoadPlaylist(const std::string &name); void LoadPlaylist(const std::string &name);
int SavePlaylist(const std::string &); void SavePlaylist(const std::string &);
bool ClearPlaylist(const std::string &); void ClearPlaylist(const std::string &playlist);
void AddToPlaylist(const std::string &, const Song &); void AddToPlaylist(const std::string &, const Song &);
void AddToPlaylist(const std::string &, const std::string &); void AddToPlaylist(const std::string &, const std::string &);
bool PlaylistMove(const std::string &, int, int); void PlaylistMove(const std::string &path, int from, int to);
bool Rename(const std::string &, const std::string &); void Rename(const std::string &from, const std::string &to);
void StartSearch(bool); void StartSearch(bool);
void StartFieldSearch(mpd_tag_type); void StartFieldSearch(mpd_tag_type);
void AddSearch(mpd_tag_type, const std::string &) const; void AddSearch(mpd_tag_type item, const std::string &str) const;
void AddSearchAny(const std::string &str) const; void AddSearchAny(const std::string &str) const;
void AddSearchURI(const std::string &str) const; void AddSearchURI(const std::string &str) const;
void CommitSearchSongs(SongConsumer f); void CommitSearchSongs(SongConsumer f);
@@ -230,53 +246,39 @@ public:
void GetDirectories(const std::string &directory, StringConsumer f); void GetDirectories(const std::string &directory, StringConsumer f);
void GetOutputs(OutputConsumer f); void GetOutputs(OutputConsumer f);
bool EnableOutput(int); void EnableOutput(int id);
bool DisableOutput(int); void DisableOutput(int id);
void GetURLHandlers(StringConsumer f); void GetURLHandlers(StringConsumer f);
void GetTagTypes(StringConsumer f); void GetTagTypes(StringConsumer f);
void idle();
int noidle();
private: private:
void GoIdle();
int GoBusy();
int CheckForErrors(); void checkConnection() const;
void prechecks();
void prechecksNoCommandsList();
void checkErrors() const;
mpd_connection *itsConnection; mpd_connection *m_connection;
bool isCommandsListEnabled; bool m_command_list_active;
std::string itsErrorMessage; int m_fd;
bool m_idle;
int itsFD; std::string m_host;
bool isIdle; int m_port;
bool isIdleEnabled; int m_timeout;
bool itsIdleBlocked; std::string m_password;
bool supportsIdle;
bool hasData;
std::string itsHost; mpd_tag_type m_searched_field;
int itsPort;
int itsTimeout;
std::string itsPassword;
mpd_status *itsCurrentStatus;
mpd_status *itsOldStatus;
unsigned itsElapsed;
time_t itsElapsedTimer[2];
StatusChanges itsChanges;
StatusUpdater itsUpdater;
void *itsStatusUpdaterUserdata;
ErrorHandler itsErrorHandler;
void *itsErrorHandlerUserdata;
mpd_tag_type itsSearchedField;
}; };
} }
extern MPD::Connection Mpd; extern MPD::Connection Mpd;
extern MPD::Status MpdStatus;
#endif // NCMPCPP_MPDPP_H #endif // NCMPCPP_MPDPP_H

View File

@@ -40,6 +40,7 @@
#include "error.h" #include "error.h"
#include "helpers.h" #include "helpers.h"
#include "lyrics.h" #include "lyrics.h"
#include "outputs.h"
#include "playlist.h" #include "playlist.h"
#include "settings.h" #include "settings.h"
#include "status.h" #include "status.h"
@@ -97,7 +98,6 @@ int main(int argc, char **argv)
using Global::wHeader; using Global::wHeader;
using Global::wFooter; using Global::wFooter;
using Global::ShowMessages;
using Global::VolumeState; using Global::VolumeState;
using Global::Timer; using Global::Timer;
@@ -126,20 +126,10 @@ int main(int argc, char **argv)
Mpd.SetPort(Config.mpd_port); Mpd.SetPort(Config.mpd_port);
Mpd.SetTimeout(Config.mpd_connection_timeout); Mpd.SetTimeout(Config.mpd_connection_timeout);
Mpd.SetIdleEnabled(Config.enable_idle_notifications);
if (argc > 1) if (argc > 1)
ParseArgv(argc, argv); ParseArgv(argc, argv);
if (!Actions::connectToMPD())
exit(1);
if (Mpd.Version() < 16)
{
std::cout << "MPD < 0.16.0 is not supported, please upgrade.\n";
exit(1);
}
CreateDir(Config.ncmpcpp_directory); CreateDir(Config.ncmpcpp_directory);
// always execute these commands, even if ncmpcpp use exit function // always execute these commands, even if ncmpcpp use exit function
@@ -171,8 +161,6 @@ int main(int argc, char **argv)
wFooter = new NC::Window(0, Actions::FooterStartY, COLS, Actions::FooterHeight, "", Config.statusbar_color, NC::Border::None); wFooter = new NC::Window(0, Actions::FooterStartY, COLS, Actions::FooterHeight, "", Config.statusbar_color, NC::Border::None);
wFooter->setTimeout(500); wFooter->setTimeout(500);
wFooter->setGetStringHelper(Statusbar::Helpers::getString); wFooter->setGetStringHelper(Statusbar::Helpers::getString);
if (Mpd.SupportsIdle())
wFooter->addFDCallback(Mpd.GetFD(), Statusbar::Helpers::mpd);
wFooter->createHistory(); wFooter->createHistory();
// initialize global timer // initialize global timer
@@ -186,9 +174,6 @@ int main(int argc, char **argv)
if (Config.startup_screen != myScreen) if (Config.startup_screen != myScreen)
Config.startup_screen->switchTo(); Config.startup_screen->switchTo();
Mpd.SetStatusUpdater(Status::update, 0);
Mpd.SetErrorHandler(Status::handleError, 0);
// local variables // local variables
Key input(0, Key::Standard); Key input(0, Key::Standard);
timeval past = { 0, 0 }; timeval past = { 0, 0 };
@@ -198,15 +183,6 @@ int main(int argc, char **argv)
if (Config.mouse_support) if (Config.mouse_support)
mousemask(ALL_MOUSE_EVENTS, 0); mousemask(ALL_MOUSE_EVENTS, 0);
Mpd.OrderDataFetching();
if (Config.jump_to_now_playing_song_at_start)
{
Status::trace();
int curr_pos = Mpd.GetCurrentSongPos();
if (curr_pos >= 0)
myPlaylist->main().highlight(curr_pos);
}
# ifndef WIN32 # ifndef WIN32
signal(SIGPIPE, sighandler); signal(SIGPIPE, sighandler);
signal(SIGWINCH, sighandler); signal(SIGWINCH, sighandler);
@@ -214,66 +190,95 @@ int main(int argc, char **argv)
while (!Actions::ExitMainLoop) while (!Actions::ExitMainLoop)
{ {
if (!Mpd.Connected()) try
{ {
if (!wFooter->FDCallbacksListEmpty()) if (!Mpd.Connected())
wFooter->clearFDCallbacksList();
Statusbar::msg("Attempting to reconnect...");
if (Mpd.Connect())
{ {
Statusbar::msg("Connected to %s", Mpd.GetHostname().c_str()); wFooter->clearFDCallbacksList();
if (Mpd.SupportsIdle()) try
{ {
Mpd.Connect();
if (Mpd.Version() < 16)
{
// FIXME workaround so we won't get assertion fails
MpdStatus = Mpd.getStatus();
Mpd.Disconnect();
throw MPD::ClientError(MPD_ERROR_STATE, "MPD < 0.16.0 is not supported", false);
}
MpdStatus.clear();
wFooter->addFDCallback(Mpd.GetFD(), Statusbar::Helpers::mpd); wFooter->addFDCallback(Mpd.GetFD(), Statusbar::Helpers::mpd);
Mpd.OrderDataFetching(); // we need info about new connection Status::update(-1); // we need info about new connection
if (Config.jump_to_now_playing_song_at_start)
{
int curr_pos = MpdStatus.currentSongPosition();
if (curr_pos >= 0)
myPlaylist->main().highlight(curr_pos);
}
myBrowser->fetchSupportedExtensions();
# ifdef ENABLE_OUTPUTS
myOutputs->FetchList();
# endif // ENABLE_OUTPUTS
# ifdef ENABLE_VISUALIZER
myVisualizer->ResetFD();
if (myScreen == myVisualizer)
myVisualizer->SetFD();
myVisualizer->FindOutputID();
# endif // ENABLE_VISUALIZER
Statusbar::msg("Connected to %s", Mpd.GetHostname().c_str());
}
catch (MPD::ClientError &e)
{
Status::handleClientError(e);
} }
ShowMessages = false;
# ifdef ENABLE_VISUALIZER
myVisualizer->ResetFD();
if (myScreen == myVisualizer)
myVisualizer->SetFD();
myVisualizer->FindOutputID();
# endif // ENABLE_VISUALIZER
} }
Status::trace();
// header stuff
if (((Timer.tv_sec == past.tv_sec && Timer.tv_usec >= past.tv_usec+500000) || Timer.tv_sec > past.tv_sec)
&& (myScreen == myPlaylist || myScreen == myBrowser || myScreen == myLyrics)
)
{
drawHeader();
past = Timer;
}
// header stuff end
if (input != Key::noOp)
myScreen->refreshWindow();
input = Key::read(*wFooter);
if (input == Key::noOp)
continue;
auto k = Bindings.get(input);
for (; k.first != k.second; ++k.first)
if (k.first->execute())
break;
if (myScreen == myPlaylist)
myPlaylist->EnableHighlighting();
# ifdef ENABLE_VISUALIZER
// visualizer sets timeout to 40ms, but since only it needs such small
// value, we should restore defalt one after switching to another screen.
if (wFooter->getTimeout() < 500
&& !(myScreen == myVisualizer || myLockedScreen == myVisualizer || myInactiveScreen == myVisualizer)
)
wFooter->setTimeout(500);
# endif // ENABLE_VISUALIZER
} }
catch (MPD::ClientError &e)
Status::trace();
ShowMessages = true;
// header stuff
if (((Timer.tv_sec == past.tv_sec && Timer.tv_usec >= past.tv_usec+500000) || Timer.tv_sec > past.tv_sec)
&& (myScreen == myPlaylist || myScreen == myBrowser || myScreen == myLyrics)
)
{ {
drawHeader(); Status::handleClientError(e);
past = Timer; }
catch (MPD::ServerError &e)
{
Status::handleServerError(e);
} }
// header stuff end
if (input != Key::noOp)
myScreen->refreshWindow();
input = Key::read(*wFooter);
if (input == Key::noOp)
continue;
auto k = Bindings.get(input);
for (; k.first != k.second; ++k.first)
if (k.first->execute())
break;
if (myScreen == myPlaylist)
myPlaylist->EnableHighlighting();
# ifdef ENABLE_VISUALIZER
// visualizer sets timeout to 40ms, but since only it needs such small
// value, we should restore defalt one after switching to another screen.
if (wFooter->getTimeout() < 500
&& !(myScreen == myVisualizer || myLockedScreen == myVisualizer || myInactiveScreen == myVisualizer)
)
wFooter->setTimeout(500);
# endif // ENABLE_VISUALIZER
} }
return 0; return 0;
} }

View File

@@ -46,7 +46,6 @@ Outputs::Outputs()
w.setItemDisplayer([](NC::Menu<MPD::Output> &menu) { w.setItemDisplayer([](NC::Menu<MPD::Output> &menu) {
menu << Charset::utf8ToLocale(menu.drawn()->value().name()); menu << Charset::utf8ToLocale(menu.drawn()->value().name());
}); });
FetchList();
} }
void Outputs::switchTo() void Outputs::switchTo()
@@ -73,16 +72,14 @@ void Outputs::enterPressed()
{ {
if (w.current().value().isEnabled()) if (w.current().value().isEnabled())
{ {
if (Mpd.DisableOutput(w.choice())) Mpd.DisableOutput(w.choice());
Statusbar::msg("Output \"%s\" disabled", w.current().value().name().c_str()); Statusbar::msg("Output \"%s\" disabled", w.current().value().name().c_str());
} }
else else
{ {
if (Mpd.EnableOutput(w.choice())) Mpd.EnableOutput(w.choice());
Statusbar::msg("Output \"%s\" enabled", w.current().value().name().c_str()); Statusbar::msg("Output \"%s\" enabled", w.current().value().name().c_str());
} }
if (!Mpd.SupportsIdle())
FetchList();
} }
void Outputs::mouseButtonPressed(MEVENT me) void Outputs::mouseButtonPressed(MEVENT me)

View File

@@ -43,6 +43,7 @@ Playlist *myPlaylist;
bool Playlist::ReloadTotalLength = 0; bool Playlist::ReloadTotalLength = 0;
bool Playlist::ReloadRemaining = false; bool Playlist::ReloadRemaining = false;
unsigned Playlist::Version = 0;
namespace {// namespace {//
@@ -217,9 +218,9 @@ MPD::SongList Playlist::getSelectedSongs()
MPD::Song Playlist::nowPlayingSong() MPD::Song Playlist::nowPlayingSong()
{ {
MPD::Song s; MPD::Song s;
if (Mpd.isPlaying()) if (MpdStatus.playerState() != MPD::psStop)
withUnfilteredMenu(w, [this, &s]() { withUnfilteredMenu(w, [this, &s]() {
s = w.at(Mpd.GetCurrentSongPos()).value(); s = w.at(MpdStatus.currentSongPosition()).value();
}); });
return s; return s;
} }
@@ -242,8 +243,8 @@ void Playlist::Reverse()
Mpd.StartCommandsList(); Mpd.StartCommandsList();
for (--end; begin < end; ++begin, --end) for (--end; begin < end; ++begin, --end)
Mpd.Swap(begin->value().getPosition(), end->value().getPosition()); Mpd.Swap(begin->value().getPosition(), end->value().getPosition());
if (Mpd.CommitCommandsList()) Mpd.CommitCommandsList();
Statusbar::msg("Playlist reversed"); Statusbar::msg("Playlist reversed");
} }
void Playlist::EnableHighlighting() void Playlist::EnableHighlighting()
@@ -271,7 +272,7 @@ std::string Playlist::TotalLength()
if (Config.playlist_show_remaining_time && ReloadRemaining && !w.isFiltered()) if (Config.playlist_show_remaining_time && ReloadRemaining && !w.isFiltered())
{ {
itsRemainingTime = 0; itsRemainingTime = 0;
for (size_t i = Mpd.GetCurrentSongPos(); i < w.size(); ++i) for (size_t i = MpdStatus.currentSongPosition(); i < w.size(); ++i)
itsRemainingTime += w[i].value().getDuration(); itsRemainingTime += w[i].value().getDuration();
ReloadRemaining = false; ReloadRemaining = false;
} }
@@ -284,7 +285,7 @@ std::string Playlist::TotalLength()
size_t real_size = w.size(); size_t real_size = w.size();
w.showFiltered(); w.showFiltered();
if (w.size() != real_size) if (w.size() != real_size)
result << " (out of " << Mpd.GetPlaylistLength() << ")"; result << " (out of " << real_size << ")";
} }
if (itsTotalLength) if (itsTotalLength)
@@ -307,7 +308,7 @@ void Playlist::PlayNewlyAddedSongs()
bool is_filtered = w.isFiltered(); bool is_filtered = w.isFiltered();
w.showAll(); w.showAll();
size_t old_size = w.size(); size_t old_size = w.size();
Mpd.UpdateStatus(); //Mpd.UpdateStatus();
if (old_size < w.size()) if (old_size < w.size())
Mpd.Play(old_size); Mpd.Play(old_size);
if (is_filtered) if (is_filtered)
@@ -320,8 +321,8 @@ void Playlist::SetSelectedItemsPriority(int prio)
Mpd.StartCommandsList(); Mpd.StartCommandsList();
for (auto it = list.begin(); it != list.end(); ++it) for (auto it = list.begin(); it != list.end(); ++it)
Mpd.SetPriority((*it)->value(), prio); Mpd.SetPriority((*it)->value(), prio);
if (Mpd.CommitCommandsList()) Mpd.CommitCommandsList();
Statusbar::msg("Priority set"); Statusbar::msg("Priority set");
} }
bool Playlist::checkForSong(const MPD::Song &s) bool Playlist::checkForSong(const MPD::Song &s)

View File

@@ -83,6 +83,7 @@ struct Playlist: Screen<NC::Menu<MPD::Song>>, Filterable, HasSongs, Searchable,
void registerHash(size_t hash); void registerHash(size_t hash);
void unregisterHash(size_t hash); void unregisterHash(size_t hash);
static unsigned Version;
static bool ReloadTotalLength; static bool ReloadTotalLength;
static bool ReloadRemaining; static bool ReloadRemaining;

View File

@@ -221,12 +221,10 @@ void PlaylistEditor::AddToPlaylist(bool add_n_play)
if (isActiveWindow(Playlists) && !Playlists.empty()) if (isActiveWindow(Playlists) && !Playlists.empty())
{ {
if (Mpd.LoadPlaylist(Playlists.current().value())) Mpd.LoadPlaylist(Playlists.current().value());
{ Statusbar::msg("Playlist \"%s\" loaded", Playlists.current().value().c_str());
Statusbar::msg("Playlist \"%s\" loaded", Playlists.current().value().c_str()); if (add_n_play)
if (add_n_play) myPlaylist->PlayNewlyAddedSongs();
myPlaylist->PlayNewlyAddedSongs();
}
} }
else if (isActiveWindow(Content) && !Content.empty()) else if (isActiveWindow(Content) && !Content.empty())
addSongToPlaylist(Content.current().value(), add_n_play); addSongToPlaylist(Content.current().value(), add_n_play);

View File

@@ -234,61 +234,54 @@ void SelectedItemsAdder::addToExistingPlaylist(const std::string &playlist) cons
Mpd.StartCommandsList(); Mpd.StartCommandsList();
for (auto s = m_selected_items.begin(); s != m_selected_items.end(); ++s) for (auto s = m_selected_items.begin(); s != m_selected_items.end(); ++s)
Mpd.AddToPlaylist(playlist, *s); Mpd.AddToPlaylist(playlist, *s);
if (Mpd.CommitCommandsList()) Mpd.CommitCommandsList();
{ Statusbar::msg("Selected item(s) added to playlist \"%s\"", playlist.c_str());
Statusbar::msg("Selected item(s) added to playlist \"%s\"", playlist.c_str()); switchToPreviousScreen();
switchToPreviousScreen();
}
} }
void SelectedItemsAdder::addAtTheEndOfPlaylist() const void SelectedItemsAdder::addAtTheEndOfPlaylist() const
{ {
bool success = addSongsToPlaylist(m_selected_items, false); addSongsToPlaylist(m_selected_items, false);
if (success) exitSuccessfully();
exitSuccessfully();
} }
void SelectedItemsAdder::addAtTheBeginningOfPlaylist() const void SelectedItemsAdder::addAtTheBeginningOfPlaylist() const
{ {
bool success = addSongsToPlaylist(m_selected_items, false, 0); addSongsToPlaylist(m_selected_items, false, 0);
if (success) exitSuccessfully();
exitSuccessfully();
} }
void SelectedItemsAdder::addAfterCurrentSong() const void SelectedItemsAdder::addAfterCurrentSong() const
{ {
if (!Mpd.isPlaying()) if (MpdStatus.playerState() == MPD::psStop)
return; return;
size_t pos = Mpd.GetCurrentSongPos(); size_t pos = MpdStatus.currentSongPosition();
++pos; ++pos;
bool success = addSongsToPlaylist(m_selected_items, false, pos); addSongsToPlaylist(m_selected_items, false, pos);
if (success) exitSuccessfully();
exitSuccessfully();
} }
void SelectedItemsAdder::addAfterCurrentAlbum() const void SelectedItemsAdder::addAfterCurrentAlbum() const
{ {
if (!Mpd.isPlaying()) if (MpdStatus.playerState() == MPD::psStop)
return; return;
auto &pl = myPlaylist->main(); auto &pl = myPlaylist->main();
size_t pos = Mpd.GetCurrentSongPos(); size_t pos = MpdStatus.currentSongPosition();
withUnfilteredMenu(pl, [&pos, &pl]() { withUnfilteredMenu(pl, [&pos, &pl]() {
std::string album = pl[pos].value().getAlbum(); std::string album = pl[pos].value().getAlbum();
while (pos < pl.size() && pl[pos].value().getAlbum() == album) while (pos < pl.size() && pl[pos].value().getAlbum() == album)
++pos; ++pos;
}); });
bool success = addSongsToPlaylist(m_selected_items, false, pos); addSongsToPlaylist(m_selected_items, false, pos);
if (success) exitSuccessfully();
exitSuccessfully();
} }
void SelectedItemsAdder::addAfterHighlightedSong() const void SelectedItemsAdder::addAfterHighlightedSong() const
{ {
size_t pos = myPlaylist->main().current().value().getPosition(); size_t pos = myPlaylist->main().current().value().getPosition();
++pos; ++pos;
bool success = addSongsToPlaylist(m_selected_items, false, pos); addSongsToPlaylist(m_selected_items, false, pos);
if (success) exitSuccessfully();
exitSuccessfully();
} }
void SelectedItemsAdder::cancel() void SelectedItemsAdder::cancel()

View File

@@ -36,19 +36,25 @@ ServerInfo::ServerInfo()
{ {
SetDimensions(); SetDimensions();
w = NC::Scrollpad((COLS-itsWidth)/2, (MainHeight-itsHeight)/2+MainStartY, itsWidth, itsHeight, "MPD server info", Config.main_color, Config.window_border); w = NC::Scrollpad((COLS-itsWidth)/2, (MainHeight-itsHeight)/2+MainStartY, itsWidth, itsHeight, "MPD server info", Config.main_color, Config.window_border);
Mpd.GetURLHandlers([this](std::string &&handler) {
itsURLHandlers.push_back(handler);
});
Mpd.GetTagTypes([this](std::string &&tag_type) {
itsTagTypes.push_back(tag_type);
});
} }
void ServerInfo::switchTo() void ServerInfo::switchTo()
{ {
using Global::myScreen; using Global::myScreen;
if (myScreen != this) if (myScreen != this)
{
SwitchTo::execute(this); SwitchTo::execute(this);
itsURLHandlers.clear();
itsTagTypes.clear();
Mpd.GetURLHandlers([this](std::string &&handler) {
itsURLHandlers.push_back(handler);
});
Mpd.GetTagTypes([this](std::string &&tag_type) {
itsTagTypes.push_back(tag_type);
});
}
else else
switchToPreviousScreen(); switchToPreviousScreen();
} }

View File

@@ -201,11 +201,9 @@ void SortPlaylistDialog::sort() const
Statusbar::msg("Sorting..."); Statusbar::msg("Sorting...");
Mpd.StartCommandsList(); Mpd.StartCommandsList();
quick_sort(playlist.begin(), playlist.end()); quick_sort(playlist.begin(), playlist.end());
if (Mpd.CommitCommandsList()) Mpd.CommitCommandsList();
{ Statusbar::msg("Playlist sorted");
Statusbar::msg("Playlist sorted"); switchToPreviousScreen();
switchToPreviousScreen();
}
} }
void SortPlaylistDialog::cancel() const void SortPlaylistDialog::cancel() const

View File

@@ -71,68 +71,68 @@ void drawTitle(const MPD::Song &np)
} }
void Status::trace() void Status::handleClientError(MPD::ClientError &e)
{ {
gettimeofday(&Timer, 0); if (!e.clearable())
if (Mpd.Connected() && (Mpd.SupportsIdle() || Timer.tv_sec > past.tv_sec)) Mpd.Disconnect();
{ Statusbar::msg("NCMPCPP: %s", e.what());
if (!Mpd.SupportsIdle())
{
past = Timer;
}
else if (Config.display_bitrate && Global::Timer.tv_sec > past.tv_sec && Mpd.GetState() == MPD::psPlay)
{
// ncmpcpp doesn't fetch status constantly if mpd supports
// idle mode so current song's bitrate is never updated.
// we need to force ncmpcpp to fetch it.
Mpd.OrderDataFetching();
past = Timer;
}
Mpd.UpdateStatus();
}
applyToVisibleWindows(&BaseScreen::update);
if (isVisible(myPlaylist)
&& Timer.tv_sec == myPlaylist->Timer()+Config.playlist_disable_highlight_delay
&& myPlaylist->main().isHighlighted()
&& Config.playlist_disable_highlight_delay)
{
myPlaylist->main().setHighlighting(false);
myPlaylist->main().refresh();
}
Statusbar::tryRedraw();
} }
void Status::handleError(MPD::Connection * , int errorid, const char *msg, void *) void Status::handleServerError(MPD::ServerError &e)
{ {
// for errorid: if (e.code() == MPD_SERVER_ERROR_PERMISSION)
// - 0-7 bits define MPD_ERROR_* codes, compare them with (0xff & errorid)
// - 8-15 bits define MPD_SERVER_ERROR_* codes, compare them with (errorid >> 8)
if ((errorid >> 8) == MPD_SERVER_ERROR_PERMISSION)
{ {
wFooter->setGetStringHelper(0); wFooter->setGetStringHelper(nullptr);
Statusbar::put() << "Password: "; Statusbar::put() << "Password: ";
Mpd.SetPassword(wFooter->getString(-1, 0, 1)); Mpd.SetPassword(wFooter->getString(-1, 0, 1));
if (Mpd.SendPassword()) Mpd.SendPassword();
Statusbar::msg("Password accepted"); Statusbar::msg("Password accepted");
wFooter->setGetStringHelper(Statusbar::Helpers::getString); wFooter->setGetStringHelper(Statusbar::Helpers::getString);
} }
else if ((errorid >> 8) == MPD_SERVER_ERROR_NO_EXIST && myScreen == myBrowser) else if (e.code() == MPD_SERVER_ERROR_NO_EXIST && myScreen == myBrowser)
{ {
myBrowser->GetDirectory(getParentDirectory(myBrowser->CurrentDir())); myBrowser->GetDirectory(getParentDirectory(myBrowser->CurrentDir()));
myBrowser->refresh(); myBrowser->refresh();
} }
else Statusbar::msg("MPD: %s", e.what());
Statusbar::msg("MPD: %s", msg); }
void Status::trace()
{
gettimeofday(&Timer, 0);
if (Mpd.Connected())
{
if (MpdStatus.playerState() == MPD::psPlay && Global::Timer.tv_sec > past.tv_sec)
{
// update elapsed time/bitrate of the current song
MpdStatus = Mpd.getStatus();
Status::Changes::elapsedTime();
wFooter->refresh();
past = Timer;
}
applyToVisibleWindows(&BaseScreen::update);
if (isVisible(myPlaylist)
&& Timer.tv_sec == myPlaylist->Timer()+Config.playlist_disable_highlight_delay
&& myPlaylist->main().isHighlighted()
&& Config.playlist_disable_highlight_delay)
{
myPlaylist->main().setHighlighting(false);
myPlaylist->main().refresh();
}
Statusbar::tryRedraw();
Mpd.idle();
}
} }
void Status::Changes::playlist() void Status::Changes::playlist()
{ {
myPlaylist->main().clearSearchResults(); myPlaylist->main().clearSearchResults();
withUnfilteredMenuReapplyFilter(myPlaylist->main(), []() { withUnfilteredMenuReapplyFilter(myPlaylist->main(), []() {
size_t playlist_length = Mpd.GetPlaylistLength(); size_t playlist_length = MpdStatus.playlistLength();
if (playlist_length < myPlaylist->main().size()) if (playlist_length < myPlaylist->main().size())
{ {
auto it = myPlaylist->main().begin()+playlist_length; auto it = myPlaylist->main().begin()+playlist_length;
@@ -142,7 +142,7 @@ void Status::Changes::playlist()
myPlaylist->main().resizeList(playlist_length); myPlaylist->main().resizeList(playlist_length);
} }
Mpd.GetPlaylistChanges(Mpd.GetOldPlaylistID(), [](MPD::Song &&s) { Mpd.GetPlaylistChanges(myPlaylist->Version, [](MPD::Song &&s) {
size_t pos = s.getPosition(); size_t pos = s.getPosition();
if (pos < myPlaylist->main().size()) if (pos < myPlaylist->main().size())
{ {
@@ -155,9 +155,11 @@ void Status::Changes::playlist()
myPlaylist->main().addItem(s); myPlaylist->main().addItem(s);
myPlaylist->registerHash(s.getHash()); myPlaylist->registerHash(s.getHash());
}); });
myPlaylist->Version = MpdStatus.playlistVersion();
}); });
if (Mpd.isPlaying()) if (MpdStatus.playerState() != MPD::psStop)
drawTitle(myPlaylist->nowPlayingSong()); drawTitle(myPlaylist->nowPlayingSong());
Playlist::ReloadTotalLength = true; Playlist::ReloadTotalLength = true;
@@ -201,7 +203,7 @@ void Status::Changes::database()
void Status::Changes::playerState() void Status::Changes::playerState()
{ {
MPD::PlayerState state = Mpd.GetState(); MPD::PlayerState state = MpdStatus.playerState();
switch (state) switch (state)
{ {
case MPD::psUnknown: case MPD::psUnknown:
@@ -214,8 +216,6 @@ void Status::Changes::playerState()
drawTitle(myPlaylist->nowPlayingSong()); drawTitle(myPlaylist->nowPlayingSong());
player_state = Config.new_design ? "[playing]" : "Playing: "; player_state = Config.new_design ? "[playing]" : "Playing: ";
Playlist::ReloadRemaining = true; Playlist::ReloadRemaining = true;
if (Mpd.GetOldState() == MPD::psStop) // show track info in status immediately
elapsedTime();
break; break;
} }
case MPD::psPause: case MPD::psPause:
@@ -272,7 +272,7 @@ void Status::Changes::songID()
playing_song_scroll_begin = 0; playing_song_scroll_begin = 0;
first_line_scroll_begin = 0; first_line_scroll_begin = 0;
second_line_scroll_begin = 0; second_line_scroll_begin = 0;
if (Mpd.isPlaying()) if (MpdStatus.playerState() != MPD::psStop)
{ {
GNUC_UNUSED int res; GNUC_UNUSED int res;
if (!Config.execute_on_song_change.empty()) if (!Config.execute_on_song_change.empty())
@@ -286,18 +286,17 @@ void Status::Changes::songID()
drawTitle(myPlaylist->nowPlayingSong()); drawTitle(myPlaylist->nowPlayingSong());
if (Config.autocenter_mode && !myPlaylist->main().isFiltered()) if (Config.autocenter_mode && !myPlaylist->main().isFiltered())
myPlaylist->main().highlight(Mpd.GetCurrentSongPos()); myPlaylist->main().highlight(MpdStatus.currentSongPosition());
if (Config.now_playing_lyrics && isVisible(myLyrics) && myLyrics->previousScreen() == myPlaylist) if (Config.now_playing_lyrics && isVisible(myLyrics) && myLyrics->previousScreen() == myPlaylist)
myLyrics->ReloadNP = 1; myLyrics->ReloadNP = 1;
elapsedTime();
} }
elapsedTime();
} }
void Status::Changes::elapsedTime() void Status::Changes::elapsedTime()
{ {
if (!Mpd.isPlaying()) if (MpdStatus.playerState() == MPD::psStop)
{ {
if (Statusbar::isUnlocked() && Config.statusbar_visibility) if (Statusbar::isUnlocked() && Config.statusbar_visibility)
*wFooter << NC::XY(0, 1) << wclrtoeol; *wFooter << NC::XY(0, 1) << wclrtoeol;
@@ -313,20 +312,20 @@ void Status::Changes::elapsedTime()
if (Config.display_remaining_time) if (Config.display_remaining_time)
{ {
tracklength = "-"; tracklength = "-";
tracklength += MPD::Song::ShowTime(Mpd.GetTotalTime()-Mpd.GetElapsedTime()); tracklength += MPD::Song::ShowTime(MpdStatus.totalTime()-MpdStatus.elapsedTime());
} }
else else
tracklength = MPD::Song::ShowTime(Mpd.GetElapsedTime()); tracklength = MPD::Song::ShowTime(MpdStatus.elapsedTime());
if (Mpd.GetTotalTime()) if (MpdStatus.totalTime())
{ {
tracklength += "/"; tracklength += "/";
tracklength += MPD::Song::ShowTime(Mpd.GetTotalTime()); tracklength += MPD::Song::ShowTime(MpdStatus.totalTime());
} }
// bitrate here doesn't look good, but it can be moved somewhere else later // bitrate here doesn't look good, but it can be moved somewhere else later
if (Config.display_bitrate && Mpd.GetBitrate()) if (Config.display_bitrate && MpdStatus.kbps())
{ {
tracklength += " "; tracklength += " ";
tracklength += boost::lexical_cast<std::string>(Mpd.GetBitrate()); tracklength += boost::lexical_cast<std::string>(MpdStatus.kbps());
tracklength += " kbps"; tracklength += " kbps";
} }
@@ -357,29 +356,29 @@ void Status::Changes::elapsedTime()
} }
else if (Statusbar::isUnlocked() && Config.statusbar_visibility) else if (Statusbar::isUnlocked() && Config.statusbar_visibility)
{ {
if (Config.display_bitrate && Mpd.GetBitrate()) if (Config.display_bitrate && MpdStatus.kbps())
{ {
tracklength += " ["; tracklength += " [";
tracklength += boost::lexical_cast<std::string>(Mpd.GetBitrate()); tracklength += boost::lexical_cast<std::string>(MpdStatus.kbps());
tracklength += " kbps]"; tracklength += " kbps]";
} }
tracklength += " ["; tracklength += " [";
if (Mpd.GetTotalTime()) if (MpdStatus.totalTime())
{ {
if (Config.display_remaining_time) if (Config.display_remaining_time)
{ {
tracklength += "-"; tracklength += "-";
tracklength += MPD::Song::ShowTime(Mpd.GetTotalTime()-Mpd.GetElapsedTime()); tracklength += MPD::Song::ShowTime(MpdStatus.totalTime()-MpdStatus.elapsedTime());
} }
else else
tracklength += MPD::Song::ShowTime(Mpd.GetElapsedTime()); tracklength += MPD::Song::ShowTime(MpdStatus.elapsedTime());
tracklength += "/"; tracklength += "/";
tracklength += MPD::Song::ShowTime(Mpd.GetTotalTime()); tracklength += MPD::Song::ShowTime(MpdStatus.totalTime());
tracklength += "]"; tracklength += "]";
} }
else else
{ {
tracklength += MPD::Song::ShowTime(Mpd.GetElapsedTime()); tracklength += MPD::Song::ShowTime(MpdStatus.elapsedTime());
tracklength += "]"; tracklength += "]";
} }
NC::WBuffer np_song; NC::WBuffer np_song;
@@ -389,44 +388,50 @@ void Status::Changes::elapsedTime()
*wFooter << NC::Format::Bold << NC::XY(wFooter->getWidth()-tracklength.length(), 1) << tracklength << NC::Format::NoBold; *wFooter << NC::Format::Bold << NC::XY(wFooter->getWidth()-tracklength.length(), 1) << tracklength << NC::Format::NoBold;
} }
if (Progressbar::isUnlocked()) if (Progressbar::isUnlocked())
Progressbar::draw(Mpd.GetElapsedTime(), Mpd.GetTotalTime()); Progressbar::draw(MpdStatus.elapsedTime(), MpdStatus.totalTime());
} }
void Status::Changes::repeat() void Status::Changes::repeat(bool show_msg)
{ {
mpd_repeat = Mpd.GetRepeat() ? 'r' : 0; mpd_repeat = MpdStatus.repeat() ? 'r' : 0;
Statusbar::msg("Repeat mode is %s", !mpd_repeat ? "off" : "on"); if (show_msg)
Statusbar::msg("Repeat mode is %s", !mpd_repeat ? "off" : "on");
} }
void Status::Changes::random() void Status::Changes::random(bool show_msg)
{ {
mpd_random = Mpd.GetRandom() ? 'z' : 0; mpd_random = MpdStatus.random() ? 'z' : 0;
Statusbar::msg("Random mode is %s", !mpd_random ? "off" : "on"); if (show_msg)
Statusbar::msg("Random mode is %s", !mpd_random ? "off" : "on");
} }
void Status::Changes::single() void Status::Changes::single(bool show_msg)
{ {
mpd_single = Mpd.GetSingle() ? 's' : 0; mpd_single = MpdStatus.single() ? 's' : 0;
Statusbar::msg("Single mode is %s", !mpd_single ? "off" : "on"); if (show_msg)
Statusbar::msg("Single mode is %s", !mpd_single ? "off" : "on");
} }
void Status::Changes::consume() void Status::Changes::consume(bool show_msg)
{ {
mpd_consume = Mpd.GetConsume() ? 'c' : 0; mpd_consume = MpdStatus.consume() ? 'c' : 0;
Statusbar::msg("Consume mode is %s", !mpd_consume ? "off" : "on"); if (show_msg)
Statusbar::msg("Consume mode is %s", !mpd_consume ? "off" : "on");
} }
void Status::Changes::crossfade() void Status::Changes::crossfade(bool show_msg)
{ {
int crossfade = Mpd.GetCrossfade(); int crossfade = MpdStatus.crossfade();
mpd_crossfade = crossfade ? 'x' : 0; mpd_crossfade = crossfade ? 'x' : 0;
Statusbar::msg("Crossfade set to %d seconds", crossfade); if (show_msg)
Statusbar::msg("Crossfade set to %d seconds", crossfade);
} }
void Status::Changes::dbUpdateState() void Status::Changes::dbUpdateState(bool show_msg)
{ {
mpd_db_updating = Mpd.GetDBIsUpdating() ? 'U' : 0; mpd_db_updating = MpdStatus.updateID() ? 'U' : 0;
Statusbar::msg(Mpd.GetDBIsUpdating() ? "Database update started" : "Database update finished"); if (show_msg)
Statusbar::msg(MpdStatus.updateID() ? "Database update started" : "Database update finished");
} }
void Status::Changes::flags() void Status::Changes::flags()
@@ -494,7 +499,7 @@ void Status::Changes::mixer()
return; return;
VolumeState = Config.new_design ? " Vol: " : " Volume: "; VolumeState = Config.new_design ? " Vol: " : " Volume: ";
int volume = Mpd.GetVolume(); int volume = MpdStatus.volume();
if (volume < 0) if (volume < 0)
VolumeState += "n/a"; VolumeState += "n/a";
else else
@@ -515,41 +520,50 @@ void Status::Changes::outputs()
# endif // ENABLE_OUTPUTS # endif // ENABLE_OUTPUTS
} }
void Status::update(MPD::Connection *, MPD::StatusChanges changes, void *) void Status::update(int event)
{ {
if (changes.Playlist) MPD::Status old = MpdStatus;
Changes::playlist(); MpdStatus = Mpd.getStatus();
if (changes.StoredPlaylists)
Changes::storedPlaylists();
if (changes.Database)
Changes::database();
if (changes.PlayerState)
Changes::playerState();
if (changes.SongID)
Changes::songID();
if (changes.ElapsedTime)
Changes::elapsedTime();
if (changes.Repeat)
Changes::repeat();
if (changes.Random)
Changes::random();
if (changes.Single)
Changes::single();
if (changes.Consume)
Changes::consume();
if (changes.Crossfade)
Changes::crossfade();
if (changes.DBUpdating)
Changes::dbUpdateState();
if (changes.StatusFlags)
Changes::flags();
if (changes.Volume)
Changes::mixer();
if (changes.Outputs)
Changes::outputs();
if (changes.PlayerState || (changes.ElapsedTime && (!Config.new_design || Mpd.GetState() == MPD::psPlay))) if (event & MPD_IDLE_DATABASE)
Changes::database();
if (event & MPD_IDLE_STORED_PLAYLIST)
Changes::storedPlaylists();
if (event & MPD_IDLE_PLAYLIST)
Changes::playlist();
if (event & MPD_IDLE_PLAYER)
{
Changes::playerState();
if (old.empty() || old.currentSongID() != MpdStatus.currentSongID())
Changes::songID();
}
if (event & MPD_IDLE_MIXER)
Changes::mixer();
if (event & MPD_IDLE_OUTPUT)
Changes::outputs();
if (event & (MPD_IDLE_UPDATE | MPD_IDLE_OPTIONS))
{
if (event & MPD_IDLE_UPDATE)
Changes::dbUpdateState(!old.empty());
if (event & MPD_IDLE_OPTIONS)
{
if (old.empty() || old.repeat() != MpdStatus.repeat())
Changes::repeat(!old.empty());
if (old.empty() || old.random() != MpdStatus.random())
Changes::random(!old.empty());
if (old.empty() || old.single() != MpdStatus.single())
Changes::single(!old.empty());
if (old.empty() || old.consume() != MpdStatus.consume())
Changes::consume(!old.empty());
if (old.empty() || old.crossfade() != MpdStatus.crossfade())
Changes::crossfade(!old.empty());
}
Changes::flags();
}
if (event & MPD_IDLE_PLAYER)
wFooter->refresh(); wFooter->refresh();
if (changes.Playlist || changes.Database || changes.PlayerState || changes.SongID)
if (event & (MPD_IDLE_PLAYLIST | MPD_IDLE_DATABASE | MPD_IDLE_PLAYER))
applyToVisibleWindows(&BaseScreen::refreshWindow); applyToVisibleWindows(&BaseScreen::refreshWindow);
} }

View File

@@ -26,11 +26,11 @@
namespace Status {// namespace Status {//
void handleClientError(MPD::ClientError &e);
void handleServerError(MPD::ServerError &e);
void trace(); void trace();
void update(int event);
void handleError(MPD::Connection * , int errorid, const char *msg, void *);
void update(MPD::Connection *, MPD::StatusChanges changes, void *);
namespace Changes {// namespace Changes {//
@@ -40,12 +40,12 @@ void database();
void playerState(); void playerState();
void songID(); void songID();
void elapsedTime(); void elapsedTime();
void repeat(); void repeat(bool show_msg);
void random(); void random(bool show_msg);
void single(); void single(bool show_msg);
void consume(); void consume(bool show_msg);
void crossfade(); void crossfade(bool show_msg);
void dbUpdateState(); void dbUpdateState(bool show_msg);
void flags(); void flags();
void mixer(); void mixer();
void outputs(); void outputs();

View File

@@ -38,7 +38,7 @@ bool statusbarAllowUnlock = true;
void showMessage(int time, const char *format, va_list list) void showMessage(int time, const char *format, va_list list)
{ {
if (Global::ShowMessages && statusbarAllowUnlock) if (statusbarAllowUnlock)
{ {
statusbarLockTime = Global::Timer; statusbarLockTime = Global::Timer;
statusbarLockDelay = time; statusbarLockDelay = time;
@@ -122,10 +122,10 @@ void Statusbar::unlock()
else else
progressbarBlockUpdate = false; progressbarBlockUpdate = false;
} }
if (!Mpd.isPlaying()) if (MpdStatus.playerState() == MPD::psStop)
{ {
if (Config.new_design) if (Config.new_design)
Progressbar::draw(Mpd.GetElapsedTime(), Mpd.GetTotalTime()); Progressbar::draw(MpdStatus.elapsedTime(), MpdStatus.totalTime());
else else
put() << wclrtoeol; put() << wclrtoeol;
wFooter->refresh(); wFooter->refresh();
@@ -150,12 +150,12 @@ void Statusbar::tryRedraw()
else else
progressbarBlockUpdate = !statusbarAllowUnlock; progressbarBlockUpdate = !statusbarAllowUnlock;
if (Mpd.GetState() != MPD::psPlay && !statusbarBlockUpdate && !progressbarBlockUpdate) if (MpdStatus.playerState() != MPD::psStop && !statusbarBlockUpdate && !progressbarBlockUpdate)
{ {
if (Config.new_design) if (Config.new_design)
Progressbar::draw(Mpd.GetElapsedTime(), Mpd.GetTotalTime()); Progressbar::draw(MpdStatus.elapsedTime(), MpdStatus.totalTime());
else else
put() << wclrtoeol; Status::Changes::elapsedTime();
wFooter->refresh(); wFooter->refresh();
} }
} }
@@ -185,7 +185,7 @@ void Statusbar::msg(int time, const char *format, ...)
void Statusbar::Helpers::mpd() void Statusbar::Helpers::mpd()
{ {
Mpd.OrderDataFetching(); Status::update(Mpd.noidle());
} }
bool Statusbar::Helpers::getString(const std::wstring &) bool Statusbar::Helpers::getString(const std::wstring &)

View File

@@ -57,8 +57,6 @@ Visualizer::Visualizer()
m_fftw_output = static_cast<fftw_complex *>(fftw_malloc(sizeof(fftw_complex)*m_fftw_results)); m_fftw_output = static_cast<fftw_complex *>(fftw_malloc(sizeof(fftw_complex)*m_fftw_results));
m_fftw_plan = fftw_plan_dft_r2c_1d(m_samples, m_fftw_input, m_fftw_output, FFTW_ESTIMATE); m_fftw_plan = fftw_plan_dft_r2c_1d(m_samples, m_fftw_input, m_fftw_output, FFTW_ESTIMATE);
# endif // HAVE_FFTW3_H # endif // HAVE_FFTW3_H
FindOutputID();
} }
void Visualizer::switchTo() void Visualizer::switchTo()