1 /*
2  * menus.c
3  * Copyright 2011-2014 John Lindgren
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions, and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  *    this list of conditions, and the following disclaimer in the documentation
13  *    provided with the distribution.
14  *
15  * This software is provided "as is" and without any warranty, express or
16  * implied. In no event shall the authors be liable for any damages arising from
17  * the use of this software.
18  */
19 
20 #include <gdk/gdkkeysyms.h>
21 #include <gtk/gtk.h>
22 
23 #include <libaudcore/drct.h>
24 #include <libaudcore/hook.h>
25 #include <libaudcore/i18n.h>
26 #include <libaudcore/interface.h>
27 #include <libaudcore/playlist.h>
28 #include <libaudcore/plugins.h>
29 #include <libaudcore/runtime.h>
30 #include <libaudgui/libaudgui.h>
31 #include <libaudgui/libaudgui-gtk.h>
32 #include <libaudgui/menu.h>
33 
34 #include "gtkui.h"
35 #include "ui_playlist_notebook.h"
36 #include "ui_playlist_widget.h"
37 
38 #include "../ui-common/menu-ops.h"
39 
40 #define SHIFT GDK_SHIFT_MASK
41 #define CTRL GDK_CONTROL_MASK
42 #define ALT GDK_MOD1_MASK
43 
44 #define SHIFT_CTRL (GdkModifierType) (SHIFT | CTRL)
45 #define NONE       0, (GdkModifierType) 0
46 
47 Playlist menu_tab_playlist; /* should really be stored in the menu somehow */
48 
open_files()49 static void open_files () { audgui_run_filebrowser (true); }
open_url()50 static void open_url () { audgui_show_add_url_window (true); }
add_files()51 static void add_files () { audgui_run_filebrowser (false); }
add_url()52 static void add_url () { audgui_show_add_url_window (false); }
53 
configure_effects()54 static void configure_effects () { audgui_show_prefs_for_plugin_type (PluginType::Effect); }
configure_output()55 static void configure_output () { audgui_show_prefs_for_plugin_type (PluginType::Output); }
configure_visualizations()56 static void configure_visualizations () { audgui_show_prefs_for_plugin_type (PluginType::Vis); }
57 
pl_rename()58 static void pl_rename () { start_rename_playlist (Playlist::active_playlist ()); }
pl_close()59 static void pl_close () { audgui_confirm_playlist_delete (Playlist::active_playlist ()); }
60 
pl_tab_play()61 static void pl_tab_play () { menu_tab_playlist.start_playback (); }
62 
pl_tab_rename()63 static void pl_tab_rename ()
64 {
65     if (menu_tab_playlist.exists ())
66         start_rename_playlist (menu_tab_playlist);
67 }
68 
pl_tab_close()69 static void pl_tab_close ()
70 {
71     if (menu_tab_playlist.exists ())
72         audgui_confirm_playlist_delete (menu_tab_playlist);
73 }
74 
get_services_main()75 static GtkWidget * get_services_main () { return audgui_get_plugin_menu (AudMenuID::Main); }
get_services_pl()76 static GtkWidget * get_services_pl () { return audgui_get_plugin_menu (AudMenuID::Playlist); }
77 
78 static const AudguiMenuItem file_items[] = {
79     MenuCommand (N_("_Open Files ..."), "document-open", 'o', CTRL, open_files),
80     MenuCommand (N_("Open _URL ..."), "folder-remote", 'l', CTRL, open_url),
81     MenuCommand (N_("_Add Files ..."), "list-add", 'o', SHIFT_CTRL, add_files),
82     MenuCommand (N_("Add U_RL ..."), "folder-remote", 'l', SHIFT_CTRL, add_url),
83     MenuSep (),
84     MenuCommand (N_("Search _Library"), "edit-find", 'y', CTRL, activate_search_tool),
85     MenuSep (),
86     MenuCommand (N_("A_bout ..."), "help-about", NONE, audgui_show_about_window),
87     MenuCommand (N_("_Settings ..."), "preferences-system", NONE, audgui_show_prefs_window),
88     MenuCommand (N_("_Quit"), "application-exit", 'q', CTRL, aud_quit)
89 };
90 
91 static const AudguiMenuItem playback_items[] = {
92     MenuCommand (N_("_Play"), "media-playback-start", GDK_KEY_Return, CTRL, aud_drct_play),
93     MenuCommand (N_("Paus_e"), "media-playback-pause", ',', CTRL, aud_drct_pause),
94     MenuCommand (N_("_Stop"), "media-playback-stop", '.', CTRL, aud_drct_stop),
95     MenuCommand (N_("Pre_vious"), "media-skip-backward", GDK_KEY_Up, ALT, aud_drct_pl_prev),
96     MenuCommand (N_("_Next"), "media-skip-forward", GDK_KEY_Down, ALT, aud_drct_pl_next),
97     MenuCommand (N_("Previous Album"), nullptr, NONE, aud_drct_pl_prev_album),
98     MenuCommand (N_("Next Album"), nullptr, NONE, aud_drct_pl_next_album),
99     MenuSep (),
100     MenuToggle (N_("_Repeat"), nullptr, 'r', CTRL, nullptr, "repeat", nullptr, "set repeat"),
101     MenuToggle (N_("S_huffle"), nullptr, 's', CTRL, nullptr, "shuffle", nullptr, "set shuffle"),
102     MenuToggle (N_("Shuffle by Albu_m"), nullptr, NONE, nullptr, "album_shuffle", nullptr, "set album_shuffle"),
103     MenuToggle (N_("N_o Playlist Advance"), nullptr, 'n', CTRL, nullptr, "no_playlist_advance", nullptr, "set no_playlist_advance"),
104     MenuToggle (N_("Stop A_fter This Song"), nullptr, 'm', CTRL, nullptr, "stop_after_current_song", nullptr, "set stop_after_current_song"),
105     MenuSep (),
106     MenuCommand (N_("Song _Info ..."), "dialog-information", 'i', CTRL, audgui_infowin_show_current),
107     MenuCommand (N_("Jump to _Time ..."), "go-jump", 'k', CTRL, audgui_jump_to_time),
108     MenuCommand (N_("_Jump to Song ..."), "go-jump", 'j', CTRL, audgui_jump_to_track),
109     MenuSep (),
110     MenuCommand (N_("Set Repeat Point _A"), nullptr, '1', CTRL, set_ab_repeat_a),
111     MenuCommand (N_("Set Repeat Point _B"), nullptr, '2', CTRL, set_ab_repeat_b),
112     MenuCommand (N_("_Clear Repeat Points"), nullptr, '3', CTRL, clear_ab_repeat)
113 };
114 
115 static const AudguiMenuItem dupe_items[] = {
116     MenuCommand (N_("By _Title"), nullptr, NONE, rm_dupes_title),
117     MenuCommand (N_("By _File Name"), nullptr, NONE, rm_dupes_filename),
118     MenuCommand (N_("By File _Path"), nullptr, NONE, rm_dupes_path)
119 };
120 
121 static const AudguiMenuItem sort_items[] = {
122     MenuCommand (N_("By Track _Number"), nullptr, NONE, sort_track),
123     MenuCommand (N_("By _Title"), nullptr, NONE, sort_title),
124     MenuCommand (N_("By _Artist"), nullptr, NONE, sort_artist),
125     MenuCommand (N_("By Al_bum"), nullptr, NONE, sort_album),
126     MenuCommand (N_("By Albu_m Artist"), nullptr, NONE, sort_album_artist),
127     MenuCommand (N_("By Release _Date"), nullptr, NONE, sort_date),
128     MenuCommand (N_("By _Genre"), nullptr, NONE, sort_genre),
129     MenuCommand (N_("By _Length"), nullptr, NONE, sort_length),
130     MenuCommand (N_("By _File Path"), nullptr, NONE, sort_path),
131     MenuCommand (N_("By _Custom Title"), nullptr, NONE, sort_custom_title),
132     MenuCommand (N_("By C_omment"), nullptr, NONE, sort_comment),
133     MenuSep (),
134     MenuCommand (N_("R_everse Order"), "view-sort-descending", NONE, sort_reverse),
135     MenuCommand (N_("_Random Order"), nullptr, NONE, sort_random)
136 };
137 
138 static const AudguiMenuItem sort_sel_items[] = {
139     MenuCommand (N_("By Track _Number"), nullptr, NONE, sort_sel_track),
140     MenuCommand (N_("By _Title"), nullptr, NONE, sort_sel_title),
141     MenuCommand (N_("By _Artist"), nullptr, NONE, sort_sel_artist),
142     MenuCommand (N_("By Al_bum"), nullptr, NONE, sort_sel_album),
143     MenuCommand (N_("By Albu_m Artist"), nullptr, NONE, sort_sel_album_artist),
144     MenuCommand (N_("By Release _Date"), nullptr, NONE, sort_sel_date),
145     MenuCommand (N_("By _Genre"), nullptr, NONE, sort_sel_genre),
146     MenuCommand (N_("By _Length"), nullptr, NONE, sort_sel_length),
147     MenuCommand (N_("By _File Path"), nullptr, NONE, sort_sel_path),
148     MenuCommand (N_("By _Custom Title"), nullptr, NONE, sort_sel_custom_title),
149     MenuCommand (N_("By C_omment"), nullptr, NONE, sort_sel_comment),
150     MenuSep (),
151     MenuCommand (N_("R_everse Order"), "view-sort-descending", NONE, sort_sel_reverse),
152     MenuCommand (N_("_Random Order"), nullptr, NONE, sort_sel_random)
153 };
154 
155 static const AudguiMenuItem playlist_items[] = {
156     MenuCommand (N_("_Play/Resume"), "media-playback-start", GDK_KEY_Return, SHIFT, pl_play),
157     MenuCommand (N_("_Refresh"), "view-refresh", GDK_KEY_F5, (GdkModifierType) 0, pl_refresh),
158     MenuSep (),
159     MenuSub (N_("_Sort"), "view-sort-ascending", {sort_items}),
160     MenuSub (N_("Sort Se_lected"), "view-sort-ascending", {sort_sel_items}),
161     MenuSub (N_("Remove _Duplicates"), "edit-copy", {dupe_items}),
162     MenuCommand (N_("Remove _Unavailable Files"), "dialog-warning", NONE, pl_remove_failed),
163     MenuSep (),
164     MenuCommand (N_("_New"), "document-new", 't', CTRL, pl_new),
165     MenuCommand (N_("Ren_ame ..."), "insert-text", GDK_KEY_F2, (GdkModifierType) 0, pl_rename),
166     MenuCommand (N_("Remo_ve"), "edit-delete", 'w', CTRL, pl_close),
167     MenuSep (),
168     MenuCommand (N_("_Import ..."), "document-open", NONE, audgui_import_playlist),
169     MenuCommand (N_("_Export ..."), "document-save", NONE, audgui_export_playlist),
170     MenuSep (),
171     MenuCommand (N_("Playlist _Manager ..."), "audio-x-generic", 'p', CTRL, activate_playlist_manager),
172     MenuCommand (N_("_Queue Manager ..."), nullptr, 'u', CTRL, audgui_queue_manager_show)
173 };
174 
175 static const AudguiMenuItem output_items[] = {
176     MenuCommand (N_("Volume _Up"), "audio-volume-high", '+', CTRL, volume_up),
177     MenuCommand (N_("Volume _Down"), "audio-volume-low", '-', CTRL, volume_down),
178     MenuSep (),
179     MenuCommand (N_("_Equalizer ..."), "multimedia-volume-control", 'e', CTRL, audgui_show_equalizer_window),
180     MenuCommand (N_("E_ffects ..."), nullptr, NONE, configure_effects),
181     MenuSep (),
182     MenuToggle (N_("_Record Stream"), nullptr, 'd', CTRL, nullptr, "record", nullptr, "set record"),
183     MenuCommand (N_("Audio _Settings ..."), "audio-card", NONE, configure_output)
184 };
185 
186 static const AudguiMenuItem view_items[] = {
187     MenuToggle (N_("Show _Menu Bar"), nullptr, 'm', SHIFT_CTRL, "gtkui", "menu_visible", show_hide_menu),
188     MenuToggle (N_("Show I_nfo Bar"), nullptr, 'i', SHIFT_CTRL, "gtkui", "infoarea_visible", show_hide_infoarea),
189     MenuToggle (N_("Show Info Bar _Album Art"), nullptr, NONE, "gtkui", "infoarea_show_art", show_hide_infoarea_art),
190     MenuToggle (N_("Show Info Bar Vis_ualization"), nullptr, NONE, "gtkui", "infoarea_show_vis", show_hide_infoarea_vis),
191     MenuToggle (N_("Show _Status Bar"), nullptr, 's', SHIFT_CTRL, "gtkui", "statusbar_visible", show_hide_statusbar),
192     MenuSep (),
193     MenuToggle (N_("Show _Remaining Time"), nullptr, 'r', SHIFT_CTRL, "gtkui", "show_remaining_time"),
194     MenuSep (),
195     MenuCommand (N_("_Visualizations ..."), nullptr, NONE, configure_visualizations)
196 };
197 
198 static const AudguiMenuItem main_items[] = {
199     MenuSub (N_("_File"), nullptr, {file_items}),
200     MenuSub (N_("_Playback"), nullptr, {playback_items}),
201     MenuSub (N_("P_laylist"), nullptr, {playlist_items}),
202     MenuSub (N_("_Services"), nullptr, get_services_main),
203     MenuSub (N_("_Output"), nullptr, {output_items}),
204     MenuSub (N_("_View"), nullptr, {view_items})
205 };
206 
207 static const AudguiMenuItem rclick_items[] = {
208     MenuCommand (N_("Song _Info ..."), "dialog-information", 'i', ALT, pl_song_info),
209     MenuCommand (N_("_Queue/Unqueue"), nullptr, 'q', ALT, pl_queue_toggle),
210     MenuSep (),
211     MenuCommand (N_("_Open Containing Folder"), "folder", NONE, pl_open_folder),
212     MenuCommand (N_("_Refresh Selected"), "view-refresh", GDK_KEY_F6, (GdkModifierType) 0, pl_refresh_sel),
213     MenuSep (),
214     MenuCommand (N_("Cu_t"), "edit-cut", NONE, pl_cut),
215     MenuCommand (N_("_Copy"), "edit-copy", NONE, pl_copy),
216     MenuCommand (N_("_Paste"), "edit-paste", NONE, pl_paste),
217     MenuCommand (N_("Paste at _End"), "edit-paste", 'v', SHIFT_CTRL, pl_paste_end),
218     MenuCommand (N_("Select _All"), "edit-select-all", NONE, pl_select_all),
219     MenuSep (),
220     MenuSub (N_("_Services"), nullptr, get_services_pl)
221 };
222 
223 static const AudguiMenuItem tab_items[] = {
224     MenuCommand (N_("_Play"), "media-playback-start", NONE, pl_tab_play),
225     MenuCommand (N_("_Rename ..."), "insert-text", NONE, pl_tab_rename),
226     MenuCommand (N_("Remo_ve"), "edit-delete", NONE, pl_tab_close)
227 };
228 
make_menu_bar(GtkAccelGroup * accel)229 GtkWidget * make_menu_bar (GtkAccelGroup * accel)
230 {
231     GtkWidget * bar = gtk_menu_bar_new ();
232     audgui_menu_init (bar, {main_items}, accel);
233     return bar;
234 }
235 
make_menu_main(GtkAccelGroup * accel)236 GtkWidget * make_menu_main (GtkAccelGroup * accel)
237 {
238     GtkWidget * shell = gtk_menu_new ();
239     audgui_menu_init (shell, {main_items}, accel);
240     return shell;
241 }
242 
make_menu_rclick(GtkAccelGroup * accel)243 GtkWidget * make_menu_rclick (GtkAccelGroup * accel)
244 {
245     GtkWidget * shell = gtk_menu_new ();
246     audgui_menu_init (shell, {rclick_items}, accel);
247     return shell;
248 }
249 
make_menu_tab(GtkAccelGroup * accel)250 GtkWidget * make_menu_tab (GtkAccelGroup * accel)
251 {
252     GtkWidget * shell = gtk_menu_new ();
253     audgui_menu_init (shell, {tab_items}, accel);
254     return shell;
255 }
256