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);
74 for (ii = 0; ii < count; ii++)
76 settings = ghb_array_get_nth(subtitle_list, ii);
77 tt = ghb_settings_combo_int(settings, "SubtitleTrack");
78 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
80 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
81 g_return_if_fail(tv != NULL);
82 tm = gtk_tree_view_get_model(tv);
83 gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii);
84 if (burned && ii != index && !mustBurn(ud, tt))
86 ghb_settings_set_boolean(settings, "SubtitleBurned", FALSE);
87 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, FALSE, -1);
93 ghb_subtitle_exclusive_default(signal_user_data_t *ud, gint index)
95 GValue *subtitle_list;
103 g_debug("ghb_subtitle_exclusive_default");
104 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
105 count = ghb_array_len(subtitle_list);
106 for (ii = 0; ii < count; ii++)
108 settings = ghb_array_get_nth(subtitle_list, ii);
109 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
111 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
112 g_return_if_fail(tv != NULL);
113 tm = gtk_tree_view_get_model(tv);
114 gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii);
115 if (def && ii != index)
118 ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", FALSE);
119 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 3, FALSE, -1);
125 ghb_add_subtitle(signal_user_data_t *ud, GValue *settings)
127 // Add the current subtitle settings to the list.
128 GValue *subtitle_list;
132 g_debug("ghb_add_subtitle ()");
134 // Only allow up to 8 subtitle entries
135 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
136 if (subtitle_list == NULL)
138 subtitle_list = ghb_array_value_new(8);
139 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
141 count = ghb_array_len(subtitle_list);
142 ghb_array_append(subtitle_list, settings);
143 add_to_subtitle_list(ud, settings);
145 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
147 ghb_subtitle_exclusive_burn(ud, count);
151 add_all_pref_subtitles(signal_user_data_t *ud)
153 const GValue *pref_subtitle;
155 gint count, ii, track;
158 pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList");
159 count = ghb_array_len(pref_subtitle);
160 for (ii = 0; ii < count; ii++)
162 subtitle = ghb_value_dup(ghb_array_get_nth(pref_subtitle, ii));
163 lang = ghb_settings_get_string(subtitle, "SubtitleLanguage");
164 // If there are multiple subtitles using the same language, then
165 // select sequential tracks for each. The hash keeps track
166 // of the tracks used for each language.
167 track = ghb_find_pref_subtitle_track(lang);
171 // Add to subtitle list
172 ghb_settings_set_int(subtitle, "SubtitleTrack", track);
173 ghb_add_subtitle(ud, subtitle);
179 ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud)
182 GHashTable *track_indices;
185 const GValue *pref_subtitle;
189 g_debug("ghb_set_pref_subtitle %d", titleindex);
190 track_indices = g_hash_table_new_full(g_str_hash, g_str_equal,
191 NULL, free_subtitle_index_list);
193 ghb_ui_update(ud, "SubtitleTrack", ghb_int_value(0));
195 // Clear the subtitle list
196 ghb_clear_subtitle_list(ud);
199 add_all_pref_subtitles(ud);
203 // Find "best" subtitle based on subtitle preferences
204 pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList");
206 count = ghb_array_len(pref_subtitle);
207 for (ii = 0; ii < count; ii++)
209 subtitle = ghb_array_get_nth(pref_subtitle, ii);
210 lang = ghb_settings_get_string(subtitle, "SubtitleLanguage");
211 // If there are multiple subtitles using the same language, then
212 // select sequential tracks for each. The hash keeps track
213 // of the tracks used for each language.
214 track = ghb_find_subtitle_track(titleindex, lang, track_indices);
218 GValue *dup = ghb_value_dup(subtitle);
219 ghb_settings_set_int(dup, "SubtitleTrack", track);
220 ghb_add_subtitle(ud, dup);
223 g_hash_table_destroy(track_indices);
227 ghb_selected_subtitle_row(signal_user_data_t *ud)
229 GtkTreeView *treeview;
230 GtkTreePath *treepath;
231 GtkTreeSelection *selection;
237 g_debug("ghb_selected_subtitle_row ()");
238 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
239 selection = gtk_tree_view_get_selection (treeview);
240 if (gtk_tree_selection_get_selected(selection, &store, &iter))
242 // Get the row number
243 treepath = gtk_tree_model_get_path (store, &iter);
244 indices = gtk_tree_path_get_indices (treepath);
246 gtk_tree_path_free(treepath);
252 ghb_selected_subtitle_settings(signal_user_data_t *ud)
254 GtkTreeView *treeview;
255 GtkTreePath *treepath;
256 GtkTreeSelection *selection;
261 GValue *settings = NULL;
262 const GValue *subtitle_list;
264 g_debug("get_selected_settings ()");
265 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
266 selection = gtk_tree_view_get_selection (treeview);
267 if (gtk_tree_selection_get_selected(selection, &store, &iter))
269 // Get the row number
270 treepath = gtk_tree_model_get_path (store, &iter);
271 indices = gtk_tree_path_get_indices (treepath);
273 gtk_tree_path_free(treepath);
274 // find subtitle settings
275 if (row < 0) return NULL;
276 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
277 if (row >= ghb_array_len(subtitle_list))
279 settings = ghb_array_get_nth(subtitle_list, row);
285 subtitle_forced_toggled_cb(
286 GtkCellRendererToggle *cell,
288 signal_user_data_t *ud)
297 GValue *subtitle_list, *settings;
300 g_debug("forced toggled");
301 tp = gtk_tree_path_new_from_string (path);
302 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
303 g_return_if_fail(tv != NULL);
304 tm = gtk_tree_view_get_model(tv);
305 g_return_if_fail(tm != NULL);
306 gtk_tree_model_get_iter(tm, &ti, tp);
307 gtk_tree_model_get(tm, &ti, 1, &active, -1);
310 // Get the row number
311 indices = gtk_tree_path_get_indices (tp);
313 gtk_tree_path_free(tp);
315 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
317 if (row < 0 || row >= ghb_array_len(subtitle_list))
320 settings = ghb_array_get_nth(subtitle_list, row);
321 track = ghb_settings_combo_int(settings, "SubtitleTrack");
323 source = ghb_subtitle_track_source(ud, track);
324 if (source != VOBSUB)
327 ghb_settings_set_boolean(settings, "SubtitleForced", active);
328 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 1, active, -1);
332 subtitle_burned_toggled_cb(
333 GtkCellRendererToggle *cell,
335 signal_user_data_t *ud)
344 GValue *subtitle_list;
345 gint count, track, source;
348 g_debug("burned toggled");
349 tp = gtk_tree_path_new_from_string (path);
350 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
351 g_return_if_fail(tv != NULL);
352 tm = gtk_tree_view_get_model(tv);
353 g_return_if_fail(tm != NULL);
354 gtk_tree_model_get_iter(tm, &ti, tp);
355 gtk_tree_model_get(tm, &ti, 2, &active, -1);
358 // Get the row number
359 indices = gtk_tree_path_get_indices (tp);
361 gtk_tree_path_free(tp);
363 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
364 count = ghb_array_len(subtitle_list);
365 if (row < 0 || row >= count)
368 settings = ghb_array_get_nth(subtitle_list, row);
369 track = ghb_settings_combo_int(settings, "SubtitleTrack");
371 source = ghb_subtitle_track_source(ud, track);
372 if (source != VOBSUB)
375 if (!active && mustBurn(ud, track))
378 ghb_settings_set_boolean(settings, "SubtitleBurned", active);
380 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, active, -1);
383 ghb_subtitle_exclusive_burn(ud, row);
387 subtitle_default_toggled_cb(
388 GtkCellRendererToggle *cell,
390 signal_user_data_t *ud)
399 GValue *subtitle_list;
403 g_debug("default toggled");
404 tp = gtk_tree_path_new_from_string (path);
405 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
406 g_return_if_fail(tv != NULL);
407 tm = gtk_tree_view_get_model(tv);
408 g_return_if_fail(tm != NULL);
409 gtk_tree_model_get_iter(tm, &ti, tp);
410 gtk_tree_model_get(tm, &ti, 3, &active, -1);
413 // Get the row number
414 indices = gtk_tree_path_get_indices (tp);
416 gtk_tree_path_free(tp);
418 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
419 count = ghb_array_len(subtitle_list);
420 if (row < 0 || row >= count)
423 settings = ghb_array_get_nth(subtitle_list, row);
424 track = ghb_settings_combo_int(settings, "SubtitleTrack");
426 ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", active);
428 gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 3, active, -1);
429 // allow only one default
430 ghb_subtitle_exclusive_default(ud, row);
434 subtitle_list_refresh_selected(signal_user_data_t *ud)
436 GtkTreeView *treeview;
437 GtkTreePath *treepath;
438 GtkTreeSelection *selection;
443 GValue *settings = NULL;
444 const GValue *subtitle_list;
446 g_debug("subtitle_list_refresh_selected ()");
447 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
448 selection = gtk_tree_view_get_selection (treeview);
449 if (gtk_tree_selection_get_selected(selection, &store, &iter))
451 const gchar *track, *source;
452 gboolean forced, burned, def;
456 // Get the row number
457 treepath = gtk_tree_model_get_path (store, &iter);
458 indices = gtk_tree_path_get_indices (treepath);
460 gtk_tree_path_free(treepath);
461 // find audio settings
463 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
464 if (row >= ghb_array_len(subtitle_list))
466 settings = ghb_array_get_nth(subtitle_list, row);
468 track = ghb_settings_combo_option(settings, "SubtitleTrack");
469 forced = ghb_settings_get_boolean(settings, "SubtitleForced");
470 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
471 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
473 s_track = ghb_settings_get_string(settings, "SubtitleTrack");
474 i_track = ghb_settings_get_int(settings, "SubtitleTrack");
475 source = ghb_subtitle_track_source_name(ud, i_track);
478 i_source = ghb_subtitle_track_source(ud, i_track);
479 if (i_source != VOBSUB)
481 // Force and burn only apply to VOBSUBS
484 ghb_settings_set_boolean(settings, "SubtitleForced", forced);
485 ghb_settings_set_boolean(settings, "SubtitleBurned", burned);
488 gtk_list_store_set(GTK_LIST_STORE(store), &iter,
489 // These are displayed in list
495 // These are used to set combo box values when a list item is selected
500 ghb_subtitle_exclusive_burn(ud, row);
505 subtitle_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
509 g_debug("subtitle_track_changed_cb ()");
510 ghb_check_dependency(ud, widget);
511 settings = ghb_selected_subtitle_settings(ud);
512 if (settings != NULL)
514 ghb_widget_to_setting(settings, widget);
515 subtitle_list_refresh_selected(ud);
521 ghb_clear_subtitle_list(signal_user_data_t *ud)
523 GtkTreeView *treeview;
525 GValue *subtitle_list;
527 g_debug("clear_subtitle_list ()");
528 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
529 if (subtitle_list == NULL)
531 subtitle_list = ghb_array_value_new(8);
532 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
535 ghb_array_value_reset(subtitle_list, 8);
536 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
537 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
538 gtk_list_store_clear (store);
542 add_to_subtitle_list(
543 signal_user_data_t *ud,
546 GtkTreeView *treeview;
549 GtkTreeSelection *selection;
550 const gchar *track, *source;
551 gboolean forced, burned, def;
555 g_debug("add_to_subtitle_list ()");
556 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
557 selection = gtk_tree_view_get_selection (treeview);
558 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
560 track = ghb_settings_combo_option(settings, "SubtitleTrack");
561 forced = ghb_settings_get_boolean(settings, "SubtitleForced");
562 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
563 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
565 s_track = ghb_settings_get_string(settings, "SubtitleTrack");
566 i_track = ghb_settings_get_int(settings, "SubtitleTrack");
567 source = ghb_subtitle_track_source_name(ud, i_track);
569 gtk_list_store_append(store, &iter);
570 gtk_list_store_set(store, &iter,
571 // These are displayed in list
577 // These are used to set combo box values when a list item is selected
580 gtk_tree_selection_select_iter(selection, &iter);
585 subtitle_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
591 g_debug("subtitle_list_selection_changed_cb ()");
592 if (gtk_tree_selection_get_selected(selection, &store, &iter))
596 gtk_tree_model_get(store, &iter, 5, &track, -1);
597 ghb_ui_update(ud, "SubtitleTrack", ghb_string_value(track));
599 widget = GHB_WIDGET (ud->builder, "subtitle_remove");
600 gtk_widget_set_sensitive(widget, TRUE);
605 subtitle_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
607 // Add the current subtitle settings to the list.
610 GValue *subtitle_list;
611 gboolean burned = FALSE;
614 g_debug("subtitle_add_clicked_cb ()");
615 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
616 if (subtitle_list == NULL)
618 subtitle_list = ghb_array_value_new(8);
619 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
621 count = ghb_array_len(subtitle_list);
622 // Don't allow more than 99
623 // This is a had limit imposed by libhb/sync.c:GetFifoForId()
627 track = ghb_settings_get_int(ud->settings, "SubtitleTrack");
629 if (mustBurn(ud, track))
633 settings = ghb_dict_value_new();
634 ghb_settings_set_int(settings, "SubtitleTrack", track);
635 ghb_settings_take_value(settings, "SubtitleForced",
636 ghb_boolean_value_new(FALSE));
637 ghb_settings_take_value(settings, "SubtitleBurned",
638 ghb_boolean_value_new(burned));
639 ghb_settings_take_value(settings, "SubtitleDefaultTrack",
640 ghb_boolean_value_new(FALSE));
642 ghb_array_append(subtitle_list, settings);
643 add_to_subtitle_list(ud, settings);
645 ghb_subtitle_exclusive_burn(ud, count);
649 widget = GHB_WIDGET (ud->builder, "subtitle_add");
650 gtk_widget_set_sensitive(widget, FALSE);
655 subtitle_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
657 GtkTreeView *treeview;
658 GtkTreePath *treepath;
659 GtkTreeSelection *selection;
661 GtkTreeIter iter, nextIter;
664 GValue *subtitle_list;
666 g_debug("subtitle_remove_clicked_cb ()");
667 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
668 selection = gtk_tree_view_get_selection (treeview);
669 if (gtk_tree_selection_get_selected(selection, &store, &iter))
672 if (!gtk_tree_model_iter_next(store, &nextIter))
675 if (gtk_tree_model_get_iter_first(store, &nextIter))
677 gtk_tree_selection_select_iter (selection, &nextIter);
682 gtk_tree_selection_select_iter (selection, &nextIter);
684 // Get the row number
685 treepath = gtk_tree_model_get_path (store, &iter);
686 indices = gtk_tree_path_get_indices (treepath);
688 gtk_tree_path_free(treepath);
689 // Remove the selected item
690 gtk_list_store_remove (GTK_LIST_STORE(store), &iter);
691 // remove from subtitle settings list
693 widget = GHB_WIDGET (ud->builder, "subtitle_add");
694 gtk_widget_set_sensitive(widget, TRUE);
695 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
696 if (row >= ghb_array_len(subtitle_list))
698 GValue *old = ghb_array_get_nth(subtitle_list, row);
700 ghb_array_remove(subtitle_list, row);
705 ghb_subtitle_prune(signal_user_data_t *ud)
710 GValue *subtitle_list, *settings;
711 gint count, ii, track;
713 gint first_track = 0, one_burned = 0;
715 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
716 if (subtitle_list == NULL)
718 count = ghb_array_len(subtitle_list);
720 tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
721 g_return_if_fail(tv != NULL);
722 tm = gtk_tree_view_get_model(tv);
723 for (ii = count-1; ii >= 0; ii--)
725 settings = ghb_array_get_nth(subtitle_list, ii);
726 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
727 track = ghb_settings_combo_int(settings, "SubtitleTrack");
728 if (!burned && mustBurn(ud, track))
730 gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii);
731 gtk_list_store_remove (GTK_LIST_STORE(tm), &ti);
732 ghb_array_remove(subtitle_list, ii);
742 ghb_subtitle_exclusive_burn(ud, first_track);
747 ghb_reset_subtitles(signal_user_data_t *ud, GValue *settings)
754 g_debug("ghb_reset_subtitles");
755 ghb_clear_subtitle_list(ud);
756 titleindex = ghb_settings_combo_int(ud->settings, "title");
760 slist = ghb_settings_get_value(settings, "subtitle_list");
761 count = ghb_array_len(slist);
762 for (ii = 0; ii < count; ii++)
764 subtitle = ghb_value_dup(ghb_array_get_nth(slist, ii));
765 ghb_add_subtitle(ud, subtitle);