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);
177 add_all_pref_subtitles(signal_user_data_t *ud)
179 const GValue *pref_subtitle;
181 gint count, ii, track;
184 pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList");
185 count = ghb_array_len(pref_subtitle);
186 for (ii = 0; ii < count; ii++)
188 subtitle = ghb_value_dup(ghb_array_get_nth(pref_subtitle, ii));
189 lang = ghb_settings_get_string(subtitle, "SubtitleLanguage");
190 // If there are multiple subtitles using the same language, then
191 // select sequential tracks for each. The hash keeps track
192 // of the tracks used for each language.
193 track = ghb_find_pref_subtitle_track(lang);
197 // Add to subtitle list
198 ghb_settings_set_int(subtitle, "SubtitleTrack", track);
199 ghb_add_subtitle(ud, subtitle);
205 ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud)
208 GHashTable *track_indices;
209 gchar *lang, *pref_lang = NULL;
211 gint foreign_lang_index = -1;
213 const GValue *pref_subtitle;
217 g_debug("ghb_set_pref_subtitle %d", titleindex);
219 // Check to see if we need to add a subtitle track for foreign audio
220 // language films. A subtitle track will be added if:
222 // The first (default) audio track language does NOT match the users
223 // chosen Preferred Language AND the Preferred Language is NOT Any (und).
225 audio_lang = ghb_get_user_audio_lang(ud, titleindex, 0);
226 pref_lang = ghb_settings_get_string(ud->settings, "SourceAudioLang");
228 if (audio_lang != NULL && pref_lang != NULL &&
229 (strcmp(audio_lang, pref_lang) == 0 || strcmp("und", pref_lang) == 0))
235 track_indices = g_hash_table_new_full(g_str_hash, g_str_equal,
236 free_subtitle_key, free_subtitle_index_list);
238 ghb_ui_update(ud, "SubtitleTrack", ghb_int_value(0));
240 // Clear the subtitle list
241 ghb_clear_subtitle_list(ud);
244 add_all_pref_subtitles(ud);
248 // Find "best" subtitle based on subtitle preferences
249 pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList");
251 count = ghb_array_len(pref_subtitle);
253 for (ii = 0; ii < count; ii++)
255 subtitle = ghb_array_get_nth(pref_subtitle, ii);
256 lang = ghb_settings_get_string(subtitle, "SubtitleLanguage");
257 // If there are multiple subtitles using the same language, then
258 // select sequential tracks for each. The hash keeps track
259 // of the tracks used for each language.
260 track = ghb_find_subtitle_track(titleindex, lang, track_indices);
263 GValue *dup = ghb_value_dup(subtitle);
264 ghb_settings_set_int(dup, "SubtitleTrack", track);
265 if (foreign_lang_index < 0 && pref_lang != NULL &&
266 strcmp(lang, pref_lang) == 0)
268 foreign_lang_index = jj;
269 ghb_settings_take_value(dup, "SubtitleForced",
270 ghb_boolean_value_new(FALSE));
271 ghb_settings_take_value(dup, "SubtitleDefaultTrack",
272 ghb_boolean_value_new(TRUE));
274 ghb_add_subtitle(ud, dup);
279 if (foreign_lang_index < 0 && pref_lang != NULL)
284 track = ghb_find_subtitle_track(titleindex, pref_lang, track_indices);
287 burn = mustBurn(ud, track);
288 settings = ghb_dict_value_new();
289 ghb_settings_set_int(settings, "SubtitleTrack", track);
290 ghb_settings_take_value(settings, "SubtitleForced",
291 ghb_boolean_value_new(FALSE));
292 ghb_settings_take_value(settings, "SubtitleBurned",
293 ghb_boolean_value_new(burn));
294 ghb_settings_take_value(settings, "SubtitleDefaultTrack",
295 ghb_boolean_value_new(TRUE));
297 ghb_add_subtitle(ud, settings);
298 foreign_lang_index = jj;
301 if (foreign_lang_index >= 0)
303 GValue *subtitle_list;
306 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
307 subtitle = ghb_array_get_nth(subtitle_list, foreign_lang_index);
309 burn = ghb_settings_get_boolean(subtitle, "SubtitleBurned");
310 def = ghb_settings_get_boolean(subtitle, "SubtitleDefaultTrack");
312 ghb_subtitle_exclusive_burn(ud, foreign_lang_index);
314 ghb_subtitle_exclusive_default(ud, foreign_lang_index);
315 ghb_log("adding subtitle for foreign language audio: %s", audio_lang);
317 if (pref_lang != NULL)
319 if (audio_lang != NULL)
321 g_hash_table_destroy(track_indices);
325 ghb_selected_subtitle_row(signal_user_data_t *ud)
327 GtkTreeView *treeview;
328 GtkTreePath *treepath;
329 GtkTreeSelection *selection;
335 g_debug("ghb_selected_subtitle_row ()");
336 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
337 selection = gtk_tree_view_get_selection (treeview);
338 if (gtk_tree_selection_get_selected(selection, &store, &iter))
340 // Get the row number
341 treepath = gtk_tree_model_get_path (store, &iter);
342 indices = gtk_tree_path_get_indices (treepath);
344 gtk_tree_path_free(treepath);
350 ghb_selected_subtitle_settings(signal_user_data_t *ud)
352 GtkTreeView *treeview;
353 GtkTreePath *treepath;
354 GtkTreeSelection *selection;
359 GValue *settings = NULL;
360 const GValue *subtitle_list;
362 g_debug("get_selected_settings ()");
363 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
364 selection = gtk_tree_view_get_selection (treeview);
365 if (gtk_tree_selection_get_selected(selection, &store, &iter))
367 // Get the row number
368 treepath = gtk_tree_model_get_path (store, &iter);
369 indices = gtk_tree_path_get_indices (treepath);
371 gtk_tree_path_free(treepath);
372 // find subtitle settings
373 if (row < 0) return NULL;
374 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
375 if (row >= ghb_array_len(subtitle_list))
377 settings = ghb_array_get_nth(subtitle_list, row);
383 subtitle_forced_toggled_cb(
384 GtkCellRendererToggle *cell,
386 signal_user_data_t *ud)
395 GValue *subtitle_list, *settings;
398 g_debug("forced toggled");
399 tp = gtk_tree_path_new_from_string (path);
400 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
401 g_return_if_fail(tv != NULL);
402 tm = gtk_tree_view_get_model(tv);
403 g_return_if_fail(tm != NULL);
404 gtk_tree_model_get_iter(tm, &ti, tp);
405 gtk_tree_model_get(tm, &ti, 1, &active, -1);
408 // Get the row number
409 indices = gtk_tree_path_get_indices (tp);
411 gtk_tree_path_free(tp);
413 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
415 if (row < 0 || row >= ghb_array_len(subtitle_list))
418 settings = ghb_array_get_nth(subtitle_list, row);
419 track = ghb_settings_combo_int(settings, "SubtitleTrack");
421 source = ghb_subtitle_track_source(ud, track);
422 if (source != VOBSUB)
425 ghb_settings_set_boolean(settings, "SubtitleForced", active);
426 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 1, active, -1);
430 subtitle_burned_toggled_cb(
431 GtkCellRendererToggle *cell,
433 signal_user_data_t *ud)
442 GValue *subtitle_list;
443 gint count, track, source;
446 g_debug("burned toggled");
447 tp = gtk_tree_path_new_from_string (path);
448 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
449 g_return_if_fail(tv != NULL);
450 tm = gtk_tree_view_get_model(tv);
451 g_return_if_fail(tm != NULL);
452 gtk_tree_model_get_iter(tm, &ti, tp);
453 gtk_tree_model_get(tm, &ti, 2, &active, -1);
456 // Get the row number
457 indices = gtk_tree_path_get_indices (tp);
459 gtk_tree_path_free(tp);
461 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
462 count = ghb_array_len(subtitle_list);
463 if (row < 0 || row >= count)
466 settings = ghb_array_get_nth(subtitle_list, row);
467 track = ghb_settings_combo_int(settings, "SubtitleTrack");
469 source = ghb_subtitle_track_source(ud, track);
470 if (source != VOBSUB)
473 if (!active && mustBurn(ud, track))
476 ghb_settings_set_boolean(settings, "SubtitleBurned", active);
478 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, active, -1);
481 ghb_subtitle_exclusive_burn(ud, row);
485 subtitle_default_toggled_cb(
486 GtkCellRendererToggle *cell,
488 signal_user_data_t *ud)
497 GValue *subtitle_list;
501 g_debug("default toggled");
502 tp = gtk_tree_path_new_from_string (path);
503 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
504 g_return_if_fail(tv != NULL);
505 tm = gtk_tree_view_get_model(tv);
506 g_return_if_fail(tm != NULL);
507 gtk_tree_model_get_iter(tm, &ti, tp);
508 gtk_tree_model_get(tm, &ti, 3, &active, -1);
511 // Get the row number
512 indices = gtk_tree_path_get_indices (tp);
514 gtk_tree_path_free(tp);
516 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
517 count = ghb_array_len(subtitle_list);
518 if (row < 0 || row >= count)
521 settings = ghb_array_get_nth(subtitle_list, row);
522 track = ghb_settings_combo_int(settings, "SubtitleTrack");
524 ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", active);
526 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 3, active, -1);
527 // allow only one default
528 ghb_subtitle_exclusive_default(ud, row);
532 subtitle_list_refresh_selected(signal_user_data_t *ud)
534 GtkTreeView *treeview;
535 GtkTreePath *treepath;
536 GtkTreeSelection *selection;
541 GValue *settings = NULL;
542 const GValue *subtitle_list;
544 g_debug("subtitle_list_refresh_selected ()");
545 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
546 selection = gtk_tree_view_get_selection (treeview);
547 if (gtk_tree_selection_get_selected(selection, &store, &iter))
549 const gchar *track, *source;
550 gboolean forced, burned, def;
554 // Get the row number
555 treepath = gtk_tree_model_get_path (store, &iter);
556 indices = gtk_tree_path_get_indices (treepath);
558 gtk_tree_path_free(treepath);
559 // find audio settings
561 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
562 if (row >= ghb_array_len(subtitle_list))
564 settings = ghb_array_get_nth(subtitle_list, row);
566 track = ghb_settings_combo_option(settings, "SubtitleTrack");
567 forced = ghb_settings_get_boolean(settings, "SubtitleForced");
568 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
569 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
571 s_track = ghb_settings_get_string(settings, "SubtitleTrack");
572 i_track = ghb_settings_get_int(settings, "SubtitleTrack");
573 source = ghb_subtitle_track_source_name(ud, i_track);
576 i_source = ghb_subtitle_track_source(ud, i_track);
577 if (i_source != VOBSUB)
579 // Force and burn only apply to VOBSUBS
582 ghb_settings_set_boolean(settings, "SubtitleForced", forced);
583 ghb_settings_set_boolean(settings, "SubtitleBurned", burned);
586 gtk_list_store_set(GTK_LIST_STORE(store), &iter,
587 // These are displayed in list
593 // These are used to set combo box values when a list item is selected
598 ghb_subtitle_exclusive_burn(ud, row);
603 subtitle_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
607 g_debug("subtitle_track_changed_cb ()");
608 ghb_check_dependency(ud, widget);
609 settings = ghb_selected_subtitle_settings(ud);
610 if (settings != NULL)
615 ghb_widget_to_setting(settings, widget);
616 subtitle_list_refresh_selected(ud);
617 track = ghb_settings_combo_option(settings, "SubtitleTrack");
618 ghb_settings_set_string(settings, "SubtitleTrackDescription", track);
619 tt = ghb_settings_get_int(settings, "SubtitleTrack");
620 source = ghb_subtitle_track_source(ud, tt);
621 ghb_settings_set_int(settings, "SubtitleSource", source);
627 ghb_clear_subtitle_list(signal_user_data_t *ud)
629 GtkTreeView *treeview;
631 GValue *subtitle_list;
633 g_debug("clear_subtitle_list ()");
634 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
635 if (subtitle_list == NULL)
637 subtitle_list = ghb_array_value_new(8);
638 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
641 ghb_array_value_reset(subtitle_list, 8);
642 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
643 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
644 gtk_list_store_clear (store);
648 add_to_subtitle_list(
649 signal_user_data_t *ud,
652 GtkTreeView *treeview;
655 GtkTreeSelection *selection;
656 const gchar *track, *source;
657 gboolean forced, burned, def;
661 g_debug("add_to_subtitle_list ()");
662 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
663 selection = gtk_tree_view_get_selection (treeview);
664 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
666 track = ghb_settings_combo_option(settings, "SubtitleTrack");
667 forced = ghb_settings_get_boolean(settings, "SubtitleForced");
668 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
669 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
671 s_track = ghb_settings_get_string(settings, "SubtitleTrack");
672 i_track = ghb_settings_get_int(settings, "SubtitleTrack");
673 source = ghb_subtitle_track_source_name(ud, i_track);
675 gtk_list_store_append(store, &iter);
676 gtk_list_store_set(store, &iter,
677 // These are displayed in list
683 // These are used to set combo box values when a list item is selected
686 gtk_tree_selection_select_iter(selection, &iter);
691 subtitle_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
697 g_debug("subtitle_list_selection_changed_cb ()");
698 if (gtk_tree_selection_get_selected(selection, &store, &iter))
702 gtk_tree_model_get(store, &iter, 5, &track, -1);
703 ghb_ui_update(ud, "SubtitleTrack", ghb_string_value(track));
705 widget = GHB_WIDGET (ud->builder, "subtitle_remove");
706 gtk_widget_set_sensitive(widget, TRUE);
711 subtitle_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
713 // Add the current subtitle settings to the list.
715 gboolean burned = FALSE;
718 g_debug("subtitle_add_clicked_cb ()");
720 track = ghb_settings_get_int(ud->settings, "SubtitleTrack");
721 if (mustBurn(ud, track))
725 settings = ghb_dict_value_new();
726 ghb_settings_set_int(settings, "SubtitleTrack", track);
727 ghb_settings_take_value(settings, "SubtitleForced",
728 ghb_boolean_value_new(FALSE));
729 ghb_settings_take_value(settings, "SubtitleBurned",
730 ghb_boolean_value_new(burned));
731 ghb_settings_take_value(settings, "SubtitleDefaultTrack",
732 ghb_boolean_value_new(FALSE));
734 ghb_add_subtitle(ud, settings);
738 subtitle_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
740 GtkTreeView *treeview;
741 GtkTreePath *treepath;
742 GtkTreeSelection *selection;
744 GtkTreeIter iter, nextIter;
747 GValue *subtitle_list;
749 g_debug("subtitle_remove_clicked_cb ()");
750 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
751 selection = gtk_tree_view_get_selection (treeview);
752 if (gtk_tree_selection_get_selected(selection, &store, &iter))
755 if (!gtk_tree_model_iter_next(store, &nextIter))
758 if (gtk_tree_model_get_iter_first(store, &nextIter))
760 gtk_tree_selection_select_iter (selection, &nextIter);
765 gtk_tree_selection_select_iter (selection, &nextIter);
767 // Get the row number
768 treepath = gtk_tree_model_get_path (store, &iter);
769 indices = gtk_tree_path_get_indices (treepath);
771 gtk_tree_path_free(treepath);
772 // Remove the selected item
773 gtk_list_store_remove (GTK_LIST_STORE(store), &iter);
774 // remove from subtitle settings list
776 widget = GHB_WIDGET (ud->builder, "subtitle_add");
777 gtk_widget_set_sensitive(widget, TRUE);
778 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
779 if (row >= ghb_array_len(subtitle_list))
781 GValue *old = ghb_array_get_nth(subtitle_list, row);
783 ghb_array_remove(subtitle_list, row);
788 ghb_subtitle_prune(signal_user_data_t *ud)
793 GValue *subtitle_list, *settings;
794 gint count, ii, track;
796 gint first_track = 0, one_burned = 0;
798 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
799 if (subtitle_list == NULL)
801 count = ghb_array_len(subtitle_list);
803 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
804 g_return_if_fail(tv != NULL);
805 tm = gtk_tree_view_get_model(tv);
806 for (ii = count-1; ii >= 0; ii--)
808 settings = ghb_array_get_nth(subtitle_list, ii);
809 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
810 track = ghb_settings_combo_int(settings, "SubtitleTrack");
811 if (!burned && mustBurn(ud, track))
813 gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii);
814 gtk_list_store_remove (GTK_LIST_STORE(tm), &ti);
815 ghb_array_remove(subtitle_list, ii);
825 ghb_subtitle_exclusive_burn(ud, first_track);
830 ghb_reset_subtitles(signal_user_data_t *ud, GValue *settings)
837 g_debug("ghb_reset_subtitles");
838 ghb_clear_subtitle_list(ud);
839 titleindex = ghb_settings_combo_int(ud->settings, "title");
843 slist = ghb_settings_get_value(settings, "subtitle_list");
844 count = ghb_array_len(slist);
845 for (ii = 0; ii < count; ii++)
847 subtitle = ghb_value_dup(ghb_array_get_nth(slist, ii));
848 ghb_add_subtitle(ud, subtitle);