4 #include <glib/gstdio.h>
8 static GValue *defaults;
16 static value_map_t vcodec_xlat[] =
18 {"MPEG-4 (FFmpeg)", "ffmpeg"},
19 {"MPEG-4 (XviD)", "xvid"},
20 {"H.264 (x264)", "x264"},
21 {"VP3 (Theora)", "theora"},
25 static value_map_t acodec_xlat[] =
27 {"AAC (faac)", "faac"},
28 {"AC3 Passthru", "ac3"},
29 {"MP3 (lame)", "lame"},
30 {"Vorbis (vorbis)", "vorbis"},
34 static value_map_t subtitle_xlat[] =
40 { "Abkhazian", "abk" },
41 { "Afrikaans", "afr" },
43 { "Albanian", "sqi" },
46 { "Aragonese", "arg" },
47 { "Armenian", "hye" },
48 { "Assamese", "asm" },
52 { "Azerbaijani", "aze" },
56 { "Belarusian", "bel" },
62 { "Bulgarian", "bul" },
65 { "Chamorro", "cha" },
68 { "Church Slavic", "chu" },
71 { "Corsican", "cos" },
77 { "Dzongkha", "dzo" },
79 { "Esperanto", "epo" },
80 { "Estonian", "est" },
86 { "Western Frisian", "fry" },
88 { "Georgian", "kat" },
90 { "Gaelic (Scots)", "gla" },
92 { "Galician", "glg" },
94 { "Greek, Modern", "ell" },
96 { "Gujarati", "guj" },
102 { "Hiri Motu", "hmo" },
103 { "Hungarian", "hun" },
105 { "Icelandic", "isl" },
107 { "Sichuan Yi", "iii" },
108 { "Inuktitut", "iku" },
109 { "Interlingue", "ile" },
110 { "Interlingua", "ina" },
111 { "Indonesian", "ind" },
112 { "Inupiaq", "ipk" },
113 { "Italian", "ita" },
114 { "Javanese", "jav" },
115 { "Japanese", "jpn" },
116 { "Kalaallisut", "kal" },
117 { "Kannada", "kan" },
118 { "Kashmiri", "kas" },
121 { "Central Khmer", "khm" },
123 { "Kinyarwanda", "kin" },
124 { "Kirghiz", "kir" },
128 { "Kuanyama", "kua" },
129 { "Kurdish", "kur" },
132 { "Latvian", "lav" },
133 { "Limburgan", "lim" },
134 { "Lingala", "lin" },
135 { "Lithuanian", "lit" },
136 { "Luxembourgish", "ltz" },
137 { "Luba-Katanga", "lub" },
139 { "Macedonian", "mkd" },
140 { "Marshallese", "mah" },
141 { "Malayalam", "mal" },
143 { "Marathi", "mar" },
145 { "Malagasy", "mlg" },
146 { "Maltese", "mlt" },
147 { "Moldavian", "mol" },
148 { "Mongolian", "mon" },
151 { "Ndebele, South", "nbl" },
152 { "Ndebele, North", "nde" },
155 { "Norwegian Nynorsk", "nno" },
156 { "Norwegian Bokmål", "nob" },
157 { "Norwegian", "nor" },
158 { "Chichewa; Nyanja", "nya" },
159 { "Occitan", "oci" },
163 { "Ossetian", "oss" },
164 { "Panjabi", "pan" },
165 { "Persian", "fas" },
168 { "Portuguese", "por" },
170 { "Quechua", "que" },
171 { "Romansh", "roh" },
172 { "Romanian", "ron" },
174 { "Russian", "rus" },
176 { "Sanskrit", "san" },
177 { "Serbian", "srp" },
178 { "Croatian", "hrv" },
179 { "Sinhala", "sin" },
181 { "Slovenian", "slv" },
182 { "Northern Sami", "sme" },
187 { "Sotho, Southern", "sot" },
188 { "Spanish", "spa" },
189 { "Sardinian", "srd" },
191 { "Sundanese", "sun" },
192 { "Swahili", "swa" },
193 { "Swedish", "swe" },
194 { "Tahitian", "tah" },
199 { "Tagalog", "tgl" },
201 { "Tibetan", "bod" },
202 { "Tigrinya", "tir" },
206 { "Turkmen", "tuk" },
207 { "Turkish", "tur" },
210 { "Ukrainian", "ukr" },
214 { "Vietnamese", "vie" },
215 { "Volapük", "vol" },
217 { "Walloon", "wln" },
220 { "Yiddish", "yid" },
227 value_map_t container_xlat[] =
237 value_map_t framerate_xlat[] =
239 {"Same as source", "source"},
244 {"23.976", "23.976"},
251 value_map_t samplerate_xlat[] =
262 value_map_t mix_xlat[] =
265 {"Stereo", "stereo"},
266 {"Dolby Surround", "dpl1"},
267 {"Dolby Pro Logic II", "dpl2"},
268 {"6-channel discrete", "6ch"},
269 {"AC3 Passthru", "none"},
273 value_map_t deint_xlat[] =
282 value_map_t denoise_xlat[] =
295 value_map_t *value_map;
299 key_map_t key_map[] =
301 {"Audio1Bitrate", NULL, NULL, FALSE},
302 {"Audio1Encoder", NULL, NULL, FALSE},
303 {"Audio1Mixdown", NULL, NULL, FALSE},
304 {"Audio1Samplerate", NULL, NULL, FALSE},
305 {"Audio1Track", NULL, NULL, FALSE},
306 {"Audio1TrackDescription", NULL, NULL, FALSE},
307 {"Audio1TrackDRCSlider", NULL, NULL, FALSE},
308 {"Audio2Bitrate", NULL, NULL, FALSE},
309 {"Audio2Encoder", NULL, NULL, FALSE},
310 {"Audio2Mixdown", NULL, NULL, FALSE},
311 {"Audio2Samplerate", NULL, NULL, FALSE},
312 {"Audio2Track", NULL, NULL, FALSE},
313 {"Audio2TrackDescription", NULL, NULL, FALSE},
314 {"Audio2TrackDRCSlider", NULL, NULL, FALSE},
315 {"ChapterMarkers", "chapter_markers", NULL, FALSE},
316 {"Default", "Default", NULL, FALSE},
317 {"FileFormat", "container", container_xlat, FALSE},
318 {"Folder", NULL, NULL, TRUE},
319 {"Mp4HttpOptimize", "http_optimize_mp4", NULL, FALSE},
320 {"Mp4iPodCompatible", "ipod_file", NULL, FALSE},
321 {"Mp4LargeFile", "large_mp4", NULL, FALSE},
322 {"PictureAutoCrop", "autocrop", NULL, FALSE},
323 {"PictureBottomCrop", NULL, NULL, TRUE},
324 {"PictureDeblock", "deblock", NULL, FALSE},
325 {"PictureDecomb", "decomb", NULL, FALSE},
326 {"PictureDeinterlace", "deinterlace", deint_xlat, FALSE},
327 {"PictureDenoise", "denoise", denoise_xlat, FALSE},
328 {"PictureDetelecine", "detelecine", NULL, FALSE},
329 {"PictureHeight", "max_height", NULL, FALSE},
330 {"PictureKeepRatio", "keep_aspect", NULL, FALSE},
331 {"PictureLeftCrop", NULL, NULL, TRUE},
332 {"PicturePAR", NULL, NULL, FALSE},
333 {"PictureRightCrop", NULL, NULL, TRUE},
334 {"PictureTopCrop", NULL, NULL, TRUE},
335 {"PictureWidth", "max_width", NULL, FALSE},
336 {"PresetDescription", "preset_description", NULL, FALSE},
337 {"PresetName", "preset_name", NULL, FALSE},
338 {"Subtitles", "subtitle_lang", subtitle_xlat, FALSE},
339 {"SubtitlesForced", "forced_subtitles", NULL, FALSE},
340 {"Type", NULL, NULL, TRUE},
341 {"UsesMaxPictureSettings", NULL, NULL, FALSE},
342 {"UsesPictureFilters", NULL, NULL, TRUE},
343 {"UsesPictureSettings", NULL, NULL, FALSE},
344 {"VFR", NULL, NULL, TRUE},
345 {"VideoAvgBitrate", "video_bitrate", NULL, FALSE},
346 {"VideoEncoder", "video_codec", vcodec_xlat, FALSE},
347 {"VideoFramerate", "framerate", framerate_xlat, FALSE},
348 {"VideoGrayScale", "grayscale", NULL, FALSE},
349 {"VideoQualitySlider", NULL, NULL, FALSE},
350 {"VideoQualityType", NULL, NULL, FALSE},
351 {"VideoTargetSize", "video_target_size", NULL, FALSE},
352 {"VideoTwoPass", "two_pass", NULL, FALSE},
353 {"VideoTurboTwoPass", "turbo", NULL, FALSE},
354 {"x264Option", "x264_options", NULL, FALSE},
359 key_xlat(key_map_t *key_map, const gchar *mac_key)
363 for (ii = 0; key_map[ii].mac_key; ii++)
365 if (strcmp(mac_key, key_map[ii].mac_key) == 0)
367 if (key_map[ii].ignore)
372 g_warning("Unrecognized key: (%s)", mac_key);
383 GValue *gval, *def_val;
384 const gchar *lin_key = key_map[key_index].lin_key;
385 value_map_t *value_map = key_map[key_index].value_map;
387 def_val = ghb_dict_lookup(defaults, lin_key);
396 str = ghb_value_string(mac_val);
397 for (ii = 0; value_map[ii].mac_val; ii++)
399 if (strcmp(str, value_map[ii].mac_val) == 0)
401 sval = ghb_string_value_new(value_map[ii].lin_val);
403 gval = ghb_value_new(G_VALUE_TYPE(def_val));
404 if (!g_value_transform(sval, gval))
406 g_warning("1 can't transform");
407 ghb_value_free(gval);
408 ghb_value_free(sval);
411 ghb_value_free(sval);
415 g_warning("Can't map value: (%s)", str);
420 gval = ghb_value_new(G_VALUE_TYPE(def_val));
421 if (!g_value_transform(mac_val, gval))
423 g_warning("2 can't transform");
424 ghb_value_free(gval);
432 g_warning("Bad key: (%s)", lin_key);
438 key_map_t audio_key_map[] =
440 {"Audio1Bitrate", "audio_bitrate", NULL, FALSE},
441 {"Audio1Encoder", "audio_codec", acodec_xlat, FALSE},
442 {"Audio1Mixdown", "audio_mix", mix_xlat, FALSE},
443 {"Audio1Samplerate", "audio_rate", samplerate_xlat, FALSE},
444 {"Audio1Track", NULL, NULL, TRUE},
445 {"Audio1TrackDescription", NULL, NULL, TRUE},
446 {"Audio1TrackDRCSlider", "audio_drc", NULL, FALSE},
447 {"Audio2Bitrate", "audio_bitrate", NULL, FALSE},
448 {"Audio2Encoder", "audio_codec", acodec_xlat, FALSE},
449 {"Audio2Mixdown", "audio_mix", mix_xlat, FALSE},
450 {"Audio2Samplerate", "audio_rate", samplerate_xlat, FALSE},
451 {"Audio2Track", NULL, NULL, TRUE},
452 {"Audio2TrackDescription", NULL, NULL, TRUE},
453 {"Audio2TrackDRCSlider", "audio_drc", NULL, FALSE},
458 hard_value_xlat(GValue *lin_dict, const gchar *mac_key, GValue *mac_val)
460 if (strcmp(mac_key, "VideoQualitySlider") == 0)
464 vquality = (ghb_value_double(mac_val) + 0.005) * 100.0;
465 ghb_dict_insert(lin_dict, "video_quality",
466 ghb_int_value_new(vquality));
468 else if (strcmp(mac_key, "UsesMaxPictureSettings") == 0)
472 gval = ghb_dict_lookup(lin_dict, "autoscale");
473 if (gval == NULL && ghb_value_boolean(mac_val))
475 ghb_dict_insert(lin_dict, "autoscale", ghb_boolean_value_new(TRUE));
478 else if (strcmp(mac_key, "UsesPictureSettings") == 0)
482 gval = ghb_dict_lookup(lin_dict, "autoscale");
483 if (gval == NULL && ghb_value_int(mac_val) == 2)
485 ghb_dict_insert(lin_dict, "autoscale", ghb_boolean_value_new(TRUE));
488 else if (strcmp(mac_key, "PicturePAR") == 0)
492 ana = ghb_value_int(mac_val);
497 ghb_dict_insert(lin_dict, "anamorphic",
498 ghb_boolean_value_new(FALSE));
499 ghb_dict_insert(lin_dict, "round_dimensions",
500 ghb_boolean_value_new(TRUE));
504 ghb_dict_insert(lin_dict, "anamorphic",
505 ghb_boolean_value_new(TRUE));
506 ghb_dict_insert(lin_dict, "round_dimensions",
507 ghb_boolean_value_new(FALSE));
511 ghb_dict_insert(lin_dict, "anamorphic",
512 ghb_boolean_value_new(TRUE));
513 ghb_dict_insert(lin_dict, "round_dimensions",
514 ghb_boolean_value_new(TRUE));
518 ghb_dict_insert(lin_dict, "anamorphic",
519 ghb_boolean_value_new(TRUE));
520 ghb_dict_insert(lin_dict, "round_dimensions",
521 ghb_boolean_value_new(TRUE));
525 else if (strcmp(mac_key, "VideoQualityType") == 0)
527 // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
530 vqtype = ghb_value_int(mac_val);
535 ghb_dict_insert(lin_dict, "vquality_type_target",
536 ghb_boolean_value_new(TRUE));
537 ghb_dict_insert(lin_dict, "vquality_type_bitrate",
538 ghb_boolean_value_new(FALSE));
539 ghb_dict_insert(lin_dict, "vquality_type_constant",
540 ghb_boolean_value_new(FALSE));
544 ghb_dict_insert(lin_dict, "vquality_type_target",
545 ghb_boolean_value_new(FALSE));
546 ghb_dict_insert(lin_dict, "vquality_type_bitrate",
547 ghb_boolean_value_new(TRUE));
548 ghb_dict_insert(lin_dict, "vquality_type_constant",
549 ghb_boolean_value_new(FALSE));
553 ghb_dict_insert(lin_dict, "vquality_type_target",
554 ghb_boolean_value_new(FALSE));
555 ghb_dict_insert(lin_dict, "vquality_type_bitrate",
556 ghb_boolean_value_new(FALSE));
557 ghb_dict_insert(lin_dict, "vquality_type_constant",
558 ghb_boolean_value_new(TRUE));
562 ghb_dict_insert(lin_dict, "vquality_type_target",
563 ghb_boolean_value_new(FALSE));
564 ghb_dict_insert(lin_dict, "vquality_type_bitrate",
565 ghb_boolean_value_new(FALSE));
566 ghb_dict_insert(lin_dict, "vquality_type_constant",
567 ghb_boolean_value_new(TRUE));
574 GValue *audio_defaults;
576 audio_defaults = ghb_array_get_nth(
577 ghb_dict_lookup(defaults, "pref_audio_list"), 0);
578 key_index = key_xlat(audio_key_map, mac_key);
581 gint audio_index, count, ii;
582 GValue *alist, *adict, *val;
584 audio_index = mac_key[5] - '1';
585 alist = ghb_dict_lookup(lin_dict, "pref_audio_list");
588 alist = ghb_array_value_new(8);
589 ghb_dict_insert(lin_dict, "pref_audio_list", alist);
591 count = ghb_array_len(alist);
592 for (ii = count; ii <= audio_index; ii++)
594 adict = ghb_value_dup(audio_defaults);
595 ghb_array_append(alist, adict);
597 adict = ghb_array_get_nth(alist, audio_index);
598 val = value_xlat(audio_defaults, audio_key_map, key_index, mac_val);
601 ghb_dict_insert(adict,
602 g_strdup(audio_key_map[key_index].lin_key), val);
609 parse_preset_dict(GValue *mac_dict, GValue *lin_dict)
613 GValue *mac_val, *val;
615 ghb_dict_iter_init(&iter, mac_dict);
616 // middle (void*) cast prevents gcc warning "defreferencing type-punned
617 // pointer will break strict-aliasing rules"
618 while (g_hash_table_iter_next(
619 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&mac_val))
623 key_index = key_xlat(key_map, key);
625 { // The simple translations
626 if (key_map[key_index].lin_key)
628 val = value_xlat(defaults, key_map, key_index, mac_val);
631 ghb_dict_insert(lin_dict,
632 g_strdup(key_map[key_index].lin_key), val);
637 hard_value_xlat(lin_dict, key, mac_val);
644 parse_preset_array(GValue *mac_array, GValue *lin_array)
647 GValue *mac_dict, *lin_dict, *gval;
649 count = ghb_array_len(mac_array);
650 for (ii = 0; ii < count; ii++)
652 mac_dict = ghb_array_get_nth(mac_array, ii);
654 // Only process builtin types
655 if (ghb_value_int(ghb_dict_lookup(mac_dict, "Type")) != 0)
658 lin_dict = ghb_dict_value_new();
659 ghb_array_append(lin_array, lin_dict);
660 gval = ghb_dict_lookup(mac_dict, "PresetName");
663 ghb_dict_insert(lin_dict, g_strdup("preset_name"),
664 ghb_value_dup(gval));
666 gval = ghb_dict_lookup(mac_dict, "PresetDescription");
669 ghb_dict_insert(lin_dict, g_strdup("preset_description"),
670 ghb_value_dup(gval));
672 gval = ghb_dict_lookup(mac_dict, "Folder");
673 if (gval && ghb_value_boolean(gval))
677 mval = ghb_dict_lookup(mac_dict, "ChildrenArray");
678 lval = ghb_array_value_new(32);
679 ghb_dict_insert(lin_dict, g_strdup("preset_folder"), lval);
680 ghb_dict_insert(lin_dict, g_strdup("preset_type"),
681 ghb_int_value_new(2));
682 parse_preset_array(mval, lval);
686 ghb_dict_insert(lin_dict, g_strdup("preset_type"),
687 ghb_int_value_new(0));
688 parse_preset_dict(mac_dict, lin_dict);
694 xlat(GValue *mac, GValue *lin)
696 return parse_preset_array(mac, lin);
700 main(gint argc, gchar *argv[])
702 GValue *mac_plist, *lin_plist;
707 fprintf(stderr, "Usage: <mac plist> <lin plist>\n");
712 ghb_register_transforms();
713 internal = ghb_plist_parse_file("internal_defaults.xml");
714 defaults = ghb_dict_lookup(internal, "Presets");
715 mac_plist = ghb_plist_parse_file(argv[1]);
716 lin_plist = ghb_array_value_new(32);
717 xlat(mac_plist, lin_plist);
718 ghb_plist_write_file(argv[2], lin_plist);