diff options
author | jstebbins <[email protected]> | 2008-08-07 17:43:55 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2008-08-07 17:43:55 +0000 |
commit | 752317f0446985db9179dcc975f10652400af589 (patch) | |
tree | 335e0f670d4e88d5b9259fdec9bdc54b07b6a5a0 /gtk/src/settings.c | |
parent | c8ed1a0c1534761b2081f6c7ea71bf7c4a698d78 (diff) |
LinGui: change how x264 options are handled
- there is now one preset key that contains the option string
- options displayed in widgets and entry box stay reflect each other
- enlarged the entry box so all options can be seen
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1614 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'gtk/src/settings.c')
-rw-r--r-- | gtk/src/settings.c | 512 |
1 files changed, 491 insertions, 21 deletions
diff --git a/gtk/src/settings.c b/gtk/src/settings.c index 31678de7c..1e78fcbd6 100644 --- a/gtk/src/settings.c +++ b/gtk/src/settings.c @@ -311,12 +311,13 @@ ghb_widget_value(GtkWidget *widget) return NULL; } value = g_malloc(sizeof(setting_value_t)); + + type = GTK_WIDGET_TYPE(widget); if (GTK_IS_ACTION(widget)) name = gtk_action_get_name(GTK_ACTION(widget)); else name = gtk_widget_get_name(widget); g_debug("ghb_widget_value widget (%s)\n", name); - type = GTK_OBJECT_TYPE(widget); if (type == GTK_TYPE_ENTRY) { const gchar *str = gtk_entry_get_text((GtkEntry*)widget); @@ -336,7 +337,7 @@ ghb_widget_value(GtkWidget *widget) g_debug("\tenable"); value->option = g_strdup("enable"); value->shortOpt = g_strdup("enable"); - value->svalue = g_strdup("enable"); + value->svalue = g_strdup("1"); value->ivalue = 1; value->dvalue = 1; } @@ -345,7 +346,7 @@ ghb_widget_value(GtkWidget *widget) g_debug("\tdisable"); value->option = g_strdup("disable"); value->shortOpt = g_strdup("disable"); - value->svalue = g_strdup("disable"); + value->svalue = g_strdup("0"); value->ivalue = 0; value->dvalue = 0; } @@ -359,7 +360,7 @@ ghb_widget_value(GtkWidget *widget) g_debug("\tenable"); value->option = g_strdup("enable"); value->shortOpt = g_strdup("enable"); - value->svalue = g_strdup("enable"); + value->svalue = g_strdup("1"); value->ivalue = 1; value->dvalue = 1; } @@ -368,7 +369,7 @@ ghb_widget_value(GtkWidget *widget) g_debug("\tdisable"); value->option = g_strdup("disable"); value->shortOpt = g_strdup("disable"); - value->svalue = g_strdup("disable"); + value->svalue = g_strdup("0"); value->ivalue = 0; value->dvalue = 0; } @@ -382,7 +383,7 @@ ghb_widget_value(GtkWidget *widget) g_debug("\tenable"); value->option = g_strdup("enable"); value->shortOpt = g_strdup("enable"); - value->svalue = g_strdup("enable"); + value->svalue = g_strdup("1"); value->ivalue = 1; value->dvalue = 1; } @@ -391,7 +392,7 @@ ghb_widget_value(GtkWidget *widget) g_debug("\tdisable"); value->option = g_strdup("disable"); value->shortOpt = g_strdup("disable"); - value->svalue = g_strdup("disable"); + value->svalue = g_strdup("0"); value->ivalue = 0; value->dvalue = 0; } @@ -405,7 +406,7 @@ ghb_widget_value(GtkWidget *widget) g_debug("\tenable"); value->option = g_strdup("enable"); value->shortOpt = g_strdup("enable"); - value->svalue = g_strdup("enable"); + value->svalue = g_strdup("1"); value->ivalue = 1; value->dvalue = 1; } @@ -414,7 +415,7 @@ ghb_widget_value(GtkWidget *widget) g_debug("\tdisable"); value->option = g_strdup("disable"); value->shortOpt = g_strdup("disable"); - value->svalue = g_strdup("disable"); + value->svalue = g_strdup("0"); value->ivalue = 0; value->dvalue = 0; } @@ -477,7 +478,6 @@ ghb_widget_value(GtkWidget *widget) value->svalue = gtk_text_buffer_get_text(buffer, &start, &end, FALSE); value->option = g_strdup(value->svalue); value->shortOpt = g_strdup(value->svalue); - g_debug("text view (%s)\n", value->svalue); value->ivalue = 0; value->dvalue = 0; value->index = 0; @@ -627,7 +627,7 @@ update_widget(GtkWidget *widget, const gchar *parm_svalue, gint parm_ivalue) GType type; gchar *value; - g_debug("update_widget\n"); + g_debug("update_widget"); // make a dup of setting value because the setting hash gets // modified and thus the value pointer can become invalid. if (parm_svalue == NULL) @@ -638,31 +638,31 @@ update_widget(GtkWidget *widget, const gchar *parm_svalue, gint parm_ivalue) { value = g_strdup(parm_svalue); } - g_debug("update widget value (%s)\n", value); + g_debug("update widget value (%s)", value); type = GTK_OBJECT_TYPE(widget); if (type == GTK_TYPE_ENTRY) { - g_debug("entry\n"); + g_debug("entry"); gtk_entry_set_text((GtkEntry*)widget, value); } else if (type == GTK_TYPE_RADIO_BUTTON) { - g_debug("radio button\n"); + g_debug("radio button"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), string_is_true(value)); } else if (type == GTK_TYPE_CHECK_BUTTON) { - g_debug("check button\n"); + g_debug("check button"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), string_is_true(value)); } else if (type == GTK_TYPE_TOGGLE_ACTION) { - g_debug("toggle action\n"); + g_debug("toggle action"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(widget), string_is_true(value)); } else if (type == GTK_TYPE_CHECK_MENU_ITEM) { - g_debug("check menu item\n"); + g_debug("check menu item"); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), string_is_true(value)); } else if (type == GTK_TYPE_COMBO_BOX) @@ -673,6 +673,7 @@ update_widget(GtkWidget *widget, const gchar *parm_svalue, gint parm_ivalue) gint ivalue; gboolean foundit = FALSE; + g_debug("combo"); store = gtk_combo_box_get_model(GTK_COMBO_BOX(widget)); if (gtk_tree_model_get_iter_first (store, &iter)) { @@ -705,7 +706,7 @@ update_widget(GtkWidget *widget, const gchar *parm_svalue, gint parm_ivalue) { gdouble val; - g_debug("spin\n"); + g_debug("spin (%s)", value); val = g_strtod(value, NULL); gtk_spin_button_set_value((GtkSpinButton*)widget, val); } @@ -713,18 +714,19 @@ update_widget(GtkWidget *widget, const gchar *parm_svalue, gint parm_ivalue) { gdouble val; - g_debug("hscale\n"); + g_debug("hscale"); val = g_strtod(value, NULL); gtk_range_set_value((GtkRange*)widget, val); } else if (type == GTK_TYPE_TEXT_VIEW) { + g_debug("textview (%s)", value); GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)); gtk_text_buffer_set_text (buffer, value, -1); } else { - g_debug("Attempt to set unknown widget type\n"); + g_debug("Attempt to set unknown widget type"); } g_free(value); } @@ -753,7 +755,7 @@ ghb_ui_update_int(signal_user_data_t *ud, const gchar *name, gint ivalue) { GObject *object; - g_debug("ghb_ui_update ()\n"); + g_debug("ghb_ui_update_int ()\n"); object = GHB_OBJECT(ud->builder, name); if (object == NULL) { @@ -1542,3 +1544,471 @@ ghb_presets_remove(GHashTable *settings, const gchar *name) return FALSE; } +enum +{ + X264_OPT_DEBLOCK, + X264_OPT_INT, + X264_OPT_COMBO, + X264_OPT_BOOL, +}; + +struct x264_opt_map_s +{ + gchar **opt_syns; + gchar *name; + gchar *def_val; + gint type; + gboolean found; +}; + +static gchar *x264_ref_syns[] = {"ref", "frameref", NULL}; +static gchar *x264_mixed_syns[] = {"mixed-refs", NULL}; +static gchar *x264_bframes_syns[] = {"bframes", NULL}; +static gchar *x264_direct_syns[] = {"direct", "direct-pred", NULL}; +static gchar *x264_weightb_syns[] = {"weightb", "weight-b", NULL}; +static gchar *x264_brdo_syns[] = {"brdo", "b-rdo", NULL}; +static gchar *x264_bime_syns[] = {"bime", NULL}; +static gchar *x264_bpyramid_syns[] = {"b-pyramid", NULL}; +static gchar *x264_me_syns[] = {"me", NULL}; +static gchar *x264_merange_syns[] = {"merange", "me-range", NULL}; +static gchar *x264_subme_syns[] = {"subme", "subq", NULL}; +static gchar *x264_analyse_syns[] = {"analyse", "partitions", NULL}; +static gchar *x264_8x8dct_syns[] = {"8x8dct", NULL}; +static gchar *x264_deblock_syns[] = {"deblock", "filter", NULL}; +static gchar *x264_trellis_syns[] = {"trellis", NULL}; +static gchar *x264_pskip_syns[] = {"no-fast-pskip", NULL}; +static gchar *x264_decimate_syns[] = {"no-dct-decimate", NULL}; +static gchar *x264_cabac_syns[] = {"cabac", NULL}; + +static gint +find_syn_match(const gchar *opt, gchar **syns) +{ + gint ii; + for (ii = 0; syns[ii] != NULL; ii++) + { + if (strcmp(opt, syns[ii]) == 0) + return ii; + } + return -1; +} + +struct x264_opt_map_s x264_opt_map[] = +{ + {x264_ref_syns, "x264_refs", "1", X264_OPT_INT}, + {x264_mixed_syns, "x264_mixed_refs", "0", X264_OPT_BOOL}, + {x264_bframes_syns, "x264_bframes", "0", X264_OPT_INT}, + {x264_direct_syns, "x264_direct", "spatial", X264_OPT_COMBO}, + {x264_weightb_syns, "x264_weighted_bframes", "0", X264_OPT_BOOL}, + {x264_brdo_syns, "x264_brdo", "0", X264_OPT_BOOL}, + {x264_bime_syns, "x264_bime", "0", X264_OPT_BOOL}, + {x264_bpyramid_syns, "x264_bpyramid", "0", X264_OPT_BOOL}, + {x264_me_syns, "x264_me", "hex", X264_OPT_COMBO}, + {x264_merange_syns, "x264_merange", "16", X264_OPT_INT}, + {x264_subme_syns, "x264_subme", "5", X264_OPT_COMBO}, + {x264_analyse_syns, "x264_analyse", "some", X264_OPT_COMBO}, + {x264_8x8dct_syns, "x264_8x8dct", "0", X264_OPT_BOOL}, + {x264_deblock_syns, "x264_deblock_alpha", "0,0", X264_OPT_DEBLOCK}, + {x264_deblock_syns, "x264_deblock_beta", "0,0", X264_OPT_DEBLOCK}, + {x264_trellis_syns, "x264_trellis", "0", X264_OPT_COMBO}, + {x264_pskip_syns, "x264_no_fast_pskip", "0", X264_OPT_BOOL}, + {x264_decimate_syns, "x264_no_dct_decimate", "0", X264_OPT_BOOL}, + {x264_cabac_syns, "x264_cabac", "1", X264_OPT_BOOL}, +}; +#define X264_OPT_MAP_SIZE (sizeof(x264_opt_map)/sizeof(struct x264_opt_map_s)) + +static const gchar* +x264_opt_get_default(const gchar *opt) +{ + gint jj; + for (jj = 0; jj < X264_OPT_MAP_SIZE; jj++) + { + if (find_syn_match(opt, x264_opt_map[jj].opt_syns) >= 0) + { + return x264_opt_map[jj].def_val; + } + } + return ""; +} + +static void +x264_update_int(signal_user_data_t *ud, const gchar *name, const gchar *val) +{ + gdouble dvalue; + gchar *end; + + if (val == NULL) return; + dvalue = g_strtod (val, &end); + ghb_ui_update_int(ud, name, dvalue); +} + +static void +x264_update_bool(signal_user_data_t *ud, const gchar *name, const gchar *val) +{ + if (val == NULL) + ghb_ui_update(ud, name, "1"); + else + ghb_ui_update(ud, name, val); +} + +static void +x264_update_combo(signal_user_data_t *ud, const gchar *name, const gchar *val) +{ + GtkTreeModel *store; + GtkTreeIter iter; + gchar *shortOpt; + gint ivalue; + gboolean foundit = FALSE; + GtkWidget *widget; + + if (val == NULL) return; + widget = GHB_WIDGET(ud->builder, name); + if (widget == NULL) + { + g_debug("Failed to find widget for key: %s\n", name); + return; + } + store = gtk_combo_box_get_model(GTK_COMBO_BOX(widget)); + if (gtk_tree_model_get_iter_first (store, &iter)) + { + do + { + gtk_tree_model_get(store, &iter, 2, &shortOpt, 3, &ivalue, -1); + if (strcmp(shortOpt, val) == 0) + { + gtk_combo_box_set_active_iter (GTK_COMBO_BOX(widget), &iter); + g_free(shortOpt); + foundit = TRUE; + break; + } + g_free(shortOpt); + } while (gtk_tree_model_iter_next (store, &iter)); + } + if (!foundit) + { + if (gtk_tree_model_get_iter_first (store, &iter)) + { + do + { + gtk_tree_model_get(store, &iter, 2, &shortOpt, 3, &ivalue, -1); + if (strcmp(shortOpt, "custom") == 0) + { + gtk_list_store_set(GTK_LIST_STORE(store), &iter, 4, val, -1); + gtk_combo_box_set_active_iter (GTK_COMBO_BOX(widget), &iter); + g_free(shortOpt); + foundit = TRUE; + break; + } + g_free(shortOpt); + } while (gtk_tree_model_iter_next (store, &iter)); + } + } + // Its possible the value hasn't changed. Since settings are only + // updated when the value changes, I'm initializing settings here as well. + ghb_widget_to_setting(ud->settings, widget); +} + +static void +x264_update_deblock(signal_user_data_t *ud, const gchar *xval) +{ + gdouble avalue, bvalue; + gchar *end; + gchar *val; + gchar *bval = NULL; + + if (xval == NULL) return; + val = g_strdup(xval); + bvalue = avalue = 0; + if (val != NULL) + { + gchar *pos = strchr(val, ','); + if (pos != NULL) + { + bval = pos + 1; + *pos = 0; + } + avalue = g_strtod (val, &end); + if (bval != NULL) + { + bvalue = g_strtod (bval, &end); + } + } + g_free(val); + ghb_ui_update_int(ud, "x264_deblock_alpha", avalue); + ghb_ui_update_int(ud, "x264_deblock_beta", bvalue); +} + +void +ghb_x264_parse_options(signal_user_data_t *ud, const gchar *options) +{ + gchar **split = g_strsplit(options, ":", -1); + if (split == NULL) return; + + gint ii; + gint jj; + + for (jj = 0; jj < X264_OPT_MAP_SIZE; jj++) + x264_opt_map[jj].found = FALSE; + + for (ii = 0; split[ii] != NULL; ii++) + { + gchar *val = NULL; + gchar *pos = strchr(split[ii], '='); + if (pos != NULL) + { + val = pos + 1; + *pos = 0; + } + for (jj = 0; jj < X264_OPT_MAP_SIZE; jj++) + { + if (find_syn_match(split[ii], x264_opt_map[jj].opt_syns) >= 0) + { + x264_opt_map[jj].found = TRUE; + switch(x264_opt_map[jj].type) + { + case X264_OPT_INT: + x264_update_int(ud, x264_opt_map[jj].name, val); + break; + case X264_OPT_BOOL: + x264_update_bool(ud, x264_opt_map[jj].name, val); + break; + case X264_OPT_COMBO: + x264_update_combo(ud, x264_opt_map[jj].name, val); + break; + case X264_OPT_DEBLOCK: + // dirty little hack. mark deblock_beta found as well + x264_opt_map[jj+1].found = TRUE; + x264_update_deblock(ud, val); + break; + } + break; + } + } + } + // For any options not found in the option string, set ui to + // default values + for (jj = 0; jj < X264_OPT_MAP_SIZE; jj++) + { + if (!x264_opt_map[jj].found) + { + gchar *val = strdup(x264_opt_map[jj].def_val); + switch(x264_opt_map[jj].type) + { + case X264_OPT_INT: + x264_update_int(ud, x264_opt_map[jj].name, val); + break; + case X264_OPT_BOOL: + x264_update_bool(ud, x264_opt_map[jj].name, val); + break; + case X264_OPT_COMBO: + x264_update_combo(ud, x264_opt_map[jj].name, val); + break; + case X264_OPT_DEBLOCK: + x264_update_deblock(ud, val); + break; + } + x264_opt_map[jj].found = TRUE; + g_free(val); + } + } + g_strfreev(split); +} + +gchar* +get_deblock_val(signal_user_data_t *ud) +{ + const gchar *alpha, *beta; + gchar *result; + alpha = ghb_settings_get_string(ud->settings, "x264_deblock_alpha"); + beta = ghb_settings_get_string(ud->settings, "x264_deblock_beta"); + result = g_strdup_printf("%s,%s", alpha, beta); + return result; +} + +void +ghb_x264_opt_update(signal_user_data_t *ud, GtkWidget *widget) +{ + gint jj; + const gchar *name = gtk_widget_get_name(widget); + gchar **opt_syns = NULL; + const gchar *def_val = NULL; + gint type; + + for (jj = 0; jj < X264_OPT_MAP_SIZE; jj++) + { + if (strcmp(name, x264_opt_map[jj].name) == 0) + { + // found the options that needs updating + opt_syns = x264_opt_map[jj].opt_syns; + def_val = x264_opt_map[jj].def_val; + type = x264_opt_map[jj].type; + break; + } + } + if (opt_syns != NULL) + { + GString *x264opts = g_string_new(""); + const gchar *options; + options = ghb_settings_get_string(ud->settings, "x264_options"); + gchar **split = g_strsplit(options, ":", -1); + gint ii; + gboolean foundit = FALSE; + + if (split == NULL) return; + for (ii = 0; split[ii] != NULL; ii++) + { + gint syn; + gchar *val = NULL; + gchar *pos = strchr(split[ii], '='); + if (pos != NULL) + { + val = pos + 1; + *pos = 0; + } + syn = find_syn_match(split[ii], opt_syns); + if (syn >= 0) + { // Updating this option + gchar *val; + foundit = TRUE; + if (type == X264_OPT_DEBLOCK) + val = get_deblock_val(ud); + else + val = ghb_widget_string(widget); + if (strcmp(def_val, val) != 0) + { + g_string_append_printf(x264opts, "%s=%s:", opt_syns[syn], val); + } + g_free(val); + } + else if (val != NULL) + g_string_append_printf(x264opts, "%s=%s:", split[ii], val); + else + g_string_append_printf(x264opts, "%s:", split[ii]); + + } + if (!foundit) + { + gchar *val; + if (type == X264_OPT_DEBLOCK) + val = get_deblock_val(ud); + else + val = ghb_widget_string(widget); + if (strcmp(def_val, val) != 0) + { + g_string_append_printf(x264opts, "%s=%s:", opt_syns[0], val); + } + g_free(val); + } + // Update the options value + // strip the trailing ":" + gchar *result; + gint len; + result = g_string_free(x264opts, FALSE); + len = strlen(result); + if (len > 0) result[len - 1] = 0; + ghb_ui_update(ud, "x264_options", result); + } +} + +static void +x264_remove_opt(gchar **opts, gchar **opt_syns) +{ + gint ii; + for (ii = 0; opts[ii] != NULL; ii++) + { + gchar *opt; + opt = g_strdup(opts[ii]); + gchar *pos = strchr(opt, '='); + if (pos != NULL) + { + *pos = 0; + } + if (find_syn_match(opt, opt_syns) >= 0) + { + // Mark as deleted + opts[ii][0] = 0; + } + g_free(opt); + } +} + +// Construct the x264 options string +// The result is allocated, so someone must free it at some point. +gchar* +ghb_sanitize_x264opts(signal_user_data_t *ud, const gchar *options) +{ + GString *x264opts = g_string_new(""); + gchar **split = g_strsplit(options, ":", -1); + + // Remove entries that match the defaults + gint ii; + for (ii = 0; split[ii] != NULL; ii++) + { + gchar *val = NULL; + gchar *opt = g_strdup(split[ii]); + gchar *pos = strchr(opt, '='); + if (pos != NULL) + { + val = pos + 1; + *pos = 0; + } + else + { + val = "1"; + } + const gchar *def_val = x264_opt_get_default(opt); + if (strcmp(val, def_val) == 0) + { + // Matches the default, so remove it + split[ii][0] = 0; + } + g_free(opt); + } + gint refs = ghb_settings_get_int(ud->settings, "x264_refs"); + if (refs <= 1) + { + x264_remove_opt(split, x264_mixed_syns); + } + gint subme = ghb_settings_get_int(ud->settings, "x264_subme"); + if (subme < 6) + { + x264_remove_opt(split, x264_brdo_syns); + } + gint bframes = ghb_settings_get_int(ud->settings, "x264_bframes"); + if (bframes == 0) + { + x264_remove_opt(split, x264_weightb_syns); + x264_remove_opt(split, x264_brdo_syns); + x264_remove_opt(split, x264_bime_syns); + } + if (bframes <= 1) + { + x264_remove_opt(split, x264_bpyramid_syns); + } + const gchar *me = ghb_settings_get_string(ud->settings, "x264_me"); + if (!(strcmp(me, "umh") == 0 || strcmp(me, "esa") == 0)) + { + x264_remove_opt(split, x264_merange_syns); + } + if (!ghb_settings_get_bool(ud->settings, "x264_cabac")) + { + x264_remove_opt(split, x264_trellis_syns); + } + gint analyse = ghb_settings_get_int(ud->settings, "x264_analyse"); + if (analyse == 1) + { + x264_remove_opt(split, x264_direct_syns); + } + for (ii = 0; split[ii] != NULL; ii++) + { + if (split[ii][0] != 0) + g_string_append_printf(x264opts, "%s:", split[ii]); + } + // strip the trailing ":" + gchar *result; + gint len; + result = g_string_free(x264opts, FALSE); + len = strlen(result); + if (len > 0) result[len - 1] = 0; + return result; +} + |