summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gtk/src/audiohandler.c29
-rw-r--r--gtk/src/callbacks.c30
-rw-r--r--gtk/src/callbacks.h1
-rw-r--r--gtk/src/ghb.ui224
-rw-r--r--gtk/src/hb-backend.c104
-rw-r--r--gtk/src/hb-backend.h1
-rw-r--r--gtk/src/internal_defaults.xml2
-rw-r--r--gtk/src/makedeps.py2
-rw-r--r--gtk/src/queuehandler.c525
-rw-r--r--gtk/src/queuehandler.h1
10 files changed, 815 insertions, 104 deletions
diff --git a/gtk/src/audiohandler.c b/gtk/src/audiohandler.c
index d5ae66f3f..ec889a013 100644
--- a/gtk/src/audiohandler.c
+++ b/gtk/src/audiohandler.c
@@ -1596,7 +1596,8 @@ static void audio_def_update_widgets(GtkWidget *row, GValue *adict)
block_updates = FALSE;
}
-GtkListBoxRow * ghb_audio_settings_get_row(GtkWidget *widget)
+static GtkListBoxRow*
+audio_settings_get_row(GtkWidget *widget)
{
while (widget != NULL && G_OBJECT_TYPE(widget) != GTK_TYPE_LIST_BOX_ROW)
{
@@ -1959,7 +1960,7 @@ GtkWidget * ghb_create_audio_settings_row(signal_user_data_t *ud)
static void
audio_def_setting_update(signal_user_data_t *ud, GtkWidget *widget)
{
- GtkListBoxRow *row = ghb_audio_settings_get_row(widget);
+ GtkListBoxRow *row = audio_settings_get_row(widget);
gint index = gtk_list_box_row_get_index(row);
GValue *alist = ghb_settings_get_value(ud->settings, "AudioList");
@@ -2061,7 +2062,7 @@ static void audio_quality_update_limits(GtkWidget *widget, int encoder)
void audio_def_set_limits(signal_user_data_t *ud, GtkWidget *widget)
{
- GtkListBoxRow *row = ghb_audio_settings_get_row(widget);
+ GtkListBoxRow *row = audio_settings_get_row(widget);
gint index = gtk_list_box_row_get_index(row);
GValue *alist = ghb_settings_get_value(ud->settings, "AudioList");
@@ -2148,7 +2149,7 @@ audio_def_quality_enable_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
{
audio_def_setting_update(ud, widget);
- GtkListBoxRow *row = ghb_audio_settings_get_row(widget);
+ GtkListBoxRow *row = audio_settings_get_row(widget);
gint index = gtk_list_box_row_get_index(row);
GValue *alist = ghb_settings_get_value(ud->settings, "AudioList");
@@ -2164,7 +2165,7 @@ audio_def_quality_changed_cb(GtkWidget *widget, gdouble quality, signal_user_dat
{
audio_def_setting_update(ud, widget);
- GtkListBoxRow *row = ghb_audio_settings_get_row(widget);
+ GtkListBoxRow *row = audio_settings_get_row(widget);
GtkWidget *quality_label = find_widget(GTK_WIDGET(row),
"AudioTrackQualityValue");
gint index = gtk_list_box_row_get_index(row);
@@ -2192,7 +2193,7 @@ audio_def_gain_changed_cb(GtkWidget *widget, gdouble gain, signal_user_data_t *u
{
audio_def_setting_update(ud, widget);
- GtkListBoxRow *row = ghb_audio_settings_get_row(widget);
+ GtkListBoxRow *row = audio_settings_get_row(widget);
GtkWidget *gain_label = find_widget(GTK_WIDGET(row), "AudioTrackGainValue");
char *s_gain;
if ( gain >= 21.0 )
@@ -2209,7 +2210,7 @@ audio_def_drc_changed_cb(GtkWidget *widget, gdouble drc, signal_user_data_t *ud)
{
audio_def_setting_update(ud, widget);
- GtkListBoxRow *row = ghb_audio_settings_get_row(widget);
+ GtkListBoxRow *row = audio_settings_get_row(widget);
GtkWidget *drc_label = find_widget(GTK_WIDGET(row), "AudioTrackDRCValue");
char *s_drc;
@@ -2225,7 +2226,7 @@ audio_def_drc_changed_cb(GtkWidget *widget, gdouble drc, signal_user_data_t *ud)
G_MODULE_EXPORT void
audio_def_setting_add_cb(GtkWidget *widget, signal_user_data_t *ud)
{
- GtkListBoxRow *row = ghb_audio_settings_get_row(widget);
+ GtkListBoxRow *row = audio_settings_get_row(widget);
GValue *adict;
GValue *alist = ghb_settings_get_value(ud->settings, "AudioList");
@@ -2257,7 +2258,7 @@ audio_def_setting_add_cb(GtkWidget *widget, signal_user_data_t *ud)
G_MODULE_EXPORT void
audio_def_setting_remove_cb(GtkWidget *widget, signal_user_data_t *ud)
{
- GtkListBoxRow *row = ghb_audio_settings_get_row(widget);
+ GtkListBoxRow *row = audio_settings_get_row(widget);
gint index = gtk_list_box_row_get_index(row);
GValue *alist = ghb_settings_get_value(ud->settings, "AudioList");
@@ -2281,16 +2282,6 @@ audio_def_encode_setting_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
ghb_clear_presets_selection(ud);
}
-static void container_empty_cb(GtkWidget *widget, gpointer data)
-{
- gtk_widget_destroy(widget);
-}
-
-void ghb_container_empty(GtkContainer *c)
-{
- gtk_container_foreach(c, container_empty_cb, NULL);
-}
-
GtkListBoxRow* ghb_find_lang_row(GtkListBox *list_box, int lang_idx)
{
GList *list, *link;
diff --git a/gtk/src/callbacks.c b/gtk/src/callbacks.c
index d22254339..e288db2d8 100644
--- a/gtk/src/callbacks.c
+++ b/gtk/src/callbacks.c
@@ -1866,22 +1866,6 @@ load_all_titles(signal_user_data_t *ud, int titleindex)
ud->settings = ghb_array_get_nth(ud->settings_array, titleindex);
}
-void
-ghb_add_all_titles(signal_user_data_t *ud)
-{
- gint ii;
- gint count;
-
- count = ghb_array_len(ud->settings_array);
- for (ii = 0; ii < count; ii++)
- {
- GValue *settings;
-
- settings = ghb_value_dup(ghb_array_get_nth(ud->settings_array, ii));
- ghb_queue_add(ud, settings, ii);
- }
-}
-
static gboolean update_preview = FALSE;
G_MODULE_EXPORT void
@@ -2908,8 +2892,8 @@ ghb_backend_events(signal_user_data_t *ud)
GtkTreeView *treeview;
GtkTreeStore *store;
GtkTreeIter iter;
- static gint prev_scan_state = 0;
- static gint prev_queue_state = 0;
+ static gint prev_scan_state = -1;
+ static gint prev_queue_state = -1;
ghb_track_status();
ghb_get_status(&status);
@@ -5282,3 +5266,13 @@ window_configure_cb(
return FALSE;
}
+static void container_empty_cb(GtkWidget *widget, gpointer data)
+{
+ gtk_widget_destroy(widget);
+}
+
+void ghb_container_empty(GtkContainer *c)
+{
+ gtk_container_foreach(c, container_empty_cb, NULL);
+}
+
diff --git a/gtk/src/callbacks.h b/gtk/src/callbacks.h
index 9b794294c..25ba5a56b 100644
--- a/gtk/src/callbacks.h
+++ b/gtk/src/callbacks.h
@@ -81,6 +81,7 @@ void ghb_update_title_info(signal_user_data_t *ud);
void ghb_chapter_list_refresh_all(signal_user_data_t *ud);
void ghb_load_settings(signal_user_data_t * ud);
void ghb_set_current_title_settings(signal_user_data_t *ud);
+void ghb_container_empty(GtkContainer *c);
#endif // _CALLBACKS_H_
diff --git a/gtk/src/ghb.ui b/gtk/src/ghb.ui
index cb938aa8f..dc4cdc66c 100644
--- a/gtk/src/ghb.ui
+++ b/gtk/src/ghb.ui
@@ -681,7 +681,7 @@ libx264 authors:
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="queue_add_menu">
- <property name="label" translatable="yes">_Add Queue</property>
+ <property name="label" translatable="yes">_Add</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
@@ -689,17 +689,17 @@ libx264 authors:
</object>
</child>
<child>
- <object class="GtkMenuItem" id="queue_add_all_menu">
- <property name="label" translatable="yes">Add A_ll Queue</property>
+ <object class="GtkMenuItem" id="queue_add_multiple_menu">
+ <property name="label" translatable="yes">Add _Multiple</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="queue_add_all_clicked_cb" swapped="no"/>
+ <signal name="activate" handler="queue_add_multiple_clicked_cb" swapped="no"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="queue_start_menu">
- <property name="label" translatable="yes">_Start Queue</property>
+ <property name="label" translatable="yes">_Start</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
@@ -708,7 +708,7 @@ libx264 authors:
</child>
<child>
<object class="GtkMenuItem" id="queue_pause_menu">
- <property name="label" translatable="yes">_Pause Queue</property>
+ <property name="label" translatable="yes">_Pause</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
@@ -3270,6 +3270,8 @@ All other secondary audio output tracks will be encoded with first encoder only.
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="vexpand">True</property>
+ <property name="selection_mode">none</property>
+ <property name="activate_on_single_click">False</property>
</object>
</child>
</object>
@@ -5577,6 +5579,204 @@ You can edit these and add additional options.</property>
<property name="step_increment">5</property>
<property name="page_increment">10</property>
</object>
+ <object class="GtkDialog" id="titla_add_multiple_dialog">
+ <property name="can_focus">False</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog_title_add_multiple_vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog_title_add_multiple_action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="title_add_multiple_cancel">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="title_add_multiple_ok">
+ <property name="label">gtk-ok</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="yalign">0.55000001192092896</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="title_add_multiple_grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">12</property>
+ <property name="margin_right">12</property>
+ <property name="margin_top">12</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="title_add_multiple_scrolledwindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="min_content_height">400</property>
+ <child>
+ <object class="GtkListBox" id="title_add_multiple_list">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="hexpand">True</property>
+ <property name="selection_mode">none</property>
+ <property name="activate_on_single_click">False</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">3</property>
+ <property name="height">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="title_add_multiple_hbox1">
+ <property name="orientation">horizontal</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="title_add_multiple_select_all">
+ <property name="label" translatable="yes">Select All</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Mark all titles for adding to the queue</property>
+ <property name="halign">start</property>
+ <property name="vexpand">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="title_add_multiple_select_all_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="title_add_multiple_clear_all">
+ <property name="label" translatable="yes">Clear All</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Unmark all titles</property>
+ <property name="halign">start</property>
+ <property name="vexpand">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="title_add_multiple_clear_all_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkInfoBar" id="title_add_multiple_infobar">
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
+ <property name="message_type">info</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="title_add_multiple_infobar-action_area1">
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <property name="layout_style">end</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="content_area">
+ <object class="GtkBox" id="title_add_multiple_infobar_content_area">
+ <property name="can_focus">False</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkLabel" id="title_add_multiple_label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Destination files OK. No duplicates detected.</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">3</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">title_add_multiple_cancel</action-widget>
+ <action-widget response="-5">title_add_multiple_ok</action-widget>
+ </action-widgets>
+ </object>
<object class="GtkDialog" id="prefs_dialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
@@ -9098,10 +9298,11 @@ YadifMode:YadifParity:McdintMode:McdeintQp</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="subtitle_cancel">
- <property name="label" translatable="yes">Cancel</property>
+ <property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
@@ -9111,10 +9312,11 @@ YadifMode:YadifParity:McdintMode:McdeintQp</property>
</child>
<child>
<object class="GtkButton" id="subtitle_ok">
- <property name="label" translatable="yes">Ok</property>
+ <property name="label">gtk-ok</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
@@ -9483,10 +9685,11 @@ in your output.</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="audio_cancel">
- <property name="label" translatable="yes">Cancel</property>
+ <property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
@@ -9496,10 +9699,11 @@ in your output.</property>
</child>
<child>
<object class="GtkButton" id="audio_ok">
- <property name="label" translatable="yes">Ok</property>
+ <property name="label">gtk-ok</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c
index ae09f6dc4..0a4a3266c 100644
--- a/gtk/src/hb-backend.c
+++ b/gtk/src/hb-backend.c
@@ -2058,6 +2058,61 @@ language_opts_set(GtkBuilder *builder, const gchar *name)
static gchar **titles = NULL;
+gchar*
+ghb_create_title_label(hb_title_t *title)
+{
+ gchar *label;
+
+ if (title->type == HB_STREAM_TYPE || title->type == HB_FF_STREAM_TYPE)
+ {
+ if (title->duration != 0)
+ {
+ char *tmp;
+ tmp = g_strdup_printf ("%d - %02dh%02dm%02ds - %s",
+ title->index, title->hours, title->minutes, title->seconds,
+ title->name);
+ label = g_markup_escape_text(tmp, -1);
+ g_free(tmp);
+ }
+ else
+ {
+ char *tmp;
+ tmp = g_strdup_printf ("%d - %s",
+ title->index, title->name);
+ label = g_markup_escape_text(tmp, -1);
+ g_free(tmp);
+ }
+ }
+ else if (title->type == HB_BD_TYPE)
+ {
+ if (title->duration != 0)
+ {
+ label = g_strdup_printf("%d (%05d.MPLS) - %02dh%02dm%02ds",
+ title->index, title->playlist, title->hours,
+ title->minutes, title->seconds);
+ }
+ else
+ {
+ label = g_strdup_printf("%d (%05d.MPLS) - Unknown Length",
+ title->index, title->playlist);
+ }
+ }
+ else
+ {
+ if (title->duration != 0)
+ {
+ label = g_strdup_printf("%d - %02dh%02dm%02ds",
+ title->index, title->hours, title->minutes, title->seconds);
+ }
+ else
+ {
+ label = g_strdup_printf("%d - Unknown Length",
+ title->index);
+ }
+ }
+ return label;
+}
+
void
title_opts_set(GtkBuilder *builder, const gchar *name)
{
@@ -2111,53 +2166,8 @@ title_opts_set(GtkBuilder *builder, const gchar *name)
for (ii = 0; ii < count; ii++)
{
title = (hb_title_t*)hb_list_item(list, ii);
- if (title->type == HB_STREAM_TYPE || title->type == HB_FF_STREAM_TYPE)
- {
- if (title->duration != 0)
- {
- char *tmp;
- tmp = g_strdup_printf ("%d - %02dh%02dm%02ds - %s",
- title->index, title->hours, title->minutes, title->seconds,
- title->name);
- titles[ii] = g_markup_escape_text(tmp, -1);
- g_free(tmp);
- }
- else
- {
- char *tmp;
- tmp = g_strdup_printf ("%d - %s",
- title->index, title->name);
- titles[ii] = g_markup_escape_text(tmp, -1);
- g_free(tmp);
- }
- }
- else if (title->type == HB_BD_TYPE)
- {
- if (title->duration != 0)
- {
- titles[ii] = g_strdup_printf("%d (%05d.MPLS) - %02dh%02dm%02ds",
- title->index, title->playlist, title->hours,
- title->minutes, title->seconds);
- }
- else
- {
- titles[ii] = g_strdup_printf("%d (%05d.MPLS) - Unknown Length",
- title->index, title->playlist);
- }
- }
- else
- {
- if (title->duration != 0)
- {
- titles[ii] = g_strdup_printf("%d - %02dh%02dm%02ds",
- title->index, title->hours, title->minutes, title->seconds);
- }
- else
- {
- titles[ii] = g_strdup_printf("%d - Unknown Length",
- title->index);
- }
- }
+ titles[ii] = ghb_create_title_label(title);
+
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
0, titles[ii],
diff --git a/gtk/src/hb-backend.h b/gtk/src/hb-backend.h
index 8311de9a2..0f15d4070 100644
--- a/gtk/src/hb-backend.h
+++ b/gtk/src/hb-backend.h
@@ -171,5 +171,6 @@ void ghb_audio_samplerate_opts_set(GtkComboBox *combo);
int ghb_lookup_audio_lang(const GValue *glang);
const iso639_lang_t* ghb_iso639_lookup_by_int(int idx);
void ghb_update_display_aspect_label(signal_user_data_t *ud);
+gchar* ghb_create_title_label(hb_title_t *title);
#endif // _HBBACKEND_H_
diff --git a/gtk/src/internal_defaults.xml b/gtk/src/internal_defaults.xml
index e1c2eaef4..2959e4945 100644
--- a/gtk/src/internal_defaults.xml
+++ b/gtk/src/internal_defaults.xml
@@ -77,6 +77,8 @@
<integer>0</integer>
<key>title</key>
<string>none</string>
+ <key>title_selected</key>
+ <false />
<key>volume_label</key>
<string>New Video</string>
<key>audio_list</key>
diff --git a/gtk/src/makedeps.py b/gtk/src/makedeps.py
index 7be7a71b5..aa2111cea 100644
--- a/gtk/src/makedeps.py
+++ b/gtk/src/makedeps.py
@@ -8,7 +8,7 @@ DepEntry = collections.namedtuple('DepEntry', 'widget dep enable die hide')
dep_map = (
DepEntry("title", "queue_add", "none", True, False),
DepEntry("title", "queue_add_menu", "none", True, False),
- DepEntry("title", "queue_add_all_menu", "none", True, False),
+ DepEntry("title", "queue_add_multiple_menu", "none", True, False),
DepEntry("title", "preview_frame", "none", True, False),
DepEntry("title", "picture_summary", "none", True, False),
DepEntry("title", "picture_summary2", "none", True, False),
diff --git a/gtk/src/queuehandler.c b/gtk/src/queuehandler.c
index 507b3cc08..847eacd6d 100644
--- a/gtk/src/queuehandler.c
+++ b/gtk/src/queuehandler.c
@@ -680,8 +680,8 @@ validate_settings(signal_user_data_t *ud, GValue *settings, gint batch)
return TRUE;
}
-gboolean
-ghb_queue_add(signal_user_data_t *ud, GValue *settings, gint batch)
+static gboolean
+queue_add(signal_user_data_t *ud, GValue *settings, gint batch)
{
// Add settings to the queue
gint titleindex;
@@ -720,17 +720,526 @@ queue_add_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
{
g_debug("queue_add_clicked_cb ()");
GValue *settings = ghb_value_dup(ud->settings);
- if (!ghb_queue_add(ud, settings, 0))
+ if (!queue_add(ud, settings, 0))
ghb_value_free(settings);
// Validation of settings may have changed audio list
ghb_audio_list_refresh_all(ud);
}
+static gboolean
+title_multiple_can_select(GValue *settings_array, int index)
+{
+ gint count, ii;
+ GValue *settings, *gdest;
+ const char *dest;
+
+ settings = ghb_array_get_nth(settings_array, index);
+ gdest = ghb_settings_get_value(settings, "destination");
+ dest = g_value_get_string(gdest);
+ if (dest == NULL)
+ return FALSE;
+
+ count = ghb_array_len(settings_array);
+ count = count < index ? count : index;
+ for (ii = 0; ii < count; ii++)
+ {
+ const char *tmp;
+
+ settings = ghb_array_get_nth(settings_array, ii);
+ gdest = ghb_settings_get_value(settings, "destination");
+ tmp = g_value_get_string(gdest);
+ if (tmp != NULL && !strncmp(dest, tmp, PATH_MAX))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static GtkWidget *find_widget(GtkWidget *widget, gchar *name)
+{
+ const char *wname;
+ GtkWidget *result = NULL;
+
+ if (widget == NULL || name == NULL)
+ return NULL;
+
+ wname = gtk_widget_get_name(widget);
+ if (wname != NULL && !strncmp(wname, name, 80))
+ {
+ return widget;
+ }
+ if (GTK_IS_CONTAINER(widget))
+ {
+ GList *list, *link;
+ link = list = gtk_container_get_children(GTK_CONTAINER(widget));
+ while (link)
+ {
+ result = find_widget(GTK_WIDGET(link->data), name);
+ if (result != NULL)
+ break;
+ link = link->next;
+ }
+ g_list_free(list);
+ }
+ return result;
+}
+
+static void
+title_add_multiple_set_sensitive(GtkWidget *row, gboolean sensitive)
+{
+ GtkWidget *widget;
+ widget = find_widget(row, "title_selected");
+ gtk_widget_set_sensitive(widget, sensitive);
+ widget = find_widget(row, "title_label");
+ gtk_widget_set_sensitive(widget, sensitive);
+}
+
+static gboolean
+title_add_multiple_are_conflicts(signal_user_data_t *ud)
+{
+ gint count, ii;
+
+ count = ghb_array_len(ud->settings_array);
+ for (ii = 0; ii < count; ii++)
+ {
+ if (!title_multiple_can_select(ud->settings_array, ii))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+title_add_multiple_set_conflict_label(
+ signal_user_data_t *ud,
+ gboolean are_conflicts)
+{
+ const gchar *msg;
+ static gboolean conflict_showing = FALSE;
+ GtkMessageType msg_type;
+
+ if (are_conflicts)
+ {
+ msg =
+ "<span foreground='red' weight='bold'>"
+ "Duplicate destination files detected.\n"
+ "Duplicates will not be added to the queue."
+ "</span>";
+ msg_type = GTK_MESSAGE_WARNING;
+ }
+ else
+ {
+ msg =
+ "Destination files OK. No duplicates detected.";
+ msg_type = GTK_MESSAGE_INFO;
+ }
+ if (are_conflicts ^ conflict_showing)
+ {
+ GtkInfoBar *info;
+ GtkContainer *content_area;
+ GList *list;
+ GtkLabel *label;
+
+ info = GTK_INFO_BAR(GHB_WIDGET(ud->builder,
+ "title_add_multiple_infobar"));
+ content_area = GTK_CONTAINER(gtk_info_bar_get_content_area(info));
+ list = gtk_container_get_children(content_area);
+ // Label is first in list
+ label = GTK_LABEL(list->data);
+ gtk_label_set_markup(label, msg);
+ gtk_info_bar_set_message_type(info, msg_type);
+ conflict_showing = are_conflicts;
+ }
+}
+
+static void
+title_add_multiple_check_conflicts(signal_user_data_t *ud)
+{
+ gint count, ii;
+ GValue *settings;
+ GtkWidget *row;
+ GtkListBox *list;
+ GtkToggleButton *selected;
+ gboolean can_select;
+ gboolean are_conflicts = FALSE;
+
+ list = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "title_add_multiple_list"));
+ count = ghb_array_len(ud->settings_array);
+ for (ii = 0; ii < count; ii++)
+ {
+ row = GTK_WIDGET(gtk_list_box_get_row_at_index(list, ii));
+ selected = GTK_TOGGLE_BUTTON(find_widget(row, "title_selected"));
+
+ settings = ghb_array_get_nth(ud->settings_array, ii);
+ can_select = title_multiple_can_select(ud->settings_array, ii);
+ ghb_settings_set_boolean(settings, "title_selected", FALSE);
+ gtk_toggle_button_set_active(selected, FALSE);
+ title_add_multiple_set_sensitive(GTK_WIDGET(row), can_select);
+ are_conflicts |= !can_select;
+ }
+ title_add_multiple_set_conflict_label(ud, are_conflicts);
+}
+
+static gboolean clear_select_all_busy = FALSE;
+
+G_MODULE_EXPORT void
+title_add_multiple_select_all_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ gint count, ii;
+ GValue *settings;
+ GtkWidget *row;
+ GtkListBox *list;
+ GtkToggleButton *selected;
+ gboolean can_select;
+ GtkToggleButton *clear_all;
+ GtkToggleButton *select_all;
+
+ if (!ghb_widget_boolean(widget))
+ return;
+
+ clear_select_all_busy = TRUE;
+
+ clear_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_clear_all"));
+ select_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_select_all"));
+ gtk_toggle_button_set_active(clear_all, FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(select_all), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(clear_all), TRUE);
+
+ list = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "title_add_multiple_list"));
+ count = ghb_array_len(ud->settings_array);
+ for (ii = 0; ii < count; ii++)
+ {
+ row = GTK_WIDGET(gtk_list_box_get_row_at_index(list, ii));
+ selected = GTK_TOGGLE_BUTTON(find_widget(row, "title_selected"));
+ settings = ghb_array_get_nth(ud->settings_array, ii);
+ can_select = title_multiple_can_select(ud->settings_array, ii);
+ ghb_settings_set_boolean(settings, "title_selected", can_select);
+ gtk_toggle_button_set_active(selected, TRUE);
+ title_add_multiple_set_sensitive(GTK_WIDGET(row), can_select);
+ }
+ clear_select_all_busy = FALSE;
+}
+
+G_MODULE_EXPORT void
+title_add_multiple_clear_all_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ gint count, ii;
+ GValue *settings;
+ GtkWidget *row;
+ GtkListBox *list;
+ GtkToggleButton *selected;
+ GtkToggleButton *clear_all;
+ GtkToggleButton *select_all;
+
+ if (!ghb_widget_boolean(widget))
+ return;
+
+ clear_select_all_busy = TRUE;
+
+ clear_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_clear_all"));
+ select_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_select_all"));
+ gtk_toggle_button_set_active(select_all, FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(select_all), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(clear_all), FALSE);
+
+ list = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "title_add_multiple_list"));
+ count = ghb_array_len(ud->settings_array);
+ for (ii = 0; ii < count; ii++)
+ {
+ row = GTK_WIDGET(gtk_list_box_get_row_at_index(list, ii));
+ selected = GTK_TOGGLE_BUTTON(find_widget(row, "title_selected"));
+ settings = ghb_array_get_nth(ud->settings_array, ii);
+ ghb_settings_set_boolean(settings, "title_selected", FALSE);
+ gtk_toggle_button_set_active(selected, FALSE);
+ }
+ clear_select_all_busy = FALSE;
+}
+
+static void
+add_multiple_titles(signal_user_data_t *ud)
+{
+ gint count, ii;
+
+ count = ghb_array_len(ud->settings_array);
+ for (ii = 0; ii < count; ii++)
+ {
+ GValue *settings;
+
+ settings = ghb_value_dup(ghb_array_get_nth(ud->settings_array, ii));
+ if (ghb_settings_get_boolean(settings, "title_selected"))
+ {
+ queue_add(ud, settings, ii);
+ }
+ }
+}
+
+static GtkListBoxRow*
+title_get_row(GtkWidget *widget)
+{
+ while (widget != NULL && G_OBJECT_TYPE(widget) != GTK_TYPE_LIST_BOX_ROW)
+ {
+ widget = gtk_widget_get_parent(widget);
+ }
+ return GTK_LIST_BOX_ROW(widget);
+}
+
+G_MODULE_EXPORT void
+title_selected_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ GValue *settings;
+ gboolean selected;
+ GtkToggleButton *select_all;
+ GtkToggleButton *clear_all;
+ gboolean can_select;
+
+ if (clear_select_all_busy)
+ return;
+
+ GtkListBoxRow * row = title_get_row(widget);
+ if (row == NULL)
+ return;
+
+ clear_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_clear_all"));
+ select_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_select_all"));
+ gtk_toggle_button_set_active(select_all, FALSE);
+ gtk_toggle_button_set_active(clear_all, FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(clear_all), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(select_all), TRUE);
+
+ gint index = gtk_list_box_row_get_index(row);
+ selected = ghb_widget_boolean(widget);
+ settings = ghb_array_get_nth(ud->settings_array, index);
+ can_select = title_multiple_can_select(ud->settings_array, index);
+ ghb_settings_set_boolean(settings, "title_selected",
+ selected && can_select);
+}
+
G_MODULE_EXPORT void
-queue_add_all_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
+title_dest_file_cb(GtkWidget *widget, signal_user_data_t *ud)
{
- g_debug("queue_add_all_clicked_cb ()");
- ghb_add_all_titles(ud);
+ GValue *settings;
+ gchar *dest_file, *dest_dir, *dest;
+ GtkListBoxRow * row = title_get_row(widget);
+ if (row == NULL)
+ return;
+ gint index = gtk_list_box_row_get_index(row);
+
+ dest_file = ghb_widget_string(widget);
+ settings = ghb_array_get_nth(ud->settings_array, index);
+
+ ghb_settings_set_string(settings, "dest_file", dest_file);
+ dest_dir = ghb_settings_get_string(settings, "dest_dir");
+ dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file);
+ ghb_settings_set_string(settings, "destination", dest);
+
+ // Check if changing the destination file name resolves
+ // a file name conflict. Enable selection if so.
+ // Disable selection if it creates a confict!!!
+ gboolean can_select;
+ can_select = title_multiple_can_select(ud->settings_array, index);
+ ghb_settings_set_boolean(settings, "title_selected", can_select);
+ title_add_multiple_set_sensitive(GTK_WIDGET(row), can_select);
+
+ g_free(dest_file);
+ g_free(dest_dir);
+ g_free(dest);
+
+ title_add_multiple_set_conflict_label(ud,
+ title_add_multiple_are_conflicts(ud));
+}
+
+G_MODULE_EXPORT void
+title_dest_dir_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ GValue *settings;
+ gchar *dest_file, *dest_dir, *dest;
+ GtkListBoxRow * row = title_get_row(widget);
+ if (row == NULL)
+ return;
+ gint index = gtk_list_box_row_get_index(row);
+
+ dest_dir = ghb_widget_string(widget);
+ settings = ghb_array_get_nth(ud->settings_array, index);
+
+ ghb_settings_set_string(settings, "dest_dir", dest_dir);
+ dest_file = ghb_settings_get_string(settings, "dest_file");
+ dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file);
+ ghb_settings_set_string(settings, "destination", dest);
+
+ // Check if changing the destination file name resolves
+ // a file name conflict. Enable selection if so.
+ // Disable selection if it creates a confict!!!
+ gboolean can_select;
+ can_select = title_multiple_can_select(ud->settings_array, index);
+ ghb_settings_set_boolean(settings, "title_selected", can_select);
+ title_add_multiple_set_sensitive(GTK_WIDGET(row), can_select);
+
+ g_free(dest_file);
+ g_free(dest_dir);
+ g_free(dest);
+
+ title_add_multiple_set_conflict_label(ud,
+ title_add_multiple_are_conflicts(ud));
+}
+
+GtkWidget * title_create_row(signal_user_data_t *ud)
+{
+ GtkBox *hbox, *vbox_dest;
+ GtkCheckButton *selected;
+ GtkLabel *title;
+ GtkEntry *dest_file;
+ GtkFileChooserButton *dest_dir;
+
+ hbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0));
+ gtk_box_set_spacing(hbox, 6);
+ gtk_widget_show(GTK_WIDGET(hbox));
+
+ // Select checkbox
+ selected = GTK_CHECK_BUTTON(gtk_check_button_new());
+ gtk_widget_set_tooltip_markup(GTK_WIDGET(selected),
+ "Select this title for adding to the queue.\n");
+ gtk_widget_set_valign(GTK_WIDGET(selected), GTK_ALIGN_CENTER);
+ gtk_widget_set_name(GTK_WIDGET(selected), "title_selected");
+ gtk_widget_show(GTK_WIDGET(selected));
+ g_signal_connect(selected, "toggled", (GCallback)title_selected_cb, ud);
+ gtk_box_pack_start(hbox, GTK_WIDGET(selected), FALSE, FALSE, 0);
+
+ // Title label
+ title = GTK_LABEL(gtk_label_new("No Title"));
+ gtk_label_set_width_chars(title, 12);
+ gtk_misc_set_alignment(GTK_MISC(title), 0, 0.5);
+ gtk_widget_set_name(GTK_WIDGET(title), "title_label");
+ gtk_widget_show(GTK_WIDGET(title));
+ gtk_box_pack_start(hbox, GTK_WIDGET(title), FALSE, FALSE, 0);
+
+ // Destination entry and file chooser
+ vbox_dest = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 0));
+ //gtk_widget_set_hexpand(GTK_WIDGET(vbox_dest), TRUE);
+ dest_file = GTK_ENTRY(gtk_entry_new());
+ gtk_entry_set_width_chars(dest_file, 40);
+ gtk_widget_set_name(GTK_WIDGET(dest_file), "title_file");
+ //gtk_widget_set_hexpand(GTK_WIDGET(dest_file), TRUE);
+ gtk_widget_show(GTK_WIDGET(dest_file));
+ g_signal_connect(dest_file, "changed", (GCallback)title_dest_file_cb, ud);
+ gtk_box_pack_start(vbox_dest, GTK_WIDGET(dest_file), FALSE, FALSE, 0);
+ dest_dir = GTK_FILE_CHOOSER_BUTTON(
+ gtk_file_chooser_button_new("Destination Directory",
+ GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER));
+ g_signal_connect(dest_dir, "selection-changed",
+ (GCallback)title_dest_dir_cb, ud);
+ gtk_widget_set_name(GTK_WIDGET(dest_dir), "title_dir");
+ gtk_widget_set_hexpand(GTK_WIDGET(dest_dir), TRUE);
+ gtk_widget_show(GTK_WIDGET(dest_dir));
+ gtk_box_pack_start(vbox_dest, GTK_WIDGET(dest_dir), FALSE, FALSE, 0);
+ gtk_widget_show(GTK_WIDGET(vbox_dest));
+ gtk_box_pack_start(hbox, GTK_WIDGET(vbox_dest), TRUE, TRUE, 0);
+
+ return GTK_WIDGET(hbox);
+}
+
+G_MODULE_EXPORT void
+queue_add_multiple_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ g_debug("queue_add_multiple_clicked_cb ()");
+
+ GtkListBox *list;
+ GtkWidget *row;
+ gint count, ii;
+ int max_title_len = 0;
+
+ list = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "title_add_multiple_list"));
+
+ // Set up the list of titles
+ count = ghb_array_len(ud->settings_array);
+ for (ii = 0; ii < count; ii++)
+ {
+ GValue *settings;
+ GtkLabel *label;
+ GtkEntry *entry;
+ GtkFileChooser *chooser;
+ gchar *title_label, *dest_dir, *dest_file;
+ int titleindex;
+ hb_title_t *title;
+
+ row = title_create_row(ud);
+ label = GTK_LABEL(find_widget(row, "title_label"));
+ entry = GTK_ENTRY(find_widget(row, "title_file"));
+ chooser = GTK_FILE_CHOOSER(find_widget(row, "title_dir"));
+
+ settings = ghb_array_get_nth(ud->settings_array, ii);
+ titleindex = ghb_settings_get_int(settings, "title_no");
+ title = ghb_get_title_info(titleindex);
+ if (title != NULL)
+ {
+ int len;
+
+ title_label = ghb_create_title_label(title);
+ len = strnlen(title_label, PATH_MAX);
+ if (len > max_title_len)
+ max_title_len = len;
+
+ dest_file = ghb_settings_get_string(settings, "dest_file");
+ dest_dir = ghb_settings_get_string(settings, "dest_dir");
+
+ gtk_label_set_markup(label, title_label);
+ gtk_entry_set_text(entry, dest_file);
+ gtk_file_chooser_set_filename(chooser, dest_dir);
+
+ g_free(title_label);
+ g_free(dest_file);
+ g_free(dest_dir);
+ }
+
+ gtk_list_box_insert(list, row, -1);
+ }
+ // Now we need to set the width of the title label since it
+ // can vary on each row
+ if (max_title_len > 60)
+ max_title_len = 60;
+ for (ii = 0; ii < count; ii++)
+ {
+ GtkWidget *row;
+ GtkLabel *label;
+
+ row = GTK_WIDGET(gtk_list_box_get_row_at_index(list, ii));
+ label = GTK_LABEL(find_widget(row, "title_label"));
+ gtk_label_set_max_width_chars(label, max_title_len);
+ gtk_label_set_width_chars(label, max_title_len);
+ gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_END);
+ }
+
+ // Clear "select all" and "clear all" options
+ GtkToggleButton *select_all;
+ GtkToggleButton *clear_all;
+
+ clear_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_clear_all"));
+ select_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_select_all"));
+ gtk_toggle_button_set_active(clear_all, FALSE);
+ gtk_toggle_button_set_active(select_all, FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(select_all), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(clear_all), TRUE);
+
+ // Disable selection of files with duplicate file names.
+ title_add_multiple_check_conflicts(ud);
+
+ // Pop up the title multiple selections dialog
+ GtkResponseType response;
+ GtkWidget *dialog = GHB_WIDGET(ud->builder, "titla_add_multiple_dialog");
+ response = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_hide(dialog);
+ if (response == GTK_RESPONSE_OK)
+ {
+ add_multiple_titles(ud);
+ }
+
+ // Clear title list
+ ghb_container_empty(GTK_CONTAINER(list));
}
G_MODULE_EXPORT void
@@ -1028,7 +1537,7 @@ ghb_queue_buttons_grey(signal_user_data_t *ud)
gtk_widget_set_sensitive(widget, show_start);
widget = GHB_WIDGET(ud->builder, "queue_add_menu");
gtk_widget_set_sensitive(widget, show_start);
- widget = GHB_WIDGET(ud->builder, "queue_add_all_menu");
+ widget = GHB_WIDGET(ud->builder, "queue_add_multiple_menu");
gtk_widget_set_sensitive(widget, show_start);
widget = GHB_WIDGET (ud->builder, "queue_start1");
@@ -1198,7 +1707,7 @@ queue_start_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
// The queue has no running or pending jobs.
// Add current settings to the queue, then run.
GValue *settings = ghb_value_dup(ud->settings);
- if (!ghb_queue_add(ud, settings, 0))
+ if (!queue_add(ud, settings, 0))
{
ghb_value_free(settings);
return;
diff --git a/gtk/src/queuehandler.h b/gtk/src/queuehandler.h
index abf33757a..e91a2f241 100644
--- a/gtk/src/queuehandler.h
+++ b/gtk/src/queuehandler.h
@@ -30,6 +30,5 @@
void ghb_queue_buttons_grey(signal_user_data_t *ud);
gboolean ghb_reload_queue(signal_user_data_t *ud);
-gboolean ghb_queue_add(signal_user_data_t *ud, GValue *settings, gint batch);
#endif // _QUEUEHANDLER_H_