poll both stdin and mpd using one select()
this allows for immediate reading mpd events
This commit is contained in:
@@ -53,7 +53,6 @@ void Browser::Init()
|
||||
{
|
||||
w = new Menu<Item>(0, MainStartY, COLS, MainHeight, Config.columns_in_browser ? Display::Columns() : "", Config.main_color, brNone);
|
||||
w->HighlightColor(Config.main_highlight_color);
|
||||
w->SetTimeout(ncmpcpp_window_timeout);
|
||||
w->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
w->SetSelectPrefix(&Config.selected_item_prefix);
|
||||
w->SetSelectSuffix(&Config.selected_item_suffix);
|
||||
|
||||
@@ -52,7 +52,6 @@ void Clock::Init()
|
||||
Width = Config.clock_display_seconds ? 60 : 40;
|
||||
|
||||
w = new Window((COLS-Width)/2, (MainHeight-Height)/2+MainStartY, Width, Height-1, "", Config.main_color, Border(Config.main_color));
|
||||
w->SetTimeout(ncmpcpp_window_timeout);
|
||||
isInitialized = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ Help *myHelp = new Help;
|
||||
void Help::Init()
|
||||
{
|
||||
w = new Scrollpad(0, MainStartY, COLS, MainHeight, "", Config.main_color, brNone);
|
||||
w->SetTimeout(ncmpcpp_window_timeout);
|
||||
GetKeybindings();
|
||||
w->Flush();
|
||||
isInitialized = 1;
|
||||
|
||||
@@ -73,7 +73,6 @@ const Info::Metadata Info::Tags[] =
|
||||
void Info::Init()
|
||||
{
|
||||
w = new Scrollpad(0, MainStartY, COLS, MainHeight, "", Config.main_color, brNone);
|
||||
w->SetTimeout(ncmpcpp_window_timeout);
|
||||
isInitialized = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@ Lyrics *myLyrics = new Lyrics;
|
||||
void Lyrics::Init()
|
||||
{
|
||||
w = new Scrollpad(0, MainStartY, COLS, MainHeight, "", Config.main_color, brNone);
|
||||
w->SetTimeout(ncmpcpp_window_timeout);
|
||||
isInitialized = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,20 +52,17 @@ void MediaLibrary::Init()
|
||||
|
||||
Artists = new Menu<std::string>(0, MainStartY, itsLeftColWidth, MainHeight, IntoStr(Config.media_lib_primary_tag) + "s", Config.main_color, brNone);
|
||||
Artists->HighlightColor(Config.active_column_color);
|
||||
Artists->SetTimeout(ncmpcpp_window_timeout);
|
||||
Artists->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
Artists->SetItemDisplayer(Display::Generic);
|
||||
|
||||
Albums = new Menu< std::pair<std::string, SearchConstraints> >(itsMiddleColStartX, MainStartY, itsMiddleColWidth, MainHeight, "Albums", Config.main_color, brNone);
|
||||
Albums->HighlightColor(Config.main_highlight_color);
|
||||
Albums->SetTimeout(ncmpcpp_window_timeout);
|
||||
Albums->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
Albums->SetItemDisplayer(Display::Pairs);
|
||||
Albums->SetGetStringFunction(StringPairToString);
|
||||
|
||||
Songs = new Menu<Song>(itsRightColStartX, MainStartY, itsRightColWidth, MainHeight, "Songs", Config.main_color, brNone);
|
||||
Songs->HighlightColor(Config.main_highlight_color);
|
||||
Songs->SetTimeout(ncmpcpp_window_timeout);
|
||||
Songs->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
Songs->SetSelectPrefix(&Config.selected_item_prefix);
|
||||
Songs->SetSelectSuffix(&Config.selected_item_suffix);
|
||||
|
||||
@@ -38,7 +38,6 @@ void SelectedItemsAdder::Init()
|
||||
{
|
||||
SetDimensions();
|
||||
w = new Menu<std::string>((COLS-itsWidth)/2, (MainHeight-itsHeight)/2+MainStartY, itsWidth, itsHeight, "Add selected items to...", Config.main_color, Config.window_border);
|
||||
w->SetTimeout(ncmpcpp_window_timeout);
|
||||
w->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
w->HighlightColor(Config.main_highlight_color);
|
||||
w->SetItemDisplayer(Display::Generic);
|
||||
|
||||
@@ -151,14 +151,14 @@ void Connection::GoIdle()
|
||||
isIdle = 1;
|
||||
}
|
||||
|
||||
mpd_idle Connection::GoBusy()
|
||||
int Connection::GoBusy()
|
||||
{
|
||||
if (isIdle && mpd_send_noidle(itsConnection))
|
||||
{
|
||||
isIdle = 0;
|
||||
return mpd_recv_idle(itsConnection, 1);
|
||||
}
|
||||
return mpd_idle(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Connection::UpdateStatus()
|
||||
@@ -166,13 +166,14 @@ void Connection::UpdateStatus()
|
||||
if (!itsConnection)
|
||||
return;
|
||||
|
||||
int idle_mask = 0;
|
||||
if (isIdle)
|
||||
{
|
||||
FD_ZERO(&itsPoll);
|
||||
FD_SET(itsFD, &itsPoll);
|
||||
timeval timeout = { 0, 0 };
|
||||
if (select(itsFD+1, &itsPoll, 0, 0, &timeout) == 1)
|
||||
GoBusy();
|
||||
if (hasData)
|
||||
{
|
||||
idle_mask = GoBusy();
|
||||
hasData = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// count local elapsed time as we don't receive
|
||||
@@ -217,14 +218,6 @@ void Connection::UpdateStatus()
|
||||
{
|
||||
// sync local elapsed time counter with mpd
|
||||
itsElapsed = mpd_status_get_elapsed_time(itsCurrentStatus);
|
||||
// little hack as it seems mpd doesn't always return elapsed
|
||||
// time equal to 0 even if song has changed, it sometimes
|
||||
// returns the last second, so we need to bypass it by zeroing
|
||||
// it in this case.
|
||||
// NOTICE: it seems polling with select() instead of poll()
|
||||
// fixes this, but that can just be more randomness.
|
||||
//if (itsElapsed == mpd_status_get_total_time(itsCurrentStatus))
|
||||
// itsElapsed = 0;
|
||||
time(&itsElapsedTimer[0]);
|
||||
}
|
||||
else
|
||||
@@ -274,7 +267,12 @@ void Connection::UpdateStatus()
|
||||
itsChanges.StatusFlags = itsChanges.Repeat || itsChanges.Random || itsChanges.Single || itsChanges.Consume || itsChanges.Crossfade || itsChanges.DBUpdating;
|
||||
}
|
||||
itsUpdater(this, itsChanges, itsErrorHandlerUserdata);
|
||||
// below conditionals are a hack to workaround mpd bug 2608/2612
|
||||
// by fetching another status with correct values after a while
|
||||
if (!((idle_mask & MPD_IDLE_PLAYER) && !itsChanges.PlayerState))
|
||||
GoIdle();
|
||||
else if (supportsIdle && !isIdle)
|
||||
OrderDataFetching();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
13
src/mpdpp.h
13
src/mpdpp.h
@@ -21,12 +21,6 @@
|
||||
#ifndef _MPDPP_H
|
||||
#define _MPDPP_H
|
||||
|
||||
#ifdef WIN32
|
||||
# include <winsock.h>
|
||||
#else
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <mpd/client.h>
|
||||
@@ -98,7 +92,10 @@ namespace MPD
|
||||
int GetPort() { return itsPort; }
|
||||
|
||||
float Version() const;
|
||||
|
||||
bool SupportsIdle() const { return supportsIdle; }
|
||||
void OrderDataFetching() { hasData = 1; }
|
||||
int GetFD() const { return itsFD; }
|
||||
|
||||
void SetHostname(const std::string &);
|
||||
void SetPort(int port) { itsPort = port; }
|
||||
@@ -213,7 +210,7 @@ namespace MPD
|
||||
|
||||
private:
|
||||
void GoIdle();
|
||||
mpd_idle GoBusy();
|
||||
int GoBusy();
|
||||
|
||||
int CheckForErrors();
|
||||
|
||||
@@ -224,10 +221,10 @@ namespace MPD
|
||||
int itsErrorCode;
|
||||
size_t itsMaxPlaylistLength;
|
||||
|
||||
fd_set itsPoll;
|
||||
int itsFD;
|
||||
bool isIdle;
|
||||
bool supportsIdle;
|
||||
bool hasData;
|
||||
|
||||
std::string itsHost;
|
||||
int itsPort;
|
||||
|
||||
@@ -159,6 +159,7 @@ int main(int argc, char *argv[])
|
||||
wFooter = new Window(0, footer_start_y, COLS, footer_height, "", Config.statusbar_color, brNone);
|
||||
wFooter->SetTimeout(ncmpcpp_window_timeout);
|
||||
wFooter->SetGetStringHelper(StatusbarGetStringHelper);
|
||||
wFooter->AddFDCallback(Mpd.GetFD(), StatusbarMPDCallback);
|
||||
wFooter->CreateHistory();
|
||||
|
||||
myPlaylist->SwitchTo();
|
||||
@@ -201,10 +202,13 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
if (!Mpd.Connected())
|
||||
{
|
||||
if (!wFooter->FDCallbacksListEmpty())
|
||||
wFooter->ClearFDCallbacksList();
|
||||
ShowMessage("Attempting to reconnect...");
|
||||
if (Mpd.Connect())
|
||||
{
|
||||
ShowMessage("Connected to %s!", Mpd.GetHostname().c_str());
|
||||
wFooter->AddFDCallback(Mpd.GetFD(), StatusbarMPDCallback);
|
||||
MessagesAllowed = 0;
|
||||
UpdateStatusImmediately = 1;
|
||||
# ifdef ENABLE_OUTPUTS
|
||||
@@ -289,7 +293,7 @@ int main(int argc, char *argv[])
|
||||
myScreen->Update();
|
||||
if (input != ERR)
|
||||
myScreen->RefreshWindow();
|
||||
myScreen->ReadKey(input);
|
||||
wFooter->ReadKey(input);
|
||||
|
||||
if (input == ERR)
|
||||
continue;
|
||||
@@ -567,7 +571,7 @@ int main(int argc, char *argv[])
|
||||
else
|
||||
{
|
||||
Playlist::BlockNowPlayingUpdate = 1;
|
||||
myPlaylist->Items->SetTimeout(50);
|
||||
wFooter->SetTimeout(50);
|
||||
int del_counter = 0;
|
||||
while (!myPlaylist->Items->Empty() && Keypressed(input, Key.Delete))
|
||||
{
|
||||
@@ -581,11 +585,11 @@ int main(int argc, char *argv[])
|
||||
Mpd.DeleteID(myPlaylist->CurrentSong()->GetID());
|
||||
myPlaylist->Items->DeleteOption(id);
|
||||
myPlaylist->Items->Refresh();
|
||||
myPlaylist->Items->ReadKey(input);
|
||||
wFooter->ReadKey(input);
|
||||
++del_counter;
|
||||
}
|
||||
myPlaylist->FixPositions(myPlaylist->Items->Choice());
|
||||
myPlaylist->Items->SetTimeout(ncmpcpp_window_timeout);
|
||||
wFooter->SetTimeout(ncmpcpp_window_timeout);
|
||||
Playlist::BlockNowPlayingUpdate = 0;
|
||||
}
|
||||
}
|
||||
@@ -703,7 +707,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
else
|
||||
{
|
||||
myPlaylistEditor->Content->SetTimeout(50);
|
||||
wFooter->SetTimeout(50);
|
||||
locale_to_utf(myPlaylistEditor->Playlists->Current());
|
||||
while (!myPlaylistEditor->Content->Empty() && Keypressed(input, Key.Delete))
|
||||
{
|
||||
@@ -712,10 +716,10 @@ int main(int argc, char *argv[])
|
||||
Mpd.Delete(myPlaylistEditor->Playlists->Current(), myPlaylistEditor->Content->Choice());
|
||||
myPlaylistEditor->Content->DeleteOption(myPlaylistEditor->Content->Choice());
|
||||
myPlaylistEditor->Content->Refresh();
|
||||
myPlaylistEditor->Content->ReadKey(input);
|
||||
wFooter->ReadKey(input);
|
||||
}
|
||||
utf_to_locale(myPlaylistEditor->Playlists->Current());
|
||||
myPlaylistEditor->Content->SetTimeout(ncmpcpp_window_timeout);
|
||||
wFooter->SetTimeout(ncmpcpp_window_timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -808,7 +812,7 @@ int main(int argc, char *argv[])
|
||||
else if (myScreen == myPlaylist && !myPlaylist->Items->Empty())
|
||||
{
|
||||
CHECK_PLAYLIST_FOR_FILTERING;
|
||||
myPlaylist->Items->SetTimeout(50);
|
||||
wFooter->SetTimeout(50);
|
||||
if (myPlaylist->Items->hasSelected())
|
||||
{
|
||||
std::vector<size_t> list;
|
||||
@@ -848,7 +852,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
myPlaylist->Items->Highlight(list[(list.size()-1)/2]);
|
||||
myPlaylist->Items->Refresh();
|
||||
myPlaylist->Items->ReadKey(input);
|
||||
wFooter->ReadKey(input);
|
||||
}
|
||||
Playlist::BlockNowPlayingUpdate = 0;
|
||||
Mpd.StartCommandsList();
|
||||
@@ -876,17 +880,17 @@ int main(int argc, char *argv[])
|
||||
myPlaylist->Items->Swap(to, to+1);
|
||||
myPlaylist->Items->Scroll(wUp);
|
||||
myPlaylist->Items->Refresh();
|
||||
myPlaylist->Items->ReadKey(input);
|
||||
wFooter->ReadKey(input);
|
||||
}
|
||||
Mpd.Move(from, to);
|
||||
Playlist::BlockNowPlayingUpdate = 0;
|
||||
UpdateStatusImmediately = 1;
|
||||
}
|
||||
myPlaylist->Items->SetTimeout(ncmpcpp_window_timeout);
|
||||
wFooter->SetTimeout(ncmpcpp_window_timeout);
|
||||
}
|
||||
else if (myScreen->ActiveWindow() == myPlaylistEditor->Content && !myPlaylistEditor->Content->Empty())
|
||||
{
|
||||
myPlaylistEditor->Content->SetTimeout(50);
|
||||
wFooter->SetTimeout(50);
|
||||
if (myPlaylistEditor->Content->hasSelected())
|
||||
{
|
||||
std::vector<size_t> list;
|
||||
@@ -905,7 +909,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
myPlaylistEditor->Content->Highlight(list[(list.size()-1)/2]);
|
||||
myPlaylistEditor->Content->Refresh();
|
||||
myPlaylistEditor->Content->ReadKey(input);
|
||||
wFooter->ReadKey(input);
|
||||
}
|
||||
Mpd.StartCommandsList();
|
||||
for (size_t i = 0; i < list.size(); ++i)
|
||||
@@ -925,12 +929,12 @@ int main(int argc, char *argv[])
|
||||
myPlaylistEditor->Content->Swap(to, to+1);
|
||||
myPlaylistEditor->Content->Scroll(wUp);
|
||||
myPlaylistEditor->Content->Refresh();
|
||||
myPlaylistEditor->Content->ReadKey(input);
|
||||
wFooter->ReadKey(input);
|
||||
}
|
||||
if (from != to)
|
||||
Mpd.Move(myPlaylistEditor->Playlists->Current(), from, to);
|
||||
}
|
||||
myPlaylistEditor->Content->SetTimeout(ncmpcpp_window_timeout);
|
||||
wFooter->SetTimeout(ncmpcpp_window_timeout);
|
||||
}
|
||||
}
|
||||
else if (Keypressed(input, Key.MvSongDown))
|
||||
@@ -940,7 +944,7 @@ int main(int argc, char *argv[])
|
||||
else if (myScreen == myPlaylist && !myPlaylist->Items->Empty())
|
||||
{
|
||||
CHECK_PLAYLIST_FOR_FILTERING;
|
||||
myPlaylist->Items->SetTimeout(50);
|
||||
wFooter->SetTimeout(50);
|
||||
if (myPlaylist->Items->hasSelected())
|
||||
{
|
||||
std::vector<size_t> list;
|
||||
@@ -974,7 +978,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
myPlaylist->Items->Highlight(list[(list.size()-1)/2]);
|
||||
myPlaylist->Items->Refresh();
|
||||
myPlaylist->Items->ReadKey(input);
|
||||
wFooter->ReadKey(input);
|
||||
}
|
||||
Playlist::BlockNowPlayingUpdate = 0;
|
||||
Mpd.StartCommandsList();
|
||||
@@ -1002,18 +1006,18 @@ int main(int argc, char *argv[])
|
||||
myPlaylist->Items->Swap(to, to-1);
|
||||
myPlaylist->Items->Scroll(wDown);
|
||||
myPlaylist->Items->Refresh();
|
||||
myPlaylist->Items->ReadKey(input);
|
||||
wFooter->ReadKey(input);
|
||||
}
|
||||
Mpd.Move(from, to);
|
||||
Playlist::BlockNowPlayingUpdate = 0;
|
||||
UpdateStatusImmediately = 1;
|
||||
}
|
||||
myPlaylist->Items->SetTimeout(ncmpcpp_window_timeout);
|
||||
wFooter->SetTimeout(ncmpcpp_window_timeout);
|
||||
|
||||
}
|
||||
else if (myScreen->ActiveWindow() == myPlaylistEditor->Content && !myPlaylistEditor->Content->Empty())
|
||||
{
|
||||
myPlaylistEditor->Content->SetTimeout(50);
|
||||
wFooter->SetTimeout(50);
|
||||
if (myPlaylistEditor->Content->hasSelected())
|
||||
{
|
||||
std::vector<size_t> list;
|
||||
@@ -1032,7 +1036,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
myPlaylistEditor->Content->Highlight(list[(list.size()-1)/2]);
|
||||
myPlaylistEditor->Content->Refresh();
|
||||
myPlaylistEditor->Content->ReadKey(input);
|
||||
wFooter->ReadKey(input);
|
||||
}
|
||||
Mpd.StartCommandsList();
|
||||
for (int i = list.size()-1; i >= 0; --i)
|
||||
@@ -1052,12 +1056,12 @@ int main(int argc, char *argv[])
|
||||
myPlaylistEditor->Content->Swap(to, to-1);
|
||||
myPlaylistEditor->Content->Scroll(wDown);
|
||||
myPlaylistEditor->Content->Refresh();
|
||||
myPlaylistEditor->Content->ReadKey(input);
|
||||
wFooter->ReadKey(input);
|
||||
}
|
||||
if (from != to)
|
||||
Mpd.Move(myPlaylistEditor->Playlists->Current(), from, to);
|
||||
}
|
||||
myPlaylistEditor->Content->SetTimeout(ncmpcpp_window_timeout);
|
||||
wFooter->SetTimeout(ncmpcpp_window_timeout);
|
||||
}
|
||||
}
|
||||
else if (Keypressed(input, Key.MoveTo) && myScreen == myPlaylist)
|
||||
@@ -1148,7 +1152,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
TraceMpdStatus();
|
||||
myPlaylist->UpdateTimer();
|
||||
myPlaylist->Items->ReadKey(input);
|
||||
wFooter->ReadKey(input);
|
||||
|
||||
int howmuch = Config.incremental_seeking ? (myPlaylist->Timer()-t)/2+Config.seek_time : Config.seek_time;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ using namespace NCurses;
|
||||
|
||||
typedef std::pair<std::string, std::string> string_pair;
|
||||
|
||||
const int ncmpcpp_window_timeout = 100;
|
||||
const int ncmpcpp_window_timeout = 500;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ Outputs *myOutputs = new Outputs;
|
||||
void Outputs::Init()
|
||||
{
|
||||
w = new Menu<MPD::Output>(0, MainStartY, COLS, MainHeight, "", Config.main_color, brNone);
|
||||
w->SetTimeout(ncmpcpp_window_timeout);
|
||||
w->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
w->HighlightColor(Config.main_highlight_color);
|
||||
w->SetItemDisplayer(Display::Pairs);
|
||||
|
||||
@@ -47,7 +47,6 @@ Menu< std::pair<std::string, MPD::Song::GetFunction> > *Playlist::SortDialog = 0
|
||||
void Playlist::Init()
|
||||
{
|
||||
Items = new Menu<MPD::Song>(0, MainStartY, COLS, MainHeight, Config.columns_in_playlist ? Display::Columns() : "", Config.main_color, brNone);
|
||||
Items->SetTimeout(ncmpcpp_window_timeout);
|
||||
Items->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
Items->HighlightColor(Config.main_highlight_color);
|
||||
Items->SetSelectPrefix(&Config.selected_item_prefix);
|
||||
@@ -62,7 +61,6 @@ void Playlist::Init()
|
||||
SortDialogHeight = std::min(int(MainHeight), 18);
|
||||
|
||||
SortDialog = new Menu< std::pair<std::string, MPD::Song::GetFunction> >((COLS-SortDialogWidth)/2, (MainHeight-SortDialogHeight)/2+MainStartY, SortDialogWidth, SortDialogHeight, "Sort songs by...", Config.main_color, Config.window_border);
|
||||
SortDialog->SetTimeout(ncmpcpp_window_timeout);
|
||||
SortDialog->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
SortDialog->SetItemDisplayer(Display::Pairs);
|
||||
|
||||
|
||||
@@ -47,13 +47,11 @@ void PlaylistEditor::Init()
|
||||
|
||||
Playlists = new Menu<std::string>(0, MainStartY, LeftColumnWidth, MainHeight, "Playlists", Config.main_color, brNone);
|
||||
Playlists->HighlightColor(Config.active_column_color);
|
||||
Playlists->SetTimeout(ncmpcpp_window_timeout);
|
||||
Playlists->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
Playlists->SetItemDisplayer(Display::Generic);
|
||||
|
||||
Content = new Menu<Song>(RightColumnStartX, MainStartY, RightColumnWidth, MainHeight, "Playlist's content", Config.main_color, brNone);
|
||||
Content->HighlightColor(Config.main_highlight_color);
|
||||
Content->SetTimeout(ncmpcpp_window_timeout);
|
||||
Content->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
Content->SetSelectPrefix(&Config.selected_item_prefix);
|
||||
Content->SetSelectSuffix(&Config.selected_item_suffix);
|
||||
|
||||
@@ -61,7 +61,6 @@ void SearchEngine::Init()
|
||||
{
|
||||
w = new Menu< std::pair<Buffer *, Song *> >(0, MainStartY, COLS, MainHeight, "", Config.main_color, brNone);
|
||||
w->HighlightColor(Config.main_highlight_color);
|
||||
w->SetTimeout(ncmpcpp_window_timeout);
|
||||
w->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
w->SetItemDisplayer(Display::SearchEngine);
|
||||
w->SetSelectPrefix(&Config.selected_item_prefix);
|
||||
|
||||
@@ -34,7 +34,6 @@ void ServerInfo::Init()
|
||||
{
|
||||
SetDimensions();
|
||||
w = new Scrollpad((COLS-itsWidth)/2, (MainHeight-itsHeight)/2+MainStartY, itsWidth, itsHeight, "MPD server info", Config.main_color, Config.window_border);
|
||||
w->SetTimeout(ncmpcpp_window_timeout);
|
||||
|
||||
Mpd.GetURLHandlers(itsURLHandlers);
|
||||
Mpd.GetTagTypes(itsTagTypes);
|
||||
|
||||
@@ -63,6 +63,11 @@ void WindowTitle(const std::string &status)
|
||||
}
|
||||
#endif // !USE_PDCURSES
|
||||
|
||||
void StatusbarMPDCallback()
|
||||
{
|
||||
Mpd.OrderDataFetching();
|
||||
}
|
||||
|
||||
void StatusbarGetStringHelper(const std::wstring &)
|
||||
{
|
||||
TraceMpdStatus();
|
||||
|
||||
@@ -44,6 +44,7 @@ Window &Statusbar();
|
||||
void DrawProgressbar(unsigned elapsed, unsigned time);
|
||||
void ShowMessage(const char *, ...) GNUC_PRINTF(1, 2);
|
||||
|
||||
void StatusbarMPDCallback();
|
||||
void StatusbarGetStringHelper(const std::wstring &);
|
||||
void StatusbarApplyFilterImmediately(const std::wstring &);
|
||||
|
||||
|
||||
@@ -68,14 +68,12 @@ void TagEditor::Init()
|
||||
|
||||
Albums = new Menu<string_pair>(0, MainStartY, LeftColumnWidth, MainHeight, "Albums", Config.main_color, brNone);
|
||||
Albums->HighlightColor(Config.active_column_color);
|
||||
Albums->SetTimeout(ncmpcpp_window_timeout);
|
||||
Albums->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
Albums->SetItemDisplayer(Display::Pairs);
|
||||
Albums->SetGetStringFunction(StringPairToString);
|
||||
|
||||
Dirs = new Menu<string_pair>(0, MainStartY, LeftColumnWidth, MainHeight, "Directories", Config.main_color, brNone);
|
||||
Dirs->HighlightColor(Config.active_column_color);
|
||||
Dirs->SetTimeout(ncmpcpp_window_timeout);
|
||||
Dirs->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
Dirs->SetItemDisplayer(Display::Pairs);
|
||||
Dirs->SetGetStringFunction(StringPairToString);
|
||||
@@ -84,7 +82,6 @@ void TagEditor::Init()
|
||||
|
||||
TagTypes = new Menu<std::string>(MiddleColumnStartX, MainStartY, MiddleColumnWidth, MainHeight, "Tag types", Config.main_color, brNone);
|
||||
TagTypes->HighlightColor(Config.main_highlight_color);
|
||||
TagTypes->SetTimeout(ncmpcpp_window_timeout);
|
||||
TagTypes->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
TagTypes->SetItemDisplayer(Display::Generic);
|
||||
|
||||
@@ -111,7 +108,6 @@ void TagEditor::Init()
|
||||
|
||||
Tags = new Menu<MPD::Song>(RightColumnStartX, MainStartY, RightColumnWidth, MainHeight, "Tags", Config.main_color, brNone);
|
||||
Tags->HighlightColor(Config.main_highlight_color);
|
||||
Tags->SetTimeout(ncmpcpp_window_timeout);
|
||||
Tags->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
Tags->SetSelectPrefix(&Config.selected_item_prefix);
|
||||
Tags->SetSelectSuffix(&Config.selected_item_suffix);
|
||||
@@ -121,7 +117,6 @@ void TagEditor::Init()
|
||||
Tags->SetGetStringFunctionUserData(TagTypes);
|
||||
|
||||
FParserDialog = new Menu<std::string>((COLS-FParserDialogWidth)/2, (MainHeight-FParserDialogHeight)/2+MainStartY, FParserDialogWidth, FParserDialogHeight, "", Config.main_color, Config.window_border);
|
||||
FParserDialog->SetTimeout(ncmpcpp_window_timeout);
|
||||
FParserDialog->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
FParserDialog->SetItemDisplayer(Display::Generic);
|
||||
FParserDialog->AddOption("Get tags from filename");
|
||||
@@ -130,15 +125,12 @@ void TagEditor::Init()
|
||||
FParserDialog->AddOption("Cancel");
|
||||
|
||||
FParser = new Menu<std::string>((COLS-FParserWidth)/2, (MainHeight-FParserHeight)/2+MainStartY, FParserWidthOne, FParserHeight, "_", Config.main_color, Config.active_window_border);
|
||||
FParser->SetTimeout(ncmpcpp_window_timeout);
|
||||
FParser->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
FParser->SetItemDisplayer(Display::Generic);
|
||||
|
||||
FParserLegend = new Scrollpad((COLS-FParserWidth)/2+FParserWidthOne, (MainHeight-FParserHeight)/2+MainStartY, FParserWidthTwo, FParserHeight, "Legend", Config.main_color, Config.window_border);
|
||||
FParserLegend->SetTimeout(ncmpcpp_window_timeout);
|
||||
|
||||
FParserPreview = new Scrollpad((COLS-FParserWidth)/2+FParserWidthOne, (MainHeight-FParserHeight)/2+MainStartY, FParserWidthTwo, FParserHeight, "Preview", Config.main_color, Config.window_border);
|
||||
FParserPreview->SetTimeout(ncmpcpp_window_timeout);
|
||||
|
||||
w = LeftColumn;
|
||||
isInitialized = 1;
|
||||
|
||||
@@ -48,7 +48,6 @@ void TinyTagEditor::Init()
|
||||
{
|
||||
w = new Menu<Buffer>(0, MainStartY, COLS, MainHeight, "", Config.main_color, brNone);
|
||||
w->HighlightColor(Config.main_highlight_color);
|
||||
w->SetTimeout(ncmpcpp_window_timeout);
|
||||
w->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
w->SetItemDisplayer(Display::Generic);
|
||||
isInitialized = 1;
|
||||
|
||||
@@ -21,6 +21,12 @@
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
#ifdef WIN32
|
||||
# include <winsock.h>
|
||||
#else
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#include "error.h"
|
||||
#include "window.h"
|
||||
|
||||
@@ -352,9 +358,63 @@ void Window::SetTimeout(int timeout)
|
||||
wtimeout(itsWindow, timeout);
|
||||
}
|
||||
|
||||
void Window::AddFDCallback(int fd, void (*callback)())
|
||||
{
|
||||
itsFDs.push_back(std::make_pair(fd, callback));
|
||||
}
|
||||
|
||||
void Window::ClearFDCallbacksList()
|
||||
{
|
||||
itsFDs.clear();
|
||||
}
|
||||
|
||||
bool Window::FDCallbacksListEmpty() const
|
||||
{
|
||||
return itsFDs.empty();
|
||||
}
|
||||
|
||||
void Window::ReadKey(int &read_key) const
|
||||
{
|
||||
// in pdcurses polling stdin doesn't work, so we can't poll
|
||||
// both stdin and other file descriptors in one select. the
|
||||
// workaround is to set the timeout of select to 0, poll
|
||||
// other file descriptors and then wait for stdin input with
|
||||
// the given timeout. unfortunately, this results in delays
|
||||
// since ncmpcpp doesn't see that data arrived while waiting
|
||||
// for input from stdin, but it seems there is no better option.
|
||||
|
||||
fd_set fdset;
|
||||
FD_ZERO(&fdset);
|
||||
# if !defined(USE_PDCURSES)
|
||||
FD_SET(STDIN_FILENO, &fdset);
|
||||
timeval timeout = { itsWindowTimeout/1000, (itsWindowTimeout%1000)*1000 };
|
||||
# else
|
||||
timeval timeout = { 0, 0 };
|
||||
# endif
|
||||
|
||||
int fd_max = STDIN_FILENO;
|
||||
for (FDCallbacks::const_iterator it = itsFDs.begin(); it != itsFDs.end(); ++it)
|
||||
{
|
||||
if (it->first > fd_max)
|
||||
fd_max = it->first;
|
||||
FD_SET(it->first, &fdset);
|
||||
}
|
||||
|
||||
if (select(fd_max+1, &fdset, 0, 0, &timeout) > 0)
|
||||
{
|
||||
# if !defined(USE_PDCURSES)
|
||||
read_key = FD_ISSET(STDIN_FILENO, &fdset) ? wgetch(itsWindow) : ERR;
|
||||
# endif // !USE_PDCURSES
|
||||
for (FDCallbacks::const_iterator it = itsFDs.begin(); it != itsFDs.end(); ++it)
|
||||
if (FD_ISSET(it->first, &fdset))
|
||||
it->second();
|
||||
}
|
||||
# if !defined(USE_PDCURSES)
|
||||
else
|
||||
read_key = ERR;
|
||||
# else
|
||||
read_key = wgetch(itsWindow);
|
||||
# endif
|
||||
}
|
||||
|
||||
void Window::ReadKey() const
|
||||
@@ -437,7 +497,7 @@ std::string Window::GetString(const std::string &base, size_t length, size_t wid
|
||||
|
||||
wmove(itsWindow, y, x);
|
||||
prefresh(itsWindow, 0, 0, itsStartY, itsStartX, itsStartY+itsHeight-1, itsStartX+itsWidth-1);
|
||||
input = wgetch(itsWindow);
|
||||
ReadKey(input);
|
||||
|
||||
// these key codes are special and should be ignored
|
||||
if ((input < 10 || (input > 10 && input != 21 && input < 32))
|
||||
|
||||
23
src/window.h
23
src/window.h
@@ -343,6 +343,23 @@ namespace NCurses
|
||||
///
|
||||
virtual void Clear(bool refresh = 1);
|
||||
|
||||
/// Adds given file descriptor to the list that will be polled in
|
||||
/// ReadKey() along with stdin and callback that will be invoked
|
||||
/// when there is data waiting for reading in it
|
||||
/// @param fd file descriptor
|
||||
/// @param callback callback
|
||||
///
|
||||
void AddFDCallback(int fd, void (*callback)());
|
||||
|
||||
/// Clears list of file descriptors and their callbacks
|
||||
///
|
||||
void ClearFDCallbacksList();
|
||||
|
||||
/// Checks if list of file descriptors is empty
|
||||
/// @return true if list is empty, false otherwise
|
||||
///
|
||||
bool FDCallbacksListEmpty() const;
|
||||
|
||||
/// Reads key from standard input and writes it into read_key variable
|
||||
/// @param read_key variable for read key to be written into it
|
||||
///
|
||||
@@ -553,6 +570,12 @@ namespace NCurses
|
||||
/// stack of colors
|
||||
std::stack<Colors> itsColors;
|
||||
|
||||
/// containter used for additional file descriptors that have
|
||||
/// to be polled in ReadKey() and correspondent callbacks that
|
||||
/// are invoked if there is data available in them
|
||||
typedef std::vector< std::pair<int, void (*)()> > FDCallbacks;
|
||||
FDCallbacks itsFDs;
|
||||
|
||||
/// pointer to container used as history
|
||||
std::deque<std::wstring> *itsHistory;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user