#include <glib/gstdio.h>
#include <string.h>
#include <gtk/gtk.h>
+#include "hb.h"
#include "settings.h"
#include "callbacks.h"
#include "audiohandler.h"
static GValue *presetsPlist = NULL;
static GValue *internalPlist = NULL;
static GValue *prefsPlist = NULL;
+static gboolean prefs_modified = FALSE;
static const GValue* preset_dict_get_value(GValue *dict, const gchar *key);
static void store_plist(GValue *plist, const gchar *name);
static void store_presets(void);
+static void store_prefs(void);
// This only handle limited depth
GtkTreePath*
return str;
}
-static void
-debug_show_type(GType tp)
-{
- const gchar *str = "unknown";
- if (tp == G_TYPE_STRING)
- {
- str ="string";
- }
- else if (tp == G_TYPE_INT)
- {
- str ="int";
- }
- else if (tp == G_TYPE_INT64)
- {
- str ="int64";
- }
- else if (tp == G_TYPE_BOOLEAN)
- {
- str ="bool";
- }
- else if (tp == ghb_array_get_type())
- {
- str ="array";
- }
- else if (tp == ghb_dict_get_type())
- {
- str ="dict";
- }
- g_message("Type: %s", str);
-}
-
void
dump_preset_path(const gchar *msg, const GValue *path)
{
return g_value_get_string(preset_dict_get_value(dict, "PresetName"));
}
+static gboolean
+preset_folder_is_open(GValue *dict)
+{
+ const GValue *gval;
+
+ gval = preset_dict_get_value(dict, "FolderOpen");
+ if (gval != NULL)
+ return g_value_get_boolean(gval);
+ return FALSE;
+}
+
gboolean
ghb_preset_folder(GValue *dict)
{
{
if (preset_is_default(dict))
{
- indices = malloc(MAX_NESTED_PRESET * sizeof(gint));
+ indices = g_malloc(MAX_NESTED_PRESET * sizeof(gint));
indices[*len] = ii;
(*len)++;
return indices;
store_presets();
}
+static void
+presets_set_folder_open(gboolean open, gint *indices, gint len)
+{
+ GValue *dict;
+
+ g_debug("presets_set_folder_open ()");
+ dict = presets_get_dict(presetsPlist, indices, len);
+ if (dict)
+ {
+ ghb_dict_insert(dict, g_strdup("FolderOpen"),
+ ghb_boolean_value_new(open));
+ }
+}
+
// Used for sorting dictionaries.
gint
key_cmp(gconstpointer a, gconstpointer b)
init_settings_from_dict(ud->settings, hidden, dict);
init_ui_from_dict(ud, internal, dict);
init_ui_from_dict(ud, hidden, dict);
-
- if (ghb_settings_get_boolean(ud->settings, "allow_tweaks"))
- {
- const GValue *gval;
- gval = preset_dict_get_value(dict, "PictureDeinterlace");
- if (gval)
- {
- ghb_ui_update(ud, "tweak_PictureDeinterlace", gval);
- }
- gval = preset_dict_get_value(dict, "PictureDenoise");
- if (gval)
- {
- ghb_ui_update(ud, "tweak_PictureDenoise", gval);
- }
- }
}
void
}
gchar*
-ghb_get_user_config_dir()
+ghb_get_user_config_dir(gchar *subdir)
{
const gchar *dir;
gchar *config;
if (!g_file_test(config, G_FILE_TEST_IS_DIR))
g_mkdir (config, 0755);
}
+ if (subdir)
+ {
+ gchar **split;
+ gint ii;
+
+ split = g_strsplit(subdir, "/", -1);
+ for (ii = 0; split[ii] != NULL; ii++)
+ {
+ gchar *tmp;
+
+ tmp = g_strdup_printf ("%s/%s", config, split[ii]);
+ g_free(config);
+ config = tmp;
+ if (!g_file_test(config, G_FILE_TEST_IS_DIR))
+ g_mkdir (config, 0755);
+ }
+ }
return config;
}
gchar *config, *path;
FILE *file;
- config = ghb_get_user_config_dir();
+ config = ghb_get_user_config_dir(NULL);
path = g_strdup_printf ("%s/%s", config, name);
file = g_fopen(path, "w");
g_free(config);
gchar *config, *path;
GValue *plist = NULL;
- config = ghb_get_user_config_dir();
+ config = ghb_get_user_config_dir(NULL);
path = g_strdup_printf ("%s/%s", config, name);
if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
{
{
gchar *config, *path;
- config = ghb_get_user_config_dir();
+ config = ghb_get_user_config_dir(NULL);
path = g_strdup_printf ("%s/%s", config, name);
if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
{
}
gval = ghb_settings_get_value(ud->settings, "default_source");
ghb_settings_set_value (ud->settings, "source", gval);
+
str = ghb_settings_get_string(ud->settings, "destination_dir");
+ ghb_ui_update(ud, "dest_dir", ghb_string_value(str));
- gchar *path = g_strdup_printf ("%s/new_video.mp4", str);
- ghb_ui_update(ud, "destination", ghb_string_value(path));
+ gchar *file = g_strdup_printf ("new_video.mp4");
+ ghb_ui_update(ud, "dest_file", ghb_string_value(file));
g_free(str);
- g_free(path);
+ g_free(file);
prefs_initializing = FALSE;
}
ghb_dict_insert(pref_dict, g_strdup(key), ghb_value_dup(value));
}
}
- store_plist(prefsPlist, "preferences");
+ store_prefs();
+ prefs_modified = FALSE;
+}
+
+void
+ghb_pref_set(GValue *settings, const gchar *key)
+{
+ const GValue *value, *value2;
+
+ if (prefs_initializing) return;
+ value = ghb_settings_get_value(settings, key);
+ if (value != NULL)
+ {
+ GValue *dict;
+ dict = plist_get_dict(prefsPlist, "Preferences");
+ if (dict == NULL) return;
+ value2 = ghb_dict_lookup(dict, key);
+ if (ghb_value_cmp(value, value2) != 0)
+ {
+ ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(value));
+ store_prefs();
+ prefs_modified = TRUE;
+ }
+ }
}
void
ghb_pref_save(GValue *settings, const gchar *key)
{
- const GValue *value;
+ const GValue *value, *value2;
if (prefs_initializing) return;
value = ghb_settings_get_value(settings, key);
GValue *dict;
dict = plist_get_dict(prefsPlist, "Preferences");
if (dict == NULL) return;
- ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(value));
- store_plist(prefsPlist, "preferences");
+ value2 = ghb_dict_lookup(dict, key);
+ if (ghb_value_cmp(value, value2) != 0)
+ {
+ ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(value));
+ store_prefs();
+ prefs_modified = FALSE;
+ }
+ }
+}
+
+void
+ghb_prefs_store(void)
+{
+ if (prefs_modified)
+ {
+ store_prefs();
+ prefs_modified = FALSE;
}
}
}
ghb_dict_insert(dict,
g_strdup("destination_dir"), ghb_value_dup(ghb_string_value(dir)));
- store_plist(prefsPlist, "preferences");
+ store_prefs();
}
// Read legacy default_preset preference and update accordingly
path = ghb_dict_lookup(dict, "default_preset");
g_free(indices);
}
ghb_dict_remove(dict, "default_preset");
- store_plist(prefsPlist, "preferences");
+ store_prefs();
}
}
if (folder)
{
ghb_presets_list_init(ud, more_indices, len+1);
+ if (preset_folder_is_open(dict))
+ {
+ GtkTreePath *path;
+
+ if (piter != NULL)
+ {
+ path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), piter);
+ gtk_tree_view_expand_row(treeview, path, FALSE);
+ gtk_tree_path_free(path);
+ }
+ path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);
+ gtk_tree_view_expand_row(treeview, path, FALSE);
+ gtk_tree_path_free(path);
+ }
}
}
g_free(more_indices);
static value_map_t vcodec_xlat[] =
{
{"MPEG-4 (FFmpeg)", "ffmpeg"},
- {"MPEG-4 (XviD)", "xvid"},
+ {"MPEG-4 (XviD)", "ffmpeg"},
{"H.264 (x264)", "x264"},
{"VP3 (Theora)", "theora"},
{NULL,NULL}
{"MP4 file", "mp4"},
{"M4V file", "m4v"},
{"MKV file", "mkv"},
- {"AVI file", "avi"},
- {"OGM file", "ogm"},
+ {"AVI file", "mkv"},
+ {"OGM file", "mkv"},
{NULL, NULL}
};
value_map_t deint_xlat[] =
{
{"0", "none"},
- {"1", "fast"},
- {"2", "slow"},
- {"3", "slower"},
+ {"1", "custom"},
+ {"2", "fast"},
+ {"3", "slow"},
+ {"4", "slower"},
{NULL, NULL}
};
value_map_t denoise_xlat[] =
{
{"0", "none"},
- {"1", "weak"},
- {"2", "medium"},
- {"3", "strong"},
+ {"1", "custom"},
+ {"2", "weak"},
+ {"3", "medium"},
+ {"4", "strong"},
+ {NULL, NULL}
+};
+
+value_map_t detel_xlat[] =
+{
+ {"0", "none"},
+ {"1", "custom"},
+ {"2", "default"},
+ {NULL, NULL}
+};
+
+value_map_t decomb_xlat[] =
+{
+ {"0", "none"},
+ {"1", "custom"},
+ {"2", "default"},
{NULL, NULL}
};
gval = export_value_xlat2(framerate_xlat, lin_val, G_TYPE_STRING);
if (gval)
ghb_dict_insert(dict, g_strdup(key), gval);
+ key = "PictureDetelecine";
+ lin_val = ghb_dict_lookup(dict, key);
+ gval = export_value_xlat2(detel_xlat, lin_val, G_TYPE_INT);
+ if (gval)
+ ghb_dict_insert(dict, g_strdup(key), gval);
+ key = "PictureDecomb";
+ lin_val = ghb_dict_lookup(dict, key);
+ gval = export_value_xlat2(decomb_xlat, lin_val, G_TYPE_INT);
+ if (gval)
+ ghb_dict_insert(dict, g_strdup(key), gval);
key = "PictureDeinterlace";
lin_val = ghb_dict_lookup(dict, key);
gval = export_value_xlat2(deint_xlat, lin_val, G_TYPE_INT);
if (gval)
ghb_dict_insert(dict, g_strdup(key), gval);
- else
- ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(lin_val));
key = "PictureDenoise";
lin_val = ghb_dict_lookup(dict, key);
gval = export_value_xlat2(denoise_xlat, lin_val, G_TYPE_INT);
if (gval)
ghb_dict_insert(dict, g_strdup(key), gval);
- else
- ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(lin_val));
key = "Subtitles";
lin_val = ghb_dict_lookup(dict, key);
gval = export_subtitle_xlat2(lin_val);
gval = import_value_xlat2(defaults, framerate_xlat, key, mac_val);
if (gval)
ghb_dict_insert(dict, g_strdup(key), gval);
+ key = "PictureDetelecine";
+ mac_val = ghb_dict_lookup(dict, key);
+ gval = import_value_xlat2(defaults, detel_xlat, key, mac_val);
+ if (gval)
+ ghb_dict_insert(dict, g_strdup(key), gval);
+ key = "PictureDecomb";
+ mac_val = ghb_dict_lookup(dict, key);
+ gval = import_value_xlat2(defaults, decomb_xlat, key, mac_val);
+ if (gval)
+ ghb_dict_insert(dict, g_strdup(key), gval);
key = "PictureDeinterlace";
mac_val = ghb_dict_lookup(dict, key);
gval = import_value_xlat2(defaults, deint_xlat, key, mac_val);
{
case 0:
{
- ghb_dict_insert(dict, g_strdup("anamorphic"),
- ghb_boolean_value_new(FALSE));
- if (ghb_dict_lookup(dict, "ModDimensions") == NULL)
- ghb_dict_insert(dict, g_strdup("ModDimensions"),
- ghb_boolean_value_new(TRUE));
+ if (ghb_dict_lookup(dict, "PictureAlignment") == NULL)
+ ghb_dict_insert(dict, g_strdup("PictureAlignment"),
+ ghb_int_value_new(16));
} break;
case 1:
{
- ghb_dict_insert(dict, g_strdup("anamorphic"),
- ghb_boolean_value_new(TRUE));
- ghb_dict_insert(dict, g_strdup("ModDimensions"),
- ghb_boolean_value_new(FALSE));
+ ghb_dict_insert(dict, g_strdup("PictureAlignment"),
+ ghb_int_value_new(1));
} break;
case 2:
{
- ghb_dict_insert(dict, g_strdup("anamorphic"),
- ghb_boolean_value_new(TRUE));
- ghb_dict_insert(dict, g_strdup("ModDimensions"),
- ghb_boolean_value_new(TRUE));
+ if (ghb_dict_lookup(dict, "PictureAlignment") == NULL)
+ ghb_dict_insert(dict, g_strdup("PictureAlignment"),
+ ghb_int_value_new(16));
} break;
default:
{
- ghb_dict_insert(dict, g_strdup("anamorphic"),
- ghb_boolean_value_new(TRUE));
- ghb_dict_insert(dict, g_strdup("ModDimensions"),
- ghb_boolean_value_new(TRUE));
+ if (ghb_dict_lookup(dict, "PictureAlignment") == NULL)
+ ghb_dict_insert(dict, g_strdup("PictureAlignment"),
+ ghb_int_value_new(16));
} break;
}
// VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
} break;
}
import_value_xlat(dict);
+
+ gdouble vquality;
+ const GValue *gval;
+
+ vquality = ghb_value_double(preset_dict_get_value(dict, "VideoQualitySlider"));
+ if (vquality < 1.0)
+ {
+ gint vcodec;
+
+ gval = preset_dict_get_value(dict, "VideoEncoder");
+ vcodec = ghb_lookup_combo_int("VideoEncoder", gval);
+ switch (vcodec)
+ {
+ case HB_VCODEC_X264:
+ {
+ vquality = 51. - vquality * 51.;
+ } break;
+
+ case HB_VCODEC_XVID:
+ case HB_VCODEC_FFMPEG:
+ {
+ vquality = 31. - vquality * 30.;
+ } break;
+
+ case HB_VCODEC_THEORA:
+ {
+ vquality = vquality * 63.;
+ } break;
+
+ default:
+ {
+ vquality = 0.;
+ } break;
+ }
+ ghb_dict_insert(dict, g_strdup("VideoQualitySlider"),
+ ghb_double_value_new(vquality));
+ }
}
static void
static void
export_xlat_preset(GValue *dict)
{
- gboolean ana, round, autoscale, target, br, constant;
+ gboolean autoscale, target, br, constant;
g_debug("export_xlat_prest ()");
autoscale = ghb_value_boolean(preset_dict_get_value(dict, "autoscale"));
- ana = ghb_value_boolean(preset_dict_get_value(dict, "anamorphic"));
- round = ghb_value_boolean(preset_dict_get_value(dict, "ModDimensions"));
target = ghb_value_boolean(
preset_dict_get_value(dict, "vquality_type_target"));
br = ghb_value_boolean(
ghb_dict_insert(dict, g_strdup("UsesPictureSettings"),
ghb_int_value_new(1));
- if (ana)
- {
- if (round)
- ghb_dict_insert(dict, g_strdup("PicturePAR"),
- ghb_int_value_new(2));
- else
- ghb_dict_insert(dict, g_strdup("PicturePAR"),
- ghb_int_value_new(1));
- }
- else
- {
- ghb_dict_insert(dict, g_strdup("PicturePAR"),
- ghb_int_value_new(0));
- }
// VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
if (target)
{
ghb_dict_insert(dict, g_strdup("VideoQualityType"),
ghb_int_value_new(2));
}
+ ghb_dict_remove(dict, "UsesMaxPictureSettings");
ghb_dict_remove(dict, "autoscale");
- ghb_dict_remove(dict, "anamorphic");
ghb_dict_remove(dict, "vquality_type_target");
ghb_dict_remove(dict, "vquality_type_bitrate");
ghb_dict_remove(dict, "vquality_type_constant");
}
}
+static guint prefs_timeout_id = 0;
+
+static gboolean
+delayed_store_prefs(gpointer data)
+{
+ store_plist(prefsPlist, "preferences");
+ prefs_timeout_id = 0;
+ return FALSE;
+}
+
static void
store_presets()
{
ghb_value_free(export);
}
+static void
+store_prefs(void)
+{
+ if (prefs_timeout_id != 0)
+ {
+ GMainContext *mc;
+ GSource *source;
+
+ mc = g_main_context_default();
+ source = g_main_context_find_source_by_id(mc, prefs_timeout_id);
+ if (source != NULL)
+ g_source_destroy(source);
+ }
+ prefs_timeout_id = g_timeout_add_seconds(1, (GSourceFunc)delayed_store_prefs, NULL);
+}
+
void
ghb_presets_reload(signal_user_data_t *ud)
{
if (presetsPlist == NULL)
{
presetsPlist = ghb_value_dup(ghb_resource_get("standard-presets"));
+ import_xlat_presets(presetsPlist);
store_presets();
}
else if (G_VALUE_TYPE(presetsPlist) == ghb_dict_get_type())
{ // Presets is older dictionary format. Convert to array
ghb_value_free(presetsPlist);
presetsPlist = ghb_value_dup(ghb_resource_get("standard-presets"));
+ import_xlat_presets(presetsPlist);
store_presets();
}
else if (check_old_presets())
{
ghb_value_free(presetsPlist);
presetsPlist = ghb_value_dup(ghb_resource_get("standard-presets"));
+ import_xlat_presets(presetsPlist);
store_presets();
}
import_xlat_presets(presetsPlist);
return;
}
}
-
- if (ghb_settings_get_boolean(ud->settings, "allow_tweaks"))
- {
- gchar *str;
- str = ghb_settings_get_string(ud->settings, "tweak_PictureDeinterlace");
- if (str)
- {
- ghb_settings_set_string(ud->settings, "PictureDeinterlace", str);
- g_free(str);
- }
- str = ghb_settings_get_string(ud->settings, "tweak_PictureDenoise");
- if (str)
- {
- ghb_settings_set_string(ud->settings, "PictureDenoise", str);
- g_free(str);
- }
- }
+ current_preset = dict;
autoscale = ghb_settings_get_boolean(ud->settings, "autoscale");
ghb_settings_set_int64(ud->settings, "Type", PRESETS_CUSTOM);
}
}
+void
+presets_row_expanded_cb(
+ GtkTreeView *treeview,
+ GtkTreeIter *iter,
+ GtkTreePath *path,
+ signal_user_data_t *ud)
+{
+ gint *indices, len;
+ gboolean expanded, folder;
+
+ expanded = gtk_tree_view_row_expanded(treeview, path);
+ indices = gtk_tree_path_get_indices(path);
+ len = gtk_tree_path_get_depth(path);
+ folder = ghb_presets_get_folder(presetsPlist, indices, len);
+ if (folder)
+ {
+ presets_set_folder_open(expanded, indices, len);
+ }
+
+ // Collapsing parent folder collapses all children
+ if (!expanded)
+ {
+ GValue *presets = NULL;
+ GValue *dict;
+ gint *more_indices, count, ii;
+
+ more_indices = g_malloc((len+1)*sizeof(gint));
+ memcpy(more_indices, indices, len*sizeof(gint));
+
+ presets = presets_get_folder(presetsPlist, indices, len);
+ count = ghb_array_len(presets);
+ for (ii = 0; ii < count; ii++)
+ {
+ dict = ghb_array_get_nth(presets, ii);
+ folder = ghb_preset_folder(dict);
+ if (folder)
+ {
+ more_indices[len] = ii;
+ presets_set_folder_open(expanded, more_indices, len+1);
+ }
+ }
+ g_free(more_indices);
+ }
+ store_presets();
+}
+
static void
preset_update_title_deps(signal_user_data_t *ud, ghb_title_info_t *tinfo)
{
ghb_ui_update(ud, "scale_width",
ghb_int64_value(tinfo->width - tinfo->crop[2] - tinfo->crop[3]));
// If anamorphic or keep_aspect, the hight will be automatically calculated
- gboolean keep_aspect, anamorphic;
+ gboolean keep_aspect;
+ gint pic_par;
keep_aspect = ghb_settings_get_boolean(ud->settings, "PictureKeepRatio");
- anamorphic = ghb_settings_get_boolean(ud->settings, "anamorphic");
- if (!(keep_aspect || anamorphic))
+ pic_par = ghb_settings_combo_int(ud->settings, "PicturePAR");
+ if (!(keep_aspect || pic_par) || pic_par == 3)
{
ghb_ui_update(ud, "scale_height",
ghb_int64_value(tinfo->height - tinfo->crop[0] - tinfo->crop[1]));
gdouble vqmin, vqmax, step, page;
gint digits;
- ghb_vquality_range(ud, &vqmin, &vqmax, &step, &page, &digits);
+ gboolean inverted;
+
+ ghb_vquality_range(ud, &vqmin, &vqmax, &step,
+ &page, &digits, &inverted);
gtk_range_set_range (GTK_RANGE(qp), vqmin, vqmax);
gtk_range_set_increments (GTK_RANGE(qp), step, page);
gtk_scale_set_digits(GTK_SCALE(qp), digits);
+ gtk_range_set_inverted (GTK_RANGE(qp), inverted);
gchar *text;
gint crop[4];