1 /***************************************************************************
4 * Fri Mar 28 10:38:44 2008
5 * Copyright 2008-2011 John Stebbins
6 * <john at stebbins dot name>
7 ****************************************************************************/
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.
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.
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
29 #include <glib/gstdio.h>
30 #include "hb-backend.h"
32 #include "callbacks.h"
33 #include "subtitlehandler.h"
34 #include "audiohandler.h"
35 #include "x264handler.h"
43 const gchar *shortOpt;
54 static gchar **index_str = NULL;
55 static gint index_str_size = 0;
58 index_str_init(gint max_index)
62 if (max_index+1 > index_str_size)
64 index_str = realloc(index_str, (max_index+1) * sizeof(char*));
65 for (ii = index_str_size; ii <= max_index; ii++)
67 index_str[ii] = g_strdup_printf("%d", ii);
69 index_str_size = max_index + 1;
73 static options_map_t d_point_to_point_opts[] =
75 {"Chapters:", "chapter", 0, "0"},
76 {"Seconds:", "time", 1, "1"},
77 {"Frames:", "frame", 2, "2"},
79 combo_opts_t point_to_point_opts =
81 sizeof(d_point_to_point_opts)/sizeof(options_map_t),
85 static options_map_t d_when_complete_opts[] =
87 {"Do Nothing", "nothing", 0, "0"},
88 {"Show Notification", "notify", 1, "1"},
89 {"Quit Handbrake", "quit", 4, "4"},
90 {"Put Computer To Sleep", "sleep", 2, "2"},
91 {"Shutdown Computer", "shutdown", 3, "3"},
93 combo_opts_t when_complete_opts =
95 sizeof(d_when_complete_opts)/sizeof(options_map_t),
99 static options_map_t d_par_opts[] =
101 {"Off", "0", 0, "0"},
102 {"Strict", "1", 1, "1"},
103 {"Loose", "2", 2, "2"},
104 {"Custom", "3", 3, "3"},
106 combo_opts_t par_opts =
108 sizeof(d_par_opts)/sizeof(options_map_t),
112 static options_map_t d_alignment_opts[] =
117 {"16", "16", 16, "16"},
119 combo_opts_t alignment_opts =
121 sizeof(d_alignment_opts)/sizeof(options_map_t),
125 static options_map_t d_logging_opts[] =
131 combo_opts_t logging_opts =
133 sizeof(d_logging_opts)/sizeof(options_map_t),
137 static options_map_t d_log_longevity_opts[] =
139 {"Week", "week", 7, "7"},
140 {"Month", "month", 30, "30"},
141 {"Year", "year", 365, "365"},
142 {"Immortal", "immortal", 366, "366"},
144 combo_opts_t log_longevity_opts =
146 sizeof(d_log_longevity_opts)/sizeof(options_map_t),
150 static options_map_t d_appcast_update_opts[] =
152 {"Never", "never", 0, "never"},
153 {"Daily", "daily", 1, "daily"},
154 {"Weekly", "weekly", 2, "weekly"},
155 {"Monthly", "monthly", 3, "monthly"},
157 combo_opts_t appcast_update_opts =
159 sizeof(d_appcast_update_opts)/sizeof(options_map_t),
160 d_appcast_update_opts
163 static options_map_t d_vqual_granularity_opts[] =
165 {"0.2", "0.2", 0.2, "0.2"},
166 {"0.25", "0.25", 0.25, "0.25"},
167 {"0.5", "0.5", 0.5, "0.5"},
170 combo_opts_t vqual_granularity_opts =
172 sizeof(d_vqual_granularity_opts)/sizeof(options_map_t),
173 d_vqual_granularity_opts
176 static options_map_t d_container_opts[] =
178 {"MKV", "mkv", HB_MUX_MKV, "mkv"},
179 {"MP4", "mp4", HB_MUX_MP4, "mp4"},
181 combo_opts_t container_opts =
183 sizeof(d_container_opts)/sizeof(options_map_t),
187 static options_map_t d_detel_opts[] =
189 {"Off", "off", 0, ""},
190 {"Custom", "custom", 1, ""},
191 {"Default","default",2, NULL},
193 combo_opts_t detel_opts =
195 sizeof(d_detel_opts)/sizeof(options_map_t),
199 static options_map_t d_decomb_opts[] =
201 {"Off", "off", 0, ""},
202 {"Custom", "custom", 1, ""},
203 {"Default","default",2, NULL},
205 combo_opts_t decomb_opts =
207 sizeof(d_decomb_opts)/sizeof(options_map_t),
211 static options_map_t d_deint_opts[] =
213 {"Off", "off", 0, ""},
214 {"Custom", "custom", 1, ""},
215 {"Fast", "fast", 2, "-1:-1:-1:0:1"},
216 {"Slow", "slow", 3, "2:-1:-1:0:1"},
217 {"Slower", "slower", 4, "0:-1:-1:0:1"},
219 combo_opts_t deint_opts =
221 sizeof(d_deint_opts)/sizeof(options_map_t),
225 static options_map_t d_denoise_opts[] =
227 {"Off", "off", 0, ""},
228 {"Custom", "custom", 1, ""},
229 {"Weak", "weak", 2, "2:1:2:3"},
230 {"Medium", "medium", 3, "3:2:2:3"},
231 {"Strong", "strong", 4, "7:7:5:5"},
233 combo_opts_t denoise_opts =
235 sizeof(d_denoise_opts)/sizeof(options_map_t),
239 static options_map_t d_vcodec_opts[] =
241 {"H.264 (x264)", "x264", HB_VCODEC_X264, ""},
242 {"MPEG-4 (FFmpeg)", "ffmpeg", HB_VCODEC_FFMPEG, ""},
243 {"VP3 (Theora)", "theora", HB_VCODEC_THEORA, ""},
245 combo_opts_t vcodec_opts =
247 sizeof(d_vcodec_opts)/sizeof(options_map_t),
251 static options_map_t d_acodec_opts[] =
253 {"AAC (faac)", "faac", HB_ACODEC_FAAC, "faac"},
254 {"MP3 (lame)", "lame", HB_ACODEC_LAME, "lame"},
255 {"Vorbis", "vorbis", HB_ACODEC_VORBIS, "vorbis"},
256 {"AC3 (ffmpeg)", "ac3", HB_ACODEC_AC3, "ac3"},
257 {"AC3 (pass-thru)", "ac3pass", HB_ACODEC_AC3_PASS, "ac3pass"},
258 {"DTS (pass-thru)", "dtspass", HB_ACODEC_DCA_PASS, "dtspass"},
259 {"Choose For Me", "auto", HB_ACODEC_ANY, "auto"},
261 combo_opts_t acodec_opts =
263 sizeof(d_acodec_opts)/sizeof(options_map_t),
267 static options_map_t d_direct_opts[] =
269 {"None", "none", 0, "none"},
270 {"Spatial", "spatial", 1, "spatial"},
271 {"Temporal", "temporal", 2, "temporal"},
272 {"Automatic", "auto", 3, "auto"},
274 combo_opts_t direct_opts =
276 sizeof(d_direct_opts)/sizeof(options_map_t),
280 static options_map_t d_badapt_opts[] =
282 {"Off", "0", 0, "0"},
283 {"Fast", "1", 1, "1"},
284 {"Optimal", "2", 2, "2"},
286 combo_opts_t badapt_opts =
288 sizeof(d_badapt_opts)/sizeof(options_map_t),
292 static options_map_t d_bpyramid_opts[] =
294 {"Off", "none", 0, "none"},
295 {"Strict", "strict", 1, "strict"},
296 {"Normal", "normal", 2, "normal"},
298 combo_opts_t bpyramid_opts =
300 sizeof(d_bpyramid_opts)/sizeof(options_map_t),
304 static options_map_t d_weightp_opts[] =
306 {"Off", "0", 0, "0"},
307 {"Simple", "1", 1, "1"},
308 {"Smart", "2", 2, "2"},
310 combo_opts_t weightp_opts =
312 sizeof(d_weightp_opts)/sizeof(options_map_t),
316 static options_map_t d_me_opts[] =
318 {"Diamond", "dia", 0, "dia"},
319 {"Hexagon", "hex", 1, "hex"},
320 {"Uneven Multi-Hexagon", "umh", 2, "umh"},
321 {"Exhaustive", "esa", 3, "esa"},
322 {"Hadamard Exhaustive", "tesa", 4, "tesa"},
324 combo_opts_t me_opts =
326 sizeof(d_me_opts)/sizeof(options_map_t),
330 static options_map_t d_subme_opts[] =
332 {"0: SAD, no subpel", "0", 0, "0"},
333 {"1: SAD, qpel", "1", 1, "1"},
334 {"2: SATD, qpel", "2", 2, "2"},
335 {"3: SATD: multi-qpel", "3", 3, "3"},
336 {"4: SATD, qpel on all", "4", 4, "4"},
337 {"5: SATD, multi-qpel on all", "5", 5, "5"},
338 {"6: RD in I/P-frames", "6", 6, "6"},
339 {"7: RD in all frames", "7", 7, "7"},
340 {"8: RD refine in I/P-frames", "8", 8, "8"},
341 {"9: RD refine in all frames", "9", 9, "9"},
342 {"10: QPRD in all frames", "10", 10, "10"},
344 combo_opts_t subme_opts =
346 sizeof(d_subme_opts)/sizeof(options_map_t),
350 static options_map_t d_analyse_opts[] =
352 {"Most", "p8x8,b8x8,i8x8,i4x4", 0, "p8x8,b8x8,i8x8,i4x4"},
353 {"None", "none", 1, "none"},
354 {"Some", "i4x4,i8x8", 2, "i4x4,i8x8"},
355 {"All", "all", 3, "all"},
356 {"Custom", "custom", 4, "all"},
358 combo_opts_t analyse_opts =
360 sizeof(d_analyse_opts)/sizeof(options_map_t),
364 static options_map_t d_trellis_opts[] =
366 {"Off", "0", 0, "0"},
367 {"Encode only", "1", 1, "1"},
368 {"Always", "2", 2, "2"},
370 combo_opts_t trellis_opts =
372 sizeof(d_trellis_opts)/sizeof(options_map_t),
376 combo_opts_t subtitle_opts =
382 combo_opts_t title_opts =
388 combo_opts_t audio_track_opts =
400 combo_name_map_t combo_name_map[] =
402 {"PtoPType", &point_to_point_opts},
403 {"WhenComplete", &when_complete_opts},
404 {"PicturePAR", &par_opts},
405 {"PictureModulus", &alignment_opts},
406 {"LoggingLevel", &logging_opts},
407 {"LogLongevity", &log_longevity_opts},
408 {"check_updates", &appcast_update_opts},
409 {"VideoQualityGranularity", &vqual_granularity_opts},
410 {"FileFormat", &container_opts},
411 {"PictureDeinterlace", &deint_opts},
412 {"PictureDecomb", &decomb_opts},
413 {"PictureDetelecine", &detel_opts},
414 {"PictureDenoise", &denoise_opts},
415 {"VideoEncoder", &vcodec_opts},
416 {"AudioEncoder", &acodec_opts},
417 {"AudioEncoderActual", &acodec_opts},
418 {"x264_direct", &direct_opts},
419 {"x264_b_adapt", &badapt_opts},
420 {"x264_bpyramid", &bpyramid_opts},
421 {"x264_weighted_pframes", &weightp_opts},
422 {"x264_me", &me_opts},
423 {"x264_subme", &subme_opts},
424 {"x264_analyse", &analyse_opts},
425 {"x264_trellis", &trellis_opts},
426 {"SubtitleTrack", &subtitle_opts},
427 {"title", &title_opts},
428 {"AudioTrack", &audio_track_opts},
432 const gchar *srt_codeset_table[] =
471 #define SRT_TABLE_SIZE (sizeof(srt_codeset_table)/ sizeof(char*)-1)
474 typedef struct iso639_lang_t
476 char * eng_name; /* Description in English */
477 char * native_name; /* Description in native language */
478 char * iso639_1; /* ISO-639-1 (2 characters) code */
479 char * iso639_2; /* ISO-639-2/t (3 character) code */
480 char * iso639_2b; /* ISO-639-2/b code (if different from above) */
484 const iso639_lang_t ghb_language_table[] =
486 { "Any", "", "zz", "und" },
487 { "Afar", "", "aa", "aar" },
488 { "Abkhazian", "", "ab", "abk" },
489 { "Afrikaans", "", "af", "afr" },
490 { "Akan", "", "ak", "aka" },
491 { "Albanian", "", "sq", "sqi", "alb" },
492 { "Amharic", "", "am", "amh" },
493 { "Arabic", "", "ar", "ara" },
494 { "Aragonese", "", "an", "arg" },
495 { "Armenian", "", "hy", "hye", "arm" },
496 { "Assamese", "", "as", "asm" },
497 { "Avaric", "", "av", "ava" },
498 { "Avestan", "", "ae", "ave" },
499 { "Aymara", "", "ay", "aym" },
500 { "Azerbaijani", "", "az", "aze" },
501 { "Bashkir", "", "ba", "bak" },
502 { "Bambara", "", "bm", "bam" },
503 { "Basque", "", "eu", "eus", "baq" },
504 { "Belarusian", "", "be", "bel" },
505 { "Bengali", "", "bn", "ben" },
506 { "Bihari", "", "bh", "bih" },
507 { "Bislama", "", "bi", "bis" },
508 { "Bosnian", "", "bs", "bos" },
509 { "Breton", "", "br", "bre" },
510 { "Bulgarian", "", "bg", "bul" },
511 { "Burmese", "", "my", "mya", "bur" },
512 { "Catalan", "", "ca", "cat" },
513 { "Chamorro", "", "ch", "cha" },
514 { "Chechen", "", "ce", "che" },
515 { "Chinese", "", "zh", "zho", "chi" },
516 { "Church Slavic", "", "cu", "chu" },
517 { "Chuvash", "", "cv", "chv" },
518 { "Cornish", "", "kw", "cor" },
519 { "Corsican", "", "co", "cos" },
520 { "Cree", "", "cr", "cre" },
521 { "Czech", "", "cs", "ces", "cze" },
522 { "Danish", "Dansk", "da", "dan" },
523 { "German", "Deutsch", "de", "deu", "ger" },
524 { "Divehi", "", "dv", "div" },
525 { "Dzongkha", "", "dz", "dzo" },
526 { "English", "English", "en", "eng" },
527 { "Spanish", "Espanol", "es", "spa" },
528 { "Esperanto", "", "eo", "epo" },
529 { "Estonian", "", "et", "est" },
530 { "Ewe", "", "ee", "ewe" },
531 { "Faroese", "", "fo", "fao" },
532 { "Fijian", "", "fj", "fij" },
533 { "French", "Francais", "fr", "fra", "fre" },
534 { "Western Frisian", "", "fy", "fry" },
535 { "Fulah", "", "ff", "ful" },
536 { "Georgian", "", "ka", "kat", "geo" },
537 { "Gaelic (Scots)", "", "gd", "gla" },
538 { "Irish", "", "ga", "gle" },
539 { "Galician", "", "gl", "glg" },
540 { "Manx", "", "gv", "glv" },
541 { "Greek, Modern", "", "el", "ell", "gre" },
542 { "Guarani", "", "gn", "grn" },
543 { "Gujarati", "", "gu", "guj" },
544 { "Haitian", "", "ht", "hat" },
545 { "Hausa", "", "ha", "hau" },
546 { "Hebrew", "", "he", "heb" },
547 { "Herero", "", "hz", "her" },
548 { "Hindi", "", "hi", "hin" },
549 { "Hiri Motu", "", "ho", "hmo" },
550 { "Croatian", "Hrvatski", "hr", "hrv", "scr" },
551 { "Igbo", "", "ig", "ibo" },
552 { "Ido", "", "io", "ido" },
553 { "Icelandic", "Islenska", "is", "isl", "ice" },
554 { "Sichuan Yi", "", "ii", "iii" },
555 { "Inuktitut", "", "iu", "iku" },
556 { "Interlingue", "", "ie", "ile" },
557 { "Interlingua", "", "ia", "ina" },
558 { "Indonesian", "", "id", "ind" },
559 { "Inupiaq", "", "ik", "ipk" },
560 { "Italian", "Italiano", "it", "ita" },
561 { "Javanese", "", "jv", "jav" },
562 { "Japanese", "", "ja", "jpn" },
563 { "Kalaallisut", "", "kl", "kal" },
564 { "Kannada", "", "kn", "kan" },
565 { "Kashmiri", "", "ks", "kas" },
566 { "Kanuri", "", "kr", "kau" },
567 { "Kazakh", "", "kk", "kaz" },
568 { "Central Khmer", "", "km", "khm" },
569 { "Kikuyu", "", "ki", "kik" },
570 { "Kinyarwanda", "", "rw", "kin" },
571 { "Kirghiz", "", "ky", "kir" },
572 { "Komi", "", "kv", "kom" },
573 { "Kongo", "", "kg", "kon" },
574 { "Korean", "", "ko", "kor" },
575 { "Kuanyama", "", "kj", "kua" },
576 { "Kurdish", "", "ku", "kur" },
577 { "Lao", "", "lo", "lao" },
578 { "Latin", "", "la", "lat" },
579 { "Latvian", "", "lv", "lav" },
580 { "Limburgan", "", "li", "lim" },
581 { "Lingala", "", "ln", "lin" },
582 { "Lithuanian", "", "lt", "lit" },
583 { "Luxembourgish", "", "lb", "ltz" },
584 { "Luba-Katanga", "", "lu", "lub" },
585 { "Ganda", "", "lg", "lug" },
586 { "Macedonian", "", "mk", "mkd", "mac" },
587 { "Hungarian", "Magyar", "hu", "hun" },
588 { "Marshallese", "", "mh", "mah" },
589 { "Malayalam", "", "ml", "mal" },
590 { "Maori", "", "mi", "mri", "mao" },
591 { "Marathi", "", "mr", "mar" },
592 { "Malay", "", "ms", "msa", "msa" },
593 { "Malagasy", "", "mg", "mlg" },
594 { "Maltese", "", "mt", "mlt" },
595 { "Moldavian", "", "mo", "mol" },
596 { "Mongolian", "", "mn", "mon" },
597 { "Nauru", "", "na", "nau" },
598 { "Navajo", "", "nv", "nav" },
599 { "Dutch", "Nederlands", "nl", "nld", "dut" },
600 { "Ndebele, South", "", "nr", "nbl" },
601 { "Ndebele, North", "", "nd", "nde" },
602 { "Ndonga", "", "ng", "ndo" },
603 { "Nepali", "", "ne", "nep" },
604 { "Norwegian", "Norsk", "no", "nor" },
605 { "Norwegian Nynorsk", "", "nn", "nno" },
606 { "Norwegian Bokmål", "", "nb", "nob" },
607 { "Chichewa; Nyanja", "", "ny", "nya" },
608 { "Occitan", "", "oc", "oci" },
609 { "Ojibwa", "", "oj", "oji" },
610 { "Oriya", "", "or", "ori" },
611 { "Oromo", "", "om", "orm" },
612 { "Ossetian", "", "os", "oss" },
613 { "Panjabi", "", "pa", "pan" },
614 { "Persian", "", "fa", "fas", "per" },
615 { "Pali", "", "pi", "pli" },
616 { "Polish", "", "pl", "pol" },
617 { "Portuguese", "Portugues", "pt", "por" },
618 { "Pushto", "", "ps", "pus" },
619 { "Quechua", "", "qu", "que" },
620 { "Romansh", "", "rm", "roh" },
621 { "Romanian", "", "ro", "ron", "rum" },
622 { "Rundi", "", "rn", "run" },
623 { "Russian", "", "ru", "rus" },
624 { "Sango", "", "sg", "sag" },
625 { "Sanskrit", "", "sa", "san" },
626 { "Serbian", "", "sr", "srp", "scc" },
627 { "Sinhala", "", "si", "sin" },
628 { "Slovak", "", "sk", "slk", "slo" },
629 { "Slovenian", "", "sl", "slv" },
630 { "Northern Sami", "", "se", "sme" },
631 { "Samoan", "", "sm", "smo" },
632 { "Shona", "", "sn", "sna" },
633 { "Sindhi", "", "sd", "snd" },
634 { "Somali", "", "so", "som" },
635 { "Sotho, Southern", "", "st", "sot" },
636 { "Sardinian", "", "sc", "srd" },
637 { "Swati", "", "ss", "ssw" },
638 { "Sundanese", "", "su", "sun" },
639 { "Finnish", "Suomi", "fi", "fin" },
640 { "Swahili", "", "sw", "swa" },
641 { "Swedish", "Svenska", "sv", "swe" },
642 { "Tahitian", "", "ty", "tah" },
643 { "Tamil", "", "ta", "tam" },
644 { "Tatar", "", "tt", "tat" },
645 { "Telugu", "", "te", "tel" },
646 { "Tajik", "", "tg", "tgk" },
647 { "Tagalog", "", "tl", "tgl" },
648 { "Thai", "", "th", "tha" },
649 { "Tibetan", "", "bo", "bod", "tib" },
650 { "Tigrinya", "", "ti", "tir" },
651 { "Tonga", "", "to", "ton" },
652 { "Tswana", "", "tn", "tsn" },
653 { "Tsonga", "", "ts", "tso" },
654 { "Turkmen", "", "tk", "tuk" },
655 { "Turkish", "", "tr", "tur" },
656 { "Twi", "", "tw", "twi" },
657 { "Uighur", "", "ug", "uig" },
658 { "Ukrainian", "", "uk", "ukr" },
659 { "Urdu", "", "ur", "urd" },
660 { "Uzbek", "", "uz", "uzb" },
661 { "Venda", "", "ve", "ven" },
662 { "Vietnamese", "", "vi", "vie" },
663 { "Volapük", "", "vo", "vol" },
664 { "Welsh", "", "cy", "cym", "wel" },
665 { "Walloon", "", "wa", "wln" },
666 { "Wolof", "", "wo", "wol" },
667 { "Xhosa", "", "xh", "xho" },
668 { "Yiddish", "", "yi", "yid" },
669 { "Yoruba", "", "yo", "yor" },
670 { "Zhuang", "", "za", "zha" },
671 { "Zulu", "", "zu", "zul" },
672 {NULL, NULL, NULL, NULL}
674 #define LANG_TABLE_SIZE (sizeof(ghb_language_table)/ sizeof(iso639_lang_t)-1)
676 static void audio_bitrate_opts_set(GtkBuilder *builder, const gchar *name);
679 del_tree(const gchar *name, gboolean del_top)
683 if (g_file_test(name, G_FILE_TEST_IS_DIR))
685 GDir *gdir = g_dir_open(name, 0, NULL);
686 file = g_dir_read_name(gdir);
690 path = g_strdup_printf("%s/%s", name, file);
691 del_tree(path, TRUE);
693 file = g_dir_read_name(gdir);
708 return hb_get_version(NULL);
713 signal_user_data_t *ud,
721 gint vcodec = ghb_settings_combo_int(ud->settings, "VideoEncoder");
730 *step = ghb_settings_combo_double(ud->settings,
731 "VideoQualityGranularity");
732 if (*step == 0.2 || *step == 0.5)
734 else if (*step == 0.25)
739 case HB_VCODEC_FFMPEG:
747 case HB_VCODEC_THEORA:
766 find_combo_entry(combo_opts_t *opts, const GValue *gval)
770 if (G_VALUE_TYPE(gval) == G_TYPE_STRING)
773 str = ghb_value_string(gval);
774 for (ii = 0; ii < opts->count; ii++)
776 if (strcmp(opts->map[ii].shortOpt, str) == 0)
784 else if (G_VALUE_TYPE(gval) == G_TYPE_DOUBLE)
787 val = ghb_value_double(gval);
788 for (ii = 0; ii < opts->count; ii++)
790 if (opts->map[ii].ivalue == val)
797 else if (G_VALUE_TYPE(gval) == G_TYPE_INT ||
798 G_VALUE_TYPE(gval) == G_TYPE_BOOLEAN ||
799 G_VALUE_TYPE(gval) == G_TYPE_INT64)
802 val = ghb_value_int64(gval);
803 for (ii = 0; ii < opts->count; ii++)
805 if ((gint64)opts->map[ii].ivalue == val)
816 lookup_generic_string(combo_opts_t *opts, const GValue *gval)
819 const gchar *result = "";
821 ii = find_combo_entry(opts, gval);
822 if (ii < opts->count)
824 result = opts->map[ii].svalue;
830 lookup_generic_int(combo_opts_t *opts, const GValue *gval)
835 ii = find_combo_entry(opts, gval);
836 if (ii < opts->count)
838 result = opts->map[ii].ivalue;
844 lookup_generic_double(combo_opts_t *opts, const GValue *gval)
849 ii = find_combo_entry(opts, gval);
850 if (ii < opts->count)
852 result = opts->map[ii].ivalue;
858 lookup_generic_option(combo_opts_t *opts, const GValue *gval)
861 const gchar *result = "";
863 ii = find_combo_entry(opts, gval);
864 if (ii < opts->count)
866 result = opts->map[ii].option;
872 lookup_mix_int(const GValue *mix)
878 if (G_VALUE_TYPE(mix) == G_TYPE_STRING)
880 gchar * str = ghb_value_string(mix);
881 for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
883 if (strcmp(hb_audio_mixdowns[ii].short_name, str) == 0)
885 result = hb_audio_mixdowns[ii].amixdown;
891 else if (G_VALUE_TYPE(mix) == G_TYPE_INT ||
892 G_VALUE_TYPE(mix) == G_TYPE_INT64 ||
893 G_VALUE_TYPE(mix) == G_TYPE_DOUBLE)
895 gint val = ghb_value_int(mix);
896 for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
898 if (hb_audio_mixdowns[ii].amixdown == val)
900 result = hb_audio_mixdowns[ii].amixdown;
909 lookup_mix_option(const GValue *mix)
912 gchar *result = "None";
915 if (G_VALUE_TYPE(mix) == G_TYPE_STRING)
917 gchar *str = ghb_value_string(mix);
918 for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
920 if (strcmp(hb_audio_mixdowns[ii].short_name, str) == 0)
922 result = hb_audio_mixdowns[ii].human_readable_name;
928 else if (G_VALUE_TYPE(mix) == G_TYPE_INT ||
929 G_VALUE_TYPE(mix) == G_TYPE_INT64 ||
930 G_VALUE_TYPE(mix) == G_TYPE_DOUBLE)
932 gint val = ghb_value_int(mix);
933 for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
935 if (hb_audio_mixdowns[ii].amixdown == val)
937 result = hb_audio_mixdowns[ii].human_readable_name;
946 lookup_mix_string(const GValue *mix)
949 gchar *result = "None";
952 if (G_VALUE_TYPE(mix) == G_TYPE_STRING)
954 gchar *str = ghb_value_string(mix);
955 for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
957 if (strcmp(hb_audio_mixdowns[ii].short_name, str) == 0)
959 result = hb_audio_mixdowns[ii].short_name;
965 else if (G_VALUE_TYPE(mix) == G_TYPE_INT ||
966 G_VALUE_TYPE(mix) == G_TYPE_INT64 ||
967 G_VALUE_TYPE(mix) == G_TYPE_DOUBLE)
969 gint val = ghb_value_int(mix);
970 for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
972 if (hb_audio_mixdowns[ii].amixdown == val)
974 result = hb_audio_mixdowns[ii].short_name;
983 lookup_video_rate_int(const GValue *vrate)
989 str = ghb_value_string(vrate);
990 for (ii = 0; ii < hb_video_rates_count; ii++)
992 if (strcmp(hb_video_rates[ii].string, str) == 0)
994 result = hb_video_rates[ii].rate;
999 // Default to "same as source"
1004 lookup_video_rate_option(const GValue *vrate)
1008 const gchar *result = "Same as source";
1010 str = ghb_value_string(vrate);
1011 for (ii = 0; ii < hb_video_rates_count; ii++)
1013 if (strcmp(hb_video_rates[ii].string, str) == 0)
1015 result = hb_video_rates[ii].string;
1020 // Default to "same as source"
1025 lookup_audio_rate_int(const GValue *rate)
1030 if (G_VALUE_TYPE(rate) == G_TYPE_STRING)
1032 // Coincidentally, the string "source" will return 0
1033 // which is our flag to use "same as source"
1034 gchar * str = ghb_value_string(rate);
1035 for (ii = 0; ii < hb_audio_rates_count; ii++)
1037 if (strcmp(hb_audio_rates[ii].string, str) == 0)
1039 result = hb_audio_rates[ii].rate;
1045 else if (G_VALUE_TYPE(rate) == G_TYPE_INT ||
1046 G_VALUE_TYPE(rate) == G_TYPE_INT64 ||
1047 G_VALUE_TYPE(rate) == G_TYPE_DOUBLE)
1049 for (ii = 0; ii < hb_audio_rates_count; ii++)
1051 gint val = ghb_value_int(rate);
1052 if (val == hb_audio_rates[ii].rate)
1054 result = hb_audio_rates[ii].rate;
1063 lookup_audio_rate_option(const GValue *rate)
1066 const gchar *result = "Same as source";
1068 if (G_VALUE_TYPE(rate) == G_TYPE_STRING)
1070 // Coincidentally, the string "source" will return 0
1071 // which is our flag to use "same as source"
1072 gchar *str = ghb_value_string(rate);
1073 for (ii = 0; ii < hb_audio_rates_count; ii++)
1075 if (strcmp(hb_audio_rates[ii].string, str) == 0)
1077 result = hb_audio_rates[ii].string;
1083 else if (G_VALUE_TYPE(rate) == G_TYPE_INT ||
1084 G_VALUE_TYPE(rate) == G_TYPE_INT64 ||
1085 G_VALUE_TYPE(rate) == G_TYPE_DOUBLE)
1087 for (ii = 0; ii < hb_audio_rates_count; ii++)
1089 gint val = ghb_value_int(rate);
1090 if (val == hb_audio_rates[ii].rate)
1092 result = hb_audio_rates[ii].string;
1101 ghb_find_closest_audio_rate(gint rate)
1107 for (ii = 0; ii < hb_audio_rates_count; ii++)
1109 if (rate <= hb_audio_rates[ii].rate)
1111 result = hb_audio_rates[ii].rate;
1118 hb_rate_t *ghb_audio_bitrates;
1119 int ghb_audio_bitrates_count;
1122 lookup_audio_bitrate_int(const GValue *rate)
1127 if (G_VALUE_TYPE(rate) == G_TYPE_STRING)
1129 // Coincidentally, the string "source" will return 0
1130 // which is our flag to use "same as source"
1131 gchar *str = ghb_value_string(rate);
1132 for (ii = 0; ii < ghb_audio_bitrates_count; ii++)
1134 if (strcmp(ghb_audio_bitrates[ii].string, str) == 0)
1136 result = ghb_audio_bitrates[ii].rate;
1142 else if (G_VALUE_TYPE(rate) == G_TYPE_INT ||
1143 G_VALUE_TYPE(rate) == G_TYPE_INT64 ||
1144 G_VALUE_TYPE(rate) == G_TYPE_DOUBLE)
1146 gint val = ghb_value_int(rate);
1147 for (ii = 0; ii < ghb_audio_bitrates_count; ii++)
1149 if (ghb_audio_bitrates[ii].rate == val)
1151 result = ghb_audio_bitrates[ii].rate;
1160 lookup_audio_bitrate_option(const GValue *rate)
1163 const gchar *result = "Same as source";
1165 if (G_VALUE_TYPE(rate) == G_TYPE_STRING)
1167 // Coincidentally, the string "source" will return 0
1168 // which is our flag to use "same as source"
1169 gchar *str = ghb_value_string(rate);
1170 for (ii = 0; ii < ghb_audio_bitrates_count; ii++)
1172 if (strcmp(ghb_audio_bitrates[ii].string, str) == 0)
1174 result = ghb_audio_bitrates[ii].string;
1180 else if (G_VALUE_TYPE(rate) == G_TYPE_INT ||
1181 G_VALUE_TYPE(rate) == G_TYPE_INT64 ||
1182 G_VALUE_TYPE(rate) == G_TYPE_DOUBLE)
1184 gint val = ghb_value_int(rate);
1185 for (ii = 0; ii < ghb_audio_bitrates_count; ii++)
1187 if (ghb_audio_bitrates[ii].rate == val)
1189 result = ghb_audio_bitrates[ii].string;
1198 lookup_audio_lang_int(const GValue *rate)
1204 // Coincidentally, the string "source" will return 0
1205 // which is our flag to use "same as source"
1206 str = ghb_value_string(rate);
1207 for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
1209 if (strcmp(ghb_language_table[ii].iso639_2, str) == 0)
1220 lookup_audio_lang_option(const GValue *rate)
1224 const gchar *result = "Same as source";
1226 // Coincidentally, the string "source" will return 0
1227 // which is our flag to use "same as source"
1228 str = ghb_value_string(rate);
1229 for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
1231 if (strcmp(ghb_language_table[ii].iso639_2, str) == 0)
1233 if (ghb_language_table[ii].native_name[0] != 0)
1234 result = ghb_language_table[ii].native_name;
1236 result = ghb_language_table[ii].eng_name;
1245 ghb_lookup_acodec_value(gint val)
1247 GValue *value = NULL;
1250 for (ii = 0; ii < acodec_opts.count; ii++)
1252 if ((int)acodec_opts.map[ii].ivalue == val)
1254 value = ghb_string_value_new(acodec_opts.map[ii].shortOpt);
1258 value = ghb_string_value_new("auto");
1263 get_amix_value(gint val)
1265 GValue *value = NULL;
1268 for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
1270 if (hb_audio_mixdowns[ii].amixdown == val)
1272 value = ghb_string_value_new(hb_audio_mixdowns[ii].short_name);
1279 // Handle for libhb. Gets set by ghb_backend_init()
1280 static hb_handle_t * h_scan = NULL;
1281 static hb_handle_t * h_queue = NULL;
1283 extern void hb_get_temporary_directory(char path[512]);
1290 hb_get_temporary_directory(dir);
1291 return g_strdup(dir);
1295 ghb_hb_cleanup(gboolean partial)
1299 hb_get_temporary_directory(dir);
1300 del_tree(dir, !partial);
1304 ghb_subtitle_track_source(signal_user_data_t *ud, gint track)
1312 titleindex = ghb_settings_combo_int(ud->settings, "title");
1318 hb_subtitle_t * sub;
1320 if (h_scan == NULL) return VOBSUB;
1321 list = hb_get_titles( h_scan );
1322 if( !hb_list_count( list ) )
1324 /* No valid title, stop right there */
1327 title = hb_list_item( list, titleindex );
1328 if (title == NULL) return VOBSUB; // Bad titleindex
1329 sub = hb_list_item( title->list_subtitle, track);
1337 ghb_subtitle_source_name(gint source)
1339 const gchar * name = "Unknown";
1368 ghb_subtitle_track_source_name(signal_user_data_t *ud, gint track)
1371 const gchar * name = "Unknown";
1384 titleindex = ghb_settings_combo_int(ud->settings, "title");
1390 hb_subtitle_t * sub;
1394 list = hb_get_titles( h_scan );
1395 if( !hb_list_count( list ) )
1398 title = hb_list_item( list, titleindex );
1402 sub = hb_list_item( title->list_subtitle, track);
1405 name = ghb_subtitle_source_name(sub->source);
1413 ghb_subtitle_track_lang(signal_user_data_t *ud, gint track)
1417 titleindex = ghb_settings_combo_int(ud->settings, "title");
1421 return ghb_get_user_audio_lang(ud, titleindex, 0);
1427 hb_subtitle_t * sub;
1432 list = hb_get_titles( h_scan );
1433 if( !hb_list_count( list ) )
1435 /* No valid title, stop right there */
1438 title = hb_list_item( list, titleindex );
1439 if (title == NULL) // Bad titleindex
1441 sub = hb_list_item( title->list_subtitle, track);
1443 return g_strdup(sub->iso639_2);
1446 return g_strdup("und");
1450 ghb_get_title_number(gint titleindex)
1455 if (h_scan == NULL) return 1;
1456 list = hb_get_titles( h_scan );
1457 if( !hb_list_count( list ) )
1459 /* No valid title, stop right there */
1462 title = hb_list_item( list, titleindex );
1463 if (title == NULL) return 1; // Bad titleindex
1464 return title->index;
1467 static hb_audio_config_t*
1468 get_hb_audio(hb_handle_t *h, gint titleindex, gint track)
1472 hb_audio_config_t *audio = NULL;
1474 if (h == NULL) return NULL;
1475 list = hb_get_titles( h );
1476 if( !hb_list_count( list ) )
1478 /* No valid title, stop right there */
1481 title = hb_list_item( list, titleindex );
1482 if (title == NULL) return NULL; // Bad titleindex
1483 if (!hb_list_count(title->list_audio))
1487 audio = (hb_audio_config_t *)hb_list_audio_config_item(title->list_audio, track);
1492 search_rates(hb_rate_t *rates, gint rate, gint count)
1495 for (ii = 0; ii < count; ii++)
1497 if (rates[ii].rate == rate)
1503 static gboolean find_combo_item_by_int(GtkTreeModel *store, gint value, GtkTreeIter *iter);
1505 static GtkListStore*
1506 get_combo_box_store(GtkBuilder *builder, const gchar *name)
1509 GtkListStore *store;
1511 g_debug("get_combo_box_store() %s\n", name);
1512 // First modify the combobox model to allow greying out of options
1513 combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name));
1514 store = GTK_LIST_STORE(gtk_combo_box_get_model (combo));
1519 grey_combo_box_item(GtkBuilder *builder, const gchar *name, gint value, gboolean grey)
1521 GtkListStore *store;
1524 store = get_combo_box_store(builder, name);
1525 if (find_combo_item_by_int(GTK_TREE_MODEL(store), value, &iter))
1527 gtk_list_store_set(store, &iter,
1534 ghb_grey_combo_options(GtkBuilder *builder)
1537 gint container, track, titleindex, acodec;
1538 hb_audio_config_t *aconfig = NULL;
1541 widget = GHB_WIDGET (builder, "title");
1542 gval = ghb_widget_value(widget);
1543 titleindex = ghb_lookup_combo_int("title", gval);
1544 ghb_value_free(gval);
1545 widget = GHB_WIDGET (builder, "AudioTrack");
1546 gval = ghb_widget_value(widget);
1547 track = ghb_lookup_combo_int("AudioTrack", gval);
1548 ghb_value_free(gval);
1549 aconfig = get_hb_audio(h_scan, titleindex, track);
1550 widget = GHB_WIDGET (builder, "FileFormat");
1551 gval = ghb_widget_value(widget);
1552 container = ghb_lookup_combo_int("FileFormat", gval);
1553 ghb_value_free(gval);
1555 grey_combo_box_item(builder, "x264_analyse", 4, TRUE);
1556 grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_FAAC, FALSE);
1557 grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_LAME, FALSE);
1558 grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_VORBIS, FALSE);
1560 gboolean allow_dca = TRUE;
1561 allow_dca = (container != HB_MUX_MP4);
1563 grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_AC3_PASS, FALSE);
1565 grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_DCA_PASS, FALSE);
1567 grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_DCA_PASS, TRUE);
1569 if (aconfig && aconfig->in.codec != HB_ACODEC_AC3)
1571 grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_AC3_PASS, TRUE);
1573 if (aconfig && aconfig->in.codec != HB_ACODEC_DCA)
1575 grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_DCA_PASS, TRUE);
1577 grey_combo_box_item(builder, "VideoEncoder", HB_VCODEC_THEORA, FALSE);
1579 widget = GHB_WIDGET (builder, "AudioEncoder");
1580 gval = ghb_widget_value(widget);
1581 acodec = ghb_lookup_combo_int("AudioEncoder", gval);
1582 ghb_value_free(gval);
1583 grey_combo_box_item(builder, "AudioMixdown", 0, TRUE);
1584 if (container == HB_MUX_MP4)
1586 grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_VORBIS, TRUE);
1587 grey_combo_box_item(builder, "VideoEncoder", HB_VCODEC_THEORA, TRUE);
1590 gboolean allow_mono = TRUE;
1591 gboolean allow_stereo = TRUE;
1592 gboolean allow_dolby = TRUE;
1593 gboolean allow_dpl2 = TRUE;
1594 gboolean allow_6ch = TRUE;
1596 allow_6ch = acodec & ~HB_ACODEC_LAME;
1599 gint best = hb_get_best_mixdown(acodec, aconfig->in.channel_layout, 0);
1601 allow_stereo = best >= HB_AMIXDOWN_STEREO;
1602 allow_dolby = best >= HB_AMIXDOWN_DOLBY;
1603 allow_dpl2 = best >= HB_AMIXDOWN_DOLBYPLII;
1604 allow_6ch = best >= HB_AMIXDOWN_6CH;
1606 grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_MONO, !allow_mono);
1607 grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_STEREO, !allow_stereo);
1608 grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_DOLBY, !allow_dolby);
1609 grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_DOLBYPLII, !allow_dpl2);
1610 grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_6CH, !allow_6ch);
1614 ghb_get_best_mix(hb_audio_config_t *aconfig, gint acodec, gint mix)
1617 layout = aconfig ? aconfig->in.channel_layout :
1618 HB_INPUT_CH_LAYOUT_3F2R | HB_INPUT_CH_LAYOUT_HAS_LFE;
1619 return hb_get_best_mixdown( acodec, layout, mix );
1622 // Set up the model for the combo box
1624 init_combo_box(GtkBuilder *builder, const gchar *name)
1627 GtkListStore *store;
1628 GtkCellRenderer *cell;
1630 g_debug("init_combo_box() %s\n", name);
1631 // First modify the combobox model to allow greying out of options
1632 combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name));
1636 // 1 - String to display
1637 // 2 - bool indicating whether the entry is selectable (grey or not)
1638 // 3 - String that is used for presets
1639 // 4 - Int value determined by backend
1640 // 5 - String value determined by backend
1641 store = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_BOOLEAN,
1642 G_TYPE_STRING, G_TYPE_DOUBLE, G_TYPE_STRING);
1643 gtk_combo_box_set_model(combo, GTK_TREE_MODEL(store));
1645 if (GTK_WIDGET_TYPE(combo) == GTK_TYPE_COMBO_BOX)
1647 gtk_cell_layout_clear(GTK_CELL_LAYOUT(combo));
1648 cell = GTK_CELL_RENDERER(gtk_cell_renderer_text_new());
1649 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), cell, TRUE);
1650 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), cell,
1651 "markup", 0, "sensitive", 1, NULL);
1654 { // Combo box entry
1655 gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(combo), 0);
1660 audio_samplerate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gint count)
1663 GtkListStore *store;
1667 g_debug("audio_samplerate_opts_set ()\n");
1668 store = get_combo_box_store(builder, name);
1669 gtk_list_store_clear(store);
1670 // Add an item for "Same As Source"
1671 gtk_list_store_append(store, &iter);
1672 gtk_list_store_set(store, &iter,
1673 0, "<small>Same as source</small>",
1679 for (ii = 0; ii < count; ii++)
1681 gtk_list_store_append(store, &iter);
1682 str = g_strdup_printf("<small>%s</small>", rates[ii].string);
1683 gtk_list_store_set(store, &iter,
1686 2, rates[ii].string,
1687 3, (gdouble)rates[ii].rate,
1688 4, rates[ii].string,
1695 video_rate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gint count)
1698 GtkListStore *store;
1701 g_debug("video_rate_opts_set ()\n");
1702 store = get_combo_box_store(builder, name);
1703 gtk_list_store_clear(store);
1704 // Add an item for "Same As Source"
1705 gtk_list_store_append(store, &iter);
1706 gtk_list_store_set(store, &iter,
1707 0, "Same as source",
1713 for (ii = 0; ii < count; ii++)
1717 if (strcmp(rates[ii].string, "23.976") == 0)
1719 desc = "(NTSC Film)";
1721 else if (strcmp(rates[ii].string, "25") == 0)
1723 desc = "(PAL Film/Video)";
1725 else if (strcmp(rates[ii].string, "29.97") == 0)
1727 desc = "(NTSC Video)";
1729 option = g_strdup_printf ("%s %s", rates[ii].string, desc);
1730 gtk_list_store_append(store, &iter);
1731 gtk_list_store_set(store, &iter,
1734 2, rates[ii].string,
1735 3, (gdouble)rates[ii].rate,
1736 4, rates[ii].string,
1743 mix_opts_set(GtkBuilder *builder, const gchar *name)
1746 GtkListStore *store;
1750 g_debug("mix_opts_set ()\n");
1751 store = get_combo_box_store(builder, name);
1752 gtk_list_store_clear(store);
1753 gtk_list_store_append(store, &iter);
1754 gtk_list_store_set(store, &iter,
1755 0, "<small>None</small>",
1761 for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
1763 gtk_list_store_append(store, &iter);
1764 str = g_strdup_printf("<small>%s</small>",
1765 hb_audio_mixdowns[ii].human_readable_name);
1766 gtk_list_store_set(store, &iter,
1769 2, hb_audio_mixdowns[ii].short_name,
1770 3, (gdouble)hb_audio_mixdowns[ii].amixdown,
1771 4, hb_audio_mixdowns[ii].internal_name,
1778 srt_codeset_opts_set(GtkBuilder *builder, const gchar *name)
1781 GtkListStore *store;
1784 g_debug("srt_codeset_opts_set ()\n");
1785 store = get_combo_box_store(builder, name);
1786 gtk_list_store_clear(store);
1787 for (ii = 0; ii < SRT_TABLE_SIZE; ii++)
1789 gtk_list_store_append(store, &iter);
1790 gtk_list_store_set(store, &iter,
1791 0, srt_codeset_table[ii],
1793 2, srt_codeset_table[ii],
1795 4, srt_codeset_table[ii],
1798 GtkComboBoxEntry *cbe;
1800 cbe = GTK_COMBO_BOX_ENTRY(GHB_WIDGET(builder, name));
1801 //gtk_combo_box_entry_set_text_column(cbe, 0);
1805 language_opts_set(GtkBuilder *builder, const gchar *name)
1808 GtkListStore *store;
1811 g_debug("language_opts_set ()\n");
1812 store = get_combo_box_store(builder, name);
1813 gtk_list_store_clear(store);
1814 for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
1818 if (ghb_language_table[ii].native_name[0] != 0)
1819 lang = ghb_language_table[ii].native_name;
1821 lang = ghb_language_table[ii].eng_name;
1823 gtk_list_store_append(store, &iter);
1824 gtk_list_store_set(store, &iter,
1827 2, ghb_language_table[ii].iso639_2,
1829 4, ghb_language_table[ii].iso639_1,
1834 static gchar **titles = NULL;
1837 title_opts_set(GtkBuilder *builder, const gchar *name)
1840 GtkListStore *store;
1841 hb_list_t * list = NULL;
1842 hb_title_t * title = NULL;
1846 g_debug("title_opts_set ()\n");
1847 store = get_combo_box_store(builder, name);
1848 gtk_list_store_clear(store);
1851 list = hb_get_titles( h_scan );
1852 count = hb_list_count( list );
1853 if (count > 100) count = 100;
1855 if (titles) g_strfreev(titles);
1856 if (title_opts.map) g_free(title_opts.map);
1859 title_opts.count = count;
1860 title_opts.map = g_malloc(count*sizeof(options_map_t));
1861 titles = g_malloc((count+1) * sizeof(gchar*));
1865 title_opts.count = 1;
1866 title_opts.map = g_malloc(sizeof(options_map_t));
1871 // No titles. Fill in a default.
1872 gtk_list_store_append(store, &iter);
1873 gtk_list_store_set(store, &iter,
1880 title_opts.map[0].option = "No Titles";
1881 title_opts.map[0].shortOpt = "none";
1882 title_opts.map[0].ivalue = -1;
1883 title_opts.map[0].svalue = "none";
1886 for (ii = 0; ii < count; ii++)
1888 title = (hb_title_t*)hb_list_item(list, ii);
1889 if (title->type == HB_STREAM_TYPE)
1891 if (title->duration != 0)
1894 tmp = g_strdup_printf ("%d - %02dh%02dm%02ds - %s",
1895 title->index, title->hours, title->minutes, title->seconds,
1897 titles[ii] = g_markup_escape_text(tmp, -1);
1903 tmp = g_strdup_printf ("%d - %s",
1904 title->index, title->name);
1905 titles[ii] = g_markup_escape_text(tmp, -1);
1911 if (title->duration != 0)
1913 titles[ii] = g_strdup_printf ("%d - %02dh%02dm%02ds",
1914 title->index, title->hours, title->minutes, title->seconds);
1918 titles[ii] = g_strdup_printf ("%d - Unknown Length",
1922 gtk_list_store_append(store, &iter);
1923 gtk_list_store_set(store, &iter,
1930 title_opts.map[ii].option = titles[ii];
1931 title_opts.map[ii].shortOpt = titles[ii];
1932 title_opts.map[ii].ivalue = ii;
1933 title_opts.map[ii].svalue = titles[ii];
1939 find_combo_item_by_int(GtkTreeModel *store, gint value, GtkTreeIter *iter)
1942 gboolean foundit = FALSE;
1944 if (gtk_tree_model_get_iter_first (store, iter))
1948 gtk_tree_model_get(store, iter, 3, &ivalue, -1);
1949 if (value == (gint)ivalue)
1954 } while (gtk_tree_model_iter_next (store, iter));
1960 audio_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
1963 GtkListStore *store;
1964 hb_list_t * list = NULL;
1965 hb_title_t * title = NULL;
1966 hb_audio_config_t * audio;
1971 g_debug("audio_track_opts_set ()\n");
1972 store = get_combo_box_store(builder, name);
1973 gtk_list_store_clear(store);
1976 list = hb_get_titles( h_scan );
1977 title = (hb_title_t*)hb_list_item( list, titleindex );
1980 count = hb_list_count( title->list_audio );
1983 if (count > 100) count = 100;
1984 if (audio_track_opts.map) g_free(audio_track_opts.map);
1987 audio_track_opts.count = count;
1988 audio_track_opts.map = g_malloc(count*sizeof(options_map_t));
1992 audio_track_opts.count = 1;
1993 audio_track_opts.map = g_malloc(sizeof(options_map_t));
1997 // No audio. set some default
1998 gtk_list_store_append(store, &iter);
1999 gtk_list_store_set(store, &iter,
2000 0, "<small>No Audio</small>",
2006 audio_track_opts.map[0].option = "No Audio";
2007 audio_track_opts.map[0].shortOpt = "none";
2008 audio_track_opts.map[0].ivalue = -1;
2009 audio_track_opts.map[0].svalue = "none";
2012 index_str_init(count-1);
2013 for (ii = 0; ii < count; ii++)
2015 audio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, ii );
2016 gtk_list_store_append(store, &iter);
2017 str = g_strdup_printf("<small>%s</small>", audio->lang.description);
2018 gtk_list_store_set(store, &iter,
2026 audio_track_opts.map[ii].option = audio->lang.description,
2027 audio_track_opts.map[ii].shortOpt = index_str[ii];
2028 audio_track_opts.map[ii].ivalue = ii;
2029 audio_track_opts.map[ii].svalue = index_str[ii];
2034 subtitle_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
2037 GtkListStore *store;
2038 hb_list_t * list = NULL;
2039 hb_title_t * title = NULL;
2040 hb_subtitle_t * subtitle;
2042 static char ** options = NULL;
2044 g_debug("subtitle_track_opts_set ()\n");
2045 store = get_combo_box_store(builder, name);
2046 gtk_list_store_clear(store);
2049 list = hb_get_titles( h_scan );
2050 title = (hb_title_t*)hb_list_item( list, titleindex );
2053 count = hb_list_count( title->list_subtitle );
2056 if (count > 100) count = 100;
2057 if (subtitle_opts.map) g_free(subtitle_opts.map);
2060 subtitle_opts.count = count+1;
2061 subtitle_opts.map = g_malloc((count+1)*sizeof(options_map_t));
2065 subtitle_opts.count = LANG_TABLE_SIZE+1;
2066 subtitle_opts.map = g_malloc((LANG_TABLE_SIZE+1)*sizeof(options_map_t));
2068 gtk_list_store_append(store, &iter);
2069 gtk_list_store_set(store, &iter,
2070 0, "Foreign Audio Search",
2076 subtitle_opts.map[0].option = "Foreign Audio Search";
2077 subtitle_opts.map[0].shortOpt = "-1";
2078 subtitle_opts.map[0].ivalue = -1;
2079 subtitle_opts.map[0].svalue = "auto";
2082 if (options != NULL)
2083 g_strfreev(options);
2084 options = g_malloc((count+1)*sizeof(gchar*));
2085 index_str_init(count-1);
2086 for (ii = 0; ii < count; ii++)
2088 subtitle = (hb_subtitle_t *)hb_list_item(title->list_subtitle, ii);
2089 options[ii] = g_strdup_printf("%d - %s (%s)", ii+1,
2091 ghb_subtitle_source_name(subtitle->source));
2092 subtitle_opts.map[ii+1].option = options[ii];
2093 subtitle_opts.map[ii+1].shortOpt = index_str[ii];
2094 subtitle_opts.map[ii+1].ivalue = ii;
2095 subtitle_opts.map[ii+1].svalue = subtitle->iso639_2;
2096 gtk_list_store_append(store, &iter);
2097 gtk_list_store_set(store, &iter,
2102 4, subtitle->iso639_2,
2105 options[count] = NULL;
2109 index_str_init(LANG_TABLE_SIZE-1);
2110 for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
2114 if (ghb_language_table[ii].native_name[0] != 0)
2115 lang = ghb_language_table[ii].native_name;
2117 lang = ghb_language_table[ii].eng_name;
2119 subtitle_opts.map[ii+1].option = lang;
2120 subtitle_opts.map[ii+1].shortOpt = index_str[ii];
2121 subtitle_opts.map[ii+1].ivalue = ii;
2122 subtitle_opts.map[ii+1].svalue = ghb_language_table[ii].iso639_2;
2123 gtk_list_store_append(store, &iter);
2124 gtk_list_store_set(store, &iter,
2129 4, ghb_language_table[ii].iso639_2,
2142 gint titleindex = 0;
2145 g_debug("ghb_longest_title ()\n");
2146 if (h_scan == NULL) return 0;
2147 list = hb_get_titles( h_scan );
2148 count = hb_list_count( list );
2149 if (count > 100) count = 100;
2150 if (count < 1) return 0;
2151 title = (hb_title_t*)hb_list_item(list, 0);
2152 feature = title->job->feature;
2153 for (ii = 0; ii < count; ii++)
2155 title = (hb_title_t*)hb_list_item(list, ii);
2156 if (title->index == feature)
2165 ghb_get_source_audio_lang(gint titleindex, gint track)
2169 hb_audio_config_t * audio;
2172 g_debug("ghb_lookup_1st_audio_lang ()\n");
2175 list = hb_get_titles( h_scan );
2176 title = (hb_title_t*)hb_list_item( list, titleindex );
2179 if (hb_list_count( title->list_audio ) <= track)
2182 audio = hb_list_audio_config_item(title->list_audio, track);
2186 lang = g_strdup(audio->lang.iso639_2);
2191 get_track_used(gint acodec, GHashTable *track_indices, gint count)
2195 used = g_hash_table_lookup(track_indices, &acodec);
2200 used = g_malloc0(count * sizeof(gboolean));
2201 key = g_malloc(sizeof(gint));
2203 g_hash_table_insert(track_indices, key, used);
2209 ghb_find_audio_track(
2213 gint fallback_acodec,
2214 GHashTable *track_indices)
2218 hb_audio_config_t * audio;
2223 gboolean *used = NULL;
2224 gboolean *passthru_used;
2226 gint passthru_acodec;
2230 g_debug("find_audio_track ()\n");
2231 if (h_scan == NULL) return -1;
2232 list = hb_get_titles( h_scan );
2233 title = (hb_title_t*)hb_list_item( list, titleindex );
2236 count = hb_list_count( title->list_audio );
2238 if (count > 10) count = 10;
2239 // Try to find an item that matches the preferred language and
2240 // the passthru codec type
2242 passthru = (acodec & HB_ACODEC_PASS_FLAG) != 0;
2245 for (ii = 0; ii < count; ii++)
2247 audio = (hb_audio_config_t*)hb_list_audio_config_item(
2248 title->list_audio, ii );
2249 passthru_acodec = HB_ACODEC_PASS_MASK & acodec & audio->in.codec;
2250 // Is the source track use a passthru capable codec?
2251 if (passthru_acodec == 0)
2253 used = get_track_used(passthru_acodec, track_indices, count);
2254 // Has the track already been used with this codec?
2258 channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
2259 audio->in.channel_layout);
2260 // Find a track that is not visually impaired or dirctor's
2261 // commentary, and has the highest channel count.
2262 if ((audio->lang.type < 2) &&
2263 ((strcmp(lang, audio->lang.iso639_2) == 0) ||
2264 (strcmp(lang, "und") == 0)))
2266 if (channels > max_chan)
2269 max_chan = channels;
2273 try_acodec = fallback_acodec;
2277 try_acodec = acodec;
2284 // Try to find an item that matches the preferred language
2286 used = get_track_used(try_acodec, track_indices, count);
2287 for (ii = 0; ii < count; ii++)
2289 // Has the track already been used with this codec?
2292 audio = (hb_audio_config_t*)hb_list_audio_config_item(
2293 title->list_audio, ii );
2294 passthru_acodec = HB_ACODEC_PASS_MASK & audio->in.codec;
2295 if (passthru_acodec && passthru)
2297 passthru_used = get_track_used(passthru_acodec, track_indices, count);
2298 // Has the track already been used with this codec for passthru?
2299 if (passthru_used[ii])
2302 channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
2303 audio->in.channel_layout);
2304 // Find a track that is not visually impaired or dirctor's commentary
2305 if ((audio->lang.type < 2) &&
2306 ((strcmp(lang, audio->lang.iso639_2) == 0) ||
2307 (strcmp(lang, "und") == 0)))
2309 if (channels > max_chan)
2312 max_chan = channels;
2321 // Try to fine an item that does not match the preferred language and
2322 // matches the passthru codec type
2326 for (ii = 0; ii < count; ii++)
2328 audio = (hb_audio_config_t*)hb_list_audio_config_item(
2329 title->list_audio, ii );
2330 passthru_acodec = HB_ACODEC_PASS_MASK & acodec & audio->in.codec;
2331 // Is the source track use a passthru capable codec?
2332 if (passthru_acodec == 0)
2334 used = get_track_used(passthru_acodec, track_indices, count);
2335 // Has the track already been used with this codec?
2339 channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
2340 audio->in.channel_layout);
2341 // Find a track that is not visually impaired or dirctor's
2342 // commentary, and has the highest channel count.
2343 if (audio->lang.type < 2)
2345 if (channels > max_chan)
2348 max_chan = channels;
2352 try_acodec = fallback_acodec;
2356 try_acodec = acodec;
2363 // Try to fine an item that does not match the preferred language
2365 used = get_track_used(try_acodec, track_indices, count);
2366 for (ii = 0; ii < count; ii++)
2368 // Has the track already been used with this codec?
2371 audio = (hb_audio_config_t*)hb_list_audio_config_item(
2372 title->list_audio, ii );
2373 passthru_acodec = HB_ACODEC_PASS_MASK & audio->in.codec;
2374 channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
2375 audio->in.channel_layout);
2376 if (passthru_acodec && passthru)
2378 passthru_used = get_track_used(passthru_acodec, track_indices, count);
2379 // Has the track already been used with this codec for passthru?
2380 if (passthru_used[ii])
2383 // Find a track that is not visually impaired or dirctor's commentary
2384 if (audio->lang.type < 2)
2386 if (channels > max_chan)
2389 max_chan = channels;
2398 // Last ditch, anything goes
2399 for (ii = 0; ii < count; ii++)
2401 audio = (hb_audio_config_t*)hb_list_audio_config_item(
2402 title->list_audio, ii );
2403 passthru_acodec = HB_ACODEC_PASS_MASK & audio->in.codec;
2404 if (passthru_acodec && passthru)
2406 passthru_used = get_track_used(passthru_acodec, track_indices, count);
2407 // Has the track already been used with this codec for passthru?
2408 if (passthru_used[ii])
2411 // Has the track already been used with this codec?
2426 ghb_find_pref_subtitle_track(const gchar *lang)
2429 count = subtitle_opts.count;
2430 for (ii = 0; ii < count; ii++)
2432 if (strcmp(lang, subtitle_opts.map[ii].svalue) == 0)
2434 return subtitle_opts.map[ii].ivalue;
2441 ghb_find_cc_track(gint titleindex)
2445 hb_subtitle_t * subtitle;
2448 g_debug("ghb_find_cc_track ()\n");
2449 if (h_scan == NULL) return -2;
2450 list = hb_get_titles( h_scan );
2451 title = (hb_title_t*)hb_list_item( list, titleindex );
2454 count = hb_list_count( title->list_subtitle );
2455 // Try to find an item that matches the preferred language
2456 for (ii = 0; ii < count; ii++)
2458 subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
2459 if (subtitle->source == CC608SUB || subtitle->source == CC708SUB)
2467 canForce(int source)
2469 return (source == VOBSUB);
2475 return (source == VOBSUB || source == SSASUB);
2479 ghb_find_subtitle_track(
2485 GHashTable * track_indices)
2489 hb_subtitle_t * subtitle;
2493 g_debug("find_subtitle_track ()\n");
2494 if (strcmp(lang, "auto") == 0)
2496 if (h_scan == NULL) return -1;
2497 list = hb_get_titles( h_scan );
2498 title = (hb_title_t*)hb_list_item( list, titleindex );
2501 count = hb_list_count( title->list_subtitle );
2502 used = g_hash_table_lookup(track_indices, lang);
2505 used = g_malloc0(count * sizeof(gboolean));
2506 g_hash_table_insert(track_indices, g_strdup(lang), used);
2508 // Try to find an item that matches the preferred language and source
2509 for (ii = 0; ii < count; ii++)
2514 subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
2515 if (source == subtitle->source &&
2516 ((strcmp(lang, subtitle->iso639_2) == 0) ||
2517 (strcmp(lang, "und") == 0)))
2523 // Try to find an item that matches the preferred language
2524 for (ii = 0; ii < count; ii++)
2529 subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
2530 if (((!force || (force && canForce(subtitle->source))) &&
2531 (!burn || (burn && canBurn(subtitle->source)))) &&
2532 ((strcmp(lang, subtitle->iso639_2) == 0) ||
2533 (strcmp(lang, "und") == 0)))
2544 generic_opts_set(GtkBuilder *builder, const gchar *name, combo_opts_t *opts)
2547 GtkListStore *store;
2550 g_debug("generic_opts_set ()\n");
2551 if (name == NULL || opts == NULL) return;
2552 store = get_combo_box_store(builder, name);
2553 gtk_list_store_clear(store);
2554 for (ii = 0; ii < opts->count; ii++)
2556 gtk_list_store_append(store, &iter);
2557 gtk_list_store_set(store, &iter,
2558 0, opts->map[ii].option,
2560 2, opts->map[ii].shortOpt,
2561 3, opts->map[ii].ivalue,
2562 4, opts->map[ii].svalue,
2568 small_opts_set(GtkBuilder *builder, const gchar *name, combo_opts_t *opts)
2571 GtkListStore *store;
2575 g_debug("small_opts_set ()\n");
2576 if (name == NULL || opts == NULL) return;
2577 store = get_combo_box_store(builder, name);
2578 gtk_list_store_clear(store);
2579 for (ii = 0; ii < opts->count; ii++)
2581 gtk_list_store_append(store, &iter);
2582 str = g_strdup_printf("<small>%s</small>", opts->map[ii].option);
2583 gtk_list_store_set(store, &iter,
2586 2, opts->map[ii].shortOpt,
2587 3, opts->map[ii].ivalue,
2588 4, opts->map[ii].svalue,
2595 find_combo_table(const gchar *name)
2599 for (ii = 0; combo_name_map[ii].name != NULL; ii++)
2601 if (strcmp(name, combo_name_map[ii].name) == 0)
2603 return combo_name_map[ii].opts;
2610 ghb_lookup_combo_int(const gchar *name, const GValue *gval)
2614 if (strcmp(name, "AudioBitrate") == 0)
2615 return lookup_audio_bitrate_int(gval);
2616 else if (strcmp(name, "AudioSamplerate") == 0)
2617 return lookup_audio_rate_int(gval);
2618 else if (strcmp(name, "VideoFramerate") == 0)
2619 return lookup_video_rate_int(gval);
2620 else if (strcmp(name, "AudioMixdown") == 0)
2621 return lookup_mix_int(gval);
2622 else if (strcmp(name, "SrtLanguage") == 0)
2623 return lookup_audio_lang_int(gval);
2624 else if (strcmp(name, "PreferredLanguage") == 0)
2625 return lookup_audio_lang_int(gval);
2628 return lookup_generic_int(find_combo_table(name), gval);
2630 g_warning("ghb_lookup_combo_int() couldn't find %s", name);
2635 ghb_lookup_combo_double(const gchar *name, const GValue *gval)
2639 if (strcmp(name, "AudioBitrate") == 0)
2640 return lookup_audio_bitrate_int(gval);
2641 else if (strcmp(name, "AudioSamplerate") == 0)
2642 return lookup_audio_rate_int(gval);
2643 else if (strcmp(name, "VideoFramerate") == 0)
2644 return lookup_video_rate_int(gval);
2645 else if (strcmp(name, "AudioMixdown") == 0)
2646 return lookup_mix_int(gval);
2647 else if (strcmp(name, "SrtLanguage") == 0)
2648 return lookup_audio_lang_int(gval);
2649 else if (strcmp(name, "PreferredLanguage") == 0)
2650 return lookup_audio_lang_int(gval);
2653 return lookup_generic_double(find_combo_table(name), gval);
2655 g_warning("ghb_lookup_combo_double() couldn't find %s", name);
2660 ghb_lookup_combo_option(const gchar *name, const GValue *gval)
2664 if (strcmp(name, "AudioBitrate") == 0)
2665 return lookup_audio_bitrate_option(gval);
2666 else if (strcmp(name, "AudioSamplerate") == 0)
2667 return lookup_audio_rate_option(gval);
2668 else if (strcmp(name, "VideoFramerate") == 0)
2669 return lookup_video_rate_option(gval);
2670 else if (strcmp(name, "AudioMixdown") == 0)
2671 return lookup_mix_option(gval);
2672 else if (strcmp(name, "SrtLanguage") == 0)
2673 return lookup_audio_lang_option(gval);
2674 else if (strcmp(name, "PreferredLanguage") == 0)
2675 return lookup_audio_lang_option(gval);
2678 return lookup_generic_option(find_combo_table(name), gval);
2680 g_warning("ghb_lookup_combo_int() couldn't find %s", name);
2685 ghb_lookup_combo_string(const gchar *name, const GValue *gval)
2689 if (strcmp(name, "AudioBitrate") == 0)
2690 return lookup_audio_bitrate_option(gval);
2691 else if (strcmp(name, "AudioSamplerate") == 0)
2692 return lookup_audio_rate_option(gval);
2693 else if (strcmp(name, "VideoFramerate") == 0)
2694 return lookup_video_rate_option(gval);
2695 else if (strcmp(name, "AudioMixdown") == 0)
2696 return lookup_mix_string(gval);
2697 else if (strcmp(name, "SrtLanguage") == 0)
2698 return lookup_audio_lang_option(gval);
2699 else if (strcmp(name, "PreferredLanguage") == 0)
2700 return lookup_audio_lang_option(gval);
2703 return lookup_generic_string(find_combo_table(name), gval);
2705 g_warning("ghb_lookup_combo_int() couldn't find %s", name);
2710 ghb_update_ui_combo_box(
2711 signal_user_data_t *ud,
2716 GtkComboBox *combo = NULL;
2718 gint handler_id = 0;
2722 g_debug("ghb_update_ui_combo_box() %s\n", name);
2723 // Clearing a combo box causes a rash of "changed" events, even when
2724 // the active item is -1 (inactive). To control things, I'm disabling
2725 // the event till things are settled down.
2726 combo = GTK_COMBO_BOX(GHB_WIDGET(ud->builder, name));
2727 signal_id = g_signal_lookup("changed", GTK_TYPE_COMBO_BOX);
2730 // Valid signal id found. This should always succeed.
2731 handler_id = g_signal_handler_find ((gpointer)combo, G_SIGNAL_MATCH_ID,
2732 signal_id, 0, 0, 0, 0);
2735 // This should also always succeed
2736 g_signal_handler_block ((gpointer)combo, handler_id);
2742 audio_bitrate_opts_set(ud->builder, "AudioBitrate");
2743 audio_samplerate_opts_set(ud->builder, "AudioSamplerate", hb_audio_rates, hb_audio_rates_count);
2744 video_rate_opts_set(ud->builder, "VideoFramerate", hb_video_rates, hb_video_rates_count);
2745 mix_opts_set(ud->builder, "AudioMixdown");
2746 language_opts_set(ud->builder, "SrtLanguage");
2747 language_opts_set(ud->builder, "PreferredLanguage");
2748 srt_codeset_opts_set(ud->builder, "SrtCodeset");
2749 title_opts_set(ud->builder, "title");
2750 audio_track_opts_set(ud->builder, "AudioTrack", user_data);
2751 subtitle_track_opts_set(ud->builder, "SubtitleTrack", user_data);
2752 generic_opts_set(ud->builder, "VideoQualityGranularity", &vqual_granularity_opts);
2753 generic_opts_set(ud->builder, "PtoPType", &point_to_point_opts);
2754 generic_opts_set(ud->builder, "WhenComplete", &when_complete_opts);
2755 generic_opts_set(ud->builder, "PicturePAR", &par_opts);
2756 generic_opts_set(ud->builder, "PictureModulus", &alignment_opts);
2757 generic_opts_set(ud->builder, "LoggingLevel", &logging_opts);
2758 generic_opts_set(ud->builder, "LogLongevity", &log_longevity_opts);
2759 generic_opts_set(ud->builder, "check_updates", &appcast_update_opts);
2760 generic_opts_set(ud->builder, "FileFormat", &container_opts);
2761 generic_opts_set(ud->builder, "PictureDeinterlace", &deint_opts);
2762 generic_opts_set(ud->builder, "PictureDetelecine", &detel_opts);
2763 generic_opts_set(ud->builder, "PictureDecomb", &decomb_opts);
2764 generic_opts_set(ud->builder, "PictureDenoise", &denoise_opts);
2765 generic_opts_set(ud->builder, "VideoEncoder", &vcodec_opts);
2766 small_opts_set(ud->builder, "AudioEncoder", &acodec_opts);
2767 small_opts_set(ud->builder, "x264_direct", &direct_opts);
2768 small_opts_set(ud->builder, "x264_b_adapt", &badapt_opts);
2769 small_opts_set(ud->builder, "x264_bpyramid", &bpyramid_opts);
2770 small_opts_set(ud->builder, "x264_weighted_pframes", &weightp_opts);
2771 small_opts_set(ud->builder, "x264_me", &me_opts);
2772 small_opts_set(ud->builder, "x264_subme", &subme_opts);
2773 small_opts_set(ud->builder, "x264_analyse", &analyse_opts);
2774 small_opts_set(ud->builder, "x264_trellis", &trellis_opts);
2778 if (strcmp(name, "AudioBitrate") == 0)
2779 audio_bitrate_opts_set(ud->builder, "AudioBitrate");
2780 else if (strcmp(name, "AudioSamplerate") == 0)
2781 audio_samplerate_opts_set(ud->builder, "AudioSamplerate", hb_audio_rates, hb_audio_rates_count);
2782 else if (strcmp(name, "VideoFramerate") == 0)
2783 video_rate_opts_set(ud->builder, "VideoFramerate", hb_video_rates, hb_video_rates_count);
2784 else if (strcmp(name, "AudioMixdown") == 0)
2785 mix_opts_set(ud->builder, "AudioMixdown");
2786 else if (strcmp(name, "SrtLanguage") == 0)
2787 language_opts_set(ud->builder, "SrtLanguage");
2788 else if (strcmp(name, "PreferredLanguage") == 0)
2789 language_opts_set(ud->builder, "PreferredLanguage");
2790 else if (strcmp(name, "SrtCodeset") == 0)
2791 srt_codeset_opts_set(ud->builder, "SrtCodeset");
2792 else if (strcmp(name, "title") == 0)
2793 title_opts_set(ud->builder, "title");
2794 else if (strcmp(name, "SubtitleTrack") == 0)
2795 subtitle_track_opts_set(ud->builder, "SubtitleTrack", user_data);
2796 else if (strcmp(name, "AudioTrack") == 0)
2797 audio_track_opts_set(ud->builder, "AudioTrack", user_data);
2799 generic_opts_set(ud->builder, name, find_combo_table(name));
2803 g_signal_handler_unblock ((gpointer)combo, handler_id);
2808 init_ui_combo_boxes(GtkBuilder *builder)
2812 init_combo_box(builder, "AudioBitrate");
2813 init_combo_box(builder, "AudioSamplerate");
2814 init_combo_box(builder, "VideoFramerate");
2815 init_combo_box(builder, "AudioMixdown");
2816 init_combo_box(builder, "SrtLanguage");
2817 init_combo_box(builder, "PreferredLanguage");
2818 init_combo_box(builder, "SrtCodeset");
2819 init_combo_box(builder, "title");
2820 init_combo_box(builder, "AudioTrack");
2821 for (ii = 0; combo_name_map[ii].name != NULL; ii++)
2823 init_combo_box(builder, combo_name_map[ii].name);
2827 static const char * turbo_opts =
2828 "ref=1:subme=2:me=dia:analyse=none:trellis=0:"
2829 "no-fast-pskip=0:8x8dct=0";
2831 // Construct the x264 options string
2832 // The result is allocated, so someone must free it at some point.
2834 ghb_build_x264opts_string(GValue *settings)
2837 gchar *opts = ghb_settings_get_string(settings, "x264Option");
2844 result = g_strdup("");
2850 ghb_part_duration(gint tt, gint sc, gint ec, gint *hh, gint *mm, gint *ss)
2854 hb_chapter_t * chapter;
2858 *hh = *mm = *ss = 0;
2859 if (h_scan == NULL) return;
2860 list = hb_get_titles( h_scan );
2861 title = (hb_title_t*)hb_list_item( list, tt );
2862 if (title == NULL) return;
2865 *mm = title->minutes;
2866 *ss = title->seconds;
2868 count = hb_list_count(title->list_chapter);
2869 if (sc > count) sc = count;
2870 if (ec > count) ec = count;
2872 if (sc == 1 && ec == count)
2876 for (c = sc; c <= ec; c++)
2878 chapter = hb_list_item(title->list_chapter, c-1);
2879 duration += chapter->duration;
2882 *hh = duration / 90000 / 3600;
2883 *mm = ((duration / 90000) % 3600) / 60;
2884 *ss = (duration / 90000) % 60;
2888 ghb_get_chapter_duration(gint ti, gint ii, gint *hh, gint *mm, gint *ss)
2892 hb_chapter_t * chapter;
2895 g_debug("ghb_get_chapter_duration (title = %d)\n", ti);
2896 *hh = *mm = *ss = 0;
2897 if (h_scan == NULL) return;
2898 list = hb_get_titles( h_scan );
2899 title = (hb_title_t*)hb_list_item( list, ti );
2900 if (title == NULL) return;
2901 count = hb_list_count( title->list_chapter );
2902 if (ii >= count) return;
2903 chapter = hb_list_item(title->list_chapter, ii);
2904 if (chapter == NULL) return;
2905 *hh = chapter->hours;
2906 *mm = chapter->minutes;
2907 *ss = chapter->seconds;
2911 ghb_get_chapters(gint titleindex)
2915 hb_chapter_t * chapter;
2917 GValue *chapters = NULL;
2919 g_debug("ghb_get_chapters (title = %d)\n", titleindex);
2920 if (h_scan == NULL) return NULL;
2921 list = hb_get_titles( h_scan );
2922 title = (hb_title_t*)hb_list_item( list, titleindex );
2923 if (title == NULL) return NULL;
2924 count = hb_list_count( title->list_chapter );
2925 chapters = ghb_array_value_new(count);
2926 for (ii = 0; ii < count; ii++)
2928 chapter = hb_list_item(title->list_chapter, ii);
2929 if (chapter == NULL) break;
2930 if (chapter->title == NULL || chapter->title[0] == 0)
2933 str = g_strdup_printf ("Chapter %2d", ii+1);
2934 ghb_array_append(chapters, ghb_string_value_new(str));
2939 ghb_array_append(chapters, ghb_string_value_new(chapter->title));
2946 ghb_ac3_in_audio_list(const GValue *audio_list)
2950 count = ghb_array_len(audio_list);
2951 for (ii = 0; ii < count; ii++)
2956 asettings = ghb_array_get_nth(audio_list, ii);
2957 acodec = ghb_settings_combo_int(asettings, "AudioEncoder");
2958 if (acodec & HB_ACODEC_AC3)
2965 audio_bitrate_opts_add(GtkBuilder *builder, const gchar *name, gint rate)
2968 GtkListStore *store;
2971 g_debug("audio_bitrate_opts_add ()\n");
2973 if (rate < 8) return;
2975 if (ghb_audio_bitrates[hb_audio_bitrates_count].string)
2977 g_free(ghb_audio_bitrates[hb_audio_bitrates_count].string);
2979 ghb_audio_bitrates[hb_audio_bitrates_count].rate = rate;
2980 ghb_audio_bitrates[hb_audio_bitrates_count].string =
2981 g_strdup_printf("%d", rate);
2982 ghb_audio_bitrates_count = hb_audio_bitrates_count + 1;
2984 store = get_combo_box_store(builder, name);
2985 if (!find_combo_item_by_int(GTK_TREE_MODEL(store), rate, &iter))
2987 str = g_strdup_printf ("<small>%d</small>", rate);
2988 gtk_list_store_append(store, &iter);
2989 gtk_list_store_set(store, &iter,
2992 2, ghb_audio_bitrates[hb_audio_bitrates_count].string,
2994 4, ghb_audio_bitrates[hb_audio_bitrates_count].string,
3001 audio_bitrate_opts_clean(
3002 GtkBuilder *builder,
3008 GtkListStore *store;
3010 gboolean done = FALSE;
3012 guint last = (guint)last_rate;
3013 guint first = (guint)first_rate;
3015 ghb_audio_bitrates_count = hb_audio_bitrates_count;
3017 g_debug("audio_bitrate_opts_clean ()\n");
3018 store = get_combo_box_store(builder, name);
3019 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter))
3023 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 3, &ivalue, -1);
3025 ghb_audio_bitrates, ivalue, ghb_audio_bitrates_count) < 0)
3027 done = !gtk_list_store_remove(store, &iter);
3029 else if (ivalue < first || ivalue > last)
3032 gtk_list_store_set(store, &iter, 1, FALSE, -1);
3033 done = !gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
3038 gtk_list_store_set(store, &iter, 1, TRUE, -1);
3039 done = !gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
3046 audio_bitrate_opts_set(GtkBuilder *builder, const gchar *name)
3049 GtkListStore *store;
3053 ghb_audio_bitrates_count = hb_audio_bitrates_count;
3054 ghb_audio_bitrates = calloc(hb_audio_bitrates_count+1, sizeof(hb_rate_t));
3056 for (ii = 0; ii < hb_audio_bitrates_count; ii++)
3058 ghb_audio_bitrates[ii] = hb_audio_bitrates[ii];
3061 g_debug("audio_bitrate_opts_set ()\n");
3062 store = get_combo_box_store(builder, name);
3063 gtk_list_store_clear(store);
3064 for (ii = 0; ii < ghb_audio_bitrates_count; ii++)
3066 gtk_list_store_append(store, &iter);
3067 str = g_strdup_printf ("<small>%s</small>",
3068 ghb_audio_bitrates[ii].string);
3069 gtk_list_store_set(store, &iter,
3072 2, ghb_audio_bitrates[ii].string,
3073 3, (gdouble)ghb_audio_bitrates[ii].rate,
3074 4, ghb_audio_bitrates[ii].string,
3081 ghb_set_passthru_bitrate_opts(GtkBuilder *builder, gint bitrate)
3083 audio_bitrate_opts_add(builder, "AudioBitrate", bitrate);
3087 ghb_set_default_bitrate_opts(
3088 GtkBuilder *builder,
3092 audio_bitrate_opts_clean(builder, "AudioBitrate", first_rate, last_rate);
3095 static ghb_status_t hb_status;
3098 ghb_combo_init(signal_user_data_t *ud)
3100 // Set up the list model for the combos
3101 init_ui_combo_boxes(ud->builder);
3102 // Populate all the combos
3103 ghb_update_ui_combo_box(ud, NULL, 0, TRUE);
3107 ghb_backend_init(gint debug)
3110 h_scan = hb_init( debug, 0 );
3111 h_queue = hb_init( debug, 0 );
3122 void ghb_backend_scan_stop()
3124 hb_scan_stop( h_scan );
3128 ghb_backend_scan(const gchar *path, gint titleindex, gint preview_count, uint64_t min_duration)
3130 hb_scan( h_scan, path, titleindex, preview_count, 1, min_duration );
3131 hb_status.scan.state |= GHB_STATE_SCANNING;
3132 // initialize count and cur to something that won't cause FPE
3133 // when computing progress
3134 hb_status.scan.title_count = 1;
3135 hb_status.scan.title_cur = 0;
3139 ghb_backend_queue_scan(const gchar *path, gint titlenum)
3141 g_debug("ghb_backend_queue_scan()");
3142 hb_scan( h_queue, path, titlenum, 10, 0, 0 );
3143 hb_status.queue.state |= GHB_STATE_SCANNING;
3147 ghb_get_scan_state()
3149 return hb_status.scan.state;
3153 ghb_get_queue_state()
3155 return hb_status.queue.state;
3159 ghb_clear_scan_state(gint state)
3161 hb_status.scan.state &= ~state;
3165 ghb_clear_queue_state(gint state)
3167 hb_status.queue.state &= ~state;
3171 ghb_set_scan_state(gint state)
3173 hb_status.scan.state |= state;
3177 ghb_set_queue_state(gint state)
3179 hb_status.queue.state |= state;
3183 ghb_get_status(ghb_status_t *status)
3185 memcpy(status, &hb_status, sizeof(ghb_status_t));
3194 if (h_scan == NULL) return;
3195 hb_get_state( h_scan, &s_scan );
3196 switch( s_scan.state )
3198 #define p s_scan.param.scanning
3199 case HB_STATE_SCANNING:
3201 hb_status.scan.state |= GHB_STATE_SCANNING;
3202 hb_status.scan.title_count = p.title_count;
3203 hb_status.scan.title_cur = p.title_cur;
3207 case HB_STATE_SCANDONE:
3209 hb_status.scan.state &= ~GHB_STATE_SCANNING;
3210 hb_status.scan.state |= GHB_STATE_SCANDONE;
3213 #define p s_scan.param.working
3214 case HB_STATE_WORKING:
3215 hb_status.scan.state |= GHB_STATE_WORKING;
3216 hb_status.scan.state &= ~GHB_STATE_PAUSED;
3217 hb_status.scan.job_cur = p.job_cur;
3218 hb_status.scan.job_count = p.job_count;
3219 hb_status.scan.progress = p.progress;
3220 hb_status.scan.rate_cur = p.rate_cur;
3221 hb_status.scan.rate_avg = p.rate_avg;
3222 hb_status.scan.hours = p.hours;
3223 hb_status.scan.minutes = p.minutes;
3224 hb_status.scan.seconds = p.seconds;
3225 hb_status.scan.unique_id = p.sequence_id & 0xFFFFFF;
3229 case HB_STATE_PAUSED:
3230 hb_status.scan.state |= GHB_STATE_PAUSED;
3233 case HB_STATE_MUXING:
3235 hb_status.scan.state |= GHB_STATE_MUXING;
3238 #define p s_scan.param.workdone
3239 case HB_STATE_WORKDONE:
3243 hb_status.scan.state |= GHB_STATE_WORKDONE;
3244 hb_status.scan.state &= ~GHB_STATE_MUXING;
3245 hb_status.scan.state &= ~GHB_STATE_PAUSED;
3246 hb_status.scan.state &= ~GHB_STATE_WORKING;
3250 hb_status.scan.error = GHB_ERROR_NONE;
3252 case HB_ERROR_CANCELED:
3253 hb_status.scan.error = GHB_ERROR_CANCELED;
3256 hb_status.scan.error = GHB_ERROR_FAIL;
3259 // Delete all remaining jobs of this encode.
3260 // An encode can be composed of multiple associated jobs.
3261 // When a job is stopped, libhb removes it from the job list,
3262 // but does not remove other jobs that may be associated with it.
3263 // Associated jobs are taged in the sequence id.
3264 while ((job = hb_job(h_scan, 0)) != NULL)
3265 hb_rem( h_scan, job );
3269 hb_get_state( h_queue, &s_queue );
3270 switch( s_queue.state )
3272 #define p s_queue.param.scanning
3273 case HB_STATE_SCANNING:
3275 hb_status.queue.state |= GHB_STATE_SCANNING;
3276 hb_status.queue.title_count = p.title_count;
3277 hb_status.queue.title_cur = p.title_cur;
3281 case HB_STATE_SCANDONE:
3283 hb_status.queue.state &= ~GHB_STATE_SCANNING;
3284 hb_status.queue.state |= GHB_STATE_SCANDONE;
3287 #define p s_queue.param.working
3288 case HB_STATE_WORKING:
3289 hb_status.queue.state |= GHB_STATE_WORKING;
3290 hb_status.queue.state &= ~GHB_STATE_PAUSED;
3291 hb_status.queue.state &= ~GHB_STATE_SEARCHING;
3292 hb_status.queue.job_cur = p.job_cur;
3293 hb_status.queue.job_count = p.job_count;
3294 hb_status.queue.progress = p.progress;
3295 hb_status.queue.rate_cur = p.rate_cur;
3296 hb_status.queue.rate_avg = p.rate_avg;
3297 hb_status.queue.hours = p.hours;
3298 hb_status.queue.minutes = p.minutes;
3299 hb_status.queue.seconds = p.seconds;
3300 hb_status.queue.unique_id = p.sequence_id & 0xFFFFFF;
3303 case HB_STATE_SEARCHING:
3304 hb_status.queue.state |= GHB_STATE_SEARCHING;
3305 hb_status.queue.state &= ~GHB_STATE_WORKING;
3306 hb_status.queue.state &= ~GHB_STATE_PAUSED;
3307 hb_status.queue.job_cur = p.job_cur;
3308 hb_status.queue.job_count = p.job_count;
3309 hb_status.queue.progress = p.progress;
3310 hb_status.queue.rate_cur = p.rate_cur;
3311 hb_status.queue.rate_avg = p.rate_avg;
3312 hb_status.queue.hours = p.hours;
3313 hb_status.queue.minutes = p.minutes;
3314 hb_status.queue.seconds = p.seconds;
3315 hb_status.queue.unique_id = p.sequence_id & 0xFFFFFF;
3319 case HB_STATE_PAUSED:
3320 hb_status.queue.state |= GHB_STATE_PAUSED;
3323 case HB_STATE_MUXING:
3325 hb_status.queue.state |= GHB_STATE_MUXING;
3328 #define p s_queue.param.workdone
3329 case HB_STATE_WORKDONE:
3333 hb_status.queue.state |= GHB_STATE_WORKDONE;
3334 hb_status.queue.state &= ~GHB_STATE_MUXING;
3335 hb_status.queue.state &= ~GHB_STATE_PAUSED;
3336 hb_status.queue.state &= ~GHB_STATE_WORKING;
3337 hb_status.queue.state &= ~GHB_STATE_SEARCHING;
3341 hb_status.queue.error = GHB_ERROR_NONE;
3343 case HB_ERROR_CANCELED:
3344 hb_status.queue.error = GHB_ERROR_CANCELED;
3347 hb_status.queue.error = GHB_ERROR_FAIL;
3350 // Delete all remaining jobs of this encode.
3351 // An encode can be composed of multiple associated jobs.
3352 // When a job is stopped, libhb removes it from the job list,
3353 // but does not remove other jobs that may be associated with it.
3354 // Associated jobs are taged in the sequence id.
3355 while ((job = hb_job(h_queue, 0)) != NULL)
3356 hb_rem( h_queue, job );
3363 ghb_get_title_info(ghb_title_info_t *tinfo, gint titleindex)
3368 if (h_scan == NULL) return FALSE;
3369 list = hb_get_titles( h_scan );
3370 if( !hb_list_count( list ) )
3372 /* No valid title, stop right there */
3376 title = hb_list_item( list, titleindex );
3377 if (title == NULL) return FALSE; // Bad titleindex
3378 tinfo->index = titleindex;
3379 tinfo->width = title->width;
3380 tinfo->height = title->height;
3381 memcpy(tinfo->crop, title->crop, 4 * sizeof(int));
3382 // Don't allow crop to 0
3383 if (title->crop[0] + title->crop[1] >= title->height)
3384 title->crop[0] = title->crop[1] = 0;
3385 if (title->crop[2] + title->crop[3] >= title->width)
3386 title->crop[2] = title->crop[3] = 0;
3387 tinfo->num_chapters = hb_list_count(title->list_chapter);
3388 tinfo->rate_base = title->rate_base;
3389 tinfo->rate = title->rate;
3390 tinfo->interlaced = title->detected_interlacing;
3391 hb_reduce(&(tinfo->aspect_n), &(tinfo->aspect_d),
3392 title->width * title->pixel_aspect_width,
3393 title->height * title->pixel_aspect_height);
3394 tinfo->hours = title->hours;
3395 tinfo->minutes = title->minutes;
3396 tinfo->seconds = title->seconds;
3397 tinfo->duration = title->duration;
3399 tinfo->angle_count = title->angle_count;
3400 tinfo->path = title->path;
3401 tinfo->name = title->name;
3402 tinfo->type = title->type;
3407 ghb_get_scan_audio_info(gint titleindex, gint audioindex)
3409 hb_audio_config_t *aconfig;
3411 aconfig = get_hb_audio(h_scan, titleindex, audioindex);
3416 ghb_audio_is_passthru(gint acodec)
3418 g_debug("ghb_audio_is_passthru () \n");
3419 return (acodec & HB_ACODEC_PASS_FLAG) != 0;
3423 ghb_audio_can_passthru(gint acodec)
3425 g_debug("ghb_audio_can_passthru () \n");
3426 return (acodec & HB_ACODEC_PASS_MASK) != 0;
3430 ghb_get_default_acodec()
3432 return HB_ACODEC_FAAC;
3436 picture_settings_deps(signal_user_data_t *ud)
3438 gboolean autoscale, keep_aspect, enable_keep_aspect;
3439 gboolean enable_scale_width, enable_scale_height;
3440 gboolean enable_disp_width, enable_disp_height, enable_par;
3444 pic_par = ghb_settings_combo_int(ud->settings, "PicturePAR");
3447 ghb_ui_update(ud, "autoscale", ghb_boolean_value(TRUE));
3448 ghb_ui_update(ud, "PictureModulus", ghb_int_value(2));
3449 ghb_ui_update(ud, "PictureLooseCrop", ghb_boolean_value(TRUE));
3451 enable_keep_aspect = (pic_par != 1 && pic_par != 2);
3452 if (!enable_keep_aspect)
3454 ghb_ui_update(ud, "PictureKeepRatio", ghb_boolean_value(TRUE));
3456 keep_aspect = ghb_settings_get_boolean(ud->settings, "PictureKeepRatio");
3457 autoscale = ghb_settings_get_boolean(ud->settings, "autoscale");
3459 enable_scale_width = !autoscale && (pic_par != 1);
3460 enable_scale_height = !autoscale && (pic_par != 1);
3461 enable_disp_width = (pic_par == 3) && !keep_aspect;
3462 enable_par = (pic_par == 3) && !keep_aspect;
3463 enable_disp_height = FALSE;
3465 widget = GHB_WIDGET(ud->builder, "PictureModulus");
3466 gtk_widget_set_sensitive(widget, pic_par != 1);
3467 widget = GHB_WIDGET(ud->builder, "PictureLooseCrop");
3468 gtk_widget_set_sensitive(widget, pic_par != 1);
3469 widget = GHB_WIDGET(ud->builder, "scale_width");
3470 gtk_widget_set_sensitive(widget, enable_scale_width);
3471 widget = GHB_WIDGET(ud->builder, "scale_height");
3472 gtk_widget_set_sensitive(widget, enable_scale_height);
3473 widget = GHB_WIDGET(ud->builder, "PictureDisplayWidth");
3474 gtk_widget_set_sensitive(widget, enable_disp_width);
3475 widget = GHB_WIDGET(ud->builder, "PictureDisplayHeight");
3476 gtk_widget_set_sensitive(widget, enable_disp_height);
3477 widget = GHB_WIDGET(ud->builder, "PicturePARWidth");
3478 gtk_widget_set_sensitive(widget, enable_par);
3479 widget = GHB_WIDGET(ud->builder, "PicturePARHeight");
3480 gtk_widget_set_sensitive(widget, enable_par);
3481 widget = GHB_WIDGET(ud->builder, "PictureKeepRatio");
3482 gtk_widget_set_sensitive(widget, enable_keep_aspect);
3483 widget = GHB_WIDGET(ud->builder, "autoscale");
3484 gtk_widget_set_sensitive(widget, pic_par != 1);
3488 ghb_set_scale(signal_user_data_t *ud, gint mode)
3493 gboolean keep_aspect;
3495 gboolean autocrop, autoscale, noscale;
3496 gint crop[4], width, height, par_width, par_height;
3497 gint crop_width, crop_height;
3498 gint aspect_n, aspect_d;
3499 gboolean keep_width = (mode & GHB_PIC_KEEP_WIDTH);
3500 gboolean keep_height = (mode & GHB_PIC_KEEP_HEIGHT);
3505 gint max_height = 0;
3507 g_debug("ghb_set_scale ()\n");
3508 picture_settings_deps(ud);
3509 if (h_scan == NULL) return;
3510 list = hb_get_titles( h_scan );
3511 if( !hb_list_count( list ) )
3513 /* No valid title, stop right there */
3518 titleindex = ghb_settings_combo_int(ud->settings, "title");
3519 title = hb_list_item( list, titleindex );
3520 if (title == NULL) return;
3522 if (job == NULL) return;
3524 if (ud->scale_busy) return;
3525 ud->scale_busy = TRUE;
3527 // First configure widgets
3528 mod = ghb_settings_combo_int(ud->settings, "PictureModulus");
3529 pic_par = ghb_settings_combo_int(ud->settings, "PicturePAR");
3530 keep_aspect = ghb_settings_get_boolean(ud->settings, "PictureKeepRatio");
3531 autocrop = ghb_settings_get_boolean(ud->settings, "PictureAutoCrop");
3532 autoscale = ghb_settings_get_boolean(ud->settings, "autoscale");
3533 // "Noscale" is a flag that says we prefer to crop extra to satisfy
3534 // alignment constraints rather than scaling to satisfy them.
3535 noscale = ghb_settings_get_boolean(ud->settings, "PictureLooseCrop");
3536 // Align dimensions to either 16 or 2 pixels
3537 // The scaler crashes if the dimensions are not divisible by 2
3538 // x264 also will not accept dims that are not multiple of 2
3542 keep_height = FALSE;
3544 // Step needs to be at least 2 because odd widths cause scaler crash
3546 widget = GHB_WIDGET (ud->builder, "scale_width");
3547 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
3548 widget = GHB_WIDGET (ud->builder, "scale_height");
3549 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
3552 widget = GHB_WIDGET (ud->builder, "PictureTopCrop");
3553 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
3554 widget = GHB_WIDGET (ud->builder, "PictureBottomCrop");
3555 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
3556 widget = GHB_WIDGET (ud->builder, "PictureLeftCrop");
3557 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
3558 widget = GHB_WIDGET (ud->builder, "PictureRightCrop");
3559 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
3563 widget = GHB_WIDGET (ud->builder, "PictureTopCrop");
3564 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 1, 16);
3565 widget = GHB_WIDGET (ud->builder, "PictureBottomCrop");
3566 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 1, 16);
3567 widget = GHB_WIDGET (ud->builder, "PictureLeftCrop");
3568 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 1, 16);
3569 widget = GHB_WIDGET (ud->builder, "PictureRightCrop");
3570 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 1, 16);
3572 ghb_title_info_t tinfo;
3573 ghb_get_title_info (&tinfo, titleindex);
3576 crop[0] = tinfo.crop[0];
3577 crop[1] = tinfo.crop[1];
3578 crop[2] = tinfo.crop[2];
3579 crop[3] = tinfo.crop[3];
3580 ghb_ui_update(ud, "PictureTopCrop", ghb_int64_value(crop[0]));
3581 ghb_ui_update(ud, "PictureBottomCrop", ghb_int64_value(crop[1]));
3582 ghb_ui_update(ud, "PictureLeftCrop", ghb_int64_value(crop[2]));
3583 ghb_ui_update(ud, "PictureRightCrop", ghb_int64_value(crop[3]));
3587 crop[0] = ghb_settings_get_int(ud->settings, "PictureTopCrop");
3588 crop[1] = ghb_settings_get_int(ud->settings, "PictureBottomCrop");
3589 crop[2] = ghb_settings_get_int(ud->settings, "PictureLeftCrop");
3590 crop[3] = ghb_settings_get_int(ud->settings, "PictureRightCrop");
3596 // Adjust the cropping to accomplish the desired width and height
3597 crop_width = tinfo.width - crop[2] - crop[3];
3598 crop_height = tinfo.height - crop[0] - crop[1];
3599 width = MOD_DOWN(crop_width, mod);
3600 height = MOD_DOWN(crop_height, mod);
3602 need1 = (crop_height - height) / 2;
3603 need2 = crop_height - height - need1;
3606 need1 = (crop_width - width) / 2;
3607 need2 = crop_width - width - need1;
3610 ghb_ui_update(ud, "PictureTopCrop", ghb_int64_value(crop[0]));
3611 ghb_ui_update(ud, "PictureBottomCrop", ghb_int64_value(crop[1]));
3612 ghb_ui_update(ud, "PictureLeftCrop", ghb_int64_value(crop[2]));
3613 ghb_ui_update(ud, "PictureRightCrop", ghb_int64_value(crop[3]));
3615 hb_reduce(&aspect_n, &aspect_d,
3616 title->width * title->pixel_aspect_width,
3617 title->height * title->pixel_aspect_height);
3618 crop_width = title->width - crop[2] - crop[3];
3619 crop_height = title->height - crop[0] - crop[1];
3623 height = crop_height;
3627 width = ghb_settings_get_int(ud->settings, "scale_width");
3628 height = ghb_settings_get_int(ud->settings, "scale_height");
3629 if (mode & GHB_PIC_USE_MAX)
3631 max_width = MOD_DOWN(
3632 ghb_settings_get_int(ud->settings, "PictureWidth"), mod);
3633 max_height = MOD_DOWN(
3634 ghb_settings_get_int(ud->settings, "PictureHeight"), mod);
3637 g_debug("max_width %d, max_height %d\n", max_width, max_height);
3640 width = title->width - crop[2] - crop[3];
3642 height = title->height - crop[0] - crop[1];
3644 width = MOD_ROUND(width, mod);
3645 height = MOD_ROUND(height, mod);
3647 job->anamorphic.mode = pic_par;
3650 // The scaler crashes if the dimensions are not divisible by 2
3651 // Align mod 2. And so does something in x264_encoder_headers()
3653 job->anamorphic.par_width = title->pixel_aspect_width;
3654 job->anamorphic.par_height = title->pixel_aspect_height;
3655 job->anamorphic.dar_width = 0;
3656 job->anamorphic.dar_height = 0;
3658 if (keep_height && pic_par == 2)
3659 width = ((double)height * crop_width / crop_height);
3661 job->height = height;
3662 job->maxWidth = max_width;
3663 job->maxHeight = max_height;
3664 job->crop[0] = crop[0]; job->crop[1] = crop[1];
3665 job->crop[2] = crop[2]; job->crop[3] = crop[3];
3666 if (job->anamorphic.mode == 3 && !keep_aspect)
3668 job->anamorphic.keep_display_aspect = 0;
3669 if (mode & GHB_PIC_KEEP_PAR)
3671 job->anamorphic.par_width =
3672 ghb_settings_get_int(ud->settings, "PicturePARWidth");
3673 job->anamorphic.par_height =
3674 ghb_settings_get_int(ud->settings, "PicturePARHeight");
3678 job->anamorphic.dar_width =
3679 ghb_settings_get_int(ud->settings,
3680 "PictureDisplayWidth");
3681 job->anamorphic.dar_height = height;
3686 job->anamorphic.keep_display_aspect = 1;
3688 // hb_set_anamorphic_size will adjust par, dar, and width/height
3689 // to conform to job parameters that have been set, including
3690 // maxWidth and maxHeight
3691 hb_set_anamorphic_size( job, &width, &height,
3692 &par_width, &par_height );
3693 if (job->anamorphic.mode == 3 && !keep_aspect &&
3694 mode & GHB_PIC_KEEP_PAR)
3696 // hb_set_anamorphic_size reduces the par, which we
3697 // don't want in this case because the user is
3698 // explicitely specifying it.
3699 par_width = ghb_settings_get_int(ud->settings,
3701 par_height = ghb_settings_get_int(ud->settings,
3702 "PicturePARHeight");
3707 // Adjust dims according to max values
3709 height = MIN(height, max_height);
3711 width = MIN(width, max_width);
3716 gint new_width, new_height;
3718 // Compute pixel aspect ration.
3719 par = (gdouble)(title->height * aspect_n) / (title->width * aspect_d);
3720 // Must scale so that par becomes 1:1
3721 // Try to keep largest dimension
3722 new_height = (crop_height * ((gdouble)width/crop_width) / par);
3723 new_width = (crop_width * ((gdouble)height/crop_height) * par);
3725 if (max_width && new_width > max_width)
3727 height = new_height;
3729 else if (max_height && new_height > max_height)
3733 else if (keep_width)
3735 height = new_height;
3737 else if (keep_height)
3741 else if (width > new_width)
3743 height = new_height;
3749 g_debug("new w %d h %d\n", width, height);
3751 width = MOD_ROUND(width, mod);
3752 height = MOD_ROUND(height, mod);
3754 height = MIN(height, max_height);
3756 width = MIN(width, max_width);
3757 par_width = par_height = 1;
3759 ghb_ui_update(ud, "scale_width", ghb_int64_value(width));
3760 ghb_ui_update(ud, "scale_height", ghb_int64_value(height));
3762 gint disp_width, dar_width, dar_height;
3765 disp_width = (gdouble)(width * par_width / par_height) + 0.5;
3766 hb_reduce(&dar_width, &dar_height, disp_width, height);
3768 gint iaspect = dar_width * 9 / dar_height;
3769 if (dar_width > 2 * dar_height)
3771 str = g_strdup_printf("%.2f : 1", (gdouble)dar_width / dar_height);
3773 else if (iaspect <= 16 && iaspect >= 15)
3775 str = g_strdup_printf("%.2f : 9", (gdouble)dar_width * 9 / dar_height);
3777 else if (iaspect <= 12 && iaspect >= 11)
3779 str = g_strdup_printf("%.2f : 3", (gdouble)dar_width * 3 / dar_height);
3783 str = g_strdup_printf("%d : %d", dar_width, dar_height);
3785 ghb_ui_update(ud, "display_aspect", ghb_string_value(str));
3787 ghb_ui_update(ud, "PicturePARWidth", ghb_int64_value(par_width));
3788 ghb_ui_update(ud, "PicturePARHeight", ghb_int64_value(par_height));
3789 ghb_ui_update(ud, "PictureDisplayWidth", ghb_int64_value(disp_width));
3790 ghb_ui_update(ud, "PictureDisplayHeight", ghb_int64_value(height));
3791 ud->scale_busy = FALSE;
3795 set_preview_job_settings(hb_job_t *job, GValue *settings)
3797 job->crop[0] = ghb_settings_get_int(settings, "PictureTopCrop");
3798 job->crop[1] = ghb_settings_get_int(settings, "PictureBottomCrop");
3799 job->crop[2] = ghb_settings_get_int(settings, "PictureLeftCrop");
3800 job->crop[3] = ghb_settings_get_int(settings, "PictureRightCrop");
3802 job->anamorphic.mode = ghb_settings_combo_int(settings, "PicturePAR");
3804 ghb_settings_combo_int(settings, "PictureModulus");
3805 job->width = ghb_settings_get_int(settings, "scale_width");
3806 job->height = ghb_settings_get_int(settings, "scale_height");
3807 if (ghb_settings_get_boolean(settings, "show_crop"))
3809 gdouble xscale = (gdouble)job->width /
3810 (gdouble)(job->title->width - job->crop[2] - job->crop[3]);
3811 gdouble yscale = (gdouble)job->height /
3812 (gdouble)(job->title->height - job->crop[0] - job->crop[1]);
3814 job->width += xscale * (job->crop[2] + job->crop[3]);
3815 job->height += yscale * (job->crop[0] + job->crop[1]);
3823 gboolean decomb_deint = ghb_settings_get_boolean(settings, "PictureDecombDeinterlace");
3826 gint decomb = ghb_settings_combo_int(settings, "PictureDecomb");
3827 job->deinterlace = (decomb == 0) ? 0 : 1;
3831 gint deint = ghb_settings_combo_int(settings, "PictureDeinterlace");
3832 job->deinterlace = (deint == 0) ? 0 : 1;
3835 gboolean keep_aspect;
3836 keep_aspect = ghb_settings_get_boolean(settings, "PictureKeepRatio");
3837 if (job->anamorphic.mode)
3839 job->anamorphic.par_width = job->title->pixel_aspect_width;
3840 job->anamorphic.par_height = job->title->pixel_aspect_height;
3841 job->anamorphic.dar_width = 0;
3842 job->anamorphic.dar_height = 0;
3844 if (job->anamorphic.mode == 3 && !keep_aspect)
3846 job->anamorphic.keep_display_aspect = 0;
3847 job->anamorphic.par_width =
3848 ghb_settings_get_int(settings, "PicturePARWidth");
3849 job->anamorphic.par_height =
3850 ghb_settings_get_int(settings, "PicturePARHeight");
3854 job->anamorphic.keep_display_aspect = 1;
3860 ghb_validate_filter_string(const gchar *str, gint max_fields)
3866 if (str == NULL || *str == 0) return TRUE;
3869 val = g_strtod(str, &end);
3871 { // Found a numeric value
3873 // negative max_fields means infinate
3874 if (max_fields >= 0 && fields > max_fields) return FALSE;
3888 ghb_validate_filters(signal_user_data_t *ud)
3894 gboolean decomb_deint = ghb_settings_get_boolean(ud->settings, "PictureDecombDeinterlace");
3896 index = ghb_settings_combo_int(ud->settings, "PictureDeinterlace");
3897 if (!decomb_deint && index == 1)
3899 str = ghb_settings_get_string(ud->settings, "PictureDeinterlaceCustom");
3900 if (!ghb_validate_filter_string(str, -1))
3902 message = g_strdup_printf(
3903 "Invalid Deinterlace Settings:\n\n%s\n",
3905 ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
3913 index = ghb_settings_combo_int(ud->settings, "PictureDetelecine");
3916 str = ghb_settings_get_string(ud->settings, "PictureDetelecineCustom");
3917 if (!ghb_validate_filter_string(str, -1))
3919 message = g_strdup_printf(
3920 "Invalid Detelecine Settings:\n\n%s\n",
3922 ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
3930 index = ghb_settings_combo_int(ud->settings, "PictureDecomb");
3931 if (decomb_deint && index == 1)
3933 str = ghb_settings_get_string(ud->settings, "PictureDecombCustom");
3934 if (!ghb_validate_filter_string(str, -1))
3936 message = g_strdup_printf(
3937 "Invalid Decomb Settings:\n\n%s\n",
3939 ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
3947 index = ghb_settings_combo_int(ud->settings, "PictureDenoise");
3950 str = ghb_settings_get_string(ud->settings, "PictureDenoiseCustom");
3951 if (!ghb_validate_filter_string(str, -1))
3953 message = g_strdup_printf(
3954 "Invalid Denoise Settings:\n\n%s\n",
3956 ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
3967 ghb_validate_video(signal_user_data_t *ud)
3972 mux = ghb_settings_combo_int(ud->settings, "FileFormat");
3973 vcodec = ghb_settings_combo_int(ud->settings, "VideoEncoder");
3974 if ((mux == HB_MUX_MP4) && (vcodec == HB_VCODEC_THEORA))
3976 // mp4/theora combination is not supported.
3977 message = g_strdup_printf(
3978 "Theora is not supported in the MP4 container.\n\n"
3979 "You should choose a different video codec or container.\n"
3980 "If you continue, FFMPEG will be chosen for you.");
3981 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
3987 vcodec = HB_VCODEC_FFMPEG;
3988 ghb_ui_update(ud, "VideoEncoder", ghb_int64_value(vcodec));
3994 ghb_validate_subtitles(signal_user_data_t *ud)
4000 if (h_scan == NULL) return FALSE;
4001 list = hb_get_titles( h_scan );
4002 if( !hb_list_count( list ) )
4004 /* No valid title, stop right there */
4005 g_message("No title found.\n");
4011 titleindex = ghb_settings_combo_int(ud->settings, "title");
4012 title = hb_list_item( list, titleindex );
4013 if (title == NULL) return FALSE;
4015 const GValue *slist, *settings;
4016 gint count, ii, source;
4017 gboolean burned, one_burned = FALSE;
4019 slist = ghb_settings_get_value(ud->settings, "subtitle_list");
4020 count = ghb_array_len(slist);
4021 for (ii = 0; ii < count; ii++)
4023 settings = ghb_array_get_nth(slist, ii);
4024 source = ghb_settings_get_int(settings, "SubtitleSource");
4025 burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
4026 if (burned && one_burned)
4028 // MP4 can only handle burned vobsubs. make sure there isn't
4029 // already something burned in the list
4030 message = g_strdup_printf(
4031 "Only one subtitle may be burned into the video.\n\n"
4032 "You should change your subtitle selections.\n"
4033 "If you continue, some subtitles will be lost.");
4034 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
4046 if (source == SRTSUB)
4050 filename = ghb_settings_get_string(settings, "SrtFile");
4051 if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
4053 message = g_strdup_printf(
4054 "Srt file does not exist or not a regular file.\n\n"
4055 "You should choose a valid file.\n"
4056 "If you continue, this subtitle will be ignored.");
4057 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message,
4058 "Cancel", "Continue"))
4072 ghb_select_audio_codec(GValue *settings, hb_audio_config_t *aconfig, gint acodec)
4074 gint mux = ghb_settings_combo_int(settings, "FileFormat");
4076 guint32 in_codec = aconfig ? aconfig->in.codec : HB_ACODEC_MASK;
4077 if (mux == HB_MUX_MP4)
4079 if ((acodec & in_codec & HB_ACODEC_AC3))
4081 return acodec & (in_codec | HB_ACODEC_PASS_FLAG);
4083 else if (acodec & HB_ACODEC_AC3)
4085 return HB_ACODEC_AC3;
4087 else if (acodec & HB_ACODEC_LAME)
4089 return HB_ACODEC_LAME;
4091 else if (acodec & HB_ACODEC_FAAC)
4093 return HB_ACODEC_FAAC;
4097 return HB_ACODEC_FAAC;
4102 if ((acodec & in_codec & HB_ACODEC_PASS_MASK))
4104 return acodec & (in_codec | HB_ACODEC_PASS_FLAG);
4106 else if (acodec & HB_ACODEC_AC3)
4108 return HB_ACODEC_AC3;
4110 else if (acodec & HB_ACODEC_VORBIS)
4112 return HB_ACODEC_VORBIS;
4114 else if (acodec & HB_ACODEC_LAME)
4116 return HB_ACODEC_LAME;
4118 else if (acodec & HB_ACODEC_FAAC)
4120 return HB_ACODEC_FAAC;
4124 return HB_ACODEC_LAME;
4130 ghb_validate_audio(signal_user_data_t *ud)
4137 if (h_scan == NULL) return FALSE;
4138 list = hb_get_titles( h_scan );
4139 if( !hb_list_count( list ) )
4141 /* No valid title, stop right there */
4142 g_message("No title found.\n");
4148 titleindex = ghb_settings_combo_int(ud->settings, "title");
4149 title = hb_list_item( list, titleindex );
4150 if (title == NULL) return FALSE;
4151 gint mux = ghb_settings_combo_int(ud->settings, "FileFormat");
4153 const GValue *audio_list;
4156 audio_list = ghb_settings_get_value(ud->settings, "audio_list");
4157 count = ghb_array_len(audio_list);
4158 for (ii = 0; ii < count; ii++)
4161 hb_audio_config_t *aconfig;
4163 asettings = ghb_array_get_nth(audio_list, ii);
4164 gint track = ghb_settings_combo_int(asettings, "AudioTrack");
4165 gint codec = ghb_settings_combo_int(asettings, "AudioEncoder");
4166 if (codec == HB_ACODEC_ANY)
4169 aconfig = (hb_audio_config_t *) hb_list_audio_config_item(
4170 title->list_audio, track );
4171 if ( ghb_audio_is_passthru(codec) &&
4172 !(ghb_audio_can_passthru(aconfig->in.codec) &&
4173 (aconfig->in.codec & codec)))
4175 // Not supported. AC3 is passthrough only, so input must be AC3
4176 message = g_strdup_printf(
4177 "The source does not support Pass-Thru.\n\n"
4178 "You should choose a different audio codec.\n"
4179 "If you continue, one will be chosen for you.");
4180 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
4186 if ((codec & HB_ACODEC_AC3) ||
4187 aconfig->in.codec == HB_ACODEC_DCA)
4189 codec = HB_ACODEC_AC3;
4191 else if (mux == HB_MUX_MKV)
4193 codec = HB_ACODEC_LAME;
4197 codec = HB_ACODEC_FAAC;
4199 value = ghb_lookup_acodec_value(codec);
4200 ghb_settings_take_value(asettings, "AudioEncoder", value);
4202 gchar *a_unsup = NULL;
4203 gchar *mux_s = NULL;
4204 if (mux == HB_MUX_MP4)
4207 // mp4/vorbis|DTS combination is not supported.
4208 if (codec == HB_ACODEC_VORBIS)
4211 codec = HB_ACODEC_FAAC;
4213 if (codec == HB_ACODEC_DCA)
4216 codec = HB_ACODEC_AC3;
4221 message = g_strdup_printf(
4222 "%s is not supported in the %s container.\n\n"
4223 "You should choose a different audio codec.\n"
4224 "If you continue, one will be chosen for you.", a_unsup, mux_s);
4225 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
4231 value = ghb_lookup_acodec_value(codec);
4232 ghb_settings_take_value(asettings, "AudioEncoder", value);
4235 gint mix = ghb_settings_combo_int (asettings, "AudioMixdown");
4236 gboolean allow_mono = TRUE;
4237 gboolean allow_stereo = TRUE;
4238 gboolean allow_dolby = TRUE;
4239 gboolean allow_dpl2 = TRUE;
4240 gboolean allow_6ch = TRUE;
4243 gint best = hb_get_best_mixdown(codec, aconfig->in.channel_layout, 0);
4245 allow_stereo = best >= HB_AMIXDOWN_STEREO;
4246 allow_dolby = best >= HB_AMIXDOWN_DOLBY;
4247 allow_dpl2 = best >= HB_AMIXDOWN_DOLBYPLII;
4248 allow_6ch = best >= HB_AMIXDOWN_6CH;
4250 gchar *mix_unsup = NULL;
4251 if (mix == HB_AMIXDOWN_MONO && !allow_mono)
4255 if (mix == HB_AMIXDOWN_STEREO && !allow_stereo)
4257 mix_unsup = "stereo";
4259 if (mix == HB_AMIXDOWN_DOLBY && !allow_dolby)
4261 mix_unsup = "Dolby";
4263 if (mix == HB_AMIXDOWN_DOLBYPLII && !allow_dpl2)
4265 mix_unsup = "Dolby Pro Logic II";
4267 if (mix == HB_AMIXDOWN_6CH && !allow_6ch)
4269 mix_unsup = "6 Channel";
4273 message = g_strdup_printf(
4274 "The source audio does not support %s mixdown.\n\n"
4275 "You should choose a different mixdown.\n"
4276 "If you continue, one will be chosen for you.", mix_unsup);
4277 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
4283 mix = ghb_get_best_mix(aconfig, codec, mix);
4284 value = get_amix_value(mix);
4285 ghb_settings_take_value(asettings, "AudioMixdown", value);
4292 ghb_validate_vquality(GValue *settings)
4298 if (ghb_settings_get_boolean(settings, "nocheckvquality")) return TRUE;
4299 vcodec = ghb_settings_combo_int(settings, "VideoEncoder");
4301 vquality = ghb_settings_get_double(settings, "VideoQualitySlider");
4302 if (ghb_settings_get_boolean(settings, "vquality_type_constant"))
4306 case HB_VCODEC_X264:
4312 case HB_VCODEC_FFMPEG:
4318 case HB_VCODEC_THEORA:
4330 if (vcodec == HB_VCODEC_X264 && vquality == 0.0)
4332 message = g_strdup_printf(
4333 "Warning: lossless h.264 selected\n\n"
4334 "Lossless h.264 is not well supported by\n"
4335 "many players and editors.\n\n"
4336 "It will produce enormous output files.\n\n"
4337 "Are you sure you wish to use this setting?",
4338 (gint)vquality, min, max);
4339 if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message,
4340 "Cancel", "Continue"))
4347 else if (vquality < min || vquality > max)
4349 message = g_strdup_printf(
4350 "Interesting video quality choice: %d\n\n"
4351 "Typical values range from %d to %d.\n\n"
4352 "Are you sure you wish to use this setting?",
4353 (gint)vquality, min, max);
4354 if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message,
4355 "Cancel", "Continue"))
4367 add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
4372 static gchar *x264opts;
4374 gboolean tweaks = FALSE;
4375 gchar *detel_str = NULL;
4376 gchar *decomb_str = NULL;
4377 gchar *deint_str = NULL;
4378 gchar *deblock_str = NULL;
4379 gchar *denoise_str = NULL;
4380 gchar *dest_str = NULL;
4382 g_debug("add_job()\n");
4383 if (h == NULL) return;
4384 list = hb_get_titles( h );
4385 if( !hb_list_count( list ) )
4387 /* No valid title, stop right there */
4391 title = hb_list_item( list, titleindex );
4392 if (title == NULL) return;
4394 /* Set job settings */
4396 if (job == NULL) return;
4398 job->angle = ghb_settings_get_int(js, "angle");
4399 job->start_at_preview = ghb_settings_get_int(js, "start_frame") + 1;
4400 if (job->start_at_preview)
4402 job->seek_points = ghb_settings_get_int(js, "preview_count");
4403 job->pts_to_stop = ghb_settings_get_int(js, "live_duration") * 90000LL;
4406 tweaks = ghb_settings_get_boolean(js, "allow_tweaks");
4407 job->mux = ghb_settings_combo_int(js, "FileFormat");
4408 if (job->mux == HB_MUX_MP4)
4410 job->largeFileSize = ghb_settings_get_boolean(js, "Mp4LargeFile");
4411 job->mp4_optimize = ghb_settings_get_boolean(js, "Mp4HttpOptimize");
4415 job->largeFileSize = FALSE;
4416 job->mp4_optimize = FALSE;
4418 if (!job->start_at_preview)
4421 gint num_chapters = hb_list_count(title->list_chapter);
4422 gint duration = title->duration / 90000;
4423 job->chapter_markers = FALSE;
4424 job->chapter_start = 1;
4425 job->chapter_end = num_chapters;
4427 if (ghb_settings_combo_int(js, "PtoPType") == 0)
4429 start = ghb_settings_get_int(js, "start_point");
4430 end = ghb_settings_get_int(js, "end_point");
4431 job->chapter_start = MIN( num_chapters, start );
4432 job->chapter_end = MAX( job->chapter_start, end );
4435 if (ghb_settings_combo_int(js, "PtoPType") == 1)
4437 start = ghb_settings_get_int(js, "start_point");
4438 end = ghb_settings_get_int(js, "end_point");
4439 job->pts_to_start = (int64_t)MIN(duration-1, start) * 90000;
4440 job->pts_to_stop = (int64_t)MAX(start+1, end) * 90000 -
4443 if (ghb_settings_combo_int(js, "PtoPType") == 2)
4445 start = ghb_settings_get_int(js, "start_point");
4446 end = ghb_settings_get_int(js, "end_point");
4448 max_frames = (gint64)duration * title->rate / title->rate_base;
4449 job->frame_to_start = (int64_t)MIN(max_frames-1, start-1);
4450 job->frame_to_stop = (int64_t)MAX(start, end-1) -
4451 job->frame_to_start;
4453 if (job->chapter_start != job->chapter_end)
4455 job->chapter_markers = ghb_settings_get_boolean(js, "ChapterMarkers");
4457 if (job->chapter_start == job->chapter_end)
4458 job->chapter_markers = 0;
4459 if ( job->chapter_markers )
4466 chapters = ghb_settings_get_value(js, "chapter_list");
4467 count = ghb_array_len(chapters);
4468 for(chap = 0; chap < count; chap++)
4470 hb_chapter_t * chapter_s;
4474 chapter = ghb_array_get_nth(chapters, chap);
4475 name = ghb_value_string(chapter);
4478 name = g_strdup_printf ("Chapter %2d", chap+1);
4480 chapter_s = hb_list_item( job->title->list_chapter, chap);
4481 strncpy(chapter_s->title, name, 1023);
4482 chapter_s->title[1023] = '\0';
4487 job->crop[0] = ghb_settings_get_int(js, "PictureTopCrop");
4488 job->crop[1] = ghb_settings_get_int(js, "PictureBottomCrop");
4489 job->crop[2] = ghb_settings_get_int(js, "PictureLeftCrop");
4490 job->crop[3] = ghb_settings_get_int(js, "PictureRightCrop");
4493 gboolean decomb_deint = ghb_settings_get_boolean(js, "PictureDecombDeinterlace");
4494 gint decomb = ghb_settings_combo_int(js, "PictureDecomb");
4495 gint deint = ghb_settings_combo_int(js, "PictureDeinterlace");
4497 job->deinterlace = (deint != 0) ? 1 : 0;
4499 job->deinterlace = 0;
4500 job->grayscale = ghb_settings_get_boolean(js, "VideoGrayScale");
4502 gboolean keep_aspect;
4503 keep_aspect = ghb_settings_get_boolean(js, "PictureKeepRatio");
4504 job->anamorphic.mode = ghb_settings_combo_int(js, "PicturePAR");
4505 job->modulus = ghb_settings_combo_int(js, "PictureModulus");
4506 if (job->anamorphic.mode)
4508 job->anamorphic.par_width = title->pixel_aspect_width;
4509 job->anamorphic.par_height = title->pixel_aspect_height;
4510 job->anamorphic.dar_width = 0;
4511 job->anamorphic.dar_height = 0;
4513 if (job->anamorphic.mode == 3 && !keep_aspect)
4515 job->anamorphic.keep_display_aspect = 0;
4516 job->anamorphic.par_width =
4517 ghb_settings_get_int(js, "PicturePARWidth");
4518 job->anamorphic.par_height =
4519 ghb_settings_get_int(js, "PicturePARHeight");
4523 job->anamorphic.keep_display_aspect = 1;
4527 /* Add selected filters */
4528 job->filters = hb_list_init();
4529 gint detel = ghb_settings_combo_int(js, "PictureDetelecine");
4534 if (detel_opts.map[detel].svalue != NULL)
4535 detel_str = g_strdup(detel_opts.map[detel].svalue);
4538 detel_str = ghb_settings_get_string(js, "PictureDetelecineCustom");
4539 hb_filter_detelecine.settings = detel_str;
4540 hb_list_add( job->filters, &hb_filter_detelecine );
4542 if ( decomb_deint && decomb )
4546 if (decomb_opts.map[decomb].svalue != NULL)
4547 decomb_str = g_strdup(decomb_opts.map[decomb].svalue);
4550 decomb_str = ghb_settings_get_string(js, "PictureDecombCustom");
4551 hb_filter_decomb.settings = decomb_str;
4552 hb_list_add( job->filters, &hb_filter_decomb );
4554 if( job->deinterlace )
4558 if (deint_opts.map[deint].svalue != NULL)
4559 deint_str = g_strdup(deint_opts.map[deint].svalue);
4562 deint_str = ghb_settings_get_string(js, "PictureDeinterlaceCustom");
4563 hb_filter_deinterlace.settings = deint_str;
4564 hb_list_add( job->filters, &hb_filter_deinterlace );
4566 gint deblock = ghb_settings_get_int(js, "PictureDeblock");
4569 deblock_str = g_strdup_printf("%d", deblock);
4570 hb_filter_deblock.settings = deblock_str;
4571 hb_list_add( job->filters, &hb_filter_deblock );
4573 gint denoise = ghb_settings_combo_int(js, "PictureDenoise");
4578 if (denoise_opts.map[denoise].svalue != NULL)
4579 denoise_str = g_strdup(denoise_opts.map[denoise].svalue);
4582 denoise_str = ghb_settings_get_string(js, "PictureDenoiseCustom");
4583 hb_filter_denoise.settings = denoise_str;
4584 hb_list_add( job->filters, &hb_filter_denoise );
4586 job->width = ghb_settings_get_int(js, "scale_width");
4587 job->height = ghb_settings_get_int(js, "scale_height");
4589 job->vcodec = ghb_settings_combo_int(js, "VideoEncoder");
4590 if ((job->mux == HB_MUX_MP4 ) && (job->vcodec == HB_VCODEC_THEORA))
4592 // mp4/theora combination is not supported.
4593 job->vcodec = HB_VCODEC_FFMPEG;
4595 if ((job->vcodec == HB_VCODEC_X264) && (job->mux == HB_MUX_MP4))
4597 job->ipod_atom = ghb_settings_get_boolean(js, "Mp4iPodCompatible");
4599 if (ghb_settings_get_boolean(js, "vquality_type_constant"))
4602 vquality = ghb_settings_get_double(js, "VideoQualitySlider");
4603 job->vquality = vquality;
4606 else if (ghb_settings_get_boolean(js, "vquality_type_bitrate"))
4608 job->vquality = -1.0;
4609 job->vbitrate = ghb_settings_get_int(js, "VideoAvgBitrate");
4612 gint vrate = ghb_settings_combo_int(js, "VideoFramerate");
4615 job->vrate = title->rate;
4616 job->vrate_base = title->rate_base;
4620 job->vrate = 27000000;
4621 job->vrate_base = vrate;
4623 if (ghb_settings_get_boolean(js, "VideoFrameratePFR"))
4625 else if (ghb_settings_get_boolean(js, "VideoFramerateCFR"))
4630 const GValue *audio_list;
4634 audio_list = ghb_settings_get_value(js, "audio_list");
4635 count = ghb_array_len(audio_list);
4636 for (ii = 0; ii < count; ii++)
4639 hb_audio_config_t audio;
4640 hb_audio_config_t *aconfig;
4643 hb_audio_config_init(&audio);
4644 asettings = ghb_array_get_nth(audio_list, ii);
4645 audio.in.track = ghb_settings_get_int(asettings, "AudioTrack");
4646 audio.out.track = tcount;
4648 aconfig = (hb_audio_config_t *) hb_list_audio_config_item(
4649 title->list_audio, audio.in.track );
4651 acodec = ghb_settings_combo_int(asettings, "AudioEncoder");
4652 audio.out.codec = ghb_select_audio_codec(js, aconfig, acodec);
4654 audio.out.dynamic_range_compression =
4655 ghb_settings_get_double(asettings, "AudioTrackDRCSlider");
4656 if (audio.out.dynamic_range_compression < 1.0)
4657 audio.out.dynamic_range_compression = 0.0;
4659 // It would be better if this were done in libhb for us, but its not yet.
4660 if (ghb_audio_is_passthru(audio.out.codec))
4662 audio.out.mixdown = 0;
4666 audio.out.mixdown = ghb_settings_combo_int(asettings, "AudioMixdown");
4667 // Make sure the mixdown is valid and pick a new one if not.
4668 audio.out.mixdown = ghb_get_best_mix(aconfig, audio.out.codec,
4671 ghb_settings_combo_int(asettings, "AudioBitrate");
4672 gint srate = ghb_settings_combo_int(asettings, "AudioSamplerate");
4673 if (srate == 0) // 0 is same as source
4674 audio.out.samplerate = aconfig->in.samplerate;
4676 audio.out.samplerate = srate;
4678 audio.out.bitrate = hb_get_best_audio_bitrate(
4679 audio.out.codec, audio.out.bitrate,
4680 audio.out.samplerate, audio.out.mixdown);
4683 // Add it to the jobs audio list
4684 hb_audio_add( job, &audio );
4688 dest_str = ghb_settings_get_string(js, "destination");
4689 job->file = dest_str;
4691 const GValue *subtitle_list;
4693 gboolean force, burned, def, one_burned = FALSE;
4695 ghb_settings_set_boolean(js, "subtitle_scan", FALSE);
4696 subtitle_list = ghb_settings_get_value(js, "subtitle_list");
4697 count = ghb_array_len(subtitle_list);
4698 for (ii = 0; ii < count; ii++)
4703 ssettings = ghb_array_get_nth(subtitle_list, ii);
4705 force = ghb_settings_get_boolean(ssettings, "SubtitleForced");
4706 burned = ghb_settings_get_boolean(ssettings, "SubtitleBurned");
4707 def = ghb_settings_get_boolean(ssettings, "SubtitleDefaultTrack");
4708 source = ghb_settings_get_int(ssettings, "SubtitleSource");
4710 if (source == SRTSUB)
4712 hb_subtitle_config_t sub_config;
4713 gchar *filename, *lang, *code;
4715 filename = ghb_settings_get_string(ssettings, "SrtFile");
4716 if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
4720 sub_config.offset = ghb_settings_get_int(ssettings, "SrtOffset");
4721 lang = ghb_settings_get_string(ssettings, "SrtLanguage");
4722 code = ghb_settings_get_string(ssettings, "SrtCodeset");
4723 strncpy(sub_config.src_filename, filename, 255);
4724 sub_config.src_filename[255] = 0;
4725 strncpy(sub_config.src_codeset, code, 39);
4726 sub_config.src_codeset[39] = 0;
4727 sub_config.force = 0;
4728 sub_config.dest = PASSTHRUSUB;
4729 sub_config.default_track = def;
4731 hb_srt_add( job, &sub_config, lang);
4739 subtitle = ghb_settings_get_int(ssettings, "SubtitleTrack");
4744 job->select_subtitle_config.dest = PASSTHRUSUB;
4748 // Only allow one subtitle to be burned into the video
4751 job->select_subtitle_config.dest = RENDERSUB;
4754 job->select_subtitle_config.force = force;
4755 job->select_subtitle_config.default_track = def;
4756 job->indepth_scan = 1;
4757 ghb_settings_set_boolean(js, "subtitle_scan", TRUE);
4759 else if (subtitle >= 0)
4761 hb_subtitle_t * subt;
4762 hb_subtitle_config_t sub_config;
4764 subt = (hb_subtitle_t *)hb_list_item(title->list_subtitle, subtitle);
4767 sub_config = subt->config;
4770 sub_config.dest = PASSTHRUSUB;
4772 else if ( burned && canBurn(subt->source) )
4774 // Only allow one subtitle to be burned into the video
4777 sub_config.dest = RENDERSUB;
4780 sub_config.force = force;
4781 sub_config.default_track = def;
4782 hb_subtitle_add( job, &sub_config, subtitle );
4787 // TODO: libhb holds onto a reference to the x264opts and is not
4788 // finished with it until encoding the job is done. But I can't
4789 // find a way to get at the job before it is removed in order to
4790 // free up the memory I am allocating here.
4791 // The short story is THIS LEAKS.
4792 x264opts = ghb_build_x264opts_string(js);
4794 if( *x264opts == '\0' )
4800 if (job->indepth_scan == 1)
4802 // Subtitle scan. Look for subtitle matching audio language
4805 * When subtitle scan is enabled do a fast pre-scan job
4806 * which will determine which subtitles to enable, if any.
4809 job->indepth_scan = 1;
4810 job->x264opts = NULL;
4813 * Add the pre-scan job
4815 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
4819 if( ghb_settings_get_boolean(js, "VideoTwoPass") &&
4820 !ghb_settings_get_boolean(js, "vquality_type_constant"))
4823 * If subtitle_scan is enabled then only turn it on
4824 * for the second pass and then off again for the
4828 job->indepth_scan = 0;
4831 * If turbo options have been selected then append them
4832 * to the x264opts now (size includes one ':' and the '\0')
4834 if( ghb_settings_get_boolean(js, "VideoTurboTwoPass") )
4836 gchar *tmp_x264opts;
4840 badapt = ghb_lookup_badapt(x264opts);
4843 extra_opts = g_strdup_printf("%s", turbo_opts);
4847 extra_opts = g_strdup_printf("%s:weightb=0", turbo_opts);
4852 tmp_x264opts = g_strdup_printf("%s:%s", x264opts, extra_opts);
4857 * No x264opts to modify, but apply the turbo options
4858 * anyway as they may be modifying defaults
4860 tmp_x264opts = g_strdup_printf("%s", extra_opts);
4864 job->x264opts = tmp_x264opts;
4868 job->x264opts = x264opts;
4870 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
4872 //if (job->x264opts != NULL)
4873 // g_free(job->x264opts);
4877 * On the second pass we turn off subtitle scan so that we
4878 * can actually encode using any subtitles that were auto
4879 * selected in the first pass (using the whacky select-subtitle
4880 * attribute of the job).
4882 job->indepth_scan = 0;
4883 job->x264opts = x264opts;
4884 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
4886 //if (job->x264opts != NULL)
4887 // g_free(job->x264opts);
4891 job->x264opts = x264opts;
4892 job->indepth_scan = 0;
4894 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
4896 //if (job->x264opts != NULL)
4897 // g_free(job->x264opts);
4900 // clean up audio list
4901 gint num_audio_tracks = hb_list_count(job->list_audio);
4902 for(ii = 0; ii < num_audio_tracks; ii++)
4904 hb_audio_t *audio = (hb_audio_t*)hb_list_item(job->list_audio, 0);
4905 hb_list_rem(job->list_audio, audio);
4909 // clean up subtitle list
4910 gint num_subtitle_tracks = hb_list_count(job->list_subtitle);
4911 for(ii = 0; ii < num_subtitle_tracks; ii++)
4913 hb_subtitle_t *subtitle = hb_list_item(job->list_subtitle, 0);
4914 hb_list_rem(job->list_subtitle, subtitle);
4918 if (detel_str) g_free(detel_str);
4919 if (decomb_str) g_free(decomb_str);
4920 if (deint_str) g_free(deint_str);
4921 if (deblock_str) g_free(deblock_str);
4922 if (denoise_str) g_free(denoise_str);
4923 if (dest_str) g_free(dest_str);
4927 ghb_add_job(GValue *js, gint unique_id)
4929 // Since I'm doing a scan of the single title I want just prior
4930 // to adding the job, there is only the one title to choose from.
4931 add_job(h_queue, js, unique_id, 0);
4935 ghb_add_live_job(GValue *js, gint unique_id)
4937 // Since I'm doing a scan of the single title I want just prior
4938 // to adding the job, there is only the one title to choose from.
4939 gint titleindex = ghb_settings_combo_int(js, "title");
4940 add_job(h_scan, js, unique_id, titleindex);
4944 ghb_remove_job(gint unique_id)
4949 // Multiples passes all get the same id
4951 // Go backwards through list, so reordering doesn't screw me.
4952 ii = hb_count(h_queue) - 1;
4953 while ((job = hb_job(h_queue, ii--)) != NULL)
4955 if ((job->sequence_id & 0xFFFFFF) == unique_id)
4956 hb_rem(h_queue, job);
4963 hb_start( h_queue );
4973 ghb_start_live_encode()
4979 ghb_stop_live_encode()
4988 hb_get_state2( h_queue, &s );
4990 if( s.state == HB_STATE_PAUSED )
4992 hb_status.queue.state &= ~GHB_STATE_PAUSED;
4993 hb_resume( h_queue );
4997 hb_status.queue.state |= GHB_STATE_PAUSED;
4998 hb_pause( h_queue );
5013 guint8 *pixels = gdk_pixbuf_get_pixels (pb);
5016 gint channels = gdk_pixbuf_get_n_channels (pb);
5017 gint stride = gdk_pixbuf_get_rowstride (pb);
5019 for (jj = 0; jj < width; jj++)
5021 dst = pixels + y * stride + (x+jj) * channels;
5022 for (ii = 0; ii < len; ii++)
5043 guint8 *pixels = gdk_pixbuf_get_pixels (pb);
5046 gint channels = gdk_pixbuf_get_n_channels (pb);
5047 gint stride = gdk_pixbuf_get_rowstride (pb);
5049 for (jj = 0; jj < width; jj++)
5051 dst = pixels + (y+jj) * stride + x * channels;
5052 for (ii = 0; ii < len; ii++)
5073 gint line_width = 8;
5080 {{0x80, 0x80, 0x80},{0xC0, 0x80, 0x70},{0x80, 0xA0, 0x80},{0x70, 0x80, 0xA0}};
5085 for (ii = x, jj = 0; ii+line_width < x+w; ii += step, jj++)
5087 vert_line(pb, c[jj&3].r, c[jj&3].g, c[jj&3].b, ii, y, h, line_width);
5093 for (ii = y, jj = 0; ii+line_width < y+h; ii += step, jj++)
5095 horz_line(pb, c[jj&3].r, c[jj&3].g, c[jj&3].b, x, ii, w, line_width);
5101 ghb_get_preview_image(
5104 signal_user_data_t *ud,
5112 settings = ud->settings;
5113 list = hb_get_titles( h_scan );
5114 if( !hb_list_count( list ) )
5116 /* No valid title, stop right there */
5119 title = hb_list_item( list, titleindex );
5120 if (title == NULL) return NULL;
5121 if (title->job == NULL) return NULL;
5122 set_preview_job_settings(title->job, settings);
5124 // hb_get_preview doesn't compensate for anamorphic, so lets
5125 // calculate scale factors
5126 gint width, height, par_width = 1, par_height = 1;
5127 gint pic_par = ghb_settings_combo_int(settings, "PicturePAR");
5130 hb_set_anamorphic_size( title->job, &width, &height,
5131 &par_width, &par_height );
5134 // Make sure we have a big enough buffer to receive the image from libhb
5135 gint dstWidth = title->job->width;
5136 gint dstHeight= title->job->height;
5138 static guint8 *buffer = NULL;
5139 static gint bufferSize = 0;
5142 newSize = dstWidth * dstHeight * 4;
5143 if( bufferSize < newSize )
5145 bufferSize = newSize;
5146 buffer = (guint8*) g_realloc( buffer, bufferSize );
5148 hb_get_preview( h_scan, title, index, buffer );
5150 // Create an GdkPixbuf and copy the libhb image into it, converting it from
5151 // libhb's format something suitable.
5153 // The image data returned by hb_get_preview is 4 bytes per pixel,
5154 // BGRA format. Alpha is ignored.
5156 GdkPixbuf *preview = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, dstWidth, dstHeight);
5157 guint8 *pixels = gdk_pixbuf_get_pixels (preview);
5159 guint32 *src = (guint32*)buffer;
5160 guint8 *dst = pixels;
5163 gint channels = gdk_pixbuf_get_n_channels (preview);
5164 gint stride = gdk_pixbuf_get_rowstride (preview);
5167 for (ii = 0; ii < dstHeight; ii++)
5170 for (jj = 0; jj < dstWidth; jj++)
5172 tmp[0] = src[0] >> 16;
5173 tmp[1] = src[0] >> 8;
5174 tmp[2] = src[0] >> 0;
5180 gint w = ghb_settings_get_int(settings, "scale_width");
5181 gint h = ghb_settings_get_int(settings, "scale_height");
5182 ghb_par_scale(ud, &w, &h, par_width, par_height);
5184 gint c0, c1, c2, c3;
5185 c0 = ghb_settings_get_int(settings, "PictureTopCrop");
5186 c1 = ghb_settings_get_int(settings, "PictureBottomCrop");
5187 c2 = ghb_settings_get_int(settings, "PictureLeftCrop");
5188 c3 = ghb_settings_get_int(settings, "PictureRightCrop");
5190 gdouble xscale = (gdouble)w / (gdouble)(title->width - c2 - c3);
5191 gdouble yscale = (gdouble)h / (gdouble)(title->height - c0 - c1);
5193 ghb_par_scale(ud, &dstWidth, &dstHeight, par_width, par_height);
5196 if (ghb_settings_get_boolean(settings, "reduce_hd_preview"))
5200 gint orig_w, orig_h;
5203 if (ghb_settings_get_boolean(settings, "preview_fullscreen"))
5207 ss = gdk_screen_get_default();
5208 s_w = gdk_screen_get_width(ss);
5209 s_h = gdk_screen_get_height(ss);
5213 if (dstWidth > s_w * factor / 100)
5215 dstWidth = s_w * factor / 100;
5216 dstHeight = dstHeight * dstWidth / orig_w;
5218 if (dstHeight > s_h * factor / 100)
5220 dstHeight = s_h * factor / 100;
5221 dstWidth = dstWidth * dstHeight / orig_h;
5223 xscale *= (gdouble)dstWidth / orig_w;
5224 yscale *= (gdouble)dstHeight / orig_h;
5225 w *= (gdouble)dstWidth / orig_w;
5226 h *= (gdouble)dstHeight / orig_h;
5228 GdkPixbuf *scaled_preview;
5229 scaled_preview = gdk_pixbuf_scale_simple(preview, dstWidth, dstHeight, GDK_INTERP_HYPER);
5230 if (ghb_settings_get_boolean(settings, "show_crop"))
5237 hash_pixbuf(scaled_preview, c2, 0, w, c0, 32, 0);
5239 hash_pixbuf(scaled_preview, c2, dstHeight-c1, w, c1, 32, 0);
5241 hash_pixbuf(scaled_preview, 0, c0, c2, h, 32, 1);
5243 hash_pixbuf(scaled_preview, dstWidth-c3, c0, c3, h, 32, 1);
5245 g_object_unref (preview);
5246 return scaled_preview;
5250 sanitize_volname(gchar *name)
5275 ghb_dvd_volname(const gchar *device)
5278 name = hb_dvd_name((gchar*)device);
5279 if (name != NULL && name[0] != 0)
5281 name = g_strdup(name);
5282 sanitize_volname(name);