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 {"two_pass", "turbo", "enable", FALSE},
75 {"container", "large_mp4", "mp4|m4v", FALSE},
76 {"container", "http_optimize_mp4", "mp4|m4v", FALSE},
77 {"container", "ipod_file", "mp4|m4v", FALSE},
78 {"container", "variable_frame_rate", "avi", TRUE},
79 {"variable_frame_rate", "framerate", "enable", TRUE},
80 {"variable_frame_rate", "detelecine", "enable", TRUE},
81 {"decomb", "deinterlace", "enable", TRUE},
82 {"autocrop", "crop_top", "disable", FALSE},
83 {"autocrop", "crop_bottom", "disable", FALSE},
84 {"autocrop", "crop_left", "disable", FALSE},
85 {"autocrop", "crop_right", "disable", FALSE},
86 {"autoscale", "scale_width", "disable", FALSE},
87 {"autoscale", "scale_height", "disable", FALSE},
88 {"anamorphic", "keep_aspect", "disable", FALSE},
89 {"anamorphic", "scale_height", "disable", FALSE},
90 {"keep_aspect", "scale_height", "disable", FALSE},
91 {"video_codec", "x264_tab", "x264", FALSE},
92 {"video_codec", "x264_tab_label", "x264", FALSE},
93 {"video_codec", "ipod_file", "x264", FALSE},
94 {"audio_track", "audio_add", "none", TRUE},
95 {"audio_track", "audio_codec", "none", TRUE},
96 {"audio_track", "audio_bitrate", "none", TRUE},
97 {"audio_track", "audio_sample_rate", "none", TRUE},
98 {"audio_track", "audio_mix", "none", TRUE},
99 {"audio_track", "audio_drc", "none", TRUE},
100 {"audio_codec", "audio_bitrate", "ac3", TRUE},
101 {"audio_codec", "audio_sample_rate", "ac3", TRUE},
102 {"audio_codec", "audio_mix", "ac3", TRUE},
103 {"audio_codec", "audio_drc", "ac3", TRUE},
104 {"x264_bframes", "x264_weighted_bframes", "0", TRUE},
105 {"x264_bframes", "x264_brdo", "0", TRUE},
106 {"x264_bframes", "x264_bime", "0", TRUE},
107 {"x264_bframes", "x264_bpyramid", "<2", TRUE},
108 {"x264_bframes", "x264_direct", "0", TRUE},
109 {"x264_refs", "x264_mixed_refs", "<2", TRUE},
110 {"x264_cabac", "x264_trellis", "enable", FALSE},
111 {"x264_subme", "x264_brdo", "<6", TRUE},
112 {"x264_analyse", "x264_direct", "none", TRUE},
113 {"x264_me", "x264_merange", "umh|esa", FALSE},
114 {"pref_audio_codec1", "pref_audio_bitrate1", "none", TRUE},
115 {"pref_audio_codec1", "pref_audio_rate1", "none", TRUE},
116 {"pref_audio_codec1", "pref_audio_mix1", "none", TRUE},
117 {"pref_audio_codec1", "pref_audio_codec2", "none", TRUE},
118 {"pref_audio_codec1", "pref_audio_bitrate2", "none", TRUE},
119 {"pref_audio_codec1", "pref_audio_rate2", "none", TRUE},
120 {"pref_audio_codec1", "pref_audio_mix2", "none", TRUE},
121 {"pref_audio_codec2", "pref_audio_bitrate2", "none", TRUE},
122 {"pref_audio_codec2", "pref_audio_rate2", "none", TRUE},
123 {"pref_audio_codec2", "pref_audio_mix2", "none", TRUE},
124 {"chapter_markers", "chapters_list", "enable", FALSE},
128 dep_check(signal_user_data_t *ud, const gchar *name)
134 int count = sizeof(dep_map) / sizeof(dependency_t);
135 gboolean result = TRUE;
137 g_debug("dep_check () %s\n", name);
138 for (ii = 0; ii < count; ii++)
140 if (strcmp(dep_map[ii].dep_name, name) == 0)
142 widget = GHB_WIDGET(ud->builder, dep_map[ii].widget_name);
143 dep_object = gtk_builder_get_object(ud->builder, dep_map[ii].dep_name);
144 value = ghb_widget_short_opt(widget);
145 if (dep_object == NULL || widget == NULL)
147 g_message("Failed to find widget\n");
152 gchar **values = g_strsplit(dep_map[ii].enable_value, "|", 10);
153 gboolean sensitive = FALSE;
155 while (values && values[jj])
157 if (values[jj][0] == '>')
159 gdouble dbl = g_strtod (&values[jj][1], NULL);
160 gdouble dvalue = ghb_widget_dbl (widget);
167 else if (values[jj][0] == '<')
169 gdouble dbl = g_strtod (&values[jj][1], NULL);
170 gdouble dvalue = ghb_widget_dbl (widget);
177 if (strcmp(values[jj], value) == 0)
184 sensitive = dep_map[ii].disable_if_equal ^ sensitive;
185 if (!sensitive) result = FALSE;
195 check_depencency(signal_user_data_t *ud, GtkWidget *widget)
200 int count = sizeof(dep_map) / sizeof(dependency_t);
202 if (ghb_widget_index(widget) < 0) return;
203 name = gtk_widget_get_name(widget);
204 g_debug("check_depencency () %s\n", name);
205 for (ii = 0; ii < count; ii++)
207 if (strcmp(dep_map[ii].widget_name, name) == 0)
211 dep_object = gtk_builder_get_object (ud->builder, dep_map[ii].dep_name);
212 if (dep_object == NULL)
214 g_message("Failed to find dependent widget %s\n", dep_map[ii].dep_name);
217 sensitive = dep_check(ud, dep_map[ii].dep_name);
218 if (GTK_IS_ACTION(dep_object))
219 gtk_action_set_sensitive(GTK_ACTION(dep_object), sensitive);
221 gtk_widget_set_sensitive(GTK_WIDGET(dep_object), sensitive);
227 ghb_check_all_depencencies(signal_user_data_t *ud)
231 int count = sizeof(dep_map) / sizeof(dependency_t);
233 g_debug("ghb_check_all_depencencies ()\n");
234 for (ii = 0; ii < count; ii++)
237 dep_object = gtk_builder_get_object (ud->builder, dep_map[ii].dep_name);
238 if (dep_object == NULL)
240 g_message("Failed to find dependent widget %s\n", dep_map[ii].dep_name);
243 sensitive = dep_check(ud, dep_map[ii].dep_name);
244 if (GTK_IS_ACTION(dep_object))
245 gtk_action_set_sensitive(GTK_ACTION(dep_object), sensitive);
247 gtk_widget_set_sensitive(GTK_WIDGET(dep_object), sensitive);
252 clear_presets_selection(signal_user_data_t *ud)
254 GtkTreeView *treeview;
255 GtkTreeSelection *selection;
257 if (ud->dont_clear_presets) return;
258 g_debug("clear_presets_selection()\n");
259 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
260 selection = gtk_tree_view_get_selection (treeview);
261 gtk_tree_selection_unselect_all (selection);
265 expand_tilde(const gchar *path)
267 const gchar *user_home;
270 gchar *expanded_path = NULL;
272 g_debug("expand_tilde ()\n");
275 user_home = g_get_home_dir();
276 home = NULL; // squash warning about home uninitialized
279 home = g_strdup(user_home);
282 else if (path[1] == '/')
284 home = g_strdup(user_home);
289 home = g_path_get_dirname(user_home);
292 expanded_path = g_strdup_printf("%s/%s", home, suffix);
295 return expanded_path;
299 on_quit1_activate(GtkMenuItem *quit, signal_user_data_t *ud)
301 g_debug("on_quit1_activate ()\n");
302 if (ud->state & GHB_STATE_WORKING)
304 if (cancel_encode("Closing HandBrake will terminate encoding.\n"))
315 set_destination(signal_user_data_t *ud)
317 if (ghb_settings_get_bool(ud->settings, "use_source_name"))
319 const gchar *vol_name, *filename, *extension;
320 gchar *dir, *new_name;
322 filename = ghb_settings_get_string(ud->settings, "destination");
323 extension = ghb_settings_get_string(ud->settings, "container");
324 dir = g_path_get_dirname (filename);
325 vol_name = ghb_settings_get_string(ud->settings, "volume_label");
326 g_debug("volume_label (%s)\n", vol_name);
327 if (vol_name == NULL)
329 vol_name = "new_video";
331 new_name = g_strdup_printf("%s/%s.%s", dir, vol_name, extension);
332 ghb_ui_update(ud, "destination", new_name);
339 uppers_and_unders(const gchar *str)
341 if (str == NULL) return FALSE;
348 if (*str >= 'a' && *str <= 'z')
364 camel_convert(gchar *str)
366 gint state = CAMEL_OTHER;
368 if (str == NULL) return;
371 if (*str == '_') *str = ' ';
376 if (*str >= 'A' && *str <= 'Z')
377 state = CAMEL_FIRST_UPPER;
382 case CAMEL_FIRST_UPPER:
384 if (*str >= 'A' && *str <= 'Z')
385 *str = *str - 'A' + 'a';
395 update_source_label(signal_user_data_t *ud, const gchar *source)
400 gchar *filename = g_strdup(source);
402 len = strlen(filename);
403 if (filename[len-1] == '/') filename[len-1] = 0;
404 if (g_file_test(filename, G_FILE_TEST_IS_DIR))
406 path = g_strsplit(filename, "/", -1);
407 len = g_strv_length (path);
408 if ((len > 1) && (strcmp("VIDEO_TS", path[len-1]) == 0))
410 label = g_strdup(path[len-2]);
414 label = g_strdup(path[len-1]);
420 // Is regular file or block dev.
421 // Check to see if it is a dvd image
422 label = ghb_dvd_volname (filename);
425 path = g_strsplit(filename, "/", -1);
426 len = g_strv_length (path);
427 // Just use the last combonent of the path
428 label = g_strdup(path[len-1]);
433 if (uppers_and_unders(label))
435 camel_convert(label);
440 GtkWidget *widget = GHB_WIDGET (ud->builder, "source_title");
443 gtk_label_set_text (GTK_LABEL(widget), label);
444 ghb_settings_set_string(ud->settings, "volume_label", label);
450 label = "No Title Found";
451 gtk_label_set_text (GTK_LABEL(widget), label);
452 ghb_settings_set_string(ud->settings, "volume_label", label);
458 static GtkWidget *dvd_device_combo = NULL;
461 chooser_file_selected_cb(GtkFileChooser *dialog, GtkComboBox *combo)
463 const gchar *name = gtk_file_chooser_get_filename (dialog);
467 gboolean foundit = FALSE;
469 if (name == NULL) return;
470 store = gtk_combo_box_get_model(combo);
471 if (gtk_tree_model_get_iter_first(store, &iter))
475 gtk_tree_model_get(store, &iter, 0, &device, -1);
476 if (strcmp(name, device) == 0)
481 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
484 gtk_combo_box_set_active_iter (combo, &iter);
486 gtk_combo_box_set_active (combo, 0);
490 dvd_device_changed_cb(GtkComboBox *combo, GtkWidget *dialog)
492 gint ii = gtk_combo_box_get_active (combo);
495 const gchar *device = gtk_combo_box_get_active_text (combo);
496 const gchar *name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(dialog));
497 if (name == NULL || strcmp(name, device) != 0)
498 gtk_file_chooser_select_filename (GTK_FILE_CHOOSER(dialog), device);
504 source_type_changed_cb(GtkToggleButton *toggle, GtkFileChooser *chooser)
508 g_debug("source_type_changed_cb ()\n");
509 if (gtk_toggle_button_get_active (toggle))
511 filename = gtk_file_chooser_get_filename (chooser);
512 gtk_file_chooser_set_action (chooser, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
513 if (filename != NULL)
515 gtk_file_chooser_set_filename(chooser, filename);
518 gtk_widget_set_sensitive (dvd_device_combo, FALSE);
519 gtk_combo_box_set_active (GTK_COMBO_BOX(dvd_device_combo), 0);
523 filename = gtk_file_chooser_get_filename (chooser);
524 gtk_file_chooser_set_action (chooser, GTK_FILE_CHOOSER_ACTION_OPEN);
525 if (filename != NULL)
527 gtk_file_chooser_set_filename(chooser, filename);
530 gtk_widget_set_sensitive (dvd_device_combo, TRUE);
535 source_dialog_extra_widgets(GtkWidget *dialog, gboolean checkbutton_active)
538 GtkWidget *checkbutton;
540 vbox = GTK_BOX(gtk_vbox_new (FALSE, 2));
541 checkbutton = gtk_check_button_new_with_label ("Open VIDEO_TS folder");
542 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(checkbutton), checkbutton_active);
543 gtk_box_pack_start (vbox, checkbutton, FALSE, FALSE, 1);
544 gtk_widget_show(checkbutton);
548 GList *drives, *link;
549 GtkWidget *label, *blank;
551 hbox = GTK_BOX(gtk_hbox_new (FALSE, 2));
552 combo = gtk_combo_box_new_text();
553 label = gtk_label_new("Detected DVD devices:");
554 blank = gtk_label_new("");
555 link = drives = dvd_device_list();
556 gtk_combo_box_append_text (GTK_COMBO_BOX(combo), "Not Selected");
559 gchar *name = (gchar*)link->data;
560 gtk_combo_box_append_text (GTK_COMBO_BOX(combo), name);
565 gtk_combo_box_set_active (GTK_COMBO_BOX(combo), 0);
566 gtk_box_pack_start (vbox, GTK_WIDGET(hbox), FALSE, FALSE, 1);
567 gtk_widget_show(GTK_WIDGET(hbox));
568 gtk_box_pack_start (hbox, label, FALSE, FALSE, 1);
569 gtk_widget_show(label);
570 gtk_box_pack_start (hbox, combo, FALSE, FALSE, 2);
571 gtk_widget_show(combo);
572 gtk_box_pack_start (hbox, blank, TRUE, TRUE, 1);
573 gtk_widget_show(blank);
575 // Ugly hackish global alert
576 dvd_device_combo = combo;
577 g_signal_connect(combo, "changed", (GCallback)dvd_device_changed_cb, dialog);
578 g_signal_connect(dialog, "selection-changed", (GCallback)chooser_file_selected_cb, combo);
580 g_signal_connect(checkbutton, "toggled", (GCallback)source_type_changed_cb, dialog);
581 return GTK_WIDGET(vbox);
585 do_scan(signal_user_data_t *ud, const gchar *filename)
587 if (filename != NULL)
589 ghb_settings_set_string(ud->settings, "source", filename);
590 if (update_source_label(ud, filename))
592 GtkProgressBar *progress;
593 progress = GTK_PROGRESS_BAR(GHB_WIDGET(ud->builder, "progressbar"));
595 path = ghb_settings_get_string( ud->settings, "source");
596 gtk_progress_bar_set_fraction (progress, 0);
597 gtk_progress_bar_set_text (progress, "Scanning ...");
598 ud->state |= GHB_STATE_SCANNING;
599 ghb_backend_scan (path, 0);
603 // TODO: error dialog
609 source_button_clicked_cb(GtkButton *button, signal_user_data_t *ud)
613 const gchar *sourcename;
615 GtkFileChooserAction action;
616 gboolean checkbutton_active;
618 g_debug("source_browse_clicked_cb ()\n");
619 sourcename = ghb_settings_get_string(ud->settings, "source");
620 checkbutton_active = FALSE;
621 if (g_file_test(sourcename, G_FILE_TEST_IS_DIR))
623 action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
624 checkbutton_active = TRUE;
628 action = GTK_FILE_CHOOSER_ACTION_OPEN;
630 dialog = gtk_file_chooser_dialog_new ("Select Source",
633 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
634 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
636 widget = source_dialog_extra_widgets(dialog, checkbutton_active);
637 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), widget);
638 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), sourcename);
639 response = gtk_dialog_run(GTK_DIALOG (dialog));
640 gtk_widget_hide(dialog);
641 if (response == GTK_RESPONSE_ACCEPT)
645 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
646 if (filename != NULL)
648 do_scan(ud, filename);
649 if (strcmp(sourcename, filename) != 0)
651 ghb_settings_set_string (ud->settings, "default_source", filename);
652 ghb_prefs_save (ud->settings);
653 ghb_dvd_set_current (filename, ud);
658 gtk_widget_destroy(dialog);
662 dvd_source_activate_cb(GtkAction *action, signal_user_data_t *ud)
664 const gchar *filename;
665 const gchar *sourcename;
667 sourcename = ghb_settings_get_string(ud->settings, "source");
668 filename = gtk_action_get_name(action);
669 do_scan(ud, filename);
670 if (strcmp(sourcename, filename) != 0)
672 ghb_settings_set_string (ud->settings, "default_source", filename);
673 ghb_prefs_save (ud->settings);
674 ghb_dvd_set_current (filename, ud);
679 update_destination_extension(signal_user_data_t *ud)
681 static gchar *containers[] = {"mkv", "mp4", "m4v", "avi", "ogm", NULL};
683 const gchar *extension;
687 g_debug("update_destination_extension ()\n");
688 extension = ghb_settings_get_string(ud->settings, "container");
689 entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "destination"));
690 filename = g_strdup(gtk_entry_get_text(entry));
691 for (ii = 0; containers[ii] != NULL; ii++)
693 if (g_str_has_suffix(filename, containers[ii]))
698 pos = g_strrstr( filename, "." );
700 if (strcmp(extension, &pos[1]) == 0)
702 // Extension is already correct
705 new_name = g_strjoin(".", filename, extension, NULL);
706 ghb_ui_update(ud, "destination", new_name);
714 static gboolean update_default_destination = FALSE;
717 destination_entry_changed_cb(GtkEntry *entry, signal_user_data_t *ud)
721 g_debug("destination_entry_changed_cb ()\n");
722 if ((dest = expand_tilde(gtk_entry_get_text(entry))) != NULL)
724 gtk_entry_set_text(entry, dest);
727 update_destination_extension(ud);
728 ghb_widget_to_setting(ud->settings, (GtkWidget*)entry);
729 // This signal goes off with ever keystroke, so I'm putting this
730 // update on the timer.
731 update_default_destination = TRUE;
735 destination_browse_clicked_cb(GtkButton *button, signal_user_data_t *ud)
739 const char *destname;
742 g_debug("destination_browse_clicked_cb ()\n");
743 destname = ghb_settings_get_string(ud->settings, "destination");
744 dialog = gtk_file_chooser_dialog_new ("Choose Destination",
746 GTK_FILE_CHOOSER_ACTION_SAVE,
747 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
748 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
750 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), destname);
751 basename = g_path_get_basename(destname);
752 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), basename);
754 if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
758 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
759 entry = (GtkEntry*)GHB_WIDGET(ud->builder, "destination");
762 g_debug("Failed to find widget: %s\n", "destination");
766 gtk_entry_set_text(entry, filename);
770 gtk_widget_destroy(dialog);
774 window_destroy_event_cb(GtkWidget *widget, GdkEvent *event, signal_user_data_t *ud)
776 g_debug("window_destroy_event_cb ()\n");
782 window_delete_event_cb(GtkWidget *widget, GdkEvent *event, signal_user_data_t *ud)
784 g_debug("window_delete_event_cb ()\n");
785 if (ud->state & GHB_STATE_WORKING)
787 if (cancel_encode("Closing HandBrake will terminate encoding.\n"))
799 update_acodec_combo(signal_user_data_t *ud)
801 ghb_grey_combo_options (ud->builder);
805 container_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
807 g_debug("container_changed_cb ()\n");
808 ghb_widget_to_setting(ud->settings, widget);
809 update_destination_extension(ud);
810 check_depencency(ud, widget);
811 update_acodec_combo(ud);
812 clear_presets_selection(ud);
816 get_aspect_string(gint aspect_n, gint aspect_d)
822 aspect = g_strdup_printf("%d:%d", aspect_n, aspect_d);
826 gdouble aspect_nf = (gdouble)aspect_n / aspect_d;
827 aspect = g_strdup_printf("%.2f:1", aspect_nf);
833 get_rate_string(gint rate_base, gint rate)
835 gdouble rate_f = (gdouble)rate / rate_base;
838 rate_s = g_strdup_printf("%.6g", rate_f);
842 show_title_info(signal_user_data_t *ud, ghb_title_info_t *tinfo)
847 widget = GHB_WIDGET (ud->builder, "title_duration");
848 text = g_strdup_printf ("%02d:%02d:%02d", tinfo->hours, tinfo->minutes, tinfo->seconds);
849 gtk_label_set_text (GTK_LABEL(widget), text);
851 widget = GHB_WIDGET (ud->builder, "source_dimensions");
852 text = g_strdup_printf ("%d x %d", tinfo->width, tinfo->height);
853 gtk_label_set_text (GTK_LABEL(widget), text);
855 widget = GHB_WIDGET (ud->builder, "source_aspect");
856 text = get_aspect_string(tinfo->aspect_n, tinfo->aspect_d);
857 gtk_label_set_text (GTK_LABEL(widget), text);
860 widget = GHB_WIDGET (ud->builder, "source_frame_rate");
861 text = (gchar*)get_rate_string(tinfo->rate_base, tinfo->rate);
862 gtk_label_set_text (GTK_LABEL(widget), text);
865 ghb_ui_update_int (ud, "scale_width", tinfo->width - tinfo->crop[2] - tinfo->crop[3]);
866 // If anamorphic or keep_aspect, the hight will be automatically calculated
867 gboolean keep_aspect = ghb_settings_get_bool(ud->settings, "keep_aspect");
868 gboolean anamorphic = ghb_settings_get_bool(ud->settings, "anamorphic");
869 if (!(keep_aspect || anamorphic))
870 ghb_ui_update_int (ud, "scale_height", tinfo->height - tinfo->crop[0] - tinfo->crop[1]);
872 // Set the limits of cropping. hb_set_anamorphic_size crashes if
873 // you pass it a cropped width or height == 0.
875 bound = tinfo->height / 2 - 2;
876 widget = GHB_WIDGET (ud->builder, "crop_top");
877 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
878 widget = GHB_WIDGET (ud->builder, "crop_bottom");
879 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
880 bound = tinfo->width / 2 - 2;
881 widget = GHB_WIDGET (ud->builder, "crop_left");
882 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
883 widget = GHB_WIDGET (ud->builder, "crop_right");
884 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
885 if (ghb_settings_get_bool (ud->settings, "autocrop"))
887 ghb_ui_update_int (ud, "crop_top", tinfo->crop[0]);
888 ghb_ui_update_int (ud, "crop_bottom", tinfo->crop[1]);
889 ghb_ui_update_int (ud, "crop_left", tinfo->crop[2]);
890 ghb_ui_update_int (ud, "crop_right", tinfo->crop[3]);
892 g_debug("setting max end chapter %d\n", tinfo->num_chapters);
893 widget = GHB_WIDGET (ud->builder, "end_chapter");
894 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 1, tinfo->num_chapters);
895 gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), tinfo->num_chapters);
896 widget = GHB_WIDGET (ud->builder, "start_chapter");
897 gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), 1);
901 adjust_audio_rate_combos(signal_user_data_t *ud)
903 gint titleindex, audioindex, acodec;
904 ghb_audio_info_t ainfo;
907 g_debug("adjust_audio_rate_combos ()\n");
908 titleindex = ghb_settings_get_index(ud->settings, "title");
910 widget = GHB_WIDGET(ud->builder, "audio_track");
911 audioindex = ghb_widget_int(widget);
913 widget = GHB_WIDGET(ud->builder, "audio_codec");
914 acodec = ghb_widget_int(widget);
916 if (ghb_get_audio_info (&ainfo, titleindex, audioindex) && ghb_audio_is_passthru (acodec))
918 // Set the values for bitrate and samplerate to the input rates
919 ghb_set_passthru_rate_opts (ud->builder, ainfo.bitrate);
920 ghb_ui_update_int (ud, "audio_bitrate", ainfo.bitrate);
921 ghb_ui_update_int (ud, "audio_sample_rate", 0);
922 ghb_ui_update_int (ud, "audio_mix", 0);
926 ghb_set_default_rate_opts (ud->builder);
931 set_pref_audio(gint titleindex, signal_user_data_t *ud)
933 gint acodec, track, ivalue;
936 ghb_audio_info_t ainfo;
937 gboolean skipped_1st = FALSE;
939 // Clear the audio list
940 clear_audio_list(ud);
942 // Find "best" audio based on audio preferences
943 button = GHB_WIDGET (ud->builder, "audio_add");
944 svalue = ghb_settings_get_short_opt(ud->settings, "pref_source_audio_lang");
945 acodec = ghb_settings_get_int(ud->settings, "pref_source_audio_codec");
946 track = ghb_find_audio_track(titleindex, svalue, acodec);
947 ghb_ui_update_int(ud, "audio_track", track);
948 // Get the resulting track, it may not be what was asked for.
949 track = ghb_settings_get_int(ud->settings, "audio_track");
952 // No audio tracks. Perhaps no source dvd yet
953 // Just initialize the audio controls and do not add anything to
955 acodec = ghb_settings_get_int(ud->settings, "pref_audio_codec1");
956 ghb_ui_update_int(ud, "audio_codec", acodec);
957 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_bitrate1");
958 ghb_ui_update_int(ud, "audio_bitrate", ivalue);
959 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_rate1");
960 ghb_ui_update_int(ud, "audio_sample_rate", ivalue);
961 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_mix1");
962 ghb_ui_update_int(ud, "audio_mix", ivalue);
963 svalue = ghb_settings_get_string(ud->settings, "pref_audio_drc");
964 ghb_ui_update(ud, "audio_drc", svalue);
967 acodec = ghb_settings_get_int(ud->settings, "pref_audio_codec1");
969 // 1. pref codec is ac3
970 // 2. source codec is not ac3
971 // 3. 2nd pref is enabled
972 if (ghb_get_audio_info (&ainfo, titleindex, track) && ghb_audio_is_passthru (acodec))
974 if (!ghb_audio_is_passthru(ainfo.codec))
976 acodec = ghb_get_default_acodec();
977 if (ghb_settings_get_int(ud->settings, "pref_audio_codec2") != 0)
979 // Skip first pref audio
985 ghb_ui_update_int(ud, "audio_codec", acodec);
986 if (!ghb_audio_is_passthru (acodec))
988 // This gets set autimatically if the codec is passthru
989 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_bitrate1");
990 ghb_ui_update_int(ud, "audio_bitrate", ivalue);
991 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_rate1");
992 ghb_ui_update_int(ud, "audio_sample_rate", ivalue);
993 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_mix1");
994 ivalue = ghb_get_best_mix(titleindex, track, acodec, ivalue);
995 ghb_ui_update_int(ud, "audio_mix", ivalue);
997 svalue = ghb_settings_get_string(ud->settings, "pref_audio_drc");
998 ghb_ui_update(ud, "audio_drc", svalue);
999 if (acodec != 0) // 0 is none
1001 // Add to audio list
1002 g_signal_emit_by_name(button, "clicked", ud);
1004 acodec = ghb_settings_get_int(ud->settings, "pref_audio_codec2");
1006 // 1. pref codec is ac3
1007 // 2. source codec is not ac3
1008 if (ghb_audio_is_passthru (acodec))
1010 if (!ghb_audio_is_passthru(ainfo.codec) && skipped_1st)
1012 acodec = ghb_get_default_acodec();
1021 ghb_ui_update_int(ud, "audio_codec", acodec);
1022 // Do the second prefs track
1023 if (!ghb_audio_is_passthru (acodec))
1025 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_bitrate2");
1026 ghb_ui_update_int(ud, "audio_bitrate", ivalue);
1027 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_rate2");
1028 ghb_ui_update_int(ud, "audio_sample_rate", ivalue);
1029 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_mix2");
1030 ivalue = ghb_get_best_mix(titleindex, track, acodec, ivalue);
1031 ghb_ui_update_int(ud, "audio_mix", ivalue);
1033 g_signal_emit_by_name(button, "clicked", ud);
1037 static gint preview_button_width;
1038 static gint preview_button_height;
1039 static gboolean update_preview = FALSE;
1042 set_preview_image(signal_user_data_t *ud)
1045 gint preview_width, preview_height, target_height, width, height;
1047 g_debug("set_preview_button_image ()\n");
1048 gint titleindex = ghb_settings_get_int(ud->settings, "title");
1049 if (titleindex < 0) return;
1050 widget = GHB_WIDGET (ud->builder, "preview_frame");
1051 gint frame = ghb_widget_int(widget) - 1;
1052 GdkPixbuf *preview = ghb_get_preview_image (titleindex, frame, ud->settings, TRUE);
1053 if (preview == NULL) return;
1054 widget = GHB_WIDGET (ud->builder, "preview_image");
1055 gtk_image_set_from_pixbuf(GTK_IMAGE(widget), preview);
1057 preview_width = gdk_pixbuf_get_width(preview);
1058 preview_height = gdk_pixbuf_get_height(preview);
1059 gchar *text = g_strdup_printf("%d x %d", preview_width, preview_height);
1060 widget = GHB_WIDGET (ud->builder, "preview_dims");
1061 gtk_label_set_text(GTK_LABEL(widget), text);
1064 g_debug("preview %d x %d\n", preview_width, preview_height);
1065 target_height = MIN(preview_button_height - 12, 128);
1066 height = target_height;
1067 width = preview_width * height / preview_height;
1069 if ((height >= 16) && (width >= 16))
1071 GdkPixbuf *scaled_preview;
1072 scaled_preview = gdk_pixbuf_scale_simple (preview, width, height, GDK_INTERP_NEAREST);
1073 if (scaled_preview != NULL)
1075 g_object_unref (preview);
1077 widget = GHB_WIDGET (ud->builder, "preview_button_image");
1078 gtk_image_set_from_pixbuf(GTK_IMAGE(widget), scaled_preview);
1079 g_object_unref (scaled_preview);
1085 title_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1087 ghb_title_info_t tinfo;
1089 const gchar *preset;
1091 g_debug("title_changed_cb ()\n");
1092 ghb_widget_to_setting(ud->settings, widget);
1093 check_depencency(ud, widget);
1095 titleindex = ghb_settings_get_int(ud->settings, "title");
1096 ghb_update_ui_combo_box (ud->builder, "audio_track", titleindex, FALSE);
1097 ghb_update_ui_combo_box (ud->builder, "subtitle_lang", titleindex, FALSE);
1098 preset = ghb_settings_get_string (ud->settings, "preset");
1099 ghb_update_from_preset(ud, preset, "subtitle_lang");
1100 if (ghb_get_title_info (&tinfo, titleindex))
1102 show_title_info(ud, &tinfo);
1104 update_chapter_list (ud);
1105 adjust_audio_rate_combos(ud);
1106 set_pref_audio(titleindex, ud);
1107 if (ghb_settings_get_bool (ud->settings, "vquality_type_target"))
1109 gint bitrate = ghb_calculate_target_bitrate (ud->settings, titleindex);
1110 ghb_ui_update_int (ud, "video_bitrate", bitrate);
1113 // Unfortunately, there is no way to query how many frames were
1114 // actually generated during the scan. It attempts to make 10.
1115 // If I knew how many were generated, I would adjust the spin
1116 // control range here.
1117 ghb_ui_update_int (ud, "preview_frame", 1);
1119 set_preview_image (ud);
1123 audio_codec_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1125 static gint prev_acodec = 0;
1126 gint acodec, ivalue;
1127 GHashTable *asettings;
1129 g_debug("audio_codec_changed_cb ()\n");
1131 acodec = ghb_widget_int(widget);
1132 if (ghb_audio_is_passthru (prev_acodec) && !ghb_audio_is_passthru (acodec))
1134 // Transition from passthru to not, put some audio settings back to
1136 gint titleindex = ghb_settings_get_int(ud->settings, "title");
1137 gint track = ghb_settings_get_int(ud->settings, "audio_track");
1139 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_bitrate1");
1140 ghb_ui_update_int (ud, "audio_bitrate", ivalue);
1141 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_rate1");
1142 ghb_ui_update_int (ud, "audio_sample_rate", ivalue);
1143 ivalue = ghb_settings_get_int(ud->settings, "pref_audio_mix1");
1144 ivalue = ghb_get_best_mix(titleindex, track, acodec, ivalue);
1145 ghb_ui_update_int (ud, "audio_mix", ivalue);
1147 adjust_audio_rate_combos(ud);
1148 ghb_grey_combo_options (ud->builder);
1149 check_depencency(ud, widget);
1150 prev_acodec = acodec;
1151 asettings = get_selected_asettings(ud);
1152 if (asettings != NULL)
1154 ghb_widget_to_setting(asettings, widget);
1155 audio_list_refresh_selected(ud);
1159 static void audio_list_refresh_selected(signal_user_data_t *ud);
1160 static GHashTable* get_selected_asettings(signal_user_data_t *ud);
1163 audio_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1165 GHashTable *asettings;
1167 g_debug("audio_track_changed_cb ()\n");
1168 adjust_audio_rate_combos(ud);
1169 check_depencency(ud, widget);
1170 ghb_grey_combo_options(ud->builder);
1171 asettings = get_selected_asettings(ud);
1172 if (asettings != NULL)
1174 ghb_widget_to_setting(asettings, widget);
1175 audio_list_refresh_selected(ud);
1180 audio_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1182 GHashTable *asettings;
1184 g_debug("audio_widget_changed_cb ()\n");
1185 check_depencency(ud, widget);
1186 asettings = get_selected_asettings(ud);
1187 if (asettings != NULL)
1189 ghb_widget_to_setting(asettings, widget);
1190 audio_list_refresh_selected(ud);
1195 generic_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1197 g_debug("generic_widget_changed_cb ()\n");
1198 check_depencency(ud, widget);
1202 setting_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1204 ghb_widget_to_setting(ud->settings, widget);
1205 check_depencency(ud, widget);
1206 clear_presets_selection(ud);
1210 vfr_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1212 //const gchar *name = gtk_widget_get_name(widget);
1213 //g_debug("setting_widget_changed_cb () %s\n", name);
1214 ghb_widget_to_setting(ud->settings, widget);
1215 check_depencency(ud, widget);
1216 clear_presets_selection(ud);
1217 if (ghb_settings_get_bool(ud->settings, "variable_frame_rate"))
1219 ghb_ui_update_int(ud, "framerate", 0);
1224 mirror_cb(GtkWidget *widget, signal_user_data_t *ud)
1226 const gchar *name = gtk_widget_get_name(widget);
1227 if (name == NULL) return;
1229 g_debug("mirror_cb () %s\n", name);
1230 gchar *mirror = g_strdup(name);
1231 gchar *pos = g_strrstr(mirror, "_mirror");
1232 if (pos == NULL) return;
1234 gchar *value = ghb_widget_short_opt (widget);
1235 ghb_ui_update (ud, mirror, value);
1239 // subtitles have their differ from other settings in that
1240 // the selection is updated automaitcally when the title
1241 // changes. I don't want the preset selection changed as
1242 // would happen for regular settings.
1244 subtitle_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1246 const gchar *name = gtk_widget_get_name(widget);
1247 g_debug("subtitle_changed_cb () %s\n", name);
1248 ghb_widget_to_setting(ud->settings, widget);
1249 check_depencency(ud, widget);
1253 target_size_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1255 const gchar *name = gtk_widget_get_name(widget);
1256 g_debug("setting_widget_changed_cb () %s\n", name);
1257 ghb_widget_to_setting(ud->settings, widget);
1258 check_depencency(ud, widget);
1259 clear_presets_selection(ud);
1260 if (ghb_settings_get_bool (ud->settings, "vquality_type_target"))
1262 gint titleindex = ghb_settings_get_int(ud->settings, "title");
1263 gint bitrate = ghb_calculate_target_bitrate (ud->settings, titleindex);
1264 ghb_ui_update_int (ud, "video_bitrate", bitrate);
1269 start_chapter_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1271 const gchar *name = gtk_widget_get_name(widget);
1272 g_debug("start_chapter_changed_cb () %s\n", name);
1273 ghb_widget_to_setting(ud->settings, widget);
1274 GtkWidget *end_ch = GHB_WIDGET (ud->builder, "end_chapter");
1276 gtk_spin_button_get_range (GTK_SPIN_BUTTON(end_ch), &start, &end);
1277 start = ghb_settings_get_int(ud->settings, "start_chapter");
1278 gtk_spin_button_set_range (GTK_SPIN_BUTTON(end_ch), start, end);
1279 check_depencency(ud, widget);
1283 end_chapter_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1285 const gchar *name = gtk_widget_get_name(widget);
1286 g_debug("end_chapter_changed_cb () %s\n", name);
1287 ghb_widget_to_setting(ud->settings, widget);
1288 GtkWidget *start_ch = GHB_WIDGET (ud->builder, "start_chapter");
1290 gtk_spin_button_get_range (GTK_SPIN_BUTTON(start_ch), &start, &end);
1291 end = ghb_settings_get_int(ud->settings, "end_chapter");
1292 gtk_spin_button_set_range (GTK_SPIN_BUTTON(start_ch), start, end);
1293 check_depencency(ud, widget);
1297 scale_width_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1299 g_debug("scale_width_changed_cb ()\n");
1300 ghb_widget_to_setting(ud->settings, widget);
1301 check_depencency(ud, widget);
1302 ghb_set_scale (ud, GHB_SCALE_KEEP_WIDTH);
1303 update_preview = TRUE;
1305 gint width = ghb_settings_get_int(ud->settings, "scale_width");
1306 gint height = ghb_settings_get_int(ud->settings, "scale_height");
1307 widget = GHB_WIDGET (ud->builder, "scale_dimensions");
1308 text = g_strdup_printf ("%d x %d", width, height);
1309 gtk_label_set_text (GTK_LABEL(widget), text);
1314 scale_height_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1316 g_debug("scale_height_changed_cb ()\n");
1317 ghb_widget_to_setting(ud->settings, widget);
1318 check_depencency(ud, widget);
1319 ghb_set_scale (ud, GHB_SCALE_KEEP_HEIGHT);
1320 update_preview = TRUE;
1322 gint width = ghb_settings_get_int(ud->settings, "scale_width");
1323 gint height = ghb_settings_get_int(ud->settings, "scale_height");
1324 widget = GHB_WIDGET (ud->builder, "scale_dimensions");
1325 text = g_strdup_printf ("%d x %d", width, height);
1326 gtk_label_set_text (GTK_LABEL(widget), text);
1331 crop_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1333 gint titleindex, crop[4];
1334 ghb_title_info_t tinfo;
1336 g_debug("crop_changed_cb ()\n");
1337 ghb_widget_to_setting(ud->settings, widget);
1338 check_depencency(ud, widget);
1339 ghb_set_scale (ud, GHB_SCALE_KEEP_NONE);
1341 crop[0] = ghb_settings_get_int(ud->settings, "crop_top");
1342 crop[1] = ghb_settings_get_int(ud->settings, "crop_bottom");
1343 crop[2] = ghb_settings_get_int(ud->settings, "crop_left");
1344 crop[3] = ghb_settings_get_int(ud->settings, "crop_right");
1345 titleindex = ghb_settings_get_index(ud->settings, "title");
1346 if (ghb_get_title_info (&tinfo, titleindex))
1351 width = tinfo.width - crop[2] - crop[3];
1352 height = tinfo.height - crop[0] - crop[1];
1353 widget = GHB_WIDGET (ud->builder, "crop_dimensions");
1354 text = g_strdup_printf ("%d x %d", width, height);
1355 gtk_label_set_text (GTK_LABEL(widget), text);
1359 widget = GHB_WIDGET (ud->builder, "crop_values");
1360 text = g_strdup_printf ("%d:%d:%d:%d", crop[0], crop[1], crop[2], crop[3]);
1361 gtk_label_set_text (GTK_LABEL(widget), text);
1363 update_preview = TRUE;
1367 scale_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
1369 g_debug("scale_changed_cb ()\n");
1370 ghb_widget_to_setting(ud->settings, widget);
1371 check_depencency(ud, widget);
1372 clear_presets_selection(ud);
1373 ghb_set_scale (ud, GHB_SCALE_KEEP_NONE);
1374 update_preview = TRUE;
1378 text = ghb_settings_get_bool(ud->settings, "autocrop") ? "On" : "Off";
1379 widget = GHB_WIDGET (ud->builder, "crop_auto");
1380 gtk_label_set_text (GTK_LABEL(widget), text);
1381 text = ghb_settings_get_bool(ud->settings, "autoscale") ? "On" : "Off";
1382 widget = GHB_WIDGET (ud->builder, "scale_auto");
1383 gtk_label_set_text (GTK_LABEL(widget), text);
1384 text = ghb_settings_get_bool(ud->settings, "anamorphic") ? "On" : "Off";
1385 widget = GHB_WIDGET (ud->builder, "scale_anamorphic");
1386 gtk_label_set_text (GTK_LABEL(widget), text);
1390 generic_entry_changed_cb(GtkEntry *entry, signal_user_data_t *ud)
1392 // Normally (due to user input) I only want to process the entry
1393 // when editing is done and the focus-out signal is sent.
1394 // But... there's always a but.
1395 // If the entry is changed by software, the focus-out signal is not sent.
1396 // The changed signal is sent ... so here we are.
1397 // I don't want to process upon every keystroke, so I prevent processing
1398 // while the widget has focus.
1399 g_debug("generic_entry_changed_cb ()\n");
1400 if (!GTK_WIDGET_HAS_FOCUS((GtkWidget*)entry))
1402 ghb_widget_to_setting(ud->settings, (GtkWidget*)entry);
1407 generic_focus_out_cb(GtkWidget *widget, GdkEventFocus *event,
1408 signal_user_data_t *ud)
1410 g_debug("generic_focus_out_cb ()\n");
1411 ghb_widget_to_setting(ud->settings, widget);
1416 clear_audio_list(signal_user_data_t *ud)
1418 GtkTreeView *treeview;
1419 GtkListStore *store;
1422 g_debug("clear_audio_list ()\n");
1423 while (ud->audio_settings != NULL)
1425 link = ud->audio_settings;
1426 ud->audio_settings = g_slist_remove_link(ud->audio_settings, link);
1427 g_hash_table_destroy((GHashTable*)link->data);
1428 g_slist_free_1(link);
1430 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
1431 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
1432 gtk_list_store_clear (store);
1436 add_to_audio_list(signal_user_data_t *ud, GHashTable *settings)
1438 GtkTreeView *treeview;
1440 GtkListStore *store;
1441 GtkTreeSelection *selection;
1443 g_debug("add_to_audio_list ()\n");
1444 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
1445 selection = gtk_tree_view_get_selection (treeview);
1446 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
1448 gtk_list_store_append(store, &iter);
1449 gtk_list_store_set(store, &iter,
1450 // These are displayed in list
1451 0, ghb_settings_get_option(settings, "audio_track"),
1452 1, ghb_settings_get_option(settings, "audio_codec"),
1453 2, ghb_settings_get_option(settings, "audio_bitrate"),
1454 3, ghb_settings_get_option(settings, "audio_sample_rate"),
1455 4, ghb_settings_get_option(settings, "audio_mix"),
1456 // These are used to set combo box values when a list item is selected
1457 5, ghb_settings_get_string(settings, "audio_drc"),
1458 6, ghb_settings_get_short_opt(settings, "audio_track"),
1459 7, ghb_settings_get_short_opt(settings, "audio_codec"),
1460 8, ghb_settings_get_short_opt(settings, "audio_bitrate"),
1461 9, ghb_settings_get_short_opt(settings, "audio_sample_rate"),
1462 10, ghb_settings_get_short_opt(settings, "audio_mix"),
1464 gtk_tree_selection_select_iter(selection, &iter);
1468 audio_list_refresh_selected(signal_user_data_t *ud)
1470 GtkTreeView *treeview;
1471 GtkTreePath *treepath;
1472 GtkTreeSelection *selection;
1473 GtkTreeModel *store;
1478 GHashTable *asettings = NULL;
1480 g_debug("get_selected_asettings ()\n");
1481 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
1482 selection = gtk_tree_view_get_selection (treeview);
1483 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1485 // Get the row number
1486 treepath = gtk_tree_model_get_path (store, &iter);
1487 indices = gtk_tree_path_get_indices (treepath);
1490 // find audio settings
1491 if (row < 0) return;
1492 link = g_slist_nth(ud->audio_settings, row);
1493 if (link == NULL) return;
1494 asettings = (GHashTable*)link->data;
1495 gtk_list_store_set(GTK_LIST_STORE(store), &iter,
1496 // These are displayed in list
1497 0, ghb_settings_get_option(asettings, "audio_track"),
1498 1, ghb_settings_get_option(asettings, "audio_codec"),
1499 2, ghb_settings_get_option(asettings, "audio_bitrate"),
1500 3, ghb_settings_get_option(asettings, "audio_sample_rate"),
1501 4, ghb_settings_get_option(asettings, "audio_mix"),
1502 // These are used to set combo box values when a list item is selected
1503 5, ghb_settings_get_string(asettings, "audio_drc"),
1504 6, ghb_settings_get_short_opt(asettings, "audio_track"),
1505 7, ghb_settings_get_short_opt(asettings, "audio_codec"),
1506 8, ghb_settings_get_short_opt(asettings, "audio_bitrate"),
1507 9, ghb_settings_get_short_opt(asettings, "audio_sample_rate"),
1508 10, ghb_settings_get_short_opt(asettings, "audio_mix"),
1514 get_selected_asettings(signal_user_data_t *ud)
1516 GtkTreeView *treeview;
1517 GtkTreePath *treepath;
1518 GtkTreeSelection *selection;
1519 GtkTreeModel *store;
1524 GHashTable *asettings = NULL;
1526 g_debug("get_selected_asettings ()\n");
1527 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
1528 selection = gtk_tree_view_get_selection (treeview);
1529 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1531 // Get the row number
1532 treepath = gtk_tree_model_get_path (store, &iter);
1533 indices = gtk_tree_path_get_indices (treepath);
1536 // find audio settings
1537 if (row < 0) return NULL;
1538 link = g_slist_nth(ud->audio_settings, row);
1539 if (link == NULL) return NULL;
1540 asettings = (GHashTable*)link->data;
1546 audio_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
1548 GtkTreeModel *store;
1552 g_debug("audio_list_selection_changed_cb ()\n");
1553 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1555 const gchar *track, *codec, *bitrate, *sample_rate, *mix, *drc;
1556 gtk_tree_model_get(store, &iter,
1564 ghb_ui_update(ud, "audio_track", track);
1565 ghb_ui_update(ud, "audio_codec", codec);
1566 ghb_ui_update(ud, "audio_bitrate", bitrate);
1567 ghb_ui_update(ud, "audio_sample_rate", sample_rate);
1568 ghb_ui_update(ud, "audio_mix", mix);
1569 ghb_ui_update(ud, "audio_drc", drc);
1570 widget = GHB_WIDGET (ud->builder, "audio_remove");
1571 gtk_widget_set_sensitive(widget, TRUE);
1572 //widget = GHB_WIDGET (ud->builder, "audio_update");
1573 //gtk_widget_set_sensitive(widget, TRUE);
1577 widget = GHB_WIDGET (ud->builder, "audio_remove");
1578 gtk_widget_set_sensitive(widget, FALSE);
1579 //widget = GHB_WIDGET (ud->builder, "audio_update");
1580 //gtk_widget_set_sensitive(widget, FALSE);
1585 audio_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
1587 // Add the current audio settings to the list.
1588 GHashTable *asettings;
1592 g_debug("audio_add_clicked_cb ()\n");
1593 // Only allow up to 8 audio entries
1594 asettings = ghb_settings_new();
1595 widget = GHB_WIDGET(ud->builder, "audio_track");
1596 ghb_settings_set(asettings, "audio_track", ghb_widget_value(widget));
1597 widget = GHB_WIDGET(ud->builder, "audio_codec");
1598 ghb_settings_set(asettings, "audio_codec", ghb_widget_value(widget));
1599 widget = GHB_WIDGET(ud->builder, "audio_bitrate");
1600 ghb_settings_set(asettings, "audio_bitrate", ghb_widget_value(widget));
1601 widget = GHB_WIDGET(ud->builder, "audio_sample_rate");
1602 ghb_settings_set(asettings, "audio_sample_rate", ghb_widget_value(widget));
1603 widget = GHB_WIDGET(ud->builder, "audio_mix");
1604 ghb_settings_set(asettings, "audio_mix", ghb_widget_value(widget));
1605 widget = GHB_WIDGET(ud->builder, "audio_drc");
1606 ghb_settings_set(asettings, "audio_drc", ghb_widget_value(widget));
1608 ud->audio_settings = g_slist_append(ud->audio_settings, asettings);
1609 add_to_audio_list(ud, asettings);
1610 count = g_slist_length(ud->audio_settings);
1613 gtk_widget_set_sensitive(xwidget, FALSE);
1618 audio_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
1620 GtkTreeView *treeview;
1621 GtkTreePath *treepath;
1622 GtkTreeSelection *selection;
1623 GtkTreeModel *store;
1624 GtkTreeIter iter, nextIter;
1629 g_debug("audio_remove_clicked_cb ()\n");
1630 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
1631 selection = gtk_tree_view_get_selection (treeview);
1632 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1635 if (!gtk_tree_model_iter_next(store, &nextIter))
1638 if (gtk_tree_model_get_iter_first(store, &nextIter))
1640 gtk_tree_selection_select_iter (selection, &nextIter);
1645 gtk_tree_selection_select_iter (selection, &nextIter);
1647 // Get the row number
1648 treepath = gtk_tree_model_get_path (store, &iter);
1649 indices = gtk_tree_path_get_indices (treepath);
1652 // Remove the selected item
1653 gtk_list_store_remove (GTK_LIST_STORE(store), &iter);
1654 // remove from audio settings list
1655 if (row < 0) return;
1656 link = g_slist_nth(ud->audio_settings, row);
1657 if (link == NULL) return;
1658 ud->audio_settings = g_slist_remove_link(ud->audio_settings, link);
1659 g_hash_table_destroy((GHashTable*)link->data);
1660 g_slist_free_1(link);
1661 widget = GHB_WIDGET (ud->builder, "audio_add");
1662 gtk_widget_set_sensitive(widget, TRUE);
1667 audio_list_refresh(signal_user_data_t *ud)
1669 GtkTreeView *treeview;
1671 GtkListStore *store;
1674 g_debug("audio_list_refresh ()\n");
1675 GSList *link = ud->audio_settings;
1676 if (link == NULL) return;
1677 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
1678 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
1679 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
1683 GHashTable *asettings;
1685 asettings = (GHashTable*)link->data;
1686 gtk_list_store_set(GTK_LIST_STORE(store), &iter,
1687 // These are displayed in list
1688 0, ghb_settings_get_option(asettings, "audio_track"),
1689 1, ghb_settings_get_option(asettings, "audio_codec"),
1690 2, ghb_settings_get_option(asettings, "audio_bitrate"),
1691 3, ghb_settings_get_option(asettings, "audio_sample_rate"),
1692 4, ghb_settings_get_option(asettings, "audio_mix"),
1693 // These are used to set combo box values when a list item is selected
1694 5, ghb_settings_get_string(asettings, "audio_drc"),
1695 6, ghb_settings_get_short_opt(asettings, "audio_track"),
1696 7, ghb_settings_get_short_opt(asettings, "audio_codec"),
1697 8, ghb_settings_get_short_opt(asettings, "audio_bitrate"),
1698 9, ghb_settings_get_short_opt(asettings, "audio_sample_rate"),
1699 10, ghb_settings_get_short_opt(asettings, "audio_mix"),
1701 done = !gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1703 } while (!done && link);
1708 ghb_presets_list_update(signal_user_data_t *ud)
1710 GtkTreeView *treeview;
1712 GtkListStore *store;
1717 gchar **descriptions;
1718 gint flags, custom, def;
1720 g_debug("ghb_presets_list_update ()\n");
1721 presets = ghb_presets_get_names();
1722 descriptions = ghb_presets_get_descriptions();
1723 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
1724 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
1725 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
1729 if ((presets != NULL) && (presets[ii] != NULL))
1731 // Update row with settings data
1732 g_debug("Updating row\n");
1733 flags = ghb_preset_flags(presets[ii], &index);
1734 def = flags & PRESET_DEFAULT;
1735 custom = flags & PRESET_CUSTOM;
1736 gtk_list_store_set(store, &iter,
1740 3, custom ? "black" : "blue",
1741 4, descriptions[ii],
1744 done = !gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1748 // No more settings data, remove row
1749 g_debug("Removing row\n");
1750 done = !gtk_list_store_remove(store, &iter);
1754 while ((presets != NULL) && (presets[ii] != NULL))
1756 // Additional settings, add row
1757 g_debug("Adding row %s\n", presets[ii]);
1758 gtk_list_store_append(store, &iter);
1759 flags = ghb_preset_flags(presets[ii], &index);
1760 def = flags & PRESET_DEFAULT;
1761 custom = flags & PRESET_CUSTOM;
1762 gtk_list_store_set(store, &iter, 0, presets[ii],
1765 3, custom ? "black" : "blue",
1766 4, descriptions[ii],
1770 g_strfreev (presets);
1774 ghb_select_preset(GtkBuilder *builder, const gchar *preset)
1776 GtkTreeView *treeview;
1777 GtkTreeSelection *selection;
1778 GtkTreeModel *store;
1783 g_debug("select_preset()\n");
1784 if (preset == NULL) return;
1785 treeview = GTK_TREE_VIEW(GHB_WIDGET(builder, "presets_list"));
1786 selection = gtk_tree_view_get_selection (treeview);
1787 store = gtk_tree_view_get_model (treeview);
1788 if (gtk_tree_model_get_iter_first(store, &iter))
1792 gtk_tree_model_get(store, &iter, 0, &tpreset, -1);
1793 if (strcmp(preset, tpreset) == 0)
1795 gtk_tree_selection_select_iter (selection, &iter);
1798 done = !gtk_tree_model_iter_next(store, &iter);
1804 presets_save_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
1809 GtkResponseType response;
1810 const gchar *preset = "";
1812 g_debug("presets_save_clicked_cb ()\n");
1813 preset = ghb_settings_get_string (ud->settings, "preset");
1814 // Clear the description
1815 desc = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "preset_description"));
1816 //gtk_entry_set_text(desc, "");
1817 dialog = GHB_WIDGET(ud->builder, "preset_save_dialog");
1818 entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "preset_name"));
1819 gtk_entry_set_text(entry, preset);
1820 response = gtk_dialog_run(GTK_DIALOG(dialog));
1821 gtk_widget_hide(dialog);
1822 if (response == GTK_RESPONSE_OK)
1825 const gchar *name = gtk_entry_get_text(entry);
1826 g_debug("description to settings\n");
1827 ghb_widget_to_setting(ud->settings, GTK_WIDGET(desc));
1828 ghb_settings_save(ud, name);
1829 ghb_presets_list_update(ud);
1830 // Make the new preset the selected item
1831 ghb_select_preset(ud->builder, name);
1836 presets_remove_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
1838 GtkTreeView *treeview;
1839 GtkTreeSelection *selection;
1840 GtkTreeModel *store;
1843 GtkResponseType response;
1845 g_debug("presets_remove_clicked_cb ()\n");
1846 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
1847 selection = gtk_tree_view_get_selection (treeview);
1848 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1852 gtk_tree_model_get(store, &iter, 0, &preset, -1);
1853 if (!ghb_presets_is_standard(preset))
1855 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
1856 GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
1857 "Confirm deletion of preset %s.", preset);
1858 response = gtk_dialog_run(GTK_DIALOG(dialog));
1859 gtk_widget_destroy (dialog);
1860 if (response == GTK_RESPONSE_YES)
1862 GtkTreeIter nextIter = iter;
1863 gchar *nextPreset = NULL;
1864 if (!gtk_tree_model_iter_next(store, &nextIter))
1866 if (gtk_tree_model_get_iter_first(store, &nextIter))
1868 gtk_tree_model_get(store, &nextIter, 0, &nextPreset, -1);
1873 gtk_tree_model_get(store, &nextIter, 0, &nextPreset, -1);
1875 // Remove the selected item
1876 // First unselect it so that selecting the new item works properly
1877 gtk_tree_selection_unselect_iter (selection, &iter);
1878 ghb_presets_remove(ud->settings, preset);
1879 ghb_presets_list_update(ud);
1880 ghb_select_preset(ud->builder, nextPreset);
1885 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
1886 GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
1887 "Can not delete standard preset %s.", preset);
1888 response = gtk_dialog_run(GTK_DIALOG(dialog));
1889 gtk_widget_destroy (dialog);
1895 preset_update_title_deps(signal_user_data_t *ud, ghb_title_info_t *tinfo)
1899 ghb_ui_update_int (ud, "scale_width", tinfo->width - tinfo->crop[2] - tinfo->crop[3]);
1900 // If anamorphic or keep_aspect, the hight will be automatically calculated
1901 gboolean keep_aspect = ghb_settings_get_bool(ud->settings, "keep_aspect");
1902 gboolean anamorphic = ghb_settings_get_bool(ud->settings, "anamorphic");
1903 if (!(keep_aspect || anamorphic))
1904 ghb_ui_update_int (ud, "scale_height", tinfo->height - tinfo->crop[0] - tinfo->crop[1]);
1906 // Set the limits of cropping. hb_set_anamorphic_size crashes if
1907 // you pass it a cropped width or height == 0.
1909 bound = tinfo->height / 2 - 2;
1910 widget = GHB_WIDGET (ud->builder, "crop_top");
1911 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
1912 widget = GHB_WIDGET (ud->builder, "crop_bottom");
1913 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
1914 bound = tinfo->width / 2 - 2;
1915 widget = GHB_WIDGET (ud->builder, "crop_left");
1916 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
1917 widget = GHB_WIDGET (ud->builder, "crop_right");
1918 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
1919 if (ghb_settings_get_bool (ud->settings, "autocrop"))
1921 ghb_ui_update_int (ud, "crop_top", tinfo->crop[0]);
1922 ghb_ui_update_int (ud, "crop_bottom", tinfo->crop[1]);
1923 ghb_ui_update_int (ud, "crop_left", tinfo->crop[2]);
1924 ghb_ui_update_int (ud, "crop_right", tinfo->crop[3]);
1929 presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
1931 GtkTreeModel *store;
1935 gboolean sensitive = FALSE;
1936 ghb_title_info_t tinfo;
1938 g_debug("presets_list_selection_changed_cb ()\n");
1939 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1941 gtk_tree_model_get(store, &iter, 0, &preset, -1);
1942 if (!ghb_presets_is_standard(preset))
1946 ud->dont_clear_presets = TRUE;
1947 ghb_set_preset(ud, preset);
1948 gint titleindex = ghb_settings_get_int(ud->settings, "title");
1949 set_pref_audio(titleindex, ud);
1950 ud->dont_clear_presets = FALSE;
1951 if (ghb_get_title_info (&tinfo, titleindex))
1953 preset_update_title_deps(ud, &tinfo);
1955 ghb_set_scale (ud, GHB_SCALE_KEEP_NONE);
1959 g_debug("No selection??? Perhaps unselected.\n");
1961 widget = GHB_WIDGET (ud->builder, "presets_remove");
1962 gtk_widget_set_sensitive(widget, sensitive);
1966 queue_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
1968 GtkTreeModel *store;
1969 GtkTreeIter iter, piter;
1971 g_debug("queue_list_selection_changed_cb ()\n");
1972 // A queue entry is made up of a parent and multiple
1973 // children that are visible when expanded. When and entry
1974 // is selected, I want the parent to be selected.
1975 // This is purely cosmetic.
1976 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1978 if (gtk_tree_model_iter_parent (store, &piter, &iter))
1981 GtkTreeView *treeview;
1983 gtk_tree_selection_select_iter (selection, &piter);
1984 path = gtk_tree_model_get_path (store, &piter);
1985 treeview = gtk_tree_selection_get_tree_view (selection);
1986 // Make the parent visible in scroll window if it is not.
1987 gtk_tree_view_scroll_to_cell (treeview, path, NULL, FALSE, 0, 0);
1994 add_to_queue_list(signal_user_data_t *ud, job_settings_t *item)
1996 GtkTreeView *treeview;
1998 GtkTreeStore *store;
2004 g_debug("update_queue_list ()\n");
2005 if (item == NULL) return;
2006 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
2007 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
2009 gint title = ghb_settings_get_int(item->settings, "title");
2010 gint start_chapter = ghb_settings_get_int(item->settings, "start_chapter");
2011 gint end_chapter = ghb_settings_get_int(item->settings, "end_chapter");
2012 gboolean pass2 = ghb_settings_get_bool(item->settings, "two_pass");
2013 const gchar *vol_name = ghb_settings_get_string(item->settings, "volume_label");
2014 if (vol_name == NULL)
2015 vol_name = "No Title";
2016 info = g_strdup_printf
2018 "<big><b>%s</b></big> (Title %d, Chapters %d through %d, %d Video %s)",
2019 vol_name, title+1, start_chapter, end_chapter,
2020 pass2 ? 2:1, pass2 ? "Passes":"Pass");
2022 gtk_tree_store_append(store, &iter, NULL);
2023 gtk_tree_store_set(store, &iter, 0, "hb-queue-job", 1, info, 2, "hb-queue-delete", -1);
2026 const gchar *vcodec = ghb_settings_get_option(item->settings, "video_codec");
2027 const gchar *container = ghb_settings_get_option(item->settings, "container");
2028 const gchar *acodec = ghb_settings_get_option(item->settings, "audio_codec");
2029 const gchar *dest = ghb_settings_get_string(item->settings, "destination");
2030 const gchar *preset = ghb_settings_get_string(item->settings, "preset");
2031 info = g_strdup_printf
2033 "<b>Preset:</b> %s\n"
2034 "<b>Format:</b> %s Container, %s Video + %s Audio\n"
2035 "<b>Destination:</b> %s",
2036 preset, container, vcodec, acodec, dest);
2038 gtk_tree_store_append(store, &citer, &iter);
2039 gtk_tree_store_set(store, &citer, 1, info, -1);
2042 gint width = ghb_settings_get_int(item->settings, "scale_width");
2043 gint height = ghb_settings_get_int(item->settings, "scale_height");
2044 gboolean anamorphic = ghb_settings_get_bool(item->settings, "anamorphic");
2045 gboolean round_dim = ghb_settings_get_bool(item->settings, "round_dimensions");
2046 gboolean keep_aspect = ghb_settings_get_bool(item->settings, "keep_aspect");
2052 aspect_desc = "(Anamorphic)";
2056 aspect_desc = "(Strict Anamorphic)";
2063 aspect_desc = "(Aspect Preserved)";
2067 aspect_desc = "(Aspect Lost)";
2070 gboolean vqtype = ghb_settings_get_bool(item->settings, "vquality_type_constant");
2072 gchar *vq_desc = "Error";
2075 vqtype = ghb_settings_get_bool(item->settings, "vquality_type_target");
2078 // Has to be bitrate
2079 vqvalue = ghb_settings_get_int(item->settings, "video_bitrate");
2085 vqvalue = ghb_settings_get_int(item->settings, "video_target");
2092 vqvalue = ghb_settings_get_int(item->settings, "video_quality");
2093 vq_desc = "% Constant Quality";
2095 const gchar *fps = ghb_settings_get_string(item->settings, "framerate");
2096 const gchar *vcodec_abbr = ghb_settings_get_short_opt(item->settings, "video_codec");
2098 if (strcmp(vcodec_abbr, "x264") == 0)
2100 gchar *x264opts = ghb_build_x264opts_string(item->settings);
2101 g_debug("xopts (%s)\n", x264opts);
2102 extra_opts = g_strdup_printf ("\n<b>x264 Options:</b> %s", x264opts);
2107 extra_opts = g_strdup("");
2109 gboolean turbo = ghb_settings_get_bool (item->settings, "turbo");
2110 gchar *turbo_desc = "\n<b>Turbo:</b> Off";;
2113 turbo_desc = "\n<b>Turbo:</b> On";
2115 num_pass = pass2 ? 2 : 1;
2116 for (ii = 0; ii < num_pass; ii++)
2118 gboolean final = (ii == (num_pass - 1));
2119 GString *pass = g_string_new("");
2120 g_string_append_printf( pass,
2122 "<b>Picture:</b> %d x %d %s\n"
2123 "<b>Video:</b> %s, %d %s, %s fps"
2125 ii ? "2nd":"1st", width, height, aspect_desc,
2126 vcodec, vqvalue, vq_desc, fps,
2127 final ? extra_opts : turbo_desc);
2132 GSList *link = item->audio_settings;
2135 GHashTable *asettings = (GHashTable*)link->data;
2136 const gchar *acodec = ghb_settings_get_option(asettings, "audio_codec");
2137 const gchar *bitrate = ghb_settings_get_string(asettings, "audio_bitrate");
2138 const gchar *samplerate = ghb_settings_get_string(asettings, "audio_sample_rate");
2139 gint track = ghb_settings_get_int(asettings, "audio_track");
2140 const gchar *mix = ghb_settings_get_option(asettings, "audio_mix");
2141 g_string_append_printf(pass,
2142 "\n<b>Audio:</b> %s, %s kbps, %s kHz, Track %d: %s",
2143 acodec, bitrate, samplerate, track+1, mix);
2147 info = g_string_free(pass, FALSE);
2148 gtk_tree_store_append(store, &citer, &iter);
2149 gtk_tree_store_set(store, &citer, 0, ii ? "hb-queue-pass2" : "hb-queue-pass1", 1, info, -1);
2156 ghb_message_dialog(GtkMessageType type, const gchar *message, const gchar *no, const gchar *yes)
2159 GtkResponseType response;
2161 // Toss up a warning dialog
2162 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
2163 type, GTK_BUTTONS_NONE,
2165 gtk_dialog_add_buttons( GTK_DIALOG(dialog),
2166 no, GTK_RESPONSE_NO,
2167 yes, GTK_RESPONSE_YES, NULL);
2168 response = gtk_dialog_run(GTK_DIALOG(dialog));
2169 gtk_widget_destroy (dialog);
2170 if (response == GTK_RESPONSE_NO)
2178 estimate_file_size(signal_user_data_t *ud)
2180 ghb_title_info_t tinfo;
2184 gint titleindex = ghb_settings_get_int(ud->settings, "title");
2185 if (titleindex < 0) return 0;
2187 if (!ghb_get_title_info(&tinfo, titleindex)) return 0;
2188 duration = ((tinfo.hours*60)+tinfo.minutes)*60+tinfo.seconds;
2189 bitrate = ghb_guess_bitrate(ud->settings);
2190 size = (gint64)duration * (gint64)bitrate/8;
2194 #define DISK_FREE_THRESH (1024L*1024L*1024L*3)
2197 validate_settings(signal_user_data_t *ud)
2199 // Check to see if the dest file exists or is
2200 // already in the queue
2202 gint titleindex = ghb_settings_get_int(ud->settings, "title");
2203 if (titleindex < 0) return FALSE;
2204 const gchar *dest = ghb_settings_get_string(ud->settings, "destination");
2205 GSList *link = ud->queue;
2206 while (link != NULL)
2208 job_settings_t *item;
2209 const gchar *filename;
2210 item = (job_settings_t*)link->data;
2211 filename = ghb_settings_get_string(item->settings, "destination");
2212 if (strcmp(dest, filename) == 0)
2214 message = g_strdup_printf(
2215 "Destination: %s\n\n"
2216 "Another queued job has specified the same destination.\n"
2217 "Do you want to overwrite?",
2219 if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message, "Cancel", "Overwrite"))
2229 gchar *destdir = g_path_get_dirname(dest);
2230 if (!g_file_test(destdir, G_FILE_TEST_IS_DIR))
2232 message = g_strdup_printf(
2233 "Destination: %s\n\n"
2234 "This is not a valid directory.",
2236 ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
2241 if (g_access(destdir, R_OK|W_OK) != 0)
2243 message = g_strdup_printf(
2244 "Destination: %s\n\n"
2245 "Can not read or write the directory.",
2247 ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
2255 gchar *resolved = ghb_resolve_symlink(destdir);
2257 gfile = g_file_new_for_path(resolved);
2258 info = g_file_query_filesystem_info(gfile,
2259 G_FILE_ATTRIBUTE_FILESYSTEM_FREE, NULL, NULL);
2262 if (g_file_info_has_attribute(info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE))
2264 size = g_file_info_get_attribute_uint64(info,
2265 G_FILE_ATTRIBUTE_FILESYSTEM_FREE);
2267 gint64 fsize = estimate_file_size(ud);
2270 message = g_strdup_printf(
2271 "Destination filesystem is almost full: %uM free\n\n"
2272 "Encode may be incomplete if you proceed.\n",
2273 (guint)(size / (1024L*1024L)));
2274 if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message, "Cancel", "Proceed"))
2282 g_object_unref(info);
2284 g_object_unref(gfile);
2287 if (g_file_test(dest, G_FILE_TEST_EXISTS))
2289 message = g_strdup_printf(
2290 "Destination: %s\n\n"
2291 "File already exhists.\n"
2292 "Do you want to overwrite?",
2294 if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message, "Cancel", "Overwrite"))
2302 // Validate video quality is in a reasonable range
2303 if (!ghb_validate_vquality(ud->settings))
2307 // Validate audio settings
2308 if (!ghb_validate_audio(ud))
2312 // Validate video settings
2313 if (!ghb_validate_video(ud))
2317 audio_list_refresh(ud);
2322 queue_add(signal_user_data_t *ud)
2324 // Add settings to the queue
2325 job_settings_t *queue_item;
2327 static gint unique_id = 0;
2329 g_debug("queue_add ()\n");
2330 if (!validate_settings(ud))
2334 // Make a copy of current settings to be used for the new job
2335 queue_item = g_malloc(sizeof(job_settings_t));
2336 queue_item->settings = ghb_settings_dup(ud->settings);
2337 queue_item->audio_settings = NULL;
2338 link = ud->audio_settings;
2339 while (link != NULL)
2341 GHashTable *asettings;
2342 asettings = ghb_settings_dup((GHashTable*)link->data);
2343 queue_item->audio_settings =
2344 g_slist_append(queue_item->audio_settings, asettings);
2345 link = g_slist_next(link);
2347 queue_item->chapter_list = g_strdupv(ud->chapter_list);
2348 ud->queue = g_slist_append(ud->queue, queue_item);
2349 add_to_queue_list(ud, queue_item);
2350 ghb_add_job (queue_item, unique_id);
2351 queue_item->unique_id = unique_id;
2352 queue_item->status = GHB_QUEUE_PENDING;
2358 queue_add_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
2360 g_debug("queue_add_clicked_cb ()\n");
2365 cancel_encode(const gchar *extra_msg)
2368 GtkResponseType response;
2370 if (extra_msg == NULL) extra_msg = "";
2371 // Toss up a warning dialog
2372 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
2373 GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE,
2374 "%sYour movie will be lost if you don't continue encoding.",
2376 gtk_dialog_add_buttons( GTK_DIALOG(dialog),
2377 "Continue Encoding", GTK_RESPONSE_NO,
2378 "Stop Encoding", GTK_RESPONSE_YES, NULL);
2379 response = gtk_dialog_run(GTK_DIALOG(dialog));
2380 gtk_widget_destroy (dialog);
2381 if (response == GTK_RESPONSE_NO) return FALSE;
2387 queue_remove_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud)
2389 GtkTreeView *treeview;
2390 GtkTreePath *treepath;
2391 GtkTreeModel *store;
2396 job_settings_t *queue_item;
2399 g_debug("queue_remove_clicked_cb ()\n");
2400 g_debug("ud %p\n", ud);
2401 g_debug("ud->builder %p\n", ud->builder);
2403 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
2404 store = gtk_tree_view_get_model(treeview);
2405 treepath = gtk_tree_path_new_from_string (path);
2406 if (gtk_tree_model_get_iter(store, &iter, treepath))
2408 // Find the entry in the queue
2409 indices = gtk_tree_path_get_indices (treepath);
2411 // Can only free the treepath After getting what I need from
2412 // indices since this points into treepath somewhere.
2413 gtk_tree_path_free (treepath);
2414 if (row < 0) return;
2415 link = g_slist_nth(ud->queue, row);
2416 if (link == NULL) return;
2417 queue_item = (job_settings_t*)link->data;
2418 if (queue_item->status == GHB_QUEUE_RUNNING)
2420 // Ask if wants to stop encode.
2421 if (!cancel_encode(NULL))
2426 // Remove the selected item
2427 g_debug(" should be removing from treestore\n");
2428 gtk_tree_store_remove(GTK_TREE_STORE(store), &iter);
2429 // Remove the corresponding item from the queue list
2430 ud->queue = g_slist_remove_link(ud->queue, link);
2431 g_slist_free_1(link);
2432 g_hash_table_destroy(queue_item->settings);
2433 link = queue_item->audio_settings;
2434 while (link != NULL)
2437 g_hash_table_destroy((GHashTable*)link->data);
2438 nextlink = g_slist_next(link);
2439 g_slist_free_1(link);
2442 g_strfreev (queue_item->chapter_list);
2443 unique_id = queue_item->unique_id;
2445 ghb_remove_job(unique_id);
2449 gtk_tree_path_free (treepath);
2454 find_queue_item(GSList *queue, gint unique_id, job_settings_t **job)
2459 while (queue != NULL)
2462 js = (job_settings_t*)queue->data;
2463 if (js->unique_id == unique_id)
2468 queue = queue->next;
2475 queue_buttons_grey(signal_user_data_t *ud, gboolean working)
2479 gint titleindex = ghb_settings_get_int(ud->settings, "title");
2480 gboolean title_ok = (titleindex >= 0);
2481 widget = GHB_WIDGET (ud->builder, "queue_start1");
2482 gtk_widget_set_sensitive (widget, !working && title_ok);
2483 widget = GHB_WIDGET (ud->builder, "queue_start2");
2484 gtk_widget_set_sensitive (widget, !working && title_ok);
2485 action = GHB_ACTION (ud->builder, "queue_start_menu");
2486 gtk_action_set_sensitive (action, !working && title_ok);
2487 widget = GHB_WIDGET (ud->builder, "queue_pause1");
2488 gtk_widget_set_sensitive (widget, working);
2489 widget = GHB_WIDGET (ud->builder, "queue_pause2");
2490 gtk_widget_set_sensitive (widget, working);
2491 action = GHB_ACTION (ud->builder, "queue_pause_menu");
2492 gtk_action_set_sensitive (action, working);
2493 widget = GHB_WIDGET (ud->builder, "queue_stop");
2494 gtk_widget_set_sensitive (widget, working);
2495 action = GHB_ACTION (ud->builder, "queue_stop_menu");
2496 gtk_action_set_sensitive (action, working);
2499 void queue_start_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud);
2501 static gint autostart_timeout = -1;
2504 autostart_timer_cb(gpointer data)
2507 GtkProgressBar *progress;
2508 signal_user_data_t *ud = (signal_user_data_t*)data;
2510 if (autostart_timeout < 0) return FALSE;
2511 gchar *remaining = g_strdup_printf("Encoding will start in %d second%c",
2512 (autostart_timeout-1) / 40 + 1, autostart_timeout <= 40 ? ' ':'s');
2513 progress = GTK_PROGRESS_BAR(GHB_WIDGET (ud->builder, "autostart_countdown"));
2514 gtk_progress_bar_set_fraction (progress, (gdouble)autostart_timeout / 800);
2515 gtk_progress_bar_set_text(progress, remaining);
2517 autostart_timeout--;
2518 if (autostart_timeout == 0)
2520 widget = GHB_WIDGET(ud->builder, "autostart_dialog");
2521 gtk_widget_hide(widget);
2522 queue_start_clicked_cb(NULL, ud);
2529 ghb_timer_cb(gpointer data)
2531 static gint ticks = 0;
2535 static gint current_id = -1;
2537 GtkTreeView *treeview;
2538 GtkTreeStore *store;
2540 static gint working = 0;
2541 static gboolean work_started = FALSE;
2543 signal_user_data_t *ud = (signal_user_data_t*)data;
2544 switch (ghb_backend_events (ud, &unique_id))
2546 case GHB_EVENT_WORKING:
2550 work_started = TRUE;
2551 queue_buttons_grey(ud, TRUE);
2553 if (unique_id != current_id)
2555 index = find_queue_item(ud->queue, current_id, &js);
2558 js->status = GHB_QUEUE_DONE;
2559 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
2560 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
2561 gchar *path = g_strdup_printf ("%d", index);
2562 if (gtk_tree_model_get_iter_from_string ( GTK_TREE_MODEL(store), &iter, path))
2564 gtk_tree_store_set(store, &iter, 0, "hb-complete", -1);
2569 index = find_queue_item(ud->queue, unique_id, &js);
2572 js->status = GHB_QUEUE_RUNNING;
2573 current_id = unique_id;
2576 index = find_queue_item(ud->queue, unique_id, &js);
2579 gchar working_icon[] = "hb-working0";
2580 working_icon[10] = '0' + working;
2581 working = (working+1) % 6;
2582 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
2583 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
2584 gchar *path = g_strdup_printf ("%d", index);
2585 if (gtk_tree_model_get_iter_from_string ( GTK_TREE_MODEL(store), &iter, path))
2587 gtk_tree_store_set(store, &iter, 0, working_icon, -1);
2592 case GHB_EVENT_PAUSED:
2595 case GHB_EVENT_WORK_DONE:
2597 ud->state &= ~GHB_STATE_WORKING;
2598 work_started = FALSE;
2599 queue_buttons_grey(ud, FALSE);
2600 index = find_queue_item(ud->queue, current_id, &js);
2603 js->status = GHB_QUEUE_DONE;
2604 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
2605 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
2606 gchar *path = g_strdup_printf ("%d", index);
2607 if (gtk_tree_model_get_iter_from_string ( GTK_TREE_MODEL(store), &iter, path))
2609 gtk_tree_store_set(store, &iter, 0, "hb-complete", -1);
2619 case GHB_EVENT_WORK_CANCELED:
2621 work_started = FALSE;
2622 queue_buttons_grey(ud, FALSE);
2623 index = find_queue_item(ud->queue, current_id, &js);
2626 js->status = GHB_QUEUE_CANCELED;
2627 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
2628 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
2629 gchar *path = g_strdup_printf ("%d", index);
2630 if (gtk_tree_model_get_iter_from_string ( GTK_TREE_MODEL(store), &iter, path))
2632 gtk_tree_store_set(store, &iter, 0, "hb-canceled", -1);
2638 case GHB_EVENT_SCAN_DONE:
2640 ghb_title_info_t tinfo;
2642 ud->state &= ~GHB_STATE_SCANNING;
2643 ghb_update_ui_combo_box(ud->builder, "title", 0, FALSE);
2644 titleindex = ghb_longest_title();
2645 ghb_ui_update_int(ud, "title", titleindex);
2646 queue_buttons_grey(ud, FALSE);
2648 // Are there really any titles.
2649 if (ghb_get_title_info(&tinfo, titleindex))
2655 gint title = ghb_settings_get_int(ud->settings, "title");
2656 gint start_chapter = ghb_settings_get_int(ud->settings, "start_chapter");
2657 gint end_chapter = ghb_settings_get_int(ud->settings, "end_chapter");
2658 gboolean pass2 = ghb_settings_get_bool(ud->settings, "two_pass");
2659 const gchar *vol_name = ghb_settings_get_string(ud->settings, "volume_label");
2660 if (vol_name == NULL)
2661 vol_name = "No Title";
2662 const gchar *vcodec = ghb_settings_get_option(ud->settings, "video_codec");
2663 const gchar *container = ghb_settings_get_option(ud->settings, "container");
2664 const gchar *acodec = ghb_settings_get_option(ud->settings, "audio_codec");
2665 const gchar *dest = ghb_settings_get_string(ud->settings, "destination");
2666 const gchar *preset = ghb_settings_get_string(ud->settings, "preset");
2667 gchar *info = g_strdup_printf
2669 "<big><b>%s</b></big> (Title %d, Chapters %d through %d, %d Video %s)"
2670 "\n<b>Preset:</b> %s"
2671 "\n<b>Format:</b> %s Container, %s Video + %s Audio"
2672 "\n<b>Destination:</b> %s",
2673 vol_name, title+1, start_chapter, end_chapter,
2674 pass2 ? 2:1, pass2 ? "Passes":"Pass",
2675 preset, container, vcodec, acodec, dest);
2677 widget = GHB_WIDGET (ud->builder, "autostart_summary");
2678 gtk_label_set_markup (GTK_LABEL(widget), info);
2680 widget = GHB_WIDGET(ud->builder, "autostart_dialog");
2681 gtk_widget_show_now(widget);
2682 g_timeout_add (25, autostart_timer_cb, (gpointer)ud);
2683 autostart_timeout = 800;
2688 GtkProgressBar *progress;
2689 progress = GTK_PROGRESS_BAR(GHB_WIDGET (ud->builder, "progressbar"));
2690 gtk_progress_bar_set_fraction (progress, 0);
2691 gtk_progress_bar_set_text (progress, "No Source");
2698 work_started = FALSE;
2699 queue_buttons_grey(ud, FALSE);
2703 if (update_default_destination)
2705 const gchar *dest = ghb_settings_get_string(ud->settings, "destination");
2706 gchar *dest_dir = g_path_get_dirname (dest);
2707 const gchar *def_dest = ghb_settings_get_string(ud->settings, "destination_dir");
2708 if (strcmp(dest_dir, def_dest) != 0)
2710 ghb_settings_set_string (ud->settings, "destination_dir", dest_dir);
2711 ghb_prefs_save (ud->settings);
2713 update_default_destination = FALSE;
2717 set_preview_image (ud);
2718 update_preview = FALSE;
2720 if (ticks == 3 && ghb_autostart)
2722 // Make sure this doesn't happen twice
2723 const gchar *source = ghb_settings_get_string(ud->settings, "source");
2724 if (update_source_label(ud, source))
2726 GtkProgressBar *progress;
2727 progress = GTK_PROGRESS_BAR(GHB_WIDGET (ud->builder, "progressbar"));
2728 const gchar *path = ghb_settings_get_string( ud->settings, "source");
2729 gtk_progress_bar_set_fraction (progress, 0);
2730 gtk_progress_bar_set_text (progress, "Scanning ...");
2731 ud->state |= GHB_STATE_SCANNING;
2732 ghb_backend_scan (path, 0);
2740 autostart_ok_cb(GtkWidget *widget, signal_user_data_t *ud)
2742 widget = GHB_WIDGET(ud->builder, "autostart_dialog");
2743 gtk_widget_hide(widget);
2744 queue_start_clicked_cb(NULL, ud);
2745 autostart_timeout = -1;
2749 autostart_cancel_cb(GtkWidget *widget, signal_user_data_t *ud)
2751 widget = GHB_WIDGET(ud->builder, "autostart_dialog");
2752 gtk_widget_hide(widget);
2753 autostart_timeout = -1;
2757 ghb_log_cb(GIOChannel *source, GIOCondition cond, gpointer data)
2761 GtkTextView *textview;
2762 GtkTextBuffer *buffer;
2764 GError *gerror = NULL;
2767 signal_user_data_t *ud = (signal_user_data_t*)data;
2769 status = g_io_channel_read_line (source, &text, &length, NULL, &gerror);
2772 textview = GTK_TEXT_VIEW(GHB_WIDGET (ud->builder, "activity_view"));
2773 buffer = gtk_text_view_get_buffer (textview);
2774 mark = gtk_text_buffer_get_insert (buffer);
2775 gtk_text_view_scroll_mark_onscreen(textview, mark);
2776 gtk_text_buffer_insert_at_cursor (buffer, text, -1);
2777 g_io_channel_write_chars (ud->activity_log, text, length, &length, NULL);
2780 if (status != G_IO_STATUS_NORMAL)
2782 // This should never happen, but if it does I would get into an
2783 // infinite loop. Returning false removes this callback.
2784 g_warning("Error while reading activity from pipe\n");
2787 g_warning("%s\n", gerror->message);
2788 g_error_free (gerror);
2793 g_error_free (gerror);
2798 about_activate_cb(GtkWidget *xwidget, signal_user_data_t *ud)
2800 GtkWidget *widget = GHB_WIDGET (ud->builder, "hb_about");
2801 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(widget), ghb_version());
2802 gtk_widget_show (widget);
2806 hb_about_response_cb(GtkWidget *widget, gint response, signal_user_data_t *ud)
2808 gtk_widget_hide (widget);
2812 show_activity_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
2814 GtkWidget *widget = GHB_WIDGET (ud->builder, "activity_window");
2815 gtk_widget_show (widget);
2819 show_queue_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
2821 GtkWidget *widget = GHB_WIDGET (ud->builder, "queue_window");
2822 gtk_widget_show (widget);
2826 show_presets_toggled_cb(GtkToggleButton *button, signal_user_data_t *ud)
2829 GtkWindow *hb_window;
2831 g_debug("show_presets_clicked_cb ()\n");
2832 widget = GHB_WIDGET (ud->builder, "presets_frame");
2833 if (gtk_toggle_button_get_active(button))
2835 gtk_widget_show_now(widget);
2839 gtk_widget_hide(widget);
2840 hb_window = GTK_WINDOW(GHB_WIDGET (ud->builder, "hb_window"));
2841 gtk_window_resize(hb_window, 16, 16);
2843 ghb_widget_to_setting(ud->settings, GTK_WIDGET(button));
2844 ghb_prefs_save(ud->settings);
2848 presets_frame_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation, signal_user_data_t *ud)
2850 GtkTreeView *treeview;
2851 GtkTreeSelection *selection;
2852 GtkTreeModel *store;
2855 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
2856 selection = gtk_tree_view_get_selection(treeview);
2857 if (gtk_tree_selection_get_selected(selection, &store, &iter))
2860 path = gtk_tree_model_get_path (store, &iter);
2861 // Make the parent visible in scroll window if it is not.
2862 gtk_tree_view_scroll_to_cell (treeview, path, NULL, FALSE, 0, 0);
2868 update_chapter_list(signal_user_data_t *ud)
2870 GtkTreeView *treeview;
2872 GtkListStore *store;
2875 gint titleindex, ii;
2877 g_debug("update_chapter_list ()\n");
2878 titleindex = ghb_settings_get_index(ud->settings, "title");
2879 chapters = ghb_get_chapters(titleindex);
2880 if (ud->chapter_list != NULL)
2881 g_strfreev (ud->chapter_list);
2882 ud->chapter_list = chapters;
2884 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "chapters_list"));
2885 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
2887 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
2891 if (chapters != NULL && chapters[ii])
2893 // Update row with settings data
2894 g_debug("Updating row\n");
2895 gtk_list_store_set(store, &iter,
2901 done = !gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
2905 // No more settings data, remove row
2906 g_debug("Removing row\n");
2907 done = !gtk_list_store_remove(store, &iter);
2911 while (chapters != NULL && chapters[ii])
2913 // Additional settings, add row
2914 g_debug("Adding row\n");
2915 g_debug("%d -- %s\n", ii, chapters[ii]);
2916 gtk_list_store_append(store, &iter);
2917 gtk_list_store_set(store, &iter,
2927 chapter_edited_cb(GtkCellRendererText *cell, gchar *path, gchar *text, signal_user_data_t *ud)
2929 GtkTreePath *treepath;
2930 GtkListStore *store;
2931 GtkTreeView *treeview;
2932 GtkTreeViewColumn *column;
2936 g_debug("chapter_edited_cb ()\n");
2937 g_debug("path (%s)\n", path);
2938 g_debug("text (%s)\n", text);
2939 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "chapters_list"));
2940 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
2941 treepath = gtk_tree_path_new_from_string (path);
2942 gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath);
2943 gtk_tree_path_free (treepath);
2944 gtk_list_store_set(store, &iter,
2948 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &index, -1);
2949 g_free(ud->chapter_list[index-1]);
2950 ud->chapter_list[index-1] = g_strdup(text);
2951 if (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter))
2953 column = gtk_tree_view_get_column(treeview, 1);
2954 treepath = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);
2955 gtk_tree_view_set_cursor(treeview, treepath, column, TRUE);
2956 gtk_tree_path_free (treepath);
2961 chapter_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
2963 GtkTreeModel *store;
2966 g_debug("chapter_list_selection_changed_cb ()\n");
2967 if (gtk_tree_selection_get_selected(selection, &store, &iter))
2974 queue_list_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation, GtkCellRenderer *cell)
2976 GtkTreeViewColumn *column;
2979 column = gtk_tree_view_get_column (GTK_TREE_VIEW(widget), 0);
2980 width = gtk_tree_view_column_get_width(column);
2981 g_debug("col width %d alloc width %d\n", width, allocation->width);
2982 // Set new wrap-width. Shave a little off to accomidate the icons
2983 // that share this column.
2984 if (width >= 564) // Don't allow below a certain size
2985 g_object_set(cell, "wrap-width", width-70, NULL);
2989 preview_button_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
2991 gint titleindex = ghb_settings_get_int(ud->settings, "title");
2992 if (titleindex < 0) return;
2993 g_debug("titleindex %d\n", titleindex);
2995 GtkWidget *widget = GHB_WIDGET (ud->builder, "preview_window");
2996 gtk_widget_show (widget);
3000 preview_frame_value_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
3002 set_preview_image(ud);
3006 preview_button_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation, signal_user_data_t *ud)
3008 g_debug("-------------------------------allocate %d x %d\n", allocation->width, allocation->height);
3009 if (preview_button_width == allocation->width &&
3010 preview_button_height == allocation->height)
3012 // Nothing to do. Bug out.
3013 g_debug("nothing to do\n");
3016 g_debug("-------------------------------prev allocate %d x %d\n", preview_button_width, preview_button_height);
3017 preview_button_width = allocation->width;
3018 preview_button_height = allocation->height;
3019 set_preview_image(ud);
3023 queue_start_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
3025 GSList *link = ud->queue;
3026 job_settings_t *job;
3027 gboolean running = FALSE;
3028 while (link != NULL)
3030 job = (job_settings_t*)link->data;
3031 if ((job->status == GHB_QUEUE_RUNNING) ||
3032 (job->status == GHB_QUEUE_PENDING))
3041 // The queue has no running or pending jobs.
3042 // Add current settings to the queue, then run.
3046 ud->state |= GHB_STATE_WORKING;
3051 queue_stop_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
3053 cancel_encode(NULL);
3057 queue_pause_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
3063 presets_default_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
3065 ghb_set_preset_default(ud->settings);
3066 ghb_presets_list_update(ud);
3070 debug_log_handler(const gchar *domain, GLogLevelFlags flags, const gchar *msg, gpointer data)
3072 signal_user_data_t *ud = (signal_user_data_t*)data;
3076 printf("%s: %s\n", domain, msg);
3081 set_visible(GtkWidget *widget, gboolean visible)
3085 gtk_widget_show_now(widget);
3089 gtk_widget_hide(widget);
3094 ghb_hbfd(signal_user_data_t *ud, gboolean hbfd)
3097 g_debug("ghb_hbfd\n");
3098 widget = GHB_WIDGET(ud->builder, "queue_pause1");
3099 set_visible(widget, !hbfd);
3100 widget = GHB_WIDGET(ud->builder, "queue_add");
3101 set_visible(widget, !hbfd);
3102 widget = GHB_WIDGET(ud->builder, "show_queue");
3103 set_visible(widget, !hbfd);
3104 widget = GHB_WIDGET(ud->builder, "show_activity");
3105 set_visible(widget, !hbfd);
3107 widget = GHB_WIDGET(ud->builder, "chapter_box");
3108 set_visible(widget, !hbfd);
3109 widget = GHB_WIDGET(ud->builder, "container_box");
3110 set_visible(widget, !hbfd);
3111 widget = GHB_WIDGET(ud->builder, "settings_box");
3112 set_visible(widget, !hbfd);
3113 widget = GHB_WIDGET(ud->builder, "presets_save");
3114 set_visible(widget, !hbfd);
3115 widget = GHB_WIDGET(ud->builder, "presets_remove");
3116 set_visible(widget, !hbfd);
3117 widget = GHB_WIDGET(ud->builder, "presets_default");
3118 set_visible(widget, !hbfd);
3119 widget = GHB_WIDGET (ud->builder, "hb_window");
3120 gtk_window_resize(GTK_WINDOW(widget), 16, 16);
3125 hbfd_toggled_cb(GtkWidget *widget, signal_user_data_t *ud)
3127 g_debug("hbfd_toggled_cb\n");
3128 ghb_widget_to_setting (ud->settings, widget);
3129 gboolean hbfd = ghb_settings_get_bool(ud->settings, "hbfd");
3131 ghb_prefs_save(ud->settings);
3135 ghb_file_menu_add_dvd(signal_user_data_t *ud)
3137 GList *link, *drives;
3139 GtkActionGroup *agroup = GTK_ACTION_GROUP(
3140 gtk_builder_get_object(ud->builder, "actiongroup1"));
3141 GtkUIManager *ui = GTK_UI_MANAGER(
3142 gtk_builder_get_object(ud->builder, "uimanager1"));
3143 guint merge_id = gtk_ui_manager_new_merge_id(ui);
3145 link = drives = dvd_device_list();
3146 while (link != NULL)
3148 gchar *name = (gchar*)link->data;
3149 // Create action for this drive
3150 GtkAction *action = gtk_action_new(name, name,
3151 "Scan this DVD source", "gtk-cdrom");
3152 // Add action to action group
3153 gtk_action_group_add_action_with_accel(agroup, action, "");
3154 // Add to ui manager
3155 gtk_ui_manager_add_ui(ui, merge_id,
3156 "ui/menubar1/menuitem1/quit1", name, name,
3157 GTK_UI_MANAGER_AUTO, TRUE);
3158 // Connect signal to action (menu item)
3159 g_signal_connect(action, "activate",
3160 (GCallback)dvd_source_activate_cb, ud);
3164 g_list_free(drives);
3167 gtk_ui_manager_add_ui(ui, merge_id,
3168 "ui/menubar1/menuitem1/quit1", "", NULL,
3169 GTK_UI_MANAGER_AUTO, TRUE);
3172 gboolean ghb_is_cd(GDrive *gd);
3177 GVolumeMonitor *gvm;
3178 GList *drives, *link;
3179 GList *dvd_devices = NULL;
3181 gvm = g_volume_monitor_get ();
3182 drives = g_volume_monitor_get_connected_drives (gvm);
3184 while (link != NULL)
3188 gd = (GDrive*)link->data;
3192 device = g_drive_get_identifier(gd, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
3193 dvd_devices = g_list_append(dvd_devices, (gpointer)device);
3195 g_object_unref (gd);
3198 g_list_free(drives);
3203 static DBusConnection *dbus_connection = NULL;
3204 static LibHalContext *hal_ctx;
3207 ghb_is_cd(GDrive *gd)
3210 LibHalDrive *halDrive;
3211 LibHalDriveType dtype;
3213 device = g_drive_get_identifier(gd, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
3214 halDrive = libhal_drive_from_device_file (hal_ctx, device);
3215 dtype = libhal_drive_get_type(halDrive);
3217 return (dtype == LIBHAL_DRIVE_TYPE_CDROM);
3221 drive_changed_cb(GVolumeMonitor *gvm, GDrive *gd, signal_user_data_t *ud)
3225 if (ud->current_dvd_device == NULL) return;
3226 if (ud->state != GHB_STATE_IDLE) return;
3227 device = g_drive_get_identifier(gd, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
3229 // DVD insertion detected. Scan it.
3230 if (strcmp(device, ud->current_dvd_device) == 0)
3232 if (g_drive_has_media (gd))
3234 GtkProgressBar *progress;
3235 progress = GTK_PROGRESS_BAR(GHB_WIDGET (ud->builder, "progressbar"));
3236 gtk_progress_bar_set_text (progress, "Scanning ...");
3237 gtk_progress_bar_set_fraction (progress, 0);
3238 update_source_label(ud, device);
3239 ud->state |= GHB_STATE_SCANNING;
3240 ghb_backend_scan(device, 0);
3244 ud->state |= GHB_STATE_SCANNING;
3245 ghb_backend_scan("/dev/null", 0);
3257 if (dbus_connection != NULL)
3260 dbus_error_init (&error);
3261 if (!(dbus_connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error))) {
3262 g_debug ("could not get system bus: %s\n", error.message);
3263 dbus_error_free (&error);
3267 //dbus_connection_setup_with_g_main (dbus_connection, NULL);
3268 //dbus_connection_set_exit_on_disconnect (dbus_connection, FALSE);
3269 //dbus_connection_add_filter (dbus_connection, gvm_dbus_filter_function, NULL, NULL);
3284 if (!(hal_ctx = libhal_ctx_new ())) {
3285 g_warning ("failed to create a HAL context!");
3289 libhal_ctx_set_dbus_connection (hal_ctx, dbus_connection);
3290 dbus_error_init (&error);
3291 if (!libhal_ctx_init (hal_ctx, &error)) {
3292 g_warning ("libhal_ctx_init failed: %s", error.message ? error.message : "unknown");
3293 dbus_error_free (&error);
3294 libhal_ctx_free (hal_ctx);
3299 * Do something to ping the HAL daemon - the above functions will
3300 * succeed even if hald is not running, so long as DBUS is. But we
3301 * want to exit silently if hald is not running, to behave on
3304 if (!(devices = libhal_get_all_devices (hal_ctx, &nr, &error))) {
3305 g_warning ("seems that HAL is not running: %s", error.message ? error.message : "unknown");
3306 dbus_error_free (&error);
3308 libhal_ctx_shutdown (hal_ctx, NULL);
3309 libhal_ctx_free (hal_ctx);
3313 libhal_free_string_array (devices);
3315 //gvm_hal_claim_branch ("/org/freedesktop/Hal/devices/local");