1 /* 2 Vimpc 3 Copyright (C) 2010 - 2012 Nathan Sweetman 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 settings.hpp - handle configuration options via :set command 19 */ 20 21 #ifndef __MAIN__SETTINGS 22 #define __MAIN__SETTINGS 23 24 #include "compiler.hpp" 25 26 #include "colours.hpp" 27 #include "test.hpp" 28 29 #include <string> 30 #include <map> 31 #include <vector> 32 33 // Create an enum entry, name and value for each setting 34 // X(enum-entry, setting-name, default-value) 35 #define TOGGLE_SETTINGS \ 36 X(AutoScroll, "autoscroll", true) /* Automatically scroll to playing song */ \ 37 X(AutoUpdate, "autoupdate", true) /* Automatically update after file edits */ \ 38 X(AutoLyrics, "autolyrics", false) /* Automatically get lyrics for the playing song */ \ 39 X(AutoScrollLyrics, "autoscrolllyrics",false) /* Automatically scroll lyrics for the playing song */ \ 40 X(AlbumArtist, "albumartist", true) /* Use the album artist tag if there is one */ \ 41 X(BrowseNumbers, "browsenumbers", false) /* Show numbers in the browse window */ \ 42 X(ColourEnabled, "colour", true) /* Determine if we should use colours */ \ 43 X(ExpandArtists, "expand-artists", false) /* Expand artists in the library window by default */ \ 44 X(HighlightSearch, "hlsearch", true) /* Show search results in a different colour */ \ 45 X(IgnoreTheGroup, "groupignorethe", false) /* Ignore 'the' when grouping the same artist into library */ \ 46 X(IgnoreCaseSearch, "ignorecase", false) /* Turn off case sensitivity on searching */ \ 47 X(IgnoreCaseSort, "sortignorecase", true) /* Turn off case sensitivity on sorting */\ 48 X(IgnoreTheSort, "sortignorethe", false) /* Ignore 'the' when sorting */ \ 49 X(IncrementalSearch,"incsearch", false) /* Search for results whilst typing */ \ 50 X(ListAllMeta, "listallmeta", true) /* Get all meta data */ \ 51 X(Mouse, "mouse", true) /* Handle mouse keys */ \ 52 X(Polling, "polling", false) /* Poll for status updates */ \ 53 X(PlaylistNumbers, "playlistnumbers", true) /* Show id next to each song in the playlist */ \ 54 X(PlayOnAdd, "playonadd", false) /* If mpd is stopped play after first add */ \ 55 X(ProgressBar, "progressbar", true) /* Show the progress bar */ \ 56 X(Reconnect, "reconnect", true) /* Reconnect to server when connection drops */ \ 57 X(ScrollOnAdd, "scrollonadd", true) /* Auto scroll down after song added */ \ 58 X(ScrollOnDelete, "scrollondelete", true) /* Auto scroll down after song delete */ \ 59 X(ScrollStatus, "scrollstatus", true) /* Scroll long status lines */ \ 60 X(SearchWrap, "searchwrap", true) /* Determine whether to wrap searching */ \ 61 X(SeekBar, "seekbar", true) /* Mouse click on progress bar causes a seek */ \ 62 X(ShowPath, "showpath", true) /* Show current path in directory window */ \ 63 X(ShowPercent, "showpercent", true) /* Show percentage on the progress bar */ \ 64 X(ShowLists, "showlists", true) /* Show playlists in directory window */ \ 65 X(SingleQuit, "singlequit", false) /* Quit the entire application not just close a tab */ \ 66 X(SongNumbers, "songnumbers", true) /* Show id numbers next to songs in any window */ \ 67 X(SmartCase, "smartcase", false) /* Case sensitivy enabled when upper case char is used */ \ 68 X(StopOnQuit, "stoponquit", false) /* Stop playing when we quit */ \ 69 X(TabBar, "tabbar", true) /* Show the tab bar */ \ 70 X(TimeRemaining, "timeremaining", false) /* Show time left rather than time elapsed */ \ 71 X(WindowNumbers, "windownumbers", false) /* Window numbers next to each window in the tab list */ 72 73 // X(enum-entry, setting-name, default-value, regex-filter) 74 #define STRING_SETTINGS \ 75 /* position to add songs */ \ 76 X(AddPosition, "add", "end", "next|end") \ 77 /* Library format string */ \ 78 X(AlbumFormat, "albumformat", "%B", ".*") \ 79 /* Library format string */ \ 80 X(ArtistFormat, "artistformat", "%A", ".*") \ 81 /* Library format string */ \ 82 X(LibraryFormat, "libraryformat", "$I%n \\| $D$H[$H%l$H]$H {%t}|{%f}$E$R ", ".*") \ 83 /* Library format string */ \ 84 X(LocalMusicDir, "local-music-dir", "", ".*") \ 85 /* Lyrics strip regex */ \ 86 X(LyricsStrip, "lyricsstrip", "(\\s*(R|r)emaster\\w*)|(\\s+-.*)", ".*") \ 87 /* Lists to show in the lists window */ \ 88 X(Playlists, "playlists", "mpd", "all|mpd|files") \ 89 /* Song format string */ \ 90 X(SongFormat, "songformat", "{{%a - }%t}|{%f}$E$R $H[$H%l$H]$H", ".*") \ 91 /* Song format fill character */ \ 92 X(SongFillChar, "songfillchar", " ", ".") \ 93 /* Sort based on song format */ \ 94 X(Sort, "sort", "format", "format|library") \ 95 /* Connection Timeout in seconds */ \ 96 X(Timeout, "timeout", "30", "\\d+") \ 97 /* Startup window */ \ 98 X(Window, "window", "help", ".*") \ 99 /* Startup windows */ \ 100 X(Windows, "windows", "help,lists,library,browse,playlist", ".*") 101 102 #define COLOUR_SETTINGS \ 103 X(COLOR_DEFAULT, "default" ) \ 104 X(COLOR_BLACK, "black" ) \ 105 X(COLOR_RED, "red" ) \ 106 X(COLOR_GREEN, "green" ) \ 107 X(COLOR_YELLOW, "yellow" ) \ 108 X(COLOR_BLUE, "blue" ) \ 109 X(COLOR_MAGENTA, "magenta" ) \ 110 X(COLOR_CYAN, "cyan" ) \ 111 X(COLOR_WHITE, "white" ) \ 112 X(BOLD(COLOR_BLACK), "bold_black" ) \ 113 X(BOLD(COLOR_RED), "bold_red" ) \ 114 X(BOLD(COLOR_GREEN), "bold_green" ) \ 115 X(BOLD(COLOR_YELLOW), "bold_yellow" ) \ 116 X(BOLD(COLOR_BLUE), "bold_blue" ) \ 117 X(BOLD(COLOR_MAGENTA), "bold_magenta" ) \ 118 X(BOLD(COLOR_CYAN), "bold_cyan" ) \ 119 X(BOLD(COLOR_WHITE), "bold_white" ) 120 121 class Setting 122 { 123 public: 124 // Provide access to default values through settings table 125 static std::string Default; 126 127 // Use for add position comparisons 128 static std::string AddEnd; 129 static std::string AddNext; 130 131 // Use for playlists comparisons 132 static std::string PlaylistsMpd; 133 static std::string PlaylistsAll; 134 static std::string PlaylistsFiles; 135 136 #define X(a, b, c) a, 137 typedef enum 138 { 139 TOGGLE_SETTINGS 140 ToggleCount 141 } ToggleSettings; 142 #undef X 143 144 #define X(a, b, c, d) a, 145 typedef enum 146 { 147 StartString = ToggleCount, 148 STRING_SETTINGS 149 StringCount 150 } StringSettings; 151 #undef X 152 }; 153 154 namespace Main 155 { 156 //! Holds the value of an individual setting 157 template <typename T> 158 class SettingValue 159 { 160 public: SettingValue(int32_t id)161 SettingValue(int32_t id) : id_(id) { } SettingValue(int32_t id,T v)162 SettingValue(int32_t id, T v) : id_(id), value_(v) { } ~SettingValue()163 ~SettingValue() { } 164 Id() const165 int32_t Id() const { return id_; } Get() const166 T Get() const { return value_; } Set(T v)167 void Set(T v) { value_ = v; } 168 169 private: 170 int32_t const id_; 171 T value_; 172 }; 173 174 //! Manages settings which are set via :set command 175 class Settings 176 { 177 public: 178 Colours colours; 179 180 public: 181 static Settings & Instance(); 182 183 protected: 184 Settings(); 185 ~Settings(); 186 187 public: 188 //! List all the available settings (including no versions); 189 std::vector<std::string> AvailableSettings() const; 190 191 //! Calls the correct setter function based upon the given input 192 void Set(std::string const & input); 193 194 //! Handles settings which are treated as an on/off setting 195 void SetSingleSetting(std::string setting); 196 197 //! Get the value of a particular setting 198 bool Get(Setting::ToggleSettings setting) const; 199 std::string Get(Setting::StringSettings setting) const; 200 201 //! Name of a particular setting 202 std::string Name(Setting::ToggleSettings setting) const; 203 std::string Name(Setting::StringSettings setting) const; 204 205 //! Register a callback to be called when a setting is changed 206 void RegisterCallback(Setting::ToggleSettings setting, FUNCTION<void (bool)> callback); 207 void RegisterCallback(Setting::StringSettings setting, FUNCTION<void (std::string)> callback); 208 209 //! Turn the callbacks on and off 210 void EnableCallbacks(); 211 void DisableCallbacks(); 212 213 public: 214 //! Set/Get whether or not to connect if asked to in config 215 void SetSkipConfigConnects(bool val); 216 bool SkipConfigConnects() const; 217 218 void SetColour(std::string property, std::string bg, std::string fg); 219 220 //! Get the value for the given \p setting 221 template <typename T> 222 inline T Get(std::string setting) const; 223 224 //! Set the value of a particular setting 225 void Set(Setting::ToggleSettings setting, bool value); 226 void Set(Setting::StringSettings setting, std::string value); 227 228 protected: 229 //! Set the value for the given \p setting SetValue(std::string setting,bool value)230 inline void SetValue(std::string setting, bool value) 231 { 232 SetValue(setting, value, toggleTable_); 233 } 234 SetValue(std::string setting,std::string value)235 inline void SetValue(std::string setting, std::string value) 236 { 237 SetValue(setting, value, stringTable_); 238 } 239 240 private: 241 template <class T> GetValue(std::string setting,T table) const242 auto GetValue(std::string setting, T table) const -> decltype (table.at(Setting::Default)->Get()) 243 { 244 mutex_.lock(); 245 auto const it = table.find(setting); 246 auto const Result = (it != table.end()) ? (it->second->Get()) : table.at(Setting::Default)->Get(); 247 mutex_.unlock(); 248 return Result; 249 } 250 251 template <class T, class U> SetValue(std::string setting,T value,U const & table)252 void SetValue(std::string setting, T value, U const & table) 253 { 254 mutex_.lock(); 255 auto const it = table.find(setting); 256 if (it != table.end()) { (it->second->Set(value)); } 257 mutex_.unlock(); 258 } 259 260 //! Used to handle settings that require very specific paramters 261 void SetSpecificSetting(std::string setting, std::string arguments); 262 263 private: 264 typedef std::map<int, std::string> SettingNameTable; 265 SettingNameTable settingName_; 266 267 // Holds yes/no, on/off style settings 268 typedef std::map<std::string, SettingValue<bool> * > BoolSettingsTable; 269 BoolSettingsTable toggleTable_; 270 271 typedef std::vector<SettingValue<bool> * > BoolVector; 272 BoolVector toggleVector_; 273 274 // Callbacks for on/off settings 275 typedef std::map<Setting::ToggleSettings, std::vector<FUNCTION<void (bool)> > > BoolCallbackTable; 276 BoolCallbackTable tCallbackTable_; 277 278 // Used to validate string settings against a regex pattern 279 typedef std::map<std::string, std::string> SettingsFilterTable; 280 SettingsFilterTable filterTable_; 281 282 // Settings that are represented by a string value 283 typedef std::map<std::string, SettingValue<std::string> * > StringSettingsTable; 284 StringSettingsTable stringTable_; 285 286 typedef std::vector<SettingValue<std::string> * > StringVector; 287 StringVector stringVector_; 288 289 // Callbacks for string style settings 290 typedef std::map<Setting::StringSettings, std::vector<FUNCTION<void (std::string)> > > StringCallbackTable; 291 StringCallbackTable sCallbackTable_; 292 293 typedef std::map<std::string, int> ColorNameTable; 294 ColorNameTable colourTable_; 295 296 bool enabled_; 297 298 mutable RecursiveMutex mutex_; 299 }; 300 301 template <> Get(std::string setting) const302 inline bool Settings::Get<bool>(std::string setting) const 303 { 304 return GetValue(setting, toggleTable_); 305 } 306 307 template <> Get(std::string setting) const308 inline std::string Settings::Get<std::string>(std::string setting) const 309 { 310 return GetValue(setting, stringTable_); 311 } 312 } 313 314 #endif 315 /* vim: set sw=3 ts=3: */ 316