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 do_one(gchar **strs, GString *res)
182 for (ii = 0; ii < 2 && strs[ii]; ii++)
184 if (audio_track[ii] == NULL) break;
186 g_string_append_c(res, ',');
187 g_string_append_printf(res, "%s", strs[ii]);
192 do_audio(parse_data_t *pd)
195 GString *enc, *br, *rate, *mix, *drc;
198 enc = g_string_new("");
199 br = g_string_new("");
200 rate = g_string_new("");
201 mix = g_string_new("");
202 drc = g_string_new("");
203 do_one(audio_enc, enc);
204 do_one(audio_bitrate, br);
205 do_one(audio_rate, rate);
206 do_one(audio_mix, mix);
207 do_one(audio_drc, drc);
208 res = g_string_free(enc, FALSE);
209 g_hash_table_insert(pd->settings, g_strdup("pref_audio_codec"), res);
210 res = g_string_free(br, FALSE);
211 g_hash_table_insert(pd->settings, g_strdup("pref_audio_bitrate"), res);
212 res = g_string_free(rate, FALSE);
213 g_hash_table_insert(pd->settings, g_strdup("pref_audio_rate"), res);
214 res = g_string_free(mix, FALSE);
215 g_hash_table_insert(pd->settings, g_strdup("pref_audio_mix"), res);
216 res = g_string_free(drc, FALSE);
217 g_hash_table_insert(pd->settings, g_strdup("pref_audio_drc"), res);
224 for (ii = 0; ii < 2; ii++)
226 audio_track[ii] = NULL;
227 audio_enc[ii] = NULL;
228 audio_bitrate[ii] = NULL;
229 audio_rate[ii] = NULL;
230 audio_mix[ii] = NULL;
231 audio_drc[ii] = NULL;
239 for (ii = 0; ii < 2; ii++)
241 if (audio_track[ii]) g_free(audio_track[ii]);
242 if (audio_enc[ii]) g_free(audio_enc[ii]);
243 if (audio_bitrate[ii]) g_free(audio_bitrate[ii]);
244 if (audio_rate[ii]) g_free(audio_rate[ii]);
245 if (audio_mix[ii]) g_free(audio_mix[ii]);
246 if (audio_drc[ii]) g_free(audio_drc[ii]);
247 audio_track[ii] = NULL;
248 audio_enc[ii] = NULL;
249 audio_bitrate[ii] = NULL;
250 audio_rate[ii] = NULL;
251 audio_mix[ii] = NULL;
252 audio_drc[ii] = NULL;
258 GMarkupParseContext *ctx,
263 parse_data_t *pd = (parse_data_t*)ud;
265 if (IS_TAG(name, "string") ||
266 IS_TAG(name, "integer") ||
267 IS_TAG(name, "real"))
269 if (IS_KEY(pd->key, "PresetName"))
273 g_message("Preset named twice");
276 pd->preset = g_strdup(pd->value);
281 my_key = (const gchar*)g_hash_table_lookup(pd->xlat_key, pd->key);
283 { // Do something with it
284 if (my_key[0] != 0) // intentionally ignored keys
286 if (pd->value != NULL)
288 g_hash_table_insert(pd->settings,
289 g_strdup(my_key), g_strdup(pd->value));
293 g_message("NULL value");
297 else if (IS_KEY(pd->key, "Audio1Encoder"))
299 if (audio_enc[0]) g_free(audio_enc[0]);
300 audio_enc[0] = g_strdup(pd->value);
302 else if (IS_KEY(pd->key, "Audio1Bitrate"))
304 if (audio_bitrate[0]) g_free(audio_bitrate[0]);
305 audio_bitrate[0] = g_strdup(pd->value);
307 else if (IS_KEY(pd->key, "Audio1Samplerate"))
309 if (audio_rate[0]) g_free(audio_rate[0]);
310 audio_rate[0] = g_strdup(pd->value);
312 else if (IS_KEY(pd->key, "Audio1Mixdown"))
314 if (audio_mix[0]) g_free(audio_mix[0]);
315 audio_mix[0] = g_strdup(pd->value);
317 else if (IS_KEY(pd->key, "Audio1TrackDRCSlider"))
319 if (audio_drc[0]) g_free(audio_drc[0]);
320 audio_drc[0] = g_strdup(pd->value);
322 else if (IS_KEY(pd->key, "Audio1Track"))
324 if (audio_track[0]) g_free(audio_track[0]);
325 audio_track[0] = g_strdup(pd->value);
327 else if (IS_KEY(pd->key, "Audio2Encoder"))
329 if (audio_enc[1]) g_free(audio_enc[1]);
330 audio_enc[1] = g_strdup(pd->value);
332 else if (IS_KEY(pd->key, "Audio2Bitrate"))
334 if (audio_bitrate[1]) g_free(audio_bitrate[1]);
335 audio_bitrate[1] = g_strdup(pd->value);
337 else if (IS_KEY(pd->key, "Audio2Samplerate"))
339 if (audio_rate[1]) g_free(audio_rate[1]);
340 audio_rate[1] = g_strdup(pd->value);
342 else if (IS_KEY(pd->key, "Audio2Mixdown"))
344 if (audio_mix[1]) g_free(audio_mix[1]);
345 audio_mix[1] = g_strdup(pd->value);
347 else if (IS_KEY(pd->key, "Audio2TrackDRCSlider"))
349 if (audio_drc[1]) g_free(audio_drc[1]);
350 audio_drc[1] = g_strdup(pd->value);
352 else if (IS_KEY(pd->key, "Audio2Track"))
354 if (audio_track[1]) g_free(audio_track[1]);
355 audio_track[1] = g_strdup(pd->value);
357 else if (IS_KEY(pd->key, "VideoQualityType"))
359 // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
360 if (IS_VAL(pd->value, "0"))
362 g_hash_table_insert(pd->settings,
363 g_strdup("vquality_type_target"),
365 g_hash_table_remove(pd->settings, "vquality_type_bitrate");
366 g_hash_table_remove(pd->settings, "vquality_type_constant");
368 else if (IS_VAL(pd->value, "1"))
370 g_hash_table_remove(pd->settings, "vquality_type_target");
371 g_hash_table_insert(pd->settings,
372 g_strdup("vquality_type_bitrate"),
374 g_hash_table_remove(pd->settings, "vquality_type_constant");
376 else if (IS_VAL(pd->value, "2"))
378 g_hash_table_remove(pd->settings, "vquality_type_target");
379 g_hash_table_remove(pd->settings, "vquality_type_bitrate");
380 g_hash_table_insert(pd->settings,
381 g_strdup("vquality_type_constant"),
387 g_message("Key not found (%s)", pd->key);
390 else if (IS_TAG(name, "dict"))
403 g_message("Preset has no name");
404 g_hash_table_remove_all(pd->settings);
410 is_number(const gchar *str)
412 gboolean result = TRUE;
414 for (ii = 0; str[ii] != 0; ii++)
416 if (!g_ascii_isdigit(str[ii]) && str[ii] != '.')
424 GMarkupParseContext *ctx,
430 gboolean is_value = FALSE;
431 parse_data_t *pd = (parse_data_t*)ud;
432 const gchar *val = NULL;
434 if (pd->state == KEY)
436 if (pd->key) g_free(pd->key);
437 pd->key = g_strdup(text);
440 if (pd->state == STR)
442 val = (gchar*)g_hash_table_lookup(pd->xlat_value, text);
444 { // Do something with it
446 else if (IS_KEY(pd->key, "PresetName") ||
447 IS_KEY(pd->key, "PresetDescription") ||
448 IS_KEY(pd->key, "x264Option") ||
455 g_message("Unrecognized val (%s)", text);
458 if (pd->state == INT || pd->state == REAL)
463 // Some keys need further translation of their values
466 if (IS_KEY(pd->key, "PictureDeinterlace"))
468 if (IS_VAL(val, "0"))
472 else if (IS_VAL(val, "1"))
476 else if (IS_VAL(val, "2"))
480 else if (IS_VAL(val, "3"))
485 else if (IS_KEY(pd->key, "Audio1Samplerate") ||
486 IS_KEY(pd->key, "Audio2Samplerate"))
488 if (IS_VAL(val, "auto"))
493 else if (IS_KEY(pd->key, "Audio1Mixdown") ||
494 IS_KEY(pd->key, "Audio2Mixdown"))
496 if (IS_VAL(val, "ac3"))
501 if (pd->value) g_free(pd->value);
502 pd->value = g_strdup(val);
508 GMarkupParseContext *ctx,
514 parse_data_t *pd = (parse_data_t*)ud;
516 g_debug("passthrough %s", text);
520 delete_key(gpointer str)
526 delete_value(gpointer str)
537 static xlat_t keys[] =
539 {"VFR", "variable_frame_rate"},
540 {"ChapterMarkers", "chapter_markers"},
542 {"FileFormat", "container"},
543 {"PictureAutoCrop", "autocrop"},
544 {"PictureBottomCrop", ""},
545 {"PictureTopCrop", ""},
546 {"PictureLeftCrop", ""},
547 {"PictureRightCrop", ""},
548 {"PictureDeblock", "deblock"},
549 {"PictureDeinterlace", "deinterlace"}, // v
550 {"PictureDenoise", "denoise"}, // v
551 {"PictureDetelecine", "detelecine"},
552 {"PictureHeight", "max_height"},
553 {"PictureWidth", "max_width"},
554 {"PictureKeepRatio", "keep_aspect"},
555 {"PicturePAR", "anamorphic"}, // v
556 {"PresetDescription", "preset_description"},
557 {"Subtitles", "subtitle_lang"},
558 {"Subtitles", "subtitle_lang"},
559 {"Type", ""}, // preset type builtin/custom
560 {"UsesMaxPictureSettings", "autoscale"},
561 {"UsesPictureFilters", ""},
562 {"UsesPictureSettings", ""},
563 {"VideoAvgBitrate", "video_bitrate"},
564 {"VideoEncoder", "video_codec"},
565 {"VideoFramerate", "framerate"},
566 {"VideoGrayScale", "grayscale"},
567 {"VideoQualitySlider", "video_quality"},
568 {"VideoTargetSize", "video_target_size"},
569 {"VideoTurboTwoPass", "turbo"},
570 {"VideoTwoPass", "two_pass"},
571 {"x264Option", "x264_options"},
572 {"Mp4LargeFile", "large_mp4"},
573 {"Mp4iPodCompatible", "ipod_file"},
577 // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
578 // Audio1Bitrate - pref_audio_bitrate
579 // Audio1Encoder - pref_audio_codec
580 // Audio1Mixdown - pref_audio_mix
581 // Audio1Samplerate - pref_audio_rate
583 // Audio1DRCSlider - pref_audio_drc
585 static xlat_t values[] =
587 {"AAC (faac)", "faac"},
588 {"AC3 Passthru", "ac3"},
589 {"H.264 (x264)", "x264"},
590 {"MPEG-4 (FFmpeg)", "x264"},
591 {"Dolby Pro Logic II", "dpl2"},
596 {"Same as source", "source"},
602 store_key_file(GKeyFile *key_file, const gchar *name)
604 gchar *settingsString;
608 settingsString = g_key_file_to_data(key_file, &length, NULL);
610 fd = g_open(name, O_RDWR|O_CREAT|O_TRUNC, 0777);
611 write(fd, settingsString, length);
613 g_free(settingsString);
617 parse_it(gchar *buf, gssize len)
619 GMarkupParseContext *ctx;
620 GMarkupParser parser;
624 presets = g_key_file_new();
629 pd.settings = g_hash_table_new_full(g_str_hash, g_str_equal,
630 delete_key, delete_value);
631 pd.xlat_key = g_hash_table_new(g_str_hash, g_str_equal);
633 for (ii = 0; keys[ii].from != NULL; ii++)
635 g_hash_table_insert(pd.xlat_key, keys[ii].from, keys[ii].to);
637 pd.xlat_value = g_hash_table_new(g_str_hash, g_str_equal);
638 for (ii = 0; values[ii].from != NULL; ii++)
640 g_hash_table_insert(pd.xlat_value, values[ii].from, values[ii].to);
642 parser.start_element = start_element;
643 parser.end_element = end_element;
644 parser.text = text_data;
645 parser.passthrough = passthrough;
646 ctx = g_markup_parse_context_new(&parser, 0, &pd, NULL);
647 g_markup_parse_context_parse(ctx, buf, len, NULL);
648 store_key_file(presets, "xlat_presets");
652 main(gint argc, gchar *argv[])
655 gchar buffer[BUF_SIZ];
658 fd = fopen(argv[1], "r");
659 size = fread(buffer, 1, BUF_SIZ, fd);
662 g_error("buffer too small");
666 parse_it(buffer, (gssize)size);