diff options
Diffstat (limited to 'src/libaudgui')
-rw-r--r-- | src/libaudgui/Makefile | 4 | ||||
-rw-r--r-- | src/libaudgui/eq-preset.cc | 7 | ||||
-rw-r--r-- | src/libaudgui/file-opener.cc | 1 | ||||
-rw-r--r-- | src/libaudgui/infopopup.cc | 2 | ||||
-rw-r--r-- | src/libaudgui/infowin.cc | 51 | ||||
-rw-r--r-- | src/libaudgui/init.cc | 1 | ||||
-rw-r--r-- | src/libaudgui/internal.h | 3 | ||||
-rw-r--r-- | src/libaudgui/jump-to-track-cache.cc | 2 | ||||
-rw-r--r-- | src/libaudgui/jump-to-track.cc | 2 | ||||
-rw-r--r-- | src/libaudgui/libaudgui-gtk.h | 4 | ||||
-rw-r--r-- | src/libaudgui/list.cc | 42 | ||||
-rw-r--r-- | src/libaudgui/menu.cc | 2 | ||||
-rw-r--r-- | src/libaudgui/playlists.cc | 3 | ||||
-rw-r--r-- | src/libaudgui/prefs-widget.cc | 76 | ||||
-rw-r--r-- | src/libaudgui/prefs-window.cc | 39 | ||||
-rw-r--r-- | src/libaudgui/preset-browser.cc | 2 | ||||
-rw-r--r-- | src/libaudgui/queue-manager.cc | 2 | ||||
-rw-r--r-- | src/libaudgui/status.cc | 11 | ||||
-rw-r--r-- | src/libaudgui/urilist.cc | 37 | ||||
-rw-r--r-- | src/libaudgui/util.cc | 80 |
20 files changed, 260 insertions, 111 deletions
diff --git a/src/libaudgui/Makefile b/src/libaudgui/Makefile index 55ba07f..dde93e1 100644 --- a/src/libaudgui/Makefile +++ b/src/libaudgui/Makefile @@ -1,6 +1,6 @@ SHARED_LIB = ${LIB_PREFIX}audgui${LIB_SUFFIX} -LIB_MAJOR = 3 -LIB_MINOR = 1 +LIB_MAJOR = 4 +LIB_MINOR = 0 SRCS = about.cc \ confirm.cc \ diff --git a/src/libaudgui/eq-preset.cc b/src/libaudgui/eq-preset.cc index 2aa37b0..a2f1c9d 100644 --- a/src/libaudgui/eq-preset.cc +++ b/src/libaudgui/eq-preset.cc @@ -103,14 +103,13 @@ static void populate_list () static void save_list () { - auto sort_cb = [] (const EqualizerPreset & a, const EqualizerPreset & b, void *) - { return strcmp (a.name, b.name); }; - Index<EqualizerPreset> presets; for (const PresetItem & item : preset_list) presets.append (item.preset); - presets.sort (sort_cb, nullptr); + presets.sort ([] (const EqualizerPreset & a, const EqualizerPreset & b) + { return strcmp (a.name, b.name); }); + aud_eq_write_presets (presets, "eq.preset"); } diff --git a/src/libaudgui/file-opener.cc b/src/libaudgui/file-opener.cc index a51abb8..efe339c 100644 --- a/src/libaudgui/file-opener.cc +++ b/src/libaudgui/file-opener.cc @@ -104,6 +104,7 @@ static GtkWidget * create_filebrowser (gboolean open) gtk_container_add ((GtkContainer *) window, vbox); GtkWidget * chooser = gtk_file_chooser_widget_new (GTK_FILE_CHOOSER_ACTION_OPEN); + gtk_file_chooser_set_local_only ((GtkFileChooser *) chooser, false); gtk_file_chooser_set_select_multiple ((GtkFileChooser *) chooser, true); String path = aud_get_str ("audgui", "filesel_path"); diff --git a/src/libaudgui/infopopup.cc b/src/libaudgui/infopopup.cc index a117b2b..bc2edfd 100644 --- a/src/libaudgui/infopopup.cc +++ b/src/libaudgui/infopopup.cc @@ -318,7 +318,7 @@ EXPORT void audgui_infopopup_show (int playlist, int entry) String filename = aud_playlist_entry_get_filename (playlist, entry); Tuple tuple = aud_playlist_entry_get_tuple (playlist, entry); - if (filename && tuple) + if (filename && tuple.valid ()) infopopup_show (filename, tuple); } diff --git a/src/libaudgui/infowin.cc b/src/libaudgui/infowin.cc index 353c9c3..5002dfc 100644 --- a/src/libaudgui/infowin.cc +++ b/src/libaudgui/infowin.cc @@ -72,6 +72,7 @@ static struct { static GtkWidget * infowin; static int current_playlist_id, current_entry; static String current_file; +static Tuple current_tuple; static PluginHandle * current_decoder = nullptr; static bool can_write = false; static QueuedFunc ministatus_timer; @@ -200,20 +201,17 @@ static void ministatus_display_message (const char * text) static void infowin_update_tuple () { - Tuple tuple; - tuple.set_filename (current_file); - - set_field_str_from_entry (tuple, Tuple::Title, widgets.title); - set_field_str_from_entry (tuple, Tuple::Artist, widgets.artist); - set_field_str_from_entry (tuple, Tuple::Album, widgets.album); - set_field_str_from_entry (tuple, Tuple::AlbumArtist, widgets.album_artist); - set_field_str_from_entry (tuple, Tuple::Comment, widgets.comment); - set_field_str_from_entry (tuple, Tuple::Genre, gtk_bin_get_child ((GtkBin *) - widgets.genre)); - set_field_int_from_entry (tuple, Tuple::Year, widgets.year); - set_field_int_from_entry (tuple, Tuple::Track, widgets.track); - - if (aud_file_write_tuple (current_file, current_decoder, tuple)) + set_field_str_from_entry (current_tuple, Tuple::Title, widgets.title); + set_field_str_from_entry (current_tuple, Tuple::Artist, widgets.artist); + set_field_str_from_entry (current_tuple, Tuple::Album, widgets.album); + set_field_str_from_entry (current_tuple, Tuple::AlbumArtist, widgets.album_artist); + set_field_str_from_entry (current_tuple, Tuple::Comment, widgets.comment); + set_field_str_from_entry (current_tuple, Tuple::Genre, + gtk_bin_get_child ((GtkBin *) widgets.genre)); + set_field_int_from_entry (current_tuple, Tuple::Year, widgets.year); + set_field_int_from_entry (current_tuple, Tuple::Track, widgets.track); + + if (aud_file_write_tuple (current_file, current_decoder, current_tuple)) { ministatus_display_message (_("Save successful")); gtk_widget_set_sensitive (widgets.apply, false); @@ -279,6 +277,7 @@ static void infowin_destroyed () infowin = nullptr; current_file = String (); + current_tuple = Tuple (); current_decoder = nullptr; } @@ -408,7 +407,7 @@ static void create_infowin () hook_associate ("art ready", (HookFunction) infowin_display_image, nullptr); } -static void infowin_show (int list, int entry, const char * filename, +static void infowin_show (int list, int entry, const String & filename, const Tuple & tuple, PluginHandle * decoder, bool writable) { if (! infowin) @@ -416,7 +415,8 @@ static void infowin_show (int list, int entry, const char * filename, current_playlist_id = aud_playlist_get_unique_id (list); current_entry = entry; - current_file = String (filename); + current_file = filename; + current_tuple = tuple.ref (); current_decoder = decoder; can_write = writable; @@ -469,17 +469,20 @@ EXPORT void audgui_infowin_show (int playlist, int entry) String error; PluginHandle * decoder = aud_playlist_entry_get_decoder (playlist, entry, Playlist::Wait, & error); + Tuple tuple = decoder ? aud_playlist_entry_get_tuple (playlist, entry, + Playlist::Wait, & error) : Tuple (); - if (decoder && ! aud_custom_infowin (filename, decoder)) + if (decoder && tuple.valid () && ! aud_custom_infowin (filename, decoder)) { - Tuple tuple = aud_playlist_entry_get_tuple (playlist, entry, Playlist::Wait, & error); - if (tuple) - { - tuple.delete_fallbacks (); - infowin_show (playlist, entry, filename, tuple, decoder, - aud_file_can_write_tuple (filename, decoder)); - } + /* cuesheet entries cannot be updated */ + bool can_write = aud_file_can_write_tuple (filename, decoder) && + ! tuple.is_set (Tuple::StartTime); + + tuple.delete_fallbacks (); + infowin_show (playlist, entry, filename, tuple, decoder, can_write); } + else + audgui_infowin_hide (); if (error) aud_ui_show_error (str_printf (_("Error opening %s:\n%s"), diff --git a/src/libaudgui/init.cc b/src/libaudgui/init.cc index d560bc3..ede7414 100644 --- a/src/libaudgui/init.cc +++ b/src/libaudgui/init.cc @@ -170,5 +170,4 @@ EXPORT void audgui_cleanup () plugin_menu_cleanup (); plugin_prefs_cleanup (); - urilist_cleanup (); } diff --git a/src/libaudgui/internal.h b/src/libaudgui/internal.h index d54204d..b43c97c 100644 --- a/src/libaudgui/internal.h +++ b/src/libaudgui/internal.h @@ -61,7 +61,4 @@ GtkWidget * plugin_view_new (PluginType type); void status_init (); void status_cleanup (); -/* urilist.c */ -void urilist_cleanup (); - #endif /* AUDGUI_INTERNAL_H */ diff --git a/src/libaudgui/jump-to-track-cache.cc b/src/libaudgui/jump-to-track-cache.cc index db07995..7dcf242 100644 --- a/src/libaudgui/jump-to-track-cache.cc +++ b/src/libaudgui/jump-to-track-cache.cc @@ -132,7 +132,7 @@ void JumpToTrackCache::init () item.entry = entry; item.path = String (uri_to_display (aud_playlist_entry_get_filename (playlist, entry))); - Tuple tuple = aud_playlist_entry_get_tuple (playlist, entry, Playlist::Guess); + Tuple tuple = aud_playlist_entry_get_tuple (playlist, entry, Playlist::NoWait); item.title = tuple.get_str (Tuple::Title); item.artist = tuple.get_str (Tuple::Artist); item.album = tuple.get_str (Tuple::Album); diff --git a/src/libaudgui/jump-to-track.cc b/src/libaudgui/jump-to-track.cc index b903912..a681163 100644 --- a/src/libaudgui/jump-to-track.cc +++ b/src/libaudgui/jump-to-track.cc @@ -220,7 +220,7 @@ static void list_get_value (void * user, int row, int column, GValue * value) g_value_set_int (value, 1 + entry); break; case 1: - Tuple tuple = aud_playlist_entry_get_tuple (playlist, entry, Playlist::Guess); + Tuple tuple = aud_playlist_entry_get_tuple (playlist, entry, Playlist::NoWait); g_value_set_string (value, tuple.get_str (Tuple::FormattedTitle)); break; } diff --git a/src/libaudgui/libaudgui-gtk.h b/src/libaudgui/libaudgui-gtk.h index fc144a5..8bd8c08 100644 --- a/src/libaudgui/libaudgui-gtk.h +++ b/src/libaudgui/libaudgui-gtk.h @@ -63,6 +63,10 @@ void audgui_simple_message (GtkWidget * * widget, GtkMessageType type, GtkWidget * audgui_button_new (const char * text, const char * icon, AudguiCallback callback, void * data); +GtkWidget * audgui_file_entry_new (GtkFileChooserAction action, const char * title); +String audgui_file_entry_get_uri (GtkWidget * entry); +void audgui_file_entry_set_uri (GtkWidget * entry, const char * uri); + GtkWidget * audgui_dialog_new (GtkMessageType type, const char * title, const char * text, GtkWidget * button1, GtkWidget * button2); void audgui_dialog_add_widget (GtkWidget * dialog, GtkWidget * widget); diff --git a/src/libaudgui/list.cc b/src/libaudgui/list.cc index a0b6ce6..906922b 100644 --- a/src/libaudgui/list.cc +++ b/src/libaudgui/list.cc @@ -343,6 +343,10 @@ static void drag_begin (GtkWidget * widget, GdkDragContext * context, g_signal_stop_emission_by_name (widget, "drag-begin"); model->dragging = true; + + /* If button_press_cb preserved a multiple selection, tell button_release_cb + * not to clear it. */ + model->frozen = false; } static void drag_end (GtkWidget * widget, GdkDragContext * context, @@ -426,14 +430,10 @@ static gboolean drag_motion (GtkWidget * widget, GdkDragContext * context, { g_signal_stop_emission_by_name (widget, "drag-motion"); - /* If button_press_cb preserved a multiple selection, tell button_release_cb - * not to clear it. */ - model->frozen = false; - - if (model->dragging && MODEL_HAS_CB (model, shift_rows)) /* dragging within same list */ - gdk_drag_status (context, GDK_ACTION_MOVE, time); - else if (MODEL_HAS_CB (model, data_type)) /* cross-widget dragging */ - gdk_drag_status (context, GDK_ACTION_COPY, time); + if (model->dragging && MODEL_HAS_CB (model, shift_rows)) + gdk_drag_status (context, GDK_ACTION_MOVE, time); /* dragging within same list */ + else if (MODEL_HAS_CB (model, data_type) && MODEL_HAS_CB (model, receive_data)) + gdk_drag_status (context, GDK_ACTION_COPY, time); /* cross-widget dragging */ else return false; @@ -489,15 +489,17 @@ static gboolean drag_drop (GtkWidget * widget, GdkDragContext * context, int x, gboolean success = true; int row = audgui_list_row_at_point_rounded (widget, x, y); - if (model->dragging && MODEL_HAS_CB (model, shift_rows)) /* dragging within same list */ + if (model->dragging && MODEL_HAS_CB (model, shift_rows)) { + /* dragging within same list */ if (model->clicked_row >= 0 && model->clicked_row < model->rows) model->cbs->shift_rows (model->user, model->clicked_row, row); else success = false; } - else if (MODEL_HAS_CB (model, data_type)) /* cross-widget dragging */ + else if (MODEL_HAS_CB (model, data_type) && MODEL_HAS_CB (model, receive_data)) { + /* cross-widget dragging */ model->receive_row = row; gtk_drag_get_data (widget, context, gdk_atom_intern (model->cbs->data_type, false), time); @@ -608,18 +610,22 @@ EXPORT GtkWidget * audgui_list_new_real (const AudguiListCallbacks * cbs, int cb gboolean supports_drag = false; - if (MODEL_HAS_CB (model, data_type) && MODEL_HAS_CB (model, get_data) && - MODEL_HAS_CB (model, receive_data)) + if (MODEL_HAS_CB (model, data_type) && + (MODEL_HAS_CB (model, get_data) || MODEL_HAS_CB (model, receive_data))) { const GtkTargetEntry target = {(char *) cbs->data_type, 0, 0}; - gtk_drag_source_set (list, GDK_BUTTON1_MASK, & target, 1, - GDK_ACTION_COPY); - gtk_drag_dest_set (list, (GtkDestDefaults) 0, & target, 1, GDK_ACTION_COPY); + if (MODEL_HAS_CB (model, get_data)) + { + gtk_drag_source_set (list, GDK_BUTTON1_MASK, & target, 1, GDK_ACTION_COPY); + g_signal_connect (list, "drag-data-get", (GCallback) drag_data_get, model); + } - g_signal_connect (list, "drag-data-get", (GCallback) drag_data_get, model); - g_signal_connect (list, "drag-data-received", (GCallback) - drag_data_received, model); + if (MODEL_HAS_CB (model, receive_data)) + { + gtk_drag_dest_set (list, (GtkDestDefaults) 0, & target, 1, GDK_ACTION_COPY); + g_signal_connect (list, "drag-data-received", (GCallback) drag_data_received, model); + } supports_drag = true; } diff --git a/src/libaudgui/menu.cc b/src/libaudgui/menu.cc index 3069d8b..ef5ac34 100644 --- a/src/libaudgui/menu.cc +++ b/src/libaudgui/menu.cc @@ -65,7 +65,7 @@ static void unhook_cb (GtkCheckMenuItem * check, const AudguiMenuItem * item) EXPORT GtkWidget * audgui_menu_item_new_with_domain (const AudguiMenuItem * item, GtkAccelGroup * accel, const char * domain) { - const char * name = domain ? dgettext (domain, item->name) : item->name; + const char * name = (domain && item->name) ? dgettext (domain, item->name) : item->name; GtkWidget * widget = nullptr; if (name && item->func && ! item->cname) /* normal widget */ diff --git a/src/libaudgui/playlists.cc b/src/libaudgui/playlists.cc index d106292..4922fba 100644 --- a/src/libaudgui/playlists.cc +++ b/src/libaudgui/playlists.cc @@ -68,7 +68,7 @@ static void finish_job (void * data) Playlist::GetMode mode = Playlist::Wait; if (aud_get_bool (nullptr, "metadata_on_play")) - mode = Playlist::Nothing; + mode = Playlist::NoWait; if (list >= 0) { @@ -184,6 +184,7 @@ static void create_selector (ImportExportJob * job, const char * filename, const } job->selector = gtk_file_chooser_dialog_new (title, nullptr, action, nullptr, nullptr); + gtk_file_chooser_set_local_only ((GtkFileChooser *) job->selector, false); if (filename) gtk_file_chooser_set_uri ((GtkFileChooser *) job->selector, filename); diff --git a/src/libaudgui/prefs-widget.cc b/src/libaudgui/prefs-widget.cc index df6b68b..c240ece 100644 --- a/src/libaudgui/prefs-widget.cc +++ b/src/libaudgui/prefs-widget.cc @@ -34,7 +34,7 @@ static void widget_changed (GtkWidget * widget, const PreferencesWidget * w) { case PreferencesWidget::CheckButton: { - gboolean set = gtk_toggle_button_get_active ((GtkToggleButton *) widget); + bool set = gtk_toggle_button_get_active ((GtkToggleButton *) widget); w->cfg.set_bool (set); auto child = (GtkWidget *) g_object_get_data ((GObject *) widget, "child"); @@ -45,10 +45,17 @@ static void widget_changed (GtkWidget * widget, const PreferencesWidget * w) } case PreferencesWidget::RadioButton: - if (gtk_toggle_button_get_active ((GtkToggleButton *) widget)) + { + bool set = gtk_toggle_button_get_active ((GtkToggleButton *) widget); + if (set) w->cfg.set_int (w->data.radio_btn.value); + auto child = (GtkWidget *) g_object_get_data ((GObject *) widget, "child"); + if (child) + gtk_widget_set_sensitive (child, set); + break; + } case PreferencesWidget::SpinButton: if (w->cfg.type == WidgetConfig::Int) @@ -66,6 +73,13 @@ static void widget_changed (GtkWidget * widget, const PreferencesWidget * w) w->cfg.set_string (gtk_entry_get_text ((GtkEntry *) widget)); break; + case PreferencesWidget::FileEntry: + { + String uri = audgui_file_entry_get_uri (widget); + w->cfg.set_string (uri ? uri : ""); + break; + } + case PreferencesWidget::ComboBox: { auto items = (const ComboItem *) g_object_get_data ((GObject *) widget, "comboitems"); @@ -120,6 +134,10 @@ static void widget_update (void *, void * widget) gtk_entry_set_text ((GtkEntry *) widget, w->cfg.get_string ()); break; + case PreferencesWidget::FileEntry: + audgui_file_entry_set_uri ((GtkWidget *) widget, w->cfg.get_string ()); + break; + case PreferencesWidget::ComboBox: combobox_update ((GtkWidget *) widget, w); break; @@ -158,6 +176,7 @@ static void widget_init (GtkWidget * widget, const PreferencesWidget * w) break; case PreferencesWidget::Entry: + case PreferencesWidget::FileEntry: case PreferencesWidget::ComboBox: g_signal_connect (widget, "changed", (GCallback) widget_changed, (void *) w); break; @@ -247,6 +266,31 @@ static void create_entry (const PreferencesWidget * widget, GtkWidget * * label, widget_init (* entry, widget); } +/* WIDGET_FILE_ENTRY */ + +static void create_file_entry (const PreferencesWidget * widget, + GtkWidget * * label, GtkWidget * * entry, const char * domain) +{ + switch (widget->data.file_entry.mode) + { + case FileSelectMode::File: + * entry = audgui_file_entry_new (GTK_FILE_CHOOSER_ACTION_OPEN, _("Choose File")); + break; + + case FileSelectMode::Folder: + * entry = audgui_file_entry_new (GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, _("Choose Folder")); + break; + } + + if (widget->label) + { + * label = gtk_label_new (dgettext (domain, widget->label)); + gtk_misc_set_alignment ((GtkMisc *) * label, 1, 0.5); + } + + widget_init (* entry, widget); +} + /* WIDGET_COMBO_BOX */ static void combobox_update (GtkWidget * combobox, const PreferencesWidget * widget) @@ -339,6 +383,11 @@ static void fill_table (GtkWidget * table, middle_policy = (GtkAttachOptions) (GTK_EXPAND | GTK_FILL); break; + case PreferencesWidget::FileEntry: + create_file_entry (& w, & widget_left, & widget_middle, domain); + middle_policy = (GtkAttachOptions) (GTK_EXPAND | GTK_FILL); + break; + case PreferencesWidget::ComboBox: create_cbox (& w, & widget_left, & widget_middle, domain); break; @@ -371,7 +420,7 @@ void audgui_create_widgets_with_domain (GtkWidget * box, { GtkWidget * widget = nullptr, * child_box = nullptr; bool disable_child = false; - GSList * radio_btn_group = nullptr; + GSList * radio_btn_group[2] = {}; int indent = 0; int spacing = 0; @@ -406,8 +455,11 @@ void audgui_create_widgets_with_domain (GtkWidget * box, widget = nullptr; disable_child = false; - if (radio_btn_group && w.type != PreferencesWidget::RadioButton) - radio_btn_group = nullptr; + if (w.type != PreferencesWidget::RadioButton) + radio_btn_group[w.child] = nullptr; + + if (! w.child) + radio_btn_group[true] = nullptr; switch (w.type) { @@ -449,9 +501,10 @@ void audgui_create_widgets_with_domain (GtkWidget * box, } case PreferencesWidget::RadioButton: - widget = gtk_radio_button_new_with_mnemonic (radio_btn_group, - dgettext (domain, w.label)); - radio_btn_group = gtk_radio_button_get_group ((GtkRadioButton *) widget); + widget = gtk_radio_button_new_with_mnemonic + (radio_btn_group[w.child], dgettext (domain, w.label)); + radio_btn_group[w.child] = gtk_radio_button_get_group ((GtkRadioButton *) widget); + disable_child = (w.cfg.get_int () != w.data.radio_btn.value); widget_init (widget, & w); break; @@ -503,11 +556,16 @@ void audgui_create_widgets_with_domain (GtkWidget * box, break; case PreferencesWidget::Entry: + case PreferencesWidget::FileEntry: { widget = gtk_hbox_new (false, 6); GtkWidget * entry = nullptr; - create_entry (& w, & label, & entry, domain); + + if (w.type == PreferencesWidget::FileEntry) + create_file_entry (& w, & label, & entry, domain); + else + create_entry (& w, & label, & entry, domain); if (label) gtk_box_pack_start ((GtkBox *) widget, label, false, false, 0); diff --git a/src/libaudgui/prefs-window.cc b/src/libaudgui/prefs-window.cc index 948119c..5ba9a09 100644 --- a/src/libaudgui/prefs-window.cc +++ b/src/libaudgui/prefs-window.cc @@ -125,12 +125,20 @@ static const ComboItem chardet_detector_presets[] = { }; static const ComboItem bitdepth_elements[] = { + ComboItem (N_("Automatic"), -1), ComboItem ("16", 16), ComboItem ("24", 24), ComboItem ("32", 32), ComboItem (N_("Floating point"), 0) }; +static const ComboItem record_elements[] = { + ComboItem (N_("As decoded"), (int) OutputStream::AsDecoded), + ComboItem (N_("After applying ReplayGain"), (int) OutputStream::AfterReplayGain), + ComboItem (N_("After applying effects"), (int) OutputStream::AfterEffects), + ComboItem (N_("After applying equalization"), (int) OutputStream::AfterEqualizer) +}; + static Index<ComboItem> iface_combo_elements; static int iface_combo_selected; static GtkWidget * iface_prefs_box; @@ -160,7 +168,7 @@ static void output_bit_depth_changed (); static const PreferencesWidget output_combo_widgets[] = { WidgetCombo (N_("Output plugin:"), - WidgetInt (output_combo_selected, output_combo_changed), + WidgetInt (output_combo_selected, output_combo_changed, "audgui update output combo"), {0, output_combo_fill}), WidgetCustomGTK (output_create_config_button), WidgetCustomGTK (output_create_about_button) @@ -199,15 +207,19 @@ static const PreferencesWidget audio_page_widgets[] = { WidgetSpin (N_("Buffer size:"), WidgetInt (0, "output_buffer_size"), {100, 10000, 1000, N_("ms")}), - WidgetCustomGTK (record_create_checkbox), - WidgetBox ({{record_buttons}, true}, - WIDGET_CHILD), WidgetCheck (N_("Soft clipping"), WidgetBool (0, "soft_clipping")), WidgetCheck (N_("Use software volume control (not recommended)"), WidgetBool (0, "software_volume_control")), - WidgetLabel (N_("<b>Replay Gain</b>")), - WidgetCheck (N_("Enable Replay Gain"), + WidgetLabel (N_("<b>Recording Settings</b>")), + WidgetCustomGTK (record_create_checkbox), + WidgetBox ({{record_buttons}, true}, + WIDGET_CHILD), + WidgetCombo (N_("Record stream:"), + WidgetInt (0, "record_stream"), + {{record_elements}}), + WidgetLabel (N_("<b>ReplayGain</b>")), + WidgetCheck (N_("Enable ReplayGain"), WidgetBool (0, "enable_replay_gain")), WidgetCheck (N_("Album mode"), WidgetBool (0, "replay_gain_album"), @@ -215,8 +227,6 @@ static const PreferencesWidget audio_page_widgets[] = { WidgetCheck (N_("Prevent clipping (recommended)"), WidgetBool (0, "enable_clipping_prevention"), WIDGET_CHILD), - WidgetLabel (N_("<b>Adjust Levels</b>"), - WIDGET_CHILD), WidgetTable ({{gain_table}}, WIDGET_CHILD) }; @@ -279,8 +289,10 @@ static const PreferencesWidget playlist_page_widgets[] = { WidgetLabel (N_("<b>Song Display</b>")), WidgetCheck (N_("Show song numbers"), WidgetBool (0, "show_numbers_in_pl", send_title_change)), - WidgetCheck (N_("Show leading zeroes (02:00 instead of 2:00)"), + WidgetCheck (N_("Show leading zeroes (02:00 vs. 2:00)"), WidgetBool (0, "leading_zero", send_title_change)), + WidgetCheck (N_("Show hours separately (1:30:00 vs. 90:00)"), + WidgetBool (0, "show_hours", send_title_change)), WidgetCustomGTK (create_titlestring_table), WidgetLabel (N_("<b>Compatibility</b>")), WidgetCheck (N_("Interpret \\ (backward slash) as a folder delimiter"), @@ -617,13 +629,20 @@ static void create_appearance_category () static void output_combo_changed () { - PluginHandle * plugin = aud_plugin_list (PluginType::Output)[output_combo_selected]; + auto & list = aud_plugin_list (PluginType::Output); + PluginHandle * plugin = list[output_combo_selected]; if (aud_plugin_enable (plugin, true)) { gtk_widget_set_sensitive (output_config_button, aud_plugin_has_configure (plugin)); gtk_widget_set_sensitive (output_about_button, aud_plugin_has_about (plugin)); } + else + { + /* set combo box back to current output */ + output_combo_selected = list.find (aud_plugin_get_current (PluginType::Output)); + hook_call ("audgui update output combo", nullptr); + } } static ArrayRef<ComboItem> output_combo_fill () diff --git a/src/libaudgui/preset-browser.cc b/src/libaudgui/preset-browser.cc index fa7ccb5..9144086 100644 --- a/src/libaudgui/preset-browser.cc +++ b/src/libaudgui/preset-browser.cc @@ -51,6 +51,8 @@ static void show_preset_browser (const char * title, gboolean save, GTK_RESPONSE_CANCEL, save ? _("Save") : _("Load"), GTK_RESPONSE_ACCEPT, nullptr); + gtk_file_chooser_set_local_only ((GtkFileChooser *) browser, false); + if (default_filename) gtk_file_chooser_set_current_name ((GtkFileChooser *) browser, default_filename); diff --git a/src/libaudgui/queue-manager.cc b/src/libaudgui/queue-manager.cc index 195a6ba..2b5e6d0 100644 --- a/src/libaudgui/queue-manager.cc +++ b/src/libaudgui/queue-manager.cc @@ -45,7 +45,7 @@ static void get_value (void * user, int row, int column, GValue * value) g_value_set_int (value, 1 + entry); break; case COLUMN_TITLE: - Tuple tuple = aud_playlist_entry_get_tuple (list, entry, Playlist::Guess); + Tuple tuple = aud_playlist_entry_get_tuple (list, entry, Playlist::NoWait); g_value_set_string (value, tuple.get_str (Tuple::FormattedTitle)); break; } diff --git a/src/libaudgui/status.cc b/src/libaudgui/status.cc index fa04fd3..6ba9b3c 100644 --- a/src/libaudgui/status.cc +++ b/src/libaudgui/status.cc @@ -27,7 +27,7 @@ static GtkWidget * progress_window; static GtkWidget * progress_label, * progress_label_2; -static GtkWidget * error_window; +static GtkWidget * error_window, * info_window; static void create_progress_window () { @@ -85,12 +85,18 @@ static void show_error (void * data, void * user) audgui_simple_message (& error_window, GTK_MESSAGE_ERROR, _("Error"), (const char *) data); } +static void show_info (void * data, void * user) +{ + audgui_simple_message (& info_window, GTK_MESSAGE_INFO, _("Information"), (const char *) data); +} + void status_init () { hook_associate ("ui show progress", show_progress, nullptr); hook_associate ("ui show progress 2", show_progress_2, nullptr); hook_associate ("ui hide progress", hide_progress, nullptr); hook_associate ("ui show error", show_error, nullptr); + hook_associate ("ui show info", show_info, nullptr); } void status_cleanup () @@ -99,9 +105,12 @@ void status_cleanup () hook_dissociate ("ui show progress 2", show_progress_2); hook_dissociate ("ui hide progress", hide_progress); hook_dissociate ("ui show error", show_error); + hook_dissociate ("ui show info", show_info); if (progress_window) gtk_widget_destroy (progress_window); if (error_window) gtk_widget_destroy (error_window); + if (info_window) + gtk_widget_destroy (info_window); } diff --git a/src/libaudgui/urilist.cc b/src/libaudgui/urilist.cc index 1dc04e4..a0809f4 100644 --- a/src/libaudgui/urilist.cc +++ b/src/libaudgui/urilist.cc @@ -21,33 +21,13 @@ #include <libaudcore/audstrings.h> #include <libaudcore/drct.h> -#include <libaudcore/mainloop.h> -#include <libaudcore/multihash.h> #include <libaudcore/playlist.h> -#include <libaudcore/tuple.h> -#include <libaudcore/vfs.h> #include "libaudgui.h" -static SimpleHash<String, Tuple> tuple_cache; -static QueuedFunc cleanup_timer; - -void urilist_cleanup () -{ - tuple_cache.clear (); - cleanup_timer.stop (); -} - static String check_uri (const char * name) { - if (! strstr (name, "://")) - { - StringBuf uri = filename_to_uri (name); - if (uri) - return String (uri); - } - - return String (name); + return strstr (name, "://") ? String (name) : String (filename_to_uri (name)); } static Index<PlaylistAddItem> urilist_to_index (const char * list) @@ -67,12 +47,7 @@ static Index<PlaylistAddItem> urilist_to_index (const char * list) next = end = strchr (list, 0); if (end > list) - { - String filename = check_uri (str_copy (list, end - list)); - const Tuple * tuple = tuple_cache.lookup (filename); - - index.append (filename, tuple ? tuple->ref () : Tuple ()); - } + index.append (check_uri (str_copy (list, end - list))); list = next; } @@ -92,6 +67,8 @@ EXPORT void audgui_urilist_insert (int playlist, int at, const char * list) EXPORT Index<char> audgui_urilist_create_from_selected (int playlist) { + aud_playlist_cache_selected (playlist); + Index<char> buf; int entries = aud_playlist_entry_count (playlist); @@ -103,15 +80,9 @@ EXPORT Index<char> audgui_urilist_create_from_selected (int playlist) buf.append ('\n'); String filename = aud_playlist_entry_get_filename (playlist, count); - Tuple tuple = aud_playlist_entry_get_tuple (playlist, count, Playlist::Nothing); - buf.insert (filename, -1, strlen (filename)); - if (tuple) - tuple_cache.add (filename, std::move (tuple)); } } - cleanup_timer.queue (30000, [] (void *) { urilist_cleanup (); }, nullptr); - return buf; } diff --git a/src/libaudgui/util.cc b/src/libaudgui/util.cc index 54e1c74..98307e5 100644 --- a/src/libaudgui/util.cc +++ b/src/libaudgui/util.cc @@ -125,6 +125,86 @@ EXPORT GtkWidget * audgui_button_new (const char * text, const char * icon, return button; } +struct FileEntryData { + GtkFileChooserAction action; + String title; +}; + +static void entry_response_cb (GtkWidget * dialog, int response, GtkWidget * entry) +{ + if (response == GTK_RESPONSE_ACCEPT) + { + char * uri = gtk_file_chooser_get_uri ((GtkFileChooser *) dialog); + if (uri) + { + audgui_file_entry_set_uri (entry, uri); + g_free (uri); + } + } + + gtk_widget_destroy (dialog); +} + +static void entry_browse_cb (GtkWidget * entry, GtkEntryIconPosition pos, + GdkEvent * event, const FileEntryData * data) +{ + GtkWidget * dialog = gtk_file_chooser_dialog_new (data->title, nullptr, + data->action, _("Open"), GTK_RESPONSE_ACCEPT, _("Cancel"), + GTK_RESPONSE_REJECT, nullptr); + + gtk_file_chooser_set_local_only ((GtkFileChooser *) dialog, false); + + String uri = audgui_file_entry_get_uri (entry); + if (uri) + gtk_file_chooser_set_uri ((GtkFileChooser *) dialog, uri); + + g_signal_connect (dialog, "response", (GCallback) entry_response_cb, entry); + g_signal_connect_object (entry, "destroy", (GCallback) gtk_widget_destroy, + dialog, G_CONNECT_SWAPPED); + + gtk_widget_show (dialog); +} + +EXPORT GtkWidget * audgui_file_entry_new (GtkFileChooserAction action, const char * title) +{ + GtkWidget * entry = gtk_entry_new (); + + auto data = new FileEntryData {action, String (title)}; + auto destroy_cb = [] (void * data) { delete (FileEntryData *) data; }; + g_object_set_data_full ((GObject *) entry, "file-entry-data", data, destroy_cb); + + gtk_entry_set_icon_from_icon_name ((GtkEntry *) entry, + GTK_ENTRY_ICON_SECONDARY, "document-open"); + g_signal_connect (entry, "icon-press", (GCallback) entry_browse_cb, data); + + return entry; +} + +EXPORT String audgui_file_entry_get_uri (GtkWidget * entry) +{ + const char * text = gtk_entry_get_text ((GtkEntry *) entry); + + if (! text[0]) + return String (); + else if (strstr (text, "://")) + return String (text); + else + return String (filename_to_uri (filename_normalize (filename_expand (str_copy (text))))); +} + +EXPORT void audgui_file_entry_set_uri (GtkWidget * entry, const char * uri) +{ + if (! uri || ! uri[0]) + { + gtk_entry_set_text ((GtkEntry *) entry, ""); + return; + } + + StringBuf path = uri_to_filename (uri, false); + gtk_entry_set_text ((GtkEntry *) entry, path ? filename_contract (std::move (path)) : uri); + gtk_editable_set_position ((GtkEditable *) entry, -1); +} + EXPORT GtkWidget * audgui_dialog_new (GtkMessageType type, const char * title, const char * text, GtkWidget * button1, GtkWidget * button2) { |