1 /***************************************************************************
2 * Copyright (C) 2008-2014 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
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 2 of the License, or *
8 * (at your option) any later version. *
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. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
28 #include "utility/wide_string.h"
30 #include "screen_switcher.h"
32 using Global::MainHeight
;
33 using Global::MainStartY
;
39 std::string
key_to_string(const Key
&key
, bool *print_backspace
)
42 if (key
== Key(KEY_UP
, Key::NCurses
))
44 else if (key
== Key(KEY_DOWN
, Key::NCurses
))
46 else if (key
== Key(KEY_PPAGE
, Key::NCurses
))
48 else if (key
== Key(KEY_NPAGE
, Key::NCurses
))
49 result
+= "Page Down";
50 else if (key
== Key(KEY_HOME
, Key::NCurses
))
52 else if (key
== Key(KEY_END
, Key::NCurses
))
54 else if (key
== Key(KEY_SPACE
, Key::Standard
))
56 else if (key
== Key(KEY_ENTER
, Key::Standard
))
58 else if (key
== Key(KEY_IC
, Key::NCurses
))
60 else if (key
== Key(KEY_DC
, Key::NCurses
))
62 else if (key
== Key(KEY_RIGHT
, Key::NCurses
))
64 else if (key
== Key(KEY_LEFT
, Key::NCurses
))
66 else if (key
== Key(KEY_TAB
, Key::Standard
))
68 else if (key
== Key(KEY_SHIFT_TAB
, Key::NCurses
))
69 result
+= "Shift-Tab";
70 else if (key
>= Key(KEY_CTRL_A
, Key::Standard
) && key
<= Key(KEY_CTRL_Z
, Key::Standard
))
73 result
+= key
.getChar()+64;
75 else if (key
>= Key(KEY_F1
, Key::NCurses
) && key
<= Key(KEY_F12
, Key::NCurses
))
78 result
+= boost::lexical_cast
<std::string
>(key
.getChar()-264);
80 else if ((key
== Key(KEY_BACKSPACE
, Key::NCurses
) || key
== Key(KEY_BACKSPACE_2
, Key::Standard
)))
82 // since some terminals interpret KEY_BACKSPACE as backspace and other need KEY_BACKSPACE_2,
83 // actions have to be bound to either of them, but we want to display "Backspace" only once,
84 // hance this 'print_backspace' switch.
85 if (!print_backspace
|| *print_backspace
)
87 result
+= "Backspace";
89 *print_backspace
= false;
93 result
+= ToString(std::wstring(1, key
.getChar()));
97 std::string
display_keys(const Actions::Type at
)
99 bool print_backspace
= true;
100 std::string result
, skey
;
101 for (auto it
= Bindings
.begin(); it
!= Bindings
.end(); ++it
)
103 for (auto j
= it
->second
.begin(); j
!= it
->second
.end(); ++j
)
105 if (j
->isSingle() && j
->action()->type() == at
)
107 skey
= key_to_string(it
->first
, &print_backspace
);
110 result
+= std::move(skey
);
116 result
.resize(16, ' ');
120 void section(NC::Scrollpad
&w
, const char *type_
, const char *title_
)
122 w
<< "\n " << NC::Format::Bold
<< type_
<< " - ";
123 w
<< title_
<< NC::Format::NoBold
<< "\n\n";
126 /**********************************************************************/
128 void key_section(NC::Scrollpad
&w
, const char *title_
)
130 section(w
, "Keys", title_
);
133 void key(NC::Scrollpad
&w
, const Actions::Type at
, const char *desc
)
135 w
<< " " << display_keys(at
) << " : " << desc
<< '\n';
138 void key(NC::Scrollpad
&w
, const Actions::Type at
, const boost::format
&desc
)
140 w
<< " " << display_keys(at
) << " : " << desc
.str() << '\n';
143 /**********************************************************************/
145 void mouse_section(NC::Scrollpad
&w
, const char *title_
)
147 section(w
, "Mouse", title_
);
150 void mouse(NC::Scrollpad
&w
, std::string action
, const char *desc
, bool indent
= false)
152 action
.resize(31 - (indent
? 2 : 0), ' ');
153 w
<< " " << (indent
? " " : "") << action
;
154 w
<< ": " << desc
<< '\n';
157 void mouse_column(NC::Scrollpad
&w
, const char *column
)
159 w
<< NC::Format::Bold
<< " " << column
<< " column:\n" << NC::Format::NoBold
;
162 /**********************************************************************/
164 void write_bindings(NC::Scrollpad
&w
)
168 key_section(w
, "Movement");
169 key(w
, Type::ScrollUp
, "Move cursor up");
170 key(w
, Type::ScrollDown
, "Move cursor down");
171 key(w
, Type::ScrollUpAlbum
, "Move cursor up one album");
172 key(w
, Type::ScrollDownAlbum
, "Move cursor down one album");
173 key(w
, Type::ScrollUpArtist
, "Move cursor up one artist");
174 key(w
, Type::ScrollDownArtist
, "Move cursor down one artist");
175 key(w
, Type::PageUp
, "Page up");
176 key(w
, Type::PageDown
, "Page down");
177 key(w
, Type::MoveHome
, "Home");
178 key(w
, Type::MoveEnd
, "End");
180 if (Config
.screen_switcher_previous
)
182 key(w
, Type::NextScreen
, "Switch between current and last screen");
183 key(w
, Type::PreviousScreen
, "Switch between current and last screen");
187 key(w
, Type::NextScreen
, "Switch to next screen in sequence");
188 key(w
, Type::PreviousScreen
, "Switch to previous screen in sequence");
190 key(w
, Type::ShowHelp
, "Show help");
191 key(w
, Type::ShowPlaylist
, "Show playlist");
192 key(w
, Type::ShowBrowser
, "Show browser");
193 key(w
, Type::ShowSearchEngine
, "Show search engine");
194 key(w
, Type::ShowMediaLibrary
, "Show media library");
195 key(w
, Type::ShowPlaylistEditor
, "Show playlist editor");
196 # ifdef HAVE_TAGLIB_H
197 key(w
, Type::ShowTagEditor
, "Show tag editor");
198 # endif // HAVE_TAGLIB_H
199 # ifdef ENABLE_OUTPUTS
200 key(w
, Type::ShowOutputs
, "Show outputs");
201 # endif // ENABLE_OUTPUTS
202 # ifdef ENABLE_VISUALIZER
203 key(w
, Type::ShowVisualizer
, "Show music visualizer");
204 # endif // ENABLE_VISUALIZER
206 key(w
, Type::ShowClock
, "Show clock");
207 # endif // ENABLE_CLOCK
209 key(w
, Type::ShowServerInfo
, "Show server info");
211 key_section(w
, "Global");
212 key(w
, Type::Stop
, "Stop");
213 key(w
, Type::Pause
, "Pause");
214 key(w
, Type::Next
, "Next track");
215 key(w
, Type::Previous
, "Previous track");
216 key(w
, Type::ReplaySong
, "Replay playing song");
217 key(w
, Type::SeekForward
, "Seek forward in playing song");
218 key(w
, Type::SeekBackward
, "Seek backward in playing song");
219 key(w
, Type::VolumeDown
,
220 boost::format("Decrease volume by %1%%%") % Config
.volume_change_step
222 key(w
, Type::VolumeUp
,
223 boost::format("Increase volume by %1%%%") % Config
.volume_change_step
226 key(w
, Type::ToggleSpaceMode
, "Toggle space mode (select/add)");
227 key(w
, Type::ToggleAddMode
, "Toggle add mode (add or remove/always add)");
228 key(w
, Type::ToggleMouse
, "Toggle mouse support");
229 key(w
, Type::ReverseSelection
, "Reverse selection");
230 key(w
, Type::RemoveSelection
, "Remove selection");
231 key(w
, Type::SelectAlbum
, "Select songs of album around the cursor");
232 key(w
, Type::AddSelectedItems
, "Add selected items to playlist");
233 key(w
, Type::AddRandomItems
, "Add random items to playlist");
235 key(w
, Type::ToggleRepeat
, "Toggle repeat mode");
236 key(w
, Type::ToggleRandom
, "Toggle random mode");
237 key(w
, Type::ToggleSingle
, "Toggle single mode");
238 key(w
, Type::ToggleConsume
, "Toggle consume mode");
239 key(w
, Type::ToggleReplayGainMode
, "Toggle replay gain mode");
240 key(w
, Type::ToggleBitrateVisibility
, "Toggle bitrate visibility");
241 key(w
, Type::Shuffle
, "Shuffle playlist");
242 key(w
, Type::ToggleCrossfade
, "Toggle crossfade mode");
243 key(w
, Type::SetCrossfade
, "Set crossfade");
244 key(w
, Type::SetVolume
, "Set volume");
245 key(w
, Type::UpdateDatabase
, "Start music database update");
247 key(w
, Type::ExecuteCommand
, "Execute command");
248 key(w
, Type::ApplyFilter
, "Apply filter");
249 key(w
, Type::FindItemForward
, "Find item forward");
250 key(w
, Type::FindItemBackward
, "Find item backward");
251 key(w
, Type::PreviousFoundItem
, "Jump to previous found item");
252 key(w
, Type::NextFoundItem
, "Jump to next found item");
253 key(w
, Type::ToggleFindMode
, "Toggle find mode (normal/wrapped)");
254 key(w
, Type::JumpToBrowser
, "Locate song in browser");
255 key(w
, Type::JumpToMediaLibrary
, "Locate song in media library");
256 key(w
, Type::ToggleScreenLock
, "Lock/unlock current screen");
257 key(w
, Type::MasterScreen
, "Switch to master screen (left one)");
258 key(w
, Type::SlaveScreen
, "Switch to slave screen (right one)");
259 # ifdef HAVE_TAGLIB_H
260 key(w
, Type::JumpToTagEditor
, "Locate song in tag editor");
261 # endif // HAVE_TAGLIB_H
262 key(w
, Type::ToggleDisplayMode
, "Toggle display mode");
263 key(w
, Type::ToggleInterface
, "Toggle user interface");
264 key(w
, Type::ToggleSeparatorsBetweenAlbums
, "Toggle displaying separators between albums");
265 key(w
, Type::JumpToPositionInSong
, "Jump to given position in playing song (formats: mm:ss, x%)");
266 key(w
, Type::ShowSongInfo
, "Show song info");
267 # ifdef HAVE_CURL_CURL_H
268 key(w
, Type::ShowArtistInfo
, "Show artist info");
269 key(w
, Type::ToggleLyricsFetcher
, "Toggle lyrics fetcher");
270 key(w
, Type::ToggleFetchingLyricsInBackground
, "Toggle fetching lyrics for playing songs in background");
271 # endif // HAVE_CURL_CURL_H
272 key(w
, Type::ShowLyrics
, "Show/hide song lyrics");
274 key(w
, Type::Quit
, "Quit");
276 key_section(w
, "Playlist");
277 key(w
, Type::PressEnter
, "Play selected item");
278 key(w
, Type::DeletePlaylistItems
, "Delete selected item(s) from playlist");
279 key(w
, Type::ClearMainPlaylist
, "Clear playlist");
280 key(w
, Type::CropMainPlaylist
, "Clear playlist except selected item(s)");
281 key(w
, Type::SetSelectedItemsPriority
, "Set priority of selected items");
282 key(w
, Type::MoveSelectedItemsUp
, "Move selected item(s) up");
283 key(w
, Type::MoveSelectedItemsDown
, "Move selected item(s) down");
284 key(w
, Type::MoveSelectedItemsTo
, "Move selected item(s) to cursor position");
285 key(w
, Type::Add
, "Add item to playlist");
286 # ifdef HAVE_TAGLIB_H
287 key(w
, Type::EditSong
, "Edit song");
288 # endif // HAVE_TAGLIB_H
289 key(w
, Type::SavePlaylist
, "Save playlist");
290 key(w
, Type::SortPlaylist
, "Sort playlist");
291 key(w
, Type::ReversePlaylist
, "Reverse playlist");
292 key(w
, Type::FilterPlaylistOnPriorities
, "Filter playlist on priorities");
293 key(w
, Type::JumpToPlayingSong
, "Jump to current song");
294 key(w
, Type::TogglePlayingSongCentering
, "Toggle playing song centering");
296 key_section(w
, "Browser");
297 key(w
, Type::PressEnter
, "Enter directory/Add item to playlist and play it");
298 key(w
, Type::PressSpace
, "Add item to playlist/select it");
299 # ifdef HAVE_TAGLIB_H
300 key(w
, Type::EditSong
, "Edit song");
301 # endif // HAVE_TAGLIB_H
302 key(w
, Type::EditDirectoryName
, "Edit directory name");
303 key(w
, Type::EditPlaylistName
, "Edit playlist name");
304 key(w
, Type::ChangeBrowseMode
, "Browse MPD database/local filesystem");
305 key(w
, Type::ToggleBrowserSortMode
, "Toggle sort mode");
306 key(w
, Type::JumpToPlayingSong
, "Locate playing song");
307 key(w
, Type::JumpToParentDirectory
, "Jump to parent directory");
308 key(w
, Type::DeleteBrowserItems
, "Delete selected items from disk");
309 key(w
, Type::JumpToPlaylistEditor
, "Jump to playlist editor (playlists only)");
311 key_section(w
, "Search engine");
312 key(w
, Type::PressEnter
, "Add item to playlist and play it/change option");
313 key(w
, Type::PressSpace
, "Add item to playlist");
314 # ifdef HAVE_TAGLIB_H
315 key(w
, Type::EditSong
, "Edit song");
316 # endif // HAVE_TAGLIB_H
317 key(w
, Type::StartSearching
, "Start searching");
318 key(w
, Type::ResetSearchEngine
, "Reset search constraints and clear results");
320 key_section(w
, "Media library");
321 key(w
, Type::ToggleMediaLibraryColumnsMode
, "Switch between two/three columns mode");
322 key(w
, Type::PreviousColumn
, "Previous column");
323 key(w
, Type::NextColumn
, "Next column");
324 key(w
, Type::PressEnter
, "Add item to playlist and play it");
325 key(w
, Type::PressSpace
, "Add item to playlist");
326 # ifdef HAVE_TAGLIB_H
327 key(w
, Type::EditSong
, "Edit song");
328 # endif // HAVE_TAGLIB_H
329 key(w
, Type::EditLibraryTag
, "Edit tag (left column)/album (middle/right column)");
330 key(w
, Type::ToggleLibraryTagType
, "Toggle type of tag used in left column");
331 key(w
, Type::ToggleMediaLibrarySortMode
, "Toggle sort mode");
333 key_section(w
, "Playlist editor");
334 key(w
, Type::PreviousColumn
, "Previous column");
335 key(w
, Type::NextColumn
, "Next column");
336 key(w
, Type::PressEnter
, "Add item to playlist and play it");
337 key(w
, Type::PressSpace
, "Add item to playlist/select it");
338 # ifdef HAVE_TAGLIB_H
339 key(w
, Type::EditSong
, "Edit song");
340 # endif // HAVE_TAGLIB_H
341 key(w
, Type::EditPlaylistName
, "Edit playlist name");
342 key(w
, Type::MoveSelectedItemsUp
, "Move selected item(s) up");
343 key(w
, Type::MoveSelectedItemsDown
, "Move selected item(s) down");
344 key(w
, Type::DeleteStoredPlaylist
, "Delete selected playlists (left column)");
345 key(w
, Type::DeletePlaylistItems
, "Delete selected item(s) from playlist (right column)");
346 key(w
, Type::ClearPlaylist
, "Clear playlist");
347 key(w
, Type::CropPlaylist
, "Clear playlist except selected items");
349 key_section(w
, "Lyrics");
350 key(w
, Type::PressSpace
, "Toggle reloading lyrics upon song change");
351 key(w
, Type::EditLyrics
, "Open lyrics in external editor");
352 key(w
, Type::RefetchLyrics
, "Refetch lyrics");
354 # ifdef HAVE_TAGLIB_H
355 key_section(w
, "Tiny tag editor");
356 key(w
, Type::PressEnter
, "Edit tag");
357 key(w
, Type::SaveTagChanges
, "Save");
359 key_section(w
, "Tag editor");
360 key(w
, Type::PressEnter
, "Edit tag/filename of selected item (left column)");
361 key(w
, Type::PressEnter
, "Perform operation on all/selected items (middle column)");
362 key(w
, Type::PressSpace
, "Switch to albums/directories view (left column)");
363 key(w
, Type::PressSpace
, "Select item (right column)");
364 key(w
, Type::PreviousColumn
, "Previous column");
365 key(w
, Type::NextColumn
, "Next column");
366 key(w
, Type::JumpToParentDirectory
, "Jump to parent directory (left column, directories view)");
367 # endif // HAVE_TAGLIB_H
369 # ifdef ENABLE_OUTPUTS
370 key_section(w
, "Outputs");
371 key(w
, Type::PressEnter
, "Toggle output");
372 # endif // ENABLE_OUTPUTS
374 # if defined(ENABLE_VISUALIZER) && defined(HAVE_FFTW3_H)
375 key_section(w
, "Music visualizer");
376 key(w
, Type::PressSpace
, "Toggle visualization type");
377 key(w
, Type::SetVisualizerSampleMultiplier
, "Set visualizer sample multiplier");
378 # endif // ENABLE_VISUALIZER && HAVE_FFTW3_H
380 mouse_section(w
, "Global");
381 mouse(w
, "Left click on \"Playing/Paused\"", "Play/pause");
382 mouse(w
, "Left click on progressbar", "Jump to pointed position in playing song");
384 mouse(w
, "Mouse wheel on \"Volume: xx\"", "Play/pause");
385 mouse(w
, "Mouse wheel on main window", "Scroll");
387 mouse_section(w
, "Playlist");
388 mouse(w
, "Left click", "Select pointed item");
389 mouse(w
, "Right click", "Play");
391 mouse_section(w
, "Browser");
392 mouse(w
, "Left click on directory", "Enter pointed directory");
393 mouse(w
, "Right click on directory", "Add pointed directory to playlist");
395 mouse(w
, "Left click on song/playlist", "Add pointed item to playlist");
396 mouse(w
, "Right click on song/playlist", "Add pointed item to playlist and play it");
398 mouse_section(w
, "Search engine");
399 mouse(w
, "Left click", "Highlight/switch value");
400 mouse(w
, "Right click", "Change value");
402 mouse_section(w
, "Media library");
403 mouse_column(w
, "Left/middle");
404 mouse(w
, "Left click", "Select pointed item", true);
405 mouse(w
, "Right click", "Add item to playlist", true);
407 mouse_column(w
, "Right");
408 mouse(w
, "Left Click", "Add pointed item to playlist", true);
409 mouse(w
, "Right Click", "Add pointed item to playlist and play it", true);
411 mouse_section(w
, "Playlist editor");
412 mouse_column(w
, "Left");
413 mouse(w
, "Left click", "Select pointed item", true);
414 mouse(w
, "Right click", "Add item to playlist", true);
416 mouse_column(w
, "Right");
417 mouse(w
, "Left click", "Add pointed item to playlist", true);
418 mouse(w
, "Right click", "Add pointed item to playlist and play it", true);
420 # ifdef HAVE_TAGLIB_H
421 mouse_section(w
, "Tiny tag editor");
422 mouse(w
, "Left click", "Select option");
423 mouse(w
, "Right click", "Set value/execute");
425 mouse_section(w
, "Tag editor");
426 mouse_column(w
, "Left");
427 mouse(w
, "Left click", "Enter pointed directory/select pointed album", true);
428 mouse(w
, "Right click", "Toggle view (directories/albums)", true);
430 mouse_column(w
, "Middle");
431 mouse(w
, "Left click", "Select option", true);
432 mouse(w
, "Right click", "Set value/execute", true);
434 mouse_column(w
, "Right");
435 mouse(w
, "Left click", "Select pointed item", true);
436 mouse(w
, "Right click", "Set value", true);
437 # endif // HAVE_TAGLIB_H
439 # ifdef ENABLE_OUTPUTS
440 mouse_section(w
, "Outputs");
441 mouse(w
, "Left click", "Select pointed output");
442 mouse(w
, "Right click", "Toggle output");
443 # endif // ENABLE_OUTPUTS
450 : Screen(NC::Scrollpad(0, MainStartY
, COLS
, MainHeight
, "", Config
.main_color
, NC::Border::None
))
458 size_t x_offset
, width
;
459 getWindowResizeParams(x_offset
, width
);
460 w
.resize(width
, MainHeight
);
461 w
.moveTo(x_offset
, MainStartY
);
465 void Help::switchTo()
467 SwitchTo::execute(this);
471 std::wstring
Help::title()