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);
108 "constant_rate_factor",
109 "variable_frame_rate",
111 "vquality_type_constant",
112 "vquality_type_bitrate",
113 "vquality_type_target",
123 verify_keys(parse_data_t *pd)
127 link = keys = g_hash_table_get_keys(pd->settings);
130 gboolean found = FALSE;
131 gchar *key = (gchar*)link->data;
133 for (ii = 0; settings[ii] != NULL; ii++)
135 if (IS_KEY(settings[ii], key))
142 g_message("bad key (%s)", key);
152 save_preset(parse_data_t *pd)
155 if (pd->preset == NULL)
157 g_message("failed to save preset");
160 for (ii = 0; settings[ii] != NULL; ii++)
163 value = (const gchar*)g_hash_table_lookup( pd->settings, settings[ii]);
166 g_key_file_set_value(presets, pd->preset, settings[ii], value);
172 gchar *audio_track[2];
174 gchar *audio_bitrate[2];
175 gchar *audio_rate[2];
180 add_keys(parse_data_t *pd)
182 // These are needed to override default values that
183 // are not set in the xml file (yet)
185 // Check to see if its really not set. Future xml versions will set it.
186 val = (const gchar*)g_hash_table_lookup(pd->settings, "decomb");
188 g_hash_table_insert(pd->settings, g_strdup("decomb"), g_strdup("0"));
192 do_one(gchar **strs, GString *res)
195 for (ii = 0; ii < 2 && strs[ii]; ii++)
197 if (audio_track[ii] == NULL) break;
199 g_string_append_c(res, ',');
200 g_string_append_printf(res, "%s", strs[ii]);
205 do_audio(parse_data_t *pd)
208 GString *enc, *br, *rate, *mix, *drc;
211 enc = g_string_new("");
212 br = g_string_new("");
213 rate = g_string_new("");
214 mix = g_string_new("");
215 drc = g_string_new("");
216 do_one(audio_enc, enc);
217 do_one(audio_bitrate, br);
218 do_one(audio_rate, rate);
219 do_one(audio_mix, mix);
220 do_one(audio_drc, drc);
221 res = g_string_free(enc, FALSE);
222 g_hash_table_insert(pd->settings, g_strdup("pref_audio_codec"), res);
223 res = g_string_free(br, FALSE);
224 g_hash_table_insert(pd->settings, g_strdup("pref_audio_bitrate"), res);
225 res = g_string_free(rate, FALSE);
226 g_hash_table_insert(pd->settings, g_strdup("pref_audio_rate"), res);
227 res = g_string_free(mix, FALSE);
228 g_hash_table_insert(pd->settings, g_strdup("pref_audio_mix"), res);
229 res = g_string_free(drc, FALSE);
230 g_hash_table_insert(pd->settings, g_strdup("pref_audio_drc"), res);
237 for (ii = 0; ii < 2; ii++)
239 audio_track[ii] = NULL;
240 audio_enc[ii] = NULL;
241 audio_bitrate[ii] = NULL;
242 audio_rate[ii] = NULL;
243 audio_mix[ii] = NULL;
244 audio_drc[ii] = NULL;
252 for (ii = 0; ii < 2; ii++)
254 if (audio_track[ii]) g_free(audio_track[ii]);
255 if (audio_enc[ii]) g_free(audio_enc[ii]);
256 if (audio_bitrate[ii]) g_free(audio_bitrate[ii]);
257 if (audio_rate[ii]) g_free(audio_rate[ii]);
258 if (audio_mix[ii]) g_free(audio_mix[ii]);
259 if (audio_drc[ii]) g_free(audio_drc[ii]);
260 audio_track[ii] = NULL;
261 audio_enc[ii] = NULL;
262 audio_bitrate[ii] = NULL;
263 audio_rate[ii] = NULL;
264 audio_mix[ii] = NULL;
265 audio_drc[ii] = NULL;
271 GMarkupParseContext *ctx,
276 parse_data_t *pd = (parse_data_t*)ud;
278 if (IS_TAG(name, "string") ||
279 IS_TAG(name, "integer") ||
280 IS_TAG(name, "real"))
282 if (IS_KEY(pd->key, "PresetName"))
286 g_message("Preset named twice");
289 pd->preset = g_strdup(pd->value);
294 my_key = (const gchar*)g_hash_table_lookup(pd->xlat_key, pd->key);
296 { // Do something with it
297 if (my_key[0] != 0) // intentionally ignored keys
299 if (pd->value != NULL)
301 g_hash_table_insert(pd->settings,
302 g_strdup(my_key), g_strdup(pd->value));
306 g_message("NULL value");
310 else if (IS_KEY(pd->key, "Audio1Encoder"))
312 if (audio_enc[0]) g_free(audio_enc[0]);
313 audio_enc[0] = g_strdup(pd->value);
315 else if (IS_KEY(pd->key, "Audio1Bitrate"))
317 if (audio_bitrate[0]) g_free(audio_bitrate[0]);
318 audio_bitrate[0] = g_strdup(pd->value);
320 else if (IS_KEY(pd->key, "Audio1Samplerate"))
322 if (audio_rate[0]) g_free(audio_rate[0]);
323 audio_rate[0] = g_strdup(pd->value);
325 else if (IS_KEY(pd->key, "Audio1Mixdown"))
327 if (audio_mix[0]) g_free(audio_mix[0]);
328 audio_mix[0] = g_strdup(pd->value);
330 else if (IS_KEY(pd->key, "Audio1TrackDRCSlider"))
332 if (audio_drc[0]) g_free(audio_drc[0]);
333 audio_drc[0] = g_strdup(pd->value);
335 else if (IS_KEY(pd->key, "Audio1Track"))
337 if (audio_track[0]) g_free(audio_track[0]);
338 audio_track[0] = g_strdup(pd->value);
340 else if (IS_KEY(pd->key, "Audio2Encoder"))
342 if (audio_enc[1]) g_free(audio_enc[1]);
343 audio_enc[1] = g_strdup(pd->value);
345 else if (IS_KEY(pd->key, "Audio2Bitrate"))
347 if (audio_bitrate[1]) g_free(audio_bitrate[1]);
348 audio_bitrate[1] = g_strdup(pd->value);
350 else if (IS_KEY(pd->key, "Audio2Samplerate"))
352 if (audio_rate[1]) g_free(audio_rate[1]);
353 audio_rate[1] = g_strdup(pd->value);
355 else if (IS_KEY(pd->key, "Audio2Mixdown"))
357 if (audio_mix[1]) g_free(audio_mix[1]);
358 audio_mix[1] = g_strdup(pd->value);
360 else if (IS_KEY(pd->key, "Audio2TrackDRCSlider"))
362 if (audio_drc[1]) g_free(audio_drc[1]);
363 audio_drc[1] = g_strdup(pd->value);
365 else if (IS_KEY(pd->key, "Audio2Track"))
367 if (audio_track[1]) g_free(audio_track[1]);
368 audio_track[1] = g_strdup(pd->value);
370 else if (IS_KEY(pd->key, "VideoQualityType"))
372 // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
373 if (IS_VAL(pd->value, "0"))
375 g_hash_table_insert(pd->settings,
376 g_strdup("vquality_type_target"),
378 g_hash_table_remove(pd->settings, "vquality_type_bitrate");
379 g_hash_table_remove(pd->settings, "vquality_type_constant");
381 else if (IS_VAL(pd->value, "1"))
383 g_hash_table_remove(pd->settings, "vquality_type_target");
384 g_hash_table_insert(pd->settings,
385 g_strdup("vquality_type_bitrate"),
387 g_hash_table_remove(pd->settings, "vquality_type_constant");
389 else if (IS_VAL(pd->value, "2"))
391 g_hash_table_remove(pd->settings, "vquality_type_target");
392 g_hash_table_remove(pd->settings, "vquality_type_bitrate");
393 g_hash_table_insert(pd->settings,
394 g_strdup("vquality_type_constant"),
400 g_message("Key not found (%s)", pd->key);
403 else if (IS_TAG(name, "dict"))
417 g_message("Preset has no name");
418 g_hash_table_remove_all(pd->settings);
424 is_number(const gchar *str)
426 gboolean result = TRUE;
428 for (ii = 0; str[ii] != 0; ii++)
430 if (!g_ascii_isdigit(str[ii]) && str[ii] != '.')
438 GMarkupParseContext *ctx,
444 gboolean is_value = FALSE;
445 parse_data_t *pd = (parse_data_t*)ud;
446 const gchar *val = NULL;
448 if (pd->state == KEY)
450 if (pd->key) g_free(pd->key);
451 pd->key = g_strdup(text);
454 if (pd->state == STR)
456 val = (gchar*)g_hash_table_lookup(pd->xlat_value, text);
458 { // Do something with it
460 else if (IS_KEY(pd->key, "PresetName") ||
461 IS_KEY(pd->key, "PresetDescription") ||
462 IS_KEY(pd->key, "x264Option") ||
469 g_message("Unrecognized val (%s)", text);
472 if (pd->state == INT || pd->state == REAL)
477 // Some keys need further translation of their values
480 if (IS_KEY(pd->key, "PictureDeinterlace"))
482 if (IS_VAL(val, "0"))
486 else if (IS_VAL(val, "1"))
490 else if (IS_VAL(val, "2"))
494 else if (IS_VAL(val, "3"))
499 else if (IS_KEY(pd->key, "VideoQualitySlider"))
502 dval = g_strtod(val, NULL);
504 if (pd->value) g_free(pd->value);
505 pd->value = g_strdup_printf("%d", (gint)dval);
508 else if (IS_KEY(pd->key, "Audio1Samplerate") ||
509 IS_KEY(pd->key, "Audio2Samplerate"))
511 if (IS_VAL(val, "auto"))
516 else if (IS_KEY(pd->key, "Audio1Mixdown") ||
517 IS_KEY(pd->key, "Audio2Mixdown"))
519 if (IS_VAL(val, "ac3"))
524 if (pd->value) g_free(pd->value);
525 pd->value = g_strdup(val);
531 GMarkupParseContext *ctx,
537 parse_data_t *pd = (parse_data_t*)ud;
539 g_debug("passthrough %s", text);
543 delete_key(gpointer str)
549 delete_value(gpointer str)
560 static xlat_t keys[] =
562 {"VFR", "variable_frame_rate"},
563 {"ChapterMarkers", "chapter_markers"},
565 {"FileFormat", "container"},
566 {"PictureAutoCrop", "autocrop"},
567 {"PictureBottomCrop", ""},
568 {"PictureTopCrop", ""},
569 {"PictureLeftCrop", ""},
570 {"PictureRightCrop", ""},
571 {"PictureDeblock", "deblock"},
572 {"PictureDeinterlace", "deinterlace"}, // v
573 {"PictureDenoise", "denoise"}, // v
574 {"PictureDetelecine", "detelecine"},
575 {"PictureHeight", "max_height"},
576 {"PictureWidth", "max_width"},
577 {"PictureKeepRatio", "keep_aspect"},
578 {"PicturePAR", "anamorphic"}, // v
579 {"PresetDescription", "preset_description"},
580 {"Subtitles", "subtitle_lang"},
581 {"Subtitles", "subtitle_lang"},
582 {"Type", "preset_type"}, // preset type builtin/custom
583 {"UsesMaxPictureSettings", "autoscale"},
584 {"UsesPictureFilters", ""},
585 {"UsesPictureSettings", ""},
586 {"VideoAvgBitrate", "video_bitrate"},
587 {"VideoEncoder", "video_codec"},
588 {"VideoFramerate", "framerate"},
589 {"VideoGrayScale", "grayscale"},
590 {"VideoQualitySlider", "video_quality"},
591 {"VideoTargetSize", "video_target_size"},
592 {"VideoTurboTwoPass", "turbo"},
593 {"VideoTwoPass", "two_pass"},
594 {"x264Option", "x264_options"},
595 {"Mp4LargeFile", "large_mp4"},
596 {"Mp4iPodCompatible", "ipod_file"},
600 // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
601 // Audio1Bitrate - pref_audio_bitrate
602 // Audio1Encoder - pref_audio_codec
603 // Audio1Mixdown - pref_audio_mix
604 // Audio1Samplerate - pref_audio_rate
606 // Audio1DRCSlider - pref_audio_drc
608 static xlat_t values[] =
610 {"AAC (faac)", "faac"},
611 {"AC3 Passthru", "ac3"},
612 {"H.264 (x264)", "x264"},
613 {"MPEG-4 (FFmpeg)", "ffmpeg"},
614 {"Dolby Pro Logic II", "dpl2"},
619 {"Same as source", "source"},
625 store_key_file(GKeyFile *key_file, const gchar *name)
627 gchar *settingsString;
631 settingsString = g_key_file_to_data(key_file, &length, NULL);
633 fd = g_open(name, O_RDWR|O_CREAT|O_TRUNC, 0777);
634 write(fd, settingsString, length);
636 g_free(settingsString);
640 parse_it(gchar *buf, gssize len)
642 GMarkupParseContext *ctx;
643 GMarkupParser parser;
647 presets = g_key_file_new();
652 pd.settings = g_hash_table_new_full(g_str_hash, g_str_equal,
653 delete_key, delete_value);
654 pd.xlat_key = g_hash_table_new(g_str_hash, g_str_equal);
656 for (ii = 0; keys[ii].from != NULL; ii++)
658 g_hash_table_insert(pd.xlat_key, keys[ii].from, keys[ii].to);
660 pd.xlat_value = g_hash_table_new(g_str_hash, g_str_equal);
661 for (ii = 0; values[ii].from != NULL; ii++)
663 g_hash_table_insert(pd.xlat_value, values[ii].from, values[ii].to);
665 parser.start_element = start_element;
666 parser.end_element = end_element;
667 parser.text = text_data;
668 parser.passthrough = passthrough;
669 ctx = g_markup_parse_context_new(&parser, 0, &pd, NULL);
670 g_markup_parse_context_parse(ctx, buf, len, NULL);
671 store_key_file(presets, "xlat_presets");
675 main(gint argc, gchar *argv[])
678 gchar buffer[BUF_SIZ];
681 fd = fopen(argv[1], "r");
682 size = fread(buffer, 1, BUF_SIZ, fd);
685 g_error("buffer too small");
689 parse_it(buffer, (gssize)size);