OSDN Git Service

Add Bluray support
[handbrake-jp/handbrake-jp-git.git] / gtk / src / preset_xlat.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <glib.h>
4 #include <glib/gstdio.h>
5 #include "plist.h"
6 #include "values.h"
7
8 static GValue *defaults;
9
10 typedef struct
11 {
12         gchar *mac_val;
13         gchar *lin_val;
14 } value_map_t;
15
16 #if 0
17 static value_map_t subtitle_xlat[] =
18
19         { "None", "none" },
20         { "Auto", "auto" },
21         { "Any", "und" },
22         { "Afar", "aar" },
23         { "Abkhazian", "abk" },
24         { "Afrikaans", "afr" },
25         { "Akan", "aka" },
26         { "Albanian", "sqi" },
27         { "Amharic", "amh" },
28         { "Arabic", "ara" },
29         { "Aragonese", "arg" },
30         { "Armenian", "hye" },
31         { "Assamese", "asm" },
32         { "Avaric", "ava" },
33         { "Avestan", "ave" },
34         { "Aymara", "aym" },
35         { "Azerbaijani", "aze" },
36         { "Bashkir", "bak" },
37         { "Bambara", "bam" },
38         { "Basque", "eus" },
39         { "Belarusian", "bel" },
40         { "Bengali", "ben" },
41         { "Bihari", "bih" },
42         { "Bislama", "bis" },
43         { "Bosnian", "bos" },
44         { "Breton", "bre" },
45         { "Bulgarian", "bul" },
46         { "Burmese", "mya" },
47         { "Catalan", "cat" },
48         { "Chamorro", "cha" },
49         { "Chechen", "che" },
50         { "Chinese", "zho" },
51         { "Church Slavic", "chu" },
52         { "Chuvash", "chv" },
53         { "Cornish", "cor" },
54         { "Corsican", "cos" },
55         { "Cree", "cre" },
56         { "Czech", "ces" },
57         { "Danish", "dan" },
58         { "Divehi", "div" },
59         { "Dutch", "nld" },
60         { "Dzongkha", "dzo" },
61         { "English", "eng" },
62         { "Esperanto", "epo" },
63         { "Estonian", "est" },
64         { "Ewe", "ewe" },
65         { "Faroese", "fao" },
66         { "Fijian", "fij" },
67         { "Finnish", "fin" },
68         { "French", "fra" },
69         { "Western Frisian", "fry" },
70         { "Fulah", "ful" },
71         { "Georgian", "kat" },
72         { "German", "deu" },
73         { "Gaelic (Scots)", "gla" },
74         { "Irish", "gle" },
75         { "Galician", "glg" },
76         { "Manx", "glv" },
77         { "Greek, Modern", "ell" },
78         { "Guarani", "grn" },
79         { "Gujarati", "guj" },
80         { "Haitian", "hat" },
81         { "Hausa", "hau" },
82         { "Hebrew", "heb" },
83         { "Herero", "her" },
84         { "Hindi", "hin" },
85         { "Hiri Motu", "hmo" },
86         { "Hungarian", "hun" },
87         { "Igbo", "ibo" },
88         { "Icelandic", "isl" },
89         { "Ido", "ido" },
90         { "Sichuan Yi", "iii" },
91         { "Inuktitut", "iku" },
92         { "Interlingue", "ile" },
93         { "Interlingua", "ina" },
94         { "Indonesian", "ind" },
95         { "Inupiaq", "ipk" },
96         { "Italian", "ita" },
97         { "Javanese", "jav" },
98         { "Japanese", "jpn" },
99         { "Kalaallisut", "kal" },
100         { "Kannada", "kan" },
101         { "Kashmiri", "kas" },
102         { "Kanuri", "kau" },
103         { "Kazakh", "kaz" },
104         { "Central Khmer", "khm" },
105         { "Kikuyu", "kik" },
106         { "Kinyarwanda", "kin" },
107         { "Kirghiz", "kir" },
108         { "Komi", "kom" },
109         { "Kongo", "kon" },
110         { "Korean", "kor" },
111         { "Kuanyama", "kua" },
112         { "Kurdish", "kur" },
113         { "Lao", "lao" },
114         { "Latin", "lat" },
115         { "Latvian", "lav" },
116         { "Limburgan", "lim" },
117         { "Lingala", "lin" },
118         { "Lithuanian", "lit" },
119         { "Luxembourgish", "ltz" },
120         { "Luba-Katanga", "lub" },
121         { "Ganda", "lug" },
122         { "Macedonian", "mkd" },
123         { "Marshallese", "mah" },
124         { "Malayalam", "mal" },
125         { "Maori", "mri" },
126         { "Marathi", "mar" },
127         { "Malay", "msa" },
128         { "Malagasy", "mlg" },
129         { "Maltese", "mlt" },
130         { "Moldavian", "mol" },
131         { "Mongolian", "mon" },
132         { "Nauru", "nau" },
133         { "Navajo", "nav" },
134         { "Ndebele, South", "nbl" },
135         { "Ndebele, North", "nde" },
136         { "Ndonga", "ndo" },
137         { "Nepali", "nep" },
138         { "Norwegian Nynorsk", "nno" },
139         { "Norwegian Bokmål", "nob" },
140         { "Norwegian", "nor" },
141         { "Chichewa; Nyanja", "nya" },
142         { "Occitan", "oci" },
143         { "Ojibwa", "oji" },
144         { "Oriya", "ori" },
145         { "Oromo", "orm" },
146         { "Ossetian", "oss" },
147         { "Panjabi", "pan" },
148         { "Persian", "fas" },
149         { "Pali", "pli" },
150         { "Polish", "pol" },
151         { "Portuguese", "por" },
152         { "Pushto", "pus" },
153         { "Quechua", "que" },
154         { "Romansh", "roh" },
155         { "Romanian", "ron" },
156         { "Rundi", "run" },
157         { "Russian", "rus" },
158         { "Sango", "sag" },
159         { "Sanskrit", "san" },
160         { "Serbian", "srp" },
161         { "Croatian", "hrv" },
162         { "Sinhala", "sin" },
163         { "Slovak", "slk" },
164         { "Slovenian", "slv" },
165         { "Northern Sami", "sme" },
166         { "Samoan", "smo" },
167         { "Shona", "sna" },
168         { "Sindhi", "snd" },
169         { "Somali", "som" },
170         { "Sotho, Southern", "sot" },
171         { "Spanish", "spa" },
172         { "Sardinian", "srd" },
173         { "Swati", "ssw" },
174         { "Sundanese", "sun" },
175         { "Swahili", "swa" },
176         { "Swedish", "swe" },
177         { "Tahitian", "tah" },
178         { "Tamil", "tam" },
179         { "Tatar", "tat" },
180         { "Telugu", "tel" },
181         { "Tajik", "tgk" },
182         { "Tagalog", "tgl" },
183         { "Thai", "tha" },
184         { "Tibetan", "bod" },
185         { "Tigrinya", "tir" },
186         { "Tonga", "ton" },
187         { "Tswana", "tsn" },
188         { "Tsonga", "tso" },
189         { "Turkmen", "tuk" },
190         { "Turkish", "tur" },
191         { "Twi", "twi" },
192         { "Uighur", "uig" },
193         { "Ukrainian", "ukr" },
194         { "Urdu", "urd" },
195         { "Uzbek", "uzb" },
196         { "Venda", "ven" },
197         { "Vietnamese", "vie" },
198         { "Volapük", "vol" },
199         { "Welsh", "cym" },
200         { "Walloon", "wln" },
201         { "Wolof", "wol" },
202         { "Xhosa", "xho" },
203         { "Yiddish", "yid" },
204         { "Yoruba", "yor" },
205         { "Zhuang", "zha" },
206         { "Zulu", "zul" },
207         {NULL, NULL}
208 };
209
210 static value_map_t vcodec_xlat[] =
211 {
212         {"MPEG-4 (FFmpeg)", "ffmpeg"},
213         {"MPEG-4 (XviD)", "ffmpeg"},
214         {"H.264 (x264)", "x264"},
215         {"VP3 (Theora)", "theora"},
216         {NULL,NULL}
217 };
218
219 value_map_t container_xlat[] =
220 {
221         {"MP4 file", "mp4"},
222         {"M4V file", "m4v"},
223         {"MKV file", "mkv"},
224         {"AVI file", "avi"},
225         {"OGM file", "ogm"},
226         {NULL, NULL}
227 };
228
229 value_map_t framerate_xlat[] =
230 {
231         {"Same as source", "source"},
232         {"5", "5"},
233         {"10", "10"},
234         {"12", "12"},
235         {"15", "15"},
236         {"23.976", "23.976"},
237         {"24", "24"},
238         {"25", "25"},
239         {"29.97", "29.97"},
240         {NULL, NULL}
241 };
242
243 value_map_t deint_xlat[] =
244 {
245         {"0", "none"},
246         {"1", "fast"},
247         {"2", "slow"},
248         {"3", "slower"},
249         {NULL, NULL}
250 };
251
252 value_map_t denoise_xlat[] =
253 {
254         {"0", "none"},
255         {"1", "weak"},
256         {"2", "medium"},
257         {"3", "strong"},
258         {NULL, NULL}
259 };
260
261 static value_map_t acodec_xlat[] =
262 {
263         {"AAC (faac)", "faac"},
264         {"AC3 Passthru", "ac3"},
265         {"MP3 (lame)", "lame"},
266         {"Vorbis (vorbis)", "vorbis"},
267         {NULL,NULL}
268 };
269
270 value_map_t samplerate_xlat[] =
271 {
272         {"Auto", "source"},
273         {"22.05", "22.05"},
274         {"24", "24"},
275         {"32", "32"},
276         {"44.1", "44.1"},
277         {"48", "48"},
278         {NULL, NULL}
279 };
280
281 value_map_t mix_xlat[] =
282 {
283         {"Mono", "mono"},
284         {"Stereo", "stereo"},
285         {"Dolby Surround", "dpl1"},
286         {"Dolby Pro Logic II", "dpl2"},
287         {"6-channel discrete", "6ch"},
288         {"AC3 Passthru", "none"},
289         {NULL, NULL}
290 };
291 #endif
292
293 typedef struct
294 {
295         gchar *mac_key;
296         gchar *lin_key;
297         value_map_t *value_map;
298         gboolean same;
299         gboolean ignore;
300 } key_map_t;
301
302 key_map_t key_map[] = 
303 {
304         {"Audio1Bitrate", NULL, NULL, FALSE, FALSE},
305         {"Audio1Encoder", NULL, NULL, FALSE, FALSE},
306         {"Audio1Mixdown", NULL, NULL, FALSE, FALSE},
307         {"Audio1Samplerate", NULL, NULL, FALSE, FALSE},
308         {"Audio1Track", NULL, NULL, FALSE, FALSE},
309         {"Audio1TrackDescription", NULL, NULL, FALSE, FALSE},
310         {"Audio1TrackDRCSlider", NULL, NULL, FALSE, FALSE},
311         {"Audio2Bitrate", NULL, NULL, FALSE, FALSE},
312         {"Audio2Encoder", NULL, NULL, FALSE, FALSE},
313         {"Audio2Mixdown", NULL, NULL, FALSE, FALSE},
314         {"Audio2Samplerate", NULL, NULL, FALSE, FALSE},
315         {"Audio2Track", NULL, NULL, FALSE, FALSE},
316         {"Audio2TrackDescription", NULL, NULL, FALSE, FALSE},
317         {"Audio2TrackDRCSlider", NULL, NULL, FALSE, FALSE},
318         {"ChapterMarkers", NULL, NULL, TRUE, FALSE},
319         {"Default", NULL, NULL, TRUE, FALSE},
320         {"FileFormat", NULL, NULL, TRUE, FALSE},
321         {"Folder", NULL, NULL, TRUE, FALSE},
322         {"Mp4HttpOptimize", NULL, NULL, TRUE, FALSE},
323         {"Mp4iPodCompatible", NULL, NULL, TRUE, FALSE},
324         {"Mp4LargeFile", NULL, NULL, TRUE, FALSE},
325         {"PictureAutoCrop", NULL, NULL, TRUE, FALSE},
326         {"PictureBottomCrop", NULL, NULL, TRUE, FALSE},
327         {"PictureDeblock", NULL, NULL, TRUE, FALSE},
328         {"PictureDecomb", NULL, NULL, TRUE, FALSE},
329         {"PictureDeinterlace", NULL, NULL, TRUE, FALSE},
330         {"PictureDenoise", NULL, NULL, TRUE, FALSE},
331         {"PictureDetelecine", NULL, NULL, TRUE, FALSE},
332         {"PictureHeight", NULL, NULL, TRUE, FALSE},
333         {"PictureKeepRatio", NULL, NULL, TRUE, FALSE},
334         {"PictureLeftCrop", NULL, NULL, TRUE, FALSE},
335         {"PicturePAR", NULL, NULL, TRUE, FALSE},
336         {"PictureRightCrop", NULL, NULL, TRUE, FALSE},
337         {"PictureTopCrop", NULL, NULL, TRUE, FALSE},
338         {"PictureWidth", NULL, NULL, TRUE, FALSE},
339         {"PresetDescription", NULL, NULL, TRUE, FALSE},
340         {"PresetName", NULL, NULL, TRUE, FALSE},
341         {"Subtitles", NULL, NULL, TRUE, FALSE},
342         {"SubtitlesForced", NULL, NULL, TRUE, FALSE},
343         {"Type", NULL, NULL, TRUE, FALSE},
344         {"UsesMaxPictureSettings", NULL, NULL, TRUE, FALSE},
345         {"UsesPictureFilters", NULL, NULL, TRUE, FALSE},
346         {"UsesPictureSettings", NULL, NULL, TRUE, FALSE},
347         {"VFR", NULL, NULL, FALSE, TRUE},
348         {"VideoAvgBitrate", NULL, NULL, TRUE, FALSE},
349         {"VideoEncoder", NULL, NULL, TRUE, FALSE},
350         {"VideoFramerate", NULL, NULL, TRUE, FALSE},
351         {"VideoGrayScale", NULL, NULL, TRUE, FALSE},
352         {"VideoQualitySlider", NULL, NULL, TRUE, FALSE},
353         {"VideoQualityType", NULL, NULL, TRUE, FALSE},
354         {"VideoTargetSize", NULL, NULL, TRUE, FALSE},
355         {"VideoTwoPass", NULL, NULL, TRUE, FALSE},
356         {"VideoTurboTwoPass", NULL, NULL, TRUE, FALSE},
357         {"x264Option", NULL, NULL, TRUE, FALSE},
358         {NULL, NULL}
359 };
360
361 const gint
362 key_xlat(key_map_t *key_map, const gchar *mac_key)
363 {
364         gint ii;
365
366         for (ii = 0; key_map[ii].mac_key; ii++)
367         {
368                 if (strcmp(mac_key, key_map[ii].mac_key) == 0)
369                 {
370                         if (key_map[ii].ignore)
371                                 return -1;
372                         return ii;
373                 }
374         }
375         g_warning("Unrecognized key: (%s)", mac_key);
376         return -1;
377 }
378
379 static GValue*
380 value_xlat(
381         GValue *defaults, 
382         key_map_t *key_map, 
383         gint key_index, 
384         GValue *mac_val)
385 {
386         GValue *gval, *def_val;
387         const gchar *lin_key;
388         if (key_map[key_index].same)
389                 lin_key = key_map[key_index].mac_key;
390         else
391                 lin_key = key_map[key_index].lin_key;
392         value_map_t *value_map = key_map[key_index].value_map;
393
394         def_val = ghb_dict_lookup(defaults, lin_key);
395         if (def_val)
396         {
397                 if (value_map)
398                 {
399                         gint ii;
400                         gchar *str;
401                         GValue *sval;
402
403                         str = ghb_value_string(mac_val);
404                         for (ii = 0; value_map[ii].mac_val; ii++)
405                         {
406                                 if (strcmp(str, value_map[ii].mac_val) == 0)
407                                 {
408                                         sval = ghb_string_value_new(value_map[ii].lin_val);
409                                         g_free(str);
410                                         gval = ghb_value_new(G_VALUE_TYPE(def_val));
411                                         if (!g_value_transform(sval, gval))
412                                         {
413                                                 g_warning("1 can't transform");
414                                                 ghb_value_free(gval);
415                                                 ghb_value_free(sval);
416                                                 return NULL;
417                                         }
418                                         ghb_value_free(sval);
419                                         return gval;
420                                 }
421                         }
422                         g_warning("Can't map value: (%s)", str);
423                         g_free(str);
424                 }
425                 else
426                 {
427                         gval = ghb_value_new(G_VALUE_TYPE(def_val));
428                         if (!g_value_transform(mac_val, gval))
429                         {
430                                 g_warning("2 can't transform");
431                                 ghb_value_free(gval);
432                                 return NULL;
433                         }
434                         return gval;
435                 }
436         }
437         else
438         {
439                 g_warning("Bad key: (%s)", lin_key);
440                 return NULL;
441         }
442         return NULL;
443 }
444
445 key_map_t audio_key_map[] =
446 {
447         {"Audio1Bitrate", "AudioBitrate", NULL, FALSE, FALSE},
448         {"Audio1Encoder", "AudioEncoder", NULL, FALSE, FALSE},
449         {"Audio1Mixdown", "AudioMixdown", NULL, FALSE},
450         {"Audio1Samplerate", "AudioSamplerate", NULL, FALSE, FALSE},
451         {"Audio1Track", "AudioTrack", NULL, FALSE, FALSE},
452         {"Audio1TrackDescription", "AudioTrackDescription", NULL, FALSE, FALSE},
453         {"Audio1TrackDRCSlider", "AudioTrackDRCSlider", NULL, FALSE, FALSE},
454         {"Audio2Bitrate", "AudioBitrate", NULL, FALSE, FALSE},
455         {"Audio2Encoder", "AudioEncoder", NULL, FALSE, FALSE},
456         {"Audio2Mixdown", "AudioMixdown", NULL, FALSE, FALSE},
457         {"Audio2Samplerate", "AudioSamplerate", NULL, FALSE, FALSE},
458         {"Audio2Track", "AudioTrack", NULL, FALSE, FALSE},
459         {"Audio2TrackDescription", "AudioTrackDescription", NULL, FALSE, FALSE},
460         {"Audio2TrackDRCSlider", "AudioTrackDRCSlider", NULL, FALSE, FALSE},
461         {NULL, NULL}
462 };
463
464 static void
465 hard_value_xlat(GValue *lin_dict, const gchar *mac_key, GValue *mac_val)
466 {
467         {
468                 gint key_index;
469                 GValue *audio_defaults;
470
471                 audio_defaults = ghb_array_get_nth(
472                         ghb_dict_lookup(defaults, "AudioList"), 0);
473                 key_index = key_xlat(audio_key_map, mac_key);
474                 if (key_index >= 0)
475                 {
476                         gint audio_index, count, ii;
477                         GValue *alist, *adict, *val;
478                         const gchar *lin_key;
479
480                         if (audio_key_map[key_index].same)
481                                 lin_key = audio_key_map[key_index].mac_key;
482                         else
483                                 lin_key = audio_key_map[key_index].lin_key;
484                         audio_index = mac_key[5] - '1';
485                         alist = ghb_dict_lookup(lin_dict, "AudioList");
486                         if (alist == NULL)
487                         {
488                                 alist = ghb_array_value_new(8);
489                                 ghb_dict_insert(lin_dict, "AudioList", alist);
490                         }
491                         count = ghb_array_len(alist);
492                         for (ii = count; ii <= audio_index; ii++)
493                         {
494                                 adict = ghb_value_dup(audio_defaults);
495                                 ghb_array_append(alist, adict);
496                         }
497                         adict = ghb_array_get_nth(alist, audio_index);
498                         val = value_xlat(audio_defaults, audio_key_map, key_index, mac_val);
499                         if (val)
500                         {
501                                 ghb_dict_insert(adict, g_strdup(lin_key), val);
502                         }
503                 }
504         }
505 }
506
507 static void
508 parse_preset_dict(GValue *mac_dict, GValue *lin_dict)
509 {
510     GHashTableIter iter;
511     gchar *key;
512     GValue *mac_val, *val;
513
514     ghb_dict_iter_init(&iter, mac_dict);
515     // middle (void*) cast prevents gcc warning "defreferencing type-punned
516     // pointer will break strict-aliasing rules"
517         while (g_hash_table_iter_next(
518                         &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&mac_val))
519         {
520                 gint key_index;
521
522                 key_index = key_xlat(key_map, key);
523                 if (key_index >= 0)
524                 { // The simple translations
525                         const gchar *lin_key;
526
527                         if (key_map[key_index].same)
528                                 lin_key = key_map[key_index].mac_key;
529                         else
530                                 lin_key = key_map[key_index].lin_key;
531                         if (lin_key)
532                         {
533                                 val = value_xlat(defaults, key_map, key_index, mac_val);
534                                 if (val)
535                                 {
536                                         ghb_dict_insert(lin_dict, g_strdup(lin_key), val);
537                                 }
538                         }
539                         else
540                         {
541                                 hard_value_xlat(lin_dict, key, mac_val);
542                         }
543                 }
544         }
545 }
546
547 static void
548 parse_preset_array(GValue *mac_array, GValue *lin_array)
549 {
550         gint count, ii;
551         GValue *mac_dict, *lin_dict, *gval;
552
553         count = ghb_array_len(mac_array);
554         for (ii = 0; ii < count; ii++)
555         {
556                 mac_dict = ghb_array_get_nth(mac_array, ii);
557                 
558                 // Only process builtin types
559                 if (ghb_value_int(ghb_dict_lookup(mac_dict, "Type")) != 0)
560                         continue;
561
562                 lin_dict = ghb_dict_value_new();
563                 ghb_array_append(lin_array, lin_dict);
564                 gval = ghb_dict_lookup(mac_dict, "PresetName");
565                 if (gval)
566                 {
567                         ghb_dict_insert(lin_dict, g_strdup("PresetName"), 
568                                                         ghb_value_dup(gval));
569                 }
570                 gval = ghb_dict_lookup(mac_dict, "PresetDescription");
571                 if (gval)
572                 {
573                         ghb_dict_insert(lin_dict, g_strdup("PresetDescription"), 
574                                                         ghb_value_dup(gval));
575                 }
576                 gval = ghb_dict_lookup(mac_dict, "Folder");
577                 if (gval && ghb_value_boolean(gval))
578                 { // Folder
579                         GValue *mval, *lval;
580
581                         mval = ghb_dict_lookup(mac_dict, "ChildrenArray");
582                         lval = ghb_array_value_new(32);
583                         ghb_dict_insert(lin_dict, g_strdup("ChildrenArray"), lval);
584                         ghb_dict_insert(lin_dict, g_strdup("Folder"), 
585                                                         ghb_boolean_value_new(TRUE));
586                         ghb_dict_insert(lin_dict, g_strdup("Type"), 
587                                                         ghb_int_value_new(0));
588                         parse_preset_array(mval, lval);
589                 }
590                 else
591                 { // Normal preset
592                         ghb_dict_insert(lin_dict, g_strdup("Type"), 
593                                                         ghb_int_value_new(0));
594                         parse_preset_dict(mac_dict, lin_dict);
595                 }
596         }
597 }
598
599 static void
600 xlat(GValue *mac, GValue *lin)
601 {
602         return parse_preset_array(mac, lin);
603 }
604
605 gint
606 main(gint argc, gchar *argv[])
607 {
608         GValue *mac_plist, *lin_plist;
609         GValue *internal;
610
611         if (argc < 3)
612         {
613                 fprintf(stderr, "Usage: <mac plist> <lin plist>\n");
614                 return 1;
615         }
616         g_type_init();
617
618         ghb_register_transforms();
619         internal = ghb_plist_parse_file("internal_defaults.xml");
620         defaults = ghb_dict_lookup(internal, "Presets");
621         mac_plist = ghb_plist_parse_file(argv[1]);
622         lin_plist = ghb_array_value_new(32);
623         xlat(mac_plist, lin_plist);
624         ghb_plist_write_file(argv[2], lin_plist);
625         return 0;
626 }
627