OSDN Git Service

WinGui:
[handbrake-jp/handbrake-jp-git.git] / gtk / src / subtitlehandler.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  * subtitlehandler.c
4  * Copyright (C) John Stebbins 2008 <stebbins@stebbins>
5  * 
6  * subtitlehandler.c is free software.
7  * 
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)
11  * any later version.
12  */
13
14 #include <gtk/gtk.h>
15 #include "hb.h"
16 #include "settings.h"
17 #include "hb-backend.h"
18 #include "values.h"
19 #include "callbacks.h"
20 #include "preview.h"
21 #include "presets.h"
22 #include "audiohandler.h"
23 #include "subtitlehandler.h"
24
25 static void add_to_subtitle_list(signal_user_data_t *ud, GValue *settings);
26
27 static void
28 free_subtitle_index_list(gpointer data)
29 {
30         g_free(data);
31 }
32
33 static void
34 free_subtitle_key(gpointer data)
35 {
36         if (data != NULL)
37                 g_free(data);
38 }
39
40 static gboolean
41 mustBurn(signal_user_data_t *ud, gint track)
42 {
43         gint mux;
44
45         mux = ghb_settings_combo_int(ud->settings, "FileFormat");
46         if (mux == HB_MUX_MP4)
47         {
48                 gint source;
49
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);
53                 if (source == VOBSUB)
54                 {
55                         return TRUE;
56                 }
57         }
58         return FALSE;
59 }
60
61 void
62 ghb_subtitle_exclusive_burn(signal_user_data_t *ud, gint index)
63 {
64         GValue *subtitle_list;
65         GValue *settings;
66         gint ii, count, tt;
67         GtkTreeView  *tv;
68         GtkTreeModel *tm;
69         GtkTreeIter   ti;
70         gboolean burned;
71
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++)
76         {
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");
80
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))
86                 {
87                         ghb_settings_set_boolean(settings, "SubtitleBurned", FALSE);
88                         gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, FALSE, -1);
89                 }
90         }
91 }
92
93 void
94 ghb_subtitle_exclusive_default(signal_user_data_t *ud, gint index)
95 {
96         GValue *subtitle_list;
97         GValue *settings;
98         gint ii, count;
99         GtkTreeView  *tv;
100         GtkTreeModel *tm;
101         GtkTreeIter   ti;
102         gboolean def;
103
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++)
108         {
109                 settings = ghb_array_get_nth(subtitle_list, ii);
110                 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
111
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)
117                 {
118
119                         ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", FALSE);
120                         gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 3, FALSE, -1);
121                 }
122         }
123 }
124
125 void
126 ghb_add_subtitle(signal_user_data_t *ud, GValue *settings)
127 {
128         // Add the current subtitle settings to the list.
129         GValue *subtitle_list;
130         gint count;
131         gboolean burned;
132         const gchar *track;
133         gint tt, source;
134         
135         g_debug("ghb_add_subtitle ()");
136
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);
141
142         tt = ghb_settings_get_int(settings, "SubtitleTrack");
143         source = ghb_subtitle_track_source(ud, tt);
144         ghb_settings_set_int(settings, "SubtitleSource", source);
145
146         subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
147         if (subtitle_list == NULL)
148         {
149                 subtitle_list = ghb_array_value_new(8);
150                 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
151         }
152         count = ghb_array_len(subtitle_list);
153
154         // Don't allow more than 99
155         // This is a had limit imposed by libhb/sync.c:GetFifoForId()
156         if (count >= 99)
157         {
158                 ghb_value_free(settings);
159                 return;
160         }
161
162         ghb_array_append(subtitle_list, settings);
163         add_to_subtitle_list(ud, settings);
164
165         burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
166         if (burned)
167                 ghb_subtitle_exclusive_burn(ud, count);
168         if (count == 98)
169         {
170                 GtkWidget *widget;
171                 widget = GHB_WIDGET (ud->builder, "subtitle_add");
172                 gtk_widget_set_sensitive(widget, FALSE);
173         }
174         ghb_live_reset(ud);
175 }
176
177 static void
178 add_all_pref_subtitles(signal_user_data_t *ud)
179 {
180         const GValue *pref_subtitle;
181         GValue *subtitle;
182         gint count, ii, track;
183         char *lang;
184
185         pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList");
186         count = ghb_array_len(pref_subtitle);
187         for (ii = 0; ii < count; ii++)
188         {
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);
195                 g_free(lang);
196                 if (track >= -1)
197                 {
198                         // Add to subtitle list
199                         ghb_settings_set_int(subtitle, "SubtitleTrack", track);
200                         ghb_add_subtitle(ud, subtitle);
201                 }
202         }
203 }
204
205 void
206 ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud)
207 {
208         gint track;
209         GHashTable *track_indices;
210         gchar *lang, *pref_lang = NULL;
211         gchar *audio_lang;
212         gint foreign_lang_index = -1;
213
214         const GValue *pref_subtitle;
215         GValue *subtitle;
216         gint count, ii, jj;
217         
218         g_debug("ghb_set_pref_subtitle %d", titleindex);
219
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:
222         //
223         // The first (default) audio track language does NOT match the users
224         // chosen Preferred Language AND the Preferred Language is NOT Any (und).
225         //
226         audio_lang = ghb_get_user_audio_lang(ud, titleindex, 0);
227         pref_lang = ghb_settings_get_string(ud->settings, "PreferredLanguage");
228
229         if (audio_lang != NULL && pref_lang != NULL &&
230                 (strcmp(audio_lang, pref_lang) == 0 || strcmp("und", pref_lang) == 0))
231         {
232                 g_free(pref_lang);
233                 pref_lang = NULL;
234         }
235
236         track_indices = g_hash_table_new_full(g_str_hash, g_str_equal, 
237                                                                                         free_subtitle_key, free_subtitle_index_list);
238
239         ghb_ui_update(ud, "SubtitleTrack", ghb_int_value(0));
240
241         // Clear the subtitle list
242         ghb_clear_subtitle_list(ud);
243         if (titleindex < 0)
244         {
245                 add_all_pref_subtitles(ud);
246                 return;
247         }
248
249         // Find "best" subtitle based on subtitle preferences
250         pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList");
251
252         count = ghb_array_len(pref_subtitle);
253         jj = 0;
254         for (ii = 0; ii < count; ii++)
255         {
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);
262                 if (track >= -1)
263                 {
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)
268                         {
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));
274                         }
275                         ghb_add_subtitle(ud, dup);
276                         jj++;
277                 }
278                 g_free(lang);
279         }
280         if (foreign_lang_index < 0 && pref_lang != NULL)
281         {
282                 GValue *settings;
283                 gboolean burn;
284
285                 track = ghb_find_subtitle_track(titleindex, pref_lang, track_indices);
286                 if (track >= -1)
287                 {
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));
297
298                         ghb_add_subtitle(ud, settings);
299                         foreign_lang_index = jj;
300                 }
301         }
302         if (foreign_lang_index >= 0)
303         {
304                 GValue *subtitle_list;
305                 gboolean burn, def;
306
307                 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
308                 subtitle = ghb_array_get_nth(subtitle_list, foreign_lang_index);
309
310                 burn = ghb_settings_get_boolean(subtitle, "SubtitleBurned");
311                 def = ghb_settings_get_boolean(subtitle, "SubtitleDefaultTrack");
312                 if (burn)
313                         ghb_subtitle_exclusive_burn(ud, foreign_lang_index);
314                 if (def)
315                         ghb_subtitle_exclusive_default(ud, foreign_lang_index);
316                 ghb_log("adding subtitle for foreign language audio: %s", audio_lang);
317         }
318         if (pref_lang != NULL)
319                 g_free(pref_lang);
320         if (audio_lang != NULL)
321                 g_free(audio_lang);
322         g_hash_table_destroy(track_indices);
323 }
324
325 gint
326 ghb_selected_subtitle_row(signal_user_data_t *ud)
327 {
328         GtkTreeView *treeview;
329         GtkTreePath *treepath;
330         GtkTreeSelection *selection;
331         GtkTreeModel *store;
332         GtkTreeIter iter;
333         gint *indices;
334         gint row = -1;
335         
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))
340         {
341                 // Get the row number
342                 treepath = gtk_tree_model_get_path (store, &iter);
343                 indices = gtk_tree_path_get_indices (treepath);
344                 row = indices[0];
345                 gtk_tree_path_free(treepath);
346         }
347         return row;
348 }
349
350 GValue*
351 ghb_selected_subtitle_settings(signal_user_data_t *ud)
352 {
353         GtkTreeView *treeview;
354         GtkTreePath *treepath;
355         GtkTreeSelection *selection;
356         GtkTreeModel *store;
357         GtkTreeIter iter;
358         gint *indices;
359         gint row;
360         GValue *settings = NULL;
361         const GValue *subtitle_list;
362         
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))
367         {
368                 // Get the row number
369                 treepath = gtk_tree_model_get_path (store, &iter);
370                 indices = gtk_tree_path_get_indices (treepath);
371                 row = indices[0];
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))
377                         return NULL;
378                 settings = ghb_array_get_nth(subtitle_list, row);
379         }
380         return settings;
381 }
382
383 G_MODULE_EXPORT void
384 subtitle_forced_toggled_cb(
385         GtkCellRendererToggle *cell, 
386         gchar                 *path,
387         signal_user_data_t    *ud)
388 {
389         GtkTreeView  *tv;
390         GtkTreeModel *tm;
391         GtkTreeIter   ti;
392         gboolean      active;
393         gint          row;
394         GtkTreePath  *tp;
395         gint *indices;
396         GValue *subtitle_list, *settings;
397         gint source, track;
398
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);
407         active ^= 1;
408
409         // Get the row number
410         indices = gtk_tree_path_get_indices (tp);
411         row = indices[0];
412         gtk_tree_path_free(tp);
413
414         subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
415
416         if (row < 0 || row >= ghb_array_len(subtitle_list))
417                 return;
418
419         settings = ghb_array_get_nth(subtitle_list, row);
420         track = ghb_settings_combo_int(settings, "SubtitleTrack");
421
422         source = ghb_subtitle_track_source(ud, track);
423         if (source != VOBSUB)
424                 return;
425
426         ghb_settings_set_boolean(settings, "SubtitleForced", active);
427         gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 1, active, -1);
428         ghb_live_reset(ud);
429 }
430
431 G_MODULE_EXPORT void
432 subtitle_burned_toggled_cb(
433         GtkCellRendererToggle *cell, 
434         gchar                 *path,
435         signal_user_data_t    *ud)
436 {
437         GtkTreeView  *tv;
438         GtkTreeModel *tm;
439         GtkTreeIter   ti;
440         GtkTreePath  *tp;
441         gboolean      active;
442         gint          row;
443         gint *indices;
444         GValue *subtitle_list;
445         gint count, track, source;
446         GValue *settings;
447
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);
456         active ^= 1;
457
458         // Get the row number
459         indices = gtk_tree_path_get_indices (tp);
460         row = indices[0];
461         gtk_tree_path_free(tp);
462
463         subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
464         count = ghb_array_len(subtitle_list);
465         if (row < 0 || row >= count)
466                 return;
467
468         settings = ghb_array_get_nth(subtitle_list, row);
469         track = ghb_settings_combo_int(settings, "SubtitleTrack");
470
471         source = ghb_subtitle_track_source(ud, track);
472         if (source != VOBSUB)
473                 return;
474
475         if (!active && mustBurn(ud, track))
476                 return;
477
478         ghb_settings_set_boolean(settings, "SubtitleBurned", active);
479
480         gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, active, -1);
481         // Unburn the rest
482         if (active)
483                 ghb_subtitle_exclusive_burn(ud, row);
484         ghb_live_reset(ud);
485 }
486
487 G_MODULE_EXPORT void
488 subtitle_default_toggled_cb(
489         GtkCellRendererToggle *cell, 
490         gchar                 *path,
491         signal_user_data_t    *ud)
492 {
493         GtkTreeView  *tv;
494         GtkTreeModel *tm;
495         GtkTreeIter   ti;
496         GtkTreePath  *tp;
497         gboolean      active;
498         gint          row;
499         gint *indices;
500         GValue *subtitle_list;
501         gint count, track;
502         GValue *settings;
503
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);
512         active ^= 1;
513
514         // Get the row number
515         indices = gtk_tree_path_get_indices (tp);
516         row = indices[0];
517         gtk_tree_path_free(tp);
518
519         subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
520         count = ghb_array_len(subtitle_list);
521         if (row < 0 || row >= count)
522                 return;
523
524         settings = ghb_array_get_nth(subtitle_list, row);
525         track = ghb_settings_combo_int(settings, "SubtitleTrack");
526
527         ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", active);
528
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);
532         ghb_live_reset(ud);
533 }
534
535 static void
536 subtitle_list_refresh_selected(signal_user_data_t *ud)
537 {
538         GtkTreeView *treeview;
539         GtkTreePath *treepath;
540         GtkTreeSelection *selection;
541         GtkTreeModel *store;
542         GtkTreeIter iter;
543         gint *indices;
544         gint row;
545         GValue *settings = NULL;
546         const GValue *subtitle_list;
547         
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))
552         {
553                 const gchar *track, *source;
554                 gboolean forced, burned, def;
555                 gchar *s_track;
556                 gint i_track;
557         
558                 // Get the row number
559                 treepath = gtk_tree_model_get_path (store, &iter);
560                 indices = gtk_tree_path_get_indices (treepath);
561                 row = indices[0];
562                 gtk_tree_path_free(treepath);
563                 // find audio settings
564                 if (row < 0) return;
565                 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
566                 if (row >= ghb_array_len(subtitle_list))
567                         return;
568                 settings = ghb_array_get_nth(subtitle_list, row);
569
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");
574
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);
578
579                 gint i_source;
580                 i_source = ghb_subtitle_track_source(ud, i_track);
581                 if (i_source != VOBSUB)
582                 {
583                         // Force and burn only apply to VOBSUBS
584                         forced = FALSE;
585                         burned = FALSE;
586                         ghb_settings_set_boolean(settings, "SubtitleForced", forced);
587                         ghb_settings_set_boolean(settings, "SubtitleBurned", burned);
588                 }
589
590                 gtk_list_store_set(GTK_LIST_STORE(store), &iter, 
591                         // These are displayed in list
592                         0, track,
593                         1, forced,
594                         2, burned,
595                         3, def,
596                         4, source,
597                         // These are used to set combo box values when a list item is selected
598                         5, s_track,
599                         -1);
600                 g_free(s_track);
601                 if (burned)
602                         ghb_subtitle_exclusive_burn(ud, row);
603         }
604 }
605
606 G_MODULE_EXPORT void
607 subtitle_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
608 {
609         GValue *settings;
610
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)
616         {
617                 const gchar *track;
618                 gint tt, source;
619
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);
627                 ghb_live_reset(ud);
628         }
629         ghb_live_reset(ud);
630 }
631
632 void
633 ghb_clear_subtitle_list(signal_user_data_t *ud)
634 {
635         GtkTreeView *treeview;
636         GtkListStore *store;
637         GValue *subtitle_list;
638         
639         g_debug("clear_subtitle_list ()");
640         subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
641         if (subtitle_list == NULL)
642         {
643                 subtitle_list = ghb_array_value_new(8);
644                 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
645         }
646         else
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);
651 }
652
653 static void
654 add_to_subtitle_list(
655         signal_user_data_t *ud, 
656         GValue *settings)
657 {
658         GtkTreeView *treeview;
659         GtkTreeIter iter;
660         GtkListStore *store;
661         GtkTreeSelection *selection;
662         const gchar *track, *source;
663         gboolean forced, burned, def;
664         gchar *s_track;
665         gint i_track;
666         
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));
671
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");
676
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);
680
681         gtk_list_store_append(store, &iter);
682         gtk_list_store_set(store, &iter, 
683                 // These are displayed in list
684                 0, track,
685                 1, forced,
686                 2, burned,
687                 3, def,
688                 4, source,
689                 // These are used to set combo box values when a list item is selected
690                 5, s_track,
691                 -1);
692         gtk_tree_selection_select_iter(selection, &iter);
693         g_free(s_track);
694 }
695
696 G_MODULE_EXPORT void
697 subtitle_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
698 {
699         GtkTreeModel *store;
700         GtkTreeIter iter;
701         GtkWidget *widget;
702         
703         g_debug("subtitle_list_selection_changed_cb ()");
704         if (gtk_tree_selection_get_selected(selection, &store, &iter))
705         {
706                 const gchar *track;
707
708                 gtk_tree_model_get(store, &iter, 5, &track, -1);
709                 ghb_ui_update(ud, "SubtitleTrack", ghb_string_value(track));
710
711                 widget = GHB_WIDGET (ud->builder, "subtitle_remove");
712                 gtk_widget_set_sensitive(widget, TRUE);
713         }
714 }
715
716 G_MODULE_EXPORT void
717 subtitle_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
718 {
719         // Add the current subtitle settings to the list.
720         GValue *settings;
721         gboolean burned = FALSE;
722         gint track;
723         
724         g_debug("subtitle_add_clicked_cb ()");
725
726         track = ghb_settings_get_int(ud->settings, "SubtitleTrack");
727         if (mustBurn(ud, track))
728         {
729                 burned = TRUE;
730         }
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));
739
740         ghb_add_subtitle(ud, settings);
741 }
742
743 G_MODULE_EXPORT void
744 subtitle_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
745 {
746         GtkTreeView *treeview;
747         GtkTreePath *treepath;
748         GtkTreeSelection *selection;
749         GtkTreeModel *store;
750         GtkTreeIter iter, nextIter;
751         gint *indices;
752         gint row;
753         GValue *subtitle_list;
754
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))
759         {
760                 nextIter = iter;
761                 if (!gtk_tree_model_iter_next(store, &nextIter))
762                 {
763                         nextIter = iter;
764                         if (gtk_tree_model_get_iter_first(store, &nextIter))
765                         {
766                                 gtk_tree_selection_select_iter (selection, &nextIter);
767                         }
768                 }
769                 else
770                 {
771                         gtk_tree_selection_select_iter (selection, &nextIter);
772                 }
773                 // Get the row number
774                 treepath = gtk_tree_model_get_path (store, &iter);
775                 indices = gtk_tree_path_get_indices (treepath);
776                 row = indices[0];
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
781                 if (row < 0) return;
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))
786                         return;
787                 GValue *old = ghb_array_get_nth(subtitle_list, row);
788                 ghb_value_free(old);
789                 ghb_array_remove(subtitle_list, row);
790                 ghb_live_reset(ud);
791         }
792 }
793
794 void
795 ghb_subtitle_prune(signal_user_data_t *ud)
796 {
797         GtkTreeView  *tv;
798         GtkTreeModel *tm;
799         GtkTreeIter   ti;
800         GValue *subtitle_list, *settings;
801         gint count, ii, track;
802         gboolean burned;
803         gint first_track = 0, one_burned = 0;
804
805         subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
806         if (subtitle_list == NULL)
807                 return;
808         count = ghb_array_len(subtitle_list);
809
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--)
814         {
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))
819                 {
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);
823                 }
824                 if (burned)
825                 {
826                         first_track = ii;
827                         one_burned++;
828                 }
829         }
830         if (one_burned)
831         {
832                 ghb_subtitle_exclusive_burn(ud, first_track);
833         }
834 }
835
836 void
837 ghb_reset_subtitles(signal_user_data_t *ud, GValue *settings)
838 {
839         GValue *slist;
840         GValue *subtitle;
841         gint count, ii;
842         gint titleindex;
843         
844         g_debug("ghb_reset_subtitles");
845         ghb_clear_subtitle_list(ud);
846         titleindex = ghb_settings_combo_int(ud->settings, "title");
847         if (titleindex < 0)
848                 return;
849
850         slist = ghb_settings_get_value(settings, "subtitle_list");
851         count = ghb_array_len(slist);
852         for (ii = 0; ii < count; ii++)
853         {
854                 subtitle = ghb_value_dup(ghb_array_get_nth(slist, ii));
855                 ghb_add_subtitle(ud, subtitle);
856         }
857 }
858