G_MODULE_EXPORT void srt_file_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { GhbValue *subsettings; g_debug("srt_file_changed_cb()"); ghb_check_dependency(ud, widget, NULL); ghb_widget_to_setting(ud->settings, widget); subsettings = subtitle_get_selected_settings(ud, NULL); if (subsettings != NULL) { const gchar *filename; gchar *dirname; ghb_widget_to_setting(subsettings, widget); subtitle_set_track_description(ud->settings, subsettings); ghb_subtitle_list_refresh_selected(ud); ghb_live_reset(ud); // Update SrtDir preference filename = ghb_dict_get_string(subsettings, "SrtFile"); if (g_file_test(filename, G_FILE_TEST_IS_DIR)) { ghb_dict_set_string(ud->prefs, "SrtDir", filename); } else { dirname = g_path_get_dirname(filename); ghb_dict_set_string(ud->prefs, "SrtDir", dirname); g_free(dirname); } ghb_pref_save(ud->prefs, "SrtDir"); } }
G_MODULE_EXPORT void live_preview_start_cb(GtkWidget *xwidget, signal_user_data_t *ud) { gchar *tmp_dir; gchar *name; gint frame = ud->preview->frame; tmp_dir = ghb_get_tmp_dir(); name = g_strdup_printf("%s/live%02d", tmp_dir, ud->preview->frame); free(tmp_dir); if (ud->preview->current) g_free(ud->preview->current); ud->preview->current = name; if (ud->preview->encoded[frame] && g_file_test(name, G_FILE_TEST_IS_REGULAR)) { #if defined(_ENABLE_GST) if (ud->preview->pause) live_preview_start(ud); else live_preview_pause(ud); #endif } else { GhbValue *js; GhbValue *range, *dest; ud->preview->encode_frame = frame; js = ghb_value_dup(ud->settings); ghb_finalize_job(js); range = ghb_get_job_range_settings(js); dest = ghb_get_job_dest_settings(js); ghb_dict_set_string(dest, "File", name); ghb_dict_set_string(range, "Type", "preview"); ghb_dict_set_int(range, "Start", ud->preview->frame + 1); ghb_dict_set_int(range, "End", ghb_dict_get_int(ud->prefs, "live_duration") * 90000); ghb_dict_set_int(range, "SeekPoints", ghb_dict_get_int(ud->prefs, "preview_count")); GhbValue *job_dict = ghb_dict_get(js, "Job"); ud->preview->live_id = ghb_add_job(ghb_live_handle(), job_dict); ghb_start_live_encode(); ghb_value_free(&js); } }
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"); } }
static void subtitle_update_pref_lang(signal_user_data_t *ud, const iso639_lang_t *lang) { GtkLabel *label; GtkButton *button; gchar *str; const char * name = _("None"); const char * code = "und"; label = GTK_LABEL(GHB_WIDGET(ud->builder, "subtitle_preferred_language")); if (lang != NULL) { code = lang->iso639_2; if (strncmp(code, "und", 4)) { name = lang->native_name && lang->native_name[0] ? lang->native_name : lang->eng_name; } } str = g_strdup_printf(_("Preferred Language: %s"), name); gtk_label_set_text(label, str); g_free(str); ghb_dict_set_string(ud->settings, "PreferredLanguage", code); button = GTK_BUTTON(GHB_WIDGET(ud->builder, "SubtitleAddForeignAudioSubtitle")); str = g_strdup_printf(_("Add %s subtitle track if default audio is not %s"), name, name); gtk_button_set_label(button, str); g_free(str); // If there is no preferred language, hide options that require // a preferred language to be set. gboolean visible = !(lang == NULL || !strncmp(code, "und", 4)); gtk_widget_set_visible(GTK_WIDGET(button), visible); button = GTK_BUTTON(GHB_WIDGET(ud->builder, "SubtitleAddForeignAudioSearch")); gtk_widget_set_visible(GTK_WIDGET(button), visible); }
int ghb_set_video_preset(GhbValue *settings, int encoder, const char * preset) { const char * const * videoPresets; int ii, result = 0; videoPresets = hb_video_encoder_get_presets(encoder); for (ii = 0; preset && videoPresets && videoPresets[ii]; ii++) { if (!strcasecmp(preset, videoPresets[ii])) { ghb_dict_set_int(settings, "VideoPresetSlider", ii); result = 1; break; } } if (preset != NULL) { ghb_dict_set_string(settings, "VideoPreset", preset); } return result; }
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; }
static void x264_update_combo(signal_user_data_t *ud, const gchar *name, const gchar *val) { ghb_dict_set_string(ud->x264_priv, name, val); }
void ghb_update_x264Option(signal_user_data_t *ud, const char *opt) { ghb_dict_set_string(ud->settings, "x264Option", opt); g_idle_add((GSourceFunc)ghb_background_refresh_x264Option, ud); }
static GhbValue* subtitle_add_track( signal_user_data_t *ud, GhbValue *settings, const hb_title_t *title, int track, int mux, gboolean default_track, gboolean srt, gboolean burn, gboolean *burned) { int source = 0; if (track >= 0 && !srt) { hb_subtitle_t *subtitle = hb_list_item(title->list_subtitle, track); source = subtitle->source; } else if (srt) { source = SRTSUB; } burn |= !hb_subtitle_can_pass(source, mux); if (*burned && burn) { // Can only burn one. Skip others that must be burned. return NULL; } GhbValue *subsettings = ghb_dict_new(); ghb_dict_set_int(subsettings, "SubtitleTrack", track); ghb_dict_set_int(subsettings, "SubtitleSource", source); // Set default SRT settings const gchar *pref_lang, *dir; gchar *filename; pref_lang = ghb_dict_get_string(settings, "PreferredLanguage"); ghb_dict_set_string(subsettings, "SrtLanguage", pref_lang); ghb_dict_set_string(subsettings, "SrtCodeset", "UTF-8"); dir = ghb_dict_get_string(ud->prefs, "SrtDir"); filename = g_strdup_printf("%s/none", dir); ghb_dict_set_string(subsettings, "SrtFile", filename); g_free(filename); ghb_dict_set_int(subsettings, "SrtOffset", 0); subtitle_set_track_description(settings, subsettings); if (burn) { ghb_dict_set_bool(subsettings, "SubtitleBurned", TRUE); 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. *burned = TRUE; } } else { ghb_dict_set_bool(subsettings, "SubtitleBurned", FALSE); } if (track == -1) { // Foreign audio search "track" ghb_dict_set_bool(subsettings, "SubtitleForced", TRUE); } else { ghb_dict_set_bool(subsettings, "SubtitleForced", FALSE); } if (default_track) { ghb_dict_set_bool(subsettings, "SubtitleDefaultTrack", TRUE); } else { ghb_dict_set_bool(subsettings, "SubtitleDefaultTrack", FALSE); } subtitle_add_to_settings(settings, subsettings); return subsettings; }
static void subtitle_set_track_description(GhbValue *settings, GhbValue *subsettings) { char *desc = NULL; if (ghb_dict_get_int(subsettings, "SubtitleSource") == SRTSUB) { const gchar *filename, *code; const gchar *lang; lang = ghb_settings_combo_option(subsettings, "SrtLanguage"); code = ghb_dict_get_string(subsettings, "SrtCodeset"); filename = ghb_dict_get_string(subsettings, "SrtFile"); if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) { gchar *basename; basename = g_path_get_basename(filename); desc = g_strdup_printf("%s (%s)(SRT)(%s)", lang, code, basename); g_free(basename); } else { desc = g_strdup_printf("%s (%s)(SRT)", lang, code); } } else { int title_id, titleindex; const hb_title_t *title; int track; hb_subtitle_t *subtitle; title_id = ghb_dict_get_int(settings, "title"); title = ghb_lookup_title(title_id, &titleindex); track = ghb_dict_get_int(subsettings, "SubtitleTrack"); if (track < 0) { desc = g_strdup(_("Foreign Audio Search")); } else { subtitle = ghb_get_subtitle_info(title, track); if (subtitle != NULL) { desc = g_strdup_printf("%d - %s (%s)", track + 1, subtitle->lang, hb_subsource_name(subtitle->source)); } } } if (desc != NULL) { ghb_dict_set_string( subsettings, "SubtitleTrackDescription", desc); } else { ghb_dict_set_string( subsettings, "SubtitleTrackDescription", "Error!"); } g_free(desc); }