6 #define BUF_SIZ (128*1024)
7 #define IS_TAG(a,b) (strcmp((a),(b)) == 0)
8 #define IS_KEY(a,b) (strcmp((a),(b)) == 0)
9 #define IS_VAL(a,b) (strcmp((a),(b)) == 0)
31 GHashTable *xlat_value;
36 GMarkupParseContext *ctx,
38 const gchar **attr_names,
39 const gchar **attr_values,
43 parse_data_t *pd = (parse_data_t*)ud;
45 if (IS_TAG(name, "array"))
49 else if (IS_TAG(name, "dict"))
51 g_hash_table_remove_all(pd->settings);
54 else if (IS_TAG(name, "key"))
58 else if (IS_TAG(name, "string"))
62 else if (IS_TAG(name, "integer"))
66 else if (IS_TAG(name, "real"))
72 g_debug("start unrecognized (%s)", name);
107 "constant_rate_factor",
108 "variable_frame_rate",
110 "vquality_type_constant",
111 "vquality_type_bitrate",
112 "vquality_type_target",
122 verify_keys(parse_data_t *pd)
126 link = keys = g_hash_table_get_keys(pd->settings);
129 gboolean found = FALSE;
130 gchar *key = (gchar*)link->data;
132 for (ii = 0; settings[ii] != NULL; ii++)
134 if (IS_KEY(settings[ii], key))
141 g_message("bad key (%s)", key);
151 save_preset(parse_data_t *pd)
154 if (pd->preset == NULL)
156 g_message("failed to save preset");
159 for (ii = 0; settings[ii] != NULL; ii++)
162 value = (const gchar*)g_hash_table_lookup( pd->settings, settings[ii]);
165 g_key_file_set_value(presets, pd->preset, settings[ii], value);
171 gchar *audio_track[2];
173 gchar *audio_bitrate[2];
174 gchar *audio_rate[2];
179 add_keys(parse_data_t *pd)
181 // These are needed to override default values that
182 // are not set in the xml file (yet)
184 // Check to see if its really not set. Future xml versions will set it.
185 val = (const gchar*)g_hash_table_lookup(pd->settings, "decomb");
187 g_hash_table_insert(pd->settings, g_strdup("decomb"), g_strdup("0"));
191 do_one(gchar **strs, GString *res)
194 for (ii = 0; ii < 2 && strs[ii]; ii++)
196 if (audio_track[ii] == NULL) break;
198 g_string_append_c(res, ',');
199 g_string_append_printf(res, "%s", strs[ii]);
204 do_audio(parse_data_t *pd)
207 GString *enc, *br, *rate, *mix, *drc;
210 enc = g_string_new("");
211 br = g_string_new("");
212 rate = g_string_new("");
213 mix = g_string_new("");
214 drc = g_string_new("");
215 do_one(audio_enc, enc);
216 do_one(audio_bitrate, br);
217 do_one(audio_rate, rate);
218 do_one(audio_mix, mix);
219 do_one(audio_drc, drc);
220 res = g_string_free(enc, FALSE);
221 g_hash_table_insert(pd->settings, g_strdup("pref_audio_codec"), res);
222 res = g_string_free(br, FALSE);
223 g_hash_table_insert(pd->settings, g_strdup("pref_audio_bitrate"), res);
224 res = g_string_free(rate, FALSE);
225 g_hash_table_insert(pd->settings, g_strdup("pref_audio_rate"), res);
226 res = g_string_free(mix, FALSE);
227 g_hash_table_insert(pd->settings, g_strdup("pref_audio_mix"), res);
228 res = g_string_free(drc, FALSE);
229 g_hash_table_insert(pd->settings, g_strdup("pref_audio_drc"), res);
236 for (ii = 0; ii < 2; ii++)
238 audio_track[ii] = NULL;
239 audio_enc[ii] = NULL;
240 audio_bitrate[ii] = NULL;
241 audio_rate[ii] = NULL;
242 audio_mix[ii] = NULL;
243 audio_drc[ii] = NULL;
251 for (ii = 0; ii < 2; ii++)
253 if (audio_track[ii]) g_free(audio_track[ii]);
254 if (audio_enc[ii]) g_free(audio_enc[ii]);
255 if (audio_bitrate[ii]) g_free(audio_bitrate[ii]);
256 if (audio_rate[ii]) g_free(audio_rate[ii]);
257 if (audio_mix[ii]) g_free(audio_mix[ii]);
258 if (audio_drc[ii]) g_free(audio_drc[ii]);
259 audio_track[ii] = NULL;
260 audio_enc[ii] = NULL;
261 audio_bitrate[ii] = NULL;
262 audio_rate[ii] = NULL;
263 audio_mix[ii] = NULL;
264 audio_drc[ii] = NULL;
270 GMarkupParseContext *ctx,
275 parse_data_t *pd = (parse_data_t*)ud;
277 if (IS_TAG(name, "string") ||
278 IS_TAG(name, "integer") ||
279 IS_TAG(name, "real"))
281 if (IS_KEY(pd->key, "PresetName"))
285 g_message("Preset named twice");
288 pd->preset = g_strdup(pd->value);
293 my_key = (const gchar*)g_hash_table_lookup(pd->xlat_key, pd->key);
295 { // Do something with it
296 if (my_key[0] != 0) // intentionally ignored keys
298 if (pd->value != NULL)
300 g_hash_table_insert(pd->settings,
301 g_strdup(my_key), g_strdup(pd->value));
305 g_message("NULL value");
309 else if (IS_KEY(pd->key, "Audio1Encoder"))
311 if (audio_enc[0]) g_free(audio_enc[0]);
312 audio_enc[0] = g_strdup(pd->value);
314 else if (IS_KEY(pd->key, "Audio1Bitrate"))
316 if (audio_bitrate[0]) g_free(audio_bitrate[0]);
317 audio_bitrate[0] = g_strdup(pd->value);
319 else if (IS_KEY(pd->key, "Audio1Samplerate"))
321 if (audio_rate[0]) g_free(audio_rate[0]);
322 audio_rate[0] = g_strdup(pd->value);
324 else if (IS_KEY(pd->key, "Audio1Mixdown"))
326 if (audio_mix[0]) g_free(audio_mix[0]);
327 audio_mix[0] = g_strdup(pd->value);
329 else if (IS_KEY(pd->key, "Audio1TrackDRCSlider"))
331 if (audio_drc[0]) g_free(audio_drc[0]);
332 audio_drc[0] = g_strdup(pd->value);
334 else if (IS_KEY(pd->key, "Audio1Track"))
336 if (audio_track[0]) g_free(audio_track[0]);
337 audio_track[0] = g_strdup(pd->value);
339 else if (IS_KEY(pd->key, "Audio2Encoder"))
341 if (audio_enc[1]) g_free(audio_enc[1]);
342 audio_enc[1] = g_strdup(pd->value);
344 else if (IS_KEY(pd->key, "Audio2Bitrate"))
346 if (audio_bitrate[1]) g_free(audio_bitrate[1]);
347 audio_bitrate[1] = g_strdup(pd->value);
349 else if (IS_KEY(pd->key, "Audio2Samplerate"))
351 if (audio_rate[1]) g_free(audio_rate[1]);
352 audio_rate[1] = g_strdup(pd->value);
354 else if (IS_KEY(pd->key, "Audio2Mixdown"))
356 if (audio_mix[1]) g_free(audio_mix[1]);
357 audio_mix[1] = g_strdup(pd->value);
359 else if (IS_KEY(pd->key, "Audio2TrackDRCSlider"))
361 if (audio_drc[1]) g_free(audio_drc[1]);
362 audio_drc[1] = g_strdup(pd->value);
364 else if (IS_KEY(pd->key, "Audio2Track"))
366 if (audio_track[1]) g_free(audio_track[1]);
367 audio_track[1] = g_strdup(pd->value);
369 else if (IS_KEY(pd->key, "VideoQualityType"))
371 // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
372 if (IS_VAL(pd->value, "0"))
374 g_hash_table_insert(pd->settings,
375 g_strdup("vquality_type_target"),
377 g_hash_table_remove(pd->settings, "vquality_type_bitrate");
378 g_hash_table_remove(pd->settings, "vquality_type_constant");
380 else if (IS_VAL(pd->value, "1"))
382 g_hash_table_remove(pd->settings, "vquality_type_target");
383 g_hash_table_insert(pd->settings,
384 g_strdup("vquality_type_bitrate"),
386 g_hash_table_remove(pd->settings, "vquality_type_constant");
388 else if (IS_VAL(pd->value, "2"))
390 g_hash_table_remove(pd->settings, "vquality_type_target");
391 g_hash_table_remove(pd->settings, "vquality_type_bitrate");
392 g_hash_table_insert(pd->settings,
393 g_strdup("vquality_type_constant"),
399 g_message("Key not found (%s)", pd->key);
402 else if (IS_TAG(name, "dict"))
416 g_message("Preset has no name");
417 g_hash_table_remove_all(pd->settings);
423 is_number(const gchar *str)
425 gboolean result = TRUE;
427 for (ii = 0; str[ii] != 0; ii++)
429 if (!g_ascii_isdigit(str[ii]) && str[ii] != '.')
437 GMarkupParseContext *ctx,
443 gboolean is_value = FALSE;
444 parse_data_t *pd = (parse_data_t*)ud;
445 const gchar *val = NULL;
447 if (pd->state == KEY)
449 if (pd->key) g_free(pd->key);
450 pd->key = g_strdup(text);
453 if (pd->state == STR)
455 val = (gchar*)g_hash_table_lookup(pd->xlat_value, text);
457 { // Do something with it
459 else if (IS_KEY(pd->key, "PresetName") ||
460 IS_KEY(pd->key, "PresetDescription") ||
461 IS_KEY(pd->key, "x264Option") ||
468 g_message("Unrecognized val (%s)", text);
471 if (pd->state == INT || pd->state == REAL)
476 // Some keys need further translation of their values
479 if (IS_KEY(pd->key, "PictureDeinterlace"))
481 if (IS_VAL(val, "0"))
485 else if (IS_VAL(val, "1"))
489 else if (IS_VAL(val, "2"))
493 else if (IS_VAL(val, "3"))
498 else if (IS_KEY(pd->key, "VideoQualitySlider"))
501 dval = g_strtod(val, NULL);
503 if (pd->value) g_free(pd->value);
504 pd->value = g_strdup_printf("%d", (gint)dval);
507 else if (IS_KEY(pd->key, "Audio1Samplerate") ||
508 IS_KEY(pd->key, "Audio2Samplerate"))
510 if (IS_VAL(val, "auto"))
515 else if (IS_KEY(pd->key, "Audio1Mixdown") ||
516 IS_KEY(pd->key, "Audio2Mixdown"))
518 if (IS_VAL(val, "ac3"))
523 if (pd->value) g_free(pd->value);
524 pd->value = g_strdup(val);
530 GMarkupParseContext *ctx,
536 parse_data_t *pd = (parse_data_t*)ud;
538 g_debug("passthrough %s", text);
542 delete_key(gpointer str)
548 delete_value(gpointer str)
559 static xlat_t keys[] =
561 {"VFR", "variable_frame_rate"},
562 {"ChapterMarkers", "chapter_markers"},
564 {"FileFormat", "container"},
565 {"PictureAutoCrop", "autocrop"},
566 {"PictureBottomCrop", ""},
567 {"PictureTopCrop", ""},
568 {"PictureLeftCrop", ""},
569 {"PictureRightCrop", ""},
570 {"PictureDeblock", "deblock"},
571 {"PictureDeinterlace", "deinterlace"}, // v
572 {"PictureDenoise", "denoise"}, // v
573 {"PictureDetelecine", "detelecine"},
574 {"PictureHeight", "max_height"},
575 {"PictureWidth", "max_width"},
576 {"PictureKeepRatio", "keep_aspect"},
577 {"PicturePAR", "anamorphic"}, // v
578 {"PresetDescription", "preset_description"},
579 {"Subtitles", "subtitle_lang"},
580 {"Subtitles", "subtitle_lang"},
581 {"Type", ""}, // preset type builtin/custom
582 {"UsesMaxPictureSettings", "autoscale"},
583 {"UsesPictureFilters", ""},
584 {"UsesPictureSettings", ""},
585 {"VideoAvgBitrate", "video_bitrate"},
586 {"VideoEncoder", "video_codec"},
587 {"VideoFramerate", "framerate"},
588 {"VideoGrayScale", "grayscale"},
589 {"VideoQualitySlider", "video_quality"},
590 {"VideoTargetSize", "video_target_size"},
591 {"VideoTurboTwoPass", "turbo"},
592 {"VideoTwoPass", "two_pass"},
593 {"x264Option", "x264_options"},
594 {"Mp4LargeFile", "large_mp4"},
595 {"Mp4iPodCompatible", "ipod_file"},
599 // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
600 // Audio1Bitrate - pref_audio_bitrate
601 // Audio1Encoder - pref_audio_codec
602 // Audio1Mixdown - pref_audio_mix
603 // Audio1Samplerate - pref_audio_rate
605 // Audio1DRCSlider - pref_audio_drc
607 static xlat_t values[] =
609 {"AAC (faac)", "faac"},
610 {"AC3 Passthru", "ac3"},
611 {"H.264 (x264)", "x264"},
612 {"MPEG-4 (FFmpeg)", "ffmpeg"},
613 {"Dolby Pro Logic II", "dpl2"},
618 {"Same as source", "source"},
624 store_key_file(GKeyFile *key_file, const gchar *name)
626 gchar *settingsString;
630 settingsString = g_key_file_to_data(key_file, &length, NULL);
632 fd = g_open(name, O_RDWR|O_CREAT|O_TRUNC, 0777);
633 write(fd, settingsString, length);
635 g_free(settingsString);
639 parse_it(gchar *buf, gssize len)
641 GMarkupParseContext *ctx;
642 GMarkupParser parser;
646 presets = g_key_file_new();
651 pd.settings = g_hash_table_new_full(g_str_hash, g_str_equal,
652 delete_key, delete_value);
653 pd.xlat_key = g_hash_table_new(g_str_hash, g_str_equal);
655 for (ii = 0; keys[ii].from != NULL; ii++)
657 g_hash_table_insert(pd.xlat_key, keys[ii].from, keys[ii].to);
659 pd.xlat_value = g_hash_table_new(g_str_hash, g_str_equal);
660 for (ii = 0; values[ii].from != NULL; ii++)
662 g_hash_table_insert(pd.xlat_value, values[ii].from, values[ii].to);
664 parser.start_element = start_element;
665 parser.end_element = end_element;
666 parser.text = text_data;
667 parser.passthrough = passthrough;
668 ctx = g_markup_parse_context_new(&parser, 0, &pd, NULL);
669 g_markup_parse_context_parse(ctx, buf, len, NULL);
670 store_key_file(presets, "xlat_presets");
674 main(gint argc, gchar *argv[])
677 gchar buffer[BUF_SIZ];
680 fd = fopen(argv[1], "r");
681 size = fread(buffer, 1, BUF_SIZ, fd);
684 g_error("buffer too small");
688 parse_it(buffer, (gssize)size);