OSDN Git Service

LinGui: fix some spam in the log about hash item not found
[handbrake-jp/handbrake-jp-git.git] / gtk / src / hb-backend.c
1 /***************************************************************************
2  *            hb-backend.c
3  *
4  *  Fri Mar 28 10:38:44 2008
5  *  Copyright  2008  John Stebbins
6  *  <john at stebbins dot name>
7  ****************************************************************************/
8
9 /*
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Library General Public License for more details.
19  * 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
23  */
24 #define _GNU_SOURCE
25 #include <limits.h>
26 #include <math.h>
27 #include "hb.h"
28 #include <gtk/gtk.h>
29 #include <glib/gstdio.h>
30 #include "hb-backend.h"
31 #include "settings.h"
32 #include "callbacks.h"
33 #include "subtitlehandler.h"
34 #include "audiohandler.h"
35 #include "x264handler.h"
36 #include "preview.h"
37 #include "values.h"
38 #include "lang.h"
39
40 typedef struct
41 {
42         const gchar *option;
43         const gchar *shortOpt;
44         gdouble ivalue;
45         const gchar *svalue;
46 } options_map_t;
47
48 typedef struct
49 {
50         gint count;
51         options_map_t *map;
52 } combo_opts_t;
53
54 static gchar **index_str = NULL;
55 static gint index_str_size = 0;
56
57 static void 
58 index_str_init(gint max_index)
59 {
60         int ii;
61
62         if (max_index+1 > index_str_size)
63         {
64                 index_str = realloc(index_str, (max_index+1) * sizeof(char*));
65                 for (ii = index_str_size; ii <= max_index; ii++)
66                 {
67                         index_str[ii] = g_strdup_printf("%d", ii);
68                 }
69                 index_str_size = max_index + 1;
70         }
71 }
72
73 static options_map_t d_point_to_point_opts[] =
74 {
75         {"Chapters:",       "chapter", 0, "0"},
76         {"Seconds:", "time",    1, "1"},
77         {"Frames:",   "frame",   2, "2"},
78 };
79 combo_opts_t point_to_point_opts =
80 {
81         sizeof(d_point_to_point_opts)/sizeof(options_map_t),
82         d_point_to_point_opts
83 };
84
85 static options_map_t d_when_complete_opts[] =
86 {
87         {"Do Nothing",            "nothing",  0, "0"},
88         {"Show Notification",     "notify",   1, "1"},
89         {"Put Computer To Sleep", "sleep",    2, "2"},
90         {"Shutdown Computer",     "shutdown", 3, "3"},
91 };
92 combo_opts_t when_complete_opts =
93 {
94         sizeof(d_when_complete_opts)/sizeof(options_map_t),
95         d_when_complete_opts
96 };
97
98 static options_map_t d_par_opts[] =
99 {
100         {"Off", "0", 0, "0"},
101         {"Strict", "1", 1, "1"},
102         {"Loose", "2", 2, "2"},
103         {"Custom", "3", 3, "3"},
104 };
105 combo_opts_t par_opts =
106 {
107         sizeof(d_par_opts)/sizeof(options_map_t),
108         d_par_opts
109 };
110
111 static options_map_t d_alignment_opts[] =
112 {
113         {"2", "2", 2, "2"},
114         {"4", "4", 4, "4"},
115         {"8", "8", 8, "8"},
116         {"16", "16", 16, "16"},
117 };
118 combo_opts_t alignment_opts =
119 {
120         sizeof(d_alignment_opts)/sizeof(options_map_t),
121         d_alignment_opts
122 };
123
124 static options_map_t d_logging_opts[] =
125 {
126         {"0", "0", 0, "0"},
127         {"1", "1", 1, "1"},
128         {"2", "2", 2, "2"},
129 };
130 combo_opts_t logging_opts =
131 {
132         sizeof(d_logging_opts)/sizeof(options_map_t),
133         d_logging_opts
134 };
135
136 static options_map_t d_log_longevity_opts[] =
137 {
138         {"Week",     "week",     7, "7"},
139         {"Month",    "month",    30, "30"},
140         {"Year",     "year",     365, "365"},
141         {"Immortal", "immortal", 366, "366"},
142 };
143 combo_opts_t log_longevity_opts =
144 {
145         sizeof(d_log_longevity_opts)/sizeof(options_map_t),
146         d_log_longevity_opts
147 };
148
149 static options_map_t d_appcast_update_opts[] =
150 {
151         {"Never", "never", 0, "never"},
152         {"Daily", "daily", 1, "daily"},
153         {"Weekly", "weekly", 2, "weekly"},
154         {"Monthly", "monthly", 3, "monthly"},
155 };
156 combo_opts_t appcast_update_opts =
157 {
158         sizeof(d_appcast_update_opts)/sizeof(options_map_t),
159         d_appcast_update_opts
160 };
161
162 static options_map_t d_vqual_granularity_opts[] =
163 {
164         {"0.2",  "0.2",  0.2,  "0.2"},
165         {"0.25", "0.25", 0.25, "0.25"},
166         {"0.5",  "0.5",  0.5,  "0.5"},
167         {"1",    "1",    1,    "1"},
168 };
169 combo_opts_t vqual_granularity_opts =
170 {
171         sizeof(d_vqual_granularity_opts)/sizeof(options_map_t),
172         d_vqual_granularity_opts
173 };
174
175 static options_map_t d_container_opts[] =
176 {
177         {"MKV", "mkv", HB_MUX_MKV, "mkv"},
178         {"MP4", "mp4", HB_MUX_MP4, "mp4"},
179 };
180 combo_opts_t container_opts =
181 {
182         sizeof(d_container_opts)/sizeof(options_map_t),
183         d_container_opts
184 };
185
186 static options_map_t d_detel_opts[] =
187 {
188         {"Off",    "off",   0, ""},
189         {"Custom", "custom", 1, ""},
190         {"Default","default",2, NULL},
191 };
192 combo_opts_t detel_opts =
193 {
194         sizeof(d_detel_opts)/sizeof(options_map_t),
195         d_detel_opts
196 };
197
198 static options_map_t d_decomb_opts[] =
199 {
200         {"Off",    "off",   0, ""},
201         {"Custom", "custom", 1, ""},
202         {"Default","default",2, NULL},
203 };
204 combo_opts_t decomb_opts =
205 {
206         sizeof(d_decomb_opts)/sizeof(options_map_t),
207         d_decomb_opts
208 };
209
210 static options_map_t d_deint_opts[] =
211 {
212         {"Off",    "off",   0, ""},
213         {"Custom", "custom", 1, ""},
214         {"Fast",   "fast",   2, "-1:-1:-1:0:1"},
215         {"Slow",   "slow",   3, "2:-1:-1:0:1"},
216         {"Slower", "slower", 4, "0:-1:-1:0:1"},
217 };
218 combo_opts_t deint_opts =
219 {
220         sizeof(d_deint_opts)/sizeof(options_map_t),
221         d_deint_opts
222 };
223
224 static options_map_t d_denoise_opts[] =
225 {
226         {"Off",    "off",   0, ""},
227         {"Custom", "custom", 1, ""},
228         {"Weak",   "weak",   2, "2:1:2:3"},
229         {"Medium", "medium", 3, "3:2:2:3"},
230         {"Strong", "strong", 4, "7:7:5:5"},
231 };
232 combo_opts_t denoise_opts =
233 {
234         sizeof(d_denoise_opts)/sizeof(options_map_t),
235         d_denoise_opts
236 };
237
238 static options_map_t d_vcodec_opts[] =
239 {
240         {"H.264 (x264)",    "x264",   HB_VCODEC_X264, ""},
241         {"MPEG-4 (FFmpeg)", "ffmpeg", HB_VCODEC_FFMPEG, ""},
242         {"VP3 (Theora)",    "theora", HB_VCODEC_THEORA, ""},
243 };
244 combo_opts_t vcodec_opts =
245 {
246         sizeof(d_vcodec_opts)/sizeof(options_map_t),
247         d_vcodec_opts
248 };
249
250 static options_map_t d_acodec_opts[] =
251 {
252         {"AAC (faac)",      "faac",   HB_ACODEC_FAAC,   "faac"},
253         {"MP3 (lame)",      "lame",   HB_ACODEC_LAME,   "lame"},
254         {"Vorbis",          "vorbis", HB_ACODEC_VORBIS, "vorbis"},
255         {"AC3 (pass-thru)", "ac3",    HB_ACODEC_AC3,    "ac3"},
256         {"DTS (pass-thru)", "dts",    HB_ACODEC_DCA,    "dts"},
257         {"Choose For Me",   "auto",   HB_ACODEC_MASK,   "auto"},
258 };
259 combo_opts_t acodec_opts =
260 {
261         sizeof(d_acodec_opts)/sizeof(options_map_t),
262         d_acodec_opts
263 };
264
265 static options_map_t d_direct_opts[] =
266 {
267         {"None",      "none",     0, "none"},
268         {"Spatial",   "spatial",  1, "spatial"},
269         {"Temporal",  "temporal", 2, "temporal"},
270         {"Automatic", "auto",     3, "auto"},
271 };
272 combo_opts_t direct_opts =
273 {
274         sizeof(d_direct_opts)/sizeof(options_map_t),
275         d_direct_opts
276 };
277
278 static options_map_t d_badapt_opts[] =
279 {
280         {"Off",             "0", 0, "0"},
281         {"Fast",            "1", 1, "1"},
282         {"Optimal",         "2", 2, "2"},
283 };
284 combo_opts_t badapt_opts =
285 {
286         sizeof(d_badapt_opts)/sizeof(options_map_t),
287         d_badapt_opts
288 };
289
290 static options_map_t d_me_opts[] =
291 {
292         {"Diamond",              "dia",  0, "dia"},
293         {"Hexagon",              "hex",  1, "hex"},
294         {"Uneven Multi-Hexagon", "umh",  2, "umh"},
295         {"Exhaustive",           "esa",  3, "esa"},
296         {"Hadamard Exhaustive",  "tesa", 4, "tesa"},
297 };
298 combo_opts_t me_opts =
299 {
300         sizeof(d_me_opts)/sizeof(options_map_t),
301         d_me_opts
302 };
303
304 static options_map_t d_subme_opts[] =
305 {
306         {"1", "1", 1, "1"},
307         {"2", "2", 2, "2"},
308         {"3", "3", 3, "3"},
309         {"4", "4", 4, "4"},
310         {"5", "5", 5, "5"},
311         {"6", "6", 6, "6"},
312         {"7", "7", 7, "7"},
313         {"8", "8", 8, "8"},
314         {"9", "9", 9, "9"},
315         {"10", "10", 10, "10"},
316 };
317 combo_opts_t subme_opts =
318 {
319         sizeof(d_subme_opts)/sizeof(options_map_t),
320         d_subme_opts
321 };
322
323 static options_map_t d_analyse_opts[] =
324 {
325         {"Some", "some", 0, "some"},
326         {"None", "none", 1, "none"},
327         {"All",  "all",  2, "all"},
328         {"Custom",  "custom",  3, "all"},
329 };
330 combo_opts_t analyse_opts =
331 {
332         sizeof(d_analyse_opts)/sizeof(options_map_t),
333         d_analyse_opts
334 };
335
336 static options_map_t d_trellis_opts[] =
337 {
338         {"Disabled",          "0", 0, "0"},
339         {"Final Macro Block", "1", 1, "1"},
340         {"Always",            "2", 2, "2"},
341 };
342 combo_opts_t trellis_opts =
343 {
344         sizeof(d_trellis_opts)/sizeof(options_map_t),
345         d_trellis_opts
346 };
347
348 combo_opts_t subtitle_opts =
349 {
350         0,
351         NULL
352 };
353
354 combo_opts_t title_opts =
355 {
356         0,
357         NULL
358 };
359
360 combo_opts_t audio_track_opts =
361 {
362         0,
363         NULL
364 };
365
366 typedef struct
367 {
368         const gchar *name;
369         combo_opts_t *opts;
370 } combo_name_map_t;
371
372 combo_name_map_t combo_name_map[] =
373 {
374         {"PtoPType", &point_to_point_opts},
375         {"WhenComplete", &when_complete_opts},
376         {"PicturePAR", &par_opts},
377         {"PictureModulus", &alignment_opts},
378         {"LoggingLevel", &logging_opts},
379         {"LogLongevity", &log_longevity_opts},
380         {"check_updates", &appcast_update_opts},
381         {"VideoQualityGranularity", &vqual_granularity_opts},
382         {"FileFormat", &container_opts},
383         {"PictureDeinterlace", &deint_opts},
384         {"PictureDecomb", &decomb_opts},
385         {"PictureDetelecine", &detel_opts},
386         {"PictureDenoise", &denoise_opts},
387         {"VideoEncoder", &vcodec_opts},
388         {"AudioEncoder", &acodec_opts},
389         {"x264_direct", &direct_opts},
390         {"x264_b_adapt", &badapt_opts},
391         {"x264_me", &me_opts},
392         {"x264_subme", &subme_opts},
393         {"x264_analyse", &analyse_opts},
394         {"x264_trellis", &trellis_opts},
395         {"SubtitleTrack", &subtitle_opts},
396         {"title", &title_opts},
397         {"AudioTrack", &audio_track_opts},
398         {NULL, NULL}
399 };
400
401 const gchar *srt_codeset_table[] =
402 {
403         "ANSI_X3.4-1968",
404         "ANSI_X3.4-1986",
405         "ANSI_X3.4",
406         "ANSI_X3.110-1983",
407         "ANSI_X3.110",
408         "ASCII",
409         "ECMA-114",
410         "ECMA-118",
411         "ECMA-128",
412         "ECMA-CYRILLIC",
413         "IEC_P27-1",
414         "ISO-8859-1",
415         "ISO-8859-2",
416         "ISO-8859-3",
417         "ISO-8859-4",
418         "ISO-8859-5",
419         "ISO-8859-6",
420         "ISO-8859-7",
421         "ISO-8859-8",
422         "ISO-8859-9",
423         "ISO-8859-9E",
424         "ISO-8859-10",
425         "ISO-8859-11",
426         "ISO-8859-13",
427         "ISO-8859-14",
428         "ISO-8859-15",
429         "ISO-8859-16",
430         "UTF-7",
431         "UTF-8",
432         "UTF-16",
433         "UTF-16LE",
434         "UTF-16BE",
435         "UTF-32",
436         "UTF-32LE",
437         "UTF-32BE",
438         NULL
439 };
440 #define SRT_TABLE_SIZE (sizeof(srt_codeset_table)/ sizeof(char*)-1)
441
442 #if 0
443 typedef struct iso639_lang_t
444 {
445     char * eng_name;        /* Description in English */
446     char * native_name;     /* Description in native language */
447     char * iso639_1;       /* ISO-639-1 (2 characters) code */
448     char * iso639_2;        /* ISO-639-2/t (3 character) code */
449     char * iso639_2b;       /* ISO-639-2/b code (if different from above) */
450 } iso639_lang_t;
451 #endif
452
453 const iso639_lang_t ghb_language_table[] =
454
455         { "Any", "", "zz", "und" },
456         { "Afar", "", "aa", "aar" },
457         { "Abkhazian", "", "ab", "abk" },
458         { "Afrikaans", "", "af", "afr" },
459         { "Akan", "", "ak", "aka" },
460         { "Albanian", "", "sq", "sqi", "alb" },
461         { "Amharic", "", "am", "amh" },
462         { "Arabic", "", "ar", "ara" },
463         { "Aragonese", "", "an", "arg" },
464         { "Armenian", "", "hy", "hye", "arm" },
465         { "Assamese", "", "as", "asm" },
466         { "Avaric", "", "av", "ava" },
467         { "Avestan", "", "ae", "ave" },
468         { "Aymara", "", "ay", "aym" },
469         { "Azerbaijani", "", "az", "aze" },
470         { "Bashkir", "", "ba", "bak" },
471         { "Bambara", "", "bm", "bam" },
472         { "Basque", "", "eu", "eus", "baq" },
473         { "Belarusian", "", "be", "bel" },
474         { "Bengali", "", "bn", "ben" },
475         { "Bihari", "", "bh", "bih" },
476         { "Bislama", "", "bi", "bis" },
477         { "Bosnian", "", "bs", "bos" },
478         { "Breton", "", "br", "bre" },
479         { "Bulgarian", "", "bg", "bul" },
480         { "Burmese", "", "my", "mya", "bur" },
481         { "Catalan", "", "ca", "cat" },
482         { "Chamorro", "", "ch", "cha" },
483         { "Chechen", "", "ce", "che" },
484         { "Chinese", "", "zh", "zho", "chi" },
485         { "Church Slavic", "", "cu", "chu" },
486         { "Chuvash", "", "cv", "chv" },
487         { "Cornish", "", "kw", "cor" },
488         { "Corsican", "", "co", "cos" },
489         { "Cree", "", "cr", "cre" },
490         { "Czech", "", "cs", "ces", "cze" },
491         { "Danish", "Dansk", "da", "dan" },
492         { "German", "Deutsch", "de", "deu", "ger" },
493         { "Divehi", "", "dv", "div" },
494         { "Dzongkha", "", "dz", "dzo" },
495         { "English", "English", "en", "eng" },
496         { "Spanish", "Espanol", "es", "spa" },
497         { "Esperanto", "", "eo", "epo" },
498         { "Estonian", "", "et", "est" },
499         { "Ewe", "", "ee", "ewe" },
500         { "Faroese", "", "fo", "fao" },
501         { "Fijian", "", "fj", "fij" },
502         { "French", "Francais", "fr", "fra", "fre" },
503         { "Western Frisian", "", "fy", "fry" },
504         { "Fulah", "", "ff", "ful" },
505         { "Georgian", "", "ka", "kat", "geo" },
506         { "Gaelic (Scots)", "", "gd", "gla" },
507         { "Irish", "", "ga", "gle" },
508         { "Galician", "", "gl", "glg" },
509         { "Manx", "", "gv", "glv" },
510         { "Greek, Modern", "", "el", "ell", "gre" },
511         { "Guarani", "", "gn", "grn" },
512         { "Gujarati", "", "gu", "guj" },
513         { "Haitian", "", "ht", "hat" },
514         { "Hausa", "", "ha", "hau" },
515         { "Hebrew", "", "he", "heb" },
516         { "Herero", "", "hz", "her" },
517         { "Hindi", "", "hi", "hin" },
518         { "Hiri Motu", "", "ho", "hmo" },
519         { "Croatian", "Hrvatski", "hr", "hrv", "scr" },
520         { "Igbo", "", "ig", "ibo" },
521         { "Ido", "", "io", "ido" },
522         { "Icelandic", "Islenska", "is", "isl", "ice" },
523         { "Sichuan Yi", "", "ii", "iii" },
524         { "Inuktitut", "", "iu", "iku" },
525         { "Interlingue", "", "ie", "ile" },
526         { "Interlingua", "", "ia", "ina" },
527         { "Indonesian", "", "id", "ind" },
528         { "Inupiaq", "", "ik", "ipk" },
529         { "Italian", "Italiano", "it", "ita" },
530         { "Javanese", "", "jv", "jav" },
531         { "Japanese", "", "ja", "jpn" },
532         { "Kalaallisut", "", "kl", "kal" },
533         { "Kannada", "", "kn", "kan" },
534         { "Kashmiri", "", "ks", "kas" },
535         { "Kanuri", "", "kr", "kau" },
536         { "Kazakh", "", "kk", "kaz" },
537         { "Central Khmer", "", "km", "khm" },
538         { "Kikuyu", "", "ki", "kik" },
539         { "Kinyarwanda", "", "rw", "kin" },
540         { "Kirghiz", "", "ky", "kir" },
541         { "Komi", "", "kv", "kom" },
542         { "Kongo", "", "kg", "kon" },
543         { "Korean", "", "ko", "kor" },
544         { "Kuanyama", "", "kj", "kua" },
545         { "Kurdish", "", "ku", "kur" },
546         { "Lao", "", "lo", "lao" },
547         { "Latin", "", "la", "lat" },
548         { "Latvian", "", "lv", "lav" },
549         { "Limburgan", "", "li", "lim" },
550         { "Lingala", "", "ln", "lin" },
551         { "Lithuanian", "", "lt", "lit" },
552         { "Luxembourgish", "", "lb", "ltz" },
553         { "Luba-Katanga", "", "lu", "lub" },
554         { "Ganda", "", "lg", "lug" },
555         { "Macedonian", "", "mk", "mkd", "mac" },
556         { "Hungarian", "Magyar", "hu", "hun" },
557         { "Marshallese", "", "mh", "mah" },
558         { "Malayalam", "", "ml", "mal" },
559         { "Maori", "", "mi", "mri", "mao" },
560         { "Marathi", "", "mr", "mar" },
561         { "Malay", "", "ms", "msa", "msa" },
562         { "Malagasy", "", "mg", "mlg" },
563         { "Maltese", "", "mt", "mlt" },
564         { "Moldavian", "", "mo", "mol" },
565         { "Mongolian", "", "mn", "mon" },
566         { "Nauru", "", "na", "nau" },
567         { "Navajo", "", "nv", "nav" },
568         { "Dutch", "Nederlands", "nl", "nld", "dut" },
569         { "Ndebele, South", "", "nr", "nbl" },
570         { "Ndebele, North", "", "nd", "nde" },
571         { "Ndonga", "", "ng", "ndo" },
572         { "Nepali", "", "ne", "nep" },
573         { "Norwegian", "Norsk", "no", "nor" },
574         { "Norwegian Nynorsk", "", "nn", "nno" },
575         { "Norwegian Bokmål", "", "nb", "nob" },
576         { "Chichewa; Nyanja", "", "ny", "nya" },
577         { "Occitan", "", "oc", "oci" },
578         { "Ojibwa", "", "oj", "oji" },
579         { "Oriya", "", "or", "ori" },
580         { "Oromo", "", "om", "orm" },
581         { "Ossetian", "", "os", "oss" },
582         { "Panjabi", "", "pa", "pan" },
583         { "Persian", "", "fa", "fas", "per" },
584         { "Pali", "", "pi", "pli" },
585         { "Polish", "", "pl", "pol" },
586         { "Portuguese", "Portugues", "pt", "por" },
587         { "Pushto", "", "ps", "pus" },
588         { "Quechua", "", "qu", "que" },
589         { "Romansh", "", "rm", "roh" },
590         { "Romanian", "", "ro", "ron", "rum" },
591         { "Rundi", "", "rn", "run" },
592         { "Russian", "", "ru", "rus" },
593         { "Sango", "", "sg", "sag" },
594         { "Sanskrit", "", "sa", "san" },
595         { "Serbian", "", "sr", "srp", "scc" },
596         { "Sinhala", "", "si", "sin" },
597         { "Slovak", "", "sk", "slk", "slo" },
598         { "Slovenian", "", "sl", "slv" },
599         { "Northern Sami", "", "se", "sme" },
600         { "Samoan", "", "sm", "smo" },
601         { "Shona", "", "sn", "sna" },
602         { "Sindhi", "", "sd", "snd" },
603         { "Somali", "", "so", "som" },
604         { "Sotho, Southern", "", "st", "sot" },
605         { "Sardinian", "", "sc", "srd" },
606         { "Swati", "", "ss", "ssw" },
607         { "Sundanese", "", "su", "sun" },
608         { "Finnish", "Suomi", "fi", "fin" },
609         { "Swahili", "", "sw", "swa" },
610         { "Swedish", "Svenska", "sv", "swe" },
611         { "Tahitian", "", "ty", "tah" },
612         { "Tamil", "", "ta", "tam" },
613         { "Tatar", "", "tt", "tat" },
614         { "Telugu", "", "te", "tel" },
615         { "Tajik", "", "tg", "tgk" },
616         { "Tagalog", "", "tl", "tgl" },
617         { "Thai", "", "th", "tha" },
618         { "Tibetan", "", "bo", "bod", "tib" },
619         { "Tigrinya", "", "ti", "tir" },
620         { "Tonga", "", "to", "ton" },
621         { "Tswana", "", "tn", "tsn" },
622         { "Tsonga", "", "ts", "tso" },
623         { "Turkmen", "", "tk", "tuk" },
624         { "Turkish", "", "tr", "tur" },
625         { "Twi", "", "tw", "twi" },
626         { "Uighur", "", "ug", "uig" },
627         { "Ukrainian", "", "uk", "ukr" },
628         { "Urdu", "", "ur", "urd" },
629         { "Uzbek", "", "uz", "uzb" },
630         { "Venda", "", "ve", "ven" },
631         { "Vietnamese", "", "vi", "vie" },
632         { "Volapük", "", "vo", "vol" },
633         { "Welsh", "", "cy", "cym", "wel" },
634         { "Walloon", "", "wa", "wln" },
635         { "Wolof", "", "wo", "wol" },
636         { "Xhosa", "", "xh", "xho" },
637         { "Yiddish", "", "yi", "yid" },
638         { "Yoruba", "", "yo", "yor" },
639         { "Zhuang", "", "za", "zha" },
640         { "Zulu", "", "zu", "zul" },
641         {NULL, NULL, NULL, NULL}
642 };
643 #define LANG_TABLE_SIZE (sizeof(ghb_language_table)/ sizeof(iso639_lang_t)-1)
644
645 static void audio_bitrate_opts_set(GtkBuilder *builder, const gchar *name);
646
647 static void
648 del_tree(const gchar *name, gboolean del_top)
649 {
650         const gchar *file;
651
652         if (g_file_test(name, G_FILE_TEST_IS_DIR))
653         {
654                 GDir *gdir = g_dir_open(name, 0, NULL);
655                 file = g_dir_read_name(gdir);
656                 while (file)
657                 {
658                         gchar *path;
659                         path = g_strdup_printf("%s/%s", name, file);
660                         del_tree(path, TRUE);
661                         g_free(path);
662                         file = g_dir_read_name(gdir);
663                 }
664                 if (del_top)
665                         g_rmdir(name);
666                 g_dir_close(gdir);
667         }
668         else
669         {
670                 g_unlink(name);
671         }
672 }
673
674 const gchar*
675 ghb_version()
676 {
677         return hb_get_version(NULL);
678 }
679
680 void
681 ghb_vquality_range(
682         signal_user_data_t *ud, 
683         gdouble *min, 
684         gdouble *max,
685         gdouble *step,
686         gdouble *page,
687         gint *digits,
688         gboolean *inverted)
689 {
690         gint vcodec = ghb_settings_combo_int(ud->settings, "VideoEncoder");
691         *page = 10;
692         *digits = 0;
693         switch (vcodec)
694         {
695                 case HB_VCODEC_X264:
696                 {
697                         *min = 0;
698                         *max = 51;
699                         *step = ghb_settings_combo_double(ud->settings, 
700                                                                                         "VideoQualityGranularity");
701                         if (*step == 0.2 || *step == 0.5)
702                                 *digits = 1;
703                         else if (*step == 0.25)
704                                 *digits = 2;
705                         *inverted = TRUE;
706                 } break;
707
708                 case HB_VCODEC_FFMPEG:
709                 {
710                         *min = 1;
711                         *max = 31;
712                         *step = 1;
713                         *inverted = TRUE;
714                 } break;
715
716                 case HB_VCODEC_THEORA:
717                 {
718                         *min = 0;
719                         *max = 63;
720                         *step = 1;
721                         *inverted = FALSE;
722                 } break;
723
724                 default:
725                 {
726                         *min = 0;
727                         *max = 100;
728                         *step = 1;
729                         *inverted = FALSE;
730                 } break;
731         }
732 }
733
734 static const gchar*
735 lookup_generic_string(combo_opts_t *opts, const GValue *gval)
736 {
737         gint ii;
738         gchar *str;
739         const gchar *result = "";
740
741         str = ghb_value_string(gval);
742         for (ii = 0; ii < opts->count; ii++)
743         {
744                 if (strcmp(opts->map[ii].shortOpt, str) == 0)
745                 {
746                         result = opts->map[ii].svalue;
747                         break;
748                 }
749         }
750         g_free(str);
751         return result;
752 }
753
754 static gint
755 lookup_generic_int(combo_opts_t *opts, const GValue *gval)
756 {
757         gint ii;
758         gchar *str;
759         gint result = -1;
760
761         str = ghb_value_string(gval);
762         for (ii = 0; ii < opts->count; ii++)
763         {
764                 if (strcmp(opts->map[ii].shortOpt, str) == 0)
765                 {
766                         result = opts->map[ii].ivalue;
767                         break;
768                 }
769         }
770         g_free(str);
771         return result;
772 }
773
774 static gdouble
775 lookup_generic_double(combo_opts_t *opts, const GValue *gval)
776 {
777         gint ii;
778         gchar *str;
779         gdouble result = -1;
780
781         str = ghb_value_string(gval);
782         for (ii = 0; ii < opts->count; ii++)
783         {
784                 if (strcmp(opts->map[ii].shortOpt, str) == 0)
785                 {
786                         result = opts->map[ii].ivalue;
787                         break;
788                 }
789         }
790         g_free(str);
791         return result;
792 }
793
794 static const gchar*
795 lookup_generic_option(combo_opts_t *opts, const GValue *gval)
796 {
797         gint ii;
798         gchar *str;
799         const gchar *result = "";
800
801         str = ghb_value_string(gval);
802         for (ii = 0; ii < opts->count; ii++)
803         {
804                 if (strcmp(opts->map[ii].shortOpt, str) == 0)
805                 {
806                         result = opts->map[ii].option;
807                         break;
808                 }
809         }
810         g_free(str);
811         return result;
812 }
813
814 static gint
815 lookup_mix_int(const GValue *mix)
816 {
817         gint ii;
818         gchar *str;
819         gint result = 0;
820
821
822         str = ghb_value_string(mix);
823         for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
824         {
825                 if (strcmp(hb_audio_mixdowns[ii].short_name, str) == 0)
826                 {
827                         result = hb_audio_mixdowns[ii].amixdown;
828                         break;
829                 }
830         }
831         g_free(str);
832         return result;
833 }
834
835 static const gchar*
836 lookup_mix_option(const GValue *mix)
837 {
838         gint ii;
839         gchar *str;
840         gchar *result = "None";
841
842
843         str = ghb_value_string(mix);
844         for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
845         {
846                 if (strcmp(hb_audio_mixdowns[ii].short_name, str) == 0)
847                 {
848                         result = hb_audio_mixdowns[ii].human_readable_name;
849                         break;
850                 }
851         }
852         g_free(str);
853         return result;
854 }
855
856 static gint
857 lookup_video_rate_int(const GValue *vrate)
858 {
859         gint ii;
860         gchar *str;
861         gint result = 0;
862
863         str = ghb_value_string(vrate);
864         for (ii = 0; ii < hb_video_rates_count; ii++)
865         {
866                 if (strcmp(hb_video_rates[ii].string, str) == 0)
867                 {
868                         result = hb_video_rates[ii].rate;
869                         break;
870                 }
871         }
872         g_free(str);
873         // Default to "same as source"
874         return result;
875 }
876
877 static const gchar*
878 lookup_video_rate_option(const GValue *vrate)
879 {
880         gint ii;
881         gchar *str;
882         const gchar *result = "Same as source";
883
884         str = ghb_value_string(vrate);
885         for (ii = 0; ii < hb_video_rates_count; ii++)
886         {
887                 if (strcmp(hb_video_rates[ii].string, str) == 0)
888                 {
889                         result = hb_video_rates[ii].string;
890                         break;
891                 }
892         }
893         g_free(str);
894         // Default to "same as source"
895         return result;
896 }
897
898 static gint
899 lookup_audio_rate_int(const GValue *rate)
900 {
901         gint ii;
902         gchar *str;
903         gint result = 0;
904
905         // Coincidentally, the string "source" will return 0
906         // which is our flag to use "same as source"
907         str = ghb_value_string(rate);
908         for (ii = 0; ii < hb_audio_rates_count; ii++)
909         {
910                 if (strcmp(hb_audio_rates[ii].string, str) == 0)
911                 {
912                         result = hb_audio_rates[ii].rate;
913                         break;
914                 }
915         }
916         g_free(str);
917         return result;
918 }
919
920 static const gchar*
921 lookup_audio_rate_option(const GValue *rate)
922 {
923         gint ii;
924         gchar *str;
925         const gchar *result = "Same as source";
926
927         // Coincidentally, the string "source" will return 0
928         // which is our flag to use "same as source"
929         str = ghb_value_string(rate);
930         for (ii = 0; ii < hb_audio_rates_count; ii++)
931         {
932                 if (strcmp(hb_audio_rates[ii].string, str) == 0)
933                 {
934                         result = hb_audio_rates[ii].string;
935                         break;
936                 }
937         }
938         g_free(str);
939         return result;
940 }
941
942 gint
943 ghb_find_closest_audio_bitrate(gint codec, gint rate)
944 {
945         gint ii;
946         gint low = 32;
947         gint high = 768;
948         gint result;
949
950         if (codec == HB_ACODEC_FAAC)
951                 high = 320;
952
953         result = high;
954         for (ii = 0; ii < hb_audio_bitrates_count; ii++)
955         {
956                 if (hb_audio_bitrates[ii].rate < low)
957                         continue;
958                 if (hb_audio_bitrates[ii].rate > high)
959                         break;
960                 if (rate <= hb_audio_bitrates[ii].rate)
961                 {
962                         result = hb_audio_bitrates[ii].rate;
963                         break;
964                 }
965         }
966         return result;
967 }
968
969 static gint
970 lookup_audio_bitrate_int(const GValue *rate)
971 {
972         gint ii;
973         gchar *str;
974         gint result = 0;
975
976         // Coincidentally, the string "source" will return 0
977         // which is our flag to use "same as source"
978         str = ghb_value_string(rate);
979         for (ii = 0; ii < hb_audio_bitrates_count; ii++)
980         {
981                 if (strcmp(hb_audio_bitrates[ii].string, str) == 0)
982                 {
983                         result = hb_audio_bitrates[ii].rate;
984                         break;
985                 }
986         }
987         g_free(str);
988         return result;
989 }
990
991 static const gchar*
992 lookup_audio_bitrate_option(const GValue *rate)
993 {
994         gint ii;
995         gchar *str;
996         const gchar *result = "Same as source";
997
998         // Coincidentally, the string "source" will return 0
999         // which is our flag to use "same as source"
1000         str = ghb_value_string(rate);
1001         for (ii = 0; ii < hb_audio_bitrates_count; ii++)
1002         {
1003                 if (strcmp(hb_audio_bitrates[ii].string, str) == 0)
1004                 {
1005                         result = hb_audio_bitrates[ii].string;
1006                         break;
1007                 }
1008         }
1009         g_free(str);
1010         return result;
1011 }
1012
1013 static gint
1014 lookup_audio_lang_int(const GValue *rate)
1015 {
1016         gint ii;
1017         gchar *str;
1018         gint result = 0;
1019
1020         // Coincidentally, the string "source" will return 0
1021         // which is our flag to use "same as source"
1022         str = ghb_value_string(rate);
1023         for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
1024         {
1025                 if (strcmp(ghb_language_table[ii].iso639_2, str) == 0)
1026                 {
1027                         result = ii;
1028                         break;
1029                 }
1030         }
1031         g_free(str);
1032         return result;
1033 }
1034
1035 static const gchar*
1036 lookup_audio_lang_option(const GValue *rate)
1037 {
1038         gint ii;
1039         gchar *str;
1040         const gchar *result = "Same as source";
1041
1042         // Coincidentally, the string "source" will return 0
1043         // which is our flag to use "same as source"
1044         str = ghb_value_string(rate);
1045         for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
1046         {
1047                 if (strcmp(ghb_language_table[ii].iso639_2, str) == 0)
1048                 {
1049                         if (ghb_language_table[ii].native_name[0] != 0)
1050                                 result = ghb_language_table[ii].native_name;
1051                         else
1052                                 result = ghb_language_table[ii].eng_name;
1053                         break;
1054                 }
1055         }
1056         g_free(str);
1057         return result;
1058 }
1059
1060 GValue*
1061 ghb_lookup_acodec_value(gint val)
1062 {
1063         GValue *value = NULL;
1064         gint ii;
1065
1066         for (ii = 0; ii < acodec_opts.count; ii++)
1067         {
1068                 if ((int)acodec_opts.map[ii].ivalue == val)
1069                 {
1070                         value = ghb_string_value_new(acodec_opts.map[ii].shortOpt);
1071                         break;
1072                 }
1073         }
1074         value = ghb_string_value_new("auto");
1075         return value;
1076 }
1077
1078 static GValue*
1079 get_amix_value(gint val)
1080 {
1081         GValue *value = NULL;
1082         gint ii;
1083
1084         for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
1085         {
1086                 if (hb_audio_mixdowns[ii].amixdown == val)
1087                 {
1088                         value = ghb_string_value_new(hb_audio_mixdowns[ii].short_name);
1089                         break;
1090                 }
1091         }
1092         return value;
1093 }
1094
1095 // Handle for libhb.  Gets set by ghb_backend_init()
1096 static hb_handle_t * h_scan = NULL;
1097 static hb_handle_t * h_queue = NULL;
1098
1099 extern void hb_get_temporary_directory(char path[512]);
1100
1101 gchar*
1102 ghb_get_tmp_dir()
1103 {
1104         char dir[512];
1105
1106         hb_get_temporary_directory(dir);
1107         return g_strdup(dir);
1108 }
1109
1110 void
1111 ghb_hb_cleanup(gboolean partial)
1112 {
1113         char dir[512];
1114
1115         hb_get_temporary_directory(dir);
1116         del_tree(dir, !partial);
1117 }
1118
1119 gint
1120 ghb_subtitle_track_source(signal_user_data_t *ud, gint track)
1121 {
1122         gint titleindex;
1123
1124         if (track == -2)
1125                 return SRTSUB;
1126         if (track < 0)
1127                 return VOBSUB;
1128         titleindex = ghb_settings_combo_int(ud->settings, "title");
1129         if (titleindex < 0)
1130                 return VOBSUB;
1131
1132         hb_list_t  * list;
1133         hb_title_t * title;
1134         hb_subtitle_t * sub;
1135         
1136         if (h_scan == NULL) return VOBSUB;
1137         list = hb_get_titles( h_scan );
1138         if( !hb_list_count( list ) )
1139         {
1140                 /* No valid title, stop right there */
1141                 return VOBSUB;
1142         }
1143         title = hb_list_item( list, titleindex );
1144         if (title == NULL) return VOBSUB;       // Bad titleindex
1145         sub = hb_list_item( title->list_subtitle, track);
1146         if (sub != NULL)
1147                 return sub->source;
1148         else
1149                 return VOBSUB;
1150 }
1151
1152 const char*
1153 ghb_subtitle_source_name(gint source)
1154 {
1155         const gchar * name = "Unknown";
1156         switch (source)
1157         {
1158                 case VOBSUB:
1159                         name = "VOBSUB";
1160                         break;
1161                 case TX3GSUB:
1162                         name = "TX3G";
1163                         break;
1164                 case UTF8SUB:
1165                         name = "UTF8";
1166                         break;
1167                 case CC708SUB:
1168                 case CC608SUB:
1169                         name = "CC";
1170                         break;
1171                 case SRTSUB:
1172                         name = "SRT";
1173                         break;
1174                 case SSASUB:
1175                         name = "SSA";
1176                         break;
1177                 default:
1178                         break;
1179         }
1180         return name;
1181 }
1182
1183 const char*
1184 ghb_subtitle_track_source_name(signal_user_data_t *ud, gint track)
1185 {
1186         gint titleindex;
1187         const gchar * name = "Unknown";
1188
1189         if (track == -2)
1190         {
1191                 name = "SRT";
1192                 goto done;
1193         }
1194         if (track == -1)
1195         {
1196                 name = "Bitmap";
1197                 goto done;
1198         }
1199
1200         titleindex = ghb_settings_combo_int(ud->settings, "title");
1201         if (titleindex < 0)
1202                 goto done;
1203
1204         hb_list_t  * list;
1205         hb_title_t * title;
1206         hb_subtitle_t * sub;
1207         
1208         if (h_scan == NULL) 
1209                 goto done;
1210         list = hb_get_titles( h_scan );
1211         if( !hb_list_count( list ) )
1212                 goto done;
1213
1214         title = hb_list_item( list, titleindex );
1215         if (title == NULL)
1216                 goto done;
1217
1218         sub = hb_list_item( title->list_subtitle, track);
1219         if (sub != NULL)
1220         {
1221                 name = ghb_subtitle_source_name(sub->source);
1222         }
1223
1224 done:
1225         return name;
1226 }
1227
1228 gchar*
1229 ghb_subtitle_track_lang(signal_user_data_t *ud, gint track)
1230 {
1231         gint titleindex;
1232
1233         titleindex = ghb_settings_combo_int(ud->settings, "title");
1234         if (titleindex < 0)
1235                 goto fail;
1236         if (track == -1)
1237                 return ghb_get_user_audio_lang(ud, titleindex, 0);
1238         if (track < 0)
1239                 goto fail;
1240
1241         hb_list_t  * list;
1242         hb_title_t * title;
1243         hb_subtitle_t * sub;
1244         
1245         if (h_scan == NULL)
1246                 goto fail;
1247
1248         list = hb_get_titles( h_scan );
1249         if( !hb_list_count( list ) )
1250         {
1251                 /* No valid title, stop right there */
1252                 goto fail;
1253         }
1254         title = hb_list_item( list, titleindex );
1255         if (title == NULL)      // Bad titleindex
1256                 goto fail;
1257         sub = hb_list_item( title->list_subtitle, track);
1258         if (sub != NULL)
1259                 return g_strdup(sub->iso639_2);
1260
1261 fail:
1262         return g_strdup("und");
1263 }
1264
1265 gint
1266 ghb_get_title_number(gint titleindex)
1267 {
1268         hb_list_t  * list;
1269         hb_title_t * title;
1270         
1271         if (h_scan == NULL) return 1;
1272         list = hb_get_titles( h_scan );
1273         if( !hb_list_count( list ) )
1274         {
1275                 /* No valid title, stop right there */
1276                 return 1;
1277         }
1278         title = hb_list_item( list, titleindex );
1279         if (title == NULL) return 1;    // Bad titleindex
1280         return title->index;
1281 }
1282
1283 static hb_audio_config_t*
1284 get_hb_audio(gint titleindex, gint track)
1285 {
1286         hb_list_t  * list;
1287         hb_title_t * title;
1288     hb_audio_config_t *audio = NULL;
1289         
1290     if (h_scan == NULL) return NULL;
1291         list = hb_get_titles( h_scan );
1292         if( !hb_list_count( list ) )
1293         {
1294                 /* No valid title, stop right there */
1295                 return NULL;
1296         }
1297     title = hb_list_item( list, titleindex );
1298         if (title == NULL) return NULL; // Bad titleindex
1299         if (!hb_list_count(title->list_audio))
1300         {
1301                 return NULL;
1302         }
1303     audio = (hb_audio_config_t *)hb_list_audio_config_item(title->list_audio, track);
1304         return audio;
1305 }
1306
1307 static gint
1308 search_rates(hb_rate_t *rates, gint rate, gint count)
1309 {
1310         gint ii;
1311         for (ii = 0; ii < count; ii++)
1312         {
1313                 if (rates[ii].rate == rate)
1314                         return ii;
1315         }
1316         return -1;
1317 }
1318
1319 static gboolean find_combo_item_by_int(GtkTreeModel *store, gint value, GtkTreeIter *iter);
1320
1321 static GtkListStore*
1322 get_combo_box_store(GtkBuilder *builder, const gchar *name)
1323 {
1324         GtkComboBox *combo;
1325         GtkListStore *store;
1326
1327         g_debug("get_combo_box_store() %s\n", name);
1328         // First modify the combobox model to allow greying out of options
1329         combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name));
1330         store = GTK_LIST_STORE(gtk_combo_box_get_model (combo));
1331         return store;
1332 }
1333
1334 static void
1335 grey_combo_box_item(GtkBuilder *builder, const gchar *name, gint value, gboolean grey)
1336 {
1337         GtkListStore *store;
1338         GtkTreeIter iter;
1339         
1340         store = get_combo_box_store(builder, name);
1341         if (find_combo_item_by_int(GTK_TREE_MODEL(store), value, &iter))
1342         {
1343                 gtk_list_store_set(store, &iter, 
1344                                                    1, !grey, 
1345                                                    -1);
1346         }
1347 }
1348
1349 void
1350 ghb_grey_combo_options(GtkBuilder *builder)
1351 {
1352         GtkWidget *widget;
1353         gint container, track, titleindex, acodec;
1354     hb_audio_config_t *audio = NULL;
1355         GValue *gval;
1356         
1357         widget = GHB_WIDGET (builder, "title");
1358         gval = ghb_widget_value(widget);
1359         titleindex = ghb_lookup_combo_int("title", gval);
1360         ghb_value_free(gval);
1361         widget = GHB_WIDGET (builder, "AudioTrack");
1362         gval = ghb_widget_value(widget);
1363         track = ghb_lookup_combo_int("AudioTrack", gval);
1364         ghb_value_free(gval);
1365         audio = get_hb_audio(titleindex, track);
1366         widget = GHB_WIDGET (builder, "FileFormat");
1367         gval = ghb_widget_value(widget);
1368         container = ghb_lookup_combo_int("FileFormat", gval);
1369         ghb_value_free(gval);
1370
1371         grey_combo_box_item(builder, "x264_analyse", 3, TRUE);
1372         grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_FAAC, FALSE);
1373         grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_LAME, FALSE);
1374         grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_VORBIS, FALSE);
1375
1376         gboolean allow_dca = TRUE;
1377         allow_dca = (container != HB_MUX_MP4);
1378
1379         grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_AC3, FALSE);
1380         if (allow_dca)
1381                 grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_DCA, FALSE);
1382         else
1383                 grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_DCA, TRUE);
1384
1385         if (audio && audio->in.codec != HB_ACODEC_AC3)
1386         {
1387                 grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_AC3, TRUE);
1388         }
1389         if (audio && audio->in.codec != HB_ACODEC_DCA)
1390         {
1391                 grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_DCA, TRUE);
1392         }
1393         grey_combo_box_item(builder, "VideoEncoder", HB_VCODEC_THEORA, FALSE);
1394
1395         widget = GHB_WIDGET (builder, "AudioEncoder");
1396         gval = ghb_widget_value(widget);
1397         acodec = ghb_lookup_combo_int("AudioEncoder", gval);
1398         ghb_value_free(gval);
1399         if (acodec != HB_ACODEC_AC3)
1400         {
1401                 grey_combo_box_item(builder, "AudioMixdown", 0, TRUE);
1402         }
1403         if (container == HB_MUX_MP4)
1404         {
1405                 grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_VORBIS, TRUE);
1406                 grey_combo_box_item(builder, "VideoEncoder", HB_VCODEC_THEORA, TRUE);
1407         }
1408
1409         gboolean allow_mono = TRUE;
1410         gboolean allow_stereo = TRUE;
1411         gboolean allow_dolby = TRUE;
1412         gboolean allow_dpl2 = TRUE;
1413         gboolean allow_6ch = TRUE;
1414         allow_mono = TRUE;
1415         allow_6ch = acodec & ~HB_ACODEC_LAME;
1416         if (audio)
1417         {
1418                 gint layout = audio->in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
1419                 allow_stereo =
1420                         ((layout == HB_INPUT_CH_LAYOUT_MONO && !allow_mono) || layout >= HB_INPUT_CH_LAYOUT_STEREO);
1421                 allow_dolby =
1422                         (layout == HB_INPUT_CH_LAYOUT_3F1R) || 
1423                         (layout == HB_INPUT_CH_LAYOUT_3F2R) || 
1424                         (layout == HB_INPUT_CH_LAYOUT_DOLBY);
1425                 allow_dpl2 = (layout == HB_INPUT_CH_LAYOUT_3F2R);
1426                 allow_6ch = allow_6ch &&
1427                         (layout == HB_INPUT_CH_LAYOUT_3F2R) && 
1428                         (audio->in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE);
1429         }
1430         grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_MONO, !allow_mono);
1431         grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_STEREO, !allow_stereo);
1432         grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_DOLBY, !allow_dolby);
1433         grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_DOLBYPLII, !allow_dpl2);
1434         grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_6CH, !allow_6ch);
1435 }
1436
1437 gint
1438 ghb_get_best_audio_bitrate(gint acodec, gint br, gint channels)
1439 {
1440         if (acodec & HB_ACODEC_FAAC)
1441         {
1442                 int maxbr;
1443
1444                 if (channels == 2)
1445                         maxbr = 320;
1446                 else
1447                         maxbr = 768;
1448                 if (br > maxbr)
1449                         br = maxbr;
1450         }
1451         return br;
1452 }
1453
1454 gint
1455 ghb_get_best_mix(gint titleindex, gint track, gint acodec, gint mix)
1456 {
1457     hb_audio_config_t *audio = NULL;
1458         gboolean allow_mono = TRUE;
1459         gboolean allow_stereo = TRUE;
1460         gboolean allow_dolby = TRUE;
1461         gboolean allow_dpl2 = TRUE;
1462         gboolean allow_6ch = TRUE;
1463         
1464         if (acodec & (HB_ACODEC_AC3 | HB_ACODEC_DCA))
1465         {
1466                 // Audio codec pass-thru.  No mixdown
1467                 return 0;
1468         }
1469         audio = get_hb_audio(titleindex, track);
1470         if (audio)
1471         {
1472                 allow_mono = TRUE;
1473                 gint layout = audio->in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
1474                 allow_stereo =
1475                         ((layout == HB_INPUT_CH_LAYOUT_MONO && !allow_mono) || layout >= HB_INPUT_CH_LAYOUT_STEREO);
1476                 allow_dolby =
1477                         (layout == HB_INPUT_CH_LAYOUT_3F1R) || 
1478                         (layout == HB_INPUT_CH_LAYOUT_3F2R) || 
1479                         (layout == HB_INPUT_CH_LAYOUT_DOLBY);
1480                 allow_dpl2 = (layout == HB_INPUT_CH_LAYOUT_3F2R);
1481                 allow_6ch =
1482                         (acodec & ~HB_ACODEC_LAME) &&
1483                         (layout == HB_INPUT_CH_LAYOUT_3F2R) && 
1484                         (audio->in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE);
1485         }
1486         gboolean greater = FALSE;
1487         if (mix == 0) 
1488         {
1489                 // If no mix is specified, select the best available.
1490                 mix = HB_AMIXDOWN_6CH;
1491         }
1492         if (mix == HB_AMIXDOWN_6CH)
1493         {
1494                 greater = TRUE;
1495                 if (allow_6ch) return HB_AMIXDOWN_6CH;
1496         }
1497         if (mix == HB_AMIXDOWN_DOLBYPLII || greater)
1498         {
1499                 greater = TRUE;
1500                 if (allow_dpl2) return HB_AMIXDOWN_DOLBYPLII;
1501         }
1502         if (mix == HB_AMIXDOWN_DOLBY || greater)
1503         {
1504                 greater = TRUE;
1505                 if (allow_dolby) return HB_AMIXDOWN_DOLBY;
1506         }
1507         if (mix == HB_AMIXDOWN_STEREO || greater)
1508         {
1509                 greater = TRUE;
1510                 if (allow_stereo) return HB_AMIXDOWN_STEREO;
1511         }
1512         if (mix == HB_AMIXDOWN_MONO || greater)
1513         {
1514                 greater = TRUE;
1515                 if (allow_mono) return HB_AMIXDOWN_MONO;
1516         }
1517         if (allow_stereo) return HB_AMIXDOWN_STEREO;
1518         if (allow_dolby) return HB_AMIXDOWN_DOLBY;
1519         if (allow_dpl2) return HB_AMIXDOWN_DOLBYPLII;
1520         if (allow_6ch) return HB_AMIXDOWN_6CH;
1521         return 0;
1522 }
1523
1524 // Set up the model for the combo box
1525 static void
1526 init_combo_box(GtkBuilder *builder, const gchar *name)
1527 {
1528         GtkComboBox *combo;
1529         GtkListStore *store;
1530         GtkCellRenderer *cell;
1531
1532         g_debug("init_combo_box() %s\n", name);
1533         // First modify the combobox model to allow greying out of options
1534         combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name));
1535         if (combo == NULL)
1536                 return;
1537         // Store contains:
1538         // 1 - String to display
1539         // 2 - bool indicating whether the entry is selectable (grey or not)
1540         // 3 - String that is used for presets
1541         // 4 - Int value determined by backend
1542         // 5 - String value determined by backend
1543         store = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_BOOLEAN, 
1544                                                            G_TYPE_STRING, G_TYPE_DOUBLE, G_TYPE_STRING);
1545         gtk_combo_box_set_model(combo, GTK_TREE_MODEL(store));
1546
1547         if (GTK_WIDGET_TYPE(combo) == GTK_TYPE_COMBO_BOX)
1548         {
1549                 gtk_cell_layout_clear(GTK_CELL_LAYOUT(combo));
1550         cell = GTK_CELL_RENDERER(gtk_cell_renderer_text_new());
1551         gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), cell, TRUE);
1552         gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), cell,
1553                 "markup", 0, "sensitive", 1, NULL);
1554         }
1555         else
1556         { // Combo box entry
1557                 gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(combo), 0);
1558         }
1559 }       
1560
1561 static void
1562 audio_samplerate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gint count)
1563 {
1564         GtkTreeIter iter;
1565         GtkListStore *store;
1566         gint ii;
1567         gchar *str;
1568         
1569         g_debug("audio_samplerate_opts_set ()\n");
1570         store = get_combo_box_store(builder, name);
1571         gtk_list_store_clear(store);
1572         // Add an item for "Same As Source"
1573         gtk_list_store_append(store, &iter);
1574         gtk_list_store_set(store, &iter, 
1575                                            0, "<small>Same as source</small>", 
1576                                            1, TRUE, 
1577                                            2, "source", 
1578                                            3, 0.0, 
1579                                            4, "source", 
1580                                            -1);
1581         for (ii = 0; ii < count; ii++)
1582         {
1583                 gtk_list_store_append(store, &iter);
1584                 str = g_strdup_printf("<small>%s</small>", rates[ii].string);
1585                 gtk_list_store_set(store, &iter, 
1586                                                    0, str,
1587                                                    1, TRUE, 
1588                                                    2, rates[ii].string, 
1589                                                    3, (gdouble)rates[ii].rate, 
1590                                                    4, rates[ii].string, 
1591                                                    -1);
1592                 g_free(str);
1593         }
1594 }
1595
1596 static void
1597 video_rate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gint count)
1598 {
1599         GtkTreeIter iter;
1600         GtkListStore *store;
1601         gint ii;
1602         
1603         g_debug("video_rate_opts_set ()\n");
1604         store = get_combo_box_store(builder, name);
1605         gtk_list_store_clear(store);
1606         // Add an item for "Same As Source"
1607         gtk_list_store_append(store, &iter);
1608         gtk_list_store_set(store, &iter, 
1609                                            0, "Same as source", 
1610                                            1, TRUE, 
1611                                            2, "source", 
1612                                            3, 0.0, 
1613                                            4, "source", 
1614                                            -1);
1615         for (ii = 0; ii < count; ii++)
1616         {
1617                 gchar *desc = "";
1618                 gchar *option;
1619                 if (strcmp(rates[ii].string, "23.976") == 0)
1620                 {
1621                         desc = "(NTSC Film)";
1622                 }
1623                 else if (strcmp(rates[ii].string, "25") == 0)
1624                 {
1625                         desc = "(PAL Film/Video)";
1626                 }
1627                 else if (strcmp(rates[ii].string, "29.97") == 0)
1628                 {
1629                         desc = "(NTSC Video)";
1630                 }
1631                 option = g_strdup_printf ("%s %s", rates[ii].string, desc);
1632                 gtk_list_store_append(store, &iter);
1633                 gtk_list_store_set(store, &iter, 
1634                                                    0, option, 
1635                                                    1, TRUE, 
1636                                                    2, rates[ii].string, 
1637                                                    3, (gdouble)rates[ii].rate, 
1638                                                    4, rates[ii].string, 
1639                                                    -1);
1640                 g_free(option);
1641         }
1642 }
1643
1644 static void
1645 mix_opts_set(GtkBuilder *builder, const gchar *name)
1646 {
1647         GtkTreeIter iter;
1648         GtkListStore *store;
1649         gint ii;
1650         gchar *str;
1651         
1652         g_debug("mix_opts_set ()\n");
1653         store = get_combo_box_store(builder, name);
1654         gtk_list_store_clear(store);
1655         gtk_list_store_append(store, &iter);
1656         gtk_list_store_set(store, &iter, 
1657                                            0, "<small>None</small>", 
1658                                            1, TRUE, 
1659                                            2, "none", 
1660                                            3, 0.0, 
1661                                            4, "none", 
1662                                            -1);
1663         for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
1664         {
1665                 gtk_list_store_append(store, &iter);
1666                 str = g_strdup_printf("<small>%s</small>",
1667                         hb_audio_mixdowns[ii].human_readable_name);
1668                 gtk_list_store_set(store, &iter, 
1669                                                    0, str,
1670                                                    1, TRUE, 
1671                                                    2, hb_audio_mixdowns[ii].short_name, 
1672                                                    3, (gdouble)hb_audio_mixdowns[ii].amixdown, 
1673                                                    4, hb_audio_mixdowns[ii].internal_name, 
1674                                                    -1);
1675                 g_free(str);
1676         }
1677 }
1678
1679 static void
1680 srt_codeset_opts_set(GtkBuilder *builder, const gchar *name)
1681 {
1682         GtkTreeIter iter;
1683         GtkListStore *store;
1684         gint ii;
1685         
1686         g_debug("srt_codeset_opts_set ()\n");
1687         store = get_combo_box_store(builder, name);
1688         gtk_list_store_clear(store);
1689         for (ii = 0; ii < SRT_TABLE_SIZE; ii++)
1690         {
1691                 gtk_list_store_append(store, &iter);
1692                 gtk_list_store_set(store, &iter, 
1693                                                    0, srt_codeset_table[ii],
1694                                                    1, TRUE, 
1695                                                    2, srt_codeset_table[ii],
1696                                                    3, (gdouble)ii, 
1697                                                    4, srt_codeset_table[ii],
1698                                                    -1);
1699         }
1700         GtkComboBoxEntry *cbe;
1701
1702         cbe = GTK_COMBO_BOX_ENTRY(GHB_WIDGET(builder, name));
1703         //gtk_combo_box_entry_set_text_column(cbe, 0);
1704 }
1705
1706 static void
1707 language_opts_set(GtkBuilder *builder, const gchar *name)
1708 {
1709         GtkTreeIter iter;
1710         GtkListStore *store;
1711         gint ii;
1712         
1713         g_debug("language_opts_set ()\n");
1714         store = get_combo_box_store(builder, name);
1715         gtk_list_store_clear(store);
1716         for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
1717         {
1718                 const gchar *lang;
1719
1720                 if (ghb_language_table[ii].native_name[0] != 0)
1721                         lang = ghb_language_table[ii].native_name;
1722                 else
1723                         lang = ghb_language_table[ii].eng_name;
1724                 
1725                 gtk_list_store_append(store, &iter);
1726                 gtk_list_store_set(store, &iter, 
1727                                                    0, lang,
1728                                                    1, TRUE, 
1729                                                    2, ghb_language_table[ii].iso639_2, 
1730                                                    3, (gdouble)ii, 
1731                                                    4, ghb_language_table[ii].iso639_1, 
1732                                                    -1);
1733         }
1734 }
1735
1736 static gchar **titles = NULL;
1737
1738 void
1739 title_opts_set(GtkBuilder *builder, const gchar *name)
1740 {
1741         GtkTreeIter iter;
1742         GtkListStore *store;
1743         hb_list_t  * list = NULL;
1744         hb_title_t * title = NULL;
1745         gint ii;
1746         gint count = 0;
1747         
1748         g_debug("title_opts_set ()\n");
1749         store = get_combo_box_store(builder, name);
1750         gtk_list_store_clear(store);
1751         if (h_scan != NULL)
1752         {
1753                 list = hb_get_titles( h_scan );
1754                 count = hb_list_count( list );
1755                 if (count > 100) count = 100;
1756         }
1757         if (titles) g_strfreev(titles);
1758         if (title_opts.map) g_free(title_opts.map);
1759         if (count > 0)
1760         {
1761                 title_opts.count = count;
1762                 title_opts.map = g_malloc(count*sizeof(options_map_t));
1763                 titles = g_malloc((count+1) * sizeof(gchar*));
1764         }
1765         else
1766         {
1767                 title_opts.count = 1;
1768                 title_opts.map = g_malloc(sizeof(options_map_t));
1769                 titles = NULL;
1770         }
1771         if( count <= 0 )
1772         {
1773                 // No titles.  Fill in a default.
1774                 gtk_list_store_append(store, &iter);
1775                 gtk_list_store_set(store, &iter, 
1776                                                    0, "No Titles", 
1777                                                    1, TRUE, 
1778                                                    2, "none", 
1779                                                    3, -1.0, 
1780                                                    4, "none", 
1781                                                    -1);
1782                 title_opts.map[0].option = "No Titles";
1783                 title_opts.map[0].shortOpt = "none";
1784                 title_opts.map[0].ivalue = -1;
1785                 title_opts.map[0].svalue = "none";
1786                 return;
1787         }
1788         for (ii = 0; ii < count; ii++)
1789         {
1790                 title = (hb_title_t*)hb_list_item(list, ii);
1791                 if (title->type == HB_STREAM_TYPE)
1792                 {
1793                         if (title->duration != 0)
1794                         {
1795                                 titles[ii]  = g_strdup_printf ("%d - %02dh%02dm%02ds - %s",
1796                                         title->index, title->hours, title->minutes, title->seconds, 
1797                                         title->name);
1798                         }
1799                         else
1800                         {
1801                                 titles[ii]  = g_strdup_printf ("%d - %s", 
1802                                                                                 title->index, title->name);
1803                         }
1804                 }
1805                 else
1806                 {
1807                         if (title->duration != 0)
1808                         {
1809                                 titles[ii]  = g_strdup_printf ("%d - %02dh%02dm%02ds",
1810                                         title->index, title->hours, title->minutes, title->seconds);
1811                         }
1812                         else
1813                         {
1814                                 titles[ii]  = g_strdup_printf ("%d - Unknown Length", 
1815                                                                                 title->index);
1816                         }
1817                 }
1818                 gtk_list_store_append(store, &iter);
1819                 gtk_list_store_set(store, &iter, 
1820                                                    0, titles[ii], 
1821                                                    1, TRUE, 
1822                                                    2, titles[ii], 
1823                                                    3, (gdouble)ii, 
1824                                                    4, titles[ii], 
1825                                                    -1);
1826                 title_opts.map[ii].option = titles[ii];
1827                 title_opts.map[ii].shortOpt = titles[ii];
1828                 title_opts.map[ii].ivalue = ii;
1829                 title_opts.map[ii].svalue = titles[ii];
1830         }
1831         titles[ii] = NULL;
1832 }
1833
1834 static gboolean
1835 find_combo_item_by_int(GtkTreeModel *store, gint value, GtkTreeIter *iter)
1836 {
1837         gdouble ivalue;
1838         gboolean foundit = FALSE;
1839         
1840         if (gtk_tree_model_get_iter_first (store, iter))
1841         {
1842                 do
1843                 {
1844                         gtk_tree_model_get(store, iter, 3, &ivalue, -1);
1845                         if (value == (int)ivalue)
1846                         {
1847                                 foundit = TRUE;
1848                                 break;
1849                         }
1850                 } while (gtk_tree_model_iter_next (store, iter));
1851         }
1852         return foundit;
1853 }
1854
1855 void
1856 audio_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
1857 {
1858         GtkTreeIter iter;
1859         GtkListStore *store;
1860         hb_list_t  * list = NULL;
1861         hb_title_t * title = NULL;
1862     hb_audio_config_t * audio;
1863         gint ii;
1864         gint count = 0;
1865         gchar *str;
1866         
1867         g_debug("audio_track_opts_set ()\n");
1868         store = get_combo_box_store(builder, name);
1869         gtk_list_store_clear(store);
1870         if (h_scan != NULL)
1871         {
1872                 list = hb_get_titles( h_scan );
1873             title = (hb_title_t*)hb_list_item( list, titleindex );
1874                 if (title != NULL)
1875                 {
1876                         count = hb_list_count( title->list_audio );
1877                 }
1878         }
1879         if (count > 100) count = 100;
1880         if (audio_track_opts.map) g_free(audio_track_opts.map);
1881         if (count > 0)
1882         {
1883                 audio_track_opts.count = count;
1884                 audio_track_opts.map = g_malloc(count*sizeof(options_map_t));
1885         }
1886         else
1887         {
1888                 audio_track_opts.count = 1;
1889                 audio_track_opts.map = g_malloc(sizeof(options_map_t));
1890         }
1891         if( count <= 0 )
1892         {
1893                 // No audio. set some default
1894                 gtk_list_store_append(store, &iter);
1895                 gtk_list_store_set(store, &iter, 
1896                                                    0, "<small>No Audio</small>", 
1897                                                    1, TRUE, 
1898                                                    2, "none", 
1899                                                    3, -1.0, 
1900                                                    4, "none", 
1901                                                    -1);
1902                 audio_track_opts.map[0].option = "No Audio";
1903                 audio_track_opts.map[0].shortOpt = "none";
1904                 audio_track_opts.map[0].ivalue = -1;
1905                 audio_track_opts.map[0].svalue = "none";
1906                 return;
1907         }
1908         index_str_init(count-1);
1909         for (ii = 0; ii < count; ii++)
1910         {
1911         audio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, ii );
1912                 gtk_list_store_append(store, &iter);
1913                 str = g_strdup_printf("<small>%s</small>", audio->lang.description);
1914                 gtk_list_store_set(store, &iter, 
1915                                                    0, str,
1916                                                    1, TRUE, 
1917                                                    2, index_str[ii], 
1918                                                    3, (gdouble)ii, 
1919                                                    4, index_str[ii], 
1920                                                    -1);
1921                 g_free(str);
1922                 audio_track_opts.map[ii].option = audio->lang.description,
1923                 audio_track_opts.map[ii].shortOpt = index_str[ii];
1924                 audio_track_opts.map[ii].ivalue = ii;
1925                 audio_track_opts.map[ii].svalue = index_str[ii];
1926         }
1927 }
1928
1929 void
1930 subtitle_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
1931 {
1932         GtkTreeIter iter;
1933         GtkListStore *store;
1934         hb_list_t  * list = NULL;
1935         hb_title_t * title = NULL;
1936         hb_subtitle_t * subtitle;
1937         gint ii, count = 0;
1938         static char ** options = NULL;
1939         
1940         g_debug("subtitle_track_opts_set ()\n");
1941         store = get_combo_box_store(builder, name);
1942         gtk_list_store_clear(store);
1943         if (h_scan != NULL)
1944         {
1945                 list = hb_get_titles( h_scan );
1946             title = (hb_title_t*)hb_list_item( list, titleindex );
1947                 if (title != NULL)
1948                 {
1949                         count = hb_list_count( title->list_subtitle );
1950                 }
1951         }
1952         if (count > 100) count = 100;
1953         if (subtitle_opts.map) g_free(subtitle_opts.map);
1954         if (count > 0)
1955         {
1956                 subtitle_opts.count = count+1;
1957                 subtitle_opts.map = g_malloc((count+1)*sizeof(options_map_t));
1958         }
1959         else
1960         {
1961                 subtitle_opts.count = LANG_TABLE_SIZE+1;
1962                 subtitle_opts.map = g_malloc((LANG_TABLE_SIZE+1)*sizeof(options_map_t));
1963         }
1964         gtk_list_store_append(store, &iter);
1965         gtk_list_store_set(store, &iter, 
1966                                            0, "Foreign Audio Search", 
1967                                            1, TRUE, 
1968                                            2, "-1", 
1969                                            3, -1.0, 
1970                                            4, "auto", 
1971                                            -1);
1972         subtitle_opts.map[0].option = "Foreign Audio Search";
1973         subtitle_opts.map[0].shortOpt = "-1";
1974         subtitle_opts.map[0].ivalue = -1;
1975         subtitle_opts.map[0].svalue = "auto";
1976         if (count > 0)
1977         {
1978                 if (options != NULL)
1979                         g_strfreev(options);
1980                 options = g_malloc((count+1)*sizeof(gchar*));
1981                 index_str_init(count-1);
1982                 for (ii = 0; ii < count; ii++)
1983                 {
1984                 subtitle = (hb_subtitle_t *)hb_list_item(title->list_subtitle, ii);
1985                         // Skip subtitles that must be burned if there is already
1986                         // a burned subtitle in the list
1987 #if 0
1988                         if (subtitle->source == VOBSUB)
1989                         {
1990                                 options[ii] = g_strdup_printf("%d - %s", ii+1, subtitle->lang);
1991                         }
1992                         else
1993 #endif
1994                         {
1995                                 options[ii] = g_strdup_printf("%d - %s (%s)", ii+1, 
1996                                         subtitle->lang, 
1997                                         ghb_subtitle_source_name(subtitle->source));
1998                         }
1999                         subtitle_opts.map[ii+1].option = options[ii];
2000                         subtitle_opts.map[ii+1].shortOpt = index_str[ii];
2001                         subtitle_opts.map[ii+1].ivalue = ii;
2002                         subtitle_opts.map[ii+1].svalue = subtitle->iso639_2;
2003                         gtk_list_store_append(store, &iter);
2004                         gtk_list_store_set(store, &iter, 
2005                                                 0, options[ii], 
2006                                                 1, TRUE, 
2007                                                 2, index_str[ii], 
2008                                                 3, (gdouble)ii, 
2009                                                 4, subtitle->iso639_2, 
2010                                                 -1);
2011                 }
2012                 options[count] = NULL;
2013         }
2014         else
2015         {
2016                 index_str_init(LANG_TABLE_SIZE-1);
2017                 for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
2018                 {
2019                         const gchar *lang;
2020
2021                         if (ghb_language_table[ii].native_name[0] != 0)
2022                                 lang = ghb_language_table[ii].native_name;
2023                         else
2024                                 lang = ghb_language_table[ii].eng_name;
2025
2026                         subtitle_opts.map[ii+1].option = lang;
2027                         subtitle_opts.map[ii+1].shortOpt = index_str[ii];
2028                         subtitle_opts.map[ii+1].ivalue = ii;
2029                         subtitle_opts.map[ii+1].svalue = ghb_language_table[ii].iso639_2;
2030                         gtk_list_store_append(store, &iter);
2031                         gtk_list_store_set(store, &iter, 
2032                                         0, lang,
2033                                         1, TRUE, 
2034                                         2, index_str[ii],
2035                                         3, (gdouble)ii, 
2036                                         4, ghb_language_table[ii].iso639_2, 
2037                                         -1);
2038                 }
2039         }
2040 }
2041
2042 gint
2043 ghb_longest_title()
2044 {
2045         hb_list_t  * list;
2046         hb_title_t * title;
2047         gint ii;
2048         gint count = 0;
2049         gint titleindex = 0;
2050         gint feature;
2051         
2052         g_debug("ghb_longest_title ()\n");
2053         if (h_scan == NULL) return 0;
2054         list = hb_get_titles( h_scan );
2055         count = hb_list_count( list );
2056         if (count > 100) count = 100;
2057         if (count < 1) return 0;
2058         title = (hb_title_t*)hb_list_item(list, 0);
2059         feature = title->job->feature;
2060         for (ii = 0; ii < count; ii++)
2061         {
2062                 title = (hb_title_t*)hb_list_item(list, ii);
2063                 if (title->index == feature)
2064                 {
2065                         return ii;
2066                 }
2067         }
2068         return titleindex;
2069 }
2070
2071 gchar*
2072 ghb_get_source_audio_lang(gint titleindex, gint track)
2073 {
2074         hb_list_t  * list;
2075         hb_title_t * title;
2076     hb_audio_config_t * audio;
2077         gchar *lang = NULL;
2078         
2079         g_debug("ghb_lookup_1st_audio_lang ()\n");
2080         if (h_scan == NULL) 
2081                 return NULL;
2082         list = hb_get_titles( h_scan );
2083     title = (hb_title_t*)hb_list_item( list, titleindex );
2084         if (title == NULL)
2085                 return NULL;
2086         if (hb_list_count( title->list_audio ) <= track)
2087                 return NULL;
2088
2089         audio = hb_list_audio_config_item(title->list_audio, track);
2090         if (audio == NULL)
2091                 return NULL;
2092
2093         lang = g_strdup(audio->lang.iso639_2);
2094         return lang;
2095 }
2096
2097 static gboolean*
2098 get_track_used(gint acodec, GHashTable *track_indices, gint count)
2099 {
2100         gboolean *used;
2101
2102         used = g_hash_table_lookup(track_indices, &acodec);
2103         if (used == NULL)
2104         {
2105                 gint *key;
2106
2107                 used = g_malloc0(count * sizeof(gboolean));
2108                 key = g_malloc(sizeof(gint));
2109                 *key = acodec;
2110                 g_hash_table_insert(track_indices, key, used);
2111         }
2112         return used;
2113 }
2114
2115 gint
2116 ghb_find_audio_track(
2117         gint titleindex, 
2118         const gchar *lang, 
2119         gint acodec,
2120         gint fallback_acodec,
2121         GHashTable *track_indices)
2122 {
2123         hb_list_t  * list;
2124         hb_title_t * title;
2125         hb_audio_config_t * audio;
2126         gint ii;
2127         gint count = 0;
2128         gint track = -1;
2129         gint max_chan = 0;
2130         gboolean *used = NULL;
2131         gboolean *passthru_used;
2132         gint try_acodec;
2133         gint passthru_acodec;
2134         gboolean passthru;
2135         
2136         g_debug("find_audio_track ()\n");
2137         if (h_scan == NULL) return -1;
2138         list = hb_get_titles( h_scan );
2139         title = (hb_title_t*)hb_list_item( list, titleindex );
2140         if (title != NULL)
2141         {
2142                 count = hb_list_count( title->list_audio );
2143         }
2144         if (count > 10) count = 10;
2145         // Try to find an item that matches the preferred language and
2146         // the passthru codec type
2147         passthru = (acodec & (HB_ACODEC_AC3 | HB_ACODEC_DCA)) != 0;
2148         if (passthru)
2149         {
2150                 for (ii = 0; ii < count; ii++)
2151                 {
2152                         gint channels;
2153
2154                         audio = (hb_audio_config_t*)hb_list_audio_config_item( 
2155                                                                                                         title->list_audio, ii );
2156                         passthru_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
2157                         // Is the source track use a passthru capable codec?
2158                         if (passthru_acodec == 0)
2159                                 continue;
2160                         used = get_track_used(passthru_acodec, track_indices, count);
2161                         // Has the track already been used with this codec?
2162                         if (used[ii])
2163                                 continue;
2164
2165                         channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
2166                                                                                                         audio->in.channel_layout);
2167                         // Find a track that is not visually impaired or dirctor's
2168                         // commentary, and has the highest channel count.
2169                         if ((audio->lang.type < 2) &&
2170                                 ((strcmp(lang, audio->lang.iso639_2) == 0) ||
2171                                 (strcmp(lang, "und") == 0)))
2172                         {
2173                                 if (channels > max_chan)
2174                                 {
2175                                         track = ii;
2176                                         max_chan = channels;
2177                                 }
2178                         }
2179                 }
2180                 try_acodec = fallback_acodec;
2181         }
2182         else
2183         {
2184                 try_acodec = acodec;
2185         }
2186         if (track > -1)
2187         {
2188                 used[track] = TRUE;
2189                 return track;
2190         }
2191         // Try to find an item that matches the preferred language
2192         used = get_track_used(try_acodec, track_indices, count);
2193         for (ii = 0; ii < count; ii++)
2194         {
2195                 // Has the track already been used with this codec?
2196                 if (used[ii])
2197                         continue;
2198                 audio = (hb_audio_config_t*)hb_list_audio_config_item( 
2199                                                                                                 title->list_audio, ii );
2200                 passthru_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
2201                 if (passthru_acodec && passthru)
2202                 {
2203                         passthru_used = get_track_used(passthru_acodec, track_indices, count);
2204                         // Has the track already been used with this codec for passthru?
2205                         if (passthru_used[ii])
2206                                 continue;
2207                 }
2208                 // Find a track that is not visually impaired or dirctor's commentary
2209                 if ((audio->lang.type < 2) &&
2210                         ((strcmp(lang, audio->lang.iso639_2) == 0) ||
2211                         (strcmp(lang, "und") == 0)))
2212                 {
2213                         track = ii;
2214                         break;
2215                 }
2216         }
2217         if (track > -1)
2218         {
2219                 used[track] = TRUE;
2220                 return track;
2221         }
2222         // Try to fine an item that does not match the preferred language and
2223         // matches the passthru codec type
2224         if (passthru)
2225         {
2226                 for (ii = 0; ii < count; ii++)
2227                 {
2228                         gint channels;
2229
2230                         audio = (hb_audio_config_t*)hb_list_audio_config_item( 
2231                                                                                                         title->list_audio, ii );
2232                         passthru_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
2233                         // Is the source track use a passthru capable codec?
2234                         if (passthru_acodec == 0)
2235                                 continue;
2236                         used = get_track_used(passthru_acodec, track_indices, count);
2237                         // Has the track already been used with this codec?
2238                         if (used[ii])
2239                                 continue;
2240
2241                         channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
2242                                                                                                         audio->in.channel_layout);
2243                         // Find a track that is not visually impaired or dirctor's
2244                         // commentary, and has the highest channel count.
2245                         if (audio->lang.type < 2)
2246                         {
2247                                 if (channels > max_chan)
2248                                 {
2249                                         track = ii;
2250                                         max_chan = channels;
2251                                 }
2252                         }
2253                 }
2254                 try_acodec = fallback_acodec;
2255         }
2256         else
2257         {
2258                 try_acodec = acodec;
2259         }
2260         if (track > -1)
2261         {
2262                 used[track] = TRUE;
2263                 return track;
2264         }
2265         // Try to fine an item that does not match the preferred language
2266         used = get_track_used(try_acodec, track_indices, count);
2267         for (ii = 0; ii < count; ii++)
2268         {
2269                 // Has the track already been used with this codec?
2270                 if (used[ii])
2271                         continue;
2272                 audio = (hb_audio_config_t*)hb_list_audio_config_item( 
2273                                                                                                         title->list_audio, ii );
2274                 passthru_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
2275                 if (passthru_acodec && passthru)
2276                 {
2277                         passthru_used = get_track_used(passthru_acodec, track_indices, count);
2278                         // Has the track already been used with this codec for passthru?
2279                         if (passthru_used[ii])
2280                                 continue;
2281                 }
2282                 // Find a track that is not visually impaired or dirctor's commentary
2283                 if (audio->lang.type < 2)
2284                 {
2285                         track = ii;
2286                         break;
2287                 }
2288         }
2289         if (track > -1)
2290         {
2291                 used[track] = TRUE;
2292                 return track;
2293         }
2294         // Last ditch, anything goes
2295         for (ii = 0; ii < count; ii++)
2296         {
2297                 audio = (hb_audio_config_t*)hb_list_audio_config_item( 
2298                                                                                                 title->list_audio, ii );
2299                 passthru_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
2300                 if (passthru_acodec && passthru)
2301                 {
2302                         passthru_used = get_track_used(passthru_acodec, track_indices, count);
2303                         // Has the track already been used with this codec for passthru?
2304                         if (passthru_used[ii])
2305                                 continue;
2306                 }
2307                 // Has the track already been used with this codec?
2308                 if (!used[ii])
2309                 {
2310                         track = ii;
2311                         break;
2312                 }
2313         }
2314         if (track > -1)
2315         {
2316                 used[track] = TRUE;
2317         }
2318         return track;
2319 }
2320
2321 gint
2322 ghb_find_pref_subtitle_track(const gchar *lang)
2323 {
2324         gint ii, count;
2325         count = subtitle_opts.count;
2326         for (ii = 0; ii < count; ii++)
2327         {
2328                 if (strcmp(lang, subtitle_opts.map[ii].svalue) == 0)
2329                 {
2330                         return subtitle_opts.map[ii].ivalue;
2331                 }
2332         }
2333         return -2;
2334 }
2335
2336 gint
2337 ghb_find_cc_track(gint titleindex)
2338 {
2339         hb_list_t  * list;
2340         hb_title_t * title;
2341         hb_subtitle_t * subtitle;
2342         gint count, ii;
2343         
2344         g_debug("ghb_find_cc_track ()\n");
2345         if (h_scan == NULL) return -2;
2346         list = hb_get_titles( h_scan );
2347         title = (hb_title_t*)hb_list_item( list, titleindex );
2348         if (title != NULL)
2349         {
2350                 count = hb_list_count( title->list_subtitle );
2351                 // Try to find an item that matches the preferred language
2352                 for (ii = 0; ii < count; ii++)
2353                 {
2354                 subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
2355                         if (subtitle->source == CC608SUB || subtitle->source == CC708SUB)
2356                                 return ii;
2357                 }
2358         }
2359         return -2;
2360 }
2361
2362 gint
2363 ghb_find_subtitle_track(
2364         gint          titleindex, 
2365         const gchar * lang, 
2366         gboolean      burn,
2367         gboolean      force,
2368         gint          source,
2369         GHashTable  * track_indices)
2370 {
2371         hb_list_t  * list;
2372         hb_title_t * title;
2373         hb_subtitle_t * subtitle;
2374         gint count, ii;
2375         gboolean *used;
2376         
2377         g_debug("find_subtitle_track ()\n");
2378         if (strcmp(lang, "auto") == 0)
2379                 return -1;
2380         if (h_scan == NULL) return -1;
2381         list = hb_get_titles( h_scan );
2382         title = (hb_title_t*)hb_list_item( list, titleindex );
2383         if (title != NULL)
2384         {
2385                 count = hb_list_count( title->list_subtitle );
2386                 used = g_hash_table_lookup(track_indices, lang);
2387                 if (used == NULL)
2388                 {
2389                         used = g_malloc0(count * sizeof(gboolean));
2390                         g_hash_table_insert(track_indices, g_strdup(lang), used);
2391                 }
2392                 // Try to find an item that matches the preferred language and source
2393                 for (ii = 0; ii < count; ii++)
2394                 {
2395                         if (used[ii])
2396                                 continue;
2397
2398                 subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
2399                         if (source == subtitle->source &&
2400                                 ((strcmp(lang, subtitle->iso639_2) == 0) ||
2401                                  (strcmp(lang, "und") == 0)))
2402                         {
2403                                 used[ii] = TRUE;
2404                                 return ii;
2405                         }
2406                 }
2407                 // Try to find an item that matches the preferred language
2408                 for (ii = 0; ii < count; ii++)
2409                 {
2410                         if (used[ii])
2411                                 continue;
2412
2413                 subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
2414                         if ((!(burn || force) || (subtitle->source == VOBSUB)) &&
2415                                 ((strcmp(lang, subtitle->iso639_2) == 0) ||
2416                                  (strcmp(lang, "und") == 0)))
2417                         {
2418                                 used[ii] = TRUE;
2419                                 return ii;
2420                         }
2421                 }
2422         }
2423         return -2;
2424 }
2425
2426 static void
2427 generic_opts_set(GtkBuilder *builder, const gchar *name, combo_opts_t *opts)
2428 {
2429         GtkTreeIter iter;
2430         GtkListStore *store;
2431         gint ii;
2432         
2433         g_debug("generic_opts_set ()\n");
2434         if (name == NULL || opts == NULL) return;
2435         store = get_combo_box_store(builder, name);
2436         gtk_list_store_clear(store);
2437         for (ii = 0; ii < opts->count; ii++)
2438         {
2439                 gtk_list_store_append(store, &iter);
2440                 gtk_list_store_set(store, &iter, 
2441                                                    0, opts->map[ii].option, 
2442                                                    1, TRUE, 
2443                                                    2, opts->map[ii].shortOpt, 
2444                                                    3, opts->map[ii].ivalue, 
2445                                                    4, opts->map[ii].svalue, 
2446                                                    -1);
2447         }
2448 }
2449
2450 static void
2451 small_opts_set(GtkBuilder *builder, const gchar *name, combo_opts_t *opts)
2452 {
2453         GtkTreeIter iter;
2454         GtkListStore *store;
2455         gint ii;
2456         gchar *str;
2457         
2458         g_debug("small_opts_set ()\n");
2459         if (name == NULL || opts == NULL) return;
2460         store = get_combo_box_store(builder, name);
2461         gtk_list_store_clear(store);
2462         for (ii = 0; ii < opts->count; ii++)
2463         {
2464                 gtk_list_store_append(store, &iter);
2465                 str = g_strdup_printf("<small>%s</small>", opts->map[ii].option);
2466                 gtk_list_store_set(store, &iter, 
2467                                                    0, str,
2468                                                    1, TRUE, 
2469                                                    2, opts->map[ii].shortOpt, 
2470                                                    3, opts->map[ii].ivalue, 
2471                                                    4, opts->map[ii].svalue, 
2472                                                    -1);
2473                 g_free(str);
2474         }
2475 }
2476
2477 combo_opts_t*
2478 find_combo_table(const gchar *name)
2479 {
2480         gint ii;
2481
2482         for (ii = 0; combo_name_map[ii].name != NULL; ii++)
2483         {
2484                 if (strcmp(name, combo_name_map[ii].name) == 0)
2485                 {
2486                         return combo_name_map[ii].opts;
2487                 }
2488         }
2489         return NULL;
2490 }
2491
2492 gint
2493 ghb_lookup_combo_int(const gchar *name, const GValue *gval)
2494 {
2495         if (gval == NULL)
2496                 return 0;
2497         if (strcmp(name, "AudioBitrate") == 0)
2498                 return lookup_audio_bitrate_int(gval);
2499         else if (strcmp(name, "AudioSamplerate") == 0)
2500                 return lookup_audio_rate_int(gval);
2501         else if (strcmp(name, "VideoFramerate") == 0)
2502                 return lookup_video_rate_int(gval);
2503         else if (strcmp(name, "AudioMixdown") == 0)
2504                 return lookup_mix_int(gval);
2505         else if (strcmp(name, "SrtLanguage") == 0)
2506                 return lookup_audio_lang_int(gval);
2507         else if (strcmp(name, "PreferredLanguage") == 0)
2508                 return lookup_audio_lang_int(gval);
2509         else
2510         {
2511                 return lookup_generic_int(find_combo_table(name), gval);
2512         }
2513         g_warning("ghb_lookup_combo_int() couldn't find %s", name);
2514         return 0;
2515 }
2516
2517 gdouble
2518 ghb_lookup_combo_double(const gchar *name, const GValue *gval)
2519 {
2520         if (gval == NULL)
2521                 return 0;
2522         if (strcmp(name, "AudioBitrate") == 0)
2523                 return lookup_audio_bitrate_int(gval);
2524         else if (strcmp(name, "AudioSamplerate") == 0)
2525                 return lookup_audio_rate_int(gval);
2526         else if (strcmp(name, "VideoFramerate") == 0)
2527                 return lookup_video_rate_int(gval);
2528         else if (strcmp(name, "AudioMixdown") == 0)
2529                 return lookup_mix_int(gval);
2530         else if (strcmp(name, "SrtLanguage") == 0)
2531                 return lookup_audio_lang_int(gval);
2532         else if (strcmp(name, "PreferredLanguage") == 0)
2533                 return lookup_audio_lang_int(gval);
2534         else
2535         {
2536                 return lookup_generic_double(find_combo_table(name), gval);
2537         }
2538         g_warning("ghb_lookup_combo_double() couldn't find %s", name);
2539         return 0;
2540 }
2541
2542 const gchar*
2543 ghb_lookup_combo_option(const gchar *name, const GValue *gval)
2544 {
2545         if (gval == NULL)
2546                 return NULL;
2547         if (strcmp(name, "AudioBitrate") == 0)
2548                 return lookup_audio_bitrate_option(gval);
2549         else if (strcmp(name, "AudioSamplerate") == 0)
2550                 return lookup_audio_rate_option(gval);
2551         else if (strcmp(name, "VideoFramerate") == 0)
2552                 return lookup_video_rate_option(gval);
2553         else if (strcmp(name, "AudioMixdown") == 0)
2554                 return lookup_mix_option(gval);
2555         else if (strcmp(name, "SrtLanguage") == 0)
2556                 return lookup_audio_lang_option(gval);
2557         else if (strcmp(name, "PreferredLanguage") == 0)
2558                 return lookup_audio_lang_option(gval);
2559         else
2560         {
2561                 return lookup_generic_option(find_combo_table(name), gval);
2562         }
2563         g_warning("ghb_lookup_combo_int() couldn't find %s", name);
2564         return NULL;
2565 }
2566
2567 const gchar*
2568 ghb_lookup_combo_string(const gchar *name, const GValue *gval)
2569 {
2570         if (gval == NULL)
2571                 return NULL;
2572         if (strcmp(name, "AudioBitrate") == 0)
2573                 return lookup_audio_bitrate_option(gval);
2574         else if (strcmp(name, "AudioSamplerate") == 0)
2575                 return lookup_audio_rate_option(gval);
2576         else if (strcmp(name, "VideoFramerate") == 0)
2577                 return lookup_video_rate_option(gval);
2578         else if (strcmp(name, "AudioMixdown") == 0)
2579                 return lookup_mix_option(gval);
2580         else if (strcmp(name, "SrtLanguage") == 0)
2581                 return lookup_audio_lang_option(gval);
2582         else if (strcmp(name, "PreferredLanguage") == 0)
2583                 return lookup_audio_lang_option(gval);
2584         else
2585         {
2586                 return lookup_generic_string(find_combo_table(name), gval);
2587         }
2588         g_warning("ghb_lookup_combo_int() couldn't find %s", name);
2589         return NULL;
2590 }
2591
2592 void
2593 ghb_update_ui_combo_box(
2594         signal_user_data_t *ud, 
2595         const gchar *name, 
2596         gint user_data, 
2597         gboolean all)
2598 {
2599         GtkComboBox *combo = NULL;
2600         gint signal_id;
2601         gint handler_id = 0;
2602
2603         if (name != NULL)
2604         {               
2605                 g_debug("ghb_update_ui_combo_box() %s\n", name);
2606                 // Clearing a combo box causes a rash of "changed" events, even when
2607                 // the active item is -1 (inactive).  To control things, I'm disabling
2608                 // the event till things are settled down.
2609                 combo = GTK_COMBO_BOX(GHB_WIDGET(ud->builder, name));
2610                 signal_id = g_signal_lookup("changed", GTK_TYPE_COMBO_BOX);
2611                 if (signal_id > 0)
2612                 {
2613                         // Valid signal id found.  This should always succeed.
2614                         handler_id = g_signal_handler_find ((gpointer)combo, G_SIGNAL_MATCH_ID, 
2615                                                                                                 signal_id, 0, 0, 0, 0);
2616                         if (handler_id > 0)
2617                         {
2618                                 // This should also always succeed
2619                                 g_signal_handler_block ((gpointer)combo, handler_id);
2620                         }
2621                 }
2622         }       
2623         if (all)
2624         {
2625                 audio_bitrate_opts_set(ud->builder, "AudioBitrate");
2626                 audio_samplerate_opts_set(ud->builder, "AudioSamplerate", hb_audio_rates, hb_audio_rates_count);
2627                 video_rate_opts_set(ud->builder, "VideoFramerate", hb_video_rates, hb_video_rates_count);
2628                 mix_opts_set(ud->builder, "AudioMixdown");
2629                 language_opts_set(ud->builder, "SrtLanguage");
2630                 language_opts_set(ud->builder, "PreferredLanguage");
2631                 srt_codeset_opts_set(ud->builder, "SrtCodeset");
2632                 title_opts_set(ud->builder, "title");
2633                 audio_track_opts_set(ud->builder, "AudioTrack", user_data);
2634                 subtitle_track_opts_set(ud->builder, "SubtitleTrack", user_data);
2635                 generic_opts_set(ud->builder, "VideoQualityGranularity", &vqual_granularity_opts);
2636                 generic_opts_set(ud->builder, "PtoPType", &point_to_point_opts);
2637                 generic_opts_set(ud->builder, "WhenComplete", &when_complete_opts);
2638                 generic_opts_set(ud->builder, "PicturePAR", &par_opts);
2639                 generic_opts_set(ud->builder, "PictureModulus", &alignment_opts);
2640                 generic_opts_set(ud->builder, "LoggingLevel", &logging_opts);
2641                 generic_opts_set(ud->builder, "LogLongevity", &log_longevity_opts);
2642                 generic_opts_set(ud->builder, "check_updates", &appcast_update_opts);
2643                 generic_opts_set(ud->builder, "FileFormat", &container_opts);
2644                 generic_opts_set(ud->builder, "PictureDeinterlace", &deint_opts);
2645                 generic_opts_set(ud->builder, "PictureDetelecine", &detel_opts);
2646                 generic_opts_set(ud->builder, "PictureDecomb", &decomb_opts);
2647                 generic_opts_set(ud->builder, "PictureDenoise", &denoise_opts);
2648                 generic_opts_set(ud->builder, "VideoEncoder", &vcodec_opts);
2649                 small_opts_set(ud->builder, "AudioEncoder", &acodec_opts);
2650                 generic_opts_set(ud->builder, "x264_direct", &direct_opts);
2651                 generic_opts_set(ud->builder, "x264_b_adapt", &badapt_opts);
2652                 generic_opts_set(ud->builder, "x264_me", &me_opts);
2653                 generic_opts_set(ud->builder, "x264_subme", &subme_opts);
2654                 generic_opts_set(ud->builder, "x264_analyse", &analyse_opts);
2655                 generic_opts_set(ud->builder, "x264_trellis", &trellis_opts);
2656         }
2657         else
2658         {
2659                 if (strcmp(name, "AudioBitrate") == 0)
2660                         audio_bitrate_opts_set(ud->builder, "AudioBitrate");
2661                 else if (strcmp(name, "AudioSamplerate") == 0)
2662                         audio_samplerate_opts_set(ud->builder, "AudioSamplerate", hb_audio_rates, hb_audio_rates_count);
2663                 else if (strcmp(name, "VideoFramerate") == 0)
2664                         video_rate_opts_set(ud->builder, "VideoFramerate", hb_video_rates, hb_video_rates_count);
2665                 else if (strcmp(name, "AudioMixdown") == 0)
2666                         mix_opts_set(ud->builder, "AudioMixdown");
2667                 else if (strcmp(name, "SrtLanguage") == 0)
2668                         language_opts_set(ud->builder, "SrtLanguage");
2669                 else if (strcmp(name, "PreferredLanguage") == 0)
2670                         language_opts_set(ud->builder, "PreferredLanguage");
2671                 else if (strcmp(name, "SrtCodeset") == 0)
2672                         srt_codeset_opts_set(ud->builder, "SrtCodeset");
2673                 else if (strcmp(name, "title") == 0)
2674                         title_opts_set(ud->builder, "title");
2675                 else if (strcmp(name, "SubtitleTrack") == 0)
2676                         subtitle_track_opts_set(ud->builder, "SubtitleTrack", user_data);
2677                 else if (strcmp(name, "AudioTrack") == 0)
2678                         audio_track_opts_set(ud->builder, "AudioTrack", user_data);
2679                 else
2680                         generic_opts_set(ud->builder, name, find_combo_table(name));
2681         }
2682         if (handler_id > 0)
2683         {
2684                 g_signal_handler_unblock ((gpointer)combo, handler_id);
2685         }
2686 }
2687         
2688 static void
2689 init_ui_combo_boxes(GtkBuilder *builder)
2690 {
2691         gint ii;
2692
2693         init_combo_box(builder, "AudioBitrate");
2694         init_combo_box(builder, "AudioSamplerate");
2695         init_combo_box(builder, "VideoFramerate");
2696         init_combo_box(builder, "AudioMixdown");
2697         init_combo_box(builder, "SrtLanguage");
2698         init_combo_box(builder, "PreferredLanguage");
2699         init_combo_box(builder, "SrtCodeset");
2700         init_combo_box(builder, "title");
2701         init_combo_box(builder, "AudioTrack");
2702         for (ii = 0; combo_name_map[ii].name != NULL; ii++)
2703         {
2704                 init_combo_box(builder, combo_name_map[ii].name);
2705         }
2706 }
2707         
2708 static const char * turbo_opts = 
2709         "ref=1:subme=2:me=dia:analyse=none:trellis=0:"
2710         "no-fast-pskip=0:8x8dct=0";
2711
2712 // Construct the x264 options string
2713 // The result is allocated, so someone must free it at some point.
2714 gchar*
2715 ghb_build_x264opts_string(GValue *settings)
2716 {
2717         gchar *result;
2718         gchar *opts = ghb_settings_get_string(settings, "x264Option");
2719         if (opts != NULL)
2720         {
2721                 result = opts;
2722         }
2723         else
2724         {
2725                 result = g_strdup("");
2726         }
2727         return result;
2728 }
2729
2730 void
2731 ghb_part_duration(gint tt, gint sc, gint ec, gint *hh, gint *mm, gint *ss)
2732 {
2733         hb_list_t  * list;
2734         hb_title_t * title;
2735     hb_chapter_t * chapter;
2736         gint count, c;
2737         gint64 duration;
2738         
2739         *hh = *mm = *ss = 0;
2740         if (h_scan == NULL) return;
2741         list = hb_get_titles( h_scan );
2742     title = (hb_title_t*)hb_list_item( list, tt );
2743         if (title == NULL) return;
2744
2745         *hh = title->hours;
2746         *mm = title->minutes;
2747         *ss = title->seconds;
2748
2749         count = hb_list_count(title->list_chapter);
2750         if (sc > count) sc = count;
2751         if (ec > count) ec = count;
2752
2753         if (sc == 1 && ec == count)
2754                 return;
2755
2756         duration = 0;
2757         for (c = sc; c <= ec; c++)
2758         {
2759                 chapter = hb_list_item(title->list_chapter, c-1);
2760                 duration += chapter->duration;
2761         }
2762
2763         *hh =   duration / 90000 / 3600;
2764         *mm = ((duration / 90000) % 3600) / 60;
2765         *ss =  (duration / 90000) % 60;
2766 }
2767
2768 void
2769 ghb_get_chapter_duration(gint ti, gint ii, gint *hh, gint *mm, gint *ss)
2770 {
2771         hb_list_t  * list;
2772         hb_title_t * title;
2773     hb_chapter_t * chapter;
2774         gint count;
2775         
2776         g_debug("ghb_get_chapter_duration (title = %d)\n", ti);
2777         *hh = *mm = *ss = 0;
2778         if (h_scan == NULL) return;
2779         list = hb_get_titles( h_scan );
2780     title = (hb_title_t*)hb_list_item( list, ti );
2781         if (title == NULL) return;
2782         count = hb_list_count( title->list_chapter );
2783         if (ii >= count) return;
2784         chapter = hb_list_item(title->list_chapter, ii);
2785         if (chapter == NULL) return;
2786         *hh = chapter->hours;
2787         *mm = chapter->minutes;
2788         *ss = chapter->seconds;
2789 }
2790
2791 GValue*
2792 ghb_get_chapters(gint titleindex)
2793 {
2794         hb_list_t  * list;
2795         hb_title_t * title;
2796     hb_chapter_t * chapter;
2797         gint count, ii;
2798         GValue *chapters = NULL;
2799         
2800         g_debug("ghb_get_chapters (title = %d)\n", titleindex);
2801         if (h_scan == NULL) return NULL;
2802         list = hb_get_titles( h_scan );
2803     title = (hb_title_t*)hb_list_item( list, titleindex );
2804         if (title == NULL) return NULL;
2805         count = hb_list_count( title->list_chapter );
2806         chapters = ghb_array_value_new(count);
2807         for (ii = 0; ii < count; ii++)
2808         {
2809                 chapter = hb_list_item(title->list_chapter, ii);
2810                 if (chapter == NULL) break;
2811                 if (chapter->title == NULL || chapter->title[0] == 0)
2812                 {
2813                         gchar *str;
2814                         str = g_strdup_printf ("Chapter %2d", ii+1);
2815                         ghb_array_append(chapters, ghb_string_value_new(str));
2816                         g_free(str);
2817                 }
2818                 else 
2819                 {
2820                         ghb_array_append(chapters, ghb_string_value_new(chapter->title));
2821                 }
2822         }
2823         return chapters;
2824 }
2825
2826 gboolean
2827 ghb_ac3_in_audio_list(const GValue *audio_list)
2828 {
2829         gint count, ii;
2830
2831         count = ghb_array_len(audio_list);
2832         for (ii = 0; ii < count; ii++)
2833         {
2834                 GValue *asettings;
2835                 gint acodec;
2836
2837                 asettings = ghb_array_get_nth(audio_list, ii);
2838                 acodec = ghb_settings_combo_int(asettings, "AudioEncoder");
2839                 if (acodec & HB_ACODEC_AC3)
2840                         return TRUE;
2841         }
2842         return FALSE;
2843 }
2844
2845 static void
2846 audio_bitrate_opts_add(GtkBuilder *builder, const gchar *name, gint rate)
2847 {
2848         GtkTreeIter iter;
2849         GtkListStore *store;
2850         gchar *str;
2851         
2852         g_debug("audio_bitrate_opts_add ()\n");
2853
2854         if (rate < 8) return;
2855
2856         store = get_combo_box_store(builder, name);
2857         if (!find_combo_item_by_int(GTK_TREE_MODEL(store), rate, &iter))
2858         {
2859                 str = g_strdup_printf ("<small>%d</small>", rate);
2860                 gtk_list_store_append(store, &iter);
2861                 gtk_list_store_set(store, &iter, 
2862                                                    0, str, 
2863                                                    1, TRUE, 
2864                                                    2, str, 
2865                                                    3, (gdouble)rate, 
2866                                                    4, str, 
2867                                                    -1);
2868                 g_free(str);
2869         }
2870 }
2871
2872 static void
2873 audio_bitrate_opts_clean(
2874         GtkBuilder *builder, 
2875         const gchar *name, 
2876         gint first_rate, 
2877         gint last_rate)
2878 {
2879         GtkTreeIter iter;
2880         GtkListStore *store;
2881         gdouble ivalue;
2882         gboolean done = FALSE;
2883         gint ii = 0;
2884         guint last = (guint)last_rate;
2885         guint first = (guint)first_rate;
2886         
2887         g_debug("audio_bitrate_opts_clean ()\n");
2888         store = get_combo_box_store(builder, name);
2889         if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter))
2890         {
2891                 do
2892                 {
2893                         gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 3, &ivalue, -1);
2894                         if (search_rates(
2895                                 hb_audio_bitrates, ivalue, hb_audio_bitrates_count) < 0)
2896                         {
2897                                 done = !gtk_list_store_remove(store, &iter);
2898                         }
2899                         else if (ivalue < first || ivalue > last)
2900                         {
2901                                 ii++;
2902                                 gtk_list_store_set(store, &iter, 1, FALSE, -1);
2903                                 done = !gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
2904                         }
2905                         else
2906                         {
2907                                 ii++;
2908                                 gtk_list_store_set(store, &iter, 1, TRUE, -1);
2909                                 done = !gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
2910                         }
2911                 } while (!done);
2912         }
2913 }
2914
2915 static void
2916 audio_bitrate_opts_set(GtkBuilder *builder, const gchar *name)
2917 {
2918         GtkTreeIter iter;
2919         GtkListStore *store;
2920         gint ii;
2921         gchar *str;
2922         
2923         g_debug("audio_bitrate_opts_set ()\n");
2924         store = get_combo_box_store(builder, name);
2925         gtk_list_store_clear(store);
2926         for (ii = 0; ii < hb_audio_bitrates_count; ii++)
2927         {
2928                 gtk_list_store_append(store, &iter);
2929                 str = g_strdup_printf ("<small>%s</small>", 
2930                         hb_audio_bitrates[ii].string);
2931                 gtk_list_store_set(store, &iter, 
2932                                                    0, str,
2933                                                    1, TRUE, 
2934                                                    2, hb_audio_bitrates[ii].string, 
2935                                                    3, (gdouble)hb_audio_bitrates[ii].rate, 
2936                                                    4, hb_audio_bitrates[ii].string, 
2937                                                    -1);
2938                 g_free(str);
2939         }
2940 }
2941
2942 void
2943 ghb_set_passthru_bitrate_opts(GtkBuilder *builder, gint bitrate)
2944 {
2945         audio_bitrate_opts_add(builder, "AudioBitrate", bitrate);
2946 }
2947
2948 void
2949 ghb_set_default_bitrate_opts(
2950         GtkBuilder *builder, 
2951         gint first_rate, 
2952         gint last_rate)
2953 {
2954         audio_bitrate_opts_clean(builder, "AudioBitrate", first_rate, last_rate);
2955 }
2956
2957 static ghb_status_t hb_status;
2958
2959 void
2960 ghb_combo_init(signal_user_data_t *ud)
2961 {
2962         // Set up the list model for the combos
2963         init_ui_combo_boxes(ud->builder);
2964         // Populate all the combos
2965         ghb_update_ui_combo_box(ud, NULL, 0, TRUE);
2966 }
2967
2968 void
2969 ghb_backend_init(gint debug)
2970 {
2971     /* Init libhb */
2972     h_scan = hb_init( debug, 0 );
2973     h_queue = hb_init( debug, 0 );
2974 }
2975
2976 void
2977 ghb_backend_close()
2978 {
2979         hb_close(&h_queue);
2980         hb_close(&h_scan);
2981         hb_global_close();
2982 }
2983
2984 void ghb_backend_scan_stop()
2985 {
2986     hb_scan_stop( h_scan );
2987 }
2988
2989 void
2990 ghb_backend_scan(const gchar *path, gint titleindex, gint preview_count)
2991 {
2992     hb_scan( h_scan, path, titleindex, preview_count, 1 );
2993         hb_status.scan.state |= GHB_STATE_SCANNING;
2994         // initialize count and cur to something that won't cause FPE
2995         // when computing progress
2996         hb_status.scan.title_count = 1;
2997         hb_status.scan.title_cur = 0;
2998 }
2999
3000 void
3001 ghb_backend_queue_scan(const gchar *path, gint titlenum)
3002 {
3003         g_debug("ghb_backend_queue_scan()");
3004         hb_scan( h_queue, path, titlenum, 10, 0 );
3005         hb_status.queue.state |= GHB_STATE_SCANNING;
3006 }
3007
3008 gint
3009 ghb_get_scan_state()
3010 {
3011         return hb_status.scan.state;
3012 }
3013
3014 gint
3015 ghb_get_queue_state()
3016 {
3017         return hb_status.queue.state;
3018 }
3019
3020 void
3021 ghb_clear_scan_state(gint state)
3022 {
3023         hb_status.scan.state &= ~state;
3024 }
3025
3026 void
3027 ghb_clear_queue_state(gint state)
3028 {
3029         hb_status.queue.state &= ~state;
3030 }
3031
3032 void
3033 ghb_set_scan_state(gint state)
3034 {
3035         hb_status.scan.state |= state;
3036 }
3037
3038 void
3039 ghb_set_queue_state(gint state)
3040 {
3041         hb_status.queue.state |= state;
3042 }
3043
3044 void
3045 ghb_get_status(ghb_status_t *status)
3046 {
3047         memcpy(status, &hb_status, sizeof(ghb_status_t));
3048 }
3049
3050 void 
3051 ghb_track_status()
3052 {
3053     hb_state_t s_scan;
3054     hb_state_t s_queue;
3055
3056         if (h_scan == NULL) return;
3057     hb_get_state( h_scan, &s_scan );
3058         switch( s_scan.state )
3059     {
3060 #define p s_scan.param.scanning
3061         case HB_STATE_SCANNING:
3062                 {
3063                         hb_status.scan.state |= GHB_STATE_SCANNING;
3064                         hb_status.scan.title_count = p.title_count;
3065                         hb_status.scan.title_cur = p.title_cur;
3066                 } break;
3067 #undef p
3068
3069         case HB_STATE_SCANDONE:
3070         {
3071                         hb_status.scan.state &= ~GHB_STATE_SCANNING;
3072                         hb_status.scan.state |= GHB_STATE_SCANDONE;
3073         } break;
3074
3075 #define p s_scan.param.working
3076         case HB_STATE_WORKING:
3077                         hb_status.scan.state |= GHB_STATE_WORKING;
3078                         hb_status.scan.state &= ~GHB_STATE_PAUSED;
3079                         hb_status.scan.job_cur = p.job_cur;
3080                         hb_status.scan.job_count = p.job_count;
3081                         hb_status.scan.progress = p.progress;
3082                         hb_status.scan.rate_cur = p.rate_cur;
3083                         hb_status.scan.rate_avg = p.rate_avg;
3084                         hb_status.scan.hours = p.hours;
3085                         hb_status.scan.minutes = p.minutes;
3086                         hb_status.scan.seconds = p.seconds;
3087                         hb_status.scan.unique_id = p.sequence_id & 0xFFFFFF;
3088             break;
3089 #undef p
3090
3091         case HB_STATE_PAUSED:
3092                         hb_status.scan.state |= GHB_STATE_PAUSED;
3093             break;
3094                                 
3095         case HB_STATE_MUXING:
3096         {
3097                         hb_status.scan.state |= GHB_STATE_MUXING;
3098         } break;
3099
3100 #define p s_scan.param.workdone
3101         case HB_STATE_WORKDONE:
3102                 {
3103             hb_job_t *job;
3104
3105                         hb_status.scan.state |= GHB_STATE_WORKDONE;
3106                         hb_status.scan.state &= ~GHB_STATE_MUXING;
3107                         hb_status.scan.state &= ~GHB_STATE_PAUSED;
3108                         hb_status.scan.state &= ~GHB_STATE_WORKING;
3109                         switch (p.error)
3110                         {
3111                         case HB_ERROR_NONE:
3112                                 hb_status.scan.error = GHB_ERROR_NONE;
3113                                 break;
3114                         case HB_ERROR_CANCELED:
3115                                 hb_status.scan.error = GHB_ERROR_CANCELED;
3116                                 break;
3117                         default:
3118                                 hb_status.scan.error = GHB_ERROR_FAIL;
3119                                 break;
3120                         }
3121                         // Delete all remaining jobs of this encode.
3122                         // An encode can be composed of multiple associated jobs.
3123                         // When a job is stopped, libhb removes it from the job list,
3124                         // but does not remove other jobs that may be associated with it.
3125                         // Associated jobs are taged in the sequence id.
3126             while ((job = hb_job(h_scan, 0)) != NULL) 
3127                 hb_rem( h_scan, job );
3128                 } break;
3129 #undef p
3130     }
3131     hb_get_state( h_queue, &s_queue );
3132         switch( s_queue.state )
3133     {
3134 #define p s_queue.param.scanning
3135         case HB_STATE_SCANNING:
3136                 {
3137                         hb_status.queue.state |= GHB_STATE_SCANNING;
3138                         hb_status.queue.title_count = p.title_count;
3139                         hb_status.queue.title_cur = p.title_cur;
3140                 } break;
3141 #undef p
3142
3143         case HB_STATE_SCANDONE:
3144         {
3145                         hb_status.queue.state &= ~GHB_STATE_SCANNING;
3146                         hb_status.queue.state |= GHB_STATE_SCANDONE;
3147         } break;
3148
3149 #define p s_queue.param.working
3150         case HB_STATE_WORKING:
3151                         hb_status.queue.state |= GHB_STATE_WORKING;
3152                         hb_status.queue.state &= ~GHB_STATE_PAUSED;
3153                         hb_status.queue.state &= ~GHB_STATE_SEARCHING;
3154                         hb_status.queue.job_cur = p.job_cur;
3155                         hb_status.queue.job_count = p.job_count;
3156                         hb_status.queue.progress = p.progress;
3157                         hb_status.queue.rate_cur = p.rate_cur;
3158                         hb_status.queue.rate_avg = p.rate_avg;
3159                         hb_status.queue.hours = p.hours;
3160                         hb_status.queue.minutes = p.minutes;
3161                         hb_status.queue.seconds = p.seconds;
3162                         hb_status.queue.unique_id = p.sequence_id & 0xFFFFFF;
3163             break;
3164
3165         case HB_STATE_SEARCHING:
3166                         hb_status.queue.state |= GHB_STATE_SEARCHING;
3167                         hb_status.queue.state &= ~GHB_STATE_WORKING;
3168                         hb_status.queue.state &= ~GHB_STATE_PAUSED;
3169                         hb_status.queue.job_cur = p.job_cur;
3170                         hb_status.queue.job_count = p.job_count;
3171                         hb_status.queue.progress = p.progress;
3172                         hb_status.queue.rate_cur = p.rate_cur;
3173                         hb_status.queue.rate_avg = p.rate_avg;
3174                         hb_status.queue.hours = p.hours;
3175                         hb_status.queue.minutes = p.minutes;
3176                         hb_status.queue.seconds = p.seconds;
3177                         hb_status.queue.unique_id = p.sequence_id & 0xFFFFFF;
3178             break;
3179 #undef p
3180
3181         case HB_STATE_PAUSED:
3182                         hb_status.queue.state |= GHB_STATE_PAUSED;
3183             break;
3184                                 
3185         case HB_STATE_MUXING:
3186         {
3187                         hb_status.queue.state |= GHB_STATE_MUXING;
3188         } break;
3189
3190 #define p s_queue.param.workdone
3191         case HB_STATE_WORKDONE:
3192                 {
3193             hb_job_t *job;
3194
3195                         hb_status.queue.state |= GHB_STATE_WORKDONE;
3196                         hb_status.queue.state &= ~GHB_STATE_MUXING;
3197                         hb_status.queue.state &= ~GHB_STATE_PAUSED;
3198                         hb_status.queue.state &= ~GHB_STATE_WORKING;
3199                         hb_status.queue.state &= ~GHB_STATE_SEARCHING;
3200                         switch (p.error)
3201                         {
3202                         case HB_ERROR_NONE:
3203                                 hb_status.queue.error = GHB_ERROR_NONE;
3204                                 break;
3205                         case HB_ERROR_CANCELED:
3206                                 hb_status.queue.error = GHB_ERROR_CANCELED;
3207                                 break;
3208                         default:
3209                                 hb_status.queue.error = GHB_ERROR_FAIL;
3210                                 break;
3211                         }
3212                         // Delete all remaining jobs of this encode.
3213                         // An encode can be composed of multiple associated jobs.
3214                         // When a job is stopped, libhb removes it from the job list,
3215                         // but does not remove other jobs that may be associated with it.
3216                         // Associated jobs are taged in the sequence id.
3217             while ((job = hb_job(h_queue, 0)) != NULL) 
3218                 hb_rem( h_queue, job );
3219                 } break;
3220 #undef p
3221     }
3222 }
3223
3224 gboolean
3225 ghb_get_title_info(ghb_title_info_t *tinfo, gint titleindex)
3226 {
3227         hb_list_t  * list;
3228         hb_title_t * title;
3229         
3230     if (h_scan == NULL) return FALSE;
3231         list = hb_get_titles( h_scan );
3232         if( !hb_list_count( list ) )
3233         {
3234                 /* No valid title, stop right there */
3235                 return FALSE;
3236         }
3237
3238         title = hb_list_item( list, titleindex );
3239         if (title == NULL) return FALSE;        // Bad titleindex
3240         tinfo->index = titleindex;
3241         tinfo->width = title->width;
3242         tinfo->height = title->height;
3243         memcpy(tinfo->crop, title->crop, 4 * sizeof(int));
3244         // Don't allow crop to 0
3245         if (title->crop[0] + title->crop[1] >= title->height)
3246                 title->crop[0] = title->crop[1] = 0;
3247         if (title->crop[2] + title->crop[3] >= title->width)
3248                 title->crop[2] = title->crop[3] = 0;
3249         tinfo->num_chapters = hb_list_count(title->list_chapter);
3250         tinfo->rate_base = title->rate_base;
3251         tinfo->rate = title->rate;
3252         hb_reduce(&(tinfo->aspect_n), &(tinfo->aspect_d), 
3253                                 title->width * title->pixel_aspect_width, 
3254                                 title->height * title->pixel_aspect_height);
3255         tinfo->hours = title->hours;
3256         tinfo->minutes = title->minutes;
3257         tinfo->seconds = title->seconds;
3258         tinfo->duration = title->duration;
3259
3260         tinfo->angle_count = title->angle_count;
3261         tinfo->path = title->path;
3262         tinfo->name = title->name;
3263         tinfo->type = title->type;
3264         return TRUE;
3265 }
3266
3267 gboolean
3268 ghb_get_audio_info(ghb_audio_info_t *ainfo, gint titleindex, gint audioindex)
3269 {
3270     hb_audio_config_t *audio;
3271         
3272         audio = get_hb_audio(titleindex, audioindex);
3273         if (audio == NULL) return FALSE; // Bad audioindex
3274         ainfo->codec = audio->in.codec;
3275         ainfo->bitrate = audio->in.bitrate;
3276         ainfo->samplerate = audio->in.samplerate;
3277         return TRUE;
3278 }
3279
3280 gboolean
3281 ghb_audio_is_passthru(gint acodec)
3282 {
3283         g_debug("ghb_audio_is_passthru () \n");
3284         return (acodec & (HB_ACODEC_AC3 | HB_ACODEC_DCA));
3285 }
3286
3287 gint
3288 ghb_get_default_acodec()
3289 {
3290         return HB_ACODEC_FAAC;
3291 }
3292
3293 static void
3294 picture_settings_deps(signal_user_data_t *ud)
3295 {
3296         gboolean autoscale, keep_aspect, enable_keep_aspect;
3297         gboolean enable_scale_width, enable_scale_height;
3298         gboolean enable_disp_width, enable_disp_height, enable_par;
3299         gint pic_par;
3300         GtkWidget *widget;
3301
3302         pic_par = ghb_settings_combo_int(ud->settings, "PicturePAR");
3303         if (pic_par == 1)
3304         {
3305                 ghb_ui_update(ud, "autoscale", ghb_boolean_value(TRUE));
3306                 ghb_ui_update(ud, "PictureModulus", ghb_int_value(2));
3307                 ghb_ui_update(ud, "PictureLooseCrop", ghb_boolean_value(TRUE));
3308         }
3309         enable_keep_aspect = (pic_par != 1 && pic_par != 2);
3310         if (!enable_keep_aspect)
3311         {
3312                 ghb_ui_update(ud, "PictureKeepRatio", ghb_boolean_value(TRUE));
3313         }
3314         keep_aspect = ghb_settings_get_boolean(ud->settings, "PictureKeepRatio");
3315         autoscale = ghb_settings_get_boolean(ud->settings, "autoscale");
3316
3317         enable_scale_width = !autoscale && (pic_par != 1);
3318         enable_scale_height = !autoscale && (pic_par != 1);
3319         enable_disp_width = (pic_par == 3) && !keep_aspect;
3320         enable_par = (pic_par == 3) && !keep_aspect;
3321         enable_disp_height = FALSE;
3322
3323         widget = GHB_WIDGET(ud->builder, "PictureModulus");
3324         gtk_widget_set_sensitive(widget, pic_par != 1);
3325         widget = GHB_WIDGET(ud->builder, "PictureLooseCrop");
3326         gtk_widget_set_sensitive(widget, pic_par != 1);
3327         widget = GHB_WIDGET(ud->builder, "scale_width");
3328         gtk_widget_set_sensitive(widget, enable_scale_width);
3329         widget = GHB_WIDGET(ud->builder, "scale_height");
3330         gtk_widget_set_sensitive(widget, enable_scale_height);
3331         widget = GHB_WIDGET(ud->builder, "PictureDisplayWidth");
3332         gtk_widget_set_sensitive(widget, enable_disp_width);
3333         widget = GHB_WIDGET(ud->builder, "PictureDisplayHeight");
3334         gtk_widget_set_sensitive(widget, enable_disp_height);
3335         widget = GHB_WIDGET(ud->builder, "PicturePARWidth");
3336         gtk_widget_set_sensitive(widget, enable_par);
3337         widget = GHB_WIDGET(ud->builder, "PicturePARHeight");
3338         gtk_widget_set_sensitive(widget, enable_par);
3339         widget = GHB_WIDGET(ud->builder, "PictureKeepRatio");
3340         gtk_widget_set_sensitive(widget, enable_keep_aspect);
3341         widget = GHB_WIDGET(ud->builder, "autoscale");
3342         gtk_widget_set_sensitive(widget, pic_par != 1);
3343 }
3344
3345 void
3346 ghb_set_scale(signal_user_data_t *ud, gint mode)
3347 {
3348         hb_list_t  * list;
3349         hb_title_t * title;
3350         hb_job_t   * job;
3351         gboolean keep_aspect;
3352         gint pic_par;
3353         gboolean autocrop, autoscale, noscale;
3354         gint crop[4], width, height, par_width, par_height;
3355         gint crop_width, crop_height;
3356         gint aspect_n, aspect_d;
3357         gboolean keep_width = (mode & GHB_PIC_KEEP_WIDTH);
3358         gboolean keep_height = (mode & GHB_PIC_KEEP_HEIGHT);
3359         gint step;
3360         GtkWidget *widget;
3361         gint mod;
3362         gint max_width = 0;
3363         gint max_height = 0;
3364         static gboolean busy = FALSE;
3365         
3366         g_debug("ghb_set_scale ()\n");
3367         picture_settings_deps(ud);
3368         if (h_scan == NULL) return;
3369         list = hb_get_titles( h_scan );
3370         if( !hb_list_count( list ) )
3371         {
3372                 /* No valid title, stop right there */
3373                 return;
3374         }
3375         gint titleindex;
3376
3377         titleindex = ghb_settings_combo_int(ud->settings, "title");
3378     title = hb_list_item( list, titleindex );
3379         if (title == NULL) return;
3380         job   = title->job;
3381         if (job == NULL) return;
3382
3383         if (busy) return;
3384         busy = TRUE;
3385
3386         if (!ud->dont_clear_presets && (keep_width || keep_height))
3387         {
3388                 ghb_settings_set_int(ud->settings, "PictureWidth", 0);
3389                 ghb_settings_set_int(ud->settings, "PictureHeight", 0);
3390         }
3391
3392         // First configure widgets
3393         mod = ghb_settings_combo_int(ud->settings, "PictureModulus");
3394         pic_par = ghb_settings_combo_int(ud->settings, "PicturePAR");
3395         keep_aspect = ghb_settings_get_boolean(ud->settings, "PictureKeepRatio");
3396         autocrop = ghb_settings_get_boolean(ud->settings, "PictureAutoCrop");
3397         autoscale = ghb_settings_get_boolean(ud->settings, "autoscale");
3398         // "Noscale" is a flag that says we prefer to crop extra to satisfy
3399         // alignment constraints rather than scaling to satisfy them.
3400         noscale = ghb_settings_get_boolean(ud->settings, "PictureLooseCrop");
3401         // Align dimensions to either 16 or 2 pixels
3402         // The scaler crashes if the dimensions are not divisible by 2
3403         // x264 also will not accept dims that are not multiple of 2
3404         if (autoscale)
3405         {
3406                 keep_width = FALSE;
3407                 keep_height = FALSE;
3408         }
3409         // Step needs to be at least 2 because odd widths cause scaler crash
3410         step = mod;
3411         widget = GHB_WIDGET (ud->builder, "scale_width");
3412         gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
3413         widget = GHB_WIDGET (ud->builder, "scale_height");
3414         gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
3415         if (noscale)
3416         {
3417                 widget = GHB_WIDGET (ud->builder, "PictureTopCrop");
3418                 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
3419                 widget = GHB_WIDGET (ud->builder, "PictureBottomCrop");
3420                 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
3421                 widget = GHB_WIDGET (ud->builder, "PictureLeftCrop");
3422                 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
3423                 widget = GHB_WIDGET (ud->builder, "PictureRightCrop");
3424                 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
3425         }
3426         else
3427         {
3428                 widget = GHB_WIDGET (ud->builder, "PictureTopCrop");
3429                 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 1, 16);
3430                 widget = GHB_WIDGET (ud->builder, "PictureBottomCrop");
3431                 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 1, 16);
3432                 widget = GHB_WIDGET (ud->builder, "PictureLeftCrop");
3433                 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 1, 16);
3434                 widget = GHB_WIDGET (ud->builder, "PictureRightCrop");
3435                 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 1, 16);
3436         }
3437         ghb_title_info_t tinfo;
3438         ghb_get_title_info (&tinfo, titleindex);
3439         if (autocrop)
3440         {
3441                 crop[0] = tinfo.crop[0];
3442                 crop[1] = tinfo.crop[1];
3443                 crop[2] = tinfo.crop[2];
3444                 crop[3] = tinfo.crop[3];
3445                 ghb_ui_update(ud, "PictureTopCrop", ghb_int64_value(crop[0]));
3446                 ghb_ui_update(ud, "PictureBottomCrop", ghb_int64_value(crop[1]));
3447                 ghb_ui_update(ud, "PictureLeftCrop", ghb_int64_value(crop[2]));
3448                 ghb_ui_update(ud, "PictureRightCrop", ghb_int64_value(crop[3]));
3449         }
3450         else
3451         {
3452                 crop[0] = ghb_settings_get_int(ud->settings, "PictureTopCrop");
3453                 crop[1] = ghb_settings_get_int(ud->settings, "PictureBottomCrop");
3454                 crop[2] = ghb_settings_get_int(ud->settings, "PictureLeftCrop");
3455                 crop[3] = ghb_settings_get_int(ud->settings, "PictureRightCrop");
3456         }
3457         if (noscale)
3458         {
3459                 gint need1, need2;
3460
3461                 // Adjust the cropping to accomplish the desired width and height
3462                 crop_width = tinfo.width - crop[2] - crop[3];
3463                 crop_height = tinfo.height - crop[0] - crop[1];
3464                 width = MOD_DOWN(crop_width, mod);
3465                 height = MOD_DOWN(crop_height, mod);
3466
3467                 need1 = (crop_height - height) / 2;
3468                 need2 = crop_height - height - need1;
3469                 crop[0] += need1;
3470                 crop[1] += need2;
3471                 need1 = (crop_width - width) / 2;
3472                 need2 = crop_width - width - need1;
3473                 crop[2] += need1;
3474                 crop[3] += need2;
3475                 ghb_ui_update(ud, "PictureTopCrop", ghb_int64_value(crop[0]));
3476                 ghb_ui_update(ud, "PictureBottomCrop", ghb_int64_value(crop[1]));
3477                 ghb_ui_update(ud, "PictureLeftCrop", ghb_int64_value(crop[2]));
3478                 ghb_ui_update(ud, "PictureRightCrop", ghb_int64_value(crop[3]));
3479         }
3480         hb_reduce(&aspect_n, &aspect_d, 
3481                                 title->width * title->pixel_aspect_width, 
3482                                 title->height * title->pixel_aspect_height);
3483         crop_width = title->width - crop[2] - crop[3];
3484         crop_height = title->height - crop[0] - crop[1];
3485         if (autoscale)
3486         {
3487                 width = crop_width;
3488                 height = crop_height;
3489         }
3490         else
3491         {
3492                 width = ghb_settings_get_int(ud->settings, "scale_width");
3493                 height = ghb_settings_get_int(ud->settings, "scale_height");
3494                 max_width = MOD_DOWN(
3495                         ghb_settings_get_int(ud->settings, "PictureWidth"), mod);
3496                 max_height = MOD_DOWN(
3497                         ghb_settings_get_int(ud->settings, "PictureHeight"), mod);
3498         }
3499         g_debug("max_width %d, max_height %d\n", max_width, max_height);
3500
3501         if (width < 16)
3502                 width = title->width - crop[2] - crop[3];
3503         if (height < 16)
3504                 height = title->height - crop[0] - crop[1];
3505
3506         width = MOD_ROUND(width, mod);
3507         height = MOD_ROUND(height, mod);
3508
3509         // Adjust dims according to max values
3510         if (max_height)
3511                 height = MIN(height, max_height);
3512         if (max_width)
3513                 width = MIN(width, max_width);
3514
3515         if (pic_par)
3516         {
3517                 job->anamorphic.mode = pic_par;
3518                 // The scaler crashes if the dimensions are not divisible by 2
3519                 // Align mod 2.  And so does something in x264_encoder_headers()
3520                 job->modulus = mod;
3521                 job->anamorphic.par_width = title->pixel_aspect_width;
3522                 job->anamorphic.par_height = title->pixel_aspect_height;
3523                 job->anamorphic.dar_width = 0;
3524                 job->anamorphic.dar_height = 0;
3525
3526                 if (keep_height && pic_par == 2)
3527                         width = ((double)height * crop_width / crop_height) + mod / 2;
3528                 job->width = width;
3529                 job->height = height;
3530                 job->maxWidth = max_width;
3531                 job->maxHeight = max_height;
3532                 job->crop[0] = crop[0]; job->crop[1] = crop[1];
3533                 job->crop[2] = crop[2]; job->crop[3] = crop[3];
3534                 if (job->anamorphic.mode == 3 && !keep_aspect)
3535                 {
3536                         job->anamorphic.keep_display_aspect = 0;
3537                         if (mode & GHB_PIC_KEEP_PAR)
3538                         {
3539                                 job->anamorphic.par_width = 
3540                                         ghb_settings_get_int(ud->settings, "PicturePARWidth");
3541                                 job->anamorphic.par_height = 
3542                                         ghb_settings_get_int(ud->settings, "PicturePARHeight");
3543                         }
3544                         else
3545                         {
3546                                 job->anamorphic.dar_width = 
3547                                         ghb_settings_get_int(ud->settings, 
3548                                                                                 "PictureDisplayWidth");
3549                                 job->anamorphic.dar_height = height;
3550                         }
3551                 }
3552                 else
3553                 {
3554                         job->anamorphic.keep_display_aspect = 1;
3555                 }
3556                 hb_set_anamorphic_size( job, &width, &height, 
3557                                                                 &par_width, &par_height );
3558                 if (job->anamorphic.mode == 3 && !keep_aspect && 
3559                         mode & GHB_PIC_KEEP_PAR)
3560                 {
3561                         // hb_set_anamorphic_size reduces the par, which we
3562                         // don't want in this case because the user is
3563                         // explicitely specifying it.
3564                         par_width = ghb_settings_get_int(ud->settings, 
3565                                                                                         "PicturePARWidth");
3566                         par_height = ghb_settings_get_int(ud->settings, 
3567                                                                                                 "PicturePARHeight");
3568                 }
3569         }
3570         else 
3571         {
3572                 job->anamorphic.mode = pic_par;
3573                 if (keep_aspect)
3574                 {
3575                         gdouble par;
3576                         gint new_width, new_height;
3577                         
3578                         // Compute pixel aspect ration.  
3579                         par = (gdouble)(title->height * aspect_n) / (title->width * aspect_d);
3580                         // Must scale so that par becomes 1:1
3581                         // Try to keep largest dimension
3582                         new_height = (crop_height * ((gdouble)width/crop_width) / par);
3583                         new_width = (crop_width * ((gdouble)height/crop_height) * par);
3584
3585                         if (max_width && new_width > max_width)
3586                         {
3587                                 height = new_height;
3588                         }
3589                         else if (max_height && new_height > max_height)
3590                         {
3591                                 width = new_width;
3592                         }
3593                         else if (keep_width)
3594                         {
3595                                 height = new_height;
3596                         }
3597                         else if (keep_height)
3598                         {
3599                                 width = new_width;
3600                         }
3601                         else if (width > new_width)
3602                         {
3603                                 height = new_height;
3604                         }
3605                         else
3606                         {
3607                                 width = new_width;
3608                         }
3609                         g_debug("new w %d h %d\n", width, height);
3610                 }
3611                 width = MOD_ROUND(width, mod);
3612                 height = MOD_ROUND(height, mod);
3613                 if (max_height)
3614                         height = MIN(height, max_height);
3615                 if (max_width)
3616                         width = MIN(width, max_width);
3617                 par_width = par_height = 1;
3618         }
3619         ghb_ui_update(ud, "scale_width", ghb_int64_value(width));
3620         ghb_ui_update(ud, "scale_height", ghb_int64_value(height));
3621
3622         gint disp_width, dar_width, dar_height;
3623         gchar *str;
3624
3625         disp_width = (gdouble)(width * par_width / par_height) + 0.5;
3626         hb_reduce(&dar_width, &dar_height, disp_width, height);
3627                 
3628         gint iaspect = dar_width * 9 / dar_height;
3629         if (dar_width > 2 * dar_height)
3630         {
3631                 str = g_strdup_printf("%.2f : 1", (gdouble)dar_width / dar_height);
3632         }
3633         else if (iaspect <= 16 && iaspect >= 15)
3634         {
3635                 str = g_strdup_printf("%.2f : 9", (gdouble)dar_width * 9 / dar_height);
3636         }
3637         else if (iaspect <= 12 && iaspect >= 11)
3638         {
3639                 str = g_strdup_printf("%.2f : 3", (gdouble)dar_width * 3 / dar_height);
3640         }
3641         else
3642         {
3643                 str = g_strdup_printf("%d : %d", dar_width, dar_height);
3644         }
3645         ghb_ui_update(ud, "display_aspect", ghb_string_value(str));
3646         g_free(str);
3647         ghb_ui_update(ud, "PicturePARWidth", ghb_int64_value(par_width));
3648         ghb_ui_update(ud, "PicturePARHeight", ghb_int64_value(par_height));
3649         ghb_ui_update(ud, "PictureDisplayWidth", ghb_int64_value(disp_width));
3650         ghb_ui_update(ud, "PictureDisplayHeight", ghb_int64_value(height));
3651         busy = FALSE;
3652 }
3653
3654 static void
3655 set_preview_job_settings(hb_job_t *job, GValue *settings)
3656 {
3657         job->crop[0] = ghb_settings_get_int(settings, "PictureTopCrop");
3658         job->crop[1] = ghb_settings_get_int(settings, "PictureBottomCrop");
3659         job->crop[2] = ghb_settings_get_int(settings, "PictureLeftCrop");
3660         job->crop[3] = ghb_settings_get_int(settings, "PictureRightCrop");
3661
3662         job->anamorphic.mode = ghb_settings_combo_int(settings, "PicturePAR");
3663         job->modulus = 
3664                 ghb_settings_combo_int(settings, "PictureModulus");
3665         job->width = ghb_settings_get_int(settings, "scale_width");
3666         job->height = ghb_settings_get_int(settings, "scale_height");
3667         if (ghb_settings_get_boolean(settings, "show_crop"))
3668         {
3669                 gdouble xscale = (gdouble)job->width / 
3670                         (gdouble)(job->title->width - job->crop[2] - job->crop[3]);
3671                 gdouble yscale = (gdouble)job->height / 
3672                         (gdouble)(job->title->height - job->crop[0] - job->crop[1]);
3673         
3674                 job->width += xscale * (job->crop[2] + job->crop[3]);
3675                 job->height += yscale * (job->crop[0] + job->crop[1]);
3676                 job->crop[0] = 0;
3677                 job->crop[1] = 0;
3678                 job->crop[2] = 0;
3679                 job->crop[3] = 0;
3680                 job->modulus = 2;
3681         }
3682
3683         gboolean decomb_deint = ghb_settings_get_boolean(settings, "PictureDecombDeinterlace");
3684         if (decomb_deint)
3685         {
3686                 gint decomb = ghb_settings_combo_int(settings, "PictureDecomb");
3687                 job->deinterlace = (decomb == 0) ? 0 : 1;
3688         }
3689         else
3690         {
3691                 gint deint = ghb_settings_combo_int(settings, "PictureDeinterlace");
3692                 job->deinterlace = (deint == 0) ? 0 : 1;
3693         }
3694
3695         gboolean keep_aspect;
3696         keep_aspect = ghb_settings_get_boolean(settings, "PictureKeepRatio");
3697         if (job->anamorphic.mode)
3698         {
3699                 job->anamorphic.par_width = job->title->pixel_aspect_width;
3700                 job->anamorphic.par_height = job->title->pixel_aspect_height;
3701                 job->anamorphic.dar_width = 0;
3702                 job->anamorphic.dar_height = 0;
3703
3704                 if (job->anamorphic.mode == 3 && !keep_aspect)
3705                 {
3706                         job->anamorphic.keep_display_aspect = 0;
3707                         job->anamorphic.par_width = 
3708                                 ghb_settings_get_int(settings, "PicturePARWidth");
3709                         job->anamorphic.par_height = 
3710                                 ghb_settings_get_int(settings, "PicturePARHeight");
3711                 }
3712                 else
3713                 {
3714                         job->anamorphic.keep_display_aspect = 1;
3715                 }
3716         }
3717 }
3718
3719 gint
3720 ghb_calculate_target_bitrate(GValue *settings, gint titleindex)
3721 {
3722         hb_list_t  * list;
3723         hb_title_t * title;
3724         hb_job_t   * job;
3725         gint size;
3726
3727         if (h_scan == NULL) return 1500;
3728         list = hb_get_titles( h_scan );
3729     title = hb_list_item( list, titleindex );
3730         if (title == NULL) return 1500;
3731         job   = title->job;
3732         if (job == NULL) return 1500;
3733         size = ghb_settings_get_int(settings, "VideoTargetSize");
3734         return hb_calc_bitrate( job, size );
3735 }
3736
3737 gboolean
3738 ghb_validate_filter_string(const gchar *str, gint max_fields)
3739 {
3740         gint fields = 0;
3741         gchar *end;
3742         gdouble val;
3743
3744         if (str == NULL || *str == 0) return TRUE;
3745         while (*str)
3746         {
3747                 val = g_strtod(str, &end);
3748                 if (str != end)
3749                 { // Found a numeric value
3750                         fields++;
3751                         // negative max_fields means infinate
3752                         if (max_fields >= 0 && fields > max_fields) return FALSE;
3753                         if (*end == 0)
3754                                 return TRUE;
3755                         if (*end != ':')
3756                                 return FALSE;
3757                         str = end + 1;
3758                 }
3759                 else
3760                         return FALSE;
3761         }
3762         return FALSE;
3763 }
3764
3765 gboolean
3766 ghb_validate_filters(signal_user_data_t *ud)
3767 {
3768         gchar *str;
3769         gint index;
3770         gchar *message;
3771
3772         gboolean decomb_deint = ghb_settings_get_boolean(ud->settings, "PictureDecombDeinterlace");
3773         // deinte
3774         index = ghb_settings_combo_int(ud->settings, "PictureDeinterlace");
3775         if (!decomb_deint && index == 1)
3776         {
3777                 str = ghb_settings_get_string(ud->settings, "PictureDeinterlaceCustom");
3778                 if (!ghb_validate_filter_string(str, -1))
3779                 {
3780                         message = g_strdup_printf(
3781                                                 "Invalid Deinterlace Settings:\n\n%s\n",
3782                                                 str);
3783                         ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
3784                         g_free(message);
3785                         g_free(str);
3786                         return FALSE;
3787                 }
3788                 g_free(str);
3789         }
3790         // detel
3791         index = ghb_settings_combo_int(ud->settings, "PictureDetelecine");
3792         if (index == 1)
3793         {
3794                 str = ghb_settings_get_string(ud->settings, "PictureDetelecineCustom");
3795                 if (!ghb_validate_filter_string(str, -1))
3796                 {
3797                         message = g_strdup_printf(
3798                                                 "Invalid Detelecine Settings:\n\n%s\n",
3799                                                 str);
3800                         ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
3801                         g_free(message);
3802                         g_free(str);
3803                         return FALSE;
3804                 }
3805                 g_free(str);
3806         }
3807         // decomb
3808         index = ghb_settings_combo_int(ud->settings, "PictureDecomb");
3809         if (decomb_deint && index == 1)
3810         {
3811                 str = ghb_settings_get_string(ud->settings, "PictureDecombCustom");
3812                 if (!ghb_validate_filter_string(str, -1))
3813                 {
3814                         message = g_strdup_printf(
3815                                                 "Invalid Decomb Settings:\n\n%s\n",
3816                                                 str);
3817                         ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
3818                         g_free(message);
3819                         g_free(str);
3820                         return FALSE;
3821                 }
3822                 g_free(str);
3823         }
3824         // denois
3825         index = ghb_settings_combo_int(ud->settings, "PictureDenoise");
3826         if (index == 1)
3827         {
3828                 str = ghb_settings_get_string(ud->settings, "PictureDenoiseCustom");
3829                 if (!ghb_validate_filter_string(str, -1))
3830                 {
3831                         message = g_strdup_printf(
3832                                                 "Invalid Denoise Settings:\n\n%s\n",
3833                                                 str);
3834                         ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
3835                         g_free(str);
3836                         g_free(message);
3837                         return FALSE;
3838                 }
3839                 g_free(str);
3840         }
3841         return TRUE;
3842 }
3843
3844 gboolean
3845 ghb_validate_video(signal_user_data_t *ud)
3846 {
3847         gint vcodec, mux;
3848         gchar *message;
3849
3850         mux = ghb_settings_combo_int(ud->settings, "FileFormat");
3851         vcodec = ghb_settings_combo_int(ud->settings, "VideoEncoder");
3852         if ((mux == HB_MUX_MP4) && (vcodec == HB_VCODEC_THEORA))
3853         {
3854                 // mp4/theora combination is not supported.
3855                 message = g_strdup_printf(
3856                                         "Theora is not supported in the MP4 container.\n\n"
3857                                         "You should choose a different video codec or container.\n"
3858                                         "If you continue, FFMPEG will be chosen for you.");
3859                 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
3860                 {
3861                         g_free(message);
3862                         return FALSE;
3863                 }
3864                 g_free(message);
3865                 vcodec = HB_VCODEC_FFMPEG;
3866                 ghb_ui_update(ud, "VideoEncoder", ghb_int64_value(vcodec));
3867         }
3868         return TRUE;
3869 }
3870
3871 gboolean
3872 ghb_validate_subtitles(signal_user_data_t *ud)
3873 {
3874         hb_list_t  * list;
3875         hb_title_t * title;
3876         gchar *message;
3877
3878         if (h_scan == NULL) return FALSE;
3879         list = hb_get_titles( h_scan );
3880         if( !hb_list_count( list ) )
3881         {
3882                 /* No valid title, stop right there */
3883                 g_message("No title found.\n");
3884                 return FALSE;
3885         }
3886
3887         gint titleindex;
3888
3889         titleindex = ghb_settings_combo_int(ud->settings, "title");
3890     title = hb_list_item( list, titleindex );
3891         if (title == NULL) return FALSE;
3892
3893         const GValue *slist, *settings;
3894         gint count, ii, source;
3895         gboolean burned, one_burned = FALSE;
3896
3897         slist = ghb_settings_get_value(ud->settings, "subtitle_list");
3898         count = ghb_array_len(slist);
3899         for (ii = 0; ii < count; ii++)
3900         {
3901                 settings = ghb_array_get_nth(slist, ii);
3902                 source = ghb_settings_get_int(settings, "SubtitleSource");
3903                 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
3904                 if (burned && one_burned)
3905                 {
3906                         // MP4 can only handle burned vobsubs.  make sure there isn't
3907                         // already something burned in the list
3908                         message = g_strdup_printf(
3909                         "Only one subtitle may be burned into the video.\n\n"
3910                                 "You should change your subtitle selections.\n"
3911                                 "If you continue, some subtitles will be lost.");
3912                         if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
3913                         {
3914                                 g_free(message);
3915                                 return FALSE;
3916                         }
3917                         g_free(message);
3918                         break;
3919                 }
3920                 else if (burned)
3921                 {
3922                         one_burned = TRUE;
3923                 }
3924                 if (source == SRTSUB)
3925                 {
3926                         gchar *filename;
3927
3928                         filename = ghb_settings_get_string(settings, "SrtFile");
3929                         if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
3930                         {
3931                                 message = g_strdup_printf(
3932                                 "Srt file does not exist or not a regular file.\n\n"
3933                                         "You should choose a valid file.\n"
3934                                         "If you continue, this subtitle will be ignored.");
3935                                 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, 
3936                                         "Cancel", "Continue"))
3937                                 {
3938                                         g_free(message);
3939                                         return FALSE;
3940                                 }
3941                                 g_free(message);
3942                                 break;
3943                         }
3944                 }
3945         }
3946         return TRUE;
3947 }
3948
3949 gint
3950 ghb_select_audio_codec(signal_user_data_t *ud, gint track)
3951 {
3952         hb_list_t  * list;
3953         hb_title_t * title;
3954         hb_audio_config_t *audio;
3955
3956         if (h_scan == NULL) return -1;
3957         list = hb_get_titles( h_scan );
3958         if( !hb_list_count( list ) )
3959         {
3960                 return -1;
3961         }
3962
3963         gint titleindex;
3964
3965         titleindex = ghb_settings_combo_int(ud->settings, "title");
3966     title = hb_list_item( list, titleindex );
3967         if (title == NULL) return -1;
3968
3969         gint mux = ghb_settings_combo_int(ud->settings, "FileFormat");
3970
3971         if (track < 0 || track >= hb_list_count(title->list_audio))
3972                 return -1;
3973
3974         audio = (hb_audio_config_t *) hb_list_audio_config_item(
3975                                                                         title->list_audio, track );
3976         if (mux == HB_MUX_MP4)
3977         {
3978                 if (audio->in.codec == HB_ACODEC_AC3)
3979                         return audio->in.codec;
3980                 else
3981                         return HB_ACODEC_FAAC;
3982         }
3983         else
3984         {
3985                 if (audio->in.codec == HB_ACODEC_AC3 || audio->in.codec == HB_ACODEC_DCA)
3986                         return audio->in.codec;
3987                 else
3988                         return HB_ACODEC_LAME;
3989         }
3990 }
3991
3992 const gchar*
3993 ghb_select_audio_codec_str(signal_user_data_t *ud, gint track)
3994 {
3995         gint acodec, ii;
3996
3997         acodec = ghb_select_audio_codec(ud, track);
3998         for (ii = 0; ii < acodec_opts.count; ii++)
3999         {
4000                 if (acodec_opts.map[ii].ivalue == acodec)
4001                         return acodec_opts.map[ii].option;
4002         }
4003         return "Unknown";
4004 }
4005
4006 gboolean
4007 ghb_validate_audio(signal_user_data_t *ud)
4008 {
4009         hb_list_t  * list;
4010         hb_title_t * title;
4011         gchar *message;
4012         GValue *value;
4013
4014         if (h_scan == NULL) return FALSE;
4015         list = hb_get_titles( h_scan );
4016         if( !hb_list_count( list ) )
4017         {
4018                 /* No valid title, stop right there */
4019                 g_message("No title found.\n");
4020                 return FALSE;
4021         }
4022
4023         gint titleindex;
4024
4025         titleindex = ghb_settings_combo_int(ud->settings, "title");
4026     title = hb_list_item( list, titleindex );
4027         if (title == NULL) return FALSE;
4028         gint mux = ghb_settings_combo_int(ud->settings, "FileFormat");
4029
4030         const GValue *audio_list;
4031         gint count, ii;
4032
4033         audio_list = ghb_settings_get_value(ud->settings, "audio_list");
4034         count = ghb_array_len(audio_list);
4035         for (ii = 0; ii < count; ii++)
4036         {
4037                 GValue *asettings;
4038             hb_audio_config_t *taudio;
4039
4040                 asettings = ghb_array_get_nth(audio_list, ii);
4041                 gint track = ghb_settings_combo_int(asettings, "AudioTrack");
4042                 gint codec = ghb_settings_combo_int(asettings, "AudioEncoder");
4043                 if (codec == HB_ACODEC_MASK)
4044                         continue;
4045
4046         taudio = (hb_audio_config_t *) hb_list_audio_config_item(
4047                                                                                         title->list_audio, track );
4048                 if (!(taudio->in.codec & codec) && 
4049                         (codec & (HB_ACODEC_AC3 | HB_ACODEC_DCA)))
4050                 {
4051                         // Not supported.  AC3 is passthrough only, so input must be AC3
4052                         message = g_strdup_printf(
4053                                                 "The source does not support Pass-Thru.\n\n"
4054                                                 "You should choose a different audio codec.\n"
4055                                                 "If you continue, one will be chosen for you.");
4056                         if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
4057                         {
4058                                 g_free(message);
4059                                 return FALSE;
4060                         }
4061                         g_free(message);
4062                         if (mux == HB_MUX_MKV)
4063                         {
4064                                 codec = HB_ACODEC_LAME;
4065                         }
4066                         else
4067                         {
4068                                 codec = HB_ACODEC_FAAC;
4069                         }
4070                         value = ghb_lookup_acodec_value(codec);
4071                         ghb_settings_take_value(asettings, "AudioEncoder", value);
4072                 }
4073                 gchar *a_unsup = NULL;
4074                 gchar *mux_s = NULL;
4075                 if (mux == HB_MUX_MP4)
4076                 { 
4077                         mux_s = "MP4";
4078                         // mp4/vorbis|DTS combination is not supported.
4079                         if (codec == HB_ACODEC_VORBIS)
4080                         {
4081                                 a_unsup = "Vorbis";
4082                                 codec = HB_ACODEC_FAAC;
4083                         }
4084                         if (codec == HB_ACODEC_DCA)
4085                         {
4086                                 a_unsup = "DTS";
4087                                 codec = HB_ACODEC_FAAC;
4088                         }
4089                 }
4090                 if (a_unsup)
4091                 {
4092                         message = g_strdup_printf(
4093                                                 "%s is not supported in the %s container.\n\n"
4094                                                 "You should choose a different audio codec.\n"
4095                                                 "If you continue, one will be chosen for you.", a_unsup, mux_s);
4096                         if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
4097                         {
4098                                 g_free(message);
4099                                 return FALSE;
4100                         }
4101                         g_free(message);
4102                         value = ghb_lookup_acodec_value(codec);
4103                         ghb_settings_take_value(asettings, "AudioEncoder", value);
4104                 }
4105                 gint mix = ghb_settings_combo_int (asettings, "AudioMixdown");
4106                 gboolean allow_mono = TRUE;
4107                 gboolean allow_stereo = TRUE;
4108                 gboolean allow_dolby = TRUE;
4109                 gboolean allow_dpl2 = TRUE;
4110                 gboolean allow_6ch = TRUE;
4111                 allow_mono = TRUE;
4112                 gint layout = taudio->in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
4113                 allow_stereo =
4114                         ((layout == HB_INPUT_CH_LAYOUT_MONO && !allow_mono) || layout >= HB_INPUT_CH_LAYOUT_STEREO);
4115                 allow_dolby =
4116                         (layout == HB_INPUT_CH_LAYOUT_3F1R) || 
4117                         (layout == HB_INPUT_CH_LAYOUT_3F2R) || 
4118                         (layout == HB_INPUT_CH_LAYOUT_DOLBY);
4119                 allow_dpl2 = (layout == HB_INPUT_CH_LAYOUT_3F2R);
4120                 allow_6ch =
4121                         (codec & ~HB_ACODEC_LAME) &&
4122                         (layout == HB_INPUT_CH_LAYOUT_3F2R) && 
4123                         (taudio->in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE);
4124
4125                 gchar *mix_unsup = NULL;
4126                 if (mix == HB_AMIXDOWN_MONO && !allow_mono)
4127                 {
4128                         mix_unsup = "mono";
4129                 }
4130                 if (mix == HB_AMIXDOWN_STEREO && !allow_stereo)
4131                 {
4132                         mix_unsup = "stereo";
4133                 }
4134                 if (mix == HB_AMIXDOWN_DOLBY && !allow_dolby)
4135                 {
4136                         mix_unsup = "Dolby";
4137                 }
4138                 if (mix == HB_AMIXDOWN_DOLBYPLII && !allow_dpl2)
4139                 {
4140                         mix_unsup = "Dolby Pro Logic II";
4141                 }
4142                 if (mix == HB_AMIXDOWN_6CH && !allow_6ch)
4143                 {
4144                         mix_unsup = "6 Channel";
4145                 }
4146                 if (mix_unsup)
4147                 {
4148                         message = g_strdup_printf(
4149                                                 "The source audio does not support %s mixdown.\n\n"
4150                                                 "You should choose a different mixdown.\n"
4151                                                 "If you continue, one will be chosen for you.", mix_unsup);
4152                         if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
4153                         {
4154                                 g_free(message);
4155                                 return FALSE;
4156                         }
4157                         g_free(message);
4158                         mix = ghb_get_best_mix(titleindex, track, codec, mix);
4159                         value = get_amix_value(mix);
4160                         ghb_settings_take_value(asettings, "AudioMixdown", value);
4161                 }
4162         }
4163         return TRUE;
4164 }
4165
4166 gboolean
4167 ghb_validate_vquality(GValue *settings)
4168 {
4169         gint vcodec;
4170         gchar *message;
4171         gint min, max;
4172
4173         if (ghb_settings_get_boolean(settings, "nocheckvquality")) return TRUE;
4174         vcodec = ghb_settings_combo_int(settings, "VideoEncoder");
4175         gdouble vquality;
4176         vquality = ghb_settings_get_double(settings, "VideoQualitySlider");
4177         if (ghb_settings_get_boolean(settings, "vquality_type_constant"))
4178         {
4179                 switch (vcodec)
4180                 {
4181                         case HB_VCODEC_X264:
4182                         {
4183                                 min = 16;
4184                                 max = 30;
4185                         } break;
4186
4187                         case HB_VCODEC_FFMPEG:
4188                         {
4189                                 min = 1;
4190                                 max = 8;
4191                         } break;
4192
4193                         case HB_VCODEC_THEORA:
4194                         {
4195                                 min = 0;
4196                                 max = 63;
4197                         } break;
4198
4199                         default:
4200                         {
4201                                 min = 48;
4202                                 max = 62;
4203                         } break;
4204                 }
4205                 if (vquality < min || vquality > max)
4206                 {
4207                         message = g_strdup_printf(
4208                                                 "Interesting video quality choise: %d\n\n"
4209                                                 "Typical values range from %d to %d.\n"
4210                                                 "Are you sure you wish to use this setting?",
4211                                                 (gint)vquality, min, max);
4212                         if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message, 
4213                                                                         "Cancel", "Continue"))
4214                         {
4215                                 g_free(message);
4216                                 return FALSE;
4217                         }
4218                         g_free(message);
4219                 }
4220         }
4221         return TRUE;
4222 }
4223
4224 static void
4225 add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
4226 {
4227         hb_list_t  * list;
4228         hb_title_t * title;
4229         hb_job_t   * job;
4230         static gchar *x264opts;
4231         gint sub_id = 0;
4232         gboolean tweaks = FALSE;
4233         gchar *detel_str = NULL;
4234         gchar *decomb_str = NULL;
4235         gchar *deint_str = NULL;
4236         gchar *deblock_str = NULL;
4237         gchar *denoise_str = NULL;
4238         gchar *dest_str = NULL;
4239
4240         g_debug("add_job()\n");
4241         if (h == NULL) return;
4242         list = hb_get_titles( h );
4243         if( !hb_list_count( list ) )
4244         {
4245                 /* No valid title, stop right there */
4246                 return;
4247         }
4248
4249     title = hb_list_item( list, titleindex );
4250         if (title == NULL) return;
4251
4252         /* Set job settings */
4253         job   = title->job;
4254         if (job == NULL) return;
4255
4256         job->angle = ghb_settings_get_int(js, "angle");
4257         job->start_at_preview = ghb_settings_get_int(js, "start_frame") + 1;
4258         if (job->start_at_preview)
4259         {
4260                 job->seek_points = ghb_settings_get_int(js, "preview_count");
4261                 job->pts_to_stop = ghb_settings_get_int(js, "live_duration") * 90000LL;
4262         }
4263
4264         tweaks = ghb_settings_get_boolean(js, "allow_tweaks");
4265         job->mux = ghb_settings_combo_int(js, "FileFormat");
4266         if (job->mux == HB_MUX_MP4)
4267         {
4268                 job->largeFileSize = ghb_settings_get_boolean(js, "Mp4LargeFile");
4269                 job->mp4_optimize = ghb_settings_get_boolean(js, "Mp4HttpOptimize");
4270         }
4271         else
4272         {
4273                 job->largeFileSize = FALSE;
4274                 job->mp4_optimize = FALSE;
4275         }
4276         if (!job->start_at_preview)
4277         {
4278                 gint start, end;
4279                 gint num_chapters = hb_list_count(title->list_chapter);
4280                 gint duration = title->duration / 90000;
4281                 job->chapter_start = 1;
4282                 job->chapter_end = num_chapters;
4283
4284                 if (ghb_settings_combo_int(js, "PtoPType") == 0)
4285                 {
4286                         start = ghb_settings_get_int(js, "start_point");
4287                         end = ghb_settings_get_int(js, "end_point");
4288                         job->chapter_start = MIN( num_chapters, start );
4289                         job->chapter_end   = MAX( job->chapter_start, end );
4290
4291                 }
4292                 if (ghb_settings_combo_int(js, "PtoPType") == 1)
4293                 {
4294                         job->chapter_start = 1;
4295                         job->chapter_end = num_chapters;
4296                         start = ghb_settings_get_int(js, "start_point");
4297                         end = ghb_settings_get_int(js, "end_point");
4298                         job->pts_to_start = (int64_t)MIN(duration-1, start) * 90000;
4299                         job->pts_to_stop = (int64_t)MAX(start+1, end) * 90000 - 
4300                                                                 job->pts_to_start;
4301                 }
4302                 if (ghb_settings_combo_int(js, "PtoPType") == 2)
4303                 {
4304                         job->chapter_start = 1;
4305                         job->chapter_end = num_chapters;
4306                         start = ghb_settings_get_int(js, "start_point");
4307                         end = ghb_settings_get_int(js, "end_point");
4308                         gint64 max_frames;
4309                         max_frames = (gint64)duration * title->rate / title->rate_base;
4310                         job->frame_to_start = (int64_t)MIN(max_frames-1, start-1);
4311                         job->frame_to_stop = (int64_t)MAX(start, end-1) - 
4312                                                                  job->frame_to_start;
4313                 }
4314                 job->chapter_markers = ghb_settings_get_boolean(js, "ChapterMarkers");
4315                 if (job->chapter_start == job->chapter_end)
4316                         job->chapter_markers = 0;
4317                 if ( job->chapter_markers )
4318                 {
4319                         GValue *chapters;
4320                         GValue *chapter;
4321                         gint chap;
4322                         gint count;
4323
4324                         chapters = ghb_settings_get_value(js, "chapter_list");
4325                         count = ghb_array_len(chapters);
4326                         for(chap = 0; chap < count; chap++)
4327                         {
4328                                 hb_chapter_t * chapter_s;
4329                                 gchar *name;
4330
4331                                 name = NULL;
4332                                 chapter = ghb_array_get_nth(chapters, chap);
4333                                 name = ghb_value_string(chapter); 
4334                                 if (name == NULL)
4335                                 {
4336                                         name = g_strdup_printf ("Chapter %2d", chap+1);
4337                                 }
4338                                 chapter_s = hb_list_item( job->title->list_chapter, chap);
4339                                 strncpy(chapter_s->title, name, 1023);
4340                                 chapter_s->title[1023] = '\0';
4341                                 g_free(name);
4342                         }
4343                 }
4344         }
4345         job->crop[0] = ghb_settings_get_int(js, "PictureTopCrop");
4346         job->crop[1] = ghb_settings_get_int(js, "PictureBottomCrop");
4347         job->crop[2] = ghb_settings_get_int(js, "PictureLeftCrop");
4348         job->crop[3] = ghb_settings_get_int(js, "PictureRightCrop");
4349
4350         
4351         gboolean decomb_deint = ghb_settings_get_boolean(js, "PictureDecombDeinterlace");
4352         gint decomb = ghb_settings_combo_int(js, "PictureDecomb");
4353         gint deint = ghb_settings_combo_int(js, "PictureDeinterlace");
4354         if (!decomb_deint)
4355                 job->deinterlace = (deint != 0) ? 1 : 0;
4356         else
4357                 job->deinterlace = 0;
4358     job->grayscale   = ghb_settings_get_boolean(js, "VideoGrayScale");
4359
4360         gboolean keep_aspect;
4361         keep_aspect = ghb_settings_get_boolean(js, "PictureKeepRatio");
4362         job->anamorphic.mode = ghb_settings_combo_int(js, "PicturePAR");
4363         job->modulus = ghb_settings_combo_int(js, "PictureModulus");
4364         if (job->anamorphic.mode)
4365         {
4366                 job->anamorphic.par_width = title->pixel_aspect_width;
4367                 job->anamorphic.par_height = title->pixel_aspect_height;
4368                 job->anamorphic.dar_width = 0;
4369                 job->anamorphic.dar_height = 0;
4370
4371                 if (job->anamorphic.mode == 3 && !keep_aspect)
4372                 {
4373                         job->anamorphic.keep_display_aspect = 0;
4374                         job->anamorphic.par_width = 
4375                                 ghb_settings_get_int(js, "PicturePARWidth");
4376                         job->anamorphic.par_height = 
4377                                 ghb_settings_get_int(js, "PicturePARHeight");
4378                 }
4379                 else
4380                 {
4381                         job->anamorphic.keep_display_aspect = 1;
4382                 }
4383         }
4384
4385         /* Add selected filters */
4386         job->filters = hb_list_init();
4387         gint detel = ghb_settings_combo_int(js, "PictureDetelecine");
4388         if ( detel )
4389         {
4390                 if (detel != 1)
4391                 {
4392                         if (detel_opts.map[detel].svalue != NULL)
4393                                 detel_str = g_strdup(detel_opts.map[detel].svalue);
4394                 }
4395                 else
4396                         detel_str = ghb_settings_get_string(js, "PictureDetelecineCustom");
4397                 hb_filter_detelecine.settings = detel_str;
4398                 hb_list_add( job->filters, &hb_filter_detelecine );
4399         }
4400         if ( decomb_deint && decomb )
4401         {
4402                 if (decomb != 1)
4403                 {
4404                         if (decomb_opts.map[decomb].svalue != NULL)
4405                                 decomb_str = g_strdup(decomb_opts.map[decomb].svalue);
4406                 }
4407                 else
4408                         decomb_str = ghb_settings_get_string(js, "PictureDecombCustom");
4409                 hb_filter_decomb.settings = decomb_str;
4410                 hb_list_add( job->filters, &hb_filter_decomb );
4411         }
4412         if( job->deinterlace )
4413         {
4414                 if (deint != 1)
4415                 {
4416                         if (deint_opts.map[deint].svalue != NULL)
4417                                 deint_str = g_strdup(deint_opts.map[deint].svalue);
4418                 }
4419                 else
4420                         deint_str = ghb_settings_get_string(js, "PictureDeinterlaceCustom");
4421                 hb_filter_deinterlace.settings = deint_str;
4422                 hb_list_add( job->filters, &hb_filter_deinterlace );
4423         }
4424         gint deblock = ghb_settings_get_int(js, "PictureDeblock");
4425         if( deblock >= 5 )
4426         {
4427                 deblock_str = g_strdup_printf("%d", deblock);
4428                 hb_filter_deblock.settings = deblock_str;
4429                 hb_list_add( job->filters, &hb_filter_deblock );
4430         }
4431         gint denoise = ghb_settings_combo_int(js, "PictureDenoise");
4432         if( denoise )
4433         {
4434                 if (denoise != 1)
4435                 {
4436                         if (denoise_opts.map[denoise].svalue != NULL)
4437                                 denoise_str = g_strdup(denoise_opts.map[denoise].svalue);
4438                 }
4439                 else
4440                         denoise_str = ghb_settings_get_string(js, "PictureDenoiseCustom");
4441                 hb_filter_denoise.settings = denoise_str;
4442                 hb_list_add( job->filters, &hb_filter_denoise );
4443         }
4444         job->width = ghb_settings_get_int(js, "scale_width");
4445         job->height = ghb_settings_get_int(js, "scale_height");
4446
4447         job->vcodec = ghb_settings_combo_int(js, "VideoEncoder");
4448         if ((job->mux == HB_MUX_MP4 ) && (job->vcodec == HB_VCODEC_THEORA))
4449         {
4450                 // mp4/theora combination is not supported.
4451                 job->vcodec = HB_VCODEC_FFMPEG;
4452         }
4453         if ((job->vcodec == HB_VCODEC_X264) && (job->mux == HB_MUX_MP4))
4454         {
4455                 job->ipod_atom = ghb_settings_get_boolean(js, "Mp4iPodCompatible");
4456         }
4457         if (ghb_settings_get_boolean(js, "vquality_type_constant"))
4458         {
4459                 gdouble vquality;
4460                 vquality = ghb_settings_get_double(js, "VideoQualitySlider");
4461                 job->vquality =  vquality;
4462                 job->vbitrate = 0;
4463         }
4464         else if (ghb_settings_get_boolean(js, "vquality_type_bitrate"))
4465         {
4466                 job->vquality = -1.0;
4467                 job->vbitrate = ghb_settings_get_int(js, "VideoAvgBitrate");
4468         }
4469
4470         gint vrate = ghb_settings_combo_int(js, "VideoFramerate");
4471         if( vrate == 0 )
4472         {
4473                 job->vrate = title->rate;
4474                 job->vrate_base = title->rate_base;
4475                 job->cfr = 0;
4476         }
4477         else
4478         {
4479                 job->vrate = 27000000;
4480                 job->vrate_base = vrate;
4481                 job->cfr = 1;
4482         }
4483
4484         const GValue *audio_list;
4485         gint count, ii;
4486         gint tcount = 0;
4487         
4488         audio_list = ghb_settings_get_value(js, "audio_list");
4489         count = ghb_array_len(audio_list);
4490         for (ii = 0; ii < count; ii++)
4491         {
4492                 GValue *asettings;
4493             hb_audio_config_t audio;
4494             hb_audio_config_t *taudio;
4495
4496                 hb_audio_config_init(&audio);
4497                 asettings = ghb_array_get_nth(audio_list, ii);
4498                 audio.in.track = ghb_settings_get_int(asettings, "AudioTrack");
4499                 audio.out.track = tcount;
4500                 audio.out.codec = ghb_settings_combo_int(asettings, "AudioEncoder");
4501         taudio = (hb_audio_config_t *) hb_list_audio_config_item(
4502                                                                         title->list_audio, audio.in.track );
4503                 if (audio.out.codec & (HB_ACODEC_AC3 | HB_ACODEC_DCA))
4504                 {
4505                         if (!(taudio->in.codec & (HB_ACODEC_AC3 | HB_ACODEC_DCA)))
4506                         {
4507                                 // Not supported.  
4508                                 // AC3/DTS is passthrough only, so input must be AC3/DTS
4509                                 if (job->mux == HB_MUX_MKV)
4510                                 {
4511                                         audio.out.codec = HB_ACODEC_LAME;
4512                                 }
4513                                 else
4514                                 {
4515                                         audio.out.codec = HB_ACODEC_FAAC;
4516                                 }
4517                         }
4518                         else
4519                         {
4520                                 audio.out.codec &= taudio->in.codec;
4521                         }
4522                 }
4523                 if ((job->mux == HB_MUX_MP4) && 
4524                         ((audio.out.codec & HB_ACODEC_DCA) ||
4525                         (audio.out.codec & HB_ACODEC_VORBIS)))
4526                 {
4527                         // mp4/mp3|dts|vorbis combination is not supported.
4528                         audio.out.codec = HB_ACODEC_FAAC;
4529                 }
4530         audio.out.dynamic_range_compression = 
4531                         ghb_settings_get_double(asettings, "AudioTrackDRCSlider");
4532         if (audio.out.dynamic_range_compression < 1.0)
4533                 audio.out.dynamic_range_compression = 0.0;
4534
4535                 // It would be better if this were done in libhb for us, but its not yet.
4536                 if (audio.out.codec & (HB_ACODEC_AC3 | HB_ACODEC_DCA))
4537                 {
4538                         audio.out.mixdown = 0;
4539                 }
4540                 else
4541                 {
4542                         int channels;
4543
4544                         audio.out.mixdown = ghb_settings_combo_int(asettings, "AudioMixdown");
4545                         if (audio.out.mixdown == HB_AMIXDOWN_MONO)
4546                                 channels = 1;
4547                         else if (audio.out.mixdown == HB_AMIXDOWN_6CH)
4548                                 channels = 6;
4549                         else
4550                                 channels = 2;
4551
4552                         // Make sure the mixdown is valid and pick a new one if not.
4553                         audio.out.mixdown = ghb_get_best_mix(titleindex, 
4554                                 audio.in.track, audio.out.codec, audio.out.mixdown);
4555                         audio.out.bitrate = 
4556                                 ghb_settings_combo_int(asettings, "AudioBitrate");
4557                         gint srate = ghb_settings_combo_int(asettings, "AudioSamplerate");
4558                         if (srate == 0) // 0 is same as source
4559                                 audio.out.samplerate = taudio->in.samplerate;
4560                         else
4561                                 audio.out.samplerate = srate;
4562
4563                         audio.out.bitrate = ghb_get_best_audio_bitrate(
4564                                 audio.out.codec, audio.out.bitrate, channels);
4565                 }
4566
4567                 // Add it to the jobs audio list
4568         hb_audio_add( job, &audio );
4569                 tcount++;
4570         }
4571         // I was tempted to move this up with the reset of the video quality
4572         // settings, but I suspect the settings above need to be made
4573         // first in order for hb_calc_bitrate to be accurate.
4574         if (ghb_settings_get_boolean(js, "vquality_type_target"))
4575         {
4576                 gint size;
4577                 
4578                 size = ghb_settings_get_int(js, "VideoTargetSize");
4579         job->vbitrate = hb_calc_bitrate( job, size );
4580                 job->vquality = -1.0;
4581         }
4582
4583         dest_str = ghb_settings_get_string(js, "destination");
4584         job->file = dest_str;
4585
4586         const GValue *subtitle_list;
4587         gint subtitle;
4588         gboolean force, burned, def, one_burned = FALSE;
4589         
4590         ghb_settings_set_boolean(js, "subtitle_scan", FALSE);
4591         subtitle_list = ghb_settings_get_value(js, "subtitle_list");
4592         count = ghb_array_len(subtitle_list);
4593         for (ii = 0; ii < count; ii++)
4594         {
4595                 GValue *ssettings;
4596                 gint source;
4597
4598                 ssettings = ghb_array_get_nth(subtitle_list, ii);
4599
4600                 force = ghb_settings_get_boolean(ssettings, "SubtitleForced");
4601                 burned = ghb_settings_get_boolean(ssettings, "SubtitleBurned");
4602                 def = ghb_settings_get_boolean(ssettings, "SubtitleDefaultTrack");
4603                 source = ghb_settings_get_int(ssettings, "SubtitleSource");
4604
4605                 if (source == SRTSUB)
4606                 {
4607                 hb_subtitle_config_t sub_config;
4608                         gchar *filename, *lang, *code;
4609
4610                         filename = ghb_settings_get_string(ssettings, "SrtFile");
4611                         if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
4612                         {
4613                                 continue;
4614                         }
4615                         sub_config.offset = ghb_settings_get_int(ssettings, "SrtOffset");
4616                         lang = ghb_settings_get_string(ssettings, "SrtLanguage");
4617                         code = ghb_settings_get_string(ssettings, "SrtCodeset");
4618                         strncpy(sub_config.src_filename, filename, 128);
4619                         strncpy(sub_config.src_codeset, code, 40);
4620                         sub_config.force = 0;
4621                         sub_config.dest = PASSTHRUSUB;
4622                         sub_config.default_track = def;
4623
4624                         hb_srt_add( job, &sub_config, lang);
4625
4626                         g_free(filename);
4627                         g_free(lang);
4628                         g_free(code);
4629                         continue;
4630                 }
4631
4632                 subtitle = ghb_settings_get_int(ssettings, "SubtitleTrack");
4633                 if (subtitle == -1)
4634                 {
4635                         if (!burned)
4636                         {
4637                                 job->select_subtitle_config.dest = PASSTHRUSUB;
4638                         }
4639                         else if (burned)
4640                         {
4641                                 // Only allow one subtitle to be burned into the video
4642                                 if (one_burned)
4643                                         continue;
4644                                 job->select_subtitle_config.dest = RENDERSUB;
4645                                 one_burned = TRUE;
4646                         }
4647                         job->select_subtitle_config.force = force;
4648                         job->select_subtitle_config.default_track = def;
4649                         job->indepth_scan = 1;
4650                         ghb_settings_set_boolean(js, "subtitle_scan", TRUE);
4651                 }
4652                 else if (subtitle >= 0)
4653                 {
4654                 hb_subtitle_t * subt;
4655                 hb_subtitle_config_t sub_config;
4656
4657                 subt = (hb_subtitle_t *)hb_list_item(title->list_subtitle, subtitle);
4658                         if (subt != NULL)
4659                         {
4660                                 sub_config = subt->config;
4661                                 if (!burned && subt->format == PICTURESUB)
4662                                 {
4663                                         sub_config.dest = PASSTHRUSUB;
4664                                 }
4665                                 else if ( burned && subt->format == PICTURESUB )
4666                                 {
4667                                         // Only allow one subtitle to be burned into the video
4668                                         if (one_burned)
4669                                                 continue;
4670                                         one_burned = TRUE;
4671                                 }
4672                                 sub_config.force = force;
4673                                 sub_config.default_track = def;
4674                         hb_subtitle_add( job, &sub_config, subtitle );
4675                         }
4676                 }
4677         }
4678
4679         // TODO: libhb holds onto a reference to the x264opts and is not
4680         // finished with it until encoding the job is done.  But I can't
4681         // find a way to get at the job before it is removed in order to
4682         // free up the memory I am allocating here.
4683         // The short story is THIS LEAKS.
4684         x264opts = ghb_build_x264opts_string(js);
4685         
4686         if( *x264opts == '\0' )
4687         {
4688                 g_free(x264opts);
4689                 x264opts = NULL;
4690         }
4691
4692         if (job->indepth_scan == 1)
4693         {
4694                 // Subtitle scan. Look for subtitle matching audio language
4695
4696                 /*
4697                  * When subtitle scan is enabled do a fast pre-scan job
4698                  * which will determine which subtitles to enable, if any.
4699                  */
4700                 job->pass = -1;
4701                 job->indepth_scan = 1;
4702                 job->x264opts = NULL;
4703
4704                 /*
4705                  * Add the pre-scan job
4706                  */
4707                 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
4708                 hb_add( h, job );
4709         }
4710
4711         if( ghb_settings_get_boolean(js, "VideoTwoPass") &&
4712                 !ghb_settings_get_boolean(js, "vquality_type_constant"))
4713         {
4714                 /*
4715                  * If subtitle_scan is enabled then only turn it on
4716                  * for the second pass and then off again for the
4717                  * second.
4718                  */
4719                 job->pass = 1;
4720                 job->indepth_scan = 0;
4721
4722                 /*
4723                  * If turbo options have been selected then append them
4724                  * to the x264opts now (size includes one ':' and the '\0')
4725                  */
4726                 if( ghb_settings_get_boolean(js, "VideoTurboTwoPass") )
4727                 {
4728                         gchar *tmp_x264opts;
4729                         gchar *extra_opts;
4730                         gint badapt;
4731
4732                         badapt = ghb_lookup_badapt(x264opts);
4733                         if (badapt == 2)
4734                         {
4735                                 extra_opts = g_strdup_printf("%s", turbo_opts);
4736                         }
4737                         else
4738                         {
4739                                 extra_opts = g_strdup_printf("%s:weightb=0", turbo_opts);
4740                         }
4741         
4742                         if ( x264opts )
4743                         {
4744                                 tmp_x264opts = g_strdup_printf("%s:%s", x264opts, extra_opts);
4745                         } 
4746                         else 
4747                         {
4748                                 /*
4749                                  * No x264opts to modify, but apply the turbo options
4750                                  * anyway as they may be modifying defaults
4751                                  */
4752                                 tmp_x264opts = g_strdup_printf("%s", extra_opts);
4753                         }
4754                         g_free(extra_opts);
4755
4756                         job->x264opts = tmp_x264opts;
4757                 }
4758                 else
4759                 {
4760                         job->x264opts = x264opts;
4761                 }
4762                 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
4763                 hb_add( h, job );
4764                 //if (job->x264opts != NULL)
4765                 //      g_free(job->x264opts);
4766
4767                 job->pass = 2;
4768                 /*
4769                  * On the second pass we turn off subtitle scan so that we
4770                  * can actually encode using any subtitles that were auto
4771                  * selected in the first pass (using the whacky select-subtitle
4772                  * attribute of the job).
4773                  */
4774                 job->indepth_scan = 0;
4775                 job->x264opts = x264opts;
4776                 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
4777                 hb_add( h, job );
4778                 //if (job->x264opts != NULL)
4779                 //      g_free(job->x264opts);
4780         }
4781         else
4782         {
4783                 job->x264opts = x264opts;
4784                 job->indepth_scan = 0;
4785                 job->pass = 0;
4786                 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
4787                 hb_add( h, job );
4788                 //if (job->x264opts != NULL)
4789                 //      g_free(job->x264opts);
4790         }
4791
4792         // clean up audio list
4793         gint num_audio_tracks = hb_list_count(job->list_audio);
4794         for(ii = 0; ii < num_audio_tracks; ii++)
4795         {
4796                 hb_audio_t *audio = (hb_audio_t*)hb_list_item(job->list_audio, 0);
4797                 hb_list_rem(job->list_audio, audio);
4798                 free(audio);
4799         }
4800
4801         // clean up subtitle list
4802         gint num_subtitle_tracks = hb_list_count(job->list_subtitle);
4803         for(ii = 0; ii < num_subtitle_tracks; ii++)
4804         {
4805                 hb_subtitle_t *subtitle = hb_list_item(job->list_subtitle, 0);
4806                 hb_list_rem(job->list_subtitle, subtitle);
4807                 free(subtitle);
4808         }
4809
4810         if (detel_str) g_free(detel_str);
4811         if (decomb_str) g_free(decomb_str);
4812         if (deint_str) g_free(deint_str);
4813         if (deblock_str) g_free(deblock_str);
4814         if (denoise_str) g_free(denoise_str);
4815         if (dest_str) g_free(dest_str);
4816 }
4817
4818 void
4819 ghb_add_job(GValue *js, gint unique_id)
4820 {
4821         // Since I'm doing a scan of the single title I want just prior 
4822         // to adding the job, there is only the one title to choose from.
4823         add_job(h_queue, js, unique_id, 0);
4824 }
4825
4826 void
4827 ghb_add_live_job(GValue *js, gint unique_id)
4828 {
4829         // Since I'm doing a scan of the single title I want just prior 
4830         // to adding the job, there is only the one title to choose from.
4831         gint titleindex = ghb_settings_combo_int(js, "title");
4832         add_job(h_scan, js, unique_id, titleindex);
4833 }
4834
4835 void
4836 ghb_remove_job(gint unique_id)
4837 {
4838     hb_job_t * job;
4839     gint ii;
4840         
4841         // Multiples passes all get the same id
4842         // remove them all.
4843         // Go backwards through list, so reordering doesn't screw me.
4844         ii = hb_count(h_queue) - 1;
4845     while ((job = hb_job(h_queue, ii--)) != NULL)
4846     {
4847         if ((job->sequence_id & 0xFFFFFF) == unique_id)
4848                         hb_rem(h_queue, job);
4849     }
4850 }
4851
4852 void
4853 ghb_start_queue()
4854 {
4855         hb_start( h_queue );
4856 }
4857
4858 void
4859 ghb_stop_queue()
4860 {
4861         hb_stop( h_queue );
4862 }
4863
4864 void
4865 ghb_start_live_encode()
4866 {
4867         hb_start( h_scan );
4868 }
4869
4870 void
4871 ghb_stop_live_encode()
4872 {
4873         hb_stop( h_scan );
4874 }
4875
4876 void
4877 ghb_pause_queue()
4878 {
4879     hb_state_t s;
4880     hb_get_state2( h_queue, &s );
4881
4882     if( s.state == HB_STATE_PAUSED )
4883     {
4884                 hb_status.queue.state &= ~GHB_STATE_PAUSED;
4885                 hb_resume( h_queue );
4886     }
4887     else
4888     {
4889                 hb_status.queue.state |= GHB_STATE_PAUSED;
4890                 hb_pause( h_queue );
4891     }
4892 }
4893
4894 static void
4895 vert_line(
4896         GdkPixbuf * pb, 
4897         guint8 r, 
4898         guint8 g, 
4899         guint8 b, 
4900         gint x, 
4901         gint y, 
4902         gint len, 
4903         gint width)
4904 {
4905         guint8 *pixels = gdk_pixbuf_get_pixels (pb);
4906         guint8 *dst;
4907         gint ii, jj;
4908         gint channels = gdk_pixbuf_get_n_channels (pb);
4909         gint stride = gdk_pixbuf_get_rowstride (pb);
4910
4911         for (jj = 0; jj < width; jj++)
4912         {
4913                 dst = pixels + y * stride + (x+jj) * channels;
4914                 for (ii = 0; ii < len; ii++)
4915                 {
4916                         dst[0] = r;
4917                         dst[1] = g;
4918                         dst[2] = b;
4919                         dst += stride;
4920                 }
4921         }
4922 }
4923
4924 static void
4925 horz_line(
4926         GdkPixbuf * pb, 
4927         guint8 r, 
4928         guint8 g, 
4929         guint8 b, 
4930         gint x, 
4931         gint y, 
4932         gint len,
4933         gint width)
4934 {
4935         guint8 *pixels = gdk_pixbuf_get_pixels (pb);
4936         guint8 *dst;
4937         gint ii, jj;
4938         gint channels = gdk_pixbuf_get_n_channels (pb);
4939         gint stride = gdk_pixbuf_get_rowstride (pb);
4940
4941         for (jj = 0; jj < width; jj++)
4942         {
4943                 dst = pixels + (y+jj) * stride + x * channels;
4944                 for (ii = 0; ii < len; ii++)
4945                 {
4946                         dst[0] = r;
4947                         dst[1] = g;
4948                         dst[2] = b;
4949                         dst += channels;
4950                 }
4951         }
4952 }
4953
4954 static void
4955 hash_pixbuf(
4956         GdkPixbuf * pb,
4957         gint        x,
4958         gint        y,
4959         gint        w,
4960         gint        h,
4961         gint        step,
4962         gint            orientation)
4963 {
4964         gint ii, jj;
4965         gint line_width = 8;
4966         struct
4967         {
4968                 guint8 r;
4969                 guint8 g;
4970                 guint8 b;
4971         } c[4] = 
4972         {{0x80, 0x80, 0x80},{0xC0, 0x80, 0x70},{0x80, 0xA0, 0x80},{0x70, 0x80, 0xA0}};
4973
4974         if (!orientation)
4975         {
4976                 // vertical lines
4977                 for (ii = x, jj = 0; ii+line_width < x+w; ii += step, jj++)
4978                 {
4979                         vert_line(pb, c[jj&3].r, c[jj&3].g, c[jj&3].b, ii, y, h, line_width);
4980                 }
4981         }
4982         else
4983         {
4984                 // horizontal lines
4985                 for (ii = y, jj = 0; ii+line_width < y+h; ii += step, jj++)
4986                 {
4987                         horz_line(pb, c[jj&3].r, c[jj&3].g, c[jj&3].b, x, ii, w, line_width);
4988                 }
4989         }
4990 }
4991
4992 GdkPixbuf*
4993 ghb_get_preview_image(
4994         gint titleindex, 
4995         gint index, 
4996         signal_user_data_t *ud,
4997         gint *out_width,
4998         gint *out_height)
4999 {
5000         GValue *settings;
5001         hb_title_t *title;
5002         hb_list_t  *list;
5003         
5004         settings = ud->settings;
5005         list = hb_get_titles( h_scan );
5006         if( !hb_list_count( list ) )
5007         {
5008                 /* No valid title, stop right there */
5009                 return NULL;
5010         }
5011     title = hb_list_item( list, titleindex );
5012         if (title == NULL) return NULL;
5013         if (title->job == NULL) return NULL;
5014         set_preview_job_settings(title->job, settings);
5015
5016         // hb_get_preview doesn't compensate for anamorphic, so lets
5017         // calculate scale factors
5018         gint width, height, par_width = 1, par_height = 1;
5019         gint pic_par = ghb_settings_combo_int(settings, "PicturePAR");
5020         if (pic_par)
5021         {
5022                 hb_set_anamorphic_size( title->job, &width, &height, 
5023                                                                 &par_width, &par_height );
5024         }
5025
5026         // Make sure we have a big enough buffer to receive the image from libhb
5027         gint dstWidth = title->job->width;
5028         gint dstHeight= title->job->height;
5029
5030         static guint8 *buffer = NULL;
5031         static gint bufferSize = 0;
5032         gint newSize;
5033
5034         newSize = dstWidth * dstHeight * 4;
5035         if( bufferSize < newSize )
5036         {
5037                 bufferSize = newSize;
5038                 buffer     = (guint8*) g_realloc( buffer, bufferSize );
5039         }
5040         hb_get_preview( h_scan, title, index, buffer );
5041
5042         // Create an GdkPixbuf and copy the libhb image into it, converting it from
5043         // libhb's format something suitable.
5044         
5045         // The image data returned by hb_get_preview is 4 bytes per pixel, 
5046         // BGRA format. Alpha is ignored.
5047
5048         GdkPixbuf *preview = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, dstWidth, dstHeight);
5049         guint8 *pixels = gdk_pixbuf_get_pixels (preview);
5050         
5051         guint32 *src = (guint32*)buffer;
5052         guint8 *dst = pixels;
5053
5054         gint ii, jj;
5055         gint channels = gdk_pixbuf_get_n_channels (preview);
5056         gint stride = gdk_pixbuf_get_rowstride (preview);
5057         guint8 *tmp;
5058
5059         for (ii = 0; ii < dstHeight; ii++)
5060         {
5061                 tmp = dst;
5062                 for (jj = 0; jj < dstWidth; jj++)
5063                 {
5064                         tmp[0] = src[0] >> 16;
5065                         tmp[1] = src[0] >> 8;
5066                         tmp[2] = src[0] >> 0;
5067                         tmp += channels;
5068                         src++;
5069                 }
5070                 dst += stride;
5071         }
5072         gint w = ghb_settings_get_int(settings, "scale_width");
5073         gint h = ghb_settings_get_int(settings, "scale_height");
5074         ghb_par_scale(ud, &w, &h, par_width, par_height);
5075
5076         gint c0, c1, c2, c3;
5077         c0 = ghb_settings_get_int(settings, "PictureTopCrop");
5078         c1 = ghb_settings_get_int(settings, "PictureBottomCrop");
5079         c2 = ghb_settings_get_int(settings, "PictureLeftCrop");
5080         c3 = ghb_settings_get_int(settings, "PictureRightCrop");
5081
5082         gdouble xscale = (gdouble)w / (gdouble)(title->width - c2 - c3);
5083         gdouble yscale = (gdouble)h / (gdouble)(title->height - c0 - c1);
5084         
5085         ghb_par_scale(ud, &dstWidth, &dstHeight, par_width, par_height);
5086         *out_width = w;
5087         *out_height = h;
5088         if (ghb_settings_get_boolean(settings, "reduce_hd_preview"))
5089         {
5090                 GdkScreen *ss;
5091                 gint s_w, s_h;
5092                 gint orig_w, orig_h;
5093                 gint factor = 80;
5094
5095                 if (ghb_settings_get_boolean(settings, "preview_fullscreen"))
5096                 {
5097                         factor = 100;
5098                 }
5099                 ss = gdk_screen_get_default();
5100                 s_w = gdk_screen_get_width(ss);
5101                 s_h = gdk_screen_get_height(ss);
5102                 orig_w = dstWidth;
5103                 orig_h = dstHeight;
5104
5105                 if (dstWidth > s_w * factor / 100)
5106                 {
5107                         dstWidth = s_w * factor / 100;
5108                         dstHeight = dstHeight * dstWidth / orig_w;
5109                 }
5110                 if (dstHeight > s_h * factor / 100)
5111                 {
5112                         dstHeight = s_h * factor / 100;
5113                         dstWidth = dstWidth * dstHeight / orig_h;
5114                 }
5115                 xscale *= (gdouble)dstWidth / orig_w;
5116                 yscale *= (gdouble)dstHeight / orig_h;
5117                 w *= (gdouble)dstWidth / orig_w;
5118                 h *= (gdouble)dstHeight / orig_h;
5119         }
5120         GdkPixbuf *scaled_preview;
5121         scaled_preview = gdk_pixbuf_scale_simple(preview, dstWidth, dstHeight, GDK_INTERP_HYPER);
5122         if (ghb_settings_get_boolean(settings, "show_crop"))
5123         {
5124                 c0 *= yscale;
5125                 c1 *= yscale;
5126                 c2 *= xscale;
5127                 c3 *= xscale;
5128                 // Top
5129                 hash_pixbuf(scaled_preview, c2, 0, w, c0, 32, 0);
5130                 // Bottom
5131                 hash_pixbuf(scaled_preview, c2, dstHeight-c1, w, c1, 32, 0);
5132                 // Left
5133                 hash_pixbuf(scaled_preview, 0, c0, c2, h, 32, 1);
5134                 // Right
5135                 hash_pixbuf(scaled_preview, dstWidth-c3, c0, c3, h, 32, 1);
5136         }
5137         g_object_unref (preview);
5138         return scaled_preview;
5139 }
5140
5141 static void
5142 sanitize_volname(gchar *name)
5143 {
5144         gchar *a, *b;
5145
5146         a = b = name;
5147         while (*b)
5148         {
5149                 switch(*b)
5150                 {
5151                 case '<':
5152                         b++;
5153                         break;
5154                 case '>':
5155                         b++;
5156                         break;
5157                 default:
5158                         *a = *b;
5159                         a++; b++;
5160                         break;
5161                 }
5162         }
5163         *a = 0;
5164 }
5165
5166 gchar*
5167 ghb_dvd_volname(const gchar *device)
5168 {
5169         gchar *name;
5170         name = hb_dvd_name((gchar*)device);
5171         if (name != NULL && name[0] != 0)
5172         {
5173                 name = g_strdup(name);
5174                 sanitize_volname(name);
5175                 return name;
5176         }
5177         return NULL;
5178 }