1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) John Stebbins 2008 <stebbins@stebbins>
6 * callbacks.c is free software.
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
22 #include <libhal-storage.h>
24 #include <glib/gstdio.h>
27 #include "callbacks.h"
29 #include "hb-backend.h"
32 extern gboolean ghb_autostart;
33 static void update_chapter_list(signal_user_data_t *ud);
34 static void clear_audio_list(signal_user_data_t *ud);
35 static GList* dvd_device_list();
36 static gboolean cancel_encode();
37 static void audio_list_refresh_selected(signal_user_data_t *ud);
38 static GHashTable* get_selected_asettings(signal_user_data_t *ud);
40 // This is a dependency map used for greying widgets
41 // that are dependent on the state of another widget.
42 // The enable_value comes from the values that are
43 // obtained from ghb_widget_value(). For combo boxes
44 // you will have to look further to combo box options
45 // maps in hb-backend.c
48 const gchar *widget_name;
49 const gchar *dep_name;
50 const gchar *enable_value;
51 const gboolean disable_if_equal;
54 static dependency_t dep_map[] =
56 {"title", "queue_add", "none", TRUE},
57 {"title", "queue_add_menu", "none", TRUE},
58 {"title", "preview_button", "none", TRUE},
59 {"title", "show_preview_menu", "none", TRUE},
60 {"title", "preview_frame", "none", TRUE},
61 {"title", "picture_label", "none", TRUE},
62 {"title", "picture_tab", "none", TRUE},
63 {"title", "audio_label", "none", TRUE},
64 {"title", "audio_tab", "none", TRUE},
65 {"title", "chapters_label", "none", TRUE},
66 {"title", "chapters_tab", "none", TRUE},
67 {"title", "title", "none", TRUE},
68 {"title", "start_chapter", "none", TRUE},
69 {"title", "end_chapter", "none", TRUE},
70 {"vquality_type_bitrate", "video_bitrate", "enable", FALSE},
71 {"vquality_type_target", "video_target_size", "enable", FALSE},
72 {"vquality_type_constant", "video_quality", "enable", FALSE},
73 {"vquality_type_constant", "constant_rate_factor", "enable", FALSE},
74 {"vquality_type_constant", "x264_trellis", "enable", TRUE},
75 {"vquality_type_constant", "two_pass", "enable", TRUE},
76 {"vquality_type_constant", "turbo", "enable", TRUE},
77 {"two_pass", "turbo", "enable", FALSE},
78 {"container", "large_mp4", "mp4|m4v", FALSE},
79 {"container", "http_optimize_mp4", "mp4|m4v", FALSE},
80 {"container", "ipod_file", "mp4|m4v", FALSE},
81 {"container", "variable_frame_rate", "avi", TRUE},
82 {"variable_frame_rate", "framerate", "enable", TRUE},
83 {"variable_frame_rate", "detelecine", "enable", TRUE},
84 {"decomb", "deinterlace", "enable", TRUE},
85 {"autocrop", "crop_top", "disable", FALSE},
86 {"autocrop", "crop_bottom", "disable", FALSE},
87 {"autocrop", "crop_left", "disable", FALSE},
88 {"autocrop", "crop_right", "disable", FALSE},
89 {"autoscale", "scale_width", "disable", FALSE},
90 {"autoscale", "scale_height", "disable", FALSE},
91 {"anamorphic", "keep_aspect", "disable", FALSE},
92 {"anamorphic", "scale_height", "disable", FALSE},
93 {"keep_aspect", "scale_height", "disable", FALSE},
94 {"video_codec", "x264_tab", "x264", FALSE},
95 {"video_codec", "x264_tab_label", "x264", FALSE},
96 {"video_codec", "ipod_file", "x264", FALSE},
97 {"audio_track", "audio_add", "none", TRUE},
98 {"audio_track", "audio_codec", "none", TRUE},
99 {"audio_track", "audio_bitrate", "none", TRUE},
100 {"audio_track", "audio_sample_rate", "none", TRUE},
101 {"audio_track", "audio_mix", "none", TRUE},
102 {"audio_track", "audio_drc", "none", TRUE},
103 {"audio_codec", "audio_bitrate", "ac3", TRUE},
104 {"audio_codec", "audio_sample_rate", "ac3", TRUE},
105 {"audio_codec", "audio_mix", "ac3", TRUE},
106 {"audio_codec", "audio_drc", "ac3", TRUE},
107 {"x264_bframes", "x264_weighted_bframes", "0", TRUE},
108 {"x264_bframes", "x264_brdo", "0", TRUE},
109 {"x264_bframes", "x264_bime", "0", TRUE},
110 {"x264_bframes", "x264_bpyramid", "<2", TRUE},
111 {"x264_bframes", "x264_direct", "0", TRUE},
112 {"x264_refs", "x264_mixed_refs", "<2", TRUE},
113 {"x264_cabac", "x264_trellis", "enable", FALSE},
114 {"x264_subme", "x264_brdo", "<6", TRUE},
115 {"x264_analyse", "x264_direct", "none", TRUE},
116 {"x264_me", "x264_merange", "umh|esa", FALSE},
117 {"pref_audio_codec1", "pref_audio_bitrate1", "none", TRUE},
118 {"pref_audio_codec1", "pref_audio_rate1", "none", TRUE},
119 {"pref_audio_codec1", "pref_audio_mix1", "none", TRUE},
120 {"pref_audio_codec1", "pref_audio_codec2", "none", TRUE},
121 {"pref_audio_codec1", "pref_audio_bitrate2", "none", TRUE},
122 {"pref_audio_codec1", "pref_audio_rate2", "none", TRUE},
123 {"pref_audio_codec1", "pref_audio_mix2", "none", TRUE},
124 {"pref_audio_codec2", "pref_audio_bitrate2", "none", TRUE},
125 {"pref_audio_codec2", "pref_audio_rate2", "none", TRUE},
126 {"pref_audio_codec2", "pref_audio_mix2", "none", TRUE},
127 {"chapter_markers", "chapters_list", "enable", FALSE},
131 dep_check(signal_user_data_t *ud, const gchar *name)
137 int count = sizeof(dep_map) / sizeof(dependency_t);
138 gboolean result = TRUE;
140 g_debug("dep_check () %s\n", name);
141 for (ii = 0; ii < count; ii++)
143 if (strcmp(dep_map[ii].dep_name, name) == 0)
145 widget = GHB_WIDGET(ud->builder, dep_map[ii].widget_name);
146 dep_object = gtk_builder_get_object(ud->builder, dep_map[ii].dep_name);
147 value = ghb_widget_short_opt(widget);
148 if (dep_object == NULL || widget == NULL)
150 g_message("Failed to find widget\n");
155 gchar **values = g_strsplit(dep_map[ii].enable_value, "|", 10);
156 gboolean sensitive = FALSE;
158 while (values && values[jj])
160 if (values[jj][0] == '>')
162 gdouble dbl = g_strtod (&values[jj][1], NULL);
163 gdouble dvalue = ghb_widget_dbl (widget);
170 else if (values[jj][0] == '<')
172 gdouble dbl = g_strtod (&values[jj][1], NULL);
173 gdouble dvalue = ghb_widget_dbl (widget);
180 if (strcmp(values[jj], value) == 0)
187 sensitive = dep_map[ii].disable_if_equal ^ sensitive;
188 if (!sensitive) result = FALSE;
198 check_depencency(signal_user_data_t *ud, GtkWidget *widget)
203 int count = sizeof(dep_map) / sizeof(dependency_t);
205 if (ghb_widget_index(widget) < 0) return;
206 name = gtk_widget_get_name(widget);
207 g_debug("check_depencency () %s\n", name);
208 for (ii = 0; ii < count; ii++)
210 if (strcmp(dep_map[ii].widget_name, name) == 0)
214 dep_object = gtk_builder_get_object (ud->builder, dep_map[ii].dep_name);
215 if (dep_object == NULL)
217 g_message("Failed to find dependent widget %s\n", dep_map[ii].dep_name);
220 sensitive = dep_check(ud, dep_map[ii].dep_name);
221 if (GTK_IS_ACTION(dep_object))
222 gtk_action_set_sensitive(GTK_ACTION(dep_object), sensitive);
224 gtk_widget_set_sensitive(GTK_WIDGET(dep_object), sensitive);
230 ghb_check_all_depencencies(signal_user_data_t *ud)
234 int count = sizeof(dep_map) / sizeof(dependency_t);
236 g_debug("ghb_check_all_depencencies ()\n");
237 for (ii = 0; ii < count; ii++)
240 dep_object = gtk_builder_get_object (ud->builder, dep_map[ii].dep_name);
241 if (dep_object == NULL)
243 g_message("Failed to find dependent widget %s\n", dep_map[ii].dep_name);
246 sensitive = dep_check(ud, dep_map[ii].dep_name);
247 if (GTK_IS_ACTION(dep_object))
248 gtk_action_set_sensitive(GTK_ACTION(dep_object), sensitive);
250 gtk_widget_set_sensitive(GTK_WIDGET(dep_object), sensitive);
255 clear_presets_selection(signal_user_data_t *ud)
257 GtkTreeView *treeview;
258 GtkTreeSelection *selection;
260 if (ud->dont_clear_presets) return;
261 g_debug("clear_presets_selection()\n");
262 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
263 selection = gtk_tree_view_get_selection (treeview);
264 gtk_tree_selection_unselect_all (selection);
268 expand_tilde(const gchar *path)
270 const gchar *user_home;
273 gchar *expanded_path = NULL;
275 g_debug("expand_tilde ()\n");
278 user_home = g_get_home_dir();
279 home = NULL; // squash warning about home uninitialized
282 home = g_strdup(user_home);
285 else if (path[1] == '/')
287 home = g_strdup(user_home);
292 home = g_path_get_dirname(user_home);
295 expanded_path = g_strdup_printf("%s/%s", home, suffix);
298 return expanded_path;
302 on_quit1_activate(GtkMenuItem *quit, signal_user_data_t *ud)
304 g_debug("on_quit1_activate ()\n");
305 if (ud->state & GHB_STATE_WORKING)
307 if (cancel_encode("Closing HandBrake will terminate encoding.\n"))
309 ghb_hb_cleanup(FALSE);
315 ghb_hb_cleanup(FALSE);
320 set_destination(signal_user_data_t *ud)
322 if (ghb_settings_get_bool(ud->settings, "use_source_name"))
324 const gchar *vol_name, *filename, *extension;
325 gchar *dir, *new_name;
327 filename = ghb_settings_get_string(ud->settings, "destination");
328 extension = ghb_settings_get_string(ud->settings, "container");
329 dir = g_path_get_dirname (filename);
330 vol_name = ghb_settings_get_string(ud->settings, "volume_label");
331 g_debug("volume_label (%s)\n", vol_name);
332 if (vol_name == NULL)
334 vol_name = "new_video";
336 new_name = g_strdup_printf("%s/%s.%s", dir, vol_name, extension);
337 ghb_ui_update(ud, "destination", new_name);
344 uppers_and_unders(const gchar *str)
346 if (str == NULL) return FALSE;
353 if (*str >= 'a' && *str <= 'z')
369 camel_convert(gchar *str)
371 gint state = CAMEL_OTHER;
373 if (str == NULL) return;
376 if (*str == '_') *str = ' ';
381 if (*str >= 'A' && *str <= 'Z')
382 state = CAMEL_FIRST_UPPER;
387 case CAMEL_FIRST_UPPER:
389 if (*str >= 'A' && *str <= 'Z')
390 *str = *str - 'A' + 'a';
400 update_source_label(signal_user_data_t *ud, const gchar *source)
405 gchar *filename = g_strdup(source);
407 len = strlen(filename);
408 if (filename[len-1] == '/') filename[len-1] = 0;
409 if (g_file_test(filename, G_FILE_TEST_IS_DIR))
411 path = g_strsplit(filename, "/", -1);
412 len = g_strv_length (path);
413 if ((len > 1) && (strcmp("VIDEO_TS", path[len-1]) == 0))
415 label = g_strdup(path[len-2]);
419 label = g_strdup(path[len-1]);
425 // Is regular file or block dev.
426 // Check to see if it is a dvd image
427 label = ghb_dvd_volname (filename);
430 path = g_strsplit(filename, "/", -1);
431 len = g_strv_length (path);
432 // Just use the last combonent of the path
433 label = g_strdup(path[len-1]);
438 if (uppers_and_unders(label))
440 camel_convert(label);
445 GtkWidget *widget = GHB_WIDGET (ud->builder, "source_title");
448 gtk_label_set_text (GTK_LABEL(widget), label);
449 ghb_settings_set_string(ud->settings, "volume_label", label);
455 label = "No Title Found";
456 gtk_label_set_text (GTK_LABEL(widget), label);
457 ghb_settings_set_string(ud->settings, "volume_label", label);
463 static GtkWidget *dvd_device_combo = NULL;
466 chooser_file_selected_cb(GtkFileChooser *dialog, GtkComboBox *combo)
468 const gchar *name = gtk_file_chooser_get_filename (dialog);
472 gboolean foundit = FALSE;
474 if (name == NULL) return;
475 store = gtk_combo_box_get_model(combo);
476 if (gtk_tree_model_get_iter_first(store, &iter))
480 gtk_tree_model_get(store, &iter, 0, &device, -1);
481 if (strcmp(name, device) == 0)
486 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
489 gtk_combo_box_set_active_iter (combo, &iter);
491 gtk_combo_box_set_active (combo, 0);
495 dvd_device_changed_cb(GtkComboBox *combo, GtkWidget *dialog)
497 gint ii = gtk_combo_box_get_active (combo);
500 const gchar *device = gtk_combo_box_get_active_text (combo);
501 const gchar *name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(dialog));
502 if (name == NULL || strcmp(name, device) != 0)
503 gtk_file_chooser_select_filename (GTK_FILE_CHOOSER(dialog), device);
509 source_type_changed_cb(GtkToggleButton *toggle, GtkFileChooser *chooser)
513 g_debug("source_type_changed_cb ()\n");
514 if (gtk_toggle_button_get_active (toggle))
516 filename = gtk_file_chooser_get_filename (chooser);
517 gtk_file_chooser_set_action (chooser, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
518 if (filename != NULL)
520 gtk_file_chooser_set_filename(chooser, filename);
523 gtk_widget_set_sensitive (dvd_device_combo, FALSE);
524 gtk_combo_box_set_active (GTK_COMBO_BOX(dvd_device_combo), 0);
528 filename = gtk_file_chooser_get_filename (chooser);
529 gtk_file_chooser_set_action (chooser, GTK_FILE_CHOOSER_ACTION_OPEN);
530 if (filename != NULL)
532 gtk_file_chooser_set_filename(chooser, filename);
535 gtk_widget_set_sensitive (dvd_device_combo, TRUE);
540 source_dialog_extra_widgets(GtkWidget *dialog, gboolean checkbutton_active)
543 GtkWidget *checkbutton;
545 vbox = GTK_BOX(gtk_vbox_new (FALSE, 2));
546 checkbutton = gtk_check_button_new_with_label ("Open VIDEO_TS folder");
547 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(checkbutton), checkbutton_active);
548 gtk_box_pack_start (vbox, checkbutton, FALSE, FALSE, 1);
549 gtk_widget_show(checkbutton);
553 GList *drives, *link;
554 GtkWidget *label, *blank;
556 hbox = GTK_BOX(gtk_hbox_new (FALSE, 2));
557 combo = gtk_combo_box_new_text();
558 label = gtk_label_new("Detected DVD devices:");
559 blank = gtk_label_new("");
560 link = drives = dvd_device_list();
561 gtk_combo_box_append_text (GTK_COMBO_BOX(combo), "Not Selected");
564 gchar *name = (gchar*)link->data;
565 gtk_combo_box_append_text (GTK_COMBO_BOX(combo), name);
570 gtk_combo_box_set_active (GTK_COMBO_BOX(combo), 0);
571 gtk_box_pack_start (vbox, GTK_WIDGET(hbox), FALSE, FALSE, 1);
572 gtk_widget_show(GTK_WIDGET(hbox));
573 gtk_box_pack_start (hbox, label, FALSE, FALSE, 1);
574 gtk_widget_show(label);
575 gtk_box_pack_start (hbox, combo, FALSE, FALSE, 2);
576 gtk_widget_show(combo);
577 gtk_box_pack_start (hbox, blank, TRUE, TRUE, 1);
578 gtk_widget_show(blank);
580 // Ugly hackish global alert
581 dvd_device_combo = combo;
582 g_signal_connect(combo, "changed", (GCallback)dvd_device_changed_cb, dialog);
583 g_signal_connect(dialog, "selection-changed", (GCallback)chooser_file_selected_cb, combo);
585 g_signal_connect(checkbutton, "toggled", (GCallback)source_type_changed_cb, dialog);
586 return GTK_WIDGET(vbox);
590 do_scan(signal_user_data_t *ud, const gchar *filename)
592 if (filename != NULL)
594 ghb_settings_set_string(ud->settings, "source", filename);
595 if (update_source_label(ud, filename))
597 GtkProgressBar *progress;
598 progress = GTK_PROGRESS_BAR(GHB_WIDGET(ud->builder, "progressbar"));
600 path = ghb_settings_get_string( ud->settings, "source");
601 gtk_progress_bar_set_fraction (progress, 0);
602 gtk_progress_bar_set_text (progress, "Scanning ...");
603 ud->state |= GHB_STATE_SCANNING;
604 ghb_hb_cleanup(TRUE);
605 ghb_backend_scan (path, 0);
609 // TODO: error dialog
615 source_button_clicked_cb(GtkButton *button, signal_user_data_t *ud)
619 const gchar *sourcename;
621 GtkFileChooserAction action;
622 gboolean checkbutton_active;
624 g_debug("source_browse_clicked_cb ()\n");
625 sourcename = ghb_settings_get_string(ud->settings, "source");
626 checkbutton_active = FALSE;
627 if (g_file_test(sourcename, G_FILE_TEST_IS_DIR))
629 action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
630 checkbutton_active = TRUE;
634 action = GTK_FILE_CHOOSER_ACTION_OPEN;
636 dialog = gtk_file_chooser_dialog_new ("Select Source",
639 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
640 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
642 widget = source_dialog_extra_widgets(dialog, checkbutton_active);
643 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), widget);
644 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), sourcename);
645 response = gtk_dialog_run(GTK_DIALOG (dialog));
646 gtk_widget_hide(dialog);
647 if (response == GTK_RESPONSE_ACCEPT)
651 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
652 if (filename != NULL)
654 do_scan(ud, filename);
655 if (strcmp(sourcename, filename) != 0)
657 ghb_settings_set_string (ud->settings, "default_source", filename);
658 ghb_pref_save (ud->settings, "default_source");
659 ghb_dvd_set_current (filename, ud);
664 gtk_widget_destroy(dialog);
668 dvd_source_activate_cb(GtkAction *action, signal_user_data_t *ud)
670 const gchar *filename;
671 const gchar *sourcename;
673 sourcename = ghb_settings_get_string(ud->settings, "source");
674 filename = gtk_action_get_name(action);
675 do_scan(ud, filename);
676 if (strcmp(sourcename, filename) != 0)
678 ghb_settings_set_string (ud->settings, "default_source", filename);
679 ghb_pref_save (ud->settings, "default_source");
680 ghb_dvd_set_current (filename, ud);
685 update_destination_extension(signal_user_data_t *ud)
687 static gchar *containers[] = {".mkv", ".mp4", ".m4v", ".avi", ".ogm", NULL};
689 const gchar *extension;
693 g_debug("update_destination_extension ()\n");
694 extension = ghb_settings_get_string(ud->settings, "container");
695 entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "destination"));
696 filename = g_strdup(gtk_entry_get_text(entry));
697 for (ii = 0; containers[ii] != NULL; ii++)
699 if (g_str_has_suffix(filename, containers[ii]))
704 pos = g_strrstr( filename, "." );
707 // No period? shouldn't happen
711 if (strcmp(extension, &pos[1]) == 0)
713 // Extension is already correct
716 new_name = g_strjoin(".", filename, extension, NULL);
717 ghb_ui_update(ud, "destination", new_name);
725 static gboolean update_default_destination = FALSE;
728 destination_entry_changed_cb(GtkEntry *entry, signal_user_data_t *ud)
732 g_debug("destination_entry_changed_cb ()\n");
733 if ((dest = expand_tilde(gtk_entry_get_text(entry))) != NULL)
735 gtk_entry_set_text(entry, dest);
738 update_destination_extension(ud);
739 ghb_widget_to_setting(ud->settings, (GtkWidget*)entry);
740 // This signal goes off with ever keystroke, so I'm putting this
741 // update on the timer.
742 update_default_destination = TRUE;
746 destination_browse_clicked_cb(GtkButton *button, signal_user_data_t *ud)
750 const char *destname;
753 g_debug("destination_browse_clicked_cb ()\n");
754 destname = ghb_settings_get_string(ud->settings, "destination");
755 dialog = gtk_file_chooser_dialog_new ("Choose Destination",
757 GTK_FILE_CHOOSER_ACTION_SAVE,
758 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
759 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
761 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), destname);
762 basename = g_path_get_basename(destname);
763 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), basename);
765 if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
769 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
770 entry = (GtkEntry*)GHB_WIDGET(ud->builder, "destination");
773 g_debug("Failed to find widget: %s\n", "destination");
777 gtk_entry_set_text(entry, filename);
781 gtk_widget_destroy(dialog);
785 window_destroy_event_cb(GtkWidget *widget, GdkEvent *event, signal_user_data_t *ud)
787 g_debug("window_destroy_event_cb ()\n");
788 ghb_hb_cleanup(FALSE);
794 window_delete_event_cb(GtkWidget *widget, GdkEvent *event, signal_user_data_t *ud)
796 g_debug("window_delete_event_cb ()\n");
797 if (ud->state & GHB_STATE_WORKING)
799 if (cancel_encode("Closing HandBrake will terminate encoding.\n"))
801 ghb_hb_cleanup(FALSE);
807 ghb_hb_cleanup(FALSE);
813 update_acodec_combo(signal_user_data_t *ud)
815 ghb_grey_combo_options (ud->builder);
819 container_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
821 g_debug("container_changed_cb ()\n");
822 ghb_widget_to_setting(ud->settings, widget);
823 update_destination_extension(ud);
824 check_depencency(ud, widget);
825 update_acodec_combo(ud);
826 clear_presets_selection(ud);
830 get_aspect_string(gint aspect_n, gint aspect_d)
836 aspect = g_strdup_printf("%d:%d", aspect_n, aspect_d);
840 gdouble aspect_nf = (gdouble)aspect_n / aspect_d;
841 aspect = g_strdup_printf("%.2f:1", aspect_nf);
847 get_rate_string(gint rate_base, gint rate)
849 gdouble rate_f = (gdouble)rate / rate_base;
852 rate_s = g_strdup_printf("%.6g", rate_f);
856 show_title_info(signal_user_data_t *ud, ghb_title_info_t *tinfo)
861 widget = GHB_WIDGET (ud->builder, "title_duration");
862 text = g_strdup_printf ("%02d:%02d:%02d", tinfo->hours, tinfo->minutes, tinfo->seconds);
863 gtk_label_set_text (GTK_LABEL(widget), text);
865 widget = GHB_WIDGET (ud->builder, "source_dimensions");
866 text = g_strdup_printf ("%d x %d", tinfo->width, tinfo->height);
867 gtk_label_set_text (GTK_LABEL(widget), text);
869 widget = GHB_WIDGET (ud->builder, "source_aspect");
870 text = get_aspect_string(tinfo->aspect_n, tinfo->aspect_d);
871 gtk_label_set_text (GTK_LABEL(widget), text);
874 widget = GHB_WIDGET (ud->builder, "source_frame_rate");
875 text = (gchar*)get_rate_string(tinfo->rate_base, tinfo->rate);
876 gtk_label_set_text (GTK_LABEL(widget), text);
879 ghb_ui_update_int (ud, "scale_width", tinfo->width - tinfo->crop[2] - tinfo->crop[3]);
880 // If anamorphic or keep_aspect, the hight will be automatically calculated
881 gboolean keep_aspect = ghb_settings_get_bool(ud->settings, "keep_aspect");
882 gboolean anamorphic = ghb_settings_get_bool(ud->settings, "anamorphic");
883 if (!(keep_aspect || anamorphic))
884 ghb_ui_update_int (ud, "scale_height", tinfo->height - tinfo->crop[0] - tinfo->crop[1]);
886 // Set the limits of cropping. hb_set_anamorphic_size crashes if
887 // you pass it a cropped width or height == 0.
889 bound = tinfo->height / 2 - 2;
890 widget = GHB_WIDGET (ud->builder, "crop_top");
891 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
892 widget = GHB_WIDGET (ud->builder, "crop_bottom");
893 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
894 bound = tinfo->width / 2 - 2;
895 widget = GHB_WIDGET (ud->builder, "crop_left");
896 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
897 widget = GHB_WIDGET (ud->builder, "crop_right");
898 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
899 if (ghb_settings_get_bool (ud->settings, "autocrop"))
901 ghb_ui_update_int (ud, "crop_top", tinfo->crop[0]);
902 ghb_ui_update_int (ud, "crop_bottom", tinfo->crop[1]);
903 ghb_ui_update_int (ud, "crop_left", tinfo->crop[2]);
904 ghb_ui_update_int (ud, "crop_right", tinfo->crop[3]);
906 g_debug("setting max end chapter %d\n", tinfo->num_chapters);
907 widget = GHB_WIDGET (ud->builder, "end_chapter");
908 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 1, tinfo->num_chapters);
909 gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), tinfo->num_chapters);
910 widget = GHB_WIDGET (ud->builder, "start_chapter");
911 gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), 1);
915 adjust_audio_rate_combos(signal_user_data_t *ud)
917 gint titleindex, audioindex, acodec;
918 ghb_audio_info_t ainfo;
921 g_debug("adjust_audio_rate_combos ()\n");
922 titleindex = ghb_settings_get_index(ud->settings, "title");
924 widget = GHB_WIDGET(ud->builder, "audio_track");
925 audioindex = ghb_widget_int(widget);
927 widget = GHB_WIDGET(ud->builder, "audio_codec");
928 acodec = ghb_widget_int(widget);
930 if (ghb_get_audio_info (&ainfo, titleindex, audioindex) && ghb_audio_is_passthru (acodec))
932 // Set the values for bitrate and samplerate to the input rates
933 ghb_set_passthru_rate_opts (ud->builder, ainfo.bitrate);
934 ghb_ui_update_int (ud, "audio_bitrate", ainfo.bitrate);
935 ghb_ui_update_int (ud, "audio_sample_rate", 0);
936 ghb_ui_update_int (ud, "audio_mix", 0);
940 ghb_set_default_rate_opts (ud->builder);
945 set_pref_audio(gint titleindex, signal_user_data_t *ud)
947 gint acodec, track, ivalue;
950 ghb_audio_info_t ainfo;
951 gboolean skipped_1st = FALSE;
953 // Clear the audio list
954 clear_audio_list(ud);
956 // Find "best" audio based on audio preferences
957 button = GHB_WIDGET (ud->builder, "audio_add");
958 svalue = ghb_settings_get_short_opt(ud->settings, "pref_source_audio_lang");
959 acodec = ghb_settings_get_int(ud->settings, "pref_source_audio_codec");
960 track = ghb_find_audio_track(titleindex, svalue, acodec);
961 ghb_ui_update_int(ud, "audio_track", track);
962 // Get the resulting track, it may not be what was asked for.
963 track = ghb_settings_get_int(ud->settings, "audio_track");
966 // No audio tracks. Perhaps no source dvd yet
967 // Just initialize the audio controls and do not add anything to
969 acodec = ghb_settings_get_int(ud->settings, "pref_audio_codec1");
970 ghb_ui_update_int(ud, "audio_codec", acodec);
971 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_bitrate1");
972 ghb_ui_update_int(ud, "audio_bitrate", ivalue);
973 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_rate1");
974 ghb_ui_update_int(ud, "audio_sample_rate", ivalue);
975 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_mix1");
976 ghb_ui_update_int(ud, "audio_mix", ivalue);
977 svalue = ghb_settings_get_string(ud->settings, "pref_audio_drc");
978 ghb_ui_update(ud, "audio_drc", svalue);
981 acodec = ghb_settings_get_int(ud->settings, "pref_audio_codec1");
983 // 1. pref codec is ac3
984 // 2. source codec is not ac3
985 // 3. 2nd pref is enabled
986 if (ghb_get_audio_info (&ainfo, titleindex, track) && ghb_audio_is_passthru (acodec))
988 if (!ghb_audio_is_passthru(ainfo.codec))
990 acodec = ghb_get_default_acodec();
991 if (ghb_settings_get_int(ud->settings, "pref_audio_codec2") != 0)
993 // Skip first pref audio
999 ghb_ui_update_int(ud, "audio_codec", acodec);
1000 if (!ghb_audio_is_passthru (acodec))
1002 // This gets set autimatically if the codec is passthru
1003 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_bitrate1");
1004 ghb_ui_update_int(ud, "audio_bitrate", ivalue);
1005 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_rate1");
1006 ghb_ui_update_int(ud, "audio_sample_rate", ivalue);
1007 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_mix1");
1008 ivalue = ghb_get_best_mix(titleindex, track, acodec, ivalue);
1009 ghb_ui_update_int(ud, "audio_mix", ivalue);
1011 svalue = ghb_settings_get_string(ud->settings, "pref_audio_drc");
1012 ghb_ui_update(ud, "audio_drc", svalue);
1013 if (acodec != 0) // 0 is none
1015 // Add to audio list
1016 g_signal_emit_by_name(button, "clicked", ud);
1018 acodec = ghb_settings_get_int(ud->settings, "pref_audio_codec2");
1020 // 1. pref codec is ac3
1021 // 2. source codec is not ac3
1022 if (ghb_audio_is_passthru (acodec))
1024 if (!ghb_audio_is_passthru(ainfo.codec) && skipped_1st)
1026 acodec = ghb_get_default_acodec();
1035 ghb_ui_update_int(ud, "audio_codec", acodec);
1036 // Do the second prefs track
1037 if (!ghb_audio_is_passthru (acodec))
1039 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_bitrate2");
1040 ghb_ui_update_int(ud, "audio_bitrate", ivalue);
1041 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_rate2");
1042 ghb_ui_update_int(ud, "audio_sample_rate", ivalue);
1043 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_mix2");
1044 ivalue = ghb_get_best_mix(titleindex, track, acodec, ivalue);
1045 ghb_ui_update_int(ud, "audio_mix", ivalue);
1047 g_signal_emit_by_name(button, "clicked", ud);
1051 static gint preview_button_width;
1052 static gint preview_button_height;
1053 static gboolean update_preview = FALSE;
1056 set_preview_image(signal_user_data_t *ud)
1059 gint preview_width, preview_height, target_height, width, height;
1061 g_debug("set_preview_button_image ()\n");
1062 gint titleindex = ghb_settings_get_int(ud->settings, "title");
1063 if (titleindex < 0) return;
1064 widget = GHB_WIDGET (ud->builder, "preview_frame");
1065 gint frame = ghb_widget_int(widget) - 1;
1066 GdkPixbuf *preview = ghb_get_preview_image (titleindex, frame, ud->settings, TRUE);
1067 if (preview == NULL) return;
1068 widget = GHB_WIDGET (ud->builder, "preview_image");
1069 gtk_image_set_from_pixbuf(GTK_IMAGE(widget), preview);
1071 preview_width = gdk_pixbuf_get_width(preview);
1072 preview_height = gdk_pixbuf_get_height(preview);
1073 gchar *text = g_strdup_printf("%d x %d", preview_width, preview_height);
1074 widget = GHB_WIDGET (ud->builder, "preview_dims");
1075 gtk_label_set_text(GTK_LABEL(widget), text);
1078 g_debug("preview %d x %d\n", preview_width, preview_height);
1079 target_height = MIN(preview_button_height - 12, 128);
1080 height = target_height;
1081 width = preview_width * height / preview_height;
1083 if ((height >= 16) && (width >= 16))
1085 GdkPixbuf *scaled_preview;
1086 scaled_preview = gdk_pixbuf_scale_simple (preview, width, height, GDK_INTERP_NEAREST);
1087 if (scaled_preview != NULL)
1089 g_object_unref (preview);
1091 widget = GHB_WIDGET (ud->builder, "preview_button_image");
1092 gtk_image_set_from_pixbuf(GTK_IMAGE(widget), scaled_preview);
1093 g_object_unref (scaled_preview);
1099 title_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1101 ghb_title_info_t tinfo;
1103 const gchar *preset;
1105 g_debug("title_changed_cb ()\n");
1106 ghb_widget_to_setting(ud->settings, widget);
1107 check_depencency(ud, widget);
1109 titleindex = ghb_settings_get_int(ud->settings, "title");
1110 ghb_update_ui_combo_box (ud->builder, "audio_track", titleindex, FALSE);
1111 ghb_update_ui_combo_box (ud->builder, "subtitle_lang", titleindex, FALSE);
1112 preset = ghb_settings_get_string (ud->settings, "preset");
1113 ghb_update_from_preset(ud, preset, "subtitle_lang");
1114 if (ghb_get_title_info (&tinfo, titleindex))
1116 show_title_info(ud, &tinfo);
1118 update_chapter_list (ud);
1119 adjust_audio_rate_combos(ud);
1120 set_pref_audio(titleindex, ud);
1121 if (ghb_settings_get_bool (ud->settings, "vquality_type_target"))
1123 gint bitrate = ghb_calculate_target_bitrate (ud->settings, titleindex);
1124 ghb_ui_update_int (ud, "video_bitrate", bitrate);
1127 // Unfortunately, there is no way to query how many frames were
1128 // actually generated during the scan. It attempts to make 10.
1129 // If I knew how many were generated, I would adjust the spin
1130 // control range here.
1131 ghb_ui_update_int (ud, "preview_frame", 1);
1133 set_preview_image (ud);
1137 audio_codec_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1139 static gint prev_acodec = 0;
1140 gint acodec, ivalue;
1141 GHashTable *asettings;
1143 g_debug("audio_codec_changed_cb ()\n");
1145 acodec = ghb_widget_int(widget);
1146 if (ghb_audio_is_passthru (prev_acodec) && !ghb_audio_is_passthru (acodec))
1148 // Transition from passthru to not, put some audio settings back to
1150 gint titleindex = ghb_settings_get_int(ud->settings, "title");
1151 gint track = ghb_settings_get_int(ud->settings, "audio_track");
1153 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_bitrate1");
1154 ghb_ui_update_int (ud, "audio_bitrate", ivalue);
1155 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_rate1");
1156 ghb_ui_update_int (ud, "audio_sample_rate", ivalue);
1157 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_mix1");
1158 ivalue = ghb_get_best_mix(titleindex, track, acodec, ivalue);
1159 ghb_ui_update_int (ud, "audio_mix", ivalue);
1161 adjust_audio_rate_combos(ud);
1162 ghb_grey_combo_options (ud->builder);
1163 check_depencency(ud, widget);
1164 prev_acodec = acodec;
1165 asettings = get_selected_asettings(ud);
1166 if (asettings != NULL)
1168 ghb_widget_to_setting(asettings, widget);
1169 audio_list_refresh_selected(ud);
1173 static void audio_list_refresh_selected(signal_user_data_t *ud);
1174 static GHashTable* get_selected_asettings(signal_user_data_t *ud);
1177 audio_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1179 GHashTable *asettings;
1181 g_debug("audio_track_changed_cb ()\n");
1182 adjust_audio_rate_combos(ud);
1183 check_depencency(ud, widget);
1184 ghb_grey_combo_options(ud->builder);
1185 asettings = get_selected_asettings(ud);
1186 if (asettings != NULL)
1188 ghb_widget_to_setting(asettings, widget);
1189 audio_list_refresh_selected(ud);
1194 audio_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1196 GHashTable *asettings;
1198 g_debug("audio_widget_changed_cb ()\n");
1199 check_depencency(ud, widget);
1200 asettings = get_selected_asettings(ud);
1201 if (asettings != NULL)
1203 ghb_widget_to_setting(asettings, widget);
1204 audio_list_refresh_selected(ud);
1209 generic_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1211 g_debug("generic_widget_changed_cb ()\n");
1212 check_depencency(ud, widget);
1216 setting_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1218 ghb_widget_to_setting(ud->settings, widget);
1219 check_depencency(ud, widget);
1220 clear_presets_selection(ud);
1224 vcodec_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1228 ghb_widget_to_setting(ud->settings, widget);
1229 check_depencency(ud, widget);
1230 clear_presets_selection(ud);
1231 ghb_vquality_range(ud, &vqmin, &vqmax);
1232 GtkWidget *qp = GHB_WIDGET(ud->builder, "video_quality");
1233 gtk_range_set_range (GTK_RANGE(qp), vqmin, vqmax);
1237 vfr_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1239 //const gchar *name = gtk_widget_get_name(widget);
1240 //g_debug("setting_widget_changed_cb () %s\n", name);
1241 ghb_widget_to_setting(ud->settings, widget);
1242 check_depencency(ud, widget);
1243 clear_presets_selection(ud);
1244 if (ghb_settings_get_bool(ud->settings, "variable_frame_rate"))
1246 ghb_ui_update_int(ud, "framerate", 0);
1251 mirror_cb(GtkWidget *widget, signal_user_data_t *ud)
1253 const gchar *name = gtk_widget_get_name(widget);
1254 if (name == NULL) return;
1256 g_debug("mirror_cb () %s\n", name);
1257 gchar *mirror = g_strdup(name);
1258 gchar *pos = g_strrstr(mirror, "_mirror");
1259 if (pos == NULL) return;
1261 gchar *value = ghb_widget_short_opt (widget);
1262 ghb_ui_update (ud, mirror, value);
1266 // subtitles have their differ from other settings in that
1267 // the selection is updated automaitcally when the title
1268 // changes. I don't want the preset selection changed as
1269 // would happen for regular settings.
1271 subtitle_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1273 const gchar *name = gtk_widget_get_name(widget);
1274 g_debug("subtitle_changed_cb () %s\n", name);
1275 ghb_widget_to_setting(ud->settings, widget);
1276 check_depencency(ud, widget);
1280 target_size_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1282 const gchar *name = gtk_widget_get_name(widget);
1283 g_debug("setting_widget_changed_cb () %s\n", name);
1284 ghb_widget_to_setting(ud->settings, widget);
1285 check_depencency(ud, widget);
1286 clear_presets_selection(ud);
1287 if (ghb_settings_get_bool (ud->settings, "vquality_type_target"))
1289 gint titleindex = ghb_settings_get_int(ud->settings, "title");
1290 gint bitrate = ghb_calculate_target_bitrate (ud->settings, titleindex);
1291 ghb_ui_update_int (ud, "video_bitrate", bitrate);
1296 start_chapter_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1298 const gchar *name = gtk_widget_get_name(widget);
1299 g_debug("start_chapter_changed_cb () %s\n", name);
1300 ghb_widget_to_setting(ud->settings, widget);
1301 GtkWidget *end_ch = GHB_WIDGET (ud->builder, "end_chapter");
1303 gtk_spin_button_get_range (GTK_SPIN_BUTTON(end_ch), &start, &end);
1304 start = ghb_settings_get_int(ud->settings, "start_chapter");
1305 gtk_spin_button_set_range (GTK_SPIN_BUTTON(end_ch), start, end);
1306 check_depencency(ud, widget);
1310 end_chapter_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1312 const gchar *name = gtk_widget_get_name(widget);
1313 g_debug("end_chapter_changed_cb () %s\n", name);
1314 ghb_widget_to_setting(ud->settings, widget);
1315 GtkWidget *start_ch = GHB_WIDGET (ud->builder, "start_chapter");
1317 gtk_spin_button_get_range (GTK_SPIN_BUTTON(start_ch), &start, &end);
1318 end = ghb_settings_get_int(ud->settings, "end_chapter");
1319 gtk_spin_button_set_range (GTK_SPIN_BUTTON(start_ch), start, end);
1320 check_depencency(ud, widget);
1324 scale_width_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1326 g_debug("scale_width_changed_cb ()\n");
1327 ghb_widget_to_setting(ud->settings, widget);
1328 check_depencency(ud, widget);
1329 ghb_set_scale (ud, GHB_SCALE_KEEP_WIDTH);
1330 update_preview = TRUE;
1332 gint width = ghb_settings_get_int(ud->settings, "scale_width");
1333 gint height = ghb_settings_get_int(ud->settings, "scale_height");
1334 widget = GHB_WIDGET (ud->builder, "scale_dimensions");
1335 text = g_strdup_printf ("%d x %d", width, height);
1336 gtk_label_set_text (GTK_LABEL(widget), text);
1341 scale_height_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1343 g_debug("scale_height_changed_cb ()\n");
1344 ghb_widget_to_setting(ud->settings, widget);
1345 check_depencency(ud, widget);
1346 ghb_set_scale (ud, GHB_SCALE_KEEP_HEIGHT);
1347 update_preview = TRUE;
1349 gint width = ghb_settings_get_int(ud->settings, "scale_width");
1350 gint height = ghb_settings_get_int(ud->settings, "scale_height");
1351 widget = GHB_WIDGET (ud->builder, "scale_dimensions");
1352 text = g_strdup_printf ("%d x %d", width, height);
1353 gtk_label_set_text (GTK_LABEL(widget), text);
1358 crop_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1360 gint titleindex, crop[4];
1361 ghb_title_info_t tinfo;
1363 g_debug("crop_changed_cb ()\n");
1364 ghb_widget_to_setting(ud->settings, widget);
1365 check_depencency(ud, widget);
1366 ghb_set_scale (ud, GHB_SCALE_KEEP_NONE);
1368 crop[0] = ghb_settings_get_int(ud->settings, "crop_top");
1369 crop[1] = ghb_settings_get_int(ud->settings, "crop_bottom");
1370 crop[2] = ghb_settings_get_int(ud->settings, "crop_left");
1371 crop[3] = ghb_settings_get_int(ud->settings, "crop_right");
1372 titleindex = ghb_settings_get_index(ud->settings, "title");
1373 if (ghb_get_title_info (&tinfo, titleindex))
1378 width = tinfo.width - crop[2] - crop[3];
1379 height = tinfo.height - crop[0] - crop[1];
1380 widget = GHB_WIDGET (ud->builder, "crop_dimensions");
1381 text = g_strdup_printf ("%d x %d", width, height);
1382 gtk_label_set_text (GTK_LABEL(widget), text);
1386 widget = GHB_WIDGET (ud->builder, "crop_values");
1387 text = g_strdup_printf ("%d:%d:%d:%d", crop[0], crop[1], crop[2], crop[3]);
1388 gtk_label_set_text (GTK_LABEL(widget), text);
1390 update_preview = TRUE;
1394 scale_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1396 g_debug("scale_changed_cb ()\n");
1397 ghb_widget_to_setting(ud->settings, widget);
1398 check_depencency(ud, widget);
1399 clear_presets_selection(ud);
1400 ghb_set_scale (ud, GHB_SCALE_KEEP_NONE);
1401 update_preview = TRUE;
1405 text = ghb_settings_get_bool(ud->settings, "autocrop") ? "On" : "Off";
1406 widget = GHB_WIDGET (ud->builder, "crop_auto");
1407 gtk_label_set_text (GTK_LABEL(widget), text);
1408 text = ghb_settings_get_bool(ud->settings, "autoscale") ? "On" : "Off";
1409 widget = GHB_WIDGET (ud->builder, "scale_auto");
1410 gtk_label_set_text (GTK_LABEL(widget), text);
1411 text = ghb_settings_get_bool(ud->settings, "anamorphic") ? "On" : "Off";
1412 widget = GHB_WIDGET (ud->builder, "scale_anamorphic");
1413 gtk_label_set_text (GTK_LABEL(widget), text);
1417 generic_entry_changed_cb(GtkEntry *entry, signal_user_data_t *ud)
1419 // Normally (due to user input) I only want to process the entry
1420 // when editing is done and the focus-out signal is sent.
1421 // But... there's always a but.
1422 // If the entry is changed by software, the focus-out signal is not sent.
1423 // The changed signal is sent ... so here we are.
1424 // I don't want to process upon every keystroke, so I prevent processing
1425 // while the widget has focus.
1426 g_debug("generic_entry_changed_cb ()\n");
1427 if (!GTK_WIDGET_HAS_FOCUS((GtkWidget*)entry))
1429 ghb_widget_to_setting(ud->settings, (GtkWidget*)entry);
1434 generic_focus_out_cb(GtkWidget *widget, GdkEventFocus *event,
1435 signal_user_data_t *ud)
1437 g_debug("generic_focus_out_cb ()\n");
1438 ghb_widget_to_setting(ud->settings, widget);
1443 clear_audio_list(signal_user_data_t *ud)
1445 GtkTreeView *treeview;
1446 GtkListStore *store;
1449 g_debug("clear_audio_list ()\n");
1450 while (ud->audio_settings != NULL)
1452 link = ud->audio_settings;
1453 ud->audio_settings = g_slist_remove_link(ud->audio_settings, link);
1454 g_hash_table_destroy((GHashTable*)link->data);
1455 g_slist_free_1(link);
1457 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
1458 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
1459 gtk_list_store_clear (store);
1463 add_to_audio_list(signal_user_data_t *ud, GHashTable *settings)
1465 GtkTreeView *treeview;
1467 GtkListStore *store;
1468 GtkTreeSelection *selection;
1470 g_debug("add_to_audio_list ()\n");
1471 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
1472 selection = gtk_tree_view_get_selection (treeview);
1473 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
1475 gtk_list_store_append(store, &iter);
1476 gtk_list_store_set(store, &iter,
1477 // These are displayed in list
1478 0, ghb_settings_get_option(settings, "audio_track"),
1479 1, ghb_settings_get_option(settings, "audio_codec"),
1480 2, ghb_settings_get_option(settings, "audio_bitrate"),
1481 3, ghb_settings_get_option(settings, "audio_sample_rate"),
1482 4, ghb_settings_get_option(settings, "audio_mix"),
1483 // These are used to set combo box values when a list item is selected
1484 5, ghb_settings_get_string(settings, "audio_drc"),
1485 6, ghb_settings_get_short_opt(settings, "audio_track"),
1486 7, ghb_settings_get_short_opt(settings, "audio_codec"),
1487 8, ghb_settings_get_short_opt(settings, "audio_bitrate"),
1488 9, ghb_settings_get_short_opt(settings, "audio_sample_rate"),
1489 10, ghb_settings_get_short_opt(settings, "audio_mix"),
1491 gtk_tree_selection_select_iter(selection, &iter);
1495 audio_list_refresh_selected(signal_user_data_t *ud)
1497 GtkTreeView *treeview;
1498 GtkTreePath *treepath;
1499 GtkTreeSelection *selection;
1500 GtkTreeModel *store;
1505 GHashTable *asettings = NULL;
1507 g_debug("get_selected_asettings ()\n");
1508 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
1509 selection = gtk_tree_view_get_selection (treeview);
1510 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1512 // Get the row number
1513 treepath = gtk_tree_model_get_path (store, &iter);
1514 indices = gtk_tree_path_get_indices (treepath);
1517 // find audio settings
1518 if (row < 0) return;
1519 link = g_slist_nth(ud->audio_settings, row);
1520 if (link == NULL) return;
1521 asettings = (GHashTable*)link->data;
1522 gtk_list_store_set(GTK_LIST_STORE(store), &iter,
1523 // These are displayed in list
1524 0, ghb_settings_get_option(asettings, "audio_track"),
1525 1, ghb_settings_get_option(asettings, "audio_codec"),
1526 2, ghb_settings_get_option(asettings, "audio_bitrate"),
1527 3, ghb_settings_get_option(asettings, "audio_sample_rate"),
1528 4, ghb_settings_get_option(asettings, "audio_mix"),
1529 // These are used to set combo box values when a list item is selected
1530 5, ghb_settings_get_string(asettings, "audio_drc"),
1531 6, ghb_settings_get_short_opt(asettings, "audio_track"),
1532 7, ghb_settings_get_short_opt(asettings, "audio_codec"),
1533 8, ghb_settings_get_short_opt(asettings, "audio_bitrate"),
1534 9, ghb_settings_get_short_opt(asettings, "audio_sample_rate"),
1535 10, ghb_settings_get_short_opt(asettings, "audio_mix"),
1541 get_selected_asettings(signal_user_data_t *ud)
1543 GtkTreeView *treeview;
1544 GtkTreePath *treepath;
1545 GtkTreeSelection *selection;
1546 GtkTreeModel *store;
1551 GHashTable *asettings = NULL;
1553 g_debug("get_selected_asettings ()\n");
1554 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
1555 selection = gtk_tree_view_get_selection (treeview);
1556 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1558 // Get the row number
1559 treepath = gtk_tree_model_get_path (store, &iter);
1560 indices = gtk_tree_path_get_indices (treepath);
1563 // find audio settings
1564 if (row < 0) return NULL;
1565 link = g_slist_nth(ud->audio_settings, row);
1566 if (link == NULL) return NULL;
1567 asettings = (GHashTable*)link->data;
1573 audio_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
1575 GtkTreeModel *store;
1579 g_debug("audio_list_selection_changed_cb ()\n");
1580 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1582 const gchar *track, *codec, *bitrate, *sample_rate, *mix, *drc;
1583 gtk_tree_model_get(store, &iter,
1591 ghb_ui_update(ud, "audio_track", track);
1592 ghb_ui_update(ud, "audio_codec", codec);
1593 ghb_ui_update(ud, "audio_bitrate", bitrate);
1594 ghb_ui_update(ud, "audio_sample_rate", sample_rate);
1595 ghb_ui_update(ud, "audio_mix", mix);
1596 ghb_ui_update(ud, "audio_drc", drc);
1597 widget = GHB_WIDGET (ud->builder, "audio_remove");
1598 gtk_widget_set_sensitive(widget, TRUE);
1599 //widget = GHB_WIDGET (ud->builder, "audio_update");
1600 //gtk_widget_set_sensitive(widget, TRUE);
1604 widget = GHB_WIDGET (ud->builder, "audio_remove");
1605 gtk_widget_set_sensitive(widget, FALSE);
1606 //widget = GHB_WIDGET (ud->builder, "audio_update");
1607 //gtk_widget_set_sensitive(widget, FALSE);
1612 audio_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
1614 // Add the current audio settings to the list.
1615 GHashTable *asettings;
1619 g_debug("audio_add_clicked_cb ()\n");
1620 // Only allow up to 8 audio entries
1621 asettings = ghb_settings_new();
1622 widget = GHB_WIDGET(ud->builder, "audio_track");
1623 ghb_settings_set(asettings, "audio_track", ghb_widget_value(widget));
1624 widget = GHB_WIDGET(ud->builder, "audio_codec");
1625 ghb_settings_set(asettings, "audio_codec", ghb_widget_value(widget));
1626 widget = GHB_WIDGET(ud->builder, "audio_bitrate");
1627 ghb_settings_set(asettings, "audio_bitrate", ghb_widget_value(widget));
1628 widget = GHB_WIDGET(ud->builder, "audio_sample_rate");
1629 ghb_settings_set(asettings, "audio_sample_rate", ghb_widget_value(widget));
1630 widget = GHB_WIDGET(ud->builder, "audio_mix");
1631 ghb_settings_set(asettings, "audio_mix", ghb_widget_value(widget));
1632 widget = GHB_WIDGET(ud->builder, "audio_drc");
1633 ghb_settings_set(asettings, "audio_drc", ghb_widget_value(widget));
1635 ud->audio_settings = g_slist_append(ud->audio_settings, asettings);
1636 add_to_audio_list(ud, asettings);
1637 count = g_slist_length(ud->audio_settings);
1640 gtk_widget_set_sensitive(xwidget, FALSE);
1645 audio_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
1647 GtkTreeView *treeview;
1648 GtkTreePath *treepath;
1649 GtkTreeSelection *selection;
1650 GtkTreeModel *store;
1651 GtkTreeIter iter, nextIter;
1656 g_debug("audio_remove_clicked_cb ()\n");
1657 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
1658 selection = gtk_tree_view_get_selection (treeview);
1659 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1662 if (!gtk_tree_model_iter_next(store, &nextIter))
1665 if (gtk_tree_model_get_iter_first(store, &nextIter))
1667 gtk_tree_selection_select_iter (selection, &nextIter);
1672 gtk_tree_selection_select_iter (selection, &nextIter);
1674 // Get the row number
1675 treepath = gtk_tree_model_get_path (store, &iter);
1676 indices = gtk_tree_path_get_indices (treepath);
1679 // Remove the selected item
1680 gtk_list_store_remove (GTK_LIST_STORE(store), &iter);
1681 // remove from audio settings list
1682 if (row < 0) return;
1683 link = g_slist_nth(ud->audio_settings, row);
1684 if (link == NULL) return;
1685 ud->audio_settings = g_slist_remove_link(ud->audio_settings, link);
1686 g_hash_table_destroy((GHashTable*)link->data);
1687 g_slist_free_1(link);
1688 widget = GHB_WIDGET (ud->builder, "audio_add");
1689 gtk_widget_set_sensitive(widget, TRUE);
1694 audio_list_refresh(signal_user_data_t *ud)
1696 GtkTreeView *treeview;
1698 GtkListStore *store;
1701 g_debug("audio_list_refresh ()\n");
1702 GSList *link = ud->audio_settings;
1703 if (link == NULL) return;
1704 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
1705 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
1706 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
1710 GHashTable *asettings;
1712 asettings = (GHashTable*)link->data;
1713 gtk_list_store_set(GTK_LIST_STORE(store), &iter,
1714 // These are displayed in list
1715 0, ghb_settings_get_option(asettings, "audio_track"),
1716 1, ghb_settings_get_option(asettings, "audio_codec"),
1717 2, ghb_settings_get_option(asettings, "audio_bitrate"),
1718 3, ghb_settings_get_option(asettings, "audio_sample_rate"),
1719 4, ghb_settings_get_option(asettings, "audio_mix"),
1720 // These are used to set combo box values when a list item is selected
1721 5, ghb_settings_get_string(asettings, "audio_drc"),
1722 6, ghb_settings_get_short_opt(asettings, "audio_track"),
1723 7, ghb_settings_get_short_opt(asettings, "audio_codec"),
1724 8, ghb_settings_get_short_opt(asettings, "audio_bitrate"),
1725 9, ghb_settings_get_short_opt(asettings, "audio_sample_rate"),
1726 10, ghb_settings_get_short_opt(asettings, "audio_mix"),
1728 done = !gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1730 } while (!done && link);
1735 ghb_presets_list_update(signal_user_data_t *ud)
1737 GtkTreeView *treeview;
1739 GtkListStore *store;
1744 gchar **descriptions;
1745 gint flags, custom, def;
1747 g_debug("ghb_presets_list_update ()\n");
1748 presets = ghb_presets_get_names();
1749 descriptions = ghb_presets_get_descriptions();
1750 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
1751 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
1752 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
1756 if ((presets != NULL) && (presets[ii] != NULL))
1758 // Update row with settings data
1759 g_debug("Updating row\n");
1760 flags = ghb_preset_flags(presets[ii], &index);
1761 def = flags & PRESET_DEFAULT;
1762 custom = flags & PRESET_CUSTOM;
1763 gtk_list_store_set(store, &iter,
1767 3, custom ? "black" : "blue",
1768 4, descriptions[ii],
1771 done = !gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1775 // No more settings data, remove row
1776 g_debug("Removing row\n");
1777 done = !gtk_list_store_remove(store, &iter);
1781 while ((presets != NULL) && (presets[ii] != NULL))
1783 // Additional settings, add row
1784 g_debug("Adding row %s\n", presets[ii]);
1785 gtk_list_store_append(store, &iter);
1786 flags = ghb_preset_flags(presets[ii], &index);
1787 def = flags & PRESET_DEFAULT;
1788 custom = flags & PRESET_CUSTOM;
1789 gtk_list_store_set(store, &iter, 0, presets[ii],
1792 3, custom ? "black" : "blue",
1793 4, descriptions[ii],
1797 g_strfreev (presets);
1801 ghb_select_preset(GtkBuilder *builder, const gchar *preset)
1803 GtkTreeView *treeview;
1804 GtkTreeSelection *selection;
1805 GtkTreeModel *store;
1810 g_debug("select_preset()\n");
1811 if (preset == NULL) return;
1812 treeview = GTK_TREE_VIEW(GHB_WIDGET(builder, "presets_list"));
1813 selection = gtk_tree_view_get_selection (treeview);
1814 store = gtk_tree_view_get_model (treeview);
1815 if (gtk_tree_model_get_iter_first(store, &iter))
1819 gtk_tree_model_get(store, &iter, 0, &tpreset, -1);
1820 if (strcmp(preset, tpreset) == 0)
1822 gtk_tree_selection_select_iter (selection, &iter);
1825 done = !gtk_tree_model_iter_next(store, &iter);
1831 presets_save_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
1836 GtkResponseType response;
1837 const gchar *preset = "";
1839 g_debug("presets_save_clicked_cb ()\n");
1840 preset = ghb_settings_get_string (ud->settings, "preset");
1841 // Clear the description
1842 desc = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "preset_description"));
1843 //gtk_entry_set_text(desc, "");
1844 dialog = GHB_WIDGET(ud->builder, "preset_save_dialog");
1845 entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "preset_name"));
1846 gtk_entry_set_text(entry, preset);
1847 response = gtk_dialog_run(GTK_DIALOG(dialog));
1848 gtk_widget_hide(dialog);
1849 if (response == GTK_RESPONSE_OK)
1852 const gchar *name = gtk_entry_get_text(entry);
1853 g_debug("description to settings\n");
1854 ghb_widget_to_setting(ud->settings, GTK_WIDGET(desc));
1855 ghb_settings_save(ud, name);
1856 ghb_presets_list_update(ud);
1857 // Make the new preset the selected item
1858 ghb_select_preset(ud->builder, name);
1863 prefs_dialog_cb(GtkWidget *xwidget, signal_user_data_t *ud)
1866 GtkResponseType response;
1868 g_debug("prefs_dialog_cb ()\n");
1869 dialog = GHB_WIDGET(ud->builder, "prefs_dialog");
1870 response = gtk_dialog_run(GTK_DIALOG(dialog));
1871 gtk_widget_hide(dialog);
1875 presets_remove_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
1877 GtkTreeView *treeview;
1878 GtkTreeSelection *selection;
1879 GtkTreeModel *store;
1882 GtkResponseType response;
1884 g_debug("presets_remove_clicked_cb ()\n");
1885 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
1886 selection = gtk_tree_view_get_selection (treeview);
1887 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1891 gtk_tree_model_get(store, &iter, 0, &preset, -1);
1892 if (!ghb_presets_is_standard(preset))
1894 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
1895 GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
1896 "Confirm deletion of preset %s.", preset);
1897 response = gtk_dialog_run(GTK_DIALOG(dialog));
1898 gtk_widget_destroy (dialog);
1899 if (response == GTK_RESPONSE_YES)
1901 GtkTreeIter nextIter = iter;
1902 gchar *nextPreset = NULL;
1903 if (!gtk_tree_model_iter_next(store, &nextIter))
1905 if (gtk_tree_model_get_iter_first(store, &nextIter))
1907 gtk_tree_model_get(store, &nextIter, 0, &nextPreset, -1);
1912 gtk_tree_model_get(store, &nextIter, 0, &nextPreset, -1);
1914 // Remove the selected item
1915 // First unselect it so that selecting the new item works properly
1916 gtk_tree_selection_unselect_iter (selection, &iter);
1917 ghb_presets_remove(ud->settings, preset);
1918 ghb_presets_list_update(ud);
1919 ghb_select_preset(ud->builder, nextPreset);
1924 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
1925 GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
1926 "Can not delete standard preset %s.", preset);
1927 response = gtk_dialog_run(GTK_DIALOG(dialog));
1928 gtk_widget_destroy (dialog);
1934 preset_update_title_deps(signal_user_data_t *ud, ghb_title_info_t *tinfo)
1938 ghb_ui_update_int (ud, "scale_width", tinfo->width - tinfo->crop[2] - tinfo->crop[3]);
1939 // If anamorphic or keep_aspect, the hight will be automatically calculated
1940 gboolean keep_aspect = ghb_settings_get_bool(ud->settings, "keep_aspect");
1941 gboolean anamorphic = ghb_settings_get_bool(ud->settings, "anamorphic");
1942 if (!(keep_aspect || anamorphic))
1943 ghb_ui_update_int (ud, "scale_height", tinfo->height - tinfo->crop[0] - tinfo->crop[1]);
1945 // Set the limits of cropping. hb_set_anamorphic_size crashes if
1946 // you pass it a cropped width or height == 0.
1948 bound = tinfo->height / 2 - 2;
1949 widget = GHB_WIDGET (ud->builder, "crop_top");
1950 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
1951 widget = GHB_WIDGET (ud->builder, "crop_bottom");
1952 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
1953 bound = tinfo->width / 2 - 2;
1954 widget = GHB_WIDGET (ud->builder, "crop_left");
1955 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
1956 widget = GHB_WIDGET (ud->builder, "crop_right");
1957 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
1958 if (ghb_settings_get_bool (ud->settings, "autocrop"))
1960 ghb_ui_update_int (ud, "crop_top", tinfo->crop[0]);
1961 ghb_ui_update_int (ud, "crop_bottom", tinfo->crop[1]);
1962 ghb_ui_update_int (ud, "crop_left", tinfo->crop[2]);
1963 ghb_ui_update_int (ud, "crop_right", tinfo->crop[3]);
1968 presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
1970 GtkTreeModel *store;
1974 gboolean sensitive = FALSE;
1975 ghb_title_info_t tinfo;
1977 g_debug("presets_list_selection_changed_cb ()\n");
1978 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1980 gtk_tree_model_get(store, &iter, 0, &preset, -1);
1981 if (!ghb_presets_is_standard(preset))
1985 ud->dont_clear_presets = TRUE;
1986 // Temporarily set the video_quality range to (0,100)
1987 // This is needed so the video_quality value does not get
1988 // truncated when set. The range will be readjusted below
1989 GtkWidget *qp = GHB_WIDGET(ud->builder, "video_quality");
1990 gtk_range_set_range (GTK_RANGE(qp), 0, 100);
1991 ghb_set_preset(ud, preset);
1992 gint titleindex = ghb_settings_get_int(ud->settings, "title");
1993 set_pref_audio(titleindex, ud);
1994 ud->dont_clear_presets = FALSE;
1995 if (ghb_get_title_info (&tinfo, titleindex))
1997 preset_update_title_deps(ud, &tinfo);
1999 ghb_set_scale (ud, GHB_SCALE_KEEP_NONE);
2002 ghb_vquality_range(ud, &vqmin, &vqmax);
2003 gtk_range_set_range (GTK_RANGE(qp), vqmin, vqmax);
2007 g_debug("No selection??? Perhaps unselected.\n");
2009 widget = GHB_WIDGET (ud->builder, "presets_remove");
2010 gtk_widget_set_sensitive(widget, sensitive);
2014 queue_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
2016 GtkTreeModel *store;
2017 GtkTreeIter iter, piter;
2019 g_debug("queue_list_selection_changed_cb ()\n");
2020 // A queue entry is made up of a parent and multiple
2021 // children that are visible when expanded. When and entry
2022 // is selected, I want the parent to be selected.
2023 // This is purely cosmetic.
2024 if (gtk_tree_selection_get_selected(selection, &store, &iter))
2026 if (gtk_tree_model_iter_parent (store, &piter, &iter))
2029 GtkTreeView *treeview;
2031 gtk_tree_selection_select_iter (selection, &piter);
2032 path = gtk_tree_model_get_path (store, &piter);
2033 treeview = gtk_tree_selection_get_tree_view (selection);
2034 // Make the parent visible in scroll window if it is not.
2035 gtk_tree_view_scroll_to_cell (treeview, path, NULL, FALSE, 0, 0);
2042 add_to_queue_list(signal_user_data_t *ud, job_settings_t *item)
2044 GtkTreeView *treeview;
2046 GtkTreeStore *store;
2052 g_debug("update_queue_list ()\n");
2053 if (item == NULL) return;
2054 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
2055 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
2057 gint title = ghb_settings_get_int(item->settings, "title");
2058 gint start_chapter = ghb_settings_get_int(item->settings, "start_chapter");
2059 gint end_chapter = ghb_settings_get_int(item->settings, "end_chapter");
2060 gboolean pass2 = ghb_settings_get_bool(item->settings, "two_pass");
2061 const gchar *vol_name = ghb_settings_get_string(item->settings, "volume_label");
2062 if (vol_name == NULL)
2063 vol_name = "No Title";
2064 info = g_strdup_printf
2066 "<big><b>%s</b></big> (Title %d, Chapters %d through %d, %d Video %s)",
2067 vol_name, title+1, start_chapter, end_chapter,
2068 pass2 ? 2:1, pass2 ? "Passes":"Pass");
2070 gtk_tree_store_append(store, &iter, NULL);
2071 gtk_tree_store_set(store, &iter, 0, "hb-queue-job", 1, info, 2, "hb-queue-delete", -1);
2074 const gchar *vcodec = ghb_settings_get_option(item->settings, "video_codec");
2075 const gchar *container = ghb_settings_get_option(item->settings, "container");
2076 const gchar *acodec = ghb_settings_get_option(item->settings, "audio_codec");
2077 const gchar *dest = ghb_settings_get_string(item->settings, "destination");
2078 const gchar *preset = ghb_settings_get_string(item->settings, "preset");
2079 info = g_strdup_printf
2081 "<b>Preset:</b> %s\n"
2082 "<b>Format:</b> %s Container, %s Video + %s Audio\n"
2083 "<b>Destination:</b> %s",
2084 preset, container, vcodec, acodec, dest);
2086 gtk_tree_store_append(store, &citer, &iter);
2087 gtk_tree_store_set(store, &citer, 1, info, -1);
2090 gint width = ghb_settings_get_int(item->settings, "scale_width");
2091 gint height = ghb_settings_get_int(item->settings, "scale_height");
2092 gboolean anamorphic = ghb_settings_get_bool(item->settings, "anamorphic");
2093 gboolean round_dim = ghb_settings_get_bool(item->settings, "round_dimensions");
2094 gboolean keep_aspect = ghb_settings_get_bool(item->settings, "keep_aspect");
2100 aspect_desc = "(Anamorphic)";
2104 aspect_desc = "(Strict Anamorphic)";
2111 aspect_desc = "(Aspect Preserved)";
2115 aspect_desc = "(Aspect Lost)";
2118 gboolean vqtype = ghb_settings_get_bool(item->settings, "vquality_type_constant");
2120 gchar *vq_desc = "Error";
2123 vqtype = ghb_settings_get_bool(item->settings, "vquality_type_target");
2126 // Has to be bitrate
2127 vqvalue = ghb_settings_get_int(item->settings, "video_bitrate");
2133 vqvalue = ghb_settings_get_int(item->settings, "video_target");
2140 vqvalue = ghb_settings_get_int(item->settings, "video_quality");
2141 vq_desc = "% Constant Quality";
2143 const gchar *fps = ghb_settings_get_string(item->settings, "framerate");
2144 const gchar *vcodec_abbr = ghb_settings_get_short_opt(item->settings, "video_codec");
2146 if (strcmp(vcodec_abbr, "x264") == 0)
2148 gchar *x264opts = ghb_build_x264opts_string(item->settings);
2149 g_debug("xopts (%s)\n", x264opts);
2150 extra_opts = g_strdup_printf ("\n<b>x264 Options:</b> %s", x264opts);
2155 extra_opts = g_strdup("");
2157 gboolean turbo = ghb_settings_get_bool (item->settings, "turbo");
2158 gchar *turbo_desc = "\n<b>Turbo:</b> Off";;
2161 turbo_desc = "\n<b>Turbo:</b> On";
2163 num_pass = pass2 ? 2 : 1;
2164 for (ii = 0; ii < num_pass; ii++)
2166 gboolean final = (ii == (num_pass - 1));
2167 GString *pass = g_string_new("");
2168 g_string_append_printf( pass,
2170 "<b>Picture:</b> %d x %d %s\n"
2171 "<b>Video:</b> %s, %d %s, %s fps"
2173 ii ? "2nd":"1st", width, height, aspect_desc,
2174 vcodec, vqvalue, vq_desc, fps,
2175 final ? extra_opts : turbo_desc);
2180 GSList *link = item->audio_settings;
2183 GHashTable *asettings = (GHashTable*)link->data;
2184 const gchar *acodec = ghb_settings_get_option(asettings, "audio_codec");
2185 const gchar *bitrate = ghb_settings_get_string(asettings, "audio_bitrate");
2186 const gchar *samplerate = ghb_settings_get_string(asettings, "audio_sample_rate");
2187 gint track = ghb_settings_get_int(asettings, "audio_track");
2188 const gchar *mix = ghb_settings_get_option(asettings, "audio_mix");
2189 g_string_append_printf(pass,
2190 "\n<b>Audio:</b> %s, %s kbps, %s kHz, Track %d: %s",
2191 acodec, bitrate, samplerate, track+1, mix);
2195 info = g_string_free(pass, FALSE);
2196 gtk_tree_store_append(store, &citer, &iter);
2197 gtk_tree_store_set(store, &citer, 0, ii ? "hb-queue-pass2" : "hb-queue-pass1", 1, info, -1);
2204 ghb_message_dialog(GtkMessageType type, const gchar *message, const gchar *no, const gchar *yes)
2207 GtkResponseType response;
2209 // Toss up a warning dialog
2210 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
2211 type, GTK_BUTTONS_NONE,
2213 gtk_dialog_add_buttons( GTK_DIALOG(dialog),
2214 no, GTK_RESPONSE_NO,
2215 yes, GTK_RESPONSE_YES, NULL);
2216 response = gtk_dialog_run(GTK_DIALOG(dialog));
2217 gtk_widget_destroy (dialog);
2218 if (response == GTK_RESPONSE_NO)
2226 estimate_file_size(signal_user_data_t *ud)
2228 ghb_title_info_t tinfo;
2232 gint titleindex = ghb_settings_get_int(ud->settings, "title");
2233 if (titleindex < 0) return 0;
2235 if (!ghb_get_title_info(&tinfo, titleindex)) return 0;
2236 duration = ((tinfo.hours*60)+tinfo.minutes)*60+tinfo.seconds;
2237 bitrate = ghb_guess_bitrate(ud->settings);
2238 size = (gint64)duration * (gint64)bitrate/8;
2242 #define DISK_FREE_THRESH (1024L*1024L*1024L*3)
2245 validate_settings(signal_user_data_t *ud)
2247 // Check to see if the dest file exists or is
2248 // already in the queue
2250 gint titleindex = ghb_settings_get_int(ud->settings, "title");
2251 if (titleindex < 0) return FALSE;
2252 const gchar *dest = ghb_settings_get_string(ud->settings, "destination");
2253 GSList *link = ud->queue;
2254 while (link != NULL)
2256 job_settings_t *item;
2257 const gchar *filename;
2258 item = (job_settings_t*)link->data;
2259 filename = ghb_settings_get_string(item->settings, "destination");
2260 if (strcmp(dest, filename) == 0)
2262 message = g_strdup_printf(
2263 "Destination: %s\n\n"
2264 "Another queued job has specified the same destination.\n"
2265 "Do you want to overwrite?",
2267 if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message, "Cancel", "Overwrite"))
2277 gchar *destdir = g_path_get_dirname(dest);
2278 if (!g_file_test(destdir, G_FILE_TEST_IS_DIR))
2280 message = g_strdup_printf(
2281 "Destination: %s\n\n"
2282 "This is not a valid directory.",
2284 ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
2289 if (g_access(destdir, R_OK|W_OK) != 0)
2291 message = g_strdup_printf(
2292 "Destination: %s\n\n"
2293 "Can not read or write the directory.",
2295 ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
2303 gchar *resolved = ghb_resolve_symlink(destdir);
2305 gfile = g_file_new_for_path(resolved);
2306 info = g_file_query_filesystem_info(gfile,
2307 G_FILE_ATTRIBUTE_FILESYSTEM_FREE, NULL, NULL);
2310 if (g_file_info_has_attribute(info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE))
2312 size = g_file_info_get_attribute_uint64(info,
2313 G_FILE_ATTRIBUTE_FILESYSTEM_FREE);
2315 gint64 fsize = estimate_file_size(ud);
2318 message = g_strdup_printf(
2319 "Destination filesystem is almost full: %uM free\n\n"
2320 "Encode may be incomplete if you proceed.\n",
2321 (guint)(size / (1024L*1024L)));
2322 if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message, "Cancel", "Proceed"))
2330 g_object_unref(info);
2332 g_object_unref(gfile);
2335 if (g_file_test(dest, G_FILE_TEST_EXISTS))
2337 message = g_strdup_printf(
2338 "Destination: %s\n\n"
2339 "File already exhists.\n"
2340 "Do you want to overwrite?",
2342 if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message, "Cancel", "Overwrite"))
2350 // Validate video quality is in a reasonable range
2351 if (!ghb_validate_vquality(ud->settings))
2355 // Validate audio settings
2356 if (!ghb_validate_audio(ud))
2360 // Validate video settings
2361 if (!ghb_validate_video(ud))
2365 audio_list_refresh(ud);
2370 queue_add(signal_user_data_t *ud)
2372 // Add settings to the queue
2373 job_settings_t *queue_item;
2375 static gint unique_id = 0;
2377 g_debug("queue_add ()\n");
2378 if (!validate_settings(ud))
2382 // Make a copy of current settings to be used for the new job
2383 queue_item = g_malloc(sizeof(job_settings_t));
2384 queue_item->settings = ghb_settings_dup(ud->settings);
2385 queue_item->audio_settings = NULL;
2386 link = ud->audio_settings;
2387 while (link != NULL)
2389 GHashTable *asettings;
2390 asettings = ghb_settings_dup((GHashTable*)link->data);
2391 queue_item->audio_settings =
2392 g_slist_append(queue_item->audio_settings, asettings);
2393 link = g_slist_next(link);
2395 queue_item->chapter_list = g_strdupv(ud->chapter_list);
2396 ud->queue = g_slist_append(ud->queue, queue_item);
2397 add_to_queue_list(ud, queue_item);
2398 ghb_add_job (queue_item, unique_id);
2399 queue_item->unique_id = unique_id;
2400 queue_item->status = GHB_QUEUE_PENDING;
2406 queue_add_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
2408 g_debug("queue_add_clicked_cb ()\n");
2413 cancel_encode(const gchar *extra_msg)
2416 GtkResponseType response;
2418 if (extra_msg == NULL) extra_msg = "";
2419 // Toss up a warning dialog
2420 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
2421 GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE,
2422 "%sYour movie will be lost if you don't continue encoding.",
2424 gtk_dialog_add_buttons( GTK_DIALOG(dialog),
2425 "Continue Encoding", GTK_RESPONSE_NO,
2426 "Stop Encoding", GTK_RESPONSE_YES, NULL);
2427 response = gtk_dialog_run(GTK_DIALOG(dialog));
2428 gtk_widget_destroy (dialog);
2429 if (response == GTK_RESPONSE_NO) return FALSE;
2435 queue_remove_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud)
2437 GtkTreeView *treeview;
2438 GtkTreePath *treepath;
2439 GtkTreeModel *store;
2444 job_settings_t *queue_item;
2447 g_debug("queue_remove_clicked_cb ()\n");
2448 g_debug("ud %p\n", ud);
2449 g_debug("ud->builder %p\n", ud->builder);
2451 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
2452 store = gtk_tree_view_get_model(treeview);
2453 treepath = gtk_tree_path_new_from_string (path);
2454 if (gtk_tree_model_get_iter(store, &iter, treepath))
2456 // Find the entry in the queue
2457 indices = gtk_tree_path_get_indices (treepath);
2459 // Can only free the treepath After getting what I need from
2460 // indices since this points into treepath somewhere.
2461 gtk_tree_path_free (treepath);
2462 if (row < 0) return;
2463 link = g_slist_nth(ud->queue, row);
2464 if (link == NULL) return;
2465 queue_item = (job_settings_t*)link->data;
2466 if (queue_item->status == GHB_QUEUE_RUNNING)
2468 // Ask if wants to stop encode.
2469 if (!cancel_encode(NULL))
2474 // Remove the selected item
2475 g_debug(" should be removing from treestore\n");
2476 gtk_tree_store_remove(GTK_TREE_STORE(store), &iter);
2477 // Remove the corresponding item from the queue list
2478 ud->queue = g_slist_remove_link(ud->queue, link);
2479 g_slist_free_1(link);
2480 g_hash_table_destroy(queue_item->settings);
2481 link = queue_item->audio_settings;
2482 while (link != NULL)
2485 g_hash_table_destroy((GHashTable*)link->data);
2486 nextlink = g_slist_next(link);
2487 g_slist_free_1(link);
2490 g_strfreev (queue_item->chapter_list);
2491 unique_id = queue_item->unique_id;
2493 ghb_remove_job(unique_id);
2497 gtk_tree_path_free (treepath);
2502 find_queue_item(GSList *queue, gint unique_id, job_settings_t **job)
2507 while (queue != NULL)
2510 js = (job_settings_t*)queue->data;
2511 if (js->unique_id == unique_id)
2516 queue = queue->next;
2523 queue_buttons_grey(signal_user_data_t *ud, gboolean working)
2527 gint titleindex = ghb_settings_get_int(ud->settings, "title");
2528 gboolean title_ok = (titleindex >= 0);
2529 widget = GHB_WIDGET (ud->builder, "queue_start1");
2530 gtk_widget_set_sensitive (widget, !working && title_ok);
2531 widget = GHB_WIDGET (ud->builder, "queue_start2");
2532 gtk_widget_set_sensitive (widget, !working && title_ok);
2533 action = GHB_ACTION (ud->builder, "queue_start_menu");
2534 gtk_action_set_sensitive (action, !working && title_ok);
2535 widget = GHB_WIDGET (ud->builder, "queue_pause1");
2536 gtk_widget_set_sensitive (widget, working);
2537 widget = GHB_WIDGET (ud->builder, "queue_pause2");
2538 gtk_widget_set_sensitive (widget, working);
2539 action = GHB_ACTION (ud->builder, "queue_pause_menu");
2540 gtk_action_set_sensitive (action, working);
2541 widget = GHB_WIDGET (ud->builder, "queue_stop");
2542 gtk_widget_set_sensitive (widget, working);
2543 action = GHB_ACTION (ud->builder, "queue_stop_menu");
2544 gtk_action_set_sensitive (action, working);
2547 void queue_start_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud);
2549 static gint autostart_timeout = -1;
2552 autostart_timer_cb(gpointer data)
2555 GtkProgressBar *progress;
2556 signal_user_data_t *ud = (signal_user_data_t*)data;
2558 if (autostart_timeout < 0) return FALSE;
2559 gchar *remaining = g_strdup_printf("Encoding will start in %d second%c",
2560 (autostart_timeout-1) / 40 + 1, autostart_timeout <= 40 ? ' ':'s');
2561 progress = GTK_PROGRESS_BAR(GHB_WIDGET (ud->builder, "autostart_countdown"));
2562 gtk_progress_bar_set_fraction (progress, (gdouble)autostart_timeout / 800);
2563 gtk_progress_bar_set_text(progress, remaining);
2565 autostart_timeout--;
2566 if (autostart_timeout == 0)
2568 widget = GHB_WIDGET(ud->builder, "autostart_dialog");
2569 gtk_widget_hide(widget);
2570 queue_start_clicked_cb(NULL, ud);
2577 ghb_timer_cb(gpointer data)
2579 static gint ticks = 0;
2583 static gint current_id = -1;
2585 GtkTreeView *treeview;
2586 GtkTreeStore *store;
2588 static gint working = 0;
2589 static gboolean work_started = FALSE;
2591 signal_user_data_t *ud = (signal_user_data_t*)data;
2592 switch (ghb_backend_events (ud, &unique_id))
2594 case GHB_EVENT_WORKING:
2598 work_started = TRUE;
2599 queue_buttons_grey(ud, TRUE);
2601 if (unique_id != current_id)
2603 index = find_queue_item(ud->queue, current_id, &js);
2606 js->status = GHB_QUEUE_DONE;
2607 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
2608 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
2609 gchar *path = g_strdup_printf ("%d", index);
2610 if (gtk_tree_model_get_iter_from_string ( GTK_TREE_MODEL(store), &iter, path))
2612 gtk_tree_store_set(store, &iter, 0, "hb-complete", -1);
2617 index = find_queue_item(ud->queue, unique_id, &js);
2620 js->status = GHB_QUEUE_RUNNING;
2621 current_id = unique_id;
2624 index = find_queue_item(ud->queue, unique_id, &js);
2627 gchar working_icon[] = "hb-working0";
2628 working_icon[10] = '0' + working;
2629 working = (working+1) % 6;
2630 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
2631 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
2632 gchar *path = g_strdup_printf ("%d", index);
2633 if (gtk_tree_model_get_iter_from_string ( GTK_TREE_MODEL(store), &iter, path))
2635 gtk_tree_store_set(store, &iter, 0, working_icon, -1);
2640 case GHB_EVENT_PAUSED:
2643 case GHB_EVENT_WORK_DONE:
2645 ud->state &= ~GHB_STATE_WORKING;
2646 work_started = FALSE;
2647 queue_buttons_grey(ud, FALSE);
2648 index = find_queue_item(ud->queue, current_id, &js);
2651 js->status = GHB_QUEUE_DONE;
2652 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
2653 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
2654 gchar *path = g_strdup_printf ("%d", index);
2655 if (gtk_tree_model_get_iter_from_string ( GTK_TREE_MODEL(store), &iter, path))
2657 gtk_tree_store_set(store, &iter, 0, "hb-complete", -1);
2664 ghb_hb_cleanup(FALSE);
2668 case GHB_EVENT_WORK_CANCELED:
2670 work_started = FALSE;
2671 queue_buttons_grey(ud, FALSE);
2672 index = find_queue_item(ud->queue, current_id, &js);
2675 js->status = GHB_QUEUE_CANCELED;
2676 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
2677 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
2678 gchar *path = g_strdup_printf ("%d", index);
2679 if (gtk_tree_model_get_iter_from_string ( GTK_TREE_MODEL(store), &iter, path))
2681 gtk_tree_store_set(store, &iter, 0, "hb-canceled", -1);
2687 case GHB_EVENT_SCAN_DONE:
2689 ghb_title_info_t tinfo;
2691 ud->state &= ~GHB_STATE_SCANNING;
2692 ghb_update_ui_combo_box(ud->builder, "title", 0, FALSE);
2693 titleindex = ghb_longest_title();
2694 ghb_ui_update_int(ud, "title", titleindex);
2695 queue_buttons_grey(ud, FALSE);
2697 // Are there really any titles.
2698 if (ghb_get_title_info(&tinfo, titleindex))
2704 gint title = ghb_settings_get_int(ud->settings, "title");
2705 gint start_chapter = ghb_settings_get_int(ud->settings, "start_chapter");
2706 gint end_chapter = ghb_settings_get_int(ud->settings, "end_chapter");
2707 gboolean pass2 = ghb_settings_get_bool(ud->settings, "two_pass");
2708 const gchar *vol_name = ghb_settings_get_string(ud->settings, "volume_label");
2709 if (vol_name == NULL)
2710 vol_name = "No Title";
2711 const gchar *vcodec = ghb_settings_get_option(ud->settings, "video_codec");
2712 const gchar *container = ghb_settings_get_option(ud->settings, "container");
2713 const gchar *acodec = ghb_settings_get_option(ud->settings, "audio_codec");
2714 const gchar *dest = ghb_settings_get_string(ud->settings, "destination");
2715 const gchar *preset = ghb_settings_get_string(ud->settings, "preset");
2716 gchar *info = g_strdup_printf
2718 "<big><b>%s</b></big> (Title %d, Chapters %d through %d, %d Video %s)"
2719 "\n<b>Preset:</b> %s"
2720 "\n<b>Format:</b> %s Container, %s Video + %s Audio"
2721 "\n<b>Destination:</b> %s",
2722 vol_name, title+1, start_chapter, end_chapter,
2723 pass2 ? 2:1, pass2 ? "Passes":"Pass",
2724 preset, container, vcodec, acodec, dest);
2726 widget = GHB_WIDGET (ud->builder, "autostart_summary");
2727 gtk_label_set_markup (GTK_LABEL(widget), info);
2729 widget = GHB_WIDGET(ud->builder, "autostart_dialog");
2730 gtk_widget_show_now(widget);
2731 g_timeout_add (25, autostart_timer_cb, (gpointer)ud);
2732 autostart_timeout = 800;
2737 GtkProgressBar *progress;
2738 progress = GTK_PROGRESS_BAR(GHB_WIDGET (ud->builder, "progressbar"));
2739 gtk_progress_bar_set_fraction (progress, 0);
2740 gtk_progress_bar_set_text (progress, "No Source");
2747 work_started = FALSE;
2748 queue_buttons_grey(ud, FALSE);
2752 if (update_default_destination)
2754 const gchar *dest = ghb_settings_get_string(ud->settings, "destination");
2755 gchar *dest_dir = g_path_get_dirname (dest);
2756 const gchar *def_dest = ghb_settings_get_string(ud->settings, "destination_dir");
2757 if (strcmp(dest_dir, def_dest) != 0)
2759 ghb_settings_set_string (ud->settings, "destination_dir", dest_dir);
2760 ghb_pref_save (ud->settings, "destination_dir");
2762 update_default_destination = FALSE;
2766 set_preview_image (ud);
2767 update_preview = FALSE;
2769 if (ticks == 3 && ghb_autostart)
2771 // Make sure this doesn't happen twice
2772 const gchar *source = ghb_settings_get_string(ud->settings, "source");
2773 if (update_source_label(ud, source))
2775 GtkProgressBar *progress;
2776 progress = GTK_PROGRESS_BAR(GHB_WIDGET (ud->builder, "progressbar"));
2777 const gchar *path = ghb_settings_get_string( ud->settings, "source");
2778 gtk_progress_bar_set_fraction (progress, 0);
2779 gtk_progress_bar_set_text (progress, "Scanning ...");
2780 ud->state |= GHB_STATE_SCANNING;
2781 ghb_hb_cleanup(TRUE);
2782 ghb_backend_scan (path, 0);
2790 autostart_ok_cb(GtkWidget *widget, signal_user_data_t *ud)
2792 widget = GHB_WIDGET(ud->builder, "autostart_dialog");
2793 gtk_widget_hide(widget);
2794 queue_start_clicked_cb(NULL, ud);
2795 autostart_timeout = -1;
2799 autostart_cancel_cb(GtkWidget *widget, signal_user_data_t *ud)
2801 widget = GHB_WIDGET(ud->builder, "autostart_dialog");
2802 gtk_widget_hide(widget);
2803 autostart_timeout = -1;
2807 ghb_log_cb(GIOChannel *source, GIOCondition cond, gpointer data)
2811 GtkTextView *textview;
2812 GtkTextBuffer *buffer;
2814 GError *gerror = NULL;
2817 signal_user_data_t *ud = (signal_user_data_t*)data;
2819 status = g_io_channel_read_line (source, &text, &length, NULL, &gerror);
2822 textview = GTK_TEXT_VIEW(GHB_WIDGET (ud->builder, "activity_view"));
2823 buffer = gtk_text_view_get_buffer (textview);
2824 mark = gtk_text_buffer_get_insert (buffer);
2825 gtk_text_view_scroll_mark_onscreen(textview, mark);
2826 gtk_text_buffer_insert_at_cursor (buffer, text, -1);
2827 g_io_channel_write_chars (ud->activity_log, text, length, &length, NULL);
2830 if (status != G_IO_STATUS_NORMAL)
2832 // This should never happen, but if it does I would get into an
2833 // infinite loop. Returning false removes this callback.
2834 g_warning("Error while reading activity from pipe\n");
2837 g_warning("%s\n", gerror->message);
2838 g_error_free (gerror);
2843 g_error_free (gerror);
2848 about_activate_cb(GtkWidget *xwidget, signal_user_data_t *ud)
2850 GtkWidget *widget = GHB_WIDGET (ud->builder, "hb_about");
2851 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(widget), ghb_version());
2852 gtk_widget_show (widget);
2856 guide_activate_cb(GtkWidget *xwidget, signal_user_data_t *ud)
2860 {"xdg-open","http://trac.handbrake.fr/wiki/HandBrakeGuide",NULL,NULL};
2861 result = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
2865 argv[0] = "gnome-open";
2866 result = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
2870 argv[0] = "kfmclient";
2872 argv[2] = "http://trac.handbrake.fr/wiki/HandBrakeGuide";
2873 result = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
2877 argv[0] = "firefox";
2878 argv[1] = "http://trac.handbrake.fr/wiki/HandBrakeGuide";
2880 result = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
2886 hb_about_response_cb(GtkWidget *widget, gint response, signal_user_data_t *ud)
2888 gtk_widget_hide (widget);
2892 show_activity_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
2894 GtkWidget *widget = GHB_WIDGET (ud->builder, "activity_window");
2895 gtk_widget_show (widget);
2899 show_queue_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
2901 GtkWidget *widget = GHB_WIDGET (ud->builder, "queue_window");
2902 gtk_widget_show (widget);
2906 show_presets_toggled_cb(GtkToggleButton *button, signal_user_data_t *ud)
2909 GtkWindow *hb_window;
2911 g_debug("show_presets_clicked_cb ()\n");
2912 widget = GHB_WIDGET (ud->builder, "presets_frame");
2913 if (gtk_toggle_button_get_active(button))
2915 gtk_widget_show_now(widget);
2919 gtk_widget_hide(widget);
2920 hb_window = GTK_WINDOW(GHB_WIDGET (ud->builder, "hb_window"));
2921 gtk_window_resize(hb_window, 16, 16);
2923 ghb_widget_to_setting(ud->settings, GTK_WIDGET(button));
2924 ghb_pref_save(ud->settings, "show_presets");
2928 presets_frame_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation, signal_user_data_t *ud)
2930 GtkTreeView *treeview;
2931 GtkTreeSelection *selection;
2932 GtkTreeModel *store;
2935 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
2936 selection = gtk_tree_view_get_selection(treeview);
2937 if (gtk_tree_selection_get_selected(selection, &store, &iter))
2940 path = gtk_tree_model_get_path (store, &iter);
2941 // Make the parent visible in scroll window if it is not.
2942 gtk_tree_view_scroll_to_cell (treeview, path, NULL, FALSE, 0, 0);
2948 update_chapter_list(signal_user_data_t *ud)
2950 GtkTreeView *treeview;
2952 GtkListStore *store;
2955 gint titleindex, ii;
2957 g_debug("update_chapter_list ()\n");
2958 titleindex = ghb_settings_get_index(ud->settings, "title");
2959 chapters = ghb_get_chapters(titleindex);
2960 if (ud->chapter_list != NULL)
2961 g_strfreev (ud->chapter_list);
2962 ud->chapter_list = chapters;
2964 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "chapters_list"));
2965 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
2967 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
2971 if (chapters != NULL && chapters[ii])
2973 // Update row with settings data
2974 g_debug("Updating row\n");
2975 gtk_list_store_set(store, &iter,
2981 done = !gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
2985 // No more settings data, remove row
2986 g_debug("Removing row\n");
2987 done = !gtk_list_store_remove(store, &iter);
2991 while (chapters != NULL && chapters[ii])
2993 // Additional settings, add row
2994 g_debug("Adding row\n");
2995 g_debug("%d -- %s\n", ii, chapters[ii]);
2996 gtk_list_store_append(store, &iter);
2997 gtk_list_store_set(store, &iter,
3007 chapter_edited_cb(GtkCellRendererText *cell, gchar *path, gchar *text, signal_user_data_t *ud)
3009 GtkTreePath *treepath;
3010 GtkListStore *store;
3011 GtkTreeView *treeview;
3012 GtkTreeViewColumn *column;
3016 g_debug("chapter_edited_cb ()\n");
3017 g_debug("path (%s)\n", path);
3018 g_debug("text (%s)\n", text);
3019 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "chapters_list"));
3020 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
3021 treepath = gtk_tree_path_new_from_string (path);
3022 gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath);
3023 gtk_tree_path_free (treepath);
3024 gtk_list_store_set(store, &iter,
3028 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &index, -1);
3029 g_free(ud->chapter_list[index-1]);
3030 ud->chapter_list[index-1] = g_strdup(text);
3031 if (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter))
3033 column = gtk_tree_view_get_column(treeview, 1);
3034 treepath = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);
3035 gtk_tree_view_set_cursor(treeview, treepath, column, TRUE);
3036 gtk_tree_path_free (treepath);
3041 chapter_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
3043 GtkTreeModel *store;
3046 g_debug("chapter_list_selection_changed_cb ()\n");
3047 if (gtk_tree_selection_get_selected(selection, &store, &iter))
3054 queue_list_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation, GtkCellRenderer *cell)
3056 GtkTreeViewColumn *column;
3059 column = gtk_tree_view_get_column (GTK_TREE_VIEW(widget), 0);
3060 width = gtk_tree_view_column_get_width(column);
3061 g_debug("col width %d alloc width %d\n", width, allocation->width);
3062 // Set new wrap-width. Shave a little off to accomidate the icons
3063 // that share this column.
3064 if (width >= 564) // Don't allow below a certain size
3065 g_object_set(cell, "wrap-width", width-70, NULL);
3069 preview_button_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
3071 gint titleindex = ghb_settings_get_int(ud->settings, "title");
3072 if (titleindex < 0) return;
3073 g_debug("titleindex %d\n", titleindex);
3075 GtkWidget *widget = GHB_WIDGET (ud->builder, "preview_window");
3076 gtk_widget_show (widget);
3080 preview_frame_value_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
3082 set_preview_image(ud);
3086 preview_button_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation, signal_user_data_t *ud)
3088 g_debug("-------------------------------allocate %d x %d\n", allocation->width, allocation->height);
3089 if (preview_button_width == allocation->width &&
3090 preview_button_height == allocation->height)
3092 // Nothing to do. Bug out.
3093 g_debug("nothing to do\n");
3096 g_debug("-------------------------------prev allocate %d x %d\n", preview_button_width, preview_button_height);
3097 preview_button_width = allocation->width;
3098 preview_button_height = allocation->height;
3099 set_preview_image(ud);
3103 queue_start_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
3105 GSList *link = ud->queue;
3106 job_settings_t *job;
3107 gboolean running = FALSE;
3108 while (link != NULL)
3110 job = (job_settings_t*)link->data;
3111 if ((job->status == GHB_QUEUE_RUNNING) ||
3112 (job->status == GHB_QUEUE_PENDING))
3121 // The queue has no running or pending jobs.
3122 // Add current settings to the queue, then run.
3126 ud->state |= GHB_STATE_WORKING;
3131 queue_stop_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
3133 cancel_encode(NULL);
3137 queue_pause_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
3143 presets_default_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
3145 ghb_set_preset_default(ud->settings);
3146 ghb_presets_list_update(ud);
3150 debug_log_handler(const gchar *domain, GLogLevelFlags flags, const gchar *msg, gpointer data)
3152 signal_user_data_t *ud = (signal_user_data_t*)data;
3156 printf("%s: %s\n", domain, msg);
3161 set_visible(GtkWidget *widget, gboolean visible)
3165 gtk_widget_show_now(widget);
3169 gtk_widget_hide(widget);
3174 ghb_hbfd(signal_user_data_t *ud, gboolean hbfd)
3177 g_debug("ghb_hbfd\n");
3178 widget = GHB_WIDGET(ud->builder, "queue_pause1");
3179 set_visible(widget, !hbfd);
3180 widget = GHB_WIDGET(ud->builder, "queue_add");
3181 set_visible(widget, !hbfd);
3182 widget = GHB_WIDGET(ud->builder, "show_queue");
3183 set_visible(widget, !hbfd);
3184 widget = GHB_WIDGET(ud->builder, "show_activity");
3185 set_visible(widget, !hbfd);
3187 widget = GHB_WIDGET(ud->builder, "chapter_box");
3188 set_visible(widget, !hbfd);
3189 widget = GHB_WIDGET(ud->builder, "container_box");
3190 set_visible(widget, !hbfd);
3191 widget = GHB_WIDGET(ud->builder, "settings_box");
3192 set_visible(widget, !hbfd);
3193 widget = GHB_WIDGET(ud->builder, "presets_save");
3194 set_visible(widget, !hbfd);
3195 widget = GHB_WIDGET(ud->builder, "presets_remove");
3196 set_visible(widget, !hbfd);
3197 widget = GHB_WIDGET(ud->builder, "presets_default");
3198 set_visible(widget, !hbfd);
3199 widget = GHB_WIDGET (ud->builder, "hb_window");
3200 gtk_window_resize(GTK_WINDOW(widget), 16, 16);
3205 hbfd_toggled_cb(GtkWidget *widget, signal_user_data_t *ud)
3207 g_debug("hbfd_toggled_cb\n");
3208 ghb_widget_to_setting (ud->settings, widget);
3209 gboolean hbfd = ghb_settings_get_bool(ud->settings, "hbfd");
3211 ghb_pref_save(ud->settings, "hbfd");
3215 pref_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
3217 g_debug("pref_changed_cb\n");
3218 ghb_widget_to_setting (ud->settings, widget);
3219 const gchar *name = gtk_widget_get_name(widget);
3220 ghb_pref_save(ud->settings, name);
3224 ghb_file_menu_add_dvd(signal_user_data_t *ud)
3226 GList *link, *drives;
3228 GtkActionGroup *agroup = GTK_ACTION_GROUP(
3229 gtk_builder_get_object(ud->builder, "actiongroup1"));
3230 GtkUIManager *ui = GTK_UI_MANAGER(
3231 gtk_builder_get_object(ud->builder, "uimanager1"));
3232 guint merge_id = gtk_ui_manager_new_merge_id(ui);
3234 link = drives = dvd_device_list();
3235 while (link != NULL)
3237 gchar *name = (gchar*)link->data;
3238 // Create action for this drive
3239 GtkAction *action = gtk_action_new(name, name,
3240 "Scan this DVD source", "gtk-cdrom");
3241 // Add action to action group
3242 gtk_action_group_add_action_with_accel(agroup, action, "");
3243 // Add to ui manager
3244 gtk_ui_manager_add_ui(ui, merge_id,
3245 "ui/menubar1/menuitem1/quit1", name, name,
3246 GTK_UI_MANAGER_AUTO, TRUE);
3247 // Connect signal to action (menu item)
3248 g_signal_connect(action, "activate",
3249 (GCallback)dvd_source_activate_cb, ud);
3253 g_list_free(drives);
3256 gtk_ui_manager_add_ui(ui, merge_id,
3257 "ui/menubar1/menuitem1/quit1", "", NULL,
3258 GTK_UI_MANAGER_AUTO, TRUE);
3261 gboolean ghb_is_cd(GDrive *gd);
3266 GVolumeMonitor *gvm;
3267 GList *drives, *link;
3268 GList *dvd_devices = NULL;
3270 gvm = g_volume_monitor_get ();
3271 drives = g_volume_monitor_get_connected_drives (gvm);
3273 while (link != NULL)
3277 gd = (GDrive*)link->data;
3281 device = g_drive_get_identifier(gd, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
3282 dvd_devices = g_list_append(dvd_devices, (gpointer)device);
3284 g_object_unref (gd);
3287 g_list_free(drives);
3292 static DBusConnection *dbus_connection = NULL;
3293 static LibHalContext *hal_ctx;
3296 ghb_is_cd(GDrive *gd)
3299 LibHalDrive *halDrive;
3300 LibHalDriveType dtype;
3302 device = g_drive_get_identifier(gd, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
3303 halDrive = libhal_drive_from_device_file (hal_ctx, device);
3304 dtype = libhal_drive_get_type(halDrive);
3306 return (dtype == LIBHAL_DRIVE_TYPE_CDROM);
3310 drive_changed_cb(GVolumeMonitor *gvm, GDrive *gd, signal_user_data_t *ud)
3314 if (ud->current_dvd_device == NULL) return;
3315 if (ud->state != GHB_STATE_IDLE) return;
3316 device = g_drive_get_identifier(gd, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
3318 // DVD insertion detected. Scan it.
3319 if (strcmp(device, ud->current_dvd_device) == 0)
3321 if (g_drive_has_media (gd))
3323 GtkProgressBar *progress;
3324 progress = GTK_PROGRESS_BAR(GHB_WIDGET (ud->builder, "progressbar"));
3325 gtk_progress_bar_set_text (progress, "Scanning ...");
3326 gtk_progress_bar_set_fraction (progress, 0);
3327 update_source_label(ud, device);
3328 ud->state |= GHB_STATE_SCANNING;
3329 ghb_hb_cleanup(TRUE);
3330 ghb_backend_scan(device, 0);
3334 ud->state |= GHB_STATE_SCANNING;
3335 ghb_hb_cleanup(TRUE);
3336 ghb_backend_scan("/dev/null", 0);
3348 if (dbus_connection != NULL)
3351 dbus_error_init (&error);
3352 if (!(dbus_connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error))) {
3353 g_debug ("could not get system bus: %s\n", error.message);
3354 dbus_error_free (&error);
3358 //dbus_connection_setup_with_g_main (dbus_connection, NULL);
3359 //dbus_connection_set_exit_on_disconnect (dbus_connection, FALSE);
3360 //dbus_connection_add_filter (dbus_connection, gvm_dbus_filter_function, NULL, NULL);
3375 if (!(hal_ctx = libhal_ctx_new ())) {
3376 g_warning ("failed to create a HAL context!");
3380 libhal_ctx_set_dbus_connection (hal_ctx, dbus_connection);
3381 dbus_error_init (&error);
3382 if (!libhal_ctx_init (hal_ctx, &error)) {
3383 g_warning ("libhal_ctx_init failed: %s", error.message ? error.message : "unknown");
3384 dbus_error_free (&error);
3385 libhal_ctx_free (hal_ctx);
3390 * Do something to ping the HAL daemon - the above functions will
3391 * succeed even if hald is not running, so long as DBUS is. But we
3392 * want to exit silently if hald is not running, to behave on
3395 if (!(devices = libhal_get_all_devices (hal_ctx, &nr, &error))) {
3396 g_warning ("seems that HAL is not running: %s", error.message ? error.message : "unknown");
3397 dbus_error_free (&error);
3399 libhal_ctx_shutdown (hal_ctx, NULL);
3400 libhal_ctx_free (hal_ctx);
3404 libhal_free_string_array (devices);
3406 //gvm_hal_claim_branch ("/org/freedesktop/Hal/devices/local");