settings: configuration file processing rewrite
This commit is contained in:
272
doc/config
272
doc/config
@@ -12,7 +12,7 @@
|
|||||||
## file which defines that while launching ncmpcpp.
|
## file which defines that while launching ncmpcpp.
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
#ncmpcpp_directory = "~/.ncmpcpp"
|
#ncmpcpp_directory = ~/.ncmpcpp
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
## Directory for storing downloaded lyrics. It
|
## Directory for storing downloaded lyrics. It
|
||||||
@@ -20,21 +20,21 @@
|
|||||||
## (eg. ncmpc) also use that location.
|
## (eg. ncmpc) also use that location.
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
#lyrics_directory = "~/.lyrics"
|
#lyrics_directory = ~/.lyrics
|
||||||
#
|
#
|
||||||
##### connection settings #####
|
##### connection settings #####
|
||||||
#
|
#
|
||||||
## set it in order to make tag editor and renaming files work properly
|
#mpd_host = localhost
|
||||||
#
|
#
|
||||||
#mpd_host = "localhost"
|
#mpd_port = 6600
|
||||||
#
|
#
|
||||||
#mpd_port = "6600"
|
#mpd_connection_timeout = 5
|
||||||
#
|
#
|
||||||
#mpd_music_dir = ""
|
## Needed for tag editor and file operations to work.
|
||||||
|
##
|
||||||
|
#mpd_music_dir = ~/music
|
||||||
#
|
#
|
||||||
#mpd_connection_timeout = "5"
|
#mpd_crossfade_time = 5
|
||||||
#
|
|
||||||
#mpd_crossfade_time = "5"
|
|
||||||
#
|
#
|
||||||
##### music visualizer #####
|
##### music visualizer #####
|
||||||
##
|
##
|
||||||
@@ -46,19 +46,13 @@
|
|||||||
##
|
##
|
||||||
## audio_output {
|
## audio_output {
|
||||||
## type "fifo"
|
## type "fifo"
|
||||||
## name "My FIFO"
|
## name "Visualizer feed"
|
||||||
## path "/tmp/mpd.fifo"
|
## path "/tmp/mpd.fifo"
|
||||||
## format "44100:16:2"
|
## format "44100:16:2"
|
||||||
## }
|
## }
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
##
|
#visualizer_fifo_path = /tmp/mpd.fifo
|
||||||
## If you set format to 44100:16:2, make it 'yes'.
|
|
||||||
##
|
|
||||||
#
|
|
||||||
#visualizer_in_stereo = "no"
|
|
||||||
#
|
|
||||||
#visualizer_fifo_path = ""
|
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
## Note: Below parameter is needed for ncmpcpp
|
## Note: Below parameter is needed for ncmpcpp
|
||||||
@@ -68,7 +62,12 @@
|
|||||||
## are some problems with it.
|
## are some problems with it.
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
#visualizer_output_name = ""
|
#visualizer_output_name = Visualizer feed
|
||||||
|
#
|
||||||
|
##
|
||||||
|
## If you set format to 44100:16:2, make it 'yes'.
|
||||||
|
##
|
||||||
|
#visualizer_in_stereo = yes
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
## Note: Below parameter defines how often ncmpcpp
|
## Note: Below parameter defines how often ncmpcpp
|
||||||
@@ -78,14 +77,16 @@
|
|||||||
## Keep in mind that sane values start with >=10.
|
## Keep in mind that sane values start with >=10.
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
#visualizer_sync_interval = "30"
|
#visualizer_sync_interval = 30
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
## Note: To enable spectrum frequency visualization
|
## Note: To enable spectrum frequency visualization
|
||||||
## you need to compile ncmpcpp with fftw3 support.
|
## you need to compile ncmpcpp with fftw3 support.
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
#visualizer_type = "wave" (spectrum/wave)
|
## Available values: spectrum, wave.
|
||||||
|
##
|
||||||
|
#visualizer_type = wave
|
||||||
#
|
#
|
||||||
#visualizer_look = "◆│"
|
#visualizer_look = "◆│"
|
||||||
#
|
#
|
||||||
@@ -99,7 +100,7 @@
|
|||||||
## supports charset detection by checking output
|
## supports charset detection by checking output
|
||||||
## of `ncmpcpp --version`.
|
## of `ncmpcpp --version`.
|
||||||
##
|
##
|
||||||
## Note: Since MPD uses utf8 by default, setting
|
## Note: Since MPD uses UTF-8 by default, setting
|
||||||
## this option makes sense only if your encoding
|
## this option makes sense only if your encoding
|
||||||
## is different.
|
## is different.
|
||||||
##
|
##
|
||||||
@@ -108,13 +109,14 @@
|
|||||||
#
|
#
|
||||||
##### delays #####
|
##### delays #####
|
||||||
#
|
#
|
||||||
## delay after playlist highlighting will be disabled (0 = don't disable)
|
## Time of inactivity (in seconds) after playlist
|
||||||
|
## highlighting will be disabled (0 = always on).
|
||||||
|
##
|
||||||
|
#playlist_disable_highlight_delay = 5
|
||||||
#
|
#
|
||||||
#playlist_disable_highlight_delay = "5"
|
## Defines how long messages are supposed to be visible.
|
||||||
#
|
##
|
||||||
## defines how long various messages are supposed to be visible
|
#message_delay_time = 5
|
||||||
#
|
|
||||||
#message_delay_time = "4"
|
|
||||||
#
|
#
|
||||||
##### song format #####
|
##### song format #####
|
||||||
##
|
##
|
||||||
@@ -151,9 +153,9 @@
|
|||||||
## you'll get nothing.
|
## you'll get nothing.
|
||||||
##
|
##
|
||||||
## text can also have different color than the main window has,
|
## text can also have different color than the main window has,
|
||||||
## eg. if you want length to be green, write $3%l$9
|
## eg. if you want length to be green, write "$3%l$9".
|
||||||
##
|
##
|
||||||
## available values:
|
## Available values:
|
||||||
##
|
##
|
||||||
## - 0 - default window color (discards all other colors)
|
## - 0 - default window color (discards all other colors)
|
||||||
## - 1 - black
|
## - 1 - black
|
||||||
@@ -169,24 +171,24 @@
|
|||||||
## Note: colors can be nested.
|
## Note: colors can be nested.
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
#song_list_format = "{%a - }{%t}|{$8%f$9}$R{$3(%l)$9}"
|
#song_list_format = {%a - }{%t}|{$8%f$9}$R{$3(%l)$9}
|
||||||
#
|
#
|
||||||
#song_status_format = "{{%a{ \"%b\"{ (%y)}} - }{%t}}|{%f}"
|
#song_status_format = {{%a{ \"%b\"{ (%y)}} - }{%t}}|{%f}
|
||||||
#
|
#
|
||||||
#song_library_format = "{%n - }{%t}|{%f}"
|
#song_library_format = {%n - }{%t}|{%f}
|
||||||
#
|
#
|
||||||
#tag_editor_album_format = "{(%y) }%b"
|
#tag_editor_album_format = {(%y) }%b
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
## Note: Below variables are used for sorting songs in browser.
|
## Note: Below variables are used for sorting songs in browser.
|
||||||
## The sort mode determines how songs are sorted, and can be used
|
## The sort mode determines how songs are sorted, and can be used
|
||||||
## in combination with a sort format to specify a custom sorting format.
|
## in combination with a sort format to specify a custom sorting format.
|
||||||
## Possible values for browser_sort_mode are "name", "mtime" and "format".
|
## Available values for browser_sort_mode are "name", "mtime" and "format".
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
#browser_sort_mode = "name"
|
#browser_sort_mode = name
|
||||||
#
|
#
|
||||||
#browser_sort_format = "{%a - }{%t}|{%f} {(%l)}"
|
#browser_sort_format = {%a - }{%t}|{%f} {(%l)}
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
## Note: Below variables are for alternative version of user's interface.
|
## Note: Below variables are for alternative version of user's interface.
|
||||||
@@ -205,30 +207,29 @@
|
|||||||
## with reversed colors.
|
## with reversed colors.
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
#alternative_header_first_line_format = "$b$1$aqqu$/a$9 {%t}|{%f} $1$atqq$/a$9$/b"
|
#alternative_header_first_line_format = $b$1$aqqu$/a$9 {%t}|{%f} $1$atqq$/a$9$/b
|
||||||
#
|
#
|
||||||
#alternative_header_second_line_format = "{{$4$b%a$/b$9}{ - $7%b$9}{ ($4%y$9)}}|{%D}"
|
#alternative_header_second_line_format = {{$4$b%a$/b$9}{ - $7%b$9}{ ($4%y$9)}}|{%D}
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
## Note: Below variables also supports
|
## Note: below variables also support text attributes listed above.
|
||||||
## text attributes listed above.
|
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
#now_playing_prefix = "$b"
|
#now_playing_prefix = $b
|
||||||
#
|
#
|
||||||
#now_playing_suffix = "$/b"
|
#now_playing_suffix = $/b
|
||||||
#
|
#
|
||||||
#browser_playlist_prefix = "$2playlist$9 "
|
#browser_playlist_prefix = "$2playlist$9 "
|
||||||
#
|
#
|
||||||
#selected_item_prefix = "$6"
|
#selected_item_prefix = $6
|
||||||
#
|
#
|
||||||
#selected_item_suffix = "$9"
|
#selected_item_suffix = $9
|
||||||
#
|
#
|
||||||
#modified_item_prefix = "$3> $9"
|
#modified_item_prefix = $3> $9
|
||||||
#
|
#
|
||||||
## colors are not supported for below variable
|
## Note: colors are not supported for below variable.
|
||||||
#
|
##
|
||||||
#song_window_title_format = "{%a - }{%t}|{%f}"
|
#song_window_title_format = {%a - }{%t}|{%f}
|
||||||
#
|
#
|
||||||
##### columns settings #####
|
##### columns settings #####
|
||||||
##
|
##
|
||||||
@@ -266,7 +267,7 @@
|
|||||||
## not available.
|
## not available.
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
#song_columns_list_format = "(7f)[green]{l} (25)[cyan]{a} (40)[]{t|f} (30)[red]{b}"
|
#song_columns_list_format = (7f)[green]{l} (25)[cyan]{a} (40)[]{t|f} (30)[red]{b}
|
||||||
#
|
#
|
||||||
##### various settings #####
|
##### various settings #####
|
||||||
#
|
#
|
||||||
@@ -279,75 +280,86 @@
|
|||||||
##
|
##
|
||||||
#execute_on_song_change = ""
|
#execute_on_song_change = ""
|
||||||
#
|
#
|
||||||
#playlist_show_remaining_time = "no"
|
#playlist_show_remaining_time = no
|
||||||
#
|
#
|
||||||
#playlist_shorten_total_times = "no"
|
#playlist_shorten_total_times = no
|
||||||
#
|
#
|
||||||
#playlist_separate_albums = "no"
|
#playlist_separate_albums = no
|
||||||
#
|
#
|
||||||
#playlist_display_mode = "classic" (classic/columns)
|
##
|
||||||
|
## Note: Possible display modes: classic, columns.
|
||||||
|
##
|
||||||
|
#playlist_display_mode = classic
|
||||||
#
|
#
|
||||||
#browser_display_mode = "classic" (classic/columns)
|
#browser_display_mode = classic
|
||||||
#
|
#
|
||||||
#search_engine_display_mode = "classic" (classic/columns)
|
#search_engine_display_mode = classic
|
||||||
#
|
#
|
||||||
#playlist_editor_display_mode = "classic" (classic/columns)
|
#playlist_editor_display_mode = classic
|
||||||
#
|
#
|
||||||
#discard_colors_if_item_is_selected = "yes"
|
#discard_colors_if_item_is_selected = yes
|
||||||
#
|
#
|
||||||
#incremental_seeking = "yes"
|
#incremental_seeking = yes
|
||||||
#
|
#
|
||||||
#seek_time = "1"
|
#seek_time = 1
|
||||||
#
|
#
|
||||||
#volume_change_step = "1"
|
#volume_change_step = 1
|
||||||
#
|
#
|
||||||
#autocenter_mode = "no"
|
#autocenter_mode = no
|
||||||
#
|
#
|
||||||
#centered_cursor = "no"
|
#centered_cursor = no
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
## Note: You can specify third character which will
|
## Note: You can specify third character which will
|
||||||
## be used to build 'empty' part of progressbar.
|
## be used to build 'empty' part of progressbar.
|
||||||
##
|
##
|
||||||
#progressbar_look = "=>"
|
#progressbar_look = =>
|
||||||
#
|
#
|
||||||
#progressbar_boldness = "yes"
|
#progressbar_boldness = yes
|
||||||
#
|
#
|
||||||
#default_place_to_search_in = "database" (database/playlist)
|
## Available values: database, playlist.
|
||||||
|
##
|
||||||
|
#default_place_to_search_in = database
|
||||||
#
|
#
|
||||||
#user_interface = "classic" (classic/alternative)
|
## Available values: classic, alternative.
|
||||||
|
##
|
||||||
|
#user_interface = classic
|
||||||
#
|
#
|
||||||
#media_library_left_column = "a" (possible values: a,y,g,c,p, legend above)
|
## Available values: artist, date, genre, composer, performer.
|
||||||
|
##
|
||||||
|
#media_library_primary_tag = artist
|
||||||
#
|
#
|
||||||
#default_find_mode = "wrapped" (wrapped/normal)
|
## Available values: wrapped, normal.
|
||||||
|
##
|
||||||
|
#default_find_mode = wrapped
|
||||||
#
|
#
|
||||||
#default_space_mode = "add" (add/select)
|
## Available values: add, select.
|
||||||
|
##
|
||||||
|
#default_space_mode = add
|
||||||
#
|
#
|
||||||
#default_tag_editor_pattern = "%n - %t"
|
#default_tag_editor_pattern = %n - %t
|
||||||
#
|
#
|
||||||
#header_visibility = "yes"
|
#header_visibility = yes
|
||||||
#
|
#
|
||||||
#statusbar_visibility = "yes"
|
#statusbar_visibility = yes
|
||||||
#
|
#
|
||||||
#titles_visibility = "yes"
|
#titles_visibility = yes
|
||||||
#
|
#
|
||||||
#header_text_scrolling = "yes"
|
#header_text_scrolling = yes
|
||||||
#
|
#
|
||||||
#fancy_scrolling = "yes"
|
#cyclic_scrolling = no
|
||||||
#
|
#
|
||||||
#cyclic_scrolling = "no"
|
#lines_scrolled = 2
|
||||||
#
|
#
|
||||||
#lines_scrolled = "2"
|
#follow_now_playing_lyrics = no
|
||||||
#
|
#
|
||||||
#follow_now_playing_lyrics = "no"
|
#fetch_lyrics_for_current_song_in_background = no
|
||||||
#
|
#
|
||||||
#fetch_lyrics_for_current_song_in_background = "no"
|
#store_lyrics_in_song_dir = no
|
||||||
#
|
#
|
||||||
#store_lyrics_in_song_dir = "no"
|
#generate_win32_compatible_filenames = yes
|
||||||
#
|
#
|
||||||
#generate_win32_compatible_filenames = "yes"
|
#allow_for_physical_item_deletion = no
|
||||||
#
|
|
||||||
#allow_for_physical_item_deletion = "no"
|
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
## Note: If you set this variable, ncmpcpp will try to
|
## Note: If you set this variable, ncmpcpp will try to
|
||||||
@@ -357,13 +369,13 @@
|
|||||||
##
|
##
|
||||||
## Note: Language has to be expressed as an ISO 639 alpha-2 code.
|
## Note: Language has to be expressed as an ISO 639 alpha-2 code.
|
||||||
##
|
##
|
||||||
#lastfm_preferred_language = ""
|
#lastfm_preferred_language = en
|
||||||
#
|
#
|
||||||
#ncmpc_like_songs_adding = "no" (enabled - add/remove, disabled - always add)
|
## Available values: add_remove, always_add.
|
||||||
|
##
|
||||||
|
#space_add_mode = always_add
|
||||||
#
|
#
|
||||||
#show_hidden_files_in_local_browser = "no"
|
#show_hidden_files_in_local_browser = no
|
||||||
#
|
|
||||||
#display_screens_numbers_on_start = "yes"
|
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
## How shall screen switcher work?
|
## How shall screen switcher work?
|
||||||
@@ -374,59 +386,61 @@
|
|||||||
## Screens available for use: help, playlist, browser, search_engine,
|
## Screens available for use: help, playlist, browser, search_engine,
|
||||||
## media_library, playlist_editor, tag_editor, outputs, visualizer, clock.
|
## media_library, playlist_editor, tag_editor, outputs, visualizer, clock.
|
||||||
##
|
##
|
||||||
#screen_switcher_mode = "playlist, browser"
|
#screen_switcher_mode = playlist, browser
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
## Note: You can define startup screen for ncmpcpp
|
## Note: You can define startup screen for ncmpcpp
|
||||||
## by choosing screen from the list above.
|
## by choosing screen from the list above.
|
||||||
##
|
##
|
||||||
#startup_screen = "playlist"
|
#startup_screen = playlist
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
## Default width of locked screen (in %).
|
## Default width of locked screen (in %).
|
||||||
## Acceptable values are from 20 to 80.
|
## Acceptable values are from 20 to 80.
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
#locked_screen_width_part = "50"
|
#locked_screen_width_part = 50
|
||||||
#
|
#
|
||||||
#ask_for_locked_screen_width_part = "yes"
|
#ask_for_locked_screen_width_part = yes
|
||||||
#
|
#
|
||||||
#jump_to_now_playing_song_at_start = "yes"
|
#jump_to_now_playing_song_at_start = yes
|
||||||
#
|
#
|
||||||
#ask_before_clearing_main_playlist = "no"
|
#ask_before_clearing_playlists = yes
|
||||||
#
|
#
|
||||||
#clock_display_seconds = "no"
|
#clock_display_seconds = no
|
||||||
#
|
#
|
||||||
#display_volume_level = "yes"
|
#display_volume_level = yes
|
||||||
#
|
#
|
||||||
#display_bitrate = "no"
|
#display_bitrate = no
|
||||||
#
|
#
|
||||||
#display_remaining_time = "no"
|
#display_remaining_time = no
|
||||||
#
|
#
|
||||||
#regular_expressions = "none" (none/basic/extended)
|
## Available values: none, basic, extended.
|
||||||
|
##
|
||||||
|
#regular_expressions = none
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
## Note: If below is enabled, ncmpcpp will ignore leading
|
## Note: If below is enabled, ncmpcpp will ignore leading
|
||||||
## "The" word while sorting items in browser, tags in
|
## "The" word while sorting items in browser, tags in
|
||||||
## media library, etc.
|
## media library, etc.
|
||||||
##
|
##
|
||||||
#ignore_leading_the = "no"
|
#ignore_leading_the = no
|
||||||
#
|
#
|
||||||
#block_search_constraints_change_if_items_found = "yes"
|
#block_search_constraints_change_if_items_found = yes
|
||||||
#
|
#
|
||||||
#mouse_support = "yes"
|
#mouse_support = yes
|
||||||
#
|
#
|
||||||
#mouse_list_scroll_whole_page = "yes"
|
#mouse_list_scroll_whole_page = yes
|
||||||
#
|
#
|
||||||
#empty_tag_marker = "<empty>"
|
#empty_tag_marker = <empty>
|
||||||
#
|
#
|
||||||
#tags_separator = " | "
|
#tags_separator = " | "
|
||||||
#
|
#
|
||||||
#tag_editor_extended_numeration = "no"
|
#tag_editor_extended_numeration = no
|
||||||
#
|
#
|
||||||
#media_library_sort_by_mtime = "no"
|
#media_library_sort_by_mtime = no
|
||||||
#
|
#
|
||||||
#enable_window_title = "yes"
|
#enable_window_title = yes
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
## Note: You can choose default search mode for search
|
## Note: You can choose default search mode for search
|
||||||
@@ -440,47 +454,49 @@
|
|||||||
## in database and local one for searching in current playlist)
|
## in database and local one for searching in current playlist)
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
#search_engine_default_search_mode = "1"
|
#search_engine_default_search_mode = 1
|
||||||
#
|
#
|
||||||
#external_editor = ""
|
#external_editor = nano
|
||||||
#
|
#
|
||||||
#use_console_editor = "no" (set to yes, if your editor is console app)
|
## Note: set to yes if external editor is a console application.
|
||||||
|
##
|
||||||
|
#use_console_editor = yes
|
||||||
#
|
#
|
||||||
##### colors definitions #####
|
##### colors definitions #####
|
||||||
#
|
#
|
||||||
#colors_enabled = "yes"
|
#colors_enabled = yes
|
||||||
#
|
#
|
||||||
#empty_tag_color = "cyan"
|
#empty_tag_color = cyan
|
||||||
#
|
#
|
||||||
#header_window_color = "default"
|
#header_window_color = default
|
||||||
#
|
#
|
||||||
#volume_color = "default"
|
#volume_color = default
|
||||||
#
|
#
|
||||||
#state_line_color = "default"
|
#state_line_color = default
|
||||||
#
|
#
|
||||||
#state_flags_color = "default"
|
#state_flags_color = default
|
||||||
#
|
#
|
||||||
#main_window_color = "yellow"
|
#main_window_color = yellow
|
||||||
#
|
#
|
||||||
#color1 = "white"
|
#color1 = white
|
||||||
#
|
#
|
||||||
#color2 = "green"
|
#color2 = green
|
||||||
#
|
#
|
||||||
#main_window_highlight_color = "yellow"
|
#main_window_highlight_color = yellow
|
||||||
#
|
#
|
||||||
#progressbar_color = "default"
|
#progressbar_color = default
|
||||||
#
|
#
|
||||||
#progressbar_elapsed_color = "default"
|
#progressbar_elapsed_color = default
|
||||||
#
|
#
|
||||||
#statusbar_color = "default"
|
#statusbar_color = default
|
||||||
#
|
#
|
||||||
#alternative_ui_separator_color = "black"
|
#alternative_ui_separator_color = black
|
||||||
#
|
#
|
||||||
#active_column_color = "red"
|
#active_column_color = red
|
||||||
#
|
#
|
||||||
#visualizer_color = "yellow"
|
#visualizer_color = yellow
|
||||||
#
|
#
|
||||||
#window_border_color = "green"
|
#window_border_color = green
|
||||||
#
|
#
|
||||||
#active_window_border = "red"
|
#active_window_border = red
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -156,9 +156,6 @@ No need to describe it, huh?
|
|||||||
.B header_text_scrolling = yes/no
|
.B header_text_scrolling = yes/no
|
||||||
If enabled, text in header window will scroll if its length is longer then actual screen width, otherwise it won't.
|
If enabled, text in header window will scroll if its length is longer then actual screen width, otherwise it won't.
|
||||||
.TP
|
.TP
|
||||||
.B fancy_scrolling = yes/no
|
|
||||||
If enabled, content of other columns will be updated immediately while scrolling, otherwise only after you stop scrolling.
|
|
||||||
.TP
|
|
||||||
.B cyclic_scrolling = yes/no
|
.B cyclic_scrolling = yes/no
|
||||||
If enabled, cyclic scrolling is used (e.g. if you press down arrow being at the end of list, it'll take you to the beginning)
|
If enabled, cyclic scrolling is used (e.g. if you press down arrow being at the end of list, it'll take you to the beginning)
|
||||||
.TP
|
.TP
|
||||||
@@ -243,8 +240,8 @@ If set to yes, it will be possible to physically delete files and directories fr
|
|||||||
.B lastfm_preferred_language = ISO 639 alpha-2 language code
|
.B lastfm_preferred_language = ISO 639 alpha-2 language code
|
||||||
If set, ncmpcpp will try to get info from last.fm in language you set and if it fails, it will fall back to english. Otherwise it will use english the first time.
|
If set, ncmpcpp will try to get info from last.fm in language you set and if it fails, it will fall back to english. Otherwise it will use english the first time.
|
||||||
.TP
|
.TP
|
||||||
.B ncmpc_like_songs_adding = yes/no
|
.B space_add_mode = add_remove/always_add
|
||||||
If enabled, pressing space on item, which is already in playlist will remove it, otherwise add it again.
|
If set to add_remove, pressing space on item which is already in playlist will remove it, otherwise add it again.
|
||||||
.TP
|
.TP
|
||||||
.B show_hidden_files_in_local_browser = yes/no
|
.B show_hidden_files_in_local_browser = yes/no
|
||||||
Trigger for displaying in local browser files and directories that begin with '.'
|
Trigger for displaying in local browser files and directories that begin with '.'
|
||||||
@@ -309,8 +306,8 @@ Type of currently used regular expressions.
|
|||||||
.B user_interface = classic/alternative
|
.B user_interface = classic/alternative
|
||||||
Default user interface used by ncmpcpp at start.
|
Default user interface used by ncmpcpp at start.
|
||||||
.TP
|
.TP
|
||||||
.B media_library_left_column = a/y/g/c/p
|
.B media_library_primary_tag = artist/date/genre/composer/performer
|
||||||
Default tag type for left column in media library. Legend for possible letters is in SONG FORMAT section.
|
Default tag type for leftmost column in media library.
|
||||||
.TP
|
.TP
|
||||||
.B empty_tag_marker = TEXT
|
.B empty_tag_marker = TEXT
|
||||||
Text that will be displayed, if requested tag is not set.
|
Text that will be displayed, if requested tag is not set.
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ bin_PROGRAMS = ncmpcpp
|
|||||||
ncmpcpp_SOURCES = \
|
ncmpcpp_SOURCES = \
|
||||||
utility/comparators.cpp \
|
utility/comparators.cpp \
|
||||||
utility/html.cpp \
|
utility/html.cpp \
|
||||||
|
utility/option_parser.cpp \
|
||||||
utility/string.cpp \
|
utility/string.cpp \
|
||||||
utility/type_conversions.cpp \
|
utility/type_conversions.cpp \
|
||||||
utility/wide_string.cpp \
|
utility/wide_string.cpp \
|
||||||
@@ -10,9 +11,10 @@ ncmpcpp_SOURCES = \
|
|||||||
browser.cpp \
|
browser.cpp \
|
||||||
charset.cpp \
|
charset.cpp \
|
||||||
clock.cpp \
|
clock.cpp \
|
||||||
cmdargs.cpp \
|
configuration.cpp \
|
||||||
curl_handle.cpp \
|
curl_handle.cpp \
|
||||||
display.cpp \
|
display.cpp \
|
||||||
|
enums.cpp \
|
||||||
error.cpp \
|
error.cpp \
|
||||||
global.cpp \
|
global.cpp \
|
||||||
help.cpp \
|
help.cpp \
|
||||||
@@ -56,7 +58,9 @@ ncmpcpp_LDFLAGS = $(all_libraries)
|
|||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
utility/comparators.h \
|
utility/comparators.h \
|
||||||
utility/conversion.h \
|
utility/conversion.h \
|
||||||
|
utility/functional.h \
|
||||||
utility/html.h \
|
utility/html.h \
|
||||||
|
utility/option_parser.h \
|
||||||
utility/string.h \
|
utility/string.h \
|
||||||
utility/type_conversions.h \
|
utility/type_conversions.h \
|
||||||
utility/wide_string.h \
|
utility/wide_string.h \
|
||||||
@@ -64,9 +68,10 @@ noinst_HEADERS = \
|
|||||||
browser.h \
|
browser.h \
|
||||||
charset.h \
|
charset.h \
|
||||||
clock.h \
|
clock.h \
|
||||||
cmdargs.h \
|
configuration.h \
|
||||||
curl_handle.h \
|
curl_handle.h \
|
||||||
display.h \
|
display.h \
|
||||||
|
enums.h \
|
||||||
error.h \
|
error.h \
|
||||||
exec_item.h \
|
exec_item.h \
|
||||||
global.h \
|
global.h \
|
||||||
|
|||||||
249
src/actions.cpp
249
src/actions.cpp
@@ -198,7 +198,7 @@ void resizeScreen(bool reload_main_window)
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
MainHeight = LINES-(Config.new_design ? 7 : 4);
|
MainHeight = LINES-(Config.design == Design::Alternative ? 7 : 4);
|
||||||
|
|
||||||
validateScreenSize();
|
validateScreenSize();
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@ void resizeScreen(bool reload_main_window)
|
|||||||
|
|
||||||
applyToVisibleWindows(&BaseScreen::resize);
|
applyToVisibleWindows(&BaseScreen::resize);
|
||||||
|
|
||||||
if (Config.header_visibility || Config.new_design)
|
if (Config.header_visibility || Config.design == Design::Alternative)
|
||||||
wHeader->resize(COLS, HeaderHeight);
|
wHeader->resize(COLS, HeaderHeight);
|
||||||
|
|
||||||
FooterStartY = LINES-(Config.statusbar_visibility ? 2 : 1);
|
FooterStartY = LINES-(Config.statusbar_visibility ? 2 : 1);
|
||||||
@@ -236,8 +236,8 @@ void setWindowsDimensions()
|
|||||||
using Global::MainStartY;
|
using Global::MainStartY;
|
||||||
using Global::MainHeight;
|
using Global::MainHeight;
|
||||||
|
|
||||||
MainStartY = Config.new_design ? 5 : 2;
|
MainStartY = Config.design == Design::Alternative ? 5 : 2;
|
||||||
MainHeight = LINES-(Config.new_design ? 7 : 4);
|
MainHeight = LINES-(Config.design == Design::Alternative ? 7 : 4);
|
||||||
|
|
||||||
if (!Config.header_visibility)
|
if (!Config.header_visibility)
|
||||||
{
|
{
|
||||||
@@ -247,7 +247,7 @@ void setWindowsDimensions()
|
|||||||
if (!Config.statusbar_visibility)
|
if (!Config.statusbar_visibility)
|
||||||
++MainHeight;
|
++MainHeight;
|
||||||
|
|
||||||
HeaderHeight = Config.new_design ? (Config.header_visibility ? 5 : 3) : 1;
|
HeaderHeight = Config.design == Design::Alternative ? (Config.header_visibility ? 5 : 3) : 1;
|
||||||
FooterStartY = LINES-(Config.statusbar_visibility ? 2 : 1);
|
FooterStartY = LINES-(Config.statusbar_visibility ? 2 : 1);
|
||||||
FooterHeight = Config.statusbar_visibility ? 2 : 1;
|
FooterHeight = Config.statusbar_visibility ? 2 : 1;
|
||||||
}
|
}
|
||||||
@@ -337,15 +337,16 @@ void MouseEvent::run()
|
|||||||
myPlaylist->currentSongLength()*m_mouse_event.x/double(COLS));
|
myPlaylist->currentSongLength()*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.design == Design::Alternative)
|
||||||
&& Status::State::player() != MPD::psStop
|
&& Status::State::player() != MPD::psStop
|
||||||
&& m_mouse_event.y == (Config.new_design ? 1 : LINES-1) && m_mouse_event.x < 9
|
&& m_mouse_event.y == (Config.design == Design::Alternative ? 1 : LINES-1)
|
||||||
|
&& m_mouse_event.x < 9
|
||||||
) // playing/paused
|
) // playing/paused
|
||||||
{
|
{
|
||||||
Mpd.Toggle();
|
Mpd.Toggle();
|
||||||
}
|
}
|
||||||
else if ((m_mouse_event.bstate & BUTTON2_PRESSED || m_mouse_event.bstate & BUTTON4_PRESSED)
|
else if ((m_mouse_event.bstate & BUTTON2_PRESSED || m_mouse_event.bstate & BUTTON4_PRESSED)
|
||||||
&& (Config.header_visibility || Config.new_design)
|
&& (Config.header_visibility || Config.design == Design::Alternative)
|
||||||
&& m_mouse_event.y == 0 && size_t(m_mouse_event.x) > COLS-VolumeState.length()
|
&& m_mouse_event.y == 0 && size_t(m_mouse_event.x) > COLS-VolumeState.length()
|
||||||
) // volume
|
) // volume
|
||||||
{
|
{
|
||||||
@@ -488,15 +489,24 @@ void MoveEnd::run()
|
|||||||
|
|
||||||
void ToggleInterface::run()
|
void ToggleInterface::run()
|
||||||
{
|
{
|
||||||
Config.new_design = !Config.new_design;
|
switch (Config.design)
|
||||||
Config.statusbar_visibility = Config.new_design ? 0 : OriginalStatusbarVisibility;
|
{
|
||||||
|
case Design::Classic:
|
||||||
|
Config.design = Design::Alternative;
|
||||||
|
Config.statusbar_visibility = false;
|
||||||
|
break;
|
||||||
|
case Design::Alternative:
|
||||||
|
Config.design = Design::Classic;
|
||||||
|
Config.statusbar_visibility = OriginalStatusbarVisibility;
|
||||||
|
break;
|
||||||
|
}
|
||||||
setWindowsDimensions();
|
setWindowsDimensions();
|
||||||
Progressbar::unlock();
|
Progressbar::unlock();
|
||||||
Statusbar::unlock();
|
Statusbar::unlock();
|
||||||
resizeScreen(false);
|
resizeScreen(false);
|
||||||
Status::Changes::mixer();
|
Status::Changes::mixer();
|
||||||
Status::Changes::elapsedTime(false);
|
Status::Changes::elapsedTime(false);
|
||||||
Statusbar::printf("User interface: %1%", Config.new_design ? "Alternative" : "Classic");
|
Statusbar::printf("User interface: %1%", Config.design);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JumpToParentDirectory::canBeRun() const
|
bool JumpToParentDirectory::canBeRun() const
|
||||||
@@ -606,13 +616,13 @@ void SlaveScreen::run()
|
|||||||
|
|
||||||
void VolumeUp::run()
|
void VolumeUp::run()
|
||||||
{
|
{
|
||||||
int volume = std::min(Status::State::volume()+Config.volume_change_step, 100);
|
int volume = std::min(Status::State::volume()+Config.volume_change_step, 100u);
|
||||||
Mpd.SetVolume(volume);
|
Mpd.SetVolume(volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VolumeDown::run()
|
void VolumeDown::run()
|
||||||
{
|
{
|
||||||
int volume = std::max(Status::State::volume()-Config.volume_change_step, 0);
|
int volume = std::max(int(Status::State::volume()-Config.volume_change_step), 0);
|
||||||
Mpd.SetVolume(volume);
|
Mpd.SetVolume(volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -999,52 +1009,83 @@ void ToggleDisplayMode::run()
|
|||||||
{
|
{
|
||||||
if (myScreen == myPlaylist)
|
if (myScreen == myPlaylist)
|
||||||
{
|
{
|
||||||
Config.columns_in_playlist = !Config.columns_in_playlist;
|
switch (Config.playlist_display_mode)
|
||||||
Statusbar::printf("Playlist display mode: %1%",
|
|
||||||
Config.columns_in_playlist ? "Columns" : "Classic"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (Config.columns_in_playlist)
|
|
||||||
{
|
{
|
||||||
myPlaylist->main().setItemDisplayer(boost::bind(Display::SongsInColumns, _1, myPlaylist->proxySongList()));
|
case DisplayMode::Classic:
|
||||||
if (Config.titles_visibility)
|
Config.playlist_display_mode = DisplayMode::Columns;
|
||||||
myPlaylist->main().setTitle(Display::Columns(myPlaylist->main().getWidth()));
|
myPlaylist->main().setItemDisplayer(boost::bind(
|
||||||
else
|
Display::SongsInColumns, _1, myPlaylist->proxySongList()
|
||||||
|
));
|
||||||
|
if (Config.titles_visibility)
|
||||||
|
myPlaylist->main().setTitle(Display::Columns(myPlaylist->main().getWidth()));
|
||||||
|
else
|
||||||
|
myPlaylist->main().setTitle("");
|
||||||
|
break;
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
Config.playlist_display_mode = DisplayMode::Classic;
|
||||||
|
myPlaylist->main().setItemDisplayer(boost::bind(
|
||||||
|
Display::Songs, _1, myPlaylist->proxySongList(), Config.song_list_format
|
||||||
|
));
|
||||||
myPlaylist->main().setTitle("");
|
myPlaylist->main().setTitle("");
|
||||||
}
|
}
|
||||||
else
|
Statusbar::printf("Playlist display mode: %1%", Config.playlist_display_mode);
|
||||||
{
|
|
||||||
myPlaylist->main().setItemDisplayer(boost::bind(Display::Songs, _1, myPlaylist->proxySongList(), Config.song_list_format));
|
|
||||||
myPlaylist->main().setTitle("");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (myScreen == myBrowser)
|
else if (myScreen == myBrowser)
|
||||||
{
|
{
|
||||||
Config.columns_in_browser = !Config.columns_in_browser;
|
switch (Config.browser_display_mode)
|
||||||
Statusbar::printf("Browser display mode: %1%",
|
{
|
||||||
Config.columns_in_browser ? "Columns" : "Classic"
|
case DisplayMode::Classic:
|
||||||
);
|
Config.browser_display_mode = DisplayMode::Columns;
|
||||||
myBrowser->main().setTitle(Config.columns_in_browser && Config.titles_visibility ? Display::Columns(myBrowser->main().getWidth()) : "");
|
if (Config.titles_visibility)
|
||||||
|
myBrowser->main().setTitle(Display::Columns(myBrowser->main().getWidth()));
|
||||||
|
else
|
||||||
|
myBrowser->main().setTitle("");
|
||||||
|
break;
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
Config.browser_display_mode = DisplayMode::Classic;
|
||||||
|
myBrowser->main().setTitle("");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Statusbar::printf("Browser display mode: %1%", Config.browser_display_mode);
|
||||||
}
|
}
|
||||||
else if (myScreen == mySearcher)
|
else if (myScreen == mySearcher)
|
||||||
{
|
{
|
||||||
Config.columns_in_search_engine = !Config.columns_in_search_engine;
|
switch (Config.search_engine_display_mode)
|
||||||
Statusbar::printf("Search engine display mode: %1%",
|
{
|
||||||
Config.columns_in_search_engine ? "Columns" : "Classic"
|
case DisplayMode::Classic:
|
||||||
);
|
Config.search_engine_display_mode = DisplayMode::Columns;
|
||||||
|
break;
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
Config.search_engine_display_mode = DisplayMode::Classic;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Statusbar::printf("Search engine display mode: %1%", Config.search_engine_display_mode);
|
||||||
if (mySearcher->main().size() > SearchEngine::StaticOptions)
|
if (mySearcher->main().size() > SearchEngine::StaticOptions)
|
||||||
mySearcher->main().setTitle(Config.columns_in_search_engine && Config.titles_visibility ? Display::Columns(mySearcher->main().getWidth()) : "");
|
mySearcher->main().setTitle(
|
||||||
|
Config.search_engine_display_mode == DisplayMode::Columns
|
||||||
|
&& Config.titles_visibility
|
||||||
|
? Display::Columns(mySearcher->main().getWidth())
|
||||||
|
: ""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else if (myScreen->isActiveWindow(myPlaylistEditor->Content))
|
else if (myScreen->isActiveWindow(myPlaylistEditor->Content))
|
||||||
{
|
{
|
||||||
Config.columns_in_playlist_editor = !Config.columns_in_playlist_editor;
|
switch (Config.playlist_editor_display_mode)
|
||||||
Statusbar::printf("Playlist editor display mode: %1%",
|
{
|
||||||
Config.columns_in_playlist_editor ? "Columns" : "Classic"
|
case DisplayMode::Classic:
|
||||||
);
|
Config.playlist_editor_display_mode = DisplayMode::Columns;
|
||||||
if (Config.columns_in_playlist_editor)
|
myPlaylistEditor->Content.setItemDisplayer(boost::bind(
|
||||||
myPlaylistEditor->Content.setItemDisplayer(boost::bind(Display::SongsInColumns, _1, myPlaylistEditor->contentProxyList()));
|
Display::SongsInColumns, _1, myPlaylistEditor->contentProxyList()
|
||||||
else
|
));
|
||||||
myPlaylistEditor->Content.setItemDisplayer(boost::bind(Display::Songs, _1, myPlaylistEditor->contentProxyList(), Config.song_list_format));
|
break;
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
Config.playlist_editor_display_mode = DisplayMode::Classic;
|
||||||
|
myPlaylistEditor->Content.setItemDisplayer(boost::bind(
|
||||||
|
Display::Songs, _1, myPlaylistEditor->contentProxyList(), Config.song_list_format
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Statusbar::printf("Playlist editor display mode: %1%", Config.playlist_editor_display_mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1688,7 +1729,7 @@ void AddSelectedItems::run()
|
|||||||
void CropMainPlaylist::run()
|
void CropMainPlaylist::run()
|
||||||
{
|
{
|
||||||
bool yes = true;
|
bool yes = true;
|
||||||
if (Config.ask_before_clearing_main_playlist)
|
if (Config.ask_before_clearing_playlists)
|
||||||
yes = askYesNoQuestion("Do you really want to crop main playlist?", Status::trace);
|
yes = askYesNoQuestion("Do you really want to crop main playlist?", Status::trace);
|
||||||
if (yes)
|
if (yes)
|
||||||
{
|
{
|
||||||
@@ -1707,7 +1748,7 @@ void CropPlaylist::run()
|
|||||||
assert(!myPlaylistEditor->Playlists.empty());
|
assert(!myPlaylistEditor->Playlists.empty());
|
||||||
std::string playlist = myPlaylistEditor->Playlists.current().value();
|
std::string playlist = myPlaylistEditor->Playlists.current().value();
|
||||||
bool yes = true;
|
bool yes = true;
|
||||||
if (Config.ask_before_clearing_main_playlist)
|
if (Config.ask_before_clearing_playlists)
|
||||||
yes = askYesNoQuestion(
|
yes = askYesNoQuestion(
|
||||||
boost::format("Do you really want to crop playlist \"%1%\"?") % playlist,
|
boost::format("Do you really want to crop playlist \"%1%\"?") % playlist,
|
||||||
Status::trace
|
Status::trace
|
||||||
@@ -1724,7 +1765,7 @@ void CropPlaylist::run()
|
|||||||
void ClearMainPlaylist::run()
|
void ClearMainPlaylist::run()
|
||||||
{
|
{
|
||||||
bool yes = true;
|
bool yes = true;
|
||||||
if (Config.ask_before_clearing_main_playlist)
|
if (Config.ask_before_clearing_playlists)
|
||||||
yes = askYesNoQuestion("Do you really want to clear main playlist?", Status::trace);
|
yes = askYesNoQuestion("Do you really want to clear main playlist?", Status::trace);
|
||||||
if (yes)
|
if (yes)
|
||||||
{
|
{
|
||||||
@@ -1747,7 +1788,7 @@ void ClearPlaylist::run()
|
|||||||
assert(!myPlaylistEditor->Playlists.empty());
|
assert(!myPlaylistEditor->Playlists.empty());
|
||||||
std::string playlist = myPlaylistEditor->Playlists.current().value();
|
std::string playlist = myPlaylistEditor->Playlists.current().value();
|
||||||
bool yes = true;
|
bool yes = true;
|
||||||
if (Config.ask_before_clearing_main_playlist)
|
if (Config.ask_before_clearing_playlists)
|
||||||
yes = askYesNoQuestion(
|
yes = askYesNoQuestion(
|
||||||
boost::format("Do you really want to clear playlist \"%1%\"?") % playlist,
|
boost::format("Do you really want to clear playlist \"%1%\"?") % playlist,
|
||||||
Status::trace
|
Status::trace
|
||||||
@@ -1937,10 +1978,19 @@ void ToggleSpaceMode::run()
|
|||||||
|
|
||||||
void ToggleAddMode::run()
|
void ToggleAddMode::run()
|
||||||
{
|
{
|
||||||
Config.ncmpc_like_songs_adding = !Config.ncmpc_like_songs_adding;
|
std::string mode_desc;
|
||||||
Statusbar::printf("Add mode: %1%",
|
switch (Config.space_add_mode)
|
||||||
Config.ncmpc_like_songs_adding ? "Add item to playlist or remove if already added" : "Always add item to playlist"
|
{
|
||||||
);
|
case SpaceAddMode::AddRemove:
|
||||||
|
Config.space_add_mode = SpaceAddMode::AlwaysAdd;
|
||||||
|
mode_desc = "Always add an item to playlist";
|
||||||
|
break;
|
||||||
|
case SpaceAddMode::AlwaysAdd:
|
||||||
|
Config.space_add_mode = SpaceAddMode::AddRemove;
|
||||||
|
mode_desc = "Add an item to playlist or remove if already added";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Statusbar::printf("Add mode: %1%", mode_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToggleMouse::run()
|
void ToggleMouse::run()
|
||||||
@@ -2008,16 +2058,16 @@ void ToggleBrowserSortMode::run()
|
|||||||
{
|
{
|
||||||
switch (Config.browser_sort_mode)
|
switch (Config.browser_sort_mode)
|
||||||
{
|
{
|
||||||
case smName:
|
case SortMode::Name:
|
||||||
Config.browser_sort_mode = smMTime;
|
Config.browser_sort_mode = SortMode::ModificationTime;
|
||||||
Statusbar::print("Sort songs by: Modification time");
|
Statusbar::print("Sort songs by: Modification time");
|
||||||
break;
|
break;
|
||||||
case smMTime:
|
case SortMode::ModificationTime:
|
||||||
Config.browser_sort_mode = smCustomFormat;
|
Config.browser_sort_mode = SortMode::CustomFormat;
|
||||||
Statusbar::print("Sort songs by: Custom format");
|
Statusbar::print("Sort songs by: Custom format");
|
||||||
break;
|
break;
|
||||||
case smCustomFormat:
|
case SortMode::CustomFormat:
|
||||||
Config.browser_sort_mode = smName;
|
Config.browser_sort_mode = SortMode::Name;
|
||||||
Statusbar::print("Sort songs by: Name");
|
Statusbar::print("Sort songs by: Name");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2211,13 +2261,12 @@ void NextScreen::run()
|
|||||||
if (auto tababble = dynamic_cast<Tabbable *>(myScreen))
|
if (auto tababble = dynamic_cast<Tabbable *>(myScreen))
|
||||||
tababble->switchToPreviousScreen();
|
tababble->switchToPreviousScreen();
|
||||||
}
|
}
|
||||||
else if (!Config.screens_seq.empty())
|
else if (!Config.screen_sequence.empty())
|
||||||
{
|
{
|
||||||
auto screen_type = std::find(Config.screens_seq.begin(), Config.screens_seq.end(),
|
const auto &seq = Config.screen_sequence;
|
||||||
myScreen->type()
|
auto screen_type = std::find(seq.begin(), seq.end(), myScreen->type());
|
||||||
);
|
if (++screen_type == seq.end())
|
||||||
if (++screen_type == Config.screens_seq.end())
|
toScreen(seq.front())->switchTo();
|
||||||
toScreen(Config.screens_seq.front())->switchTo();
|
|
||||||
else
|
else
|
||||||
toScreen(*screen_type)->switchTo();
|
toScreen(*screen_type)->switchTo();
|
||||||
}
|
}
|
||||||
@@ -2230,13 +2279,12 @@ void PreviousScreen::run()
|
|||||||
if (auto tababble = dynamic_cast<Tabbable *>(myScreen))
|
if (auto tababble = dynamic_cast<Tabbable *>(myScreen))
|
||||||
tababble->switchToPreviousScreen();
|
tababble->switchToPreviousScreen();
|
||||||
}
|
}
|
||||||
else if (!Config.screens_seq.empty())
|
else if (!Config.screen_sequence.empty())
|
||||||
{
|
{
|
||||||
auto screen_type = std::find(Config.screens_seq.begin(), Config.screens_seq.end(),
|
const auto &seq = Config.screen_sequence;
|
||||||
myScreen->type()
|
auto screen_type = std::find(seq.begin(), seq.end(), myScreen->type());
|
||||||
);
|
if (screen_type == seq.begin())
|
||||||
if (screen_type == Config.screens_seq.begin())
|
toScreen(seq.back())->switchTo();
|
||||||
toScreen(Config.screens_seq.back())->switchTo();
|
|
||||||
else
|
else
|
||||||
toScreen(*--screen_type)->switchTo();
|
toScreen(*--screen_type)->switchTo();
|
||||||
}
|
}
|
||||||
@@ -2635,34 +2683,35 @@ void seek()
|
|||||||
|
|
||||||
*wFooter << NC::Format::Bold;
|
*wFooter << NC::Format::Bold;
|
||||||
std::string tracklength;
|
std::string tracklength;
|
||||||
if (Config.new_design)
|
switch (Config.design)
|
||||||
{
|
{
|
||||||
if (Config.display_remaining_time)
|
case Design::Classic:
|
||||||
{
|
tracklength = " [";
|
||||||
tracklength = "-";
|
if (Config.display_remaining_time)
|
||||||
tracklength += MPD::Song::ShowTime(myPlaylist->currentSongLength()-songpos);
|
{
|
||||||
}
|
tracklength += "-";
|
||||||
else
|
tracklength += MPD::Song::ShowTime(myPlaylist->currentSongLength()-songpos);
|
||||||
tracklength = MPD::Song::ShowTime(songpos);
|
}
|
||||||
tracklength += "/";
|
else
|
||||||
tracklength += MPD::Song::ShowTime(myPlaylist->currentSongLength());
|
tracklength += MPD::Song::ShowTime(songpos);
|
||||||
*wHeader << NC::XY(0, 0) << tracklength << " ";
|
tracklength += "/";
|
||||||
wHeader->refresh();
|
tracklength += MPD::Song::ShowTime(myPlaylist->currentSongLength());
|
||||||
}
|
tracklength += "]";
|
||||||
else
|
*wFooter << NC::XY(wFooter->getWidth()-tracklength.length(), 1) << tracklength;
|
||||||
{
|
break;
|
||||||
tracklength = " [";
|
case Design::Alternative:
|
||||||
if (Config.display_remaining_time)
|
if (Config.display_remaining_time)
|
||||||
{
|
{
|
||||||
tracklength += "-";
|
tracklength = "-";
|
||||||
tracklength += MPD::Song::ShowTime(myPlaylist->currentSongLength()-songpos);
|
tracklength += MPD::Song::ShowTime(myPlaylist->currentSongLength()-songpos);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tracklength += MPD::Song::ShowTime(songpos);
|
tracklength = MPD::Song::ShowTime(songpos);
|
||||||
tracklength += "/";
|
tracklength += "/";
|
||||||
tracklength += MPD::Song::ShowTime(myPlaylist->currentSongLength());
|
tracklength += MPD::Song::ShowTime(myPlaylist->currentSongLength());
|
||||||
tracklength += "]";
|
*wHeader << NC::XY(0, 0) << tracklength << " ";
|
||||||
*wFooter << NC::XY(wFooter->getWidth()-tracklength.length(), 1) << tracklength;
|
wHeader->refresh();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
*wFooter << NC::Format::NoBold;
|
*wFooter << NC::Format::NoBold;
|
||||||
Progressbar::draw(songpos, myPlaylist->currentSongLength());
|
Progressbar::draw(songpos, myPlaylist->currentSongLength());
|
||||||
|
|||||||
@@ -99,10 +99,6 @@ struct Binding
|
|||||||
return m_actions[0];
|
return m_actions[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
const ActionChain &actions() const {
|
|
||||||
return m_actions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ActionChain m_actions;
|
ActionChain m_actions;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
#include "tags.h"
|
#include "tags.h"
|
||||||
#include "utility/comparators.h"
|
#include "utility/comparators.h"
|
||||||
#include "utility/string.h"
|
#include "utility/string.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
using Global::MainHeight;
|
using Global::MainHeight;
|
||||||
using Global::MainStartY;
|
using Global::MainStartY;
|
||||||
@@ -49,6 +50,8 @@ using MPD::itDirectory;
|
|||||||
using MPD::itSong;
|
using MPD::itSong;
|
||||||
using MPD::itPlaylist;
|
using MPD::itPlaylist;
|
||||||
|
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
Browser *myBrowser;
|
Browser *myBrowser;
|
||||||
|
|
||||||
namespace {//
|
namespace {//
|
||||||
@@ -63,7 +66,7 @@ bool BrowserEntryMatcher(const boost::regex &rx, const MPD::Item &item, bool fil
|
|||||||
|
|
||||||
Browser::Browser() : itsBrowseLocally(0), itsScrollBeginning(0), itsBrowsedDir("/")
|
Browser::Browser() : itsBrowseLocally(0), itsScrollBeginning(0), itsBrowsedDir("/")
|
||||||
{
|
{
|
||||||
w = NC::Menu<MPD::Item>(0, MainStartY, COLS, MainHeight, Config.columns_in_browser && Config.titles_visibility ? Display::Columns(COLS) : "", Config.main_color, NC::Border::None);
|
w = NC::Menu<MPD::Item>(0, MainStartY, COLS, MainHeight, Config.browser_display_mode == DisplayMode::Columns && Config.titles_visibility ? Display::Columns(COLS) : "", Config.main_color, NC::Border::None);
|
||||||
w.setHighlightColor(Config.main_highlight_color);
|
w.setHighlightColor(Config.main_highlight_color);
|
||||||
w.cyclicScrolling(Config.use_cyclic_scrolling);
|
w.cyclicScrolling(Config.use_cyclic_scrolling);
|
||||||
w.centeredCursor(Config.centered_cursor);
|
w.centeredCursor(Config.centered_cursor);
|
||||||
@@ -78,7 +81,18 @@ void Browser::resize()
|
|||||||
getWindowResizeParams(x_offset, width);
|
getWindowResizeParams(x_offset, width);
|
||||||
w.resize(width, MainHeight);
|
w.resize(width, MainHeight);
|
||||||
w.moveTo(x_offset, MainStartY);
|
w.moveTo(x_offset, MainStartY);
|
||||||
w.setTitle(Config.columns_in_browser && Config.titles_visibility ? Display::Columns(w.getWidth()) : "");
|
switch (Config.browser_display_mode)
|
||||||
|
{
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
if (Config.titles_visibility)
|
||||||
|
{
|
||||||
|
w.setTitle(Display::Columns(w.getWidth()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DisplayMode::Classic:
|
||||||
|
w.setTitle("");
|
||||||
|
break;
|
||||||
|
}
|
||||||
hasToBeResized = 0;
|
hasToBeResized = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +111,7 @@ void Browser::switchTo()
|
|||||||
std::wstring Browser::title()
|
std::wstring Browser::title()
|
||||||
{
|
{
|
||||||
std::wstring result = L"Browse: ";
|
std::wstring result = L"Browse: ";
|
||||||
result += Scroller(ToWString(itsBrowsedDir), itsScrollBeginning, COLS-result.length()-(Config.new_design ? 2 : Global::VolumeState.length()));
|
result += Scroller(ToWString(itsBrowsedDir), itsScrollBeginning, COLS-result.length()-(Config.design == Design::Alternative ? 2 : Global::VolumeState.length()));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,8 +480,6 @@ void Browser::GetDirectory(std::string dir, std::string subdir)
|
|||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
void Browser::GetLocalDirectory(MPD::ItemList &v, const std::string &directory, bool recursively) const
|
void Browser::GetLocalDirectory(MPD::ItemList &v, const std::string &directory, bool recursively) const
|
||||||
{
|
{
|
||||||
namespace fs = boost::filesystem;
|
|
||||||
|
|
||||||
size_t start_size = v.size();
|
size_t start_size = v.size();
|
||||||
fs::path dir(directory);
|
fs::path dir(directory);
|
||||||
std::for_each(fs::directory_iterator(dir), fs::directory_iterator(), [&](fs::directory_entry &e) {
|
std::for_each(fs::directory_iterator(dir), fs::directory_iterator(), [&](fs::directory_entry &e) {
|
||||||
@@ -511,8 +523,6 @@ void Browser::GetLocalDirectory(MPD::ItemList &v, const std::string &directory,
|
|||||||
|
|
||||||
void Browser::ClearDirectory(const std::string &path) const
|
void Browser::ClearDirectory(const std::string &path) const
|
||||||
{
|
{
|
||||||
namespace fs = boost::filesystem;
|
|
||||||
|
|
||||||
fs::path dir(path);
|
fs::path dir(path);
|
||||||
std::for_each(fs::directory_iterator(dir), fs::directory_iterator(), [&](fs::directory_entry &e) {
|
std::for_each(fs::directory_iterator(dir), fs::directory_iterator(), [&](fs::directory_entry &e) {
|
||||||
if (!fs::is_symlink(e) && fs::is_directory(e))
|
if (!fs::is_symlink(e) && fs::is_directory(e))
|
||||||
@@ -535,9 +545,15 @@ void Browser::ChangeBrowseMode()
|
|||||||
Statusbar::printf("Browse mode: %1%",
|
Statusbar::printf("Browse mode: %1%",
|
||||||
itsBrowseLocally ? "Local filesystem" : "MPD database"
|
itsBrowseLocally ? "Local filesystem" : "MPD database"
|
||||||
);
|
);
|
||||||
itsBrowsedDir = itsBrowseLocally ? Config.GetHomeDirectory() : "/";
|
if (itsBrowseLocally)
|
||||||
if (itsBrowseLocally && *itsBrowsedDir.rbegin() == '/')
|
{
|
||||||
itsBrowsedDir.resize(itsBrowsedDir.length()-1);
|
itsBrowsedDir = "~";
|
||||||
|
expand_home(itsBrowsedDir);
|
||||||
|
if (*itsBrowsedDir.rbegin() == '/')
|
||||||
|
itsBrowsedDir.resize(itsBrowsedDir.length()-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
itsBrowsedDir = "/";
|
||||||
w.reset();
|
w.reset();
|
||||||
GetDirectory(itsBrowsedDir);
|
GetDirectory(itsBrowsedDir);
|
||||||
drawHeader();
|
drawHeader();
|
||||||
@@ -605,10 +621,15 @@ std::string ItemToString(const MPD::Item &item)
|
|||||||
result = "[" + getBasename(item.name) + "]";
|
result = "[" + getBasename(item.name) + "]";
|
||||||
break;
|
break;
|
||||||
case MPD::itSong:
|
case MPD::itSong:
|
||||||
if (Config.columns_in_browser)
|
switch (Config.browser_display_mode)
|
||||||
result = item.song->toString(Config.song_in_columns_to_string_format, Config.tags_separator);
|
{
|
||||||
else
|
case DisplayMode::Classic:
|
||||||
result = item.song->toString(Config.song_list_format_dollar_free, Config.tags_separator);
|
result = item.song->toString(Config.song_list_format_dollar_free, Config.tags_separator);
|
||||||
|
break;
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
result = item.song->toString(Config.song_in_columns_to_string_format, Config.tags_separator);
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MPD::itPlaylist:
|
case MPD::itPlaylist:
|
||||||
result = Config.browser_playlist_prefix.str() + getBasename(item.name);
|
result = Config.browser_playlist_prefix.str() + getBasename(item.name);
|
||||||
|
|||||||
@@ -18,11 +18,12 @@
|
|||||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <boost/filesystem/operations.hpp>
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "bindings.h"
|
#include "bindings.h"
|
||||||
#include "cmdargs.h"
|
#include "configuration.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "mpdpp.h"
|
#include "mpdpp.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
@@ -36,25 +37,25 @@ namespace {
|
|||||||
|
|
||||||
const char *env_home;
|
const char *env_home;
|
||||||
|
|
||||||
void replace_tilda_with_home(std::string &s)
|
}
|
||||||
|
|
||||||
|
void expand_home(std::string &path)
|
||||||
{
|
{
|
||||||
if (!s.empty() && s[0] == '~')
|
if (!path.empty() && path[0] == '~')
|
||||||
s.replace(0, 1, env_home);
|
path.replace(0, 1, env_home);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
bool configure(int argc, char **argv)
|
||||||
|
|
||||||
bool ParseArguments(int argc, char **argv)
|
|
||||||
{
|
{
|
||||||
std::string bindings_path, config_path;
|
std::string bindings_path, config_path;
|
||||||
|
|
||||||
po::options_description desc("Options");
|
po::options_description options("Options");
|
||||||
desc.add_options()
|
options.add_options()
|
||||||
("host,h", po::value<std::string>()->default_value("localhost"), "connect to server at host")
|
("host,h", po::value<std::string>()->default_value("localhost"), "connect to server at host")
|
||||||
("port,p", po::value<int>()->default_value(6600), "connect to server at port")
|
("port,p", po::value<int>()->default_value(6600), "connect to server at port")
|
||||||
("config,c", po::value<std::string>(&config_path)->default_value("~/.ncmpcpp/config"), "specify configuration file")
|
("config,c", po::value<std::string>(&config_path)->default_value("~/.ncmpcpp/config"), "specify configuration file")
|
||||||
("bindigs,b", po::value<std::string>(&bindings_path)->default_value("~/.ncmpcpp/bindings"), "specify bindings file")
|
("bindigs,b", po::value<std::string>(&bindings_path)->default_value("~/.ncmpcpp/bindings"), "specify bindings file")
|
||||||
("screen,s", po::value<std::string>(), "specify the startup screen")
|
("screen,s", po::value<std::string>(), "specify initial screen")
|
||||||
("help,?", "show help message")
|
("help,?", "show help message")
|
||||||
("version,v", "display version information")
|
("version,v", "display version information")
|
||||||
;
|
;
|
||||||
@@ -62,11 +63,11 @@ bool ParseArguments(int argc, char **argv)
|
|||||||
po::variables_map vm;
|
po::variables_map vm;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
po::store(po::parse_command_line(argc, argv, options), vm);
|
||||||
|
|
||||||
if (vm.count("help"))
|
if (vm.count("help"))
|
||||||
{
|
{
|
||||||
cout << "Usage: " << argv[0] << " [options]...\n" << desc << "\n";
|
cout << "Usage: " << argv[0] << " [options]...\n" << options << "\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (vm.count("version"))
|
if (vm.count("version"))
|
||||||
@@ -119,30 +120,33 @@ bool ParseArguments(int argc, char **argv)
|
|||||||
|
|
||||||
po::notify(vm);
|
po::notify(vm);
|
||||||
|
|
||||||
|
// get home directory
|
||||||
env_home = getenv("HOME");
|
env_home = getenv("HOME");
|
||||||
if (env_home == nullptr)
|
if (env_home == nullptr)
|
||||||
{
|
{
|
||||||
cerr << "Fatal error: HOME environment variable is not defined\n";
|
cerr << "Fatal error: HOME environment variable is not defined\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
replace_tilda_with_home(config_path);
|
expand_home(config_path);
|
||||||
replace_tilda_with_home(bindings_path);
|
expand_home(bindings_path);
|
||||||
|
|
||||||
// read configuration
|
// read configuration
|
||||||
Config.SetDefaults();
|
if (Config.read(config_path) == false)
|
||||||
Config.Read(config_path);
|
exit(1);
|
||||||
Config.GenerateColumns();
|
|
||||||
|
|
||||||
// read bindings
|
// read bindings
|
||||||
if (Bindings.read(bindings_path) == false)
|
if (Bindings.read(bindings_path) == false)
|
||||||
return false;
|
exit(1);
|
||||||
Bindings.generateDefaults();
|
Bindings.generateDefaults();
|
||||||
|
|
||||||
|
// create directories
|
||||||
|
boost::filesystem::create_directory(Config.ncmpcpp_directory);
|
||||||
|
boost::filesystem::create_directory(Config.lyrics_directory);
|
||||||
|
|
||||||
// try to get MPD connection details from environment variables
|
// try to get MPD connection details from environment variables
|
||||||
// as they take precedence over these from the configuration.
|
// as they take precedence over these from the configuration.
|
||||||
auto env_host = getenv("MPD_HOST");
|
auto env_host = getenv("MPD_HOST");
|
||||||
auto env_port = getenv("MPD_PORT");
|
auto env_port = getenv("MPD_PORT");
|
||||||
|
|
||||||
if (env_host != nullptr)
|
if (env_host != nullptr)
|
||||||
Mpd.SetHostname(env_host);
|
Mpd.SetHostname(env_host);
|
||||||
if (env_port != nullptr)
|
if (env_port != nullptr)
|
||||||
@@ -150,10 +154,11 @@ bool ParseArguments(int argc, char **argv)
|
|||||||
|
|
||||||
// if MPD connection details are provided as command line
|
// if MPD connection details are provided as command line
|
||||||
// parameters, use them as their priority is the highest.
|
// parameters, use them as their priority is the highest.
|
||||||
if (vm.count("host"))
|
if (!vm["host"].defaulted())
|
||||||
Mpd.SetHostname(vm["host"].as<std::string>());
|
Mpd.SetHostname(vm["host"].as<std::string>());
|
||||||
if (vm.count("port"))
|
if (!vm["port"].defaulted())
|
||||||
Mpd.SetPort(vm["port"].as<int>());
|
Mpd.SetPort(vm["port"].as<int>());
|
||||||
|
Mpd.SetTimeout(Config.mpd_connection_timeout);
|
||||||
|
|
||||||
// custom startup screen
|
// custom startup screen
|
||||||
if (vm.count("screen"))
|
if (vm.count("screen"))
|
||||||
@@ -162,15 +167,15 @@ bool ParseArguments(int argc, char **argv)
|
|||||||
Config.startup_screen_type = stringtoStartupScreenType(screen);
|
Config.startup_screen_type = stringtoStartupScreenType(screen);
|
||||||
if (Config.startup_screen_type == ScreenType::Unknown)
|
if (Config.startup_screen_type == ScreenType::Unknown)
|
||||||
{
|
{
|
||||||
std::cerr << "Invalid screen: " << screen << "\n";
|
std::cerr << "Unknown screen: " << screen << "\n";
|
||||||
return false;
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception &e)
|
catch (std::exception &e)
|
||||||
{
|
{
|
||||||
cerr << "Error while parsing command line options: " << e.what() << "\n";
|
cerr << "Error while processing configuration: " << e.what() << "\n";
|
||||||
return false;
|
exit(1);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -18,9 +18,11 @@
|
|||||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef NCMPCPP_CMDARGS_H
|
#ifndef NCMPCPP_CONFIGURATION_H
|
||||||
#define NCMPCPP_CMDARGS_H
|
#define NCMPCPP_CONFIGURATION_H
|
||||||
|
|
||||||
bool ParseArguments(int argc, char **argv);
|
void expand_home(std::string &path);
|
||||||
|
|
||||||
#endif // NCMPCPP_CMDARGS_H
|
bool configure(int argc, char **argv);
|
||||||
|
|
||||||
|
#endif // NCMPCPP_CONFIGURATION_H
|
||||||
@@ -392,10 +392,15 @@ void Display::Items(NC::Menu<MPD::Item> &menu, const ProxySongList &pl)
|
|||||||
<< "]";
|
<< "]";
|
||||||
break;
|
break;
|
||||||
case MPD::itSong:
|
case MPD::itSong:
|
||||||
if (!Config.columns_in_browser)
|
switch (Config.browser_display_mode)
|
||||||
showSongs(menu, *item.song, pl, Config.song_list_format);
|
{
|
||||||
else
|
case DisplayMode::Classic:
|
||||||
showSongsInColumns(menu, *item.song, pl);
|
showSongs(menu, *item.song, pl, Config.song_list_format);
|
||||||
|
break;
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
showSongsInColumns(menu, *item.song, pl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MPD::itPlaylist:
|
case MPD::itPlaylist:
|
||||||
menu << Config.browser_playlist_prefix
|
menu << Config.browser_playlist_prefix
|
||||||
@@ -409,10 +414,15 @@ void Display::SEItems(NC::Menu<SEItem> &menu, const ProxySongList &pl)
|
|||||||
const SEItem &si = menu.drawn()->value();
|
const SEItem &si = menu.drawn()->value();
|
||||||
if (si.isSong())
|
if (si.isSong())
|
||||||
{
|
{
|
||||||
if (!Config.columns_in_search_engine)
|
switch (Config.search_engine_display_mode)
|
||||||
showSongs(menu, si.song(), pl, Config.song_list_format);
|
{
|
||||||
else
|
case DisplayMode::Classic:
|
||||||
showSongsInColumns(menu, si.song(), pl);
|
showSongs(menu, si.song(), pl, Config.song_list_format);
|
||||||
|
break;
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
showSongsInColumns(menu, si.song(), pl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
menu << si.buffer();
|
menu << si.buffer();
|
||||||
|
|||||||
134
src/enums.cpp
Normal file
134
src/enums.cpp
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008-2014 by Andrzej Rybczak *
|
||||||
|
* electricityispower@gmail.com *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "enums.h"
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, SpaceAddMode sam)
|
||||||
|
{
|
||||||
|
switch (sam)
|
||||||
|
{
|
||||||
|
case SpaceAddMode::AddRemove:
|
||||||
|
os << "add_remove";
|
||||||
|
break;
|
||||||
|
case SpaceAddMode::AlwaysAdd:
|
||||||
|
os << "always_add";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream &operator>>(std::istream &is, SpaceAddMode &sam)
|
||||||
|
{
|
||||||
|
std::string ssam;
|
||||||
|
is >> ssam;
|
||||||
|
if (ssam == "add_remove")
|
||||||
|
sam = SpaceAddMode::AddRemove;
|
||||||
|
else if (ssam == "always_add")
|
||||||
|
sam = SpaceAddMode::AlwaysAdd;
|
||||||
|
else
|
||||||
|
is.setstate(std::ios::failbit);
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, SortMode sm)
|
||||||
|
{
|
||||||
|
switch (sm)
|
||||||
|
{
|
||||||
|
case SortMode::Name:
|
||||||
|
os << "name";
|
||||||
|
break;
|
||||||
|
case SortMode::ModificationTime:
|
||||||
|
os << "mtime";
|
||||||
|
break;
|
||||||
|
case SortMode::CustomFormat:
|
||||||
|
os << "format";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream &operator>>(std::istream &is, SortMode &sm)
|
||||||
|
{
|
||||||
|
std::string ssm;
|
||||||
|
is >> ssm;
|
||||||
|
if (ssm == "name")
|
||||||
|
sm = SortMode::Name;
|
||||||
|
else if (ssm == "mtime")
|
||||||
|
sm = SortMode::ModificationTime;
|
||||||
|
else if (ssm == "format")
|
||||||
|
sm = SortMode::CustomFormat;
|
||||||
|
else
|
||||||
|
is.setstate(std::ios::failbit);
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, DisplayMode dm)
|
||||||
|
{
|
||||||
|
switch (dm)
|
||||||
|
{
|
||||||
|
case DisplayMode::Classic:
|
||||||
|
os << "classic";
|
||||||
|
break;
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
os << "columns";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream &operator>>(std::istream &is, DisplayMode &dm)
|
||||||
|
{
|
||||||
|
std::string sdm;
|
||||||
|
is >> sdm;
|
||||||
|
if (sdm == "classic")
|
||||||
|
dm = DisplayMode::Classic;
|
||||||
|
else if (sdm == "columns")
|
||||||
|
dm = DisplayMode::Columns;
|
||||||
|
else
|
||||||
|
is.setstate(std::ios::failbit);
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, Design ui)
|
||||||
|
{
|
||||||
|
switch (ui)
|
||||||
|
{
|
||||||
|
case Design::Classic:
|
||||||
|
os << "classic";
|
||||||
|
break;
|
||||||
|
case Design::Alternative:
|
||||||
|
os << "alternative";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream &operator>>(std::istream &is, Design &ui)
|
||||||
|
{
|
||||||
|
std::string sui;
|
||||||
|
is >> sui;
|
||||||
|
if (sui == "classic")
|
||||||
|
ui = Design::Classic;
|
||||||
|
else if (sui == "alternative")
|
||||||
|
ui = Design::Alternative;
|
||||||
|
else
|
||||||
|
is.setstate(std::ios::failbit);
|
||||||
|
return is;
|
||||||
|
}
|
||||||
42
src/enums.h
Normal file
42
src/enums.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008-2014 by Andrzej Rybczak *
|
||||||
|
* electricityispower@gmail.com *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef NCMPCPP_ENUMS_H
|
||||||
|
#define NCMPCPP_ENUMS_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
enum class SpaceAddMode { AddRemove, AlwaysAdd };
|
||||||
|
std::ostream &operator<<(std::ostream &os, SpaceAddMode sam);
|
||||||
|
std::istream &operator>>(std::istream &is, SpaceAddMode &sam);
|
||||||
|
|
||||||
|
enum class SortMode { Name, ModificationTime, CustomFormat };
|
||||||
|
std::ostream &operator<<(std::ostream &os, SortMode sm);
|
||||||
|
std::istream &operator>>(std::istream &is, SortMode &sm);
|
||||||
|
|
||||||
|
enum class DisplayMode { Classic, Columns };
|
||||||
|
std::ostream &operator<<(std::ostream &os, DisplayMode dm);
|
||||||
|
std::istream &operator>>(std::istream &is, DisplayMode &dm);
|
||||||
|
|
||||||
|
enum class Design { Classic, Alternative };
|
||||||
|
std::ostream &operator<<(std::ostream &os, Design ui);
|
||||||
|
std::istream &operator>>(std::istream &is, Design &ui);
|
||||||
|
|
||||||
|
#endif // NCMPCPP_ENUMS_H
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
bool addSongToPlaylist(const MPD::Song &s, bool play, int position)
|
bool addSongToPlaylist(const MPD::Song &s, bool play, int position)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (Config.ncmpc_like_songs_adding && myPlaylist->checkForSong(s))
|
if (Config.space_add_mode == SpaceAddMode::AddRemove && myPlaylist->checkForSong(s))
|
||||||
{
|
{
|
||||||
auto &w = myPlaylist->main();
|
auto &w = myPlaylist->main();
|
||||||
if (play)
|
if (play)
|
||||||
|
|||||||
@@ -434,6 +434,14 @@ void stringToBuffer(const std::basic_string<CharT> &s, NC::BasicBuffer<CharT> &b
|
|||||||
stringToBuffer(s.begin(), s.end(), buf);
|
stringToBuffer(s.begin(), s.end(), buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename CharT>
|
||||||
|
NC::BasicBuffer<CharT> stringToBuffer(const std::basic_string<CharT> &s)
|
||||||
|
{
|
||||||
|
NC::BasicBuffer<CharT> result;
|
||||||
|
stringToBuffer(s, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T> void ShowTime(T &buf, size_t length, bool short_names)
|
template <typename T> void ShowTime(T &buf, size_t length, bool short_names)
|
||||||
{
|
{
|
||||||
const unsigned MINUTE = 60;
|
const unsigned MINUTE = 60;
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ void Lyrics::switchTo()
|
|||||||
std::wstring Lyrics::title()
|
std::wstring Lyrics::title()
|
||||||
{
|
{
|
||||||
std::wstring result = L"Lyrics: ";
|
std::wstring result = L"Lyrics: ";
|
||||||
result += Scroller(ToWString(itsSong.toString("{%a - %t}", ", ")), itsScrollBegin, COLS-result.length()-(Config.new_design ? 2 : Global::VolumeState.length()));
|
result += Scroller(ToWString(itsSong.toString("{%a - %t}", ", ")), itsScrollBegin, COLS-result.length()-(Config.design == Design::Alternative ? 2 : Global::VolumeState.length()));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,8 +314,6 @@ void Lyrics::Load()
|
|||||||
|
|
||||||
itsFilename = GenerateFilename(itsSong);
|
itsFilename = GenerateFilename(itsSong);
|
||||||
|
|
||||||
CreateDir(Config.lyrics_directory);
|
|
||||||
|
|
||||||
w.clear();
|
w.clear();
|
||||||
w.reset();
|
w.reset();
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
#include "bindings.h"
|
#include "bindings.h"
|
||||||
#include "browser.h"
|
#include "browser.h"
|
||||||
#include "charset.h"
|
#include "charset.h"
|
||||||
#include "cmdargs.h"
|
#include "configuration.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
@@ -101,12 +101,9 @@ int main(int argc, char **argv)
|
|||||||
std::setlocale(LC_ALL, "");
|
std::setlocale(LC_ALL, "");
|
||||||
std::locale::global(Charset::internalLocale());
|
std::locale::global(Charset::internalLocale());
|
||||||
|
|
||||||
if (!ParseArguments(argc, argv))
|
if (!configure(argc, argv))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Mpd.SetTimeout(Config.mpd_connection_timeout);
|
|
||||||
CreateDir(Config.ncmpcpp_directory);
|
|
||||||
|
|
||||||
// always execute these commands, even if ncmpcpp use exit function
|
// always execute these commands, even if ncmpcpp use exit function
|
||||||
atexit(do_at_exit);
|
atexit(do_at_exit);
|
||||||
|
|
||||||
@@ -122,7 +119,7 @@ int main(int argc, char **argv)
|
|||||||
if (!Config.titles_visibility)
|
if (!Config.titles_visibility)
|
||||||
wattron(stdscr, COLOR_PAIR(int(Config.main_color)));
|
wattron(stdscr, COLOR_PAIR(int(Config.main_color)));
|
||||||
|
|
||||||
if (Config.new_design)
|
if (Config.design == Design::Alternative)
|
||||||
Config.statusbar_visibility = 0;
|
Config.statusbar_visibility = 0;
|
||||||
|
|
||||||
Actions::setWindowsDimensions();
|
Actions::setWindowsDimensions();
|
||||||
@@ -130,7 +127,7 @@ int main(int argc, char **argv)
|
|||||||
Actions::initializeScreens();
|
Actions::initializeScreens();
|
||||||
|
|
||||||
wHeader = new NC::Window(0, 0, COLS, Actions::HeaderHeight, "", Config.header_color, NC::Border::None);
|
wHeader = new NC::Window(0, 0, COLS, Actions::HeaderHeight, "", Config.header_color, NC::Border::None);
|
||||||
if (Config.header_visibility || Config.new_design)
|
if (Config.header_visibility || Config.design == Design::Alternative)
|
||||||
wHeader->display();
|
wHeader->display();
|
||||||
|
|
||||||
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);
|
||||||
@@ -140,14 +137,14 @@ int main(int argc, char **argv)
|
|||||||
// initialize global timer
|
// initialize global timer
|
||||||
Timer = boost::posix_time::microsec_clock::local_time();
|
Timer = boost::posix_time::microsec_clock::local_time();
|
||||||
|
|
||||||
// go to playlist
|
// initialize playlist
|
||||||
myPlaylist->switchTo();
|
myPlaylist->switchTo();
|
||||||
|
|
||||||
// local variables
|
// local variables
|
||||||
Key input(0, Key::Standard);
|
Key input(0, Key::Standard);
|
||||||
boost::posix_time::ptime past = boost::posix_time::from_time_t(0);
|
auto past = boost::posix_time::from_time_t(0);
|
||||||
// local variables end
|
|
||||||
|
|
||||||
|
/// enable mouse
|
||||||
mouseinterval(0);
|
mouseinterval(0);
|
||||||
if (Config.mouse_support)
|
if (Config.mouse_support)
|
||||||
mousemask(ALL_MOUSE_EVENTS, 0);
|
mousemask(ALL_MOUSE_EVENTS, 0);
|
||||||
@@ -240,7 +237,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
catch (OutOfBounds &e)
|
catch (OutOfBounds &e)
|
||||||
{
|
{
|
||||||
Statusbar::print(e.errorMessage());
|
Statusbar::printf("Error: %1%", e.errorMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myScreen == myPlaylist)
|
if (myScreen == myPlaylist)
|
||||||
|
|||||||
@@ -53,16 +53,21 @@ bool playlistEntryMatcher(const boost::regex &rx, const MPD::Song &s);
|
|||||||
Playlist::Playlist()
|
Playlist::Playlist()
|
||||||
: itsTotalLength(0), itsRemainingTime(0), itsScrollBegin(0), m_old_playlist_version(0)
|
: itsTotalLength(0), itsRemainingTime(0), itsScrollBegin(0), m_old_playlist_version(0)
|
||||||
{
|
{
|
||||||
w = NC::Menu<MPD::Song>(0, MainStartY, COLS, MainHeight, Config.columns_in_playlist && Config.titles_visibility ? Display::Columns(COLS) : "", Config.main_color, NC::Border::None);
|
w = NC::Menu<MPD::Song>(0, MainStartY, COLS, MainHeight, Config.playlist_display_mode == DisplayMode::Columns && Config.titles_visibility ? Display::Columns(COLS) : "", Config.main_color, NC::Border::None);
|
||||||
w.cyclicScrolling(Config.use_cyclic_scrolling);
|
w.cyclicScrolling(Config.use_cyclic_scrolling);
|
||||||
w.centeredCursor(Config.centered_cursor);
|
w.centeredCursor(Config.centered_cursor);
|
||||||
w.setHighlightColor(Config.main_highlight_color);
|
w.setHighlightColor(Config.main_highlight_color);
|
||||||
w.setSelectedPrefix(Config.selected_item_prefix);
|
w.setSelectedPrefix(Config.selected_item_prefix);
|
||||||
w.setSelectedSuffix(Config.selected_item_suffix);
|
w.setSelectedSuffix(Config.selected_item_suffix);
|
||||||
if (Config.columns_in_playlist)
|
switch (Config.playlist_display_mode)
|
||||||
w.setItemDisplayer(boost::bind(Display::SongsInColumns, _1, proxySongList()));
|
{
|
||||||
else
|
case DisplayMode::Classic:
|
||||||
w.setItemDisplayer(boost::bind(Display::Songs, _1, proxySongList(), Config.song_list_format));
|
w.setItemDisplayer(boost::bind(Display::Songs, _1, proxySongList(), Config.song_list_format));
|
||||||
|
break;
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
w.setItemDisplayer(boost::bind(Display::SongsInColumns, _1, proxySongList()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Playlist::switchTo()
|
void Playlist::switchTo()
|
||||||
@@ -80,11 +85,18 @@ void Playlist::resize()
|
|||||||
w.resize(width, MainHeight);
|
w.resize(width, MainHeight);
|
||||||
w.moveTo(x_offset, MainStartY);
|
w.moveTo(x_offset, MainStartY);
|
||||||
|
|
||||||
if (Config.columns_in_playlist && Config.titles_visibility)
|
switch (Config.playlist_display_mode)
|
||||||
w.setTitle(Display::Columns(w.getWidth()));
|
{
|
||||||
else
|
case DisplayMode::Columns:
|
||||||
w.setTitle("");
|
if (Config.titles_visibility)
|
||||||
|
{
|
||||||
|
w.setTitle(Display::Columns(w.getWidth()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DisplayMode::Classic:
|
||||||
|
w.setTitle("");
|
||||||
|
}
|
||||||
|
|
||||||
hasToBeResized = 0;
|
hasToBeResized = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +105,7 @@ std::wstring Playlist::title()
|
|||||||
std::wstring result = L"Playlist ";
|
std::wstring result = L"Playlist ";
|
||||||
if (ReloadTotalLength || ReloadRemaining)
|
if (ReloadTotalLength || ReloadRemaining)
|
||||||
itsBufferedStats = TotalLength();
|
itsBufferedStats = TotalLength();
|
||||||
result += Scroller(ToWString(itsBufferedStats), itsScrollBegin, COLS-result.length()-(Config.new_design ? 2 : Global::VolumeState.length()));
|
result += Scroller(ToWString(itsBufferedStats), itsScrollBegin, COLS-result.length()-(Config.design == Design::Alternative ? 2 : Global::VolumeState.length()));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,10 +385,14 @@ namespace {//
|
|||||||
std::string songToString(const MPD::Song &s)
|
std::string songToString(const MPD::Song &s)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
if (Config.columns_in_playlist)
|
switch (Config.playlist_display_mode)
|
||||||
result = s.toString(Config.song_in_columns_to_string_format, Config.tags_separator);
|
{
|
||||||
else
|
case DisplayMode::Classic:
|
||||||
result = s.toString(Config.song_list_format_dollar_free, Config.tags_separator);
|
result = s.toString(Config.song_list_format_dollar_free, Config.tags_separator);
|
||||||
|
break;
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
result = s.toString(Config.song_in_columns_to_string_format, Config.tags_separator);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,10 +77,15 @@ PlaylistEditor::PlaylistEditor()
|
|||||||
Content.centeredCursor(Config.centered_cursor);
|
Content.centeredCursor(Config.centered_cursor);
|
||||||
Content.setSelectedPrefix(Config.selected_item_prefix);
|
Content.setSelectedPrefix(Config.selected_item_prefix);
|
||||||
Content.setSelectedSuffix(Config.selected_item_suffix);
|
Content.setSelectedSuffix(Config.selected_item_suffix);
|
||||||
if (Config.columns_in_playlist_editor)
|
switch (Config.playlist_editor_display_mode)
|
||||||
Content.setItemDisplayer(boost::bind(Display::SongsInColumns, _1, contentProxyList()));
|
{
|
||||||
else
|
case DisplayMode::Classic:
|
||||||
Content.setItemDisplayer(boost::bind(Display::Songs, _1, contentProxyList(), Config.song_list_format));
|
Content.setItemDisplayer(boost::bind(Display::Songs, _1, contentProxyList(), Config.song_list_format));
|
||||||
|
break;
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
Content.setItemDisplayer(boost::bind(Display::SongsInColumns, _1, contentProxyList()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
w = &Playlists;
|
w = &Playlists;
|
||||||
}
|
}
|
||||||
@@ -550,10 +555,15 @@ namespace {//
|
|||||||
std::string SongToString(const MPD::Song &s)
|
std::string SongToString(const MPD::Song &s)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
if (Config.columns_in_playlist_editor)
|
switch (Config.playlist_display_mode)
|
||||||
result = s.toString(Config.song_in_columns_to_string_format, Config.tags_separator);
|
{
|
||||||
else
|
case DisplayMode::Classic:
|
||||||
result = s.toString(Config.song_list_format_dollar_free, Config.tags_separator);
|
result = s.toString(Config.song_list_format_dollar_free, Config.tags_separator);
|
||||||
|
break;
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
result = s.toString(Config.song_in_columns_to_string_format, Config.tags_separator);
|
||||||
|
break;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,8 +112,10 @@ BaseScreen *toScreen(ScreenType st)
|
|||||||
# endif // ENABLE_CLOCK
|
# endif // ENABLE_CLOCK
|
||||||
case ScreenType::Help:
|
case ScreenType::Help:
|
||||||
return myHelp;
|
return myHelp;
|
||||||
|
# ifdef HAVE_CURL_CURL_H
|
||||||
case ScreenType::Lastfm:
|
case ScreenType::Lastfm:
|
||||||
return myLastfm;
|
return myLastfm;
|
||||||
|
# endif // HAVE_CURL_CURL_H
|
||||||
case ScreenType::Lyrics:
|
case ScreenType::Lyrics:
|
||||||
return myLyrics;
|
return myLyrics;
|
||||||
case ScreenType::MediaLibrary:
|
case ScreenType::MediaLibrary:
|
||||||
|
|||||||
@@ -119,7 +119,17 @@ void SearchEngine::resize()
|
|||||||
getWindowResizeParams(x_offset, width);
|
getWindowResizeParams(x_offset, width);
|
||||||
w.resize(width, MainHeight);
|
w.resize(width, MainHeight);
|
||||||
w.moveTo(x_offset, MainStartY);
|
w.moveTo(x_offset, MainStartY);
|
||||||
w.setTitle(Config.columns_in_search_engine && Config.titles_visibility ? Display::Columns(w.getWidth()) : "");
|
switch (Config.search_engine_display_mode)
|
||||||
|
{
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
if (Config.titles_visibility)
|
||||||
|
{
|
||||||
|
w.setTitle(Display::Columns(w.getWidth()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DisplayMode::Classic:
|
||||||
|
w.setTitle("");
|
||||||
|
}
|
||||||
hasToBeResized = 0;
|
hasToBeResized = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +185,7 @@ void SearchEngine::enterPressed()
|
|||||||
Search();
|
Search();
|
||||||
if (w.back().value().isSong())
|
if (w.back().value().isSong())
|
||||||
{
|
{
|
||||||
if (Config.columns_in_search_engine)
|
if (Config.search_engine_display_mode == DisplayMode::Columns)
|
||||||
w.setTitle(Config.titles_visibility ? Display::Columns(w.getWidth()) : "");
|
w.setTitle(Config.titles_visibility ? Display::Columns(w.getWidth()) : "");
|
||||||
size_t found = w.size()-SearchEngine::StaticOptions;
|
size_t found = w.size()-SearchEngine::StaticOptions;
|
||||||
found += 3; // don't count options inserted below
|
found += 3; // don't count options inserted below
|
||||||
@@ -616,10 +626,15 @@ std::string SEItemToString(const SEItem &ei)
|
|||||||
std::string result;
|
std::string result;
|
||||||
if (ei.isSong())
|
if (ei.isSong())
|
||||||
{
|
{
|
||||||
if (Config.columns_in_search_engine)
|
switch (Config.search_engine_display_mode)
|
||||||
result = ei.song().toString(Config.song_in_columns_to_string_format, Config.tags_separator);
|
{
|
||||||
else
|
case DisplayMode::Classic:
|
||||||
result = ei.song().toString(Config.song_list_format_dollar_free, Config.tags_separator);
|
result = ei.song().toString(Config.song_list_format_dollar_free, Config.tags_separator);
|
||||||
|
break;
|
||||||
|
case DisplayMode::Columns:
|
||||||
|
result = ei.song().toString(Config.song_in_columns_to_string_format, Config.tags_separator);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = ei.buffer().str();
|
result = ei.buffer().str();
|
||||||
|
|||||||
1404
src/settings.cpp
1404
src/settings.cpp
File diff suppressed because it is too large
Load Diff
@@ -26,12 +26,11 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <mpd/client.h>
|
#include <mpd/client.h>
|
||||||
#include "actions.h"
|
|
||||||
|
#include "enums.h"
|
||||||
#include "screen_type.h"
|
#include "screen_type.h"
|
||||||
#include "strbuffer.h"
|
#include "strbuffer.h"
|
||||||
|
|
||||||
enum SortMode { smName, smMTime, smCustomFormat };
|
|
||||||
|
|
||||||
struct Column
|
struct Column
|
||||||
{
|
{
|
||||||
Column() : stretch_limit(-1), right_alignment(0), display_empty_tag(1) { }
|
Column() : stretch_limit(-1), right_alignment(0), display_empty_tag(1) { }
|
||||||
@@ -48,25 +47,20 @@ struct Column
|
|||||||
|
|
||||||
struct Configuration
|
struct Configuration
|
||||||
{
|
{
|
||||||
Configuration();
|
Configuration()
|
||||||
|
: playlist_disable_highlight_delay(0), visualizer_sync_interval(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
const std::string &GetHomeDirectory();
|
bool read(const std::string &config_path);
|
||||||
void CheckForCommandLineConfigFilePath(char **argv, int argc);
|
|
||||||
|
|
||||||
void SetDefaults();
|
|
||||||
void Read(const std::string& config_path);
|
|
||||||
void GenerateColumns();
|
|
||||||
|
|
||||||
std::string ncmpcpp_directory;
|
std::string ncmpcpp_directory;
|
||||||
std::string lyrics_directory;
|
std::string lyrics_directory;
|
||||||
|
|
||||||
std::string mpd_host;
|
|
||||||
std::string mpd_music_dir;
|
std::string mpd_music_dir;
|
||||||
std::string visualizer_fifo_path;
|
std::string visualizer_fifo_path;
|
||||||
std::string visualizer_output_name;
|
std::string visualizer_output_name;
|
||||||
std::string empty_tag;
|
std::string empty_tag;
|
||||||
std::string tags_separator;
|
std::string tags_separator;
|
||||||
std::string song_list_columns_format;
|
|
||||||
std::string song_list_format;
|
std::string song_list_format;
|
||||||
std::string song_list_format_dollar_free;
|
std::string song_list_format_dollar_free;
|
||||||
std::string song_status_format;
|
std::string song_status_format;
|
||||||
@@ -86,9 +80,14 @@ struct Configuration
|
|||||||
std::wstring visualizer_chars;
|
std::wstring visualizer_chars;
|
||||||
|
|
||||||
std::string pattern;
|
std::string pattern;
|
||||||
|
|
||||||
std::vector<Column> columns;
|
std::vector<Column> columns;
|
||||||
|
|
||||||
|
DisplayMode playlist_display_mode;
|
||||||
|
DisplayMode browser_display_mode;
|
||||||
|
DisplayMode search_engine_display_mode;
|
||||||
|
DisplayMode playlist_editor_display_mode;
|
||||||
|
|
||||||
NC::Buffer browser_playlist_prefix;
|
NC::Buffer browser_playlist_prefix;
|
||||||
NC::Buffer selected_item_prefix;
|
NC::Buffer selected_item_prefix;
|
||||||
NC::Buffer selected_item_suffix;
|
NC::Buffer selected_item_suffix;
|
||||||
@@ -115,16 +114,16 @@ struct Configuration
|
|||||||
NC::Border window_border;
|
NC::Border window_border;
|
||||||
NC::Border active_window_border;
|
NC::Border active_window_border;
|
||||||
|
|
||||||
|
Design design;
|
||||||
|
|
||||||
|
SpaceAddMode space_add_mode;
|
||||||
|
|
||||||
mpd_tag_type media_lib_primary_tag;
|
mpd_tag_type media_lib_primary_tag;
|
||||||
|
|
||||||
bool colors_enabled;
|
bool colors_enabled;
|
||||||
bool playlist_show_remaining_time;
|
bool playlist_show_remaining_time;
|
||||||
bool playlist_shorten_total_times;
|
bool playlist_shorten_total_times;
|
||||||
bool playlist_separate_albums;
|
bool playlist_separate_albums;
|
||||||
bool columns_in_playlist;
|
|
||||||
bool columns_in_browser;
|
|
||||||
bool columns_in_search_engine;
|
|
||||||
bool columns_in_playlist_editor;
|
|
||||||
bool set_window_title;
|
bool set_window_title;
|
||||||
bool header_visibility;
|
bool header_visibility;
|
||||||
bool header_text_scrolling;
|
bool header_text_scrolling;
|
||||||
@@ -135,7 +134,6 @@ struct Configuration
|
|||||||
bool autocenter_mode;
|
bool autocenter_mode;
|
||||||
bool wrapped_search;
|
bool wrapped_search;
|
||||||
bool space_selects;
|
bool space_selects;
|
||||||
bool ncmpc_like_songs_adding;
|
|
||||||
bool incremental_seeking;
|
bool incremental_seeking;
|
||||||
bool now_playing_lyrics;
|
bool now_playing_lyrics;
|
||||||
bool fetch_lyrics_in_background;
|
bool fetch_lyrics_in_background;
|
||||||
@@ -150,10 +148,9 @@ struct Configuration
|
|||||||
bool block_search_constraints_change;
|
bool block_search_constraints_change;
|
||||||
bool use_console_editor;
|
bool use_console_editor;
|
||||||
bool use_cyclic_scrolling;
|
bool use_cyclic_scrolling;
|
||||||
bool ask_before_clearing_main_playlist;
|
bool ask_before_clearing_playlists;
|
||||||
bool mouse_support;
|
bool mouse_support;
|
||||||
bool mouse_list_scroll_whole_page;
|
bool mouse_list_scroll_whole_page;
|
||||||
bool new_design;
|
|
||||||
bool visualizer_use_wave;
|
bool visualizer_use_wave;
|
||||||
bool visualizer_in_stereo;
|
bool visualizer_in_stereo;
|
||||||
bool media_library_sort_by_mtime;
|
bool media_library_sort_by_mtime;
|
||||||
@@ -165,18 +162,16 @@ struct Configuration
|
|||||||
bool allow_for_physical_item_deletion;
|
bool allow_for_physical_item_deletion;
|
||||||
bool progressbar_boldness;
|
bool progressbar_boldness;
|
||||||
|
|
||||||
int mpd_port;
|
unsigned mpd_connection_timeout;
|
||||||
int mpd_connection_timeout;
|
unsigned crossfade_time;
|
||||||
int crossfade_time;
|
unsigned seek_time;
|
||||||
int seek_time;
|
unsigned volume_change_step;
|
||||||
int volume_change_step;
|
unsigned message_delay_time;
|
||||||
int message_delay_time;
|
unsigned lyrics_db;
|
||||||
int lyrics_db;
|
|
||||||
|
|
||||||
boost::regex::flag_type regex_type;
|
|
||||||
|
|
||||||
unsigned lines_scrolled;
|
unsigned lines_scrolled;
|
||||||
unsigned search_engine_default_search_mode;
|
unsigned search_engine_default_search_mode;
|
||||||
|
|
||||||
|
boost::regex::flag_type regex_type;
|
||||||
|
|
||||||
boost::posix_time::seconds playlist_disable_highlight_delay;
|
boost::posix_time::seconds playlist_disable_highlight_delay;
|
||||||
boost::posix_time::seconds visualizer_sync_interval;
|
boost::posix_time::seconds visualizer_sync_interval;
|
||||||
@@ -189,19 +184,12 @@ struct Configuration
|
|||||||
size_t now_playing_suffix_length;
|
size_t now_playing_suffix_length;
|
||||||
|
|
||||||
ScreenType startup_screen_type;
|
ScreenType startup_screen_type;
|
||||||
std::list<ScreenType> screens_seq;
|
std::list<ScreenType> screen_sequence;
|
||||||
|
|
||||||
SortMode browser_sort_mode;
|
SortMode browser_sort_mode;
|
||||||
|
|
||||||
private:
|
|
||||||
void MakeProperPath(std::string &dir);
|
|
||||||
|
|
||||||
std::string home_directory;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Configuration Config;
|
extern Configuration Config;
|
||||||
|
|
||||||
void CreateDir(const std::string &dir);
|
|
||||||
|
|
||||||
#endif // NCMPCPP_SETTINGS_H
|
#endif // NCMPCPP_SETTINGS_H
|
||||||
|
|
||||||
|
|||||||
15
src/song.cpp
15
src/song.cpp
@@ -288,7 +288,7 @@ std::string Song::ShowTime(unsigned length)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MPD::Song::isFormatOk(const std::string &type, const std::string &fmt)
|
void MPD::Song::validateFormat(const std::string &fmt)
|
||||||
{
|
{
|
||||||
int braces = 0;
|
int braces = 0;
|
||||||
for (std::string::const_iterator it = fmt.begin(); it != fmt.end(); ++it)
|
for (std::string::const_iterator it = fmt.begin(); it != fmt.end(); ++it)
|
||||||
@@ -299,22 +299,17 @@ bool MPD::Song::isFormatOk(const std::string &type, const std::string &fmt)
|
|||||||
--braces;
|
--braces;
|
||||||
}
|
}
|
||||||
if (braces)
|
if (braces)
|
||||||
{
|
throw std::runtime_error("number of opening and closing braces is not equal");
|
||||||
std::cerr << type << ": number of opening and closing braces does not equal\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = fmt.find('%'); i != std::string::npos; i = fmt.find('%', i))
|
for (size_t i = fmt.find('%'); i != std::string::npos; i = fmt.find('%', i))
|
||||||
{
|
{
|
||||||
if (isdigit(fmt[++i]))
|
if (isdigit(fmt[++i]))
|
||||||
while (isdigit(fmt[++i])) { }
|
while (isdigit(fmt[++i])) { }
|
||||||
if (!charToGetFunction(fmt[i]))
|
if (!charToGetFunction(fmt[i]))
|
||||||
{
|
throw std::runtime_error(
|
||||||
std::cerr << type << ": invalid character at position " << boost::lexical_cast<std::string>(i+1) << ": '" << fmt[i] << "'\n";
|
(boost::format("invalid character at position %1%: %2%") % (i+1) % fmt[i]).str()
|
||||||
return false;
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Song::ParseFormat(std::string::const_iterator &it, const std::string &tags_separator,
|
std::string Song::ParseFormat(std::string::const_iterator &it, const std::string &tags_separator,
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ struct Song
|
|||||||
bool operator!=(const Song &rhs) const { return m_hash != rhs.m_hash; }
|
bool operator!=(const Song &rhs) const { return m_hash != rhs.m_hash; }
|
||||||
|
|
||||||
static std::string ShowTime(unsigned length);
|
static std::string ShowTime(unsigned length);
|
||||||
static bool isFormatOk(const std::string &type, const std::string &fmt);
|
static void validateFormat(const std::string &fmt);
|
||||||
|
|
||||||
static const char FormatEscapeCharacter = 1;
|
static const char FormatEscapeCharacter = 1;
|
||||||
|
|
||||||
|
|||||||
272
src/status.cpp
272
src/status.cpp
@@ -80,19 +80,19 @@ std::string playerStateToString(MPD::PlayerState ps)
|
|||||||
result = "[unknown]";
|
result = "[unknown]";
|
||||||
break;
|
break;
|
||||||
case MPD::psPlay:
|
case MPD::psPlay:
|
||||||
if (Config.new_design)
|
if (Config.design == Design::Alternative)
|
||||||
result = "[playing]";
|
result = "[playing]";
|
||||||
else
|
else
|
||||||
result = "Playing: ";
|
result = "Playing: ";
|
||||||
break;
|
break;
|
||||||
case MPD::psPause:
|
case MPD::psPause:
|
||||||
if (Config.new_design)
|
if (Config.design == Design::Alternative)
|
||||||
result = "[paused] ";
|
result = "[paused] ";
|
||||||
else
|
else
|
||||||
result = "[Paused] ";
|
result = "[Paused] ";
|
||||||
break;
|
break;
|
||||||
case MPD::psStop:
|
case MPD::psStop:
|
||||||
if (Config.new_design)
|
if (Config.design == Design::Alternative)
|
||||||
result = "[stopped]";
|
result = "[stopped]";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -337,7 +337,7 @@ void Status::Changes::playerState()
|
|||||||
if (Progressbar::isUnlocked())
|
if (Progressbar::isUnlocked())
|
||||||
Progressbar::draw(0, 0);
|
Progressbar::draw(0, 0);
|
||||||
Playlist::ReloadRemaining = true;
|
Playlist::ReloadRemaining = true;
|
||||||
if (Config.new_design)
|
if (Config.design == Design::Alternative)
|
||||||
{
|
{
|
||||||
*wHeader << NC::XY(0, 0) << wclrtoeol << NC::XY(0, 1) << wclrtoeol;
|
*wHeader << NC::XY(0, 0) << wclrtoeol << NC::XY(0, 1) << wclrtoeol;
|
||||||
mixer();
|
mixer();
|
||||||
@@ -358,7 +358,7 @@ void Status::Changes::playerState()
|
|||||||
# endif // ENABLE_VISUALIZER
|
# endif // ENABLE_VISUALIZER
|
||||||
|
|
||||||
std::string state = playerStateToString(State::player());
|
std::string state = playerStateToString(State::player());
|
||||||
if (Config.new_design)
|
if (Config.design == Design::Alternative)
|
||||||
{
|
{
|
||||||
*wHeader << NC::XY(0, 1) << NC::Format::Bold << state << NC::Format::NoBold;
|
*wHeader << NC::XY(0, 1) << NC::Format::Bold << state << NC::Format::NoBold;
|
||||||
wHeader->refresh();
|
wHeader->refresh();
|
||||||
@@ -428,85 +428,88 @@ void Status::Changes::elapsedTime(bool update_elapsed)
|
|||||||
drawTitle(np);
|
drawTitle(np);
|
||||||
|
|
||||||
std::string tracklength;
|
std::string tracklength;
|
||||||
if (Config.new_design)
|
switch (Config.design)
|
||||||
{
|
{
|
||||||
if (Config.display_remaining_time)
|
case Design::Classic:
|
||||||
{
|
if (Statusbar::isUnlocked() && Config.statusbar_visibility)
|
||||||
tracklength = "-";
|
{
|
||||||
tracklength += MPD::Song::ShowTime(st.totalTime()-st.elapsedTime());
|
if (Config.display_bitrate && st.kbps())
|
||||||
}
|
{
|
||||||
else
|
tracklength += " [";
|
||||||
tracklength = MPD::Song::ShowTime(st.elapsedTime());
|
tracklength += boost::lexical_cast<std::string>(st.kbps());
|
||||||
if (st.totalTime())
|
tracklength += " kbps]";
|
||||||
{
|
}
|
||||||
tracklength += "/";
|
tracklength += " [";
|
||||||
tracklength += MPD::Song::ShowTime(st.totalTime());
|
if (st.totalTime())
|
||||||
}
|
{
|
||||||
// bitrate here doesn't look good, but it can be moved somewhere else later
|
if (Config.display_remaining_time)
|
||||||
if (Config.display_bitrate && st.kbps())
|
{
|
||||||
{
|
tracklength += "-";
|
||||||
tracklength += " ";
|
tracklength += MPD::Song::ShowTime(st.totalTime()-st.elapsedTime());
|
||||||
tracklength += boost::lexical_cast<std::string>(st.kbps());
|
}
|
||||||
tracklength += " kbps";
|
else
|
||||||
}
|
tracklength += MPD::Song::ShowTime(st.elapsedTime());
|
||||||
|
tracklength += "/";
|
||||||
NC::WBuffer first, second;
|
tracklength += MPD::Song::ShowTime(st.totalTime());
|
||||||
stringToBuffer(ToWString(Charset::utf8ToLocale(np.toString(Config.new_header_first_line, Config.tags_separator, "$"))), first);
|
tracklength += "]";
|
||||||
stringToBuffer(ToWString(Charset::utf8ToLocale(np.toString(Config.new_header_second_line, Config.tags_separator, "$"))), second);
|
}
|
||||||
|
else
|
||||||
size_t first_len = wideLength(first.str());
|
{
|
||||||
size_t first_margin = (std::max(tracklength.length()+1, VolumeState.length()))*2;
|
tracklength += MPD::Song::ShowTime(st.elapsedTime());
|
||||||
size_t first_start = first_len < COLS-first_margin ? (COLS-first_len)/2 : tracklength.length()+1;
|
tracklength += "]";
|
||||||
|
}
|
||||||
size_t second_len = wideLength(second.str());
|
NC::WBuffer np_song;
|
||||||
size_t second_margin = (std::max(ps.length(), size_t(8))+1)*2;
|
stringToBuffer(ToWString(Charset::utf8ToLocale(np.toString(Config.song_status_format, Config.tags_separator, "$"))), np_song);
|
||||||
size_t second_start = second_len < COLS-second_margin ? (COLS-second_len)/2 : ps.length()+1;
|
*wFooter << NC::XY(0, 1) << wclrtoeol << NC::Format::Bold << ps << NC::Format::NoBold;
|
||||||
|
writeCyclicBuffer(np_song, *wFooter, playing_song_scroll_begin, wFooter->getWidth()-ps.length()-tracklength.length(), L" ** ");
|
||||||
if (!Global::SeekingInProgress)
|
*wFooter << NC::Format::Bold << NC::XY(wFooter->getWidth()-tracklength.length(), 1) << tracklength << NC::Format::NoBold;
|
||||||
*wHeader << NC::XY(0, 0) << wclrtoeol << tracklength;
|
}
|
||||||
*wHeader << NC::XY(first_start, 0);
|
break;
|
||||||
writeCyclicBuffer(first, *wHeader, first_line_scroll_begin, COLS-tracklength.length()-VolumeState.length()-1, L" ** ");
|
case Design::Alternative:
|
||||||
|
|
||||||
*wHeader << NC::XY(0, 1) << wclrtoeol << NC::Format::Bold << ps << NC::Format::NoBold;
|
|
||||||
*wHeader << NC::XY(second_start, 1);
|
|
||||||
writeCyclicBuffer(second, *wHeader, second_line_scroll_begin, COLS-ps.length()-8-2, L" ** ");
|
|
||||||
|
|
||||||
*wHeader << NC::XY(wHeader->getWidth()-VolumeState.length(), 0) << Config.volume_color << VolumeState << NC::Color::End;
|
|
||||||
|
|
||||||
flags();
|
|
||||||
}
|
|
||||||
else if (Statusbar::isUnlocked() && Config.statusbar_visibility)
|
|
||||||
{
|
|
||||||
if (Config.display_bitrate && st.kbps())
|
|
||||||
{
|
|
||||||
tracklength += " [";
|
|
||||||
tracklength += boost::lexical_cast<std::string>(st.kbps());
|
|
||||||
tracklength += " kbps]";
|
|
||||||
}
|
|
||||||
tracklength += " [";
|
|
||||||
if (st.totalTime())
|
|
||||||
{
|
|
||||||
if (Config.display_remaining_time)
|
if (Config.display_remaining_time)
|
||||||
{
|
{
|
||||||
tracklength += "-";
|
tracklength = "-";
|
||||||
tracklength += MPD::Song::ShowTime(st.totalTime()-st.elapsedTime());
|
tracklength += MPD::Song::ShowTime(st.totalTime()-st.elapsedTime());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tracklength += MPD::Song::ShowTime(st.elapsedTime());
|
tracklength = MPD::Song::ShowTime(st.elapsedTime());
|
||||||
tracklength += "/";
|
if (st.totalTime())
|
||||||
tracklength += MPD::Song::ShowTime(st.totalTime());
|
{
|
||||||
tracklength += "]";
|
tracklength += "/";
|
||||||
}
|
tracklength += MPD::Song::ShowTime(st.totalTime());
|
||||||
else
|
}
|
||||||
{
|
// bitrate here doesn't look good, but it can be moved somewhere else later
|
||||||
tracklength += MPD::Song::ShowTime(st.elapsedTime());
|
if (Config.display_bitrate && st.kbps())
|
||||||
tracklength += "]";
|
{
|
||||||
}
|
tracklength += " ";
|
||||||
NC::WBuffer np_song;
|
tracklength += boost::lexical_cast<std::string>(st.kbps());
|
||||||
stringToBuffer(ToWString(Charset::utf8ToLocale(np.toString(Config.song_status_format, Config.tags_separator, "$"))), np_song);
|
tracklength += " kbps";
|
||||||
*wFooter << NC::XY(0, 1) << wclrtoeol << NC::Format::Bold << ps << NC::Format::NoBold;
|
}
|
||||||
writeCyclicBuffer(np_song, *wFooter, playing_song_scroll_begin, wFooter->getWidth()-ps.length()-tracklength.length(), L" ** ");
|
|
||||||
*wFooter << NC::Format::Bold << NC::XY(wFooter->getWidth()-tracklength.length(), 1) << tracklength << NC::Format::NoBold;
|
NC::WBuffer first, second;
|
||||||
|
stringToBuffer(ToWString(Charset::utf8ToLocale(np.toString(Config.new_header_first_line, Config.tags_separator, "$"))), first);
|
||||||
|
stringToBuffer(ToWString(Charset::utf8ToLocale(np.toString(Config.new_header_second_line, Config.tags_separator, "$"))), second);
|
||||||
|
|
||||||
|
size_t first_len = wideLength(first.str());
|
||||||
|
size_t first_margin = (std::max(tracklength.length()+1, VolumeState.length()))*2;
|
||||||
|
size_t first_start = first_len < COLS-first_margin ? (COLS-first_len)/2 : tracklength.length()+1;
|
||||||
|
|
||||||
|
size_t second_len = wideLength(second.str());
|
||||||
|
size_t second_margin = (std::max(ps.length(), size_t(8))+1)*2;
|
||||||
|
size_t second_start = second_len < COLS-second_margin ? (COLS-second_len)/2 : ps.length()+1;
|
||||||
|
|
||||||
|
if (!Global::SeekingInProgress)
|
||||||
|
*wHeader << NC::XY(0, 0) << wclrtoeol << tracklength;
|
||||||
|
*wHeader << NC::XY(first_start, 0);
|
||||||
|
writeCyclicBuffer(first, *wHeader, first_line_scroll_begin, COLS-tracklength.length()-VolumeState.length()-1, L" ** ");
|
||||||
|
|
||||||
|
*wHeader << NC::XY(0, 1) << wclrtoeol << NC::Format::Bold << ps << NC::Format::NoBold;
|
||||||
|
*wHeader << NC::XY(second_start, 1);
|
||||||
|
writeCyclicBuffer(second, *wHeader, second_line_scroll_begin, COLS-ps.length()-8-2, L" ** ");
|
||||||
|
|
||||||
|
*wHeader << NC::XY(wHeader->getWidth()-VolumeState.length(), 0) << Config.volume_color << VolumeState << NC::Color::End;
|
||||||
|
|
||||||
|
flags();
|
||||||
}
|
}
|
||||||
if (Progressbar::isUnlocked())
|
if (Progressbar::isUnlocked())
|
||||||
Progressbar::draw(st.elapsedTime(), st.totalTime());
|
Progressbar::draw(st.elapsedTime(), st.totalTime());
|
||||||
@@ -557,69 +560,78 @@ void Status::Changes::dbUpdateState(bool show_msg)
|
|||||||
|
|
||||||
void Status::Changes::flags()
|
void Status::Changes::flags()
|
||||||
{
|
{
|
||||||
if (!Config.header_visibility && !Config.new_design)
|
if (!Config.header_visibility && Config.design == Design::Classic)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string switch_state;
|
std::string switch_state;
|
||||||
if (Config.new_design)
|
switch (Config.design)
|
||||||
{
|
{
|
||||||
switch_state += '[';
|
case Design::Classic:
|
||||||
switch_state += m_repeat ? m_repeat : '-';
|
if (m_repeat)
|
||||||
switch_state += m_random ? m_random : '-';
|
switch_state += m_repeat;
|
||||||
switch_state += m_single ? m_single : '-';
|
if (m_random)
|
||||||
switch_state += m_consume ? m_consume : '-';
|
switch_state += m_random;
|
||||||
switch_state += m_crossfade ? m_crossfade : '-';
|
if (m_single)
|
||||||
switch_state += m_db_updating ? m_db_updating : '-';
|
switch_state += m_single;
|
||||||
switch_state += ']';
|
if (m_consume)
|
||||||
*wHeader << NC::XY(COLS-switch_state.length(), 1) << NC::Format::Bold << Config.state_flags_color << switch_state << NC::Color::End << NC::Format::NoBold;
|
switch_state += m_consume;
|
||||||
if (Config.new_design && !Config.header_visibility) // in this case also draw separator
|
if (m_crossfade)
|
||||||
{
|
switch_state += m_crossfade;
|
||||||
*wHeader << NC::Format::Bold << NC::Color::Black;
|
if (m_db_updating)
|
||||||
mvwhline(wHeader->raw(), 2, 0, 0, COLS);
|
switch_state += m_db_updating;
|
||||||
*wHeader << NC::Color::End << NC::Format::NoBold;
|
|
||||||
}
|
// this is done by raw ncurses because creating another
|
||||||
wHeader->refresh();
|
// window only for handling this is quite silly
|
||||||
}
|
attrset(A_BOLD|COLOR_PAIR(int(Config.state_line_color)));
|
||||||
else
|
mvhline(1, 0, 0, COLS);
|
||||||
{
|
if (!switch_state.empty())
|
||||||
if (m_repeat)
|
{
|
||||||
switch_state += m_repeat;
|
mvprintw(1, COLS-switch_state.length()-3, "[");
|
||||||
if (m_random)
|
attroff(COLOR_PAIR(int(Config.state_line_color)));
|
||||||
switch_state += m_random;
|
attron(COLOR_PAIR(int(Config.state_flags_color)));
|
||||||
if (m_single)
|
mvprintw(1, COLS-switch_state.length()-2, "%s", switch_state.c_str());
|
||||||
switch_state += m_single;
|
attroff(COLOR_PAIR(int(Config.state_flags_color)));
|
||||||
if (m_consume)
|
attron(COLOR_PAIR(int(Config.state_line_color)));
|
||||||
switch_state += m_consume;
|
mvprintw(1, COLS-2, "]");
|
||||||
if (m_crossfade)
|
}
|
||||||
switch_state += m_crossfade;
|
attroff(A_BOLD|COLOR_PAIR(int(Config.state_line_color)));
|
||||||
if (m_db_updating)
|
refresh();
|
||||||
switch_state += m_db_updating;
|
break;
|
||||||
|
case Design::Alternative:
|
||||||
// this is done by raw ncurses because creating another
|
switch_state += '[';
|
||||||
// window only for handling this is quite silly
|
switch_state += m_repeat ? m_repeat : '-';
|
||||||
attrset(A_BOLD|COLOR_PAIR(int(Config.state_line_color)));
|
switch_state += m_random ? m_random : '-';
|
||||||
mvhline(1, 0, 0, COLS);
|
switch_state += m_single ? m_single : '-';
|
||||||
if (!switch_state.empty())
|
switch_state += m_consume ? m_consume : '-';
|
||||||
{
|
switch_state += m_crossfade ? m_crossfade : '-';
|
||||||
mvprintw(1, COLS-switch_state.length()-3, "[");
|
switch_state += m_db_updating ? m_db_updating : '-';
|
||||||
attroff(COLOR_PAIR(int(Config.state_line_color)));
|
switch_state += ']';
|
||||||
attron(COLOR_PAIR(int(Config.state_flags_color)));
|
*wHeader << NC::XY(COLS-switch_state.length(), 1) << NC::Format::Bold << Config.state_flags_color << switch_state << NC::Color::End << NC::Format::NoBold;
|
||||||
mvprintw(1, COLS-switch_state.length()-2, "%s", switch_state.c_str());
|
if (!Config.header_visibility) // in this case also draw separator
|
||||||
attroff(COLOR_PAIR(int(Config.state_flags_color)));
|
{
|
||||||
attron(COLOR_PAIR(int(Config.state_line_color)));
|
*wHeader << NC::Format::Bold << NC::Color::Black;
|
||||||
mvprintw(1, COLS-2, "]");
|
mvwhline(wHeader->raw(), 2, 0, 0, COLS);
|
||||||
}
|
*wHeader << NC::Color::End << NC::Format::NoBold;
|
||||||
attroff(A_BOLD|COLOR_PAIR(int(Config.state_line_color)));
|
}
|
||||||
refresh();
|
wHeader->refresh();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Status::Changes::mixer()
|
void Status::Changes::mixer()
|
||||||
{
|
{
|
||||||
if (!Config.display_volume_level || (!Config.header_visibility && !Config.new_design))
|
if (!Config.display_volume_level || (!Config.header_visibility && Config.design == Design::Classic))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
VolumeState = Config.new_design ? " Vol: " : " Volume: ";
|
switch (Config.design)
|
||||||
|
{
|
||||||
|
case Design::Classic:
|
||||||
|
VolumeState = " " "Volume" ": ";
|
||||||
|
break;
|
||||||
|
case Design::Alternative:
|
||||||
|
VolumeState = " " "Vol" ": ";
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (State::volume() < 0)
|
if (State::volume() < 0)
|
||||||
VolumeState += "n/a";
|
VolumeState += "n/a";
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -106,10 +106,15 @@ void Statusbar::unlock()
|
|||||||
}
|
}
|
||||||
if (Status::State::player() == MPD::psStop)
|
if (Status::State::player() == MPD::psStop)
|
||||||
{
|
{
|
||||||
if (Config.new_design)
|
switch (Config.design)
|
||||||
Progressbar::draw(Status::State::elapsedTime(), myPlaylist->currentSongLength());
|
{
|
||||||
else
|
case Design::Classic:
|
||||||
put() << wclrtoeol;
|
put() << wclrtoeol;
|
||||||
|
break;
|
||||||
|
case Design::Alternative:
|
||||||
|
Progressbar::draw(Status::State::elapsedTime(), myPlaylist->currentSongLength());
|
||||||
|
break;
|
||||||
|
}
|
||||||
wFooter->refresh();
|
wFooter->refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,10 +139,15 @@ void Statusbar::tryRedraw()
|
|||||||
|
|
||||||
if (Status::State::player() != MPD::psStop && !statusbarBlockUpdate && !progressbarBlockUpdate)
|
if (Status::State::player() != MPD::psStop && !statusbarBlockUpdate && !progressbarBlockUpdate)
|
||||||
{
|
{
|
||||||
if (Config.new_design)
|
switch (Config.design)
|
||||||
Progressbar::draw(Status::State::elapsedTime(), myPlaylist->currentSongLength());
|
{
|
||||||
else
|
case Design::Classic:
|
||||||
Status::Changes::elapsedTime(false);
|
Status::Changes::elapsedTime(false);
|
||||||
|
break;
|
||||||
|
case Design::Alternative:
|
||||||
|
Progressbar::draw(Status::State::elapsedTime(), myPlaylist->currentSongLength());
|
||||||
|
break;
|
||||||
|
}
|
||||||
wFooter->refresh();
|
wFooter->refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,18 +63,19 @@ template <typename CharT> class BasicBuffer
|
|||||||
return m_id < rhs.m_id;
|
return m_id < rhs.m_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend Window &operator<<(Window &w, const Property &p)
|
template <typename OutputStreamT>
|
||||||
|
friend OutputStreamT &operator<<(OutputStreamT &os, const Property &p)
|
||||||
{
|
{
|
||||||
switch (p.m_type)
|
switch (p.m_type)
|
||||||
{
|
{
|
||||||
case Type::Color:
|
case Type::Color:
|
||||||
w << p.m_color;
|
os << p.m_color;
|
||||||
break;
|
break;
|
||||||
case Type::Format:
|
case Type::Format:
|
||||||
w << p.m_format;
|
os << p.m_format;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return w;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -89,8 +90,12 @@ public:
|
|||||||
typedef std::basic_string<CharT> StringType;
|
typedef std::basic_string<CharT> StringType;
|
||||||
typedef std::set<Property> Properties;
|
typedef std::set<Property> Properties;
|
||||||
|
|
||||||
BasicBuffer() { }
|
template <typename... Args>
|
||||||
|
BasicBuffer(Args... args)
|
||||||
|
{
|
||||||
|
construct(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
const StringType &str() const { return m_string; }
|
const StringType &str() const { return m_string; }
|
||||||
const Properties &properties() const { return m_properties; }
|
const Properties &properties() const { return m_properties; }
|
||||||
|
|
||||||
@@ -183,6 +188,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void construct() { }
|
||||||
|
template <typename ArgT, typename... Args>
|
||||||
|
void construct(ArgT &&arg, Args... args)
|
||||||
|
{
|
||||||
|
*this << std::forward<ArgT>(arg);
|
||||||
|
construct(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
StringType m_string;
|
StringType m_string;
|
||||||
Properties m_properties;
|
Properties m_properties;
|
||||||
};
|
};
|
||||||
@@ -190,11 +203,11 @@ private:
|
|||||||
typedef BasicBuffer<char> Buffer;
|
typedef BasicBuffer<char> Buffer;
|
||||||
typedef BasicBuffer<wchar_t> WBuffer;
|
typedef BasicBuffer<wchar_t> WBuffer;
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename OutputStreamT, typename CharT>
|
||||||
Window &operator<<(Window &w, const BasicBuffer<CharT> &buffer)
|
OutputStreamT &operator<<(OutputStreamT &os, const BasicBuffer<CharT> &buffer)
|
||||||
{
|
{
|
||||||
if (buffer.properties().empty())
|
if (buffer.properties().empty())
|
||||||
w << buffer.str();
|
os << buffer.str();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto &s = buffer.str();
|
auto &s = buffer.str();
|
||||||
@@ -203,14 +216,14 @@ Window &operator<<(Window &w, const BasicBuffer<CharT> &buffer)
|
|||||||
for (size_t i = 0; i < s.size(); ++i)
|
for (size_t i = 0; i < s.size(); ++i)
|
||||||
{
|
{
|
||||||
for (; p != ps.end() && p->position() == i; ++p)
|
for (; p != ps.end() && p->position() == i; ++p)
|
||||||
w << *p;
|
os << *p;
|
||||||
w << s[i];
|
os << s[i];
|
||||||
}
|
}
|
||||||
// load remaining properties
|
// load remaining properties
|
||||||
for (; p != ps.end(); ++p)
|
for (; p != ps.end(); ++p)
|
||||||
w << *p;
|
os << *p;
|
||||||
}
|
}
|
||||||
return w;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,8 @@
|
|||||||
#include <boost/locale/conversion.hpp>
|
#include <boost/locale/conversion.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
|
#include "actions.h"
|
||||||
#include "browser.h"
|
#include "browser.h"
|
||||||
#include "charset.h"
|
#include "charset.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
|||||||
@@ -44,23 +44,24 @@ void drawHeader()
|
|||||||
|
|
||||||
if (!Config.header_visibility)
|
if (!Config.header_visibility)
|
||||||
return;
|
return;
|
||||||
if (Config.new_design)
|
switch (Config.design)
|
||||||
{
|
{
|
||||||
std::wstring title = myScreen->title();
|
case Design::Classic:
|
||||||
*wHeader << NC::XY(0, 3) << wclrtoeol;
|
*wHeader << NC::XY(0, 0) << wclrtoeol << NC::Format::Bold << myScreen->title() << NC::Format::NoBold;
|
||||||
*wHeader << NC::Format::Bold << Config.alternative_ui_separator_color;
|
*wHeader << Config.volume_color;
|
||||||
mvwhline(wHeader->raw(), 2, 0, 0, COLS);
|
*wHeader << NC::XY(wHeader->getWidth()-VolumeState.length(), 0) << VolumeState;
|
||||||
mvwhline(wHeader->raw(), 4, 0, 0, COLS);
|
*wHeader << NC::Color::End;
|
||||||
*wHeader << NC::XY((COLS-wideLength(title))/2, 3);
|
break;
|
||||||
*wHeader << Config.header_color << title << NC::Color::End;
|
case Design::Alternative:
|
||||||
*wHeader << NC::Color::End << NC::Format::NoBold;
|
std::wstring title = myScreen->title();
|
||||||
}
|
*wHeader << NC::XY(0, 3) << wclrtoeol;
|
||||||
else
|
*wHeader << NC::Format::Bold << Config.alternative_ui_separator_color;
|
||||||
{
|
mvwhline(wHeader->raw(), 2, 0, 0, COLS);
|
||||||
*wHeader << NC::XY(0, 0) << wclrtoeol << NC::Format::Bold << myScreen->title() << NC::Format::NoBold;
|
mvwhline(wHeader->raw(), 4, 0, 0, COLS);
|
||||||
*wHeader << Config.volume_color;
|
*wHeader << NC::XY((COLS-wideLength(title))/2, 3);
|
||||||
*wHeader << NC::XY(wHeader->getWidth()-VolumeState.length(), 0) << VolumeState;
|
*wHeader << Config.header_color << title << NC::Color::End;
|
||||||
*wHeader << NC::Color::End;
|
*wHeader << NC::Color::End << NC::Format::NoBold;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
wHeader->refresh();
|
wHeader->refresh();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,13 +68,13 @@ bool LocaleBasedItemSorting::operator()(const MPD::Item &a, const MPD::Item &b)
|
|||||||
case MPD::itSong:
|
case MPD::itSong:
|
||||||
switch (m_sort_mode)
|
switch (m_sort_mode)
|
||||||
{
|
{
|
||||||
case smName:
|
case SortMode::Name:
|
||||||
result = m_cmp(*a.song, *b.song);
|
result = m_cmp(*a.song, *b.song);
|
||||||
break;
|
break;
|
||||||
case smMTime:
|
case SortMode::ModificationTime:
|
||||||
result = a.song->getMTime() > b.song->getMTime();
|
result = a.song->getMTime() > b.song->getMTime();
|
||||||
break;
|
break;
|
||||||
case smCustomFormat:
|
case SortMode::CustomFormat:
|
||||||
result = m_cmp(a.song->toString(Config.browser_sort_format, Config.tags_separator),
|
result = m_cmp(a.song->toString(Config.browser_sort_format, Config.tags_separator),
|
||||||
b.song->toString(Config.browser_sort_format, Config.tags_separator));
|
b.song->toString(Config.browser_sort_format, Config.tags_separator));
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -18,10 +18,14 @@
|
|||||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef NCMPCPP_UTILITY_CONVERSION_H
|
||||||
|
#define NCMPCPP_UTILITY_CONVERSION_H
|
||||||
|
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/type_traits/is_unsigned.hpp>
|
#include <boost/type_traits/is_unsigned.hpp>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include "gcc.h"
|
#include "gcc.h"
|
||||||
|
|
||||||
struct ConversionError
|
struct ConversionError
|
||||||
@@ -35,7 +39,7 @@ private:
|
|||||||
std::string m_source_value;
|
std::string m_source_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OutOfBounds
|
struct OutOfBounds : std::exception
|
||||||
{
|
{
|
||||||
const std::string &errorMessage() { return m_error_message; }
|
const std::string &errorMessage() { return m_error_message; }
|
||||||
|
|
||||||
@@ -43,23 +47,25 @@ struct OutOfBounds
|
|||||||
GNUC_NORETURN static void raise(const Type &value, const Type &lbound, const Type &ubound)
|
GNUC_NORETURN static void raise(const Type &value, const Type &lbound, const Type &ubound)
|
||||||
{
|
{
|
||||||
throw OutOfBounds((boost::format(
|
throw OutOfBounds((boost::format(
|
||||||
"Value is out of bounds ([%1%, %2%] expected, %3% given)") % lbound % ubound % value).str());
|
"value is out of bounds ([%1%, %2%] expected, %3% given)") % lbound % ubound % value).str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
GNUC_NORETURN static void raiseLower(const Type &value, const Type &lbound)
|
GNUC_NORETURN static void raiseLower(const Type &value, const Type &lbound)
|
||||||
{
|
{
|
||||||
throw OutOfBounds((boost::format(
|
throw OutOfBounds((boost::format(
|
||||||
"Value is out of bounds ([%1%, ->) expected, %2% given)") % lbound % value).str());
|
"value is out of bounds ([%1%, ->) expected, %2% given)") % lbound % value).str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
GNUC_NORETURN static void raiseUpper(const Type &value, const Type &ubound)
|
GNUC_NORETURN static void raiseUpper(const Type &value, const Type &ubound)
|
||||||
{
|
{
|
||||||
throw OutOfBounds((boost::format(
|
throw OutOfBounds((boost::format(
|
||||||
"Value is out of bounds ((<-, %1%] expected, %2% given)") % ubound % value).str());
|
"value is out of bounds ((<-, %1%] expected, %2% given)") % ubound % value).str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual const char *what() const noexcept OVERRIDE { return m_error_message.c_str(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OutOfBounds(std::string msg) : m_error_message(msg) { }
|
OutOfBounds(std::string msg) : m_error_message(msg) { }
|
||||||
|
|
||||||
@@ -115,3 +121,5 @@ void upperBoundCheck(const Type &value, const Type &ubound)
|
|||||||
if (value > ubound)
|
if (value > ubound)
|
||||||
OutOfBounds::raiseUpper(value, ubound);
|
OutOfBounds::raiseUpper(value, ubound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // NCMPCPP_UTILITY_CONVERSION_H
|
||||||
|
|||||||
37
src/utility/functional.h
Normal file
37
src/utility/functional.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008-2014 by Andrzej Rybczak *
|
||||||
|
* electricityispower@gmail.com *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef NCMPCPP_UTILITY_FUNCTIONAL_H
|
||||||
|
#define NCMPCPP_UTILITY_FUNCTIONAL_H
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
// identity function object
|
||||||
|
struct id_
|
||||||
|
{
|
||||||
|
template <typename ValueT>
|
||||||
|
constexpr auto operator()(ValueT &&v) const noexcept
|
||||||
|
-> decltype(std::forward<ValueT>(v))
|
||||||
|
{
|
||||||
|
return std::forward<ValueT>(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NCMPCPP_UTILITY_FUNCTIONAL_H
|
||||||
82
src/utility/option_parser.cpp
Normal file
82
src/utility/option_parser.cpp
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008-2014 by Andrzej Rybczak *
|
||||||
|
* electricityispower@gmail.com *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <boost/regex.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "utility/option_parser.h"
|
||||||
|
|
||||||
|
bool option_parser::run(std::istream &is)
|
||||||
|
{
|
||||||
|
// quoted value. leftmost and rightmost quotation marks are the delimiters.
|
||||||
|
boost::regex quoted("(\\w+)\\h*=\\h*\"(.*)\"[^\"]*");
|
||||||
|
// unquoted value. whitespaces get trimmed.
|
||||||
|
boost::regex unquoted("(\\w+)\\h*=\\h*(.*?)\\h*");
|
||||||
|
boost::smatch match;
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(is, line))
|
||||||
|
{
|
||||||
|
if (boost::regex_match(line, match, quoted)
|
||||||
|
|| boost::regex_match(line, match, unquoted))
|
||||||
|
{
|
||||||
|
std::string option = match[1];
|
||||||
|
auto it = m_parsers.find(option);
|
||||||
|
if (it != m_parsers.end())
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
it->second.parse(match[2]);
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
std::cerr << "Error while processing option \"" << option << "\": " << e.what() << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Unknown option: " << option << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto &p : m_parsers)
|
||||||
|
{
|
||||||
|
if (!p.second.defined())
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
p.second.run_default();
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
std::cerr << "Error while finalizing option \"" << p.first << "\": " << e.what() << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
option_parser::worker yes_no(bool &arg, bool value)
|
||||||
|
{
|
||||||
|
return option_parser::worker([&arg](std::string &&v) {
|
||||||
|
if (v == "yes")
|
||||||
|
arg = true;
|
||||||
|
else if (v == "no")
|
||||||
|
arg = false;
|
||||||
|
else
|
||||||
|
throw std::runtime_error("invalid argument: " + v);
|
||||||
|
}, defaults_to(arg, value));
|
||||||
|
}
|
||||||
131
src/utility/option_parser.h
Normal file
131
src/utility/option_parser.h
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008-2014 by Andrzej Rybczak *
|
||||||
|
* electricityispower@gmail.com *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef NCMPCPP_UTILITY_OPTION_PARSER_H
|
||||||
|
#define NCMPCPP_UTILITY_OPTION_PARSER_H
|
||||||
|
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include <cassert>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "helpers.h"
|
||||||
|
#include "strbuffer.h"
|
||||||
|
#include "utility/functional.h"
|
||||||
|
|
||||||
|
struct option_parser
|
||||||
|
{
|
||||||
|
typedef std::function<void(std::string &&)> parser_t;
|
||||||
|
typedef std::function<void()> default_t;
|
||||||
|
|
||||||
|
struct worker
|
||||||
|
{
|
||||||
|
worker() { }
|
||||||
|
|
||||||
|
template <typename ParserT, typename DefaultT>
|
||||||
|
worker(ParserT &&p, DefaultT &&d)
|
||||||
|
: m_defined(false), m_parser(std::forward<ParserT>(p))
|
||||||
|
, m_default(std::forward<DefaultT>(d)) { }
|
||||||
|
|
||||||
|
template <typename ValueT>
|
||||||
|
void parse(ValueT &&value)
|
||||||
|
{
|
||||||
|
if (m_defined)
|
||||||
|
throw std::runtime_error("option already defined");
|
||||||
|
m_parser(std::forward<ValueT>(value));
|
||||||
|
m_defined = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool defined() const { return m_defined; }
|
||||||
|
void run_default() const { m_default(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_defined;
|
||||||
|
parser_t m_parser;
|
||||||
|
default_t m_default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ParserT, typename DefaultT>
|
||||||
|
void add(const std::string &option, ParserT &&p, DefaultT &&d)
|
||||||
|
{
|
||||||
|
assert(m_parsers.count(option) == 0);
|
||||||
|
m_parsers[option] = worker(std::forward<ParserT>(p), std::forward<DefaultT>(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WorkerT>
|
||||||
|
void add(const std::string &option, WorkerT &&w)
|
||||||
|
{
|
||||||
|
assert(m_parsers.count(option) == 0);
|
||||||
|
m_parsers[option] = std::forward<WorkerT>(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run(std::istream &is);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, worker> m_parsers;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename IntermediateT, typename ArgT, typename TransformT>
|
||||||
|
option_parser::parser_t assign(ArgT &arg, TransformT map = id_())
|
||||||
|
{
|
||||||
|
return [&arg, map](std::string &&v) {
|
||||||
|
try {
|
||||||
|
arg = map(boost::lexical_cast<IntermediateT>(v));
|
||||||
|
} catch (boost::bad_lexical_cast &) {
|
||||||
|
throw std::runtime_error("invalid value: " + v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ArgT, typename ValueT>
|
||||||
|
option_parser::default_t defaults_to(ArgT &arg, ValueT &&value)
|
||||||
|
{
|
||||||
|
return [&arg, value] {
|
||||||
|
arg = std::move(value);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename IntermediateT, typename ArgT, typename ValueT, typename TransformT>
|
||||||
|
option_parser::worker assign_default(ArgT &arg, ValueT &&value, TransformT map)
|
||||||
|
{
|
||||||
|
return option_parser::worker(
|
||||||
|
assign<IntermediateT>(arg, map), defaults_to(arg, map(std::forward<ValueT>(value)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ArgT, typename ValueT>
|
||||||
|
option_parser::worker assign_default(ArgT &arg, ValueT &&value)
|
||||||
|
{
|
||||||
|
return assign_default<ArgT>(arg, std::forward<ValueT>(value), id_());
|
||||||
|
}
|
||||||
|
|
||||||
|
// workers for specific types
|
||||||
|
|
||||||
|
template <typename ValueT, typename TransformT>
|
||||||
|
option_parser::worker buffer(NC::Buffer &arg, ValueT &&value, TransformT map)
|
||||||
|
{
|
||||||
|
return option_parser::worker(assign<std::string>(arg, [&arg, map](std::string &&s) {
|
||||||
|
return map(stringToBuffer(s));
|
||||||
|
}), defaults_to(arg, map(std::forward<ValueT>(value))));
|
||||||
|
}
|
||||||
|
|
||||||
|
option_parser::worker yes_no(bool &arg, bool value);
|
||||||
|
|
||||||
|
#endif // NCMPCPP_UTILITY_OPTION_PARSER_H
|
||||||
191
src/window.cpp
191
src/window.cpp
@@ -21,6 +21,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
|
|
||||||
@@ -158,6 +159,196 @@ int add_base()
|
|||||||
|
|
||||||
namespace NC {//
|
namespace NC {//
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, Color c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case Color::Default:
|
||||||
|
os << "default";
|
||||||
|
break;
|
||||||
|
case Color::Black:
|
||||||
|
os << "black";
|
||||||
|
break;
|
||||||
|
case Color::Red:
|
||||||
|
os << "red";
|
||||||
|
break;
|
||||||
|
case Color::Green:
|
||||||
|
os << "green";
|
||||||
|
break;
|
||||||
|
case Color::Yellow:
|
||||||
|
os << "yellow";
|
||||||
|
break;
|
||||||
|
case Color::Blue:
|
||||||
|
os << "blue";
|
||||||
|
break;
|
||||||
|
case Color::Magenta:
|
||||||
|
os << "magenta";
|
||||||
|
break;
|
||||||
|
case Color::Cyan:
|
||||||
|
os << "cyan";
|
||||||
|
break;
|
||||||
|
case Color::White:
|
||||||
|
os << "white";
|
||||||
|
break;
|
||||||
|
case Color::End:
|
||||||
|
os << "color_end";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream &operator>>(std::istream &is, Color &c)
|
||||||
|
{
|
||||||
|
std::string sc;
|
||||||
|
is >> sc;
|
||||||
|
if (sc == "default")
|
||||||
|
c = Color::Default;
|
||||||
|
else if (sc == "black")
|
||||||
|
c = Color::Black;
|
||||||
|
else if (sc == "red")
|
||||||
|
c = Color::Red;
|
||||||
|
else if (sc == "green")
|
||||||
|
c = Color::Green;
|
||||||
|
else if (sc == "yellow")
|
||||||
|
c = Color::Yellow;
|
||||||
|
else if (sc == "blue")
|
||||||
|
c = Color::Blue;
|
||||||
|
else if (sc == "magenta")
|
||||||
|
c = Color::Magenta;
|
||||||
|
else if (sc == "cyan")
|
||||||
|
c = Color::Cyan;
|
||||||
|
else if (sc == "white")
|
||||||
|
c = Color::White;
|
||||||
|
else if (sc == "color_end")
|
||||||
|
c = Color::End;
|
||||||
|
else
|
||||||
|
is.setstate(std::ios::failbit);
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, Format f)
|
||||||
|
{
|
||||||
|
switch (f)
|
||||||
|
{
|
||||||
|
case Format::None:
|
||||||
|
os << "none";
|
||||||
|
break;
|
||||||
|
case Format::Bold:
|
||||||
|
os << "bold";
|
||||||
|
break;
|
||||||
|
case Format::NoBold:
|
||||||
|
os << "bold";
|
||||||
|
break;
|
||||||
|
case Format::Underline:
|
||||||
|
os << "underline";
|
||||||
|
break;
|
||||||
|
case Format::NoUnderline:
|
||||||
|
os << "no_underline";
|
||||||
|
break;
|
||||||
|
case Format::Reverse:
|
||||||
|
os << "reverse";
|
||||||
|
break;
|
||||||
|
case Format::NoReverse:
|
||||||
|
os << "no_reverse";
|
||||||
|
break;
|
||||||
|
case Format::AltCharset:
|
||||||
|
os << "alt_charset";
|
||||||
|
break;
|
||||||
|
case Format::NoAltCharset:
|
||||||
|
os << "no_alt_charset";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, Border b)
|
||||||
|
{
|
||||||
|
switch (b)
|
||||||
|
{
|
||||||
|
case Border::None:
|
||||||
|
os << "none";
|
||||||
|
break;
|
||||||
|
case Border::Black:
|
||||||
|
os << "black";
|
||||||
|
break;
|
||||||
|
case Border::Red:
|
||||||
|
os << "red";
|
||||||
|
break;
|
||||||
|
case Border::Green:
|
||||||
|
os << "green";
|
||||||
|
break;
|
||||||
|
case Border::Yellow:
|
||||||
|
os << "yellow";
|
||||||
|
break;
|
||||||
|
case Border::Blue:
|
||||||
|
os << "blue";
|
||||||
|
break;
|
||||||
|
case Border::Magenta:
|
||||||
|
os << "magenta";
|
||||||
|
break;
|
||||||
|
case Border::Cyan:
|
||||||
|
os << "cyan";
|
||||||
|
break;
|
||||||
|
case Border::White:
|
||||||
|
os << "white";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream &operator>>(std::istream &is, Border &b)
|
||||||
|
{
|
||||||
|
std::string sb;
|
||||||
|
is >> sb;
|
||||||
|
if (sb == "none")
|
||||||
|
b = Border::None;
|
||||||
|
else if (sb == "black")
|
||||||
|
b = Border::Black;
|
||||||
|
else if (sb == "red")
|
||||||
|
b = Border::Red;
|
||||||
|
else if (sb == "green")
|
||||||
|
b = Border::Green;
|
||||||
|
else if (sb == "yellow")
|
||||||
|
b = Border::Yellow;
|
||||||
|
else if (sb == "blue")
|
||||||
|
b = Border::Blue;
|
||||||
|
else if (sb == "magenta")
|
||||||
|
b = Border::Magenta;
|
||||||
|
else if (sb == "cyan")
|
||||||
|
b = Border::Cyan;
|
||||||
|
else if (sb == "white")
|
||||||
|
b = Border::White;
|
||||||
|
else
|
||||||
|
is.setstate(std::ios::failbit);
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, Scroll s)
|
||||||
|
{
|
||||||
|
switch (s)
|
||||||
|
{
|
||||||
|
case Scroll::Up:
|
||||||
|
os << "scroll_up";
|
||||||
|
break;
|
||||||
|
case Scroll::Down:
|
||||||
|
os << "scroll_down";
|
||||||
|
break;
|
||||||
|
case Scroll::PageUp:
|
||||||
|
os << "scroll_page_up";
|
||||||
|
break;
|
||||||
|
case Scroll::PageDown:
|
||||||
|
os << "scroll_page_down";
|
||||||
|
break;
|
||||||
|
case Scroll::Home:
|
||||||
|
os << "scroll_home";
|
||||||
|
break;
|
||||||
|
case Scroll::End:
|
||||||
|
os << "scroll_end";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
void initScreen(GNUC_UNUSED const char *window_title, bool enable_colors)
|
void initScreen(GNUC_UNUSED const char *window_title, bool enable_colors)
|
||||||
{
|
{
|
||||||
const int ColorsTable[] =
|
const int ColorsTable[] =
|
||||||
|
|||||||
10
src/window.h
10
src/window.h
@@ -114,6 +114,9 @@ namespace NC {//
|
|||||||
/// Colors used by NCurses
|
/// Colors used by NCurses
|
||||||
enum class Color { Default, Black, Red, Green, Yellow, Blue, Magenta, Cyan, White, End };
|
enum class Color { Default, Black, Red, Green, Yellow, Blue, Magenta, Cyan, White, End };
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, Color c);
|
||||||
|
std::istream &operator>>(std::istream &is, Color &c);
|
||||||
|
|
||||||
/// Format flags used by NCurses
|
/// Format flags used by NCurses
|
||||||
enum class Format {
|
enum class Format {
|
||||||
None,
|
None,
|
||||||
@@ -123,12 +126,19 @@ enum class Format {
|
|||||||
AltCharset, NoAltCharset
|
AltCharset, NoAltCharset
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, Format f);
|
||||||
|
|
||||||
/// Available border colors for window
|
/// Available border colors for window
|
||||||
enum class Border { None, Black, Red, Green, Yellow, Blue, Magenta, Cyan, White };
|
enum class Border { None, Black, Red, Green, Yellow, Blue, Magenta, Cyan, White };
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, Border b);
|
||||||
|
std::istream &operator>>(std::istream &is, Border &b);
|
||||||
|
|
||||||
/// This indicates how much the window has to be scrolled
|
/// This indicates how much the window has to be scrolled
|
||||||
enum class Scroll { Up, Down, PageUp, PageDown, Home, End };
|
enum class Scroll { Up, Down, PageUp, PageDown, Home, End };
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, Scroll s);
|
||||||
|
|
||||||
/// Helper function that is invoked each time one will want
|
/// Helper function that is invoked each time one will want
|
||||||
/// to obtain string from Window::getString() function
|
/// to obtain string from Window::getString() function
|
||||||
/// @see Window::getString()
|
/// @see Window::getString()
|
||||||
|
|||||||
Reference in New Issue
Block a user