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;
133 g_debug("ghb_add_subtitle ()");
135 // Only allow up to 8 subtitle entries
136 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
137 if (subtitle_list == NULL)
139 subtitle_list = ghb_array_value_new(8);
140 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
142 count = ghb_array_len(subtitle_list);
143 ghb_array_append(subtitle_list, settings);
144 add_to_subtitle_list(ud, settings);
146 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
148 ghb_subtitle_exclusive_burn(ud, count);
152 add_all_pref_subtitles(signal_user_data_t *ud)
154 const GValue *pref_subtitle;
156 gint count, ii, track;
159 pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList");
160 count = ghb_array_len(pref_subtitle);
161 for (ii = 0; ii < count; ii++)
163 subtitle = ghb_value_dup(ghb_array_get_nth(pref_subtitle, ii));
164 lang = ghb_settings_get_string(subtitle, "SubtitleLanguage");
165 // If there are multiple subtitles using the same language, then
166 // select sequential tracks for each. The hash keeps track
167 // of the tracks used for each language.
168 track = ghb_find_pref_subtitle_track(lang);
172 // Add to subtitle list
173 ghb_settings_set_int(subtitle, "SubtitleTrack", track);
174 ghb_add_subtitle(ud, subtitle);
180 ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud)
183 GHashTable *track_indices;
184 gchar *lang, *pref_lang = NULL;
186 gint foreign_lang_index = -1;
188 const GValue *pref_subtitle;
192 g_debug("ghb_set_pref_subtitle %d", titleindex);
194 // Check to see if we need to add a subtitle track for foreign audio
195 // language films. A subtitle track will be added if:
197 // The first (default) audio track language does NOT match the users
198 // chosen Preferred Language AND the Preferred Language is NOT Any (und).
200 audio_lang = ghb_get_user_audio_lang(ud, titleindex, 0);
201 pref_lang = ghb_settings_get_string(ud->settings, "SourceAudioLang");
203 if (audio_lang != NULL && pref_lang != NULL &&
204 (strcmp(audio_lang, pref_lang) == 0 || strcmp("und", pref_lang) == 0))
210 track_indices = g_hash_table_new_full(g_str_hash, g_str_equal,
211 free_subtitle_key, free_subtitle_index_list);
213 ghb_ui_update(ud, "SubtitleTrack", ghb_int_value(0));
215 // Clear the subtitle list
216 ghb_clear_subtitle_list(ud);
219 add_all_pref_subtitles(ud);
223 // Find "best" subtitle based on subtitle preferences
224 pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList");
226 count = ghb_array_len(pref_subtitle);
228 for (ii = 0; ii < count; ii++)
230 subtitle = ghb_array_get_nth(pref_subtitle, ii);
231 lang = ghb_settings_get_string(subtitle, "SubtitleLanguage");
232 // If there are multiple subtitles using the same language, then
233 // select sequential tracks for each. The hash keeps track
234 // of the tracks used for each language.
235 track = ghb_find_subtitle_track(titleindex, lang, track_indices);
238 GValue *dup = ghb_value_dup(subtitle);
239 ghb_settings_set_int(dup, "SubtitleTrack", track);
240 if (foreign_lang_index < 0 && pref_lang != NULL &&
241 strcmp(lang, pref_lang) == 0)
243 foreign_lang_index = jj;
244 ghb_settings_take_value(dup, "SubtitleForced",
245 ghb_boolean_value_new(FALSE));
246 ghb_settings_take_value(dup, "SubtitleDefaultTrack",
247 ghb_boolean_value_new(TRUE));
249 ghb_add_subtitle(ud, dup);
254 if (foreign_lang_index < 0 && pref_lang != NULL)
259 track = ghb_find_subtitle_track(titleindex, pref_lang, track_indices);
262 burn = mustBurn(ud, track);
263 settings = ghb_dict_value_new();
264 ghb_settings_set_int(settings, "SubtitleTrack", track);
265 ghb_settings_take_value(settings, "SubtitleForced",
266 ghb_boolean_value_new(FALSE));
267 ghb_settings_take_value(settings, "SubtitleBurned",
268 ghb_boolean_value_new(burn));
269 ghb_settings_take_value(settings, "SubtitleDefaultTrack",
270 ghb_boolean_value_new(TRUE));
272 ghb_add_subtitle(ud, settings);
273 foreign_lang_index = jj;
276 if (foreign_lang_index >= 0)
278 GValue *subtitle_list;
281 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
282 subtitle = ghb_array_get_nth(subtitle_list, foreign_lang_index);
284 burn = ghb_settings_get_boolean(subtitle, "SubtitleBurned");
285 def = ghb_settings_get_boolean(subtitle, "SubtitleDefaultTrack");
287 ghb_subtitle_exclusive_burn(ud, foreign_lang_index);
289 ghb_subtitle_exclusive_default(ud, foreign_lang_index);
290 ghb_log("adding subtitle for foreign language audio: %s", audio_lang);
292 if (pref_lang != NULL)
294 if (audio_lang != NULL)
296 g_hash_table_destroy(track_indices);
300 ghb_selected_subtitle_row(signal_user_data_t *ud)
302 GtkTreeView *treeview;
303 GtkTreePath *treepath;
304 GtkTreeSelection *selection;
310 g_debug("ghb_selected_subtitle_row ()");
311 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
312 selection = gtk_tree_view_get_selection (treeview);
313 if (gtk_tree_selection_get_selected(selection, &store, &iter))
315 // Get the row number
316 treepath = gtk_tree_model_get_path (store, &iter);
317 indices = gtk_tree_path_get_indices (treepath);
319 gtk_tree_path_free(treepath);
325 ghb_selected_subtitle_settings(signal_user_data_t *ud)
327 GtkTreeView *treeview;
328 GtkTreePath *treepath;
329 GtkTreeSelection *selection;
334 GValue *settings = NULL;
335 const GValue *subtitle_list;
337 g_debug("get_selected_settings ()");
338 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
339 selection = gtk_tree_view_get_selection (treeview);
340 if (gtk_tree_selection_get_selected(selection, &store, &iter))
342 // Get the row number
343 treepath = gtk_tree_model_get_path (store, &iter);
344 indices = gtk_tree_path_get_indices (treepath);
346 gtk_tree_path_free(treepath);
347 // find subtitle settings
348 if (row < 0) return NULL;
349 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
350 if (row >= ghb_array_len(subtitle_list))
352 settings = ghb_array_get_nth(subtitle_list, row);
358 subtitle_forced_toggled_cb(
359 GtkCellRendererToggle *cell,
361 signal_user_data_t *ud)
370 GValue *subtitle_list, *settings;
373 g_debug("forced toggled");
374 tp = gtk_tree_path_new_from_string (path);
375 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
376 g_return_if_fail(tv != NULL);
377 tm = gtk_tree_view_get_model(tv);
378 g_return_if_fail(tm != NULL);
379 gtk_tree_model_get_iter(tm, &ti, tp);
380 gtk_tree_model_get(tm, &ti, 1, &active, -1);
383 // Get the row number
384 indices = gtk_tree_path_get_indices (tp);
386 gtk_tree_path_free(tp);
388 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
390 if (row < 0 || row >= ghb_array_len(subtitle_list))
393 settings = ghb_array_get_nth(subtitle_list, row);
394 track = ghb_settings_combo_int(settings, "SubtitleTrack");
396 source = ghb_subtitle_track_source(ud, track);
397 if (source != VOBSUB)
400 ghb_settings_set_boolean(settings, "SubtitleForced", active);
401 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 1, active, -1);
405 subtitle_burned_toggled_cb(
406 GtkCellRendererToggle *cell,
408 signal_user_data_t *ud)
417 GValue *subtitle_list;
418 gint count, track, source;
421 g_debug("burned toggled");
422 tp = gtk_tree_path_new_from_string (path);
423 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
424 g_return_if_fail(tv != NULL);
425 tm = gtk_tree_view_get_model(tv);
426 g_return_if_fail(tm != NULL);
427 gtk_tree_model_get_iter(tm, &ti, tp);
428 gtk_tree_model_get(tm, &ti, 2, &active, -1);
431 // Get the row number
432 indices = gtk_tree_path_get_indices (tp);
434 gtk_tree_path_free(tp);
436 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
437 count = ghb_array_len(subtitle_list);
438 if (row < 0 || row >= count)
441 settings = ghb_array_get_nth(subtitle_list, row);
442 track = ghb_settings_combo_int(settings, "SubtitleTrack");
444 source = ghb_subtitle_track_source(ud, track);
445 if (source != VOBSUB)
448 if (!active && mustBurn(ud, track))
451 ghb_settings_set_boolean(settings, "SubtitleBurned", active);
453 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, active, -1);
456 ghb_subtitle_exclusive_burn(ud, row);
460 subtitle_default_toggled_cb(
461 GtkCellRendererToggle *cell,
463 signal_user_data_t *ud)
472 GValue *subtitle_list;
476 g_debug("default toggled");
477 tp = gtk_tree_path_new_from_string (path);
478 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
479 g_return_if_fail(tv != NULL);
480 tm = gtk_tree_view_get_model(tv);
481 g_return_if_fail(tm != NULL);
482 gtk_tree_model_get_iter(tm, &ti, tp);
483 gtk_tree_model_get(tm, &ti, 3, &active, -1);
486 // Get the row number
487 indices = gtk_tree_path_get_indices (tp);
489 gtk_tree_path_free(tp);
491 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
492 count = ghb_array_len(subtitle_list);
493 if (row < 0 || row >= count)
496 settings = ghb_array_get_nth(subtitle_list, row);
497 track = ghb_settings_combo_int(settings, "SubtitleTrack");
499 ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", active);
501 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 3, active, -1);
502 // allow only one default
503 ghb_subtitle_exclusive_default(ud, row);
507 subtitle_list_refresh_selected(signal_user_data_t *ud)
509 GtkTreeView *treeview;
510 GtkTreePath *treepath;
511 GtkTreeSelection *selection;
516 GValue *settings = NULL;
517 const GValue *subtitle_list;
519 g_debug("subtitle_list_refresh_selected ()");
520 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
521 selection = gtk_tree_view_get_selection (treeview);
522 if (gtk_tree_selection_get_selected(selection, &store, &iter))
524 const gchar *track, *source;
525 gboolean forced, burned, def;
529 // Get the row number
530 treepath = gtk_tree_model_get_path (store, &iter);
531 indices = gtk_tree_path_get_indices (treepath);
533 gtk_tree_path_free(treepath);
534 // find audio settings
536 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
537 if (row >= ghb_array_len(subtitle_list))
539 settings = ghb_array_get_nth(subtitle_list, row);
541 track = ghb_settings_combo_option(settings, "SubtitleTrack");
542 forced = ghb_settings_get_boolean(settings, "SubtitleForced");
543 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
544 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
546 s_track = ghb_settings_get_string(settings, "SubtitleTrack");
547 i_track = ghb_settings_get_int(settings, "SubtitleTrack");
548 source = ghb_subtitle_track_source_name(ud, i_track);
551 i_source = ghb_subtitle_track_source(ud, i_track);
552 if (i_source != VOBSUB)
554 // Force and burn only apply to VOBSUBS
557 ghb_settings_set_boolean(settings, "SubtitleForced", forced);
558 ghb_settings_set_boolean(settings, "SubtitleBurned", burned);
561 gtk_list_store_set(GTK_LIST_STORE(store), &iter,
562 // These are displayed in list
568 // These are used to set combo box values when a list item is selected
573 ghb_subtitle_exclusive_burn(ud, row);
578 subtitle_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
582 g_debug("subtitle_track_changed_cb ()");
583 ghb_check_dependency(ud, widget);
584 settings = ghb_selected_subtitle_settings(ud);
585 if (settings != NULL)
587 ghb_widget_to_setting(settings, widget);
588 subtitle_list_refresh_selected(ud);
594 ghb_clear_subtitle_list(signal_user_data_t *ud)
596 GtkTreeView *treeview;
598 GValue *subtitle_list;
600 g_debug("clear_subtitle_list ()");
601 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
602 if (subtitle_list == NULL)
604 subtitle_list = ghb_array_value_new(8);
605 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
608 ghb_array_value_reset(subtitle_list, 8);
609 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
610 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
611 gtk_list_store_clear (store);
615 add_to_subtitle_list(
616 signal_user_data_t *ud,
619 GtkTreeView *treeview;
622 GtkTreeSelection *selection;
623 const gchar *track, *source;
624 gboolean forced, burned, def;
628 g_debug("add_to_subtitle_list ()");
629 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
630 selection = gtk_tree_view_get_selection (treeview);
631 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
633 track = ghb_settings_combo_option(settings, "SubtitleTrack");
634 forced = ghb_settings_get_boolean(settings, "SubtitleForced");
635 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
636 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
638 s_track = ghb_settings_get_string(settings, "SubtitleTrack");
639 i_track = ghb_settings_get_int(settings, "SubtitleTrack");
640 source = ghb_subtitle_track_source_name(ud, i_track);
642 gtk_list_store_append(store, &iter);
643 gtk_list_store_set(store, &iter,
644 // These are displayed in list
650 // These are used to set combo box values when a list item is selected
653 gtk_tree_selection_select_iter(selection, &iter);
658 subtitle_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
664 g_debug("subtitle_list_selection_changed_cb ()");
665 if (gtk_tree_selection_get_selected(selection, &store, &iter))
669 gtk_tree_model_get(store, &iter, 5, &track, -1);
670 ghb_ui_update(ud, "SubtitleTrack", ghb_string_value(track));
672 widget = GHB_WIDGET (ud->builder, "subtitle_remove");
673 gtk_widget_set_sensitive(widget, TRUE);
678 subtitle_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
680 // Add the current subtitle settings to the list.
683 GValue *subtitle_list;
684 gboolean burned = FALSE;
687 g_debug("subtitle_add_clicked_cb ()");
688 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
689 if (subtitle_list == NULL)
691 subtitle_list = ghb_array_value_new(8);
692 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
694 count = ghb_array_len(subtitle_list);
695 // Don't allow more than 99
696 // This is a had limit imposed by libhb/sync.c:GetFifoForId()
700 track = ghb_settings_get_int(ud->settings, "SubtitleTrack");
702 if (mustBurn(ud, track))
706 settings = ghb_dict_value_new();
707 ghb_settings_set_int(settings, "SubtitleTrack", track);
708 ghb_settings_take_value(settings, "SubtitleForced",
709 ghb_boolean_value_new(FALSE));
710 ghb_settings_take_value(settings, "SubtitleBurned",
711 ghb_boolean_value_new(burned));
712 ghb_settings_take_value(settings, "SubtitleDefaultTrack",
713 ghb_boolean_value_new(FALSE));
715 ghb_array_append(subtitle_list, settings);
716 add_to_subtitle_list(ud, settings);
718 ghb_subtitle_exclusive_burn(ud, count);
722 widget = GHB_WIDGET (ud->builder, "subtitle_add");
723 gtk_widget_set_sensitive(widget, FALSE);
728 subtitle_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
730 GtkTreeView *treeview;
731 GtkTreePath *treepath;
732 GtkTreeSelection *selection;
734 GtkTreeIter iter, nextIter;
737 GValue *subtitle_list;
739 g_debug("subtitle_remove_clicked_cb ()");
740 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
741 selection = gtk_tree_view_get_selection (treeview);
742 if (gtk_tree_selection_get_selected(selection, &store, &iter))
745 if (!gtk_tree_model_iter_next(store, &nextIter))
748 if (gtk_tree_model_get_iter_first(store, &nextIter))
750 gtk_tree_selection_select_iter (selection, &nextIter);
755 gtk_tree_selection_select_iter (selection, &nextIter);
757 // Get the row number
758 treepath = gtk_tree_model_get_path (store, &iter);
759 indices = gtk_tree_path_get_indices (treepath);
761 gtk_tree_path_free(treepath);
762 // Remove the selected item
763 gtk_list_store_remove (GTK_LIST_STORE(store), &iter);
764 // remove from subtitle settings list
766 widget = GHB_WIDGET (ud->builder, "subtitle_add");
767 gtk_widget_set_sensitive(widget, TRUE);
768 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
769 if (row >= ghb_array_len(subtitle_list))
771 GValue *old = ghb_array_get_nth(subtitle_list, row);
773 ghb_array_remove(subtitle_list, row);
778 ghb_subtitle_prune(signal_user_data_t *ud)
783 GValue *subtitle_list, *settings;
784 gint count, ii, track;
786 gint first_track = 0, one_burned = 0;
788 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
789 if (subtitle_list == NULL)
791 count = ghb_array_len(subtitle_list);
793 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
794 g_return_if_fail(tv != NULL);
795 tm = gtk_tree_view_get_model(tv);
796 for (ii = count-1; ii >= 0; ii--)
798 settings = ghb_array_get_nth(subtitle_list, ii);
799 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
800 track = ghb_settings_combo_int(settings, "SubtitleTrack");
801 if (!burned && mustBurn(ud, track))
803 gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii);
804 gtk_list_store_remove (GTK_LIST_STORE(tm), &ti);
805 ghb_array_remove(subtitle_list, ii);
815 ghb_subtitle_exclusive_burn(ud, first_track);
820 ghb_reset_subtitles(signal_user_data_t *ud, GValue *settings)
827 g_debug("ghb_reset_subtitles");
828 ghb_clear_subtitle_list(ud);
829 titleindex = ghb_settings_combo_int(ud->settings, "title");
833 slist = ghb_settings_get_value(settings, "subtitle_list");
834 count = ghb_array_len(slist);
835 for (ii = 0; ii < count; ii++)
837 subtitle = ghb_value_dup(ghb_array_get_nth(slist, ii));
838 ghb_add_subtitle(ud, subtitle);