1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) John Stebbins 2008 <stebbins@stebbins>
6 * subtitlehandler.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)
17 #include "hb-backend.h"
19 #include "callbacks.h"
22 #include "audiohandler.h"
23 #include "subtitlehandler.h"
25 static void add_to_subtitle_list(signal_user_data_t *ud, GValue *settings);
28 free_subtitle_index_list(gpointer data)
34 free_subtitle_key(gpointer data)
41 mustBurn(signal_user_data_t *ud, gint track)
45 mux = ghb_settings_combo_int(ud->settings, "FileFormat");
46 if (mux == HB_MUX_MP4)
50 // MP4 can only handle burned vobsubs. make sure there isn't
51 // already something burned in the list
52 source = ghb_subtitle_track_source(ud, track);
62 ghb_subtitle_exclusive_burn(signal_user_data_t *ud, gint index)
64 GValue *subtitle_list;
72 g_debug("ghb_subtitle_exclusive_burn");
73 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
74 count = ghb_array_len(subtitle_list);
75 for (ii = 0; ii < count; ii++)
77 settings = ghb_array_get_nth(subtitle_list, ii);
78 tt = ghb_settings_combo_int(settings, "SubtitleTrack");
79 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
81 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
82 g_return_if_fail(tv != NULL);
83 tm = gtk_tree_view_get_model(tv);
84 gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii);
85 if (burned && ii != index && !mustBurn(ud, tt))
87 ghb_settings_set_boolean(settings, "SubtitleBurned", FALSE);
88 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, FALSE, -1);
94 ghb_subtitle_exclusive_default(signal_user_data_t *ud, gint index)
96 GValue *subtitle_list;
104 g_debug("ghb_subtitle_exclusive_default");
105 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
106 count = ghb_array_len(subtitle_list);
107 for (ii = 0; ii < count; ii++)
109 settings = ghb_array_get_nth(subtitle_list, ii);
110 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
112 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
113 g_return_if_fail(tv != NULL);
114 tm = gtk_tree_view_get_model(tv);
115 gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii);
116 if (def && ii != index)
119 ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", FALSE);
120 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 3, FALSE, -1);
126 ghb_add_subtitle(signal_user_data_t *ud, GValue *settings)
128 // Add the current subtitle settings to the list.
129 GValue *subtitle_list;
135 g_debug("ghb_add_subtitle ()");
137 // Add the long track description so the queue can access it
138 // when a different title is selected.
139 track = ghb_settings_combo_option(settings, "SubtitleTrack");
140 ghb_settings_set_string(settings, "SubtitleTrackDescription", track);
142 tt = ghb_settings_get_int(settings, "SubtitleTrack");
143 source = ghb_subtitle_track_source(ud, tt);
144 ghb_settings_set_int(settings, "SubtitleSource", source);
146 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
147 if (subtitle_list == NULL)
149 subtitle_list = ghb_array_value_new(8);
150 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
152 count = ghb_array_len(subtitle_list);
154 // Don't allow more than 99
155 // This is a had limit imposed by libhb/sync.c:GetFifoForId()
158 ghb_value_free(settings);
162 ghb_array_append(subtitle_list, settings);
163 add_to_subtitle_list(ud, settings);
165 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
167 ghb_subtitle_exclusive_burn(ud, count);
171 widget = GHB_WIDGET (ud->builder, "subtitle_add");
172 gtk_widget_set_sensitive(widget, FALSE);
178 add_all_pref_subtitles(signal_user_data_t *ud)
180 const GValue *pref_subtitle;
182 gint count, ii, track;
185 pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList");
186 count = ghb_array_len(pref_subtitle);
187 for (ii = 0; ii < count; ii++)
189 subtitle = ghb_value_dup(ghb_array_get_nth(pref_subtitle, ii));
190 lang = ghb_settings_get_string(subtitle, "SubtitleLanguage");
191 // If there are multiple subtitles using the same language, then
192 // select sequential tracks for each. The hash keeps track
193 // of the tracks used for each language.
194 track = ghb_find_pref_subtitle_track(lang);
198 // Add to subtitle list
199 ghb_settings_set_int(subtitle, "SubtitleTrack", track);
200 ghb_add_subtitle(ud, subtitle);
206 ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud)
209 GHashTable *track_indices;
210 gchar *lang, *pref_lang = NULL;
212 gint foreign_lang_index = -1;
214 const GValue *pref_subtitle;
218 g_debug("ghb_set_pref_subtitle %d", titleindex);
220 // Check to see if we need to add a subtitle track for foreign audio
221 // language films. A subtitle track will be added if:
223 // The first (default) audio track language does NOT match the users
224 // chosen Preferred Language AND the Preferred Language is NOT Any (und).
226 audio_lang = ghb_get_user_audio_lang(ud, titleindex, 0);
227 pref_lang = ghb_settings_get_string(ud->settings, "PreferredLanguage");
229 if (audio_lang != NULL && pref_lang != NULL &&
230 (strcmp(audio_lang, pref_lang) == 0 || strcmp("und", pref_lang) == 0))
236 track_indices = g_hash_table_new_full(g_str_hash, g_str_equal,
237 free_subtitle_key, free_subtitle_index_list);
239 ghb_ui_update(ud, "SubtitleTrack", ghb_int_value(0));
241 // Clear the subtitle list
242 ghb_clear_subtitle_list(ud);
245 add_all_pref_subtitles(ud);
249 // Find "best" subtitle based on subtitle preferences
250 pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList");
252 count = ghb_array_len(pref_subtitle);
254 for (ii = 0; ii < count; ii++)
256 subtitle = ghb_array_get_nth(pref_subtitle, ii);
257 lang = ghb_settings_get_string(subtitle, "SubtitleLanguage");
258 // If there are multiple subtitles using the same language, then
259 // select sequential tracks for each. The hash keeps track
260 // of the tracks used for each language.
261 track = ghb_find_subtitle_track(titleindex, lang, track_indices);
264 GValue *dup = ghb_value_dup(subtitle);
265 ghb_settings_set_int(dup, "SubtitleTrack", track);
266 if (foreign_lang_index < 0 && pref_lang != NULL &&
267 strcmp(lang, pref_lang) == 0)
269 foreign_lang_index = jj;
270 ghb_settings_take_value(dup, "SubtitleForced",
271 ghb_boolean_value_new(FALSE));
272 ghb_settings_take_value(dup, "SubtitleDefaultTrack",
273 ghb_boolean_value_new(TRUE));
275 ghb_add_subtitle(ud, dup);
280 if (foreign_lang_index < 0 && pref_lang != NULL)
285 track = ghb_find_subtitle_track(titleindex, pref_lang, track_indices);
288 burn = mustBurn(ud, track);
289 settings = ghb_dict_value_new();
290 ghb_settings_set_int(settings, "SubtitleTrack", track);
291 ghb_settings_take_value(settings, "SubtitleForced",
292 ghb_boolean_value_new(FALSE));
293 ghb_settings_take_value(settings, "SubtitleBurned",
294 ghb_boolean_value_new(burn));
295 ghb_settings_take_value(settings, "SubtitleDefaultTrack",
296 ghb_boolean_value_new(TRUE));
298 ghb_add_subtitle(ud, settings);
299 foreign_lang_index = jj;
302 if (foreign_lang_index >= 0)
304 GValue *subtitle_list;
307 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
308 subtitle = ghb_array_get_nth(subtitle_list, foreign_lang_index);
310 burn = ghb_settings_get_boolean(subtitle, "SubtitleBurned");
311 def = ghb_settings_get_boolean(subtitle, "SubtitleDefaultTrack");
313 ghb_subtitle_exclusive_burn(ud, foreign_lang_index);
315 ghb_subtitle_exclusive_default(ud, foreign_lang_index);
316 ghb_log("adding subtitle for foreign language audio: %s", audio_lang);
318 if (pref_lang != NULL)
320 if (audio_lang != NULL)
322 g_hash_table_destroy(track_indices);
326 ghb_selected_subtitle_row(signal_user_data_t *ud)
328 GtkTreeView *treeview;
329 GtkTreePath *treepath;
330 GtkTreeSelection *selection;
336 g_debug("ghb_selected_subtitle_row ()");
337 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
338 selection = gtk_tree_view_get_selection (treeview);
339 if (gtk_tree_selection_get_selected(selection, &store, &iter))
341 // Get the row number
342 treepath = gtk_tree_model_get_path (store, &iter);
343 indices = gtk_tree_path_get_indices (treepath);
345 gtk_tree_path_free(treepath);
351 ghb_selected_subtitle_settings(signal_user_data_t *ud)
353 GtkTreeView *treeview;
354 GtkTreePath *treepath;
355 GtkTreeSelection *selection;
360 GValue *settings = NULL;
361 const GValue *subtitle_list;
363 g_debug("get_selected_settings ()");
364 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
365 selection = gtk_tree_view_get_selection (treeview);
366 if (gtk_tree_selection_get_selected(selection, &store, &iter))
368 // Get the row number
369 treepath = gtk_tree_model_get_path (store, &iter);
370 indices = gtk_tree_path_get_indices (treepath);
372 gtk_tree_path_free(treepath);
373 // find subtitle settings
374 if (row < 0) return NULL;
375 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
376 if (row >= ghb_array_len(subtitle_list))
378 settings = ghb_array_get_nth(subtitle_list, row);
384 subtitle_forced_toggled_cb(
385 GtkCellRendererToggle *cell,
387 signal_user_data_t *ud)
396 GValue *subtitle_list, *settings;
399 g_debug("forced toggled");
400 tp = gtk_tree_path_new_from_string (path);
401 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
402 g_return_if_fail(tv != NULL);
403 tm = gtk_tree_view_get_model(tv);
404 g_return_if_fail(tm != NULL);
405 gtk_tree_model_get_iter(tm, &ti, tp);
406 gtk_tree_model_get(tm, &ti, 1, &active, -1);
409 // Get the row number
410 indices = gtk_tree_path_get_indices (tp);
412 gtk_tree_path_free(tp);
414 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
416 if (row < 0 || row >= ghb_array_len(subtitle_list))
419 settings = ghb_array_get_nth(subtitle_list, row);
420 track = ghb_settings_combo_int(settings, "SubtitleTrack");
422 source = ghb_subtitle_track_source(ud, track);
423 if (source != VOBSUB)
426 ghb_settings_set_boolean(settings, "SubtitleForced", active);
427 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 1, active, -1);
432 subtitle_burned_toggled_cb(
433 GtkCellRendererToggle *cell,
435 signal_user_data_t *ud)
444 GValue *subtitle_list;
445 gint count, track, source;
448 g_debug("burned toggled");
449 tp = gtk_tree_path_new_from_string (path);
450 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
451 g_return_if_fail(tv != NULL);
452 tm = gtk_tree_view_get_model(tv);
453 g_return_if_fail(tm != NULL);
454 gtk_tree_model_get_iter(tm, &ti, tp);
455 gtk_tree_model_get(tm, &ti, 2, &active, -1);
458 // Get the row number
459 indices = gtk_tree_path_get_indices (tp);
461 gtk_tree_path_free(tp);
463 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
464 count = ghb_array_len(subtitle_list);
465 if (row < 0 || row >= count)
468 settings = ghb_array_get_nth(subtitle_list, row);
469 track = ghb_settings_combo_int(settings, "SubtitleTrack");
471 source = ghb_subtitle_track_source(ud, track);
472 if (source != VOBSUB)
475 if (!active && mustBurn(ud, track))
478 ghb_settings_set_boolean(settings, "SubtitleBurned", active);
480 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, active, -1);
483 ghb_subtitle_exclusive_burn(ud, row);
488 subtitle_default_toggled_cb(
489 GtkCellRendererToggle *cell,
491 signal_user_data_t *ud)
500 GValue *subtitle_list;
504 g_debug("default toggled");
505 tp = gtk_tree_path_new_from_string (path);
506 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
507 g_return_if_fail(tv != NULL);
508 tm = gtk_tree_view_get_model(tv);
509 g_return_if_fail(tm != NULL);
510 gtk_tree_model_get_iter(tm, &ti, tp);
511 gtk_tree_model_get(tm, &ti, 3, &active, -1);
514 // Get the row number
515 indices = gtk_tree_path_get_indices (tp);
517 gtk_tree_path_free(tp);
519 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
520 count = ghb_array_len(subtitle_list);
521 if (row < 0 || row >= count)
524 settings = ghb_array_get_nth(subtitle_list, row);
525 track = ghb_settings_combo_int(settings, "SubtitleTrack");
527 ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", active);
529 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 3, active, -1);
530 // allow only one default
531 ghb_subtitle_exclusive_default(ud, row);
536 subtitle_list_refresh_selected(signal_user_data_t *ud)
538 GtkTreeView *treeview;
539 GtkTreePath *treepath;
540 GtkTreeSelection *selection;
545 GValue *settings = NULL;
546 const GValue *subtitle_list;
548 g_debug("subtitle_list_refresh_selected ()");
549 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
550 selection = gtk_tree_view_get_selection (treeview);
551 if (gtk_tree_selection_get_selected(selection, &store, &iter))
553 const gchar *track, *source;
554 gboolean forced, burned, def;
558 // Get the row number
559 treepath = gtk_tree_model_get_path (store, &iter);
560 indices = gtk_tree_path_get_indices (treepath);
562 gtk_tree_path_free(treepath);
563 // find audio settings
565 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
566 if (row >= ghb_array_len(subtitle_list))
568 settings = ghb_array_get_nth(subtitle_list, row);
570 track = ghb_settings_combo_option(settings, "SubtitleTrack");
571 forced = ghb_settings_get_boolean(settings, "SubtitleForced");
572 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
573 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
575 s_track = ghb_settings_get_string(settings, "SubtitleTrack");
576 i_track = ghb_settings_get_int(settings, "SubtitleTrack");
577 source = ghb_subtitle_track_source_name(ud, i_track);
580 i_source = ghb_subtitle_track_source(ud, i_track);
581 if (i_source != VOBSUB)
583 // Force and burn only apply to VOBSUBS
586 ghb_settings_set_boolean(settings, "SubtitleForced", forced);
587 ghb_settings_set_boolean(settings, "SubtitleBurned", burned);
590 gtk_list_store_set(GTK_LIST_STORE(store), &iter,
591 // These are displayed in list
597 // These are used to set combo box values when a list item is selected
602 ghb_subtitle_exclusive_burn(ud, row);
607 subtitle_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
611 g_debug("subtitle_track_changed_cb ()");
612 ghb_check_dependency(ud, widget);
613 ghb_widget_to_setting(ud->settings, widget);
614 settings = ghb_selected_subtitle_settings(ud);
615 if (settings != NULL)
620 ghb_widget_to_setting(settings, widget);
621 subtitle_list_refresh_selected(ud);
622 track = ghb_settings_combo_option(settings, "SubtitleTrack");
623 ghb_settings_set_string(settings, "SubtitleTrackDescription", track);
624 tt = ghb_settings_get_int(settings, "SubtitleTrack");
625 source = ghb_subtitle_track_source(ud, tt);
626 ghb_settings_set_int(settings, "SubtitleSource", source);
633 ghb_clear_subtitle_list(signal_user_data_t *ud)
635 GtkTreeView *treeview;
637 GValue *subtitle_list;
639 g_debug("clear_subtitle_list ()");
640 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
641 if (subtitle_list == NULL)
643 subtitle_list = ghb_array_value_new(8);
644 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
647 ghb_array_value_reset(subtitle_list, 8);
648 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
649 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
650 gtk_list_store_clear (store);
654 add_to_subtitle_list(
655 signal_user_data_t *ud,
658 GtkTreeView *treeview;
661 GtkTreeSelection *selection;
662 const gchar *track, *source;
663 gboolean forced, burned, def;
667 g_debug("add_to_subtitle_list ()");
668 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
669 selection = gtk_tree_view_get_selection (treeview);
670 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
672 track = ghb_settings_combo_option(settings, "SubtitleTrack");
673 forced = ghb_settings_get_boolean(settings, "SubtitleForced");
674 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
675 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
677 s_track = ghb_settings_get_string(settings, "SubtitleTrack");
678 i_track = ghb_settings_get_int(settings, "SubtitleTrack");
679 source = ghb_subtitle_track_source_name(ud, i_track);
681 gtk_list_store_append(store, &iter);
682 gtk_list_store_set(store, &iter,
683 // These are displayed in list
689 // These are used to set combo box values when a list item is selected
692 gtk_tree_selection_select_iter(selection, &iter);
697 subtitle_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
703 g_debug("subtitle_list_selection_changed_cb ()");
704 if (gtk_tree_selection_get_selected(selection, &store, &iter))
708 gtk_tree_model_get(store, &iter, 5, &track, -1);
709 ghb_ui_update(ud, "SubtitleTrack", ghb_string_value(track));
711 widget = GHB_WIDGET (ud->builder, "subtitle_remove");
712 gtk_widget_set_sensitive(widget, TRUE);
717 subtitle_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
719 // Add the current subtitle settings to the list.
721 gboolean burned = FALSE;
724 g_debug("subtitle_add_clicked_cb ()");
726 track = ghb_settings_get_int(ud->settings, "SubtitleTrack");
727 if (mustBurn(ud, track))
731 settings = ghb_dict_value_new();
732 ghb_settings_set_int(settings, "SubtitleTrack", track);
733 ghb_settings_take_value(settings, "SubtitleForced",
734 ghb_boolean_value_new(FALSE));
735 ghb_settings_take_value(settings, "SubtitleBurned",
736 ghb_boolean_value_new(burned));
737 ghb_settings_take_value(settings, "SubtitleDefaultTrack",
738 ghb_boolean_value_new(FALSE));
740 ghb_add_subtitle(ud, settings);
744 subtitle_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
746 GtkTreeView *treeview;
747 GtkTreePath *treepath;
748 GtkTreeSelection *selection;
750 GtkTreeIter iter, nextIter;
753 GValue *subtitle_list;
755 g_debug("subtitle_remove_clicked_cb ()");
756 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
757 selection = gtk_tree_view_get_selection (treeview);
758 if (gtk_tree_selection_get_selected(selection, &store, &iter))
761 if (!gtk_tree_model_iter_next(store, &nextIter))
764 if (gtk_tree_model_get_iter_first(store, &nextIter))
766 gtk_tree_selection_select_iter (selection, &nextIter);
771 gtk_tree_selection_select_iter (selection, &nextIter);
773 // Get the row number
774 treepath = gtk_tree_model_get_path (store, &iter);
775 indices = gtk_tree_path_get_indices (treepath);
777 gtk_tree_path_free(treepath);
778 // Remove the selected item
779 gtk_list_store_remove (GTK_LIST_STORE(store), &iter);
780 // remove from subtitle settings list
782 widget = GHB_WIDGET (ud->builder, "subtitle_add");
783 gtk_widget_set_sensitive(widget, TRUE);
784 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
785 if (row >= ghb_array_len(subtitle_list))
787 GValue *old = ghb_array_get_nth(subtitle_list, row);
789 ghb_array_remove(subtitle_list, row);
795 ghb_subtitle_prune(signal_user_data_t *ud)
800 GValue *subtitle_list, *settings;
801 gint count, ii, track;
803 gint first_track = 0, one_burned = 0;
805 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
806 if (subtitle_list == NULL)
808 count = ghb_array_len(subtitle_list);
810 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
811 g_return_if_fail(tv != NULL);
812 tm = gtk_tree_view_get_model(tv);
813 for (ii = count-1; ii >= 0; ii--)
815 settings = ghb_array_get_nth(subtitle_list, ii);
816 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
817 track = ghb_settings_combo_int(settings, "SubtitleTrack");
818 if (!burned && mustBurn(ud, track))
820 gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii);
821 gtk_list_store_remove (GTK_LIST_STORE(tm), &ti);
822 ghb_array_remove(subtitle_list, ii);
832 ghb_subtitle_exclusive_burn(ud, first_track);
837 ghb_reset_subtitles(signal_user_data_t *ud, GValue *settings)
844 g_debug("ghb_reset_subtitles");
845 ghb_clear_subtitle_list(ud);
846 titleindex = ghb_settings_combo_int(ud->settings, "title");
850 slist = ghb_settings_get_value(settings, "subtitle_list");
851 count = ghb_array_len(slist);
852 for (ii = 0; ii < count; ii++)
854 subtitle = ghb_value_dup(ghb_array_get_nth(slist, ii));
855 ghb_add_subtitle(ud, subtitle);