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 "subtitlehandler.h"
24 static void add_to_subtitle_list(signal_user_data_t *ud, GValue *settings);
27 free_subtitle_index_list(gpointer data)
33 free_subtitle_key(gpointer data)
40 mustBurn(signal_user_data_t *ud, gint track)
44 mux = ghb_settings_combo_int(ud->settings, "FileFormat");
45 if (mux == HB_MUX_MP4)
49 // MP4 can only handle burned vobsubs. make sure there isn't
50 // already something burned in the list
51 source = ghb_subtitle_track_source(ud, track);
61 ghb_subtitle_exclusive_burn(signal_user_data_t *ud, gint index)
63 GValue *subtitle_list;
71 g_debug("ghb_subtitle_exclusive_burn");
72 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
73 count = ghb_array_len(subtitle_list);
76 burned = ghb_settings_get_boolean(ud->settings, "SubtitleForeignBurned");
77 if (burned && !mustBurn(ud, -1))
78 ghb_ui_update(ud, "SubtitleForeignBurned", ghb_boolean_value(FALSE));
80 for (ii = 0; ii < count; ii++)
82 settings = ghb_array_get_nth(subtitle_list, ii);
83 tt = ghb_settings_combo_int(settings, "SubtitleTrack");
84 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
86 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
87 g_return_if_fail(tv != NULL);
88 tm = gtk_tree_view_get_model(tv);
89 gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii);
90 if (burned && ii != index && !mustBurn(ud, tt))
92 ghb_settings_set_boolean(settings, "SubtitleBurned", FALSE);
93 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, FALSE, -1);
99 ghb_subtitle_exclusive_default(signal_user_data_t *ud, gint index)
101 GValue *subtitle_list;
109 g_debug("ghb_subtitle_exclusive_default");
110 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
111 count = ghb_array_len(subtitle_list);
114 def = ghb_settings_get_boolean(ud->settings, "SubtitleForeignDefaultTrack");
116 ghb_ui_update(ud, "SubtitleForeignDefaultTrack", ghb_boolean_value(FALSE));
118 for (ii = 0; ii < count; ii++)
120 settings = ghb_array_get_nth(subtitle_list, ii);
121 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
123 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
124 g_return_if_fail(tv != NULL);
125 tm = gtk_tree_view_get_model(tv);
126 gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii);
127 if (def && ii != index)
130 ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", FALSE);
132 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 3, FALSE, -1);
138 ghb_add_subtitle(signal_user_data_t *ud, GValue *settings)
140 // Add the current subtitle settings to the list.
141 GValue *subtitle_list;
145 g_debug("ghb_add_subtitle ()");
147 // Only allow up to 8 subtitle entries
148 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
149 if (subtitle_list == NULL)
151 subtitle_list = ghb_array_value_new(8);
152 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
154 count = ghb_array_len(subtitle_list);
155 ghb_array_append(subtitle_list, settings);
156 add_to_subtitle_list(ud, settings);
158 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
160 ghb_subtitle_exclusive_burn(ud, count);
164 add_all_pref_subtitles(signal_user_data_t *ud)
166 const GValue *pref_subtitle;
168 gint count, ii, track;
171 pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList");
172 count = ghb_array_len(pref_subtitle);
173 for (ii = 0; ii < count; ii++)
175 subtitle = ghb_value_dup(ghb_array_get_nth(pref_subtitle, ii));
176 lang = ghb_settings_get_string(subtitle, "SubtitleLanguage");
177 // If there are multiple subtitles using the same language, then
178 // select sequential tracks for each. The hash keeps track
179 // of the tracks used for each language.
180 track = ghb_find_pref_subtitle_track(lang);
184 // Add to subtitle list
185 ghb_settings_set_int(subtitle, "SubtitleTrack", track);
186 ghb_add_subtitle(ud, subtitle);
192 ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud)
195 GHashTable *track_indices;
198 const GValue *pref_subtitle;
202 g_debug("ghb_set_pref_subtitle %d", titleindex);
203 track_indices = g_hash_table_new_full(g_str_hash, g_str_equal,
204 NULL, free_subtitle_index_list);
206 ghb_ui_update(ud, "SubtitleTrack", ghb_int_value(0));
208 // Clear the subtitle list
209 ghb_clear_subtitle_list(ud);
212 add_all_pref_subtitles(ud);
216 // Find "best" subtitle based on subtitle preferences
217 pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList");
219 count = ghb_array_len(pref_subtitle);
220 for (ii = 0; ii < count; ii++)
222 subtitle = ghb_array_get_nth(pref_subtitle, ii);
223 lang = ghb_settings_get_string(subtitle, "SubtitleLanguage");
224 // If there are multiple subtitles using the same language, then
225 // select sequential tracks for each. The hash keeps track
226 // of the tracks used for each language.
227 track = ghb_find_subtitle_track(titleindex, lang, track_indices);
231 GValue *dup = ghb_value_dup(subtitle);
232 ghb_settings_set_int(dup, "SubtitleTrack", track);
233 ghb_add_subtitle(ud, dup);
236 g_hash_table_destroy(track_indices);
240 ghb_selected_subtitle_row(signal_user_data_t *ud)
242 GtkTreeView *treeview;
243 GtkTreePath *treepath;
244 GtkTreeSelection *selection;
250 g_debug("ghb_selected_subtitle_row ()");
251 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
252 selection = gtk_tree_view_get_selection (treeview);
253 if (gtk_tree_selection_get_selected(selection, &store, &iter))
255 // Get the row number
256 treepath = gtk_tree_model_get_path (store, &iter);
257 indices = gtk_tree_path_get_indices (treepath);
259 gtk_tree_path_free(treepath);
265 ghb_selected_subtitle_settings(signal_user_data_t *ud)
267 GtkTreeView *treeview;
268 GtkTreePath *treepath;
269 GtkTreeSelection *selection;
274 GValue *settings = NULL;
275 const GValue *subtitle_list;
277 g_debug("get_selected_settings ()");
278 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
279 selection = gtk_tree_view_get_selection (treeview);
280 if (gtk_tree_selection_get_selected(selection, &store, &iter))
282 // Get the row number
283 treepath = gtk_tree_model_get_path (store, &iter);
284 indices = gtk_tree_path_get_indices (treepath);
286 gtk_tree_path_free(treepath);
287 // find subtitle settings
288 if (row < 0) return NULL;
289 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
290 if (row >= ghb_array_len(subtitle_list))
292 settings = ghb_array_get_nth(subtitle_list, row);
298 subtitle_forced_toggled_cb(
299 GtkCellRendererToggle *cell,
301 signal_user_data_t *ud)
310 GValue *subtitle_list, *settings;
313 g_debug("forced toggled");
314 tp = gtk_tree_path_new_from_string (path);
315 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
316 g_return_if_fail(tv != NULL);
317 tm = gtk_tree_view_get_model(tv);
318 g_return_if_fail(tm != NULL);
319 gtk_tree_model_get_iter(tm, &ti, tp);
320 gtk_tree_model_get(tm, &ti, 1, &active, -1);
323 // Get the row number
324 indices = gtk_tree_path_get_indices (tp);
326 gtk_tree_path_free(tp);
328 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
330 if (row < 0 || row >= ghb_array_len(subtitle_list))
333 settings = ghb_array_get_nth(subtitle_list, row);
334 track = ghb_settings_combo_int(settings, "SubtitleTrack");
336 source = ghb_subtitle_track_source(ud, track);
337 if (source != VOBSUB)
340 ghb_settings_set_boolean(settings, "SubtitleForced", active);
341 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 1, active, -1);
345 subtitle_burned_toggled_cb(
346 GtkCellRendererToggle *cell,
348 signal_user_data_t *ud)
357 GValue *subtitle_list;
358 gint count, track, source;
361 g_debug("burned toggled");
362 tp = gtk_tree_path_new_from_string (path);
363 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
364 g_return_if_fail(tv != NULL);
365 tm = gtk_tree_view_get_model(tv);
366 g_return_if_fail(tm != NULL);
367 gtk_tree_model_get_iter(tm, &ti, tp);
368 gtk_tree_model_get(tm, &ti, 2, &active, -1);
371 // Get the row number
372 indices = gtk_tree_path_get_indices (tp);
374 gtk_tree_path_free(tp);
376 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
377 count = ghb_array_len(subtitle_list);
378 if (row < 0 || row >= count)
381 settings = ghb_array_get_nth(subtitle_list, row);
382 track = ghb_settings_combo_int(settings, "SubtitleTrack");
384 source = ghb_subtitle_track_source(ud, track);
385 if (source != VOBSUB)
388 if (!active && mustBurn(ud, track))
391 ghb_settings_set_boolean(settings, "SubtitleBurned", active);
393 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, active, -1);
396 ghb_subtitle_exclusive_burn(ud, row);
400 subtitle_default_toggled_cb(
401 GtkCellRendererToggle *cell,
403 signal_user_data_t *ud)
412 GValue *subtitle_list;
416 g_debug("default toggled");
417 tp = gtk_tree_path_new_from_string (path);
418 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
419 g_return_if_fail(tv != NULL);
420 tm = gtk_tree_view_get_model(tv);
421 g_return_if_fail(tm != NULL);
422 gtk_tree_model_get_iter(tm, &ti, tp);
423 gtk_tree_model_get(tm, &ti, 3, &active, -1);
426 // Get the row number
427 indices = gtk_tree_path_get_indices (tp);
429 gtk_tree_path_free(tp);
431 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
432 count = ghb_array_len(subtitle_list);
433 if (row < 0 || row >= count)
436 settings = ghb_array_get_nth(subtitle_list, row);
437 track = ghb_settings_combo_int(settings, "SubtitleTrack");
439 ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", active);
441 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 3, active, -1);
442 // allow only one default
443 ghb_subtitle_exclusive_default(ud, row);
447 subtitle_list_refresh_selected(signal_user_data_t *ud)
449 GtkTreeView *treeview;
450 GtkTreePath *treepath;
451 GtkTreeSelection *selection;
456 GValue *settings = NULL;
457 const GValue *subtitle_list;
459 g_debug("subtitle_list_refresh_selected ()");
460 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
461 selection = gtk_tree_view_get_selection (treeview);
462 if (gtk_tree_selection_get_selected(selection, &store, &iter))
464 const gchar *track, *source;
465 gboolean forced, burned, def;
469 // Get the row number
470 treepath = gtk_tree_model_get_path (store, &iter);
471 indices = gtk_tree_path_get_indices (treepath);
473 gtk_tree_path_free(treepath);
474 // find audio settings
476 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
477 if (row >= ghb_array_len(subtitle_list))
479 settings = ghb_array_get_nth(subtitle_list, row);
481 track = ghb_settings_combo_option(settings, "SubtitleTrack");
482 forced = ghb_settings_get_boolean(settings, "SubtitleForced");
483 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
484 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
486 s_track = ghb_settings_get_string(settings, "SubtitleTrack");
487 i_track = ghb_settings_get_int(settings, "SubtitleTrack");
488 source = ghb_subtitle_track_source_name(ud, i_track);
491 i_source = ghb_subtitle_track_source(ud, i_track);
492 if (i_source != VOBSUB)
494 // Force and burn only apply to VOBSUBS
497 ghb_settings_set_boolean(settings, "SubtitleForced", forced);
498 ghb_settings_set_boolean(settings, "SubtitleBurned", burned);
501 gtk_list_store_set(GTK_LIST_STORE(store), &iter,
502 // These are displayed in list
508 // These are used to set combo box values when a list item is selected
513 ghb_subtitle_exclusive_burn(ud, row);
518 subtitle_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
522 g_debug("subtitle_track_changed_cb ()");
523 ghb_check_dependency(ud, widget);
524 settings = ghb_selected_subtitle_settings(ud);
525 if (settings != NULL)
527 ghb_widget_to_setting(settings, widget);
528 subtitle_list_refresh_selected(ud);
534 ghb_clear_subtitle_list(signal_user_data_t *ud)
536 GtkTreeView *treeview;
538 GValue *subtitle_list;
540 g_debug("clear_subtitle_list ()");
541 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
542 if (subtitle_list == NULL)
544 subtitle_list = ghb_array_value_new(8);
545 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
548 ghb_array_value_reset(subtitle_list, 8);
549 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
550 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
551 gtk_list_store_clear (store);
555 add_to_subtitle_list(
556 signal_user_data_t *ud,
559 GtkTreeView *treeview;
562 GtkTreeSelection *selection;
563 const gchar *track, *source;
564 gboolean forced, burned, def;
568 g_debug("add_to_subtitle_list ()");
569 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
570 selection = gtk_tree_view_get_selection (treeview);
571 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
573 track = ghb_settings_combo_option(settings, "SubtitleTrack");
574 forced = ghb_settings_get_boolean(settings, "SubtitleForced");
575 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
576 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
578 s_track = ghb_settings_get_string(settings, "SubtitleTrack");
579 i_track = ghb_settings_get_int(settings, "SubtitleTrack");
580 source = ghb_subtitle_track_source_name(ud, i_track);
582 gtk_list_store_append(store, &iter);
583 gtk_list_store_set(store, &iter,
584 // These are displayed in list
590 // These are used to set combo box values when a list item is selected
593 gtk_tree_selection_select_iter(selection, &iter);
598 subtitle_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
604 g_debug("subtitle_list_selection_changed_cb ()");
605 if (gtk_tree_selection_get_selected(selection, &store, &iter))
609 gtk_tree_model_get(store, &iter, 5, &track, -1);
610 ghb_ui_update(ud, "SubtitleTrack", ghb_string_value(track));
612 widget = GHB_WIDGET (ud->builder, "subtitle_remove");
613 gtk_widget_set_sensitive(widget, TRUE);
618 subtitle_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
620 // Add the current subtitle settings to the list.
623 GValue *subtitle_list;
624 gboolean burned = FALSE;
627 g_debug("subtitle_add_clicked_cb ()");
628 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
629 if (subtitle_list == NULL)
631 subtitle_list = ghb_array_value_new(8);
632 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
634 count = ghb_array_len(subtitle_list);
635 // Don't allow more than 99
636 // This is a had limit imposed by libhb/sync.c:GetFifoForId()
640 track = ghb_settings_get_int(ud->settings, "SubtitleTrack");
642 if (mustBurn(ud, track))
646 settings = ghb_dict_value_new();
647 ghb_settings_set_int(settings, "SubtitleTrack", track);
648 ghb_settings_take_value(settings, "SubtitleForced",
649 ghb_boolean_value_new(FALSE));
650 ghb_settings_take_value(settings, "SubtitleBurned",
651 ghb_boolean_value_new(burned));
652 ghb_settings_take_value(settings, "SubtitleDefaultTrack",
653 ghb_boolean_value_new(FALSE));
655 ghb_array_append(subtitle_list, settings);
656 add_to_subtitle_list(ud, settings);
658 ghb_subtitle_exclusive_burn(ud, count);
662 widget = GHB_WIDGET (ud->builder, "subtitle_add");
663 gtk_widget_set_sensitive(widget, FALSE);
668 subtitle_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
670 GtkTreeView *treeview;
671 GtkTreePath *treepath;
672 GtkTreeSelection *selection;
674 GtkTreeIter iter, nextIter;
677 GValue *subtitle_list;
679 g_debug("subtitle_remove_clicked_cb ()");
680 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
681 selection = gtk_tree_view_get_selection (treeview);
682 if (gtk_tree_selection_get_selected(selection, &store, &iter))
685 if (!gtk_tree_model_iter_next(store, &nextIter))
688 if (gtk_tree_model_get_iter_first(store, &nextIter))
690 gtk_tree_selection_select_iter (selection, &nextIter);
695 gtk_tree_selection_select_iter (selection, &nextIter);
697 // Get the row number
698 treepath = gtk_tree_model_get_path (store, &iter);
699 indices = gtk_tree_path_get_indices (treepath);
701 gtk_tree_path_free(treepath);
702 // Remove the selected item
703 gtk_list_store_remove (GTK_LIST_STORE(store), &iter);
704 // remove from subtitle settings list
706 widget = GHB_WIDGET (ud->builder, "subtitle_add");
707 gtk_widget_set_sensitive(widget, TRUE);
708 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
709 if (row >= ghb_array_len(subtitle_list))
711 GValue *old = ghb_array_get_nth(subtitle_list, row);
713 ghb_array_remove(subtitle_list, row);
718 ghb_subtitle_prune(signal_user_data_t *ud)
723 GValue *subtitle_list, *settings;
724 gint count, ii, track;
726 gint first_track, one_burned = 0;
728 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
729 if (subtitle_list == NULL)
731 count = ghb_array_len(subtitle_list);
733 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
734 g_return_if_fail(tv != NULL);
735 tm = gtk_tree_view_get_model(tv);
736 for (ii = count-1; ii >= 0; ii--)
738 settings = ghb_array_get_nth(subtitle_list, ii);
739 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
740 track = ghb_settings_combo_int(settings, "SubtitleTrack");
741 if (!burned && mustBurn(ud, track))
743 gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii);
744 gtk_list_store_remove (GTK_LIST_STORE(tm), &ti);
745 ghb_array_remove(subtitle_list, ii);
755 ghb_subtitle_exclusive_burn(ud, first_track);
758 mux = ghb_settings_combo_int(ud->settings, "FileFormat");
759 if (mux == HB_MUX_MP4)
761 ghb_ui_update(ud, "SubtitleForeignBurned", ghb_boolean_value(TRUE));
762 ghb_ui_update(ud, "SubtitleForeignDefaultTrack", ghb_boolean_value(FALSE));
767 ghb_reset_subtitles(signal_user_data_t *ud, GValue *settings)
774 g_debug("ghb_reset_subtitles");
775 ghb_clear_subtitle_list(ud);
776 titleindex = ghb_settings_combo_int(ud->settings, "title");
780 slist = ghb_settings_get_value(settings, "subtitle_list");
781 count = ghb_array_len(slist);
782 for (ii = 0; ii < count; ii++)
784 subtitle = ghb_value_dup(ghb_array_get_nth(slist, ii));
785 ghb_add_subtitle(ud, subtitle);
790 subtitle_foreign_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
792 ghb_widget_to_setting(ud->settings, widget);
793 ghb_check_dependency(ud, widget);
794 ghb_clear_presets_selection(ud);
797 if (ghb_settings_get_boolean(ud->settings, "SubtitleForeignBurned"))
799 ghb_subtitle_exclusive_burn(ud, -1);
801 if (ghb_settings_get_boolean(ud->settings, "SubtitleForeignDefaultTrack"))
803 ghb_subtitle_exclusive_default(ud, -1);