void ghb_subtitle_list_refresh_selected(signal_user_data_t *ud) { GtkTreeView *tv; GtkTreeModel *tm; GtkTreePath *tp; GtkTreeSelection *ts; GtkTreeIter ti; gint *indices; gint row; GhbValue *subsettings = NULL; const GhbValue *subtitle_list; g_debug("subtitle_list_refresh_selected()"); tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list_view")); ts = gtk_tree_view_get_selection(tv); if (gtk_tree_selection_get_selected(ts, &tm, &ti)) { // Get the row number tp = gtk_tree_model_get_path(tm, &ti); indices = gtk_tree_path_get_indices(tp); row = indices[0]; gtk_tree_path_free(tp); if (row < 0) return; subtitle_list = ghb_dict_get_value(ud->settings, "subtitle_list"); if (row >= ghb_array_len(subtitle_list)) return; subsettings = ghb_array_get(subtitle_list, row); subtitle_refresh_list_row_ui(tm, &ti, subsettings); } }
static void subtitle_refresh_list_ui_from_settings(signal_user_data_t *ud, GhbValue *settings) { GhbValue *subtitle_list; GhbValue *subsettings; gint ii, count, tm_count; GtkTreeView *tv; GtkTreeModel *tm; GtkTreeIter ti; tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list_view")); tm = gtk_tree_view_get_model(tv); tm_count = gtk_tree_model_iter_n_children(tm, NULL); subtitle_list = ghb_dict_get_value(settings, "subtitle_list"); count = ghb_array_len(subtitle_list); if (count != tm_count) { ghb_clear_subtitle_list_ui(ud->builder); for (ii = 0; ii < count; ii++) { gtk_tree_store_append(GTK_TREE_STORE(tm), &ti, NULL); } } for (ii = 0; ii < count; ii++) { g_return_if_fail(tv != NULL); gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii); subsettings = ghb_array_get(subtitle_list, ii); subtitle_refresh_list_row_ui(tm, &ti, subsettings); } }
G_MODULE_EXPORT void video_preset_slider_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { ghb_widget_to_setting(ud->settings, widget); int presetIndex = ghb_dict_get_int(ud->settings, "VideoPresetSlider"); const char * const *video_presets; const char *preset = "medium"; int count; int encoder = ghb_get_video_encoder(ud->settings); video_presets = hb_video_encoder_get_presets(encoder); if (video_presets != NULL) { for (count = 0; video_presets[count]; count++); if (presetIndex < count) { preset = video_presets[presetIndex]; } } ghb_set_video_preset(ud->settings, encoder, preset); GhbValue *gval = ghb_dict_get_value(ud->settings, "VideoPresetSlider"); ghb_ui_settings_update(ud, ud->settings, "VideoPresetSlider", gval); ghb_check_dependency(ud, widget, NULL); ghb_clear_presets_selection(ud); update_adv_settings_tooltip(ud); }
void ghb_reset_subtitles(signal_user_data_t *ud, GhbValue *settings) { GhbValue *slist; GhbValue *subtitle; gint count, ii; gint title_id, titleindex; const hb_title_t *title; g_debug("ghb_reset_subtitles"); ghb_clear_subtitle_list_settings(ud->settings); ghb_clear_subtitle_list_ui(ud->builder); title_id = ghb_dict_get_int(ud->settings, "title"); title = ghb_lookup_title(title_id, &titleindex); if (title == NULL) return; slist = ghb_dict_get_value(settings, "subtitle_list"); count = ghb_array_len(slist); for (ii = 0; ii < count; ii++) { subtitle = ghb_value_dup(ghb_array_get(slist, ii)); subtitle_add_to_settings(ud->settings, subtitle); } subtitle_refresh_list_ui(ud); }
const gchar* ghb_dict_get_string(const GhbValue *dict, const gchar *key) { const GhbValue* value; value = ghb_dict_get_value(dict, key); return ghb_value_get_string(value); }
static GhbValue* subtitle_get_selected_settings(signal_user_data_t *ud, int *index) { GtkTreeView *tv; GtkTreePath *tp; GtkTreeSelection *ts; GtkTreeModel *tm; GtkTreeIter iter; gint *indices; gint row; GhbValue *subsettings = NULL; const GhbValue *subtitle_list; g_debug("get_selected_settings ()"); tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list_view")); ts = gtk_tree_view_get_selection(tv); if (gtk_tree_selection_get_selected(ts, &tm, &iter)) { // Get the row number tp = gtk_tree_model_get_path(tm, &iter); indices = gtk_tree_path_get_indices(tp); row = indices[0]; gtk_tree_path_free(tp); if (row < 0) return NULL; subtitle_list = ghb_dict_get_value(ud->settings, "subtitle_list"); if (row >= ghb_array_len(subtitle_list)) return NULL; subsettings = ghb_array_get(subtitle_list, row); if (index != NULL) *index = row; } return subsettings; }
gboolean ghb_dict_get_bool(const GhbValue *dict, const gchar *key) { const GhbValue* value; value = ghb_dict_get_value(dict, key); if (value == NULL) return FALSE; return ghb_value_get_bool(value); }
gint64 ghb_dict_get_int(const GhbValue *dict, const gchar *key) { const GhbValue* value; value = ghb_dict_get_value(dict, key); if (value == NULL) return 0; return ghb_value_get_int(value); }
gdouble ghb_dict_get_double(const GhbValue *dict, const gchar *key) { const GhbValue* value; value = ghb_dict_get_value(dict, key); if (value == NULL) return 0; return ghb_value_get_double(value); }
gchar* ghb_dict_get_string_xform(const GhbValue *dict, const gchar *key) { const GhbValue* value; value = ghb_dict_get_value(dict, key); if (value == NULL) return g_strdup(""); return ghb_value_get_string_xform(value); }
G_MODULE_EXPORT void subtitle_remove_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud) { GtkTreeView *tv; GtkTreePath *tp; GtkTreeModel *tm; GtkTreeSelection *ts; GtkTreeIter ti, nextIter; gint row; gint *indices; GhbValue *subtitle_list; tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list_view")); ts = gtk_tree_view_get_selection(tv); tm = gtk_tree_view_get_model(tv); tp = gtk_tree_path_new_from_string (path); if (gtk_tree_path_get_depth(tp) > 1) return; if (gtk_tree_model_get_iter(tm, &ti, tp)) { nextIter = ti; if (!gtk_tree_model_iter_next(tm, &nextIter)) { nextIter = ti; if (gtk_tree_model_get_iter_first(tm, &nextIter)) { gtk_tree_selection_select_iter(ts, &nextIter); } } else { gtk_tree_selection_select_iter(ts, &nextIter); } subtitle_list = ghb_dict_get_value(ud->settings, "subtitle_list"); // Get the row number indices = gtk_tree_path_get_indices (tp); row = indices[0]; if (row < 0 || row >= ghb_array_len(subtitle_list)) { gtk_tree_path_free(tp); return; } // Update our settings list before removing the row from the // treeview. Removing from the treeview sometimes provokes an // immediate selection change, so the list needs to be up to date // when this happens. ghb_array_remove(subtitle_list, row); // Remove the selected item gtk_tree_store_remove(GTK_TREE_STORE(tm), &ti); ghb_live_reset(ud); } gtk_tree_path_free(tp); }
static void subtitle_def_lang_list_init(signal_user_data_t *ud) { GhbValue *lang_list; // Clear selected languages. subtitle_def_selected_lang_list_clear(ud); lang_list = ghb_dict_get_value(ud->settings, "SubtitleLanguageList"); if (lang_list == NULL) { lang_list = ghb_array_new(); ghb_dict_set(ud->settings, "SubtitleLanguageList", lang_list); } int ii, count; count = ghb_array_len(lang_list); for (ii = 0; ii < count; ) { GhbValue *lang_val = ghb_array_get(lang_list, ii); int idx = ghb_lookup_audio_lang(lang_val); if (ii == 0) { const iso639_lang_t *lang; lang = ghb_iso639_lookup_by_int(idx); subtitle_update_pref_lang(ud, lang); } GtkListBox *avail, *selected; GtkListBoxRow *row; avail = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_avail_lang")); selected = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_selected_lang")); row = ghb_find_lang_row(avail, idx); if (row) { GtkWidget *label = gtk_bin_get_child(GTK_BIN(row)); g_object_ref(G_OBJECT(label)); gtk_widget_destroy(GTK_WIDGET(row)); gtk_widget_show(label); gtk_list_box_insert(selected, label, -1); ii++; } else { // Error in list. Probably duplicate languages. Remove // this item from the list. ghb_array_remove(lang_list, ii); count--; } } if (count == 0) { subtitle_update_pref_lang(ud, NULL); } }
static void subtitle_add_to_settings(GhbValue *settings, GhbValue *subsettings) { // Add the current subtitle settings to the list. GhbValue *subtitle_list; gint count; gboolean burned, forced, def; gint source; subtitle_list = ghb_dict_get_value(settings, "subtitle_list"); if (subtitle_list == NULL) { subtitle_list = ghb_array_new(); ghb_dict_set(settings, "subtitle_list", subtitle_list); } // Validate some settings const char *mux_id; const hb_container_t *mux; mux_id = ghb_dict_get_string(settings, "FileFormat"); mux = ghb_lookup_container_by_name(mux_id); source = ghb_dict_get_int(subsettings, "SubtitleSource"); burned = ghb_dict_get_bool(subsettings, "SubtitleBurned"); if (burned && !hb_subtitle_can_burn(source)) { burned = FALSE; ghb_dict_set_bool(subsettings, "SubtitleBurned", burned); } if (!burned && !hb_subtitle_can_pass(source, mux->format)) { burned = TRUE; ghb_dict_set_bool(subsettings, "SubtitleBurned", burned); ghb_dict_set_bool(subsettings, "SubtitleDefaultTrack", FALSE); } def = ghb_dict_get_bool(subsettings, "SubtitleDefaultTrack"); forced = ghb_dict_get_bool(subsettings, "SubtitleForced"); if (forced && !hb_subtitle_can_force(source)) { forced = FALSE; ghb_dict_set_bool(subsettings, "SubtitleForced", forced); } ghb_array_append(subtitle_list, subsettings); // Check consistancy of exclusive flags count = ghb_array_len(subtitle_list); if (burned) ghb_subtitle_exclusive_burn_settings(settings, count-1); if (def) ghb_subtitle_exclusive_default_settings(settings, count-1); }
G_MODULE_EXPORT void vcodec_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { float val, vqmin, vqmax, step, page; int inverted, digits; ghb_widget_to_setting(ud->settings, widget); ghb_check_dependency(ud, widget, NULL); ghb_show_container_options(ud); ghb_update_summary_info(ud); ghb_clear_presets_selection(ud); ghb_live_reset(ud); // Set the range of the video quality slider val = ghb_vquality_default(ud); ghb_vquality_range(ud, &vqmin, &vqmax, &step, &page, &digits, &inverted); ghb_scale_configure(ud, "VideoQualitySlider", val, vqmin, vqmax, step, page, digits, inverted); ghb_update_ui_combo_box(ud, "VideoTune", NULL, FALSE); ghb_update_ui_combo_box(ud, "VideoProfile", NULL, FALSE); ghb_update_ui_combo_box(ud, "VideoLevel", NULL, FALSE); ghb_ui_update(ud, "VideoTune", ghb_int_value(0)); ghb_ui_update(ud, "VideoProfile", ghb_int_value(0)); ghb_ui_update(ud, "VideoLevel", ghb_int_value(0)); ghb_ui_update(ud, "VideoOptionExtra", ghb_string_value("")); // Set the range of the preset slider int encoder = ghb_get_video_encoder(ud->settings); GtkWidget *presetSlider = GHB_WIDGET(ud->builder, "VideoPresetSlider"); GtkWidget *presetLabel = GHB_WIDGET(ud->builder, "VideoPresetLabel"); const char * const *video_presets; int count = 0; video_presets = hb_video_encoder_get_presets(encoder); while (video_presets && video_presets[count]) count++; gtk_widget_set_visible(presetSlider, count > 0); gtk_widget_set_visible(presetLabel, count > 0); if (count) { gtk_range_set_range(GTK_RANGE(presetSlider), 0, count-1); } ghb_set_video_preset(ud->settings, encoder, "medium"); GhbValue *gval = ghb_dict_get_value(ud->settings, "VideoPresetSlider"); ghb_ui_settings_update(ud, ud->settings, "VideoPresetSlider", gval); // Advanced options are only for x264 if (!(encoder & HB_VCODEC_X264_MASK)) { ghb_ui_update(ud, "x264UseAdvancedOptions", ghb_boolean_value(FALSE)); } }
static void ghb_clear_subtitle_list_settings(GhbValue *settings) { GhbValue *subtitle_list; subtitle_list = ghb_dict_get_value(settings, "subtitle_list"); if (subtitle_list == NULL) { subtitle_list = ghb_array_new(); ghb_dict_set(settings, "subtitle_list", subtitle_list); } else ghb_array_reset(subtitle_list); }
G_MODULE_EXPORT void subtitle_list_selection_changed_cb(GtkTreeSelection *ts, signal_user_data_t *ud) { GtkTreeModel *tm; GtkTreeIter iter; GhbValue *subsettings = NULL; int row; g_debug("subtitle_list_selection_changed_cb()"); if (gtk_tree_selection_get_selected(ts, &tm, &iter)) { GtkTreeIter piter; if (gtk_tree_model_iter_parent(tm, &piter, &iter)) { GtkTreePath *path; GtkTreeView *tv; gtk_tree_selection_select_iter(ts, &piter); path = gtk_tree_model_get_path(tm, &piter); tv = gtk_tree_selection_get_tree_view(ts); // Make the parent visible in scroll window if it is not. gtk_tree_view_scroll_to_cell(tv, path, NULL, FALSE, 0, 0); gtk_tree_path_free(path); return; } GtkTreePath *tp; gint *indices; GhbValue *subtitle_list; tp = gtk_tree_model_get_path(tm, &iter); indices = gtk_tree_path_get_indices(tp); row = indices[0]; gtk_tree_path_free(tp); subtitle_list = ghb_dict_get_value(ud->settings, "subtitle_list"); if (row >= 0 && row < ghb_array_len(subtitle_list)) subsettings = ghb_array_get(subtitle_list, row); } subtitle_update_dialog_widgets(ud, subsettings); if (subsettings) { if (ghb_dict_get_bool(subsettings, "SubtitleBurned")) { ghb_subtitle_exclusive_burn(ud, row); } } }
G_MODULE_EXPORT void subtitle_remove_lang_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) { GtkListBox *avail, *selected; GtkListBoxRow *row; GtkWidget *label; avail = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_avail_lang")); selected = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_selected_lang")); row = gtk_list_box_get_selected_row(selected); if (row != NULL) { gint index; GhbValue *lang_list; index = gtk_list_box_row_get_index(row); // Remove from UI selected language list box label = gtk_bin_get_child(GTK_BIN(row)); g_object_ref(G_OBJECT(label)); int idx = (intptr_t)g_object_get_data(G_OBJECT(label), "lang_idx"); gtk_widget_destroy(GTK_WIDGET(row)); gtk_widget_show(label); // Add to UI available language list box gtk_list_box_insert(avail, label, idx); // Remove from preset language list lang_list = ghb_dict_get_value(ud->settings, "SubtitleLanguageList"); ghb_array_remove(lang_list, index); ghb_clear_presets_selection(ud); if (ghb_array_len(lang_list) > 0) { const iso639_lang_t *lang; GhbValue *entry = ghb_array_get(lang_list, 0); lang = ghb_iso639_lookup_by_int(ghb_lookup_audio_lang(entry)); subtitle_update_pref_lang(ud, lang); } else { subtitle_update_pref_lang(ud, NULL); } } }
G_MODULE_EXPORT void subtitle_edit_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud) { GtkTreeView *tv; GtkTreePath *tp; GtkTreeModel *tm; GtkTreeSelection *ts; GtkTreeIter ti; tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list_view")); ts = gtk_tree_view_get_selection(tv); tm = gtk_tree_view_get_model(tv); tp = gtk_tree_path_new_from_string (path); if (gtk_tree_path_get_depth(tp) > 1) return; if (gtk_tree_model_get_iter(tm, &ti, tp)) { GhbValue *subsettings, *backup; gtk_tree_selection_select_iter(ts, &ti); // Back up settings in case we need to revert. backup = ghb_value_dup( ghb_dict_get_value(ud->settings, "subtitle_list")); // Pop up the edit dialog GtkResponseType response; GtkWidget *dialog = GHB_WIDGET(ud->builder, "subtitle_dialog"); response = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_hide(dialog); if (response != GTK_RESPONSE_OK) { ghb_dict_set(ud->settings, "subtitle_list", backup); subsettings = subtitle_get_selected_settings(ud, NULL); if (subsettings != NULL) { subtitle_update_dialog_widgets(ud, subsettings); } subtitle_refresh_list_ui(ud); } else { ghb_value_free(&backup); } } }
void ghb_subtitle_exclusive_default_settings(GhbValue *settings, gint index) { GhbValue *subtitle_list; GhbValue *subtitle; gint ii, count; subtitle_list = ghb_dict_get_value(settings, "subtitle_list"); count = ghb_array_len(subtitle_list); for (ii = 0; ii < count; ii++) { if (ii != index) { subtitle = ghb_array_get(subtitle_list, ii); ghb_dict_set_bool(subtitle, "SubtitleDefaultTrack", FALSE); } } }
void ghb_subtitle_prune(signal_user_data_t *ud) { GhbValue *subtitle_list; GhbValue *subsettings; gint ii; gboolean one_burned = FALSE; subtitle_list = ghb_dict_get_value(ud->settings, "subtitle_list"); if (subtitle_list == NULL) return; const char *mux_id; const hb_container_t *mux; mux_id = ghb_dict_get_string(ud->settings, "FileFormat"); mux = ghb_lookup_container_by_name(mux_id); for (ii = 0; ii < ghb_array_len(subtitle_list); ) { gboolean burned; int source; subsettings = ghb_array_get(subtitle_list, ii); burned = ghb_dict_get_bool(subsettings, "SubtitleBurned"); source = ghb_dict_get_bool(subsettings, "SubtitleSource"); burned = burned || !hb_subtitle_can_pass(source, mux->format); if (burned && one_burned) { ghb_array_remove(subtitle_list, ii); continue; } one_burned = one_burned || burned; ghb_dict_set_bool(subsettings, "SubtitleBurned", burned); ii++; } subsettings = subtitle_get_selected_settings(ud, NULL); if (subsettings != NULL) { subtitle_update_dialog_widgets(ud, subsettings); } }
static gboolean subtitle_is_one_burned(GhbValue *settings) { GhbValue *subtitle_list, *subsettings; int count, ii; subtitle_list = ghb_dict_get_value(settings, "subtitle_list"); if (subtitle_list == NULL) return FALSE; count = ghb_array_len(subtitle_list); for (ii = 0; ii < count; ii++) { subsettings = ghb_array_get(subtitle_list, ii); if (ghb_dict_get_bool(subsettings, "SubtitleBurned")) { return TRUE; } } return FALSE; }
void ghb_subtitle_set_pref_lang(GhbValue *settings) { GhbValue *lang_list; gboolean set = FALSE; lang_list = ghb_dict_get_value(settings, "SubtitleLanguageList"); if (ghb_array_len(lang_list) > 0) { GhbValue *glang = ghb_array_get(lang_list, 0); if (glang != NULL) { ghb_dict_set_string(settings, "PreferredLanguage", ghb_value_get_string(glang)); set = TRUE; } } if (!set) { ghb_dict_set_string(settings, "PreferredLanguage", "und"); } }
void ghb_subtitle_exclusive_burn_settings(GhbValue *settings, gint index) { GhbValue *subtitle_list; GhbValue *subsettings; gint ii, count; subtitle_list = ghb_dict_get_value(settings, "subtitle_list"); subsettings = ghb_array_get(subtitle_list, index); if (subsettings != NULL) { int track = ghb_dict_get_int(subsettings, "SubtitleTrack"); if (track == -1) { // Allow 2 tracks to be marked burned when one is // foreign audio search. Extra burned track will be // sanitized away if foreign audio search actually finds // something. return; } } count = ghb_array_len(subtitle_list); for (ii = 0; ii < count; ii++) { if (ii != index) { subsettings = ghb_array_get(subtitle_list, ii); int track = ghb_dict_get_int(subsettings, "SubtitleTrack"); if (track != -1) { // Allow 2 tracks to be marked burned when one is // foreign audio search. Extra burned track will be // sanitized away if foreign audio search actually finds // something. ghb_dict_set_bool(subsettings, "SubtitleBurned", FALSE); } } } }
G_MODULE_EXPORT void subtitle_add_lang_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) { GtkListBox *avail = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_avail_lang")); GtkListBox *selected = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_selected_lang")); GtkListBoxRow *row; GtkWidget *label; row = gtk_list_box_get_selected_row(avail); if (row != NULL) { int idx; const iso639_lang_t *lang; GhbValue *glang, *lang_list; // Remove from UI available language list box label = gtk_bin_get_child(GTK_BIN(row)); g_object_ref(G_OBJECT(label)); gtk_widget_destroy(GTK_WIDGET(row)); gtk_widget_show(label); // Add to UI selected language list box gtk_list_box_insert(selected, label, -1); // Add to preset language list idx = (intptr_t)g_object_get_data(G_OBJECT(label), "lang_idx"); lang = ghb_iso639_lookup_by_int(idx); glang = ghb_string_value_new(lang->iso639_2); lang_list = ghb_dict_get_value(ud->settings, "SubtitleLanguageList"); if (ghb_array_len(lang_list) == 0) { subtitle_update_pref_lang(ud, lang); } ghb_array_append(lang_list, glang); ghb_clear_presets_selection(ud); } }
G_MODULE_EXPORT void subtitle_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { // Add the current subtitle settings to the list. GhbValue *subsettings, *backup; gboolean one_burned; gint track; int title_id, titleindex; const hb_title_t *title; title_id = ghb_dict_get_int(ud->settings, "title"); title = ghb_lookup_title(title_id, &titleindex); if (title == NULL) { return; } // Back up settings in case we need to revert. backup = ghb_value_dup( ghb_dict_get_value(ud->settings, "subtitle_list")); one_burned = subtitle_is_one_burned(ud->settings); const char *mux_id; const hb_container_t *mux; mux_id = ghb_dict_get_string(ud->settings, "FileFormat"); mux = ghb_lookup_container_by_name(mux_id); int count = hb_list_count(title->list_subtitle); for (subsettings = NULL, track = 0; subsettings == NULL && track < count; track++) { subsettings = subtitle_add_track(ud, ud->settings, title, track, mux->format, FALSE, FALSE, FALSE, &one_burned); } if (subsettings == NULL) { subsettings = subtitle_add_track(ud, ud->settings, title, 0, mux->format, FALSE, TRUE, FALSE, &one_burned); } ghb_add_subtitle_to_ui(ud, subsettings); if (subsettings != NULL) { // Pop up the edit dialog GtkResponseType response; GtkWidget *dialog = GHB_WIDGET(ud->builder, "subtitle_dialog"); response = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_hide(dialog); if (response != GTK_RESPONSE_OK) { ghb_dict_set(ud->settings, "subtitle_list", backup); subsettings = subtitle_get_selected_settings(ud, NULL); if (subsettings != NULL) { subtitle_update_dialog_widgets(ud, subsettings); } subtitle_refresh_list_ui(ud); } else { ghb_value_free(&backup); } } }
int main(int argc, char *argv[]) { signal_user_data_t *ud; GError *error = NULL; GOptionContext *context; #if defined(_WIN32) // Tell gdk pixbuf where it's loader config file is. _putenv_s("GDK_PIXBUF_MODULE_FILE", "ghb.exe.local/loaders.cache"); _putenv_s("GST_PLUGIN_PATH", "lib/gstreamer-1.0"); #endif hb_global_init(); #ifdef ENABLE_NLS bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); textdomain(GETTEXT_PACKAGE); #endif context = g_option_context_new(_("- Transcode media formats")); g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE); g_option_context_add_group(context, gtk_get_option_group(TRUE)); #if defined(_ENABLE_GST) g_option_context_add_group(context, gst_init_get_option_group()); #endif g_option_context_parse(context, &argc, &argv, &error); if (error != NULL) { g_warning("%s: %s", G_STRFUNC, error->message); g_clear_error(&error); } g_option_context_free(context); #if defined(_WIN32) if (win32_console) { // Enable console logging if(AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole()){ close(STDOUT_FILENO); freopen("CONOUT$", "w", stdout); close(STDERR_FILENO); freopen("CONOUT$", "w", stderr); } } else { // Non-console windows apps do not have a stderr->_file // assigned properly stderr->_file = STDERR_FILENO; stdout->_file = STDOUT_FILENO; } #endif if (argc > 1 && dvd_device == NULL && argv[1][0] != '-') { dvd_device = argv[1]; } gtk_init(&argc, &argv); GtkCssProvider *css = gtk_css_provider_new(); error = NULL; gtk_css_provider_load_from_data(css, MyCSS, -1, &error); if (error == NULL) { GdkScreen *ss = gdk_screen_get_default(); gtk_style_context_add_provider_for_screen(ss, GTK_STYLE_PROVIDER(css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); } else { g_warning("%s: %s", G_STRFUNC, error->message); g_clear_error(&error); } #if !defined(_WIN32) notify_init("HandBrake"); #endif ghb_resource_init(); ghb_load_icons(); #if !defined(_WIN32) dbus_g_thread_init(); #endif ghb_udev_init(); ghb_write_pid_file(); ud = g_malloc0(sizeof(signal_user_data_t)); ud->debug = ghb_debug; g_log_set_handler(NULL, G_LOG_LEVEL_DEBUG, debug_log_handler, ud); g_log_set_handler("Gtk", G_LOG_LEVEL_WARNING, warn_log_handler, ud); //g_log_set_handler("Gtk", G_LOG_LEVEL_CRITICAL, warn_log_handler, ud); ud->globals = ghb_dict_new(); ud->prefs = ghb_dict_new(); ud->settings_array = ghb_array_new(); ud->settings = ghb_dict_new(); ghb_array_append(ud->settings_array, ud->settings); ud->builder = create_builder_or_die(BUILDER_NAME); // Enable events that alert us to media change events watch_volumes(ud); //GtkWidget *widget = GHB_WIDGET(ud->builder, "PictureDetelecineCustom"); //gtk_entry_set_inner_border(widget, 2); // Since GtkBuilder no longer assigns object ids to widget names // Assign a few that are necessary for style overrides to work #if defined(_NO_UPDATE_CHECK) GtkWidget *widget; widget = GHB_WIDGET(ud->builder, "check_updates_box"); gtk_widget_hide(widget); #endif // Must set the names of the widgets that I want to modify // style for. gtk_widget_set_name(GHB_WIDGET(ud->builder, "preview_hud"), "preview_hud"); gtk_widget_set_name(GHB_WIDGET(ud->builder, "preview_frame"), "preview_frame"); gtk_widget_set_name(GHB_WIDGET(ud->builder, "live_preview_play"), "live_preview_play"); gtk_widget_set_name(GHB_WIDGET(ud->builder, "live_preview_progress"), "live_preview_progress"); gtk_widget_set_name(GHB_WIDGET(ud->builder, "live_encode_progress"), "live_encode_progress"); gtk_widget_set_name(GHB_WIDGET(ud->builder, "live_duration"), "live_duration"); gtk_widget_set_name(GHB_WIDGET(ud->builder, "preview_show_crop"), "preview_show_crop"); gtk_widget_set_name(GHB_WIDGET(ud->builder, "preview_fullscreen"), "preview_fullscreen"); gtk_widget_set_name(GHB_WIDGET(ud->builder, "activity_view"), "activity_view"); // Redirect stderr to the activity window ghb_preview_init(ud); IoRedirect(ud); ghb_log( "%s - %s - %s", HB_PROJECT_TITLE, HB_PROJECT_BUILD_TITLE, HB_PROJECT_URL_WEBSITE ); ghb_init_dep_map(); // Need to connect x264_options textview buffer to the changed signal // since it can't be done automatically GtkTextView *textview; GtkTextBuffer *buffer; textview = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "x264Option")); buffer = gtk_text_view_get_buffer(textview); g_signal_connect(buffer, "changed", (GCallback)x264_entry_changed_cb, ud); textview = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "VideoOptionExtra")); buffer = gtk_text_view_get_buffer(textview); g_signal_connect(buffer, "changed", (GCallback)video_option_changed_cb, ud); textview = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "MetaLongDescription")); buffer = gtk_text_view_get_buffer(textview); g_signal_connect(buffer, "changed", (GCallback)plot_changed_cb, ud); ghb_combo_init(ud); g_debug("ud %p\n", ud); g_debug("ud->builder %p\n", ud->builder); bind_audio_tree_model(ud); bind_subtitle_tree_model(ud); bind_presets_tree_model(ud); bind_queue_tree_model(ud); bind_chapter_tree_model(ud); // Connect up the signals to their callbacks // I wrote my own connector so that I could pass user data // to the callbacks. Builder's standard autoconnect doesn't all this. gtk_builder_connect_signals_full(ud->builder, MyConnect, ud); ghb_init_audio_defaults_ui(ud); ghb_init_subtitle_defaults_ui(ud); // Parsing x264 options "" initializes x264 widgets to proper defaults ghb_x264_init(ud); // Load prefs before presets. Some preset defaults may depend // on preference settings. // First load default values ghb_settings_init(ud->prefs, "Preferences"); ghb_settings_init(ud->globals, "Globals"); ghb_settings_init(ud->settings, "Initialization"); ghb_settings_init(ud->settings, "OneTimeInitialization"); // Load user preferences file ghb_prefs_load(ud); // Store user preferences into ud->prefs ghb_prefs_to_settings(ud->prefs); int logLevel = ghb_dict_get_int(ud->prefs, "LoggingLevel"); ghb_backend_init(logLevel); // Load the presets files ghb_presets_load(ud); // Note that ghb_preset_to_settings(ud->settings) is called when // the default preset is selected. ghb_settings_to_ui(ud, ud->globals); ghb_settings_to_ui(ud, ud->prefs); // Note that ghb_settings_to_ui(ud->settings) happens when initial // empty title is initialized. if (ghb_dict_get_bool(ud->prefs, "hbfd")) { ghb_hbfd(ud, TRUE); } const gchar *source = ghb_dict_get_string(ud->prefs, "default_source"); ghb_dvd_set_current(source, ud); // Populate the presets tree view ghb_presets_list_init(ud, NULL); // Get the first preset name if (arg_preset != NULL) { ghb_select_preset(ud->builder, arg_preset); } else { ghb_select_default_preset(ud->builder); } // Grey out widgets that are dependent on a disabled feature ghb_check_all_depencencies(ud); if (dvd_device != NULL) { // Source overridden from command line option ghb_dict_set_string(ud->globals, "scan_source", dvd_device); g_idle_add((GSourceFunc)ghb_idle_scan, ud); } else { GhbValue *gval = ghb_dict_get_value(ud->prefs, "default_source"); ghb_dict_set(ud->globals, "scan_source", ghb_value_dup(gval)); } // Reload and check status of the last saved queue g_idle_add((GSourceFunc)ghb_reload_queue, ud); // Start timer for monitoring libhb status, 500ms g_timeout_add(200, ghb_timer_cb, (gpointer)ud); // Add dvd devices to File menu ghb_volname_cache_init(); GHB_THREAD_NEW("Cache Volume Names", (GThreadFunc)ghb_cache_volnames, ud); GtkWidget *ghb_window = GHB_WIDGET(ud->builder, "hb_window"); gint window_width, window_height; GdkGeometry geo = { -1, -1, 1920, 768, -1, -1, 10, 10, 0, 0, GDK_GRAVITY_NORTH_WEST }; GdkWindowHints geo_mask; geo_mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE | GDK_HINT_BASE_SIZE; gtk_window_set_geometry_hints(GTK_WINDOW(ghb_window), ghb_window, &geo, geo_mask); window_width = ghb_dict_get_int(ud->prefs, "window_width"); window_height = ghb_dict_get_int(ud->prefs, "window_height"); /* * Filter objects in GtkBuilder xml * Unfortunately, GtkFilter is poorly supported by GtkBuilder, * so a lot of the setup must happen in code. SourceFilterAll SourceFilterVideo SourceFilterTS SourceFilterMPG SourceFilterEVO SourceFilterVOB SourceFilterMKV SourceFilterMP4 SourceFilterAVI SourceFilterMOV SourceFilterOGG SourceFilterFLV SourceFilterWMV */ // Add filters to source chooser GtkFileFilter *filter; GtkFileChooser *chooser; chooser = GTK_FILE_CHOOSER(GHB_WIDGET(ud->builder, "source_dialog")); filter = GTK_FILE_FILTER(GHB_OBJECT(ud->builder, "SourceFilterAll")); gtk_file_filter_set_name(filter, _("All")); gtk_file_filter_add_pattern(filter, "*"); gtk_file_chooser_add_filter(chooser, filter); filter = GTK_FILE_FILTER(GHB_OBJECT(ud->builder, "SourceFilterVideo")); gtk_file_filter_set_name(filter, _("Video")); gtk_file_filter_add_mime_type(filter, "video/*"); gtk_file_chooser_add_filter(chooser, filter); filter = GTK_FILE_FILTER(GHB_OBJECT(ud->builder, "SourceFilterTS")); gtk_file_filter_set_name(filter, "TS"); gtk_file_filter_add_pattern(filter, "*.ts"); gtk_file_filter_add_pattern(filter, "*.TS"); gtk_file_filter_add_pattern(filter, "*.m2ts"); gtk_file_filter_add_pattern(filter, "*.M2TS"); gtk_file_chooser_add_filter(chooser, filter); filter = GTK_FILE_FILTER(GHB_OBJECT(ud->builder, "SourceFilterMPG")); gtk_file_filter_set_name(filter, "MPG"); gtk_file_filter_add_pattern(filter, "*.mpg"); gtk_file_filter_add_pattern(filter, "*.MPG"); gtk_file_filter_add_pattern(filter, "*.mepg"); gtk_file_filter_add_pattern(filter, "*.MEPG"); gtk_file_chooser_add_filter(chooser, filter); filter = GTK_FILE_FILTER(GHB_OBJECT(ud->builder, "SourceFilterEVO")); gtk_file_filter_set_name(filter, "EVO"); gtk_file_filter_add_pattern(filter, "*.evo"); gtk_file_filter_add_pattern(filter, "*.EVO"); gtk_file_chooser_add_filter(chooser, filter); filter = GTK_FILE_FILTER(GHB_OBJECT(ud->builder, "SourceFilterVOB")); gtk_file_filter_set_name(filter, "VOB"); gtk_file_filter_add_pattern(filter, "*.vob"); gtk_file_filter_add_pattern(filter, "*.VOB"); gtk_file_chooser_add_filter(chooser, filter); filter = GTK_FILE_FILTER(GHB_OBJECT(ud->builder, "SourceFilterMKV")); gtk_file_filter_set_name(filter, "MKV"); gtk_file_filter_add_pattern(filter, "*.mkv"); gtk_file_filter_add_pattern(filter, "*.MKV"); gtk_file_chooser_add_filter(chooser, filter); filter = GTK_FILE_FILTER(GHB_OBJECT(ud->builder, "SourceFilterMP4")); gtk_file_filter_set_name(filter, "MP4"); gtk_file_filter_add_pattern(filter, "*.mp4"); gtk_file_filter_add_pattern(filter, "*.MP4"); gtk_file_filter_add_pattern(filter, "*.m4v"); gtk_file_filter_add_pattern(filter, "*.M4V"); gtk_file_chooser_add_filter(chooser, filter); filter = GTK_FILE_FILTER(GHB_OBJECT(ud->builder, "SourceFilterMOV")); gtk_file_filter_set_name(filter, "MOV"); gtk_file_filter_add_pattern(filter, "*.mov"); gtk_file_filter_add_pattern(filter, "*.MOV"); gtk_file_chooser_add_filter(chooser, filter); filter = GTK_FILE_FILTER(GHB_OBJECT(ud->builder, "SourceFilterAVI")); gtk_file_filter_set_name(filter, "AVI"); gtk_file_filter_add_pattern(filter, "*.avi"); gtk_file_filter_add_pattern(filter, "*.AVI"); gtk_file_chooser_add_filter(chooser, filter); filter = GTK_FILE_FILTER(GHB_OBJECT(ud->builder, "SourceFilterOGG")); gtk_file_filter_set_name(filter, "OGG"); gtk_file_filter_add_pattern(filter, "*.ogg"); gtk_file_filter_add_pattern(filter, "*.OGG"); gtk_file_filter_add_pattern(filter, "*.ogv"); gtk_file_filter_add_pattern(filter, "*.OGV"); gtk_file_filter_add_pattern(filter, "*.ogm"); gtk_file_filter_add_pattern(filter, "*.OGM"); gtk_file_chooser_add_filter(chooser, filter); filter = GTK_FILE_FILTER(GHB_OBJECT(ud->builder, "SourceFilterFLV")); gtk_file_filter_set_name(filter, "FLV"); gtk_file_filter_add_pattern(filter, "*.flv"); gtk_file_filter_add_pattern(filter, "*.FLV"); gtk_file_chooser_add_filter(chooser, filter); filter = GTK_FILE_FILTER(GHB_OBJECT(ud->builder, "SourceFilterWMV")); gtk_file_filter_set_name(filter, "WMV"); gtk_file_filter_add_pattern(filter, "*.wmv"); gtk_file_filter_add_pattern(filter, "*.WMV"); gtk_file_chooser_add_filter(chooser, filter); // Gtk has a really stupid bug. If the file chooser is showing // hidden files AND there is no filter set, it will not select // the filename when gtk_file_chooser_set_filename is called. // So add a completely unnessary filter to prevent this behavior. filter = GTK_FILE_FILTER(GHB_OBJECT(ud->builder, "SourceFilterAll")); gtk_file_chooser_set_filter(chooser, filter); #if !GTK_CHECK_VERSION(3, 16, 0) PangoFontDescription *font_desc; font_desc = pango_font_description_from_string("monospace 10"); textview = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "activity_view")); gtk_widget_override_font(GTK_WIDGET(textview), font_desc); pango_font_description_free(font_desc); #endif // Grrrr! Gtk developers !!!hard coded!!! the width of the // radio buttons in GtkStackSwitcher to 100!!! // // Thankfully, GtkStackSwitcher is a regular container object // and we can access the buttons to change their width. GList *stack_switcher_children, *link; GtkContainer * stack_switcher = GTK_CONTAINER( GHB_WIDGET(ud->builder, "SettingsStackSwitcher")); link = stack_switcher_children = gtk_container_get_children(stack_switcher); while (link != NULL) { GtkWidget *widget = link->data; gtk_widget_set_size_request(widget, -1, -1); gtk_widget_set_hexpand(widget, TRUE); gtk_widget_set_halign(widget, GTK_ALIGN_FILL); link = link->next; } g_list_free(stack_switcher_children); gtk_window_resize(GTK_WINDOW(ghb_window), window_width, window_height); gtk_widget_show(ghb_window); // Everything should be go-to-go. Lets rock! gtk_main(); ghb_backend_close(); ghb_value_free(&ud->queue); ghb_value_free(&ud->settings_array); ghb_value_free(&ud->prefs); ghb_value_free(&ud->globals); ghb_value_free(&ud->x264_priv); g_io_channel_unref(ud->activity_log); ghb_settings_close(); ghb_resource_free(); #if !defined(_WIN32) notify_uninit(); #endif g_object_unref(ud->builder); g_free(ud->current_dvd_device); g_free(ud); return 0; }
void ghb_set_pref_subtitle_settings(signal_user_data_t *ud, const hb_title_t *title, GhbValue *settings) { gint track; gboolean *used; const gchar *audio_lang, *pref_lang = NULL; gboolean foreign_audio_search, foreign_audio_subs; gboolean burn_foreign, burn_first, burn_dvd, burn_bd; gboolean one_burned = FALSE; const GhbValue *lang_list; gint lang_count, sub_count, ii; int behavior; behavior = ghb_settings_combo_int(settings, "SubtitleTrackSelectionBehavior"); // Clear the subtitle list ghb_clear_subtitle_list_settings(settings); if (title == NULL) { // no source title return; } sub_count = hb_list_count(title->list_subtitle); if (sub_count == 0) { // No source subtitles return; } const char *mux_id; const hb_container_t *mux; mux_id = ghb_dict_get_string(settings, "FileFormat"); mux = ghb_lookup_container_by_name(mux_id); // Check to see if we need to add a subtitle track for foreign audio // language films. A subtitle track will be added if: // // The first (default) audio track language does NOT match the users // chosen Preferred Language AND the Preferred Language is NOT Any (und). // audio_lang = ghb_get_user_audio_lang(settings, title, 0); foreign_audio_search = ghb_dict_get_bool( settings, "SubtitleAddForeignAudioSearch"); foreign_audio_subs = ghb_dict_get_bool( settings, "SubtitleAddForeignAudioSubtitle"); lang_list = ghb_dict_get_value(settings, "SubtitleLanguageList"); lang_count = ghb_array_len(lang_list); if (lang_count > 0) { GhbValue *glang = ghb_array_get(lang_list, 0); pref_lang = ghb_value_get_string(glang); } if (pref_lang == NULL || !strncmp(pref_lang, "und", 4)) { foreign_audio_search = foreign_audio_subs = FALSE; pref_lang = NULL; } used = g_malloc0(sub_count * sizeof(gboolean)); int burn_behavior; burn_behavior = ghb_settings_combo_int(settings, "SubtitleBurnBehavior"); burn_foreign = burn_behavior == 1 || burn_behavior == 3; burn_first = burn_behavior == 2 || burn_behavior == 3; burn_dvd = ghb_dict_get_bool(settings, "SubtitleBurnDVDSub"); burn_bd = ghb_dict_get_bool(settings, "SubtitleBurnBDSub"); if (foreign_audio_subs && (audio_lang == NULL || strncmp(audio_lang, pref_lang, 4))) { // Add preferred language subtitle since first audio track // is foreign language. foreign_audio_search = FALSE; track = ghb_find_subtitle_track(title, pref_lang, 0); if (track >= 0) { gboolean burn; hb_subtitle_t *subtitle; subtitle = hb_list_item(title->list_subtitle, track); burn = (subtitle->source == VOBSUB && burn_dvd) || (subtitle->source == PGSSUB && burn_bd) || burn_foreign || burn_first; used[track] = TRUE; subtitle_add_track(ud, settings, title, track, mux->format, !burn, FALSE, burn, &one_burned); burn_first &= !burn; } } if (foreign_audio_search && (audio_lang != NULL && !strncmp(audio_lang, pref_lang, 4))) { // Add search for foreign audio segments gboolean burn = burn_foreign || burn_first; subtitle_add_track(ud, settings, title, -1, mux->format, !burn, FALSE, burn, &one_burned); burn_first &= !burn; } if (behavior != 0) { // Find "best" subtitle based on subtitle preferences for (ii = 0; ii < lang_count; ii++) { GhbValue *glang = ghb_array_get(lang_list, ii); const gchar *lang = ghb_value_get_string(glang); int next_track = 0; track = ghb_find_subtitle_track(title, lang, next_track); while (track >= 0) { if (!used[track]) { gboolean burn; hb_subtitle_t *subtitle; subtitle = hb_list_item(title->list_subtitle, track); burn = (subtitle->source == VOBSUB && burn_dvd) || (subtitle->source == PGSSUB && burn_bd) || burn_first; used[track] = TRUE; subtitle_add_track(ud, settings, title, track, mux->format, FALSE, FALSE, burn, &one_burned); burn_first &= !burn; } next_track = track + 1; if (behavior == 2) { track = ghb_find_subtitle_track(title, lang, next_track); } else { break; } } } } if (ghb_dict_get_bool(settings, "SubtitleAddCC")) { for (track = 0; track < sub_count; track++) { hb_subtitle_t *subtitle = hb_list_item(title->list_subtitle, track); if (subtitle->source == CC608SUB || subtitle->source == CC708SUB) break; } if (track < sub_count && !used[track]) { used[track] = TRUE; subtitle_add_track(ud, settings, title, track, mux->format, FALSE, FALSE, burn_first, &one_burned); } } g_free(used); }