OSDN Git Service

31fa4060522038a20108f62a3955d98da0e3ec7c
[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 }
175
176 static void
177 add_all_pref_subtitles(signal_user_data_t *ud)
178 {
179         const GValue *pref_subtitle;
180         GValue *subtitle;
181         gint count, ii, track;
182         char *lang;
183
184         pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList");
185         count = ghb_array_len(pref_subtitle);
186         for (ii = 0; ii < count; ii++)
187         {
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);
194                 g_free(lang);
195                 if (track >= -1)
196                 {
197                         // Add to subtitle list
198                         ghb_settings_set_int(subtitle, "SubtitleTrack", track);
199                         ghb_add_subtitle(ud, subtitle);
200                 }
201         }
202 }
203
204 void
205 ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud)
206 {
207         gint track;
208         GHashTable *track_indices;
209         gchar *lang, *pref_lang = NULL;
210         gchar *audio_lang;
211         gint foreign_lang_index = -1;
212
213         const GValue *pref_subtitle;
214         GValue *subtitle;
215         gint count, ii, jj;
216         
217         g_debug("ghb_set_pref_subtitle %d", titleindex);
218
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:
221         //
222         // The first (default) audio track language does NOT match the users
223         // chosen Preferred Language AND the Preferred Language is NOT Any (und).
224         //
225         audio_lang = ghb_get_user_audio_lang(ud, titleindex, 0);
226         pref_lang = ghb_settings_get_string(ud->settings, "SourceAudioLang");
227
228         if (audio_lang != NULL && pref_lang != NULL &&
229                 (strcmp(audio_lang, pref_lang) == 0 || strcmp("und", pref_lang) == 0))
230         {
231                 g_free(pref_lang);
232                 pref_lang = NULL;
233         }
234
235         track_indices = g_hash_table_new_full(g_str_hash, g_str_equal, 
236                                                                                         free_subtitle_key, free_subtitle_index_list);
237
238         ghb_ui_update(ud, "SubtitleTrack", ghb_int_value(0));
239
240         // Clear the subtitle list
241         ghb_clear_subtitle_list(ud);
242         if (titleindex < 0)
243         {
244                 add_all_pref_subtitles(ud);
245                 return;
246         }
247
248         // Find "best" subtitle based on subtitle preferences
249         pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList");
250
251         count = ghb_array_len(pref_subtitle);
252         jj = 0;
253         for (ii = 0; ii < count; ii++)
254         {
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);
261                 if (track >= -1)
262                 {
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)
267                         {
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));
273                         }
274                         ghb_add_subtitle(ud, dup);
275                         jj++;
276                 }
277                 g_free(lang);
278         }
279         if (foreign_lang_index < 0 && pref_lang != NULL)
280         {
281                 GValue *settings;
282                 gboolean burn;
283
284                 track = ghb_find_subtitle_track(titleindex, pref_lang, track_indices);
285                 if (track >= -1)
286                 {
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));
296
297                         ghb_add_subtitle(ud, settings);
298                         foreign_lang_index = jj;
299                 }
300         }
301         if (foreign_lang_index >= 0)
302         {
303                 GValue *subtitle_list;
304                 gboolean burn, def;
305
306                 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
307                 subtitle = ghb_array_get_nth(subtitle_list, foreign_lang_index);
308
309                 burn = ghb_settings_get_boolean(subtitle, "SubtitleBurned");
310                 def = ghb_settings_get_boolean(subtitle, "SubtitleDefaultTrack");
311                 if (burn)
312                         ghb_subtitle_exclusive_burn(ud, foreign_lang_index);
313                 if (def)
314                         ghb_subtitle_exclusive_default(ud, foreign_lang_index);
315                 ghb_log("adding subtitle for foreign language audio: %s", audio_lang);
316         }
317         if (pref_lang != NULL)
318                 g_free(pref_lang);
319         if (audio_lang != NULL)
320                 g_free(audio_lang);
321         g_hash_table_destroy(track_indices);
322 }
323
324 gint
325 ghb_selected_subtitle_row(signal_user_data_t *ud)
326 {
327         GtkTreeView *treeview;
328         GtkTreePath *treepath;
329         GtkTreeSelection *selection;
330         GtkTreeModel *store;
331         GtkTreeIter iter;
332         gint *indices;
333         gint row = -1;
334         
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))
339         {
340                 // Get the row number
341                 treepath = gtk_tree_model_get_path (store, &iter);
342                 indices = gtk_tree_path_get_indices (treepath);
343                 row = indices[0];
344                 gtk_tree_path_free(treepath);
345         }
346         return row;
347 }
348
349 GValue*
350 ghb_selected_subtitle_settings(signal_user_data_t *ud)
351 {
352         GtkTreeView *treeview;
353         GtkTreePath *treepath;
354         GtkTreeSelection *selection;
355         GtkTreeModel *store;
356         GtkTreeIter iter;
357         gint *indices;
358         gint row;
359         GValue *settings = NULL;
360         const GValue *subtitle_list;
361         
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))
366         {
367                 // Get the row number
368                 treepath = gtk_tree_model_get_path (store, &iter);
369                 indices = gtk_tree_path_get_indices (treepath);
370                 row = indices[0];
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))
376                         return NULL;
377                 settings = ghb_array_get_nth(subtitle_list, row);
378         }
379         return settings;
380 }
381
382 G_MODULE_EXPORT void
383 subtitle_forced_toggled_cb(
384         GtkCellRendererToggle *cell, 
385         gchar                 *path,
386         signal_user_data_t    *ud)
387 {
388         GtkTreeView  *tv;
389         GtkTreeModel *tm;
390         GtkTreeIter   ti;
391         gboolean      active;
392         gint          row;
393         GtkTreePath  *tp;
394         gint *indices;
395         GValue *subtitle_list, *settings;
396         gint source, track;
397
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);
406         active ^= 1;
407
408         // Get the row number
409         indices = gtk_tree_path_get_indices (tp);
410         row = indices[0];
411         gtk_tree_path_free(tp);
412
413         subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
414
415         if (row < 0 || row >= ghb_array_len(subtitle_list))
416                 return;
417
418         settings = ghb_array_get_nth(subtitle_list, row);
419         track = ghb_settings_combo_int(settings, "SubtitleTrack");
420
421         source = ghb_subtitle_track_source(ud, track);
422         if (source != VOBSUB)
423                 return;
424
425         ghb_settings_set_boolean(settings, "SubtitleForced", active);
426         gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 1, active, -1);
427 }
428
429 G_MODULE_EXPORT void
430 subtitle_burned_toggled_cb(
431         GtkCellRendererToggle *cell, 
432         gchar                 *path,
433         signal_user_data_t    *ud)
434 {
435         GtkTreeView  *tv;
436         GtkTreeModel *tm;
437         GtkTreeIter   ti;
438         GtkTreePath  *tp;
439         gboolean      active;
440         gint          row;
441         gint *indices;
442         GValue *subtitle_list;
443         gint count, track, source;
444         GValue *settings;
445
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);
454         active ^= 1;
455
456         // Get the row number
457         indices = gtk_tree_path_get_indices (tp);
458         row = indices[0];
459         gtk_tree_path_free(tp);
460
461         subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
462         count = ghb_array_len(subtitle_list);
463         if (row < 0 || row >= count)
464                 return;
465
466         settings = ghb_array_get_nth(subtitle_list, row);
467         track = ghb_settings_combo_int(settings, "SubtitleTrack");
468
469         source = ghb_subtitle_track_source(ud, track);
470         if (source != VOBSUB)
471                 return;
472
473         if (!active && mustBurn(ud, track))
474                 return;
475
476         ghb_settings_set_boolean(settings, "SubtitleBurned", active);
477
478         gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, active, -1);
479         // Unburn the rest
480         if (active)
481                 ghb_subtitle_exclusive_burn(ud, row);
482 }
483
484 G_MODULE_EXPORT void
485 subtitle_default_toggled_cb(
486         GtkCellRendererToggle *cell, 
487         gchar                 *path,
488         signal_user_data_t    *ud)
489 {
490         GtkTreeView  *tv;
491         GtkTreeModel *tm;
492         GtkTreeIter   ti;
493         GtkTreePath  *tp;
494         gboolean      active;
495         gint          row;
496         gint *indices;
497         GValue *subtitle_list;
498         gint count, track;
499         GValue *settings;
500
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);
509         active ^= 1;
510
511         // Get the row number
512         indices = gtk_tree_path_get_indices (tp);
513         row = indices[0];
514         gtk_tree_path_free(tp);
515
516         subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
517         count = ghb_array_len(subtitle_list);
518         if (row < 0 || row >= count)
519                 return;
520
521         settings = ghb_array_get_nth(subtitle_list, row);
522         track = ghb_settings_combo_int(settings, "SubtitleTrack");
523
524         ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", active);
525
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);
529 }
530
531 static void
532 subtitle_list_refresh_selected(signal_user_data_t *ud)
533 {
534         GtkTreeView *treeview;
535         GtkTreePath *treepath;
536         GtkTreeSelection *selection;
537         GtkTreeModel *store;
538         GtkTreeIter iter;
539         gint *indices;
540         gint row;
541         GValue *settings = NULL;
542         const GValue *subtitle_list;
543         
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))
548         {
549                 const gchar *track, *source;
550                 gboolean forced, burned, def;
551                 gchar *s_track;
552                 gint i_track;
553         
554                 // Get the row number
555                 treepath = gtk_tree_model_get_path (store, &iter);
556                 indices = gtk_tree_path_get_indices (treepath);
557                 row = indices[0];
558                 gtk_tree_path_free(treepath);
559                 // find audio settings
560                 if (row < 0) return;
561                 subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
562                 if (row >= ghb_array_len(subtitle_list))
563                         return;
564                 settings = ghb_array_get_nth(subtitle_list, row);
565
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");
570
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);
574
575                 gint i_source;
576                 i_source = ghb_subtitle_track_source(ud, i_track);
577                 if (i_source != VOBSUB)
578                 {
579                         // Force and burn only apply to VOBSUBS
580                         forced = FALSE;
581                         burned = FALSE;
582                         ghb_settings_set_boolean(settings, "SubtitleForced", forced);
583                         ghb_settings_set_boolean(settings, "SubtitleBurned", burned);
584                 }
585
586                 gtk_list_store_set(GTK_LIST_STORE(store), &iter, 
587                         // These are displayed in list
588                         0, track,
589                         1, forced,
590                         2, burned,
591                         3, def,
592                         4, source,
593                         // These are used to set combo box values when a list item is selected
594                         5, s_track,
595                         -1);
596                 g_free(s_track);
597                 if (burned)
598                         ghb_subtitle_exclusive_burn(ud, row);
599         }
600 }
601
602 G_MODULE_EXPORT void
603 subtitle_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
604 {
605         GValue *settings;
606
607         g_debug("subtitle_track_changed_cb ()");
608         ghb_check_dependency(ud, widget);
609         settings = ghb_selected_subtitle_settings(ud);
610         if (settings != NULL)
611         {
612                 const gchar *track;
613                 gint tt, source;
614
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);
622         }
623         ghb_live_reset(ud);
624 }
625
626 void
627 ghb_clear_subtitle_list(signal_user_data_t *ud)
628 {
629         GtkTreeView *treeview;
630         GtkListStore *store;
631         GValue *subtitle_list;
632         
633         g_debug("clear_subtitle_list ()");
634         subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
635         if (subtitle_list == NULL)
636         {
637                 subtitle_list = ghb_array_value_new(8);
638                 ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list);
639         }
640         else
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);
645 }
646
647 static void
648 add_to_subtitle_list(
649         signal_user_data_t *ud, 
650         GValue *settings)
651 {
652         GtkTreeView *treeview;
653         GtkTreeIter iter;
654         GtkListStore *store;
655         GtkTreeSelection *selection;
656         const gchar *track, *source;
657         gboolean forced, burned, def;
658         gchar *s_track;
659         gint i_track;
660         
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));
665
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");
670
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);
674
675         gtk_list_store_append(store, &iter);
676         gtk_list_store_set(store, &iter, 
677                 // These are displayed in list
678                 0, track,
679                 1, forced,
680                 2, burned,
681                 3, def,
682                 4, source,
683                 // These are used to set combo box values when a list item is selected
684                 5, s_track,
685                 -1);
686         gtk_tree_selection_select_iter(selection, &iter);
687         g_free(s_track);
688 }
689
690 G_MODULE_EXPORT void
691 subtitle_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
692 {
693         GtkTreeModel *store;
694         GtkTreeIter iter;
695         GtkWidget *widget;
696         
697         g_debug("subtitle_list_selection_changed_cb ()");
698         if (gtk_tree_selection_get_selected(selection, &store, &iter))
699         {
700                 const gchar *track;
701
702                 gtk_tree_model_get(store, &iter, 5, &track, -1);
703                 ghb_ui_update(ud, "SubtitleTrack", ghb_string_value(track));
704
705                 widget = GHB_WIDGET (ud->builder, "subtitle_remove");
706                 gtk_widget_set_sensitive(widget, TRUE);
707         }
708 }
709
710 G_MODULE_EXPORT void
711 subtitle_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
712 {
713         // Add the current subtitle settings to the list.
714         GValue *settings;
715         gboolean burned = FALSE;
716         gint track;
717         
718         g_debug("subtitle_add_clicked_cb ()");
719
720         track = ghb_settings_get_int(ud->settings, "SubtitleTrack");
721         if (mustBurn(ud, track))
722         {
723                 burned = TRUE;
724         }
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));
733
734         ghb_add_subtitle(ud, settings);
735 }
736
737 G_MODULE_EXPORT void
738 subtitle_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
739 {
740         GtkTreeView *treeview;
741         GtkTreePath *treepath;
742         GtkTreeSelection *selection;
743         GtkTreeModel *store;
744         GtkTreeIter iter, nextIter;
745         gint *indices;
746         gint row;
747         GValue *subtitle_list;
748
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))
753         {
754                 nextIter = iter;
755                 if (!gtk_tree_model_iter_next(store, &nextIter))
756                 {
757                         nextIter = iter;
758                         if (gtk_tree_model_get_iter_first(store, &nextIter))
759                         {
760                                 gtk_tree_selection_select_iter (selection, &nextIter);
761                         }
762                 }
763                 else
764                 {
765                         gtk_tree_selection_select_iter (selection, &nextIter);
766                 }
767                 // Get the row number
768                 treepath = gtk_tree_model_get_path (store, &iter);
769                 indices = gtk_tree_path_get_indices (treepath);
770                 row = indices[0];
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
775                 if (row < 0) return;
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))
780                         return;
781                 GValue *old = ghb_array_get_nth(subtitle_list, row);
782                 ghb_value_free(old);
783                 ghb_array_remove(subtitle_list, row);
784         }
785 }
786
787 void
788 ghb_subtitle_prune(signal_user_data_t *ud)
789 {
790         GtkTreeView  *tv;
791         GtkTreeModel *tm;
792         GtkTreeIter   ti;
793         GValue *subtitle_list, *settings;
794         gint count, ii, track;
795         gboolean burned;
796         gint first_track = 0, one_burned = 0;
797
798         subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
799         if (subtitle_list == NULL)
800                 return;
801         count = ghb_array_len(subtitle_list);
802
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--)
807         {
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))
812                 {
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);
816                 }
817                 if (burned)
818                 {
819                         first_track = ii;
820                         one_burned++;
821                 }
822         }
823         if (one_burned)
824         {
825                 ghb_subtitle_exclusive_burn(ud, first_track);
826         }
827 }
828
829 void
830 ghb_reset_subtitles(signal_user_data_t *ud, GValue *settings)
831 {
832         GValue *slist;
833         GValue *subtitle;
834         gint count, ii;
835         gint titleindex;
836         
837         g_debug("ghb_reset_subtitles");
838         ghb_clear_subtitle_list(ud);
839         titleindex = ghb_settings_combo_int(ud->settings, "title");
840         if (titleindex < 0)
841                 return;
842
843         slist = ghb_settings_get_value(settings, "subtitle_list");
844         count = ghb_array_len(slist);
845         for (ii = 0; ii < count; ii++)
846         {
847                 subtitle = ghb_value_dup(ghb_array_get_nth(slist, ii));
848                 ghb_add_subtitle(ud, subtitle);
849         }
850 }
851