summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gtk/src/preset_xlat.c668
1 files changed, 668 insertions, 0 deletions
diff --git a/gtk/src/preset_xlat.c b/gtk/src/preset_xlat.c
new file mode 100644
index 000000000..1c77e7716
--- /dev/null
+++ b/gtk/src/preset_xlat.c
@@ -0,0 +1,668 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <fcntl.h>
+
+#define BUF_SIZ (128*1024)
+#define IS_TAG(a,b) (strcmp((a),(b)) == 0)
+#define IS_KEY(a,b) (strcmp((a),(b)) == 0)
+#define IS_VAL(a,b) (strcmp((a),(b)) == 0)
+
+enum
+{
+ NONE,
+ START,
+ ARRAY,
+ DICT,
+ KEY,
+ INT,
+ STR,
+ REAL,
+};
+
+typedef struct
+{
+ gint state;
+ gchar *preset;
+ gchar *key;
+ gchar *value;
+ GHashTable *settings;
+ GHashTable *xlat_key;
+ GHashTable *xlat_value;
+} parse_data_t;
+
+static void
+start_element(
+ GMarkupParseContext *ctx,
+ const gchar *name,
+ const gchar **attr_names,
+ const gchar **attr_values,
+ gpointer ud,
+ GError **error)
+{
+ parse_data_t *pd = (parse_data_t*)ud;
+
+ if (IS_TAG(name, "array"))
+ {
+ pd->state = ARRAY;
+ }
+ else if (IS_TAG(name, "dict"))
+ {
+ g_hash_table_remove_all(pd->settings);
+ pd->state = DICT;
+ }
+ else if (IS_TAG(name, "key"))
+ {
+ pd->state = KEY;
+ }
+ else if (IS_TAG(name, "string"))
+ {
+ pd->state = STR;
+ }
+ else if (IS_TAG(name, "integer"))
+ {
+ pd->state = INT;
+ }
+ else if (IS_TAG(name, "real"))
+ {
+ pd->state = REAL;
+ }
+ else
+ {
+ g_debug("start unrecognized (%s)", name);
+ }
+}
+
+gchar *settings[] =
+{
+ "preset_description",
+ "subtitle_lang",
+ "forced_subtitles",
+ "source_audio_lang",
+ "pref_audio_codec",
+ "pref_audio_bitrate",
+ "pref_audio_rate",
+ "pref_audio_mix",
+ "pref_audio_drc",
+ "chapter_markers",
+ "container",
+ "ipod_file",
+ "large_mp4",
+ "autocrop",
+ "autoscale",
+ "max_width",
+ "max_height",
+ "anamorphic",
+ "round_dimensions",
+ "keep_aspect",
+ "detelecine",
+ "decomb",
+ "deinterlace",
+ "denoise",
+ "grayscale",
+ "deblock",
+ "video_codec",
+ "two_pass",
+ "turbo",
+ "constant_rate_factor",
+ "variable_frame_rate",
+ "framerate",
+ "vquality_type_constant",
+ "vquality_type_bitrate",
+ "vquality_type_target",
+ "video_bitrate",
+ "video_target_size",
+ "video_quality",
+ "x264_options",
+ "directqp",
+ NULL
+};
+
+static void
+verify_keys(parse_data_t *pd)
+{
+ GList *keys, *link;
+
+ link = keys = g_hash_table_get_keys(pd->settings);
+ while (link)
+ {
+ gboolean found = FALSE;
+ gchar *key = (gchar*)link->data;
+ gint ii;
+ for (ii = 0; settings[ii] != NULL; ii++)
+ {
+ if (IS_KEY(settings[ii], key))
+ {
+ found = TRUE;
+ }
+ }
+ if (!found)
+ {
+ g_message("bad key (%s)", key);
+ }
+ link = link->next;
+ }
+ g_list_free(keys);
+}
+
+GKeyFile *presets;
+
+static void
+save_preset(parse_data_t *pd)
+{
+ gint ii;
+ if (pd->preset == NULL)
+ {
+ g_message("failed to save preset");
+ return;
+ }
+ for (ii = 0; settings[ii] != NULL; ii++)
+ {
+ const gchar *value;
+ value = (const gchar*)g_hash_table_lookup( pd->settings, settings[ii]);
+ if (value)
+ {
+ g_key_file_set_value(presets, pd->preset, settings[ii], value);
+ }
+ }
+ verify_keys(pd);
+}
+
+gchar *audio_track[2];
+gchar *audio_enc[2];
+gchar *audio_bitrate[2];
+gchar *audio_rate[2];
+gchar *audio_mix[2];
+gchar *audio_drc[2];
+
+static void
+do_one(gchar **strs, GString *res)
+{
+ gint ii;
+ for (ii = 0; ii < 2 && strs[ii]; ii++)
+ {
+ if (audio_track[ii] == NULL) break;
+ if (ii)
+ g_string_append_c(res, ',');
+ g_string_append_printf(res, "%s", strs[ii]);
+ }
+}
+
+static void
+do_audio(parse_data_t *pd)
+{
+ gint ii;
+ GString *enc, *br, *rate, *mix, *drc;
+ gchar *res;
+
+ enc = g_string_new("");
+ br = g_string_new("");
+ rate = g_string_new("");
+ mix = g_string_new("");
+ drc = g_string_new("");
+ do_one(audio_enc, enc);
+ do_one(audio_bitrate, br);
+ do_one(audio_rate, rate);
+ do_one(audio_mix, mix);
+ do_one(audio_drc, drc);
+ res = g_string_free(enc, FALSE);
+ g_hash_table_insert(pd->settings, g_strdup("pref_audio_codec"), res);
+ res = g_string_free(br, FALSE);
+ g_hash_table_insert(pd->settings, g_strdup("pref_audio_bitrate"), res);
+ res = g_string_free(rate, FALSE);
+ g_hash_table_insert(pd->settings, g_strdup("pref_audio_rate"), res);
+ res = g_string_free(mix, FALSE);
+ g_hash_table_insert(pd->settings, g_strdup("pref_audio_mix"), res);
+ res = g_string_free(drc, FALSE);
+ g_hash_table_insert(pd->settings, g_strdup("pref_audio_drc"), res);
+}
+
+static void
+null_audio()
+{
+ gint ii;
+ for (ii = 0; ii < 2; ii++)
+ {
+ audio_track[ii] = NULL;
+ audio_enc[ii] = NULL;
+ audio_bitrate[ii] = NULL;
+ audio_rate[ii] = NULL;
+ audio_mix[ii] = NULL;
+ audio_drc[ii] = NULL;
+ }
+}
+
+static void
+clear_audio()
+{
+ gint ii;
+ for (ii = 0; ii < 2; ii++)
+ {
+ if (audio_track[ii]) g_free(audio_track[ii]);
+ if (audio_enc[ii]) g_free(audio_enc[ii]);
+ if (audio_bitrate[ii]) g_free(audio_bitrate[ii]);
+ if (audio_rate[ii]) g_free(audio_rate[ii]);
+ if (audio_mix[ii]) g_free(audio_mix[ii]);
+ if (audio_drc[ii]) g_free(audio_drc[ii]);
+ audio_track[ii] = NULL;
+ audio_enc[ii] = NULL;
+ audio_bitrate[ii] = NULL;
+ audio_rate[ii] = NULL;
+ audio_mix[ii] = NULL;
+ audio_drc[ii] = NULL;
+ }
+}
+
+static void
+end_element(
+ GMarkupParseContext *ctx,
+ const gchar *name,
+ gpointer ud,
+ GError **error)
+{
+ parse_data_t *pd = (parse_data_t*)ud;
+
+ if (IS_TAG(name, "string") ||
+ IS_TAG(name, "integer") ||
+ IS_TAG(name, "real"))
+ {
+ if (IS_KEY(pd->key, "PresetName"))
+ {
+ if (pd->preset)
+ {
+ g_message("Preset named twice");
+ }
+ else
+ pd->preset = g_strdup(pd->value);
+ pd->state = NONE;
+ return;
+ }
+ const gchar *my_key;
+ my_key = (const gchar*)g_hash_table_lookup(pd->xlat_key, pd->key);
+ if (my_key != NULL)
+ { // Do something with it
+ if (my_key[0] != 0) // intentionally ignored keys
+ {
+ if (pd->value != NULL)
+ {
+ g_hash_table_insert(pd->settings,
+ g_strdup(my_key), g_strdup(pd->value));
+ }
+ else
+ {
+ g_message("NULL value");
+ }
+ }
+ }
+ else if (IS_KEY(pd->key, "Audio1Encoder"))
+ {
+ if (audio_enc[0]) g_free(audio_enc[0]);
+ audio_enc[0] = g_strdup(pd->value);
+ }
+ else if (IS_KEY(pd->key, "Audio1Bitrate"))
+ {
+ if (audio_bitrate[0]) g_free(audio_bitrate[0]);
+ audio_bitrate[0] = g_strdup(pd->value);
+ }
+ else if (IS_KEY(pd->key, "Audio1Samplerate"))
+ {
+ if (audio_rate[0]) g_free(audio_rate[0]);
+ audio_rate[0] = g_strdup(pd->value);
+ }
+ else if (IS_KEY(pd->key, "Audio1Mixdown"))
+ {
+ if (audio_mix[0]) g_free(audio_mix[0]);
+ audio_mix[0] = g_strdup(pd->value);
+ }
+ else if (IS_KEY(pd->key, "Audio1TrackDRCSlider"))
+ {
+ if (audio_drc[0]) g_free(audio_drc[0]);
+ audio_drc[0] = g_strdup(pd->value);
+ }
+ else if (IS_KEY(pd->key, "Audio1Track"))
+ {
+ if (audio_track[0]) g_free(audio_track[0]);
+ audio_track[0] = g_strdup(pd->value);
+ }
+ else if (IS_KEY(pd->key, "Audio2Encoder"))
+ {
+ if (audio_enc[1]) g_free(audio_enc[1]);
+ audio_enc[1] = g_strdup(pd->value);
+ }
+ else if (IS_KEY(pd->key, "Audio2Bitrate"))
+ {
+ if (audio_bitrate[1]) g_free(audio_bitrate[1]);
+ audio_bitrate[1] = g_strdup(pd->value);
+ }
+ else if (IS_KEY(pd->key, "Audio2Samplerate"))
+ {
+ if (audio_rate[1]) g_free(audio_rate[1]);
+ audio_rate[1] = g_strdup(pd->value);
+ }
+ else if (IS_KEY(pd->key, "Audio2Mixdown"))
+ {
+ if (audio_mix[1]) g_free(audio_mix[1]);
+ audio_mix[1] = g_strdup(pd->value);
+ }
+ else if (IS_KEY(pd->key, "Audio2TrackDRCSlider"))
+ {
+ if (audio_drc[1]) g_free(audio_drc[1]);
+ audio_drc[1] = g_strdup(pd->value);
+ }
+ else if (IS_KEY(pd->key, "Audio2Track"))
+ {
+ if (audio_track[1]) g_free(audio_track[1]);
+ audio_track[1] = g_strdup(pd->value);
+ }
+ else if (IS_KEY(pd->key, "VideoQualityType"))
+ {
+ // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
+ if (IS_VAL(pd->value, "0"))
+ {
+ g_hash_table_insert(pd->settings,
+ g_strdup("vquality_type_target"),
+ g_strdup("1"));
+ g_hash_table_remove(pd->settings, "vquality_type_bitrate");
+ g_hash_table_remove(pd->settings, "vquality_type_constant");
+ }
+ else if (IS_VAL(pd->value, "1"))
+ {
+ g_hash_table_remove(pd->settings, "vquality_type_target");
+ g_hash_table_insert(pd->settings,
+ g_strdup("vquality_type_bitrate"),
+ g_strdup("1"));
+ g_hash_table_remove(pd->settings, "vquality_type_constant");
+ }
+ else if (IS_VAL(pd->value, "2"))
+ {
+ g_hash_table_remove(pd->settings, "vquality_type_target");
+ g_hash_table_remove(pd->settings, "vquality_type_bitrate");
+ g_hash_table_insert(pd->settings,
+ g_strdup("vquality_type_constant"),
+ g_strdup("1"));
+ }
+ }
+ else
+ {
+ g_message("Key not found (%s)", pd->key);
+ }
+ }
+ else if (IS_TAG(name, "dict"))
+ {
+ gint ii;
+ do_audio(pd);
+ clear_audio();
+ save_preset(pd);
+
+ if (pd->preset)
+ {
+ g_free(pd->preset);
+ pd->preset = NULL;
+ }
+ else
+ g_message("Preset has no name");
+ g_hash_table_remove_all(pd->settings);
+ }
+ pd->state = NONE;
+}
+
+static gboolean
+is_number(const gchar *str)
+{
+ gboolean result = TRUE;
+ gint ii;
+ for (ii = 0; str[ii] != 0; ii++)
+ {
+ if (!g_ascii_isdigit(str[ii]) && str[ii] != '.')
+ result = FALSE;
+ }
+ return result;
+}
+
+static void
+text_data(
+ GMarkupParseContext *ctx,
+ const gchar *text,
+ gsize len,
+ gpointer ud,
+ GError **error)
+{
+ gboolean is_value = FALSE;
+ parse_data_t *pd = (parse_data_t*)ud;
+ const gchar *val = NULL;
+
+ if (pd->state == KEY)
+ {
+ if (pd->key) g_free(pd->key);
+ pd->key = g_strdup(text);
+ return;
+ }
+ if (pd->state == STR)
+ {
+ val = (gchar*)g_hash_table_lookup(pd->xlat_value, text);
+ if (val != NULL)
+ { // Do something with it
+ }
+ else if (IS_KEY(pd->key, "PresetName") ||
+ IS_KEY(pd->key, "PresetDescription") ||
+ IS_KEY(pd->key, "x264Option") ||
+ is_number(text))
+ {
+ val = text;
+ }
+ else
+ {
+ g_message("Unrecognized val (%s)", text);
+ }
+ }
+ if (pd->state == INT || pd->state == REAL)
+ {
+ val = text;
+ }
+
+ // Some keys need further translation of their values
+ if (val)
+ {
+ if (IS_KEY(pd->key, "PictureDeinterlace"))
+ {
+ if (IS_VAL(val, "0"))
+ {
+ val = "none";
+ }
+ else if (IS_VAL(val, "1"))
+ {
+ val = "fast";
+ }
+ else if (IS_VAL(val, "2"))
+ {
+ val = "slow";
+ }
+ else if (IS_VAL(val, "3"))
+ {
+ val = "slower";
+ }
+ }
+ else if (IS_KEY(pd->key, "Audio1Samplerate") ||
+ IS_KEY(pd->key, "Audio2Samplerate"))
+ {
+ if (IS_VAL(val, "auto"))
+ {
+ val = "source";
+ }
+ }
+ else if (IS_KEY(pd->key, "Audio1Mixdown") ||
+ IS_KEY(pd->key, "Audio2Mixdown"))
+ {
+ if (IS_VAL(val, "ac3"))
+ {
+ val = "none";
+ }
+ }
+ if (pd->value) g_free(pd->value);
+ pd->value = g_strdup(val);
+ }
+}
+
+static void
+passthrough(
+ GMarkupParseContext *ctx,
+ const gchar *text,
+ gsize len,
+ gpointer ud,
+ GError **error)
+{
+ parse_data_t *pd = (parse_data_t*)ud;
+
+ g_debug("passthrough %s", text);
+}
+
+static void
+delete_key(gpointer str)
+{
+ g_free(str);
+}
+
+static void
+delete_value(gpointer str)
+{
+ g_free(str);
+}
+
+typedef struct
+{
+ gchar *from;
+ gchar *to;
+} xlat_t;
+
+static xlat_t keys[] =
+{
+ {"VFR", "variable_frame_rate"},
+ {"ChapterMarkers", "chapter_markers"},
+ {"Default", ""},
+ {"FileFormat", "container"},
+ {"PictureAutoCrop", "autocrop"},
+ {"PictureBottomCrop", ""},
+ {"PictureTopCrop", ""},
+ {"PictureLeftCrop", ""},
+ {"PictureRightCrop", ""},
+ {"PictureDeblock", "deblock"},
+ {"PictureDeinterlace", "deinterlace"}, // v
+ {"PictureDenoise", "denoise"}, // v
+ {"PictureDetelecine", "detelecine"},
+ {"PictureHeight", "max_height"},
+ {"PictureWidth", "max_width"},
+ {"PictureKeepRatio", "keep_aspect"},
+ {"PicturePAR", "anamorphic"}, // v
+ {"PresetDescription", "preset_description"},
+ {"Subtitles", "subtitle_lang"},
+ {"Subtitles", "subtitle_lang"},
+ {"Type", ""}, // preset type builtin/custom
+ {"UsesMaxPictureSettings", "autoscale"},
+ {"UsesPictureFilters", ""},
+ {"UsesPictureSettings", ""},
+ {"VideoAvgBitrate", "video_bitrate"},
+ {"VideoEncoder", "video_codec"},
+ {"VideoFramerate", "framerate"},
+ {"VideoGrayScale", "grayscale"},
+ {"VideoQualitySlider", "video_quality"},
+ {"VideoTargetSize", "video_target_size"},
+ {"VideoTurboTwoPass", "turbo"},
+ {"VideoTwoPass", "two_pass"},
+ {"x264Option", "x264_options"},
+ {"Mp4LargeFile", "large_mp4"},
+ {"Mp4iPodCompatible", "ipod_file"},
+ {NULL, NULL}
+};
+
+// VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
+// Audio1Bitrate - pref_audio_bitrate
+// Audio1Encoder - pref_audio_codec
+// Audio1Mixdown - pref_audio_mix
+// Audio1Samplerate - pref_audio_rate
+// Audio1Track - na
+// Audio1DRCSlider - pref_audio_drc
+
+static xlat_t values[] =
+{
+ {"AAC (faac)", "faac"},
+ {"AC3 Passthru", "ac3"},
+ {"H.264 (x264)", "x264"},
+ {"MPEG-4 (FFmpeg)", "x264"},
+ {"Dolby Pro Logic II", "dpl2"},
+ {"Auto", "auto"},
+ {"MKV file", "mkv"},
+ {"MP4 file", "mp4"},
+ {"None", "none"},
+ {"Same as source", "source"},
+ {"160", "160"},
+ {NULL, NULL}
+};
+
+static void
+store_key_file(GKeyFile *key_file, const gchar *name)
+{
+ gchar *settingsString;
+ gsize length;
+ gint fd;
+
+ settingsString = g_key_file_to_data(key_file, &length, NULL);
+
+ fd = g_open(name, O_RDWR|O_CREAT|O_TRUNC, 0777);
+ write(fd, settingsString, length);
+ close(fd);
+ g_free(settingsString);
+}
+
+static void
+parse_it(gchar *buf, gssize len)
+{
+ GMarkupParseContext *ctx;
+ GMarkupParser parser;
+ parse_data_t pd;
+
+ null_audio();
+ presets = g_key_file_new();
+ pd.state = START;
+ pd.key = NULL;
+ pd.value = NULL;
+ pd.preset = NULL;
+ pd.settings = g_hash_table_new_full(g_str_hash, g_str_equal,
+ delete_key, delete_value);
+ pd.xlat_key = g_hash_table_new(g_str_hash, g_str_equal);
+ gint ii;
+ for (ii = 0; keys[ii].from != NULL; ii++)
+ {
+ g_hash_table_insert(pd.xlat_key, keys[ii].from, keys[ii].to);
+ }
+ pd.xlat_value = g_hash_table_new(g_str_hash, g_str_equal);
+ for (ii = 0; values[ii].from != NULL; ii++)
+ {
+ g_hash_table_insert(pd.xlat_value, values[ii].from, values[ii].to);
+ }
+ parser.start_element = start_element;
+ parser.end_element = end_element;
+ parser.text = text_data;
+ parser.passthrough = passthrough;
+ ctx = g_markup_parse_context_new(&parser, 0, &pd, NULL);
+ g_markup_parse_context_parse(ctx, buf, len, NULL);
+ store_key_file(presets, "xlat_presets");
+}
+
+gint
+main(gint argc, gchar *argv[])
+{
+ FILE *fd;
+ gchar buffer[BUF_SIZ];
+ size_t size;
+
+ fd = fopen(argv[1], "r");
+ size = fread(buffer, 1, BUF_SIZ, fd);
+ if (size >= BUF_SIZ)
+ {
+ g_error("buffer too small");
+ exit(1);
+ }
+ buffer[size] = 0;
+ parse_it(buffer, (gssize)size);
+}
+