From 55ae5b18163c5cc6b14eb5815db9bbda4ac330dc Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Sat, 25 Aug 2012 04:44:02 +0200 Subject: [PATCH] initial support for binding keys to action chains --- configure.in | 17 ++- src/actions.cpp | 4 +- src/help.cpp | 4 +- src/ncmpcpp.cpp | 16 ++- src/settings.cpp | 266 +++++++++++++++++++++++------------------------ src/settings.h | 32 +++++- 6 files changed, 194 insertions(+), 145 deletions(-) diff --git a/configure.in b/configure.in index 83f169fb..fc6e5228 100644 --- a/configure.in +++ b/configure.in @@ -35,12 +35,25 @@ old_CXXFLAGS="$CXXFLAGS" CXXFLAGS="-fno-exceptions" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]])], AC_MSG_RESULT([yes]) - no_exceptions="-fno-exceptions" - , + no_exceptions="-fno-exceptions", AC_MSG_RESULT([no]) ) CXXFLAGS="$old_CXXFLAGS $no_exceptions" +dnl ================================ +dnl = checking for -std=c++0x flag = +dnl ================================ +AC_MSG_CHECKING([whether compiler supports -std=c++0x]) +old_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="-std=c++0x" +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]])], + AC_MSG_RESULT([yes]) + std_cpp0x="-std=c++0x", + AC_MSG_RESULT([no]) + AC_MSG_ERROR([[Your compiler doesn't seem to support C++0x, please upgrade (GCC >= 4.4)]]) +) +CXXFLAGS="$old_CXXFLAGS $std_cpp0x" + dnl ============================== dnl = checking for regex (win32) = dnl ============================== diff --git a/src/actions.cpp b/src/actions.cpp index 67cef72c..a6267908 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -261,9 +261,9 @@ void Action::Seek() Key input = ReadKey(*wFooter); KeyConfiguration::Binding k = Keys.Bindings.equal_range(input); // no action? - if (k.first == k.second) + if (k.first == k.second || !k.first->second.isSingle()) break; - Action *a = k.first->second; + Action *a = k.first->second.getAction(); if (dynamic_cast(a)) { if (songpos < Mpd.GetTotalTime()) diff --git a/src/help.cpp b/src/help.cpp index ae274652..a6e9e6c9 100644 --- a/src/help.cpp +++ b/src/help.cpp @@ -80,9 +80,9 @@ std::string Help::DisplayKeys(const ActionType at) { bool print_backspace = true; std::string result; - for (std::multimap::const_iterator it = Keys.Bindings.begin(); it != Keys.Bindings.end(); ++it) + for (std::multimap::const_iterator it = Keys.Bindings.begin(); it != Keys.Bindings.end(); ++it) { - if (it->second->Type() == at) + if (it->second.isSingle() && it->second.getAction()->Type() == at) { result += IntoStr(it->first, &print_backspace); result += " "; diff --git a/src/ncmpcpp.cpp b/src/ncmpcpp.cpp index b7b0a3e5..f2e936b1 100644 --- a/src/ncmpcpp.cpp +++ b/src/ncmpcpp.cpp @@ -271,8 +271,22 @@ int main(int argc, char **argv) KeyConfiguration::Binding k = Keys.Bindings.equal_range(input); for (; k.first != k.second; ++k.first) - if (k.first->second->Execute()) + { + Bind &b = k.first->second; + if (b.isSingle()) + { + if (b.getAction()->Execute()) + break; + } + else + { + Bind::ActionChain *chain = b.getChain(); + for (Bind::ActionChain::iterator it = chain->begin(); it != chain->end(); ++it) + if (!(*it)->Execute()) + break; break; + } + } if (myScreen == myPlaylist) myPlaylist->EnableHighlighting(); diff --git a/src/settings.cpp b/src/settings.cpp index b0dceea7..a2fb2fd4 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -133,142 +133,138 @@ void CreateDir(const std::string &dir) void KeyConfiguration::GenerateBindings() { -# define BIND(key, type, action) Bindings.insert(std::make_pair(Action::Key(key, type), Action::Get(action))) + Bind_(KEY_MOUSE, ctNCurses, aMouseEvent); + Bind_(KEY_UP, ctNCurses, aScrollUp); + Bind_(KEY_DOWN, ctNCurses, aScrollDown); + Bind_('[', ctStandard, aScrollUpAlbum); + Bind_(']', ctStandard, aScrollDownAlbum); + Bind_('{', ctStandard, aScrollUpArtist); + Bind_('}', ctStandard, aScrollDownArtist); + Bind_(KEY_PPAGE, ctNCurses, aPageUp); + Bind_(KEY_NPAGE, ctNCurses, aPageDown); + Bind_(KEY_HOME, ctNCurses, aMoveHome); + Bind_(KEY_END, ctNCurses, aMoveEnd); + Bind_(KEY_SPACE, ctStandard, aPressSpace); + Bind_(KEY_ENTER, ctStandard, aPressEnter); + Bind_(KEY_DC, ctNCurses, aDelete); + Bind_(KEY_RIGHT, ctNCurses, aNextColumn); + Bind_(KEY_RIGHT, ctNCurses, aSlaveScreen); + Bind_(KEY_RIGHT, ctNCurses, aVolumeUp); + Bind_(KEY_LEFT, ctNCurses, aPreviousColumn); + Bind_(KEY_LEFT, ctNCurses, aMasterScreen); + Bind_(KEY_LEFT, ctNCurses, aVolumeDown); + Bind_(KEY_TAB, ctStandard, aNextScreen); + Bind_(KEY_SHIFT_TAB, ctNCurses, aPreviousScreen); + Bind_('1', ctStandard, aShowHelp); + Bind_('2', ctStandard, aShowPlaylist); + Bind_('3', ctStandard, aShowBrowser); + Bind_('4', ctStandard, aShowSearchEngine); + Bind_('5', ctStandard, aShowMediaLibrary); + Bind_('6', ctStandard, aShowPlaylistEditor); + Bind_('7', ctStandard, aShowTagEditor); + Bind_('8', ctStandard, aShowOutputs); + Bind_('9', ctStandard, aShowVisualizer); + Bind_('0', ctStandard, aShowClock); + Bind_('@', ctStandard, aShowServerInfo); + Bind_('s', ctStandard, aStop); + Bind_('P', ctStandard, aPause); + Bind_('>', ctStandard, aNextSong); + Bind_('<', ctStandard, aPreviousSong); + Bind_(KEY_CTRL_H, ctStandard, aJumpToParentDir); + Bind_(KEY_CTRL_H, ctStandard, aReplaySong); + Bind_(KEY_BACKSPACE, ctNCurses, aJumpToParentDir); + Bind_(KEY_BACKSPACE, ctNCurses, aReplaySong); + Bind_(KEY_BACKSPACE_2, ctStandard, aJumpToParentDir); + Bind_(KEY_BACKSPACE_2, ctStandard, aReplaySong); + Bind_('f', ctStandard, aSeekForward); + Bind_('b', ctStandard, aSeekBackward); + Bind_('r', ctStandard, aToggleRepeat); + Bind_('z', ctStandard, aToggleRandom); + Bind_('y', ctStandard, aSaveTagChanges); + Bind_('y', ctStandard, aStartSearching); + Bind_('y', ctStandard, aToggleSingle); + Bind_('R', ctStandard, aToggleConsume); + Bind_('Y', ctStandard, aToggleReplayGainMode); + Bind_('t', ctStandard, aToggleSpaceMode); + Bind_('T', ctStandard, aToggleAddMode); + Bind_('|', ctStandard, aToggleMouse); + Bind_('#', ctStandard, aToggleBitrateVisibility); + Bind_('Z', ctStandard, aShuffle); + Bind_('x', ctStandard, aToggleCrossfade); + Bind_('X', ctStandard, aSetCrossfade); + Bind_('u', ctStandard, aUpdateDatabase); + Bind_(KEY_CTRL_V, ctStandard, aSortPlaylist); + Bind_(KEY_CTRL_R, ctStandard, aReversePlaylist); + Bind_(KEY_CTRL_F, ctStandard, aApplyFilter); + Bind_(KEY_CTRL_G, ctStandard, aDisableFilter); + Bind_('/', ctStandard, aFind); + Bind_('/', ctStandard, aFindItemForward); + Bind_('?', ctStandard, aFind); + Bind_('?', ctStandard, aFindItemBackward); + Bind_('.', ctStandard, aNextFoundItem); + Bind_(',', ctStandard, aPreviousFoundItem); + Bind_('w', ctStandard, aToggleFindMode); + Bind_('e', ctStandard, aEditSong); + Bind_('e', ctStandard, aEditLibraryTag); + Bind_('e', ctStandard, aEditLibraryAlbum); + Bind_('e', ctStandard, aEditDirectoryName); + Bind_('e', ctStandard, aEditPlaylistName); + Bind_('e', ctStandard, aEditLyrics); + Bind_('i', ctStandard, aShowSongInfo); + Bind_('I', ctStandard, aShowArtistInfo); + Bind_('g', ctStandard, aJumpToPositionInSong); + Bind_('l', ctStandard, aShowLyrics); + Bind_('v', ctStandard, aReverseSelection); + Bind_('V', ctStandard, aDeselectItems); + Bind_('B', ctStandard, aSelectAlbum); + Bind_('a', ctStandard, aAddSelectedItems); + Bind_('c', ctStandard, aClearPlaylist); + Bind_('c', ctStandard, aClearMainPlaylist); + Bind_('C', ctStandard, aCropPlaylist); + Bind_('C', ctStandard, aCropMainPlaylist); + Bind_('m', ctStandard, aMoveSortOrderUp); + Bind_('m', ctStandard, aMoveSelectedItemsUp); + Bind_('n', ctStandard, aMoveSortOrderDown); + Bind_('n', ctStandard, aMoveSelectedItemsDown); + Bind_('M', ctStandard, aMoveSelectedItemsTo); + Bind_('A', ctStandard, aAdd); + Bind_('S', ctStandard, aSavePlaylist); + Bind_('o', ctStandard, aJumpToPlayingSong); + Bind_('G', ctStandard, aJumpToBrowser); + Bind_('G', ctStandard, aJumpToPlaylistEditor); + Bind_('~', ctStandard, aJumpToMediaLibrary); + Bind_('E', ctStandard, aJumpToTagEditor); + Bind_('U', ctStandard, aToggleAutoCenter); + Bind_('p', ctStandard, aToggleDisplayMode); + Bind_('\\', ctStandard, aToggleInterface); + Bind_('!', ctStandard, aToggleSeparatorsInPlaylist); + Bind_('L', ctStandard, aToggleLyricsFetcher); + Bind_('F', ctStandard, aToggleFetchingLyricsInBackground); + Bind_(KEY_CTRL_L, ctStandard, aToggleScreenLock); + Bind_('`', ctStandard, aToggleBrowserSortMode); + Bind_('`', ctStandard, aToggleLibraryTagType); + Bind_('`', ctStandard, aRefetchLyrics); + Bind_('`', ctStandard, aRefetchArtistInfo); + Bind_('`', ctStandard, aAddRandomItems); + Bind_(KEY_CTRL_P, ctStandard, aSetSelectedItemsPriority); + Bind_('q', ctStandard, aQuit); - BIND(KEY_MOUSE, ctNCurses, aMouseEvent); - BIND(KEY_UP, ctNCurses, aScrollUp); - BIND(KEY_DOWN, ctNCurses, aScrollDown); - BIND('[', ctStandard, aScrollUpAlbum); - BIND(']', ctStandard, aScrollDownAlbum); - BIND('{', ctStandard, aScrollUpArtist); - BIND('}', ctStandard, aScrollDownArtist); - BIND(KEY_PPAGE, ctNCurses, aPageUp); - BIND(KEY_NPAGE, ctNCurses, aPageDown); - BIND(KEY_HOME, ctNCurses, aMoveHome); - BIND(KEY_END, ctNCurses, aMoveEnd); - BIND(KEY_SPACE, ctStandard, aPressSpace); - BIND(KEY_ENTER, ctStandard, aPressEnter); - BIND(KEY_DC, ctNCurses, aDelete); - BIND(KEY_RIGHT, ctNCurses, aNextColumn); - BIND(KEY_RIGHT, ctNCurses, aSlaveScreen); - BIND(KEY_RIGHT, ctNCurses, aVolumeUp); - BIND(KEY_LEFT, ctNCurses, aPreviousColumn); - BIND(KEY_LEFT, ctNCurses, aMasterScreen); - BIND(KEY_LEFT, ctNCurses, aVolumeDown); - BIND(KEY_TAB, ctStandard, aNextScreen); - BIND(KEY_SHIFT_TAB, ctNCurses, aPreviousScreen); - BIND('1', ctStandard, aShowHelp); - BIND('2', ctStandard, aShowPlaylist); - BIND('3', ctStandard, aShowBrowser); - BIND('4', ctStandard, aShowSearchEngine); - BIND('5', ctStandard, aShowMediaLibrary); - BIND('6', ctStandard, aShowPlaylistEditor); - BIND('7', ctStandard, aShowTagEditor); - BIND('8', ctStandard, aShowOutputs); - BIND('9', ctStandard, aShowVisualizer); - BIND('0', ctStandard, aShowClock); - BIND('@', ctStandard, aShowServerInfo); - BIND('s', ctStandard, aStop); - BIND('P', ctStandard, aPause); - BIND('>', ctStandard, aNextSong); - BIND('<', ctStandard, aPreviousSong); - BIND(KEY_CTRL_H, ctStandard, aJumpToParentDir); - BIND(KEY_CTRL_H, ctStandard, aReplaySong); - BIND(KEY_BACKSPACE, ctNCurses, aJumpToParentDir); - BIND(KEY_BACKSPACE, ctNCurses, aReplaySong); - BIND(KEY_BACKSPACE_2, ctStandard, aJumpToParentDir); - BIND(KEY_BACKSPACE_2, ctStandard, aReplaySong); - BIND('f', ctStandard, aSeekForward); - BIND('b', ctStandard, aSeekBackward); - BIND('r', ctStandard, aToggleRepeat); - BIND('z', ctStandard, aToggleRandom); - BIND('y', ctStandard, aSaveTagChanges); - BIND('y', ctStandard, aStartSearching); - BIND('y', ctStandard, aToggleSingle); - BIND('R', ctStandard, aToggleConsume); - BIND('Y', ctStandard, aToggleReplayGainMode); - BIND('t', ctStandard, aToggleSpaceMode); - BIND('T', ctStandard, aToggleAddMode); - BIND('|', ctStandard, aToggleMouse); - BIND('#', ctStandard, aToggleBitrateVisibility); - BIND('Z', ctStandard, aShuffle); - BIND('x', ctStandard, aToggleCrossfade); - BIND('X', ctStandard, aSetCrossfade); - BIND('u', ctStandard, aUpdateDatabase); - BIND(KEY_CTRL_V, ctStandard, aSortPlaylist); - BIND(KEY_CTRL_R, ctStandard, aReversePlaylist); - BIND(KEY_CTRL_F, ctStandard, aApplyFilter); - BIND(KEY_CTRL_G, ctStandard, aDisableFilter); - BIND('/', ctStandard, aFind); - BIND('/', ctStandard, aFindItemForward); - BIND('?', ctStandard, aFind); - BIND('?', ctStandard, aFindItemBackward); - BIND('.', ctStandard, aNextFoundItem); - BIND(',', ctStandard, aPreviousFoundItem); - BIND('w', ctStandard, aToggleFindMode); - BIND('e', ctStandard, aEditSong); - BIND('e', ctStandard, aEditLibraryTag); - BIND('e', ctStandard, aEditLibraryAlbum); - BIND('e', ctStandard, aEditDirectoryName); - BIND('e', ctStandard, aEditPlaylistName); - BIND('e', ctStandard, aEditLyrics); - BIND('i', ctStandard, aShowSongInfo); - BIND('I', ctStandard, aShowArtistInfo); - BIND('g', ctStandard, aJumpToPositionInSong); - BIND('l', ctStandard, aShowLyrics); - BIND('v', ctStandard, aReverseSelection); - BIND('V', ctStandard, aDeselectItems); - BIND('B', ctStandard, aSelectAlbum); - BIND('a', ctStandard, aAddSelectedItems); - BIND('c', ctStandard, aClearPlaylist); - BIND('c', ctStandard, aClearMainPlaylist); - BIND('C', ctStandard, aCropPlaylist); - BIND('C', ctStandard, aCropMainPlaylist); - BIND('m', ctStandard, aMoveSortOrderUp); - BIND('m', ctStandard, aMoveSelectedItemsUp); - BIND('n', ctStandard, aMoveSortOrderDown); - BIND('n', ctStandard, aMoveSelectedItemsDown); - BIND('M', ctStandard, aMoveSelectedItemsTo); - BIND('A', ctStandard, aAdd); - BIND('S', ctStandard, aSavePlaylist); - BIND('o', ctStandard, aJumpToPlayingSong); - BIND('G', ctStandard, aJumpToBrowser); - BIND('G', ctStandard, aJumpToPlaylistEditor); - BIND('~', ctStandard, aJumpToMediaLibrary); - BIND('E', ctStandard, aJumpToTagEditor); - BIND('U', ctStandard, aToggleAutoCenter); - BIND('p', ctStandard, aToggleDisplayMode); - BIND('\\', ctStandard, aToggleInterface); - BIND('!', ctStandard, aToggleSeparatorsInPlaylist); - BIND('L', ctStandard, aToggleLyricsFetcher); - BIND('F', ctStandard, aToggleFetchingLyricsInBackground); - BIND(KEY_CTRL_L, ctStandard, aToggleScreenLock); - BIND('`', ctStandard, aToggleBrowserSortMode); - BIND('`', ctStandard, aToggleLibraryTagType); - BIND('`', ctStandard, aRefetchLyrics); - BIND('`', ctStandard, aRefetchArtistInfo); - BIND('`', ctStandard, aAddRandomItems); - BIND(KEY_CTRL_P, ctStandard, aSetSelectedItemsPriority); - BIND('q', ctStandard, aQuit); - - BIND('k', ctStandard, aScrollUp); - BIND('j', ctStandard, aScrollDown); - BIND('d', ctStandard, aDelete); - BIND('+', ctStandard, aVolumeUp); - BIND('-', ctStandard, aVolumeDown); - BIND(KEY_F1, ctNCurses, aShowHelp); - BIND(KEY_F2, ctNCurses, aShowPlaylist); - BIND(KEY_F3, ctNCurses, aShowBrowser); - BIND(KEY_F4, ctNCurses, aShowSearchEngine); - BIND(KEY_F5, ctNCurses, aShowMediaLibrary); - BIND(KEY_F6, ctNCurses, aShowPlaylistEditor); - BIND(KEY_F7, ctNCurses, aShowTagEditor); - BIND(KEY_F8, ctNCurses, aShowOutputs); - BIND(KEY_F9, ctNCurses, aShowVisualizer); - BIND(KEY_F10, ctNCurses, aShowClock); - BIND('Q', ctStandard, aQuit); - -# undef BIND + Bind_('k', ctStandard, aScrollUp); + Bind_('j', ctStandard, aScrollDown); + Bind_('d', ctStandard, aDelete); + Bind_('+', ctStandard, aVolumeUp); + Bind_('-', ctStandard, aVolumeDown); + Bind_(KEY_F1, ctNCurses, aShowHelp); + Bind_(KEY_F2, ctNCurses, aShowPlaylist); + Bind_(KEY_F3, ctNCurses, aShowBrowser); + Bind_(KEY_F4, ctNCurses, aShowSearchEngine); + Bind_(KEY_F5, ctNCurses, aShowMediaLibrary); + Bind_(KEY_F6, ctNCurses, aShowPlaylistEditor); + Bind_(KEY_F7, ctNCurses, aShowTagEditor); + Bind_(KEY_F8, ctNCurses, aShowOutputs); + Bind_(KEY_F9, ctNCurses, aShowVisualizer); + Bind_(KEY_F10, ctNCurses, aShowClock); + Bind_('Q', ctStandard, aQuit); } void Configuration::SetDefaults() diff --git a/src/settings.h b/src/settings.h index 1ad7a585..0f9aaf80 100644 --- a/src/settings.h +++ b/src/settings.h @@ -21,6 +21,7 @@ #ifndef _SETTINGS_H #define _SETTINGS_H +#include #include #include @@ -45,16 +46,41 @@ struct Column bool display_empty_tag; }; +struct Bind +{ + typedef std::vector ActionChain; + + Bind(ActionType at) : isThisSingle(true), itsAction(Action::Get(at)) { } + Bind(ActionChain *chain) : isThisSingle(false), itsChain(chain) { } + + bool isSingle() const { return isThisSingle; } + ActionChain *getChain() const { assert(!isThisSingle); return itsChain; } + Action *getAction() const { assert(isThisSingle); return itsAction; } + + private: + bool isThisSingle; + union { + Action *itsAction; + ActionChain *itsChain; + }; +}; + struct KeyConfiguration { typedef std::pair< - std::multimap::iterator - , std::multimap::iterator + std::multimap::iterator + , std::multimap::iterator > Binding; void GenerateBindings(); - std::multimap Bindings; + std::multimap Bindings; + + private: + template void Bind_(wchar_t c, CharType ct, T t) + { + Bindings.insert(std::make_pair(Action::Key(c, ct), Bind(t))); + } }; struct Configuration