]> granicus.if.org Git - handbrake/commitdiff
lingui: use libhb preset management from linux gui
authorjstebbins <jstebbins.hb@gmail.com>
Thu, 14 May 2015 17:11:48 +0000 (17:11 +0000)
committerjstebbins <jstebbins.hb@gmail.com>
Thu, 14 May 2015 17:11:48 +0000 (17:11 +0000)
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@7179 b64f7644-9d1e-0410-96f1-a4d463321fa5

29 files changed:
gtk/src/Makefile.am
gtk/src/callbacks.c
gtk/src/callbacks.h
gtk/src/data_res.gresource.xml
gtk/src/ghb-3.12.ui
gtk/src/ghb-3.14.ui
gtk/src/ghb.ui
gtk/src/internal_defaults.json
gtk/src/main.c
gtk/src/presets.c
gtk/src/presets.h
gtk/src/queuehandler.c
gtk/src/resources.c
gtk/src/standard_presets.json [deleted file]
gtk/src/values.c
gtk/src/values.h
libhb/builtin_presets.h
libhb/hb.h
libhb/hb_dict.c
libhb/hb_dict.h
libhb/plist.c
libhb/plist.h
libhb/preset.c
libhb/preset.h
libhb/preset_builtin.json
libhb/preset_template.json
libhb/work.c
scripts/create_resources.py
test/test.c

index dc9f489419994149d5cbdd0dde1bc4b8fe61b899..e72ba59aff2db2f73ac96ae0c3e0a6d91312cd4b 100644 (file)
@@ -100,12 +100,12 @@ icon_res.h : icon_res.gresource.xml $(icons_dep)
 
 icon_res.o: icon_res.c icon_res.h
 
-data_res.c : data_res.gresource.xml $(srcdir)/internal_defaults.json $(srcdir)/standard_presets.json widget.deps widget_reverse.deps
-       cp $(srcdir)/internal_defaults.json $(srcdir)/standard_presets.json .
+data_res.c : data_res.gresource.xml $(srcdir)/internal_defaults.json widget.deps widget_reverse.deps
+       cp $(srcdir)/internal_defaults.json .
        glib-compile-resources --generate --target=$@ --c-name ghb_data --manual-register $<
 
-data_res.h : data_res.gresource.xml $(srcdir)/internal_defaults.json $(srcdir)/standard_presets.json widget.deps widget_reverse.deps
-       cp $(srcdir)/internal_defaults.json $(srcdir)/standard_presets.json .
+data_res.h : data_res.gresource.xml $(srcdir)/internal_defaults.json widget.deps widget_reverse.deps
+       cp $(srcdir)/internal_defaults.json .
        glib-compile-resources --generate --target=$@ --c-name ghb_data --manual-register $<
 
 if GHB_GTK_3_14
index 5fc3d7589e9309f3670ebfcecfc50e0ee17ddc35..5b5db99af03ec44dc217529112d68f70b1ecb5ae 100644 (file)
@@ -818,14 +818,14 @@ update_source_label(signal_user_data_t *ud, const gchar *source)
     if (label != NULL)
     {
         gtk_label_set_text (GTK_LABEL(widget), label);
-        ghb_dict_set_string(ud->settings, "volume_label", label);
+        ghb_dict_set_string(ud->globals, "volume_label", label);
         g_free(label);
     }
     else
     {
         label = _("No Title Found");
         gtk_label_set_text (GTK_LABEL(widget), label);
-        ghb_dict_set_string(ud->settings, "volume_label", label);
+        ghb_dict_set_string(ud->globals, "volume_label", label);
         return FALSE;
     }
     return TRUE;
@@ -1158,7 +1158,7 @@ show_settings(GhbValue *settings)
 void
 ghb_load_settings(signal_user_data_t * ud)
 {
-    GhbValue *preset;
+    const char *fullname;
     gboolean preset_modified;
     static gboolean busy = FALSE;
 
@@ -1166,7 +1166,7 @@ ghb_load_settings(signal_user_data_t * ud)
         return;
     busy = TRUE;
 
-    preset = ghb_dict_get_value(ud->settings, "preset");
+    fullname = ghb_dict_get_string(ud->settings, "PresetFullName");
     preset_modified = ghb_dict_get_bool(ud->settings, "preset_modified");
     if (preset_modified)
     {
@@ -1175,10 +1175,23 @@ ghb_load_settings(signal_user_data_t * ud)
     else
     {
         ghb_dict_set_bool(ud->settings, "preset_reload", TRUE);
-        ghb_select_preset(ud->builder, preset);
+        ghb_select_preset(ud->builder, fullname);
         ghb_dict_set_bool(ud->settings, "preset_reload", FALSE);
     }
 
+    busy = FALSE;
+
+    ghb_load_post_settings(ud);
+}
+
+void
+ghb_load_post_settings(signal_user_data_t * ud)
+{
+    static gboolean busy = FALSE;
+    if (busy)
+        return;
+    busy = TRUE;
+
     ud->dont_clear_presets = TRUE;
     ud->scale_busy = TRUE;
 
@@ -1831,7 +1844,7 @@ set_title_settings(signal_user_data_t *ud, GhbValue *settings)
         else
         {
             ghb_dict_set(settings, "volume_label", ghb_value_dup(
-                    ghb_dict_get_value(ud->settings, "volume_label")));
+                    ghb_dict_get_value(ud->globals, "volume_label")));
         }
         ghb_dict_set_int(settings, "scale_width",
                              title->geometry.width - title->crop[2] - title->crop[3]);
@@ -1909,7 +1922,7 @@ static void
 load_all_titles(signal_user_data_t *ud, int titleindex)
 {
     gint ii, count;
-    GhbValue *preset, *preset_path = NULL;
+    GhbValue *preset;
     GhbValue *settings_array;
     const hb_title_t *title;
 
@@ -1924,28 +1937,21 @@ load_all_titles(signal_user_data_t *ud, int titleindex)
     preset = ghb_get_current_preset(ud);
     if (preset != NULL)
     {
-        preset_path = ghb_get_current_preset_path(ud);
-    }
-    else
-    {
-        preset = ud->settings;
+        ghb_preset_to_settings(ud->settings, preset);
+        ghb_value_free(&preset);
     }
     for (ii = 0; ii < count; ii++)
     {
         int index;
-        GhbValue *settings = ghb_dict_new();
+        GhbValue *settings = ghb_value_dup(ud->settings);
 
         title = hb_list_item(list, ii);
         index = (title != NULL) ? title->index : -1;
 
-        ghb_settings_init(settings, "Initialization");
-        ghb_preset_to_settings(settings, preset);
-        ghb_dict_set(settings, "preset", ghb_value_dup(preset_path));
         ghb_dict_set_int(settings, "title", index);
         set_title_settings(ud, settings);
         ghb_array_append(settings_array, settings);
     }
-    ghb_value_free(&preset_path);
     if (titleindex < 0 || titleindex >= count)
     {
         titleindex = 0;
@@ -2755,20 +2761,18 @@ static void
 submit_job(signal_user_data_t *ud, GhbValue *settings)
 {
     static gint unique_id = 1;
-    gchar *type, *modified, *preset;
-    const GhbValue *path;
+    gchar *type, *modified;
+    const char *name;
     GhbValue *js;
     gboolean preset_modified;
 
     g_debug("submit_job");
     if (settings == NULL) return;
     preset_modified = ghb_dict_get_bool(settings, "preset_modified");
-    path = ghb_dict_get_value(settings, "preset");
-    preset = ghb_preset_path_string(path);
-    type = ghb_preset_is_custom() ? "Custom " : "";
+    name = ghb_dict_get_string(settings, "PresetFullName");
+    type = ghb_dict_get_int(settings, "Type") == 1 ? "Custom " : "";
     modified = preset_modified ? "Modified " : "";
-    ghb_log("%s%sPreset: %s", modified, type, preset);
-    g_free(preset);
+    ghb_log("%s%sPreset: %s", modified, type, name);
 
     ghb_dict_set_int(settings, "job_unique_id", unique_id);
     ghb_dict_set_int(settings, "job_status", GHB_QUEUE_RUNNING);
@@ -3155,7 +3159,7 @@ ghb_backend_events(signal_user_data_t *ud)
         if (title == NULL)
         {
             gtk_label_set_text(label, _("No Title Found"));
-            ghb_ui_update(ud, "title", ghb_int_value(-1));
+            ghb_ui_update(ud, "title", ghb_string_value("none"));
         }
         else
         {
index 73003211ef347f79473b4eaf0c124a96024f6464..02c8e08055f56b08cce96caac89666f0fd6b88ef 100644 (file)
@@ -82,6 +82,7 @@ void ghb_add_all_titles(signal_user_data_t *ud);
 void ghb_update_title_info(signal_user_data_t *ud);
 void ghb_chapter_list_refresh_all(signal_user_data_t *ud);
 void ghb_load_settings(signal_user_data_t * ud);
+void ghb_load_post_settings(signal_user_data_t * ud);
 void ghb_set_current_title_settings(signal_user_data_t *ud);
 void ghb_container_empty(GtkContainer *c);
 void ghb_show_container_options(signal_user_data_t *ud);
index 5570e4bea2b1cd5eff7b3b33c47eaaae5a5ecb4c..d0f75543b7647131d189525e4791f06f7bd9d281 100644 (file)
@@ -2,7 +2,6 @@
 <gresources>
   <gresource prefix="/org/handbrake/data">
     <file>internal_defaults.json</file>
-    <file>standard_presets.json</file>
     <file>widget.deps</file>
     <file>widget_reverse.deps</file>
   </gresource>
index 47cf3776fa948b5dde4b306a2d5fbc867bb735b5..74b9ba0af6b88493641d5dbe3a8ebbb7146e38e9 100644 (file)
@@ -841,7 +841,7 @@ libx264 authors:
                     </child>
                     <child>
                       <object class="GtkMenuItem" id="presets_restore">
-                        <property name="label" translatable="yes">_Update Built-in Presets</property>
+                        <property name="label" translatable="yes">_Reload Built-in Presets</property>
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <property name="use_underline">True</property>
@@ -7568,7 +7568,7 @@ on the Video tab instead.</property>
 Check this if you want the queue to clean itself up by deleting completed jobs.</property>
                             <property name="halign">start</property>
                             <property name="draw_indicator">True</property>
-                            <signal name="toggled" handler="advanced_video_changed_cb" swapped="no"/>
+                            <signal name="toggled" handler="pref_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">6</property>
index edd4dcdfb5cdfe6aa5d898c7f6741901696ef6a9..101f17558ca3310ee6d306a59746a0551d9ca491 100644 (file)
@@ -842,7 +842,7 @@ libx264 authors:
                     </child>
                     <child>
                       <object class="GtkMenuItem" id="presets_restore">
-                        <property name="label" translatable="yes">_Update Built-in Presets</property>
+                        <property name="label" translatable="yes">_Reload Built-in Presets</property>
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <property name="use_underline">True</property>
@@ -7574,7 +7574,7 @@ on the Video tab instead.</property>
 Check this if you want the queue to clean itself up by deleting completed jobs.</property>
                             <property name="halign">start</property>
                             <property name="draw_indicator">True</property>
-                            <signal name="toggled" handler="advanced_video_changed_cb" swapped="no"/>
+                            <signal name="toggled" handler="pref_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">6</property>
index bf82ac57fead0b3436ccdde80e11aace712387c0..4ec2c5ef740fa5df1f469338e53fc4ba9c7bd99a 100644 (file)
@@ -841,7 +841,7 @@ libx264 authors:
                     </child>
                     <child>
                       <object class="GtkMenuItem" id="presets_restore">
-                        <property name="label" translatable="yes">_Update Built-in Presets</property>
+                        <property name="label" translatable="yes">_Reload Built-in Presets</property>
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <property name="use_underline">True</property>
@@ -7568,7 +7568,7 @@ on the Video tab instead.</property>
 Check this if you want the queue to clean itself up by deleting completed jobs.</property>
                             <property name="halign">start</property>
                             <property name="draw_indicator">True</property>
-                            <signal name="toggled" handler="advanced_video_changed_cb" swapped="no"/>
+                            <signal name="toggled" handler="pref_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">6</property>
index 0d4fd76571eec1a899c65473d2161aea8d730f39..d4a24ab157b304a9b3bb7f39a59dfa81c3964db3 100644 (file)
@@ -1,9 +1,21 @@
 {
     "Globals": {
         "show_preview": false,
-        "scan_source": ""
+        "scan_source": "",
+        "volume_label": "New Video"
+    },
+    "OneTimeInitialization": {
+        "title": "none"
     },
     "Initialization": {
+        "AudioAllowMP3Pass": false,
+        "AudioAllowAACPass": false,
+        "AudioAllowAC3Pass": false,
+        "AudioAllowDTSPass": false,
+        "AudioAllowDTSHDPass": false,
+        "AudioAllowEAC3Pass": false,
+        "AudioAllowFLACPass": false,
+        "AudioAllowTRUEHDPass": false,
         "AudioBitrate": "192",
         "AudioEncoder": "copy:ac3",
         "AudioTrack": 0,
         "MetaGenre": "",
         "MetaDescription": "",
         "MetaLongDescription": "",
-        "preset": [
-            "Regular",
-            "Normal"
-        ],
+        "PresetFullName": "/Regular/Normal",
         "preset_modified": false,
         "preset_reload": false,
-        "preset_selection": [
-            "Regular",
-            "Normal"
-        ],
         "PictureDisplayWidth": 720,
         "PictureDisplayHeight": 480,
         "PtoPType": "chapter",
@@ -46,7 +51,6 @@
         "single_title": 1,
         "start_point": 1.0,
         "start_frame": -1,
-        "title": 0,
         "title_selected": false,
         "volume_label": "New Video",
         "audio_list": [],
         "SrtDir": "",
         "window_width": 1,
         "window_height": 1
-    },
-    "Presets": {
-        "PictureAutoCrop": true,
-        "ChapterMarkers": true,
-        "FileFormat": "mp4",
-        "Folder": false,
-        "PictureLooseCrop": false,
-        "PictureModulus": 2,
-        "PictureDeblock": 0,
-        "PictureDecombDeinterlace": true,
-        "PictureDecomb": "off",
-        "PictureDecombCustom": "",
-        "Default": false,
-        "PictureBottomCrop": 0,
-        "PictureLeftCrop": 0,
-        "PictureRightCrop": 0,
-        "PictureTopCrop": 0,
-        "PictureDeinterlace": "off",
-        "PictureDeinterlaceCustom": "",
-        "PictureDenoiseFilter": "off",
-        "PictureDenoisePreset": "medium",
-        "PictureDenoiseTune": "none",
-        "PictureDenoiseCustom": "",
-        "PictureDetelecine": "off",
-        "PictureDetelecineCustom": "",
-        "PicturePAR": "loose",
-        "PicturePARWidth": 853,
-        "PicturePARHeight": 720,
-        "PictureHeight": 0,
-        "PictureWidth": 0,
-        "VideoFramerate": "auto",
-        "VideoFramerateMode": "vfr",
-        "VideoGrayScale": false,
-        "Mp4HttpOptimize": false,
-        "Mp4iPodCompatible": false,
-        "PictureKeepRatio": true,
-        "AudioAllowMP3Pass": false,
-        "AudioAllowAACPass": false,
-        "AudioAllowAC3Pass": true,
-        "AudioAllowDTSPass": false,
-        "AudioAllowDTSHDPass": false,
-        "AudioAllowEAC3Pass": false,
-        "AudioAllowFLACPass": false,
-        "AudioAllowTRUEHDPass": false,
-        "AudioCopyMask": [
-            "copy:ac3"
-        ],
-        "AudioEncoderFallback": "ac3",
-        "AudioLanguageList": [
-            "und"
-        ],
-        "AudioList": [
-            {
-                "AudioBitrate": "192",
-                "AudioEncoder": "copy:ac3",
-                "AudioTrackQualityEnable": false,
-                "AudioTrackQuality": -1.0,
-                "AudioTrackGainSlider": 0.0,
-                "AudioTrackDRCSlider": 0.0,
-                "AudioMixdown": "dpl2",
-                "AudioSamplerate": "auto"
-            }
-        ],
-        "AudioSecondaryEncoderMode": true,
-        "AudioTrackSelectionBehavior": "first",
-        "PresetDescription": "",
-        "PresetName": "Name Missing",
-        "Type": 1,
-        "SubtitleLanguageList": [
-            "und"
-        ],
-        "SubtitleTrackSelectionBehavior": "none",
-        "SubtitleAddCC": false,
-        "SubtitleAddForeignAudioSearch": false,
-        "SubtitleAddForeignAudioSubtitle": false,
-        "SubtitleBurnBehavior": "none",
-        "SubtitleBurnDVDSub": false,
-        "SubtitleBurnBDSub": false,
-        "VideoTurboTwoPass": false,
-        "UsesPictureFilters": true,
-        "UsesPictureSettings": 2,
-        "VideoTwoPass": false,
-        "VideoAvgBitrate": 1800,
-        "VideoEncoder": "x264",
-        "VideoQualityType": 2,
-        "VideoQualitySlider": 0.59999999999999998,
-        "x264Option": "",
-        "VideoPreset": "medium",
-        "VideoTune": "",
-        "VideoProfile": "",
-        "VideoLevel": "",
-        "x264UseAdvancedOptions": false,
-        "VideoOptionExtra": ""
     }
 }
index 5b60252fe35e02d932c281684801ced145df7630..de5b3813f2d0557761e5f41a4688b6bfe6ceef22 100644 (file)
@@ -798,7 +798,6 @@ int
 main(int argc, char *argv[])
 {
     signal_user_data_t *ud;
-    GhbValue *preset;
     GError *error = NULL;
     GOptionContext *context;
 
@@ -1011,13 +1010,15 @@ main(int argc, char *argv[])
     ghb_settings_init(ud->prefs, "Preferences");
     ghb_settings_init(ud->globals, "Globals");
     ghb_settings_init(ud->settings, "Initialization");
+    ghb_settings_init(ud->settings, "OneTimeInitialization");
     // Load user preferences file
     ghb_prefs_load(ud);
     // Store user preferences into ud->prefs
     ghb_prefs_to_settings(ud->prefs);
 
-    // Load all settings with default preset values
-    ghb_settings_init(ud->settings, "Presets");
+    int logLevel = ghb_dict_get_int(ud->prefs, "LoggingLevel");
+    ghb_backend_init(logLevel);
+
     // Load the presets files
     ghb_presets_load(ud);
     // Note that ghb_preset_to_settings(ud->settings) is called when
@@ -1028,9 +1029,6 @@ main(int argc, char *argv[])
     // Note that ghb_settings_to_ui(ud->settings) happens when initial
     // empty title is initialized.
 
-    gint logLevel;
-    logLevel = ghb_dict_get_int(ud->prefs, "LoggingLevel");
-    ghb_backend_init(logLevel);
 
     if (ghb_dict_get_bool(ud->prefs, "hbfd"))
     {
@@ -1040,16 +1038,11 @@ main(int argc, char *argv[])
     ghb_dvd_set_current(source, ud);
 
     // Populate the presets tree view
-    ghb_presets_list_init(ud, NULL, 0);
+    ghb_presets_list_init(ud, NULL);
     // Get the first preset name
     if (arg_preset != NULL)
     {
-        preset = ghb_parse_preset_path(arg_preset);
-        if (preset)
-        {
-            ghb_select_preset(ud->builder, preset);
-            ghb_value_free(&preset);
-        }
+        ghb_select_preset(ud->builder, arg_preset);
     }
     else
     {
index 5c2825c7e8b8b6bfc247f6a29e6642d251e91df5..7f9c5f8c9f70dcded4adc2e205f1eaac424c11d3 100644 (file)
@@ -27,7 +27,6 @@
 #include "audiohandler.h"
 #include "subtitlehandler.h"
 #include "hb-backend.h"
-#include "plist.h"
 #include "resources.h"
 #include "presets.h"
 #include "values.h"
 
 enum
 {
+    PRESETS_INVALID = -1,
     PRESETS_BUILTIN = 0,
     PRESETS_CUSTOM
 };
 
-static GhbValue *presetsPlistFile = NULL;
-static GhbValue *presetsPlist = NULL;
-static GhbValue *prefsPlist = NULL;
+static GhbValue *prefsDict = NULL;
 static gboolean prefs_modified = FALSE;
 
-static void store_presets(void);
 static void store_prefs(void);
+static void store_presets(void);
 
-static void
-dict_clean(GhbValue *dict, GhbValue *template)
+hb_preset_index_t*
+ghb_tree_get_index(GtkTreeModel *store, GtkTreeIter *iter)
 {
-    GhbValue *tmp = ghb_value_dup(dict);
-    GhbDictIter iter;
-    const gchar *key;
-    GhbValue *val;
-    GhbValue *template_val;
+    GtkTreePath       *treepath;
+    int               *indices, len;
+    hb_preset_index_t *path;
 
-    iter = ghb_dict_iter_init(tmp);
-    while (ghb_dict_iter_next(tmp, &iter, &key, &val))
-    {
-        template_val = ghb_dict_get(template, key);
-        if (template_val == NULL)
-        {
-            ghb_dict_remove(dict, key);
-        }
-        if (ghb_value_type(val) == GHB_DICT &&
-            ghb_value_type(template_val) == GHB_DICT)
-        {
-            val = ghb_dict_get(dict, key);
-            dict_clean(val, template_val);
-        }
-        if (ghb_value_type(val) == GHB_ARRAY &&
-            ghb_value_type(template_val) == GHB_ARRAY &&
-            ghb_array_len(template_val) > 0)
-        {
-            template_val = ghb_array_get(template_val, 0);
-            if (ghb_value_type(template_val) == GHB_DICT)
-            {
-                val = ghb_dict_get(dict, key);
-                int count = ghb_array_len(val);
-                int ii;
-                for (ii = 0; ii < count; ii++)
-                {
-                    GhbValue *array_val;
-                    array_val = ghb_array_get(val, ii);
-                    if (ghb_value_type(array_val) == GHB_DICT)
-                    {
-                        dict_clean(array_val, template_val);
-                    }
-                }
-            }
-        }
-    }
-    ghb_value_free(&tmp);
+    treepath = gtk_tree_model_get_path(store, iter);
+    indices  = gtk_tree_path_get_indices(treepath);
+    len      = gtk_tree_path_get_depth(treepath);
+    path     = hb_preset_index_init(indices, len);
+    gtk_tree_path_free(treepath);
+
+    return path;
 }
 
-gint
-preset_path_cmp(gint *indices1, gint len1, gint *indices2, gint len2)
+hb_preset_index_t*
+ghb_tree_path_get_index(GtkTreePath *treepath)
 {
-    gint ii;
-    for (ii = 0; ii < len1 && ii < len2; ii++)
-    {
-        if (indices1[ii] != indices2[ii])
-            return indices1[ii] - indices2[ii];
-    }
-    return len1 - len2;
+    int *indices, len;
+
+    indices = gtk_tree_path_get_indices(treepath);
+    len     = gtk_tree_path_get_depth(treepath);
+
+    return hb_preset_index_init(indices, len);
 }
 
 // This only handle limited depth
 GtkTreePath*
-ghb_tree_path_new_from_indices(gint *indices, gint len)
+ghb_tree_path_new_from_index(const hb_preset_index_t *path)
 {
-    switch (len)
+    if (path == NULL || path->depth == 0)
+        return NULL;
+
+#if GTK_CHECK_VERSION(3, 12, 0)
+    return gtk_tree_path_new_from_indicesv((int*)path->index, path->depth);
+#else
+    switch (path->depth)
     {
         case 1:
             return gtk_tree_path_new_from_indices(
-                indices[0], -1);
+                path->index[0], -1);
         case 2:
             return gtk_tree_path_new_from_indices(
-                indices[0], indices[1], -1);
+                path->index[0], path->index[1], -1);
         case 3:
             return gtk_tree_path_new_from_indices(
-                indices[0], indices[1], indices[2], -1);
+                path->index[0], path->index[1], path->index[2], -1);
         case 4:
             return gtk_tree_path_new_from_indices(
-                indices[0], indices[1], indices[2], indices[3], -1);
+                path->index[0], path->index[1], path->index[2],
+                path->index[3], -1);
         case 5:
             return gtk_tree_path_new_from_indices(
-                indices[0], indices[1], indices[2], indices[3], indices[4], -1);
+                path->index[0], path->index[1], path->index[2],
+                path->index[3], path->index[4], -1);
+        case 6:
+            return gtk_tree_path_new_from_indices(
+                path->index[0], path->index[1], path->index[2],
+                path->index[3], path->index[4], path->index[5], -1);
+        case 7:
+            return gtk_tree_path_new_from_indices(
+                path->index[0], path->index[1], path->index[2],
+                path->index[3], path->index[4], path->index[5],
+                path->index[6], -1);
+        case 8:
+            return gtk_tree_path_new_from_indices(
+                path->index[0], path->index[1], path->index[2],
+                path->index[3], path->index[4], path->index[5],
+                path->index[6], path->index[7], -1);
         default:
+            g_warning("Preset path depth too deep");
             return NULL;
     }
+#endif
 }
 
-GhbValue*
-ghb_parse_preset_path(const gchar *path)
+#if 0
+void
+dump_preset_indices(const gchar *msg, hb_preset_index_t *path)
 {
-    gchar **split;
-    GhbValue *preset;
     gint ii;
 
-    preset = ghb_array_new();
-    split = g_strsplit(path, "#", MAX_NESTED_PRESET);
-    for (ii = 0; split[ii] != NULL; ii++)
+    g_message("%s indices: len %d", msg, path->depth);
+    for (ii = 0; ii < path->depth; ii++)
     {
-        ghb_array_append(preset, ghb_string_value_new(split[ii]));
+        printf("%d ", path->index[ii]);
     }
-    g_strfreev(split);
-    return preset;
+    printf("\n");
 }
+#endif
 
-static GhbValue*
-preset_path_from_indices(GhbValue *presets, gint *indices, gint len)
+static gint
+preset_tree_depth(GhbValue *dict)
 {
-    gint ii;
-    GhbValue *path;
-
-    g_debug("preset_path_from_indices");
-    path = ghb_array_new();
-    for (ii = 0; ii < len; ii++)
+    if (ghb_dict_get_bool(dict, "Folder"))
     {
-        GhbValue *dict;
-        gint count, folder;
-        const GhbValue *name;
-
-        count = ghb_array_len(presets);
-        if (indices[ii] >= count) break;
-        dict = ghb_array_get(presets, indices[ii]);
-        name = ghb_dict_get(dict, "PresetName");
-        if (name)
-            ghb_array_append(path, ghb_value_dup(name));
-        folder = ghb_value_get_bool(ghb_dict_get(dict, "Folder"));
-        if (!folder)
-            break;
+        gint      depth = 0;
+        gint      count, ii;
+        GhbValue *presets;
+
         presets = ghb_dict_get(dict, "ChildrenArray");
+        count   = ghb_array_len(presets);
+        for (ii = 0; ii < count; ii++)
+        {
+            gint tmp;
+
+            dict  = ghb_array_get(presets, ii);
+            tmp   = preset_tree_depth(dict);
+            depth = MAX(depth, tmp);
+        }
+        return depth + 1;
+    }
+    else
+    {
+        return 1;
     }
-    return path;
 }
 
-gchar*
-ghb_preset_path_string(const GhbValue *path)
+void
+ghb_presets_list_show_default(signal_user_data_t *ud)
 {
-    gint count, ii;
-    GString *gstr;
-    GhbValue *val;
-    gchar *str;
+    hb_preset_index_t *path;
 
-    gstr = g_string_new("");
-    if (path != NULL)
+    path = hb_presets_get_default_index();
+    if (path == NULL || path->depth == 0)
+        return;
+
+    GtkTreeView  *treeview;
+    GtkTreeStore *store;
+    GtkTreePath  *treepath;
+    GtkTreeIter   iter;
+
+    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
+    store    = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
+    treepath = ghb_tree_path_new_from_index(path);
+    if (treepath)
     {
-        count = ghb_array_len(path);
-        for (ii = 0; ii < count; ii++)
+        if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath))
         {
-            val = ghb_array_get(path, ii);
-            const char *tmp = ghb_value_get_string(val);
-            g_string_append(gstr, tmp);
-            if (ii < count-1)
-                g_string_append(gstr, "->");
+            gtk_tree_store_set(store, &iter,
+                        1, 800,
+                        2, 2 ,
+                        -1);
         }
+        gtk_tree_path_free(treepath);
     }
-    str = g_string_free(gstr, FALSE);
-    return str;
+    free(path);
 }
 
 void
-dump_preset_path(const gchar *msg, const GhbValue *path)
+ghb_presets_list_clear_default(signal_user_data_t *ud)
 {
-    gchar *str;
+    hb_preset_index_t *path;
 
-    if (path)
-        debug_show_type (ghb_value_type(path));
-    str = ghb_preset_path_string(path);
-    g_message("%s path: (%s)", msg, str);
-    g_free(str);
-}
+    path = hb_presets_get_default_index();
+    if (path == NULL || path->depth == 0)
+        return;
 
-void
-dump_preset_indices(const gchar *msg, gint *indices, gint len)
-{
-    gint ii;
+    GtkTreeView  *treeview;
+    GtkTreeStore *store;
+    GtkTreePath  *treepath;
+    GtkTreeIter   iter;
 
-    g_message("%s indices: len %d", msg, len);
-    for (ii = 0; ii < len; ii++)
+    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
+    store    = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
+    treepath = ghb_tree_path_new_from_index(path);
+    if (treepath)
     {
-        printf("%d ", indices[ii]);
+        if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath))
+        {
+            gtk_tree_store_set(store, &iter,
+                        1, 400,
+                        2, 0 ,
+                        -1);
+        }
+        gtk_tree_path_free(treepath);
     }
-    printf("\n");
+    free(path);
 }
 
-#if 0
 static gint
-preset_path_cmp(const GhbValue *path1, const GhbValue *path2)
+preset_get_type(hb_preset_index_t *path)
 {
-    gint count, ii;
-    GhbValue *val;
-    const gchar *str1, *str2;
-    gint result;
-
-    count = ghb_array_len(path1);
-    ii = ghb_array_len(path2);
-    if (ii != count)
-        return ii - count;
-    for (ii = 0; ii < count; ii++)
+    GhbValue *dict;
+    dict = hb_preset_get(path);
+    if (dict)
     {
-        val = ghb_array_get(path1, ii);
-        str1 = ghb_value_get_string(val);
-        val = ghb_array_get(path2, ii);
-        str2 = ghb_value_get_string(val);
-        result = strcmp(str1, str2);
-        if (result != 0)
-            return result;
+        return ghb_dict_get_int(dict, "Type");
     }
-    return 0;
-}
-#endif
-
-static GhbValue*
-presets_get_dict(GhbValue *presets, gint *indices, gint len)
-{
-    gint ii, count, folder;
-    GhbValue *dict = NULL;
-
-    g_debug("presets_get_dict ()");
-    for (ii = 0; ii < len; ii++)
+    else
     {
-        count = ghb_array_len(presets);
-        if (indices[ii] >= count) return NULL;
-        dict = ghb_array_get(presets, indices[ii]);
-        if (ii < len-1)
-        {
-            folder = ghb_value_get_bool(ghb_dict_get(dict, "Folder"));
-            if (!folder)
-                return NULL;
-            presets = ghb_dict_get(dict, "ChildrenArray");
-        }
+        g_warning("ghb_preset_get_type (): internal preset lookup error");
+        return 0;
     }
-    if (ii < len)
-        return NULL;
-    return dict;
+    return 0;
 }
 
-static GhbValue*
-presets_get_folder(GhbValue *presets, gint *indices, gint len)
+static gboolean
+preset_is_folder(hb_preset_index_t *path)
 {
-    gint ii, count, folder;
     GhbValue *dict;
+    gboolean folder = FALSE;
 
-    g_debug("presets_get_folder ()");
-    for (ii = 0; ii < len; ii++)
+    dict = hb_preset_get(path);
+    if (dict)
     {
-        count = ghb_array_len(presets);
-        if (indices[ii] >= count) return NULL;
-        dict = ghb_array_get(presets, indices[ii]);
-        folder = ghb_value_get_bool(ghb_dict_get(dict, "Folder"));
-        if (!folder)
-            break;
-        presets = ghb_dict_get(dict, "ChildrenArray");
+        folder = ghb_dict_get_bool(dict, "Folder");
     }
-    if (ii < len)
-        return NULL;
-    return presets;
-}
-
-static GhbValue*
-plist_get_dict(GhbValue *presets, const gchar *name)
-{
-    if (presets == NULL || name == NULL) return NULL;
-    return ghb_dict_get(presets, name);
+    return folder;
 }
 
-static const gchar*
-preset_get_name(GhbValue *dict)
+void
+ghb_preset_to_settings(GhbValue *settings, GhbValue *preset)
 {
-    return ghb_value_get_string(ghb_dict_get(dict, "PresetName"));
-}
+    // Remove troublesome x264Option
+    ghb_dict_remove(settings, "x264Option");
 
-static gboolean
-preset_folder_is_open(GhbValue *dict)
-{
-    const GhbValue *gval;
+    // Initialize defaults
+    ghb_settings_init(settings, "Initialization");
 
-    gval = ghb_dict_get(dict, "FolderOpen");
-    if (gval != NULL)
-        return ghb_value_get_bool(gval);
-    return FALSE;
-}
+    // Initialize the ui settings from a preset
+    ghb_dict_copy(settings, preset);
 
-gboolean
-ghb_preset_folder(GhbValue *dict)
-{
-    return ghb_value_get_int(ghb_dict_get(dict, "Folder"));
-}
+    // Fix up all the internal settings that are derived from preset values.
+    ghb_dict_set_bool(settings, "PictureDeinterlaceDecomb",
+        !ghb_dict_get_bool(settings, "PictureDecombDeinterlace"));
 
-gint
-ghb_preset_type(GhbValue *dict)
-{
-    return ghb_value_get_int(ghb_dict_get(dict, "Type"));
-}
+    ghb_dict_set(settings, "scale_height", ghb_value_dup(
+        ghb_dict_get_value(settings, "PictureHeight")));
 
-static void
-presets_remove_nth(GhbValue *presets, gint pos)
-{
-    gint count;
+    ghb_dict_set(settings, "scale_width", ghb_value_dup(
+        ghb_dict_get_value(settings, "PictureWidth")));
 
-    if (presets == NULL || pos < 0) return;
-    count = ghb_array_len(presets);
-    if (pos >= count) return;
-    ghb_array_remove(presets, pos);
-}
+    gint uses_pic;
+    gint vqtype;
 
-gboolean
-ghb_presets_remove(
-    GhbValue *presets,
-    gint *indices,
-    gint len)
-{
-    GhbValue *folder = NULL;
+    uses_pic = ghb_dict_get_int(settings, "UsesPictureSettings");
+    vqtype = ghb_dict_get_int(settings, "VideoQualityType");
 
-    folder = presets_get_folder(presets, indices, len-1);
-    if (folder)
-        presets_remove_nth(folder, indices[len-1]);
-    else
+    // "Use max" or "strict anamorphic" imply autoscale
+    if (uses_pic == 2)
     {
-        g_warning("ghb_presets_remove (): internal preset lookup error");
-        return FALSE;
+        ghb_dict_set_bool(settings, "autoscale", TRUE);
+    }
+    else if (uses_pic == 1)
+    {
+        ghb_dict_set_bool(settings, "autoscale", FALSE);
     }
-    return TRUE;
-}
 
-static void
-ghb_presets_replace(
-    GhbValue *presets,
-    GhbValue *dict,
-    gint *indices,
-    gint len)
-{
-    GhbValue *folder = NULL;
+    // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
+    // *note: target is no longer used
+    switch (vqtype)
+    {
+    case 0:
+    {
+        ghb_dict_set_bool(settings, "vquality_type_bitrate", TRUE);
+        ghb_dict_set_bool(settings, "vquality_type_constant", FALSE);
+    } break;
+    case 1:
+    {
+        ghb_dict_set_bool(settings, "vquality_type_bitrate", TRUE);
+        ghb_dict_set_bool(settings, "vquality_type_constant", FALSE);
+    } break;
+    case 2:
+    {
+        ghb_dict_set_bool(settings, "vquality_type_bitrate", FALSE);
+        ghb_dict_set_bool(settings, "vquality_type_constant", TRUE);
+    } break;
+    default:
+    {
+        ghb_dict_set_bool(settings, "vquality_type_bitrate", FALSE);
+        ghb_dict_set_bool(settings, "vquality_type_constant", TRUE);
+    } break;
+    }
 
-    folder = presets_get_folder(presets, indices, len-1);
-    if (folder)
-        ghb_array_replace(folder, indices[len-1], dict);
+    const gchar *mode = ghb_dict_get_string(settings, "VideoFramerateMode");
+    if (strcmp(mode, "cfr") == 0)
+    {
+        ghb_dict_set_bool(settings, "VideoFramerateCFR", TRUE);
+        ghb_dict_set_bool(settings, "VideoFrameratePFR", FALSE);
+        ghb_dict_set_bool(settings, "VideoFramerateVFR", FALSE);
+    }
+    else if (strcmp(mode, "pfr") == 0)
+    {
+        ghb_dict_set_bool(settings, "VideoFramerateCFR", FALSE);
+        ghb_dict_set_bool(settings, "VideoFrameratePFR", TRUE);
+        ghb_dict_set_bool(settings, "VideoFramerateVFR", FALSE);
+    }
     else
     {
-        g_warning("ghb_presets_replace (): internal preset lookup error");
+        ghb_dict_set_bool(settings, "VideoFramerateCFR", FALSE);
+        ghb_dict_set_bool(settings, "VideoFrameratePFR", FALSE);
+        ghb_dict_set_bool(settings, "VideoFramerateVFR", TRUE);
     }
-}
-
-static void
-ghb_presets_insert(
-    GhbValue *presets,
-    GhbValue *dict,
-    gint *indices,
-    gint len)
-{
-    GhbValue *folder = NULL;
 
-    folder = presets_get_folder(presets, indices, len-1);
-    if (folder)
-        ghb_array_insert(folder, indices[len-1], dict);
+    if (ghb_dict_get_bool(settings, "x264UseAdvancedOptions"))
+    {
+        // Force preset/tune/profile/level/opts to conform to option string
+        ghb_dict_set_string(settings, "VideoPreset", "medium");
+        ghb_dict_set_string(settings, "VideoTune", "none");
+        ghb_dict_set_string(settings, "VideoProfile", "auto");
+        ghb_dict_set_string(settings, "VideoLevel", "auto");
+        ghb_dict_set(settings, "VideoOptionExtra", ghb_value_dup(
+            ghb_dict_get_value(settings, "x264Option")));
+    }
     else
     {
-        g_warning("ghb_presets_insert (): internal preset lookup error");
+        ghb_dict_remove(settings, "x264Option");
     }
-}
 
-static gint
-presets_find_element(GhbValue *presets, const gchar *name)
-{
-    GhbValue *dict;
-    gint count, ii;
+    int                 ii, encoder;
+    const char * const *videoPresets;
+    const char         *videoPreset;
 
-    g_debug("presets_find_element () (%s)", name);
-    if (presets == NULL || name == NULL) return -1;
-    count = ghb_array_len(presets);
-    for (ii = 0; ii < count; ii++)
+    encoder      = ghb_get_video_encoder(settings);
+    videoPresets = hb_video_encoder_get_presets(encoder);
+    videoPreset  = ghb_dict_get_string(settings, "VideoPreset");
+    for (ii = 0; videoPreset && videoPresets && videoPresets[ii]; ii++)
     {
-        const gchar *str;
-        dict = ghb_array_get(presets, ii);
-        str = preset_get_name(dict);
-        if (strcmp(name, str) == 0)
+        if (!strcasecmp(videoPreset, videoPresets[ii]))
         {
-            return ii;
+            ghb_dict_set_int(settings, "VideoPresetSlider", ii);
+            break;
         }
     }
-    return -1;
-}
+    if (videoPreset != NULL)
+        ghb_dict_set_string(settings, "VideoPreset", videoPreset);
 
-static gint
-single_find_pos(GhbValue *presets, const gchar *name, gint type)
-{
-    GhbValue *dict;
-    gint count, ii, ptype, last;
+    char *videoTune;
+    char *tune = NULL;
+    char *saveptr;
+    char *tok;
 
-    if (presets == NULL || name == NULL) return -1;
-    last = count = ghb_array_len(presets);
-    for (ii = 0; ii < count; ii++)
+    videoTune = g_strdup(ghb_dict_get_string(settings, "VideoTune"));
+    tok = strtok_r(videoTune, ",./-+", &saveptr);
+    ghb_dict_set_bool(settings, "x264FastDecode", FALSE);
+    ghb_dict_set_bool(settings, "x264ZeroLatency", FALSE);
+    while (tok != NULL)
     {
-        const gchar *str;
-        dict = ghb_array_get(presets, ii);
-        str = preset_get_name(dict);
-        ptype = ghb_value_get_int(ghb_dict_get(dict, "Type"));
-        if (strcasecmp(name, str) <= 0 && ptype == type)
+        if (!strcasecmp(tok, "fastdecode"))
         {
-            return ii;
+            ghb_dict_set_bool(settings, "x264FastDecode", TRUE);
         }
-        if (ptype == type)
-            last = ii+1;
-    }
-    return last;
-}
-
-static gint*
-presets_find_pos(const GhbValue *path, gint type, gint *len)
-{
-    GhbValue *nested;
-    GhbValue *val;
-    gint count, ii;
-    gboolean folder;
-    gint *indices = NULL;
-    const gchar *name;
-    GhbValue *dict;
-
-    g_debug("presets_find_pos () ");
-    nested = presetsPlist;
-    count = ghb_array_len(path);
-    indices = g_malloc(MAX_NESTED_PRESET * sizeof(gint));
-    for (ii = 0; ii < count-1; ii++)
-    {
-        val = ghb_array_get(path, ii);
-        name = ghb_value_get_string(val);
-        indices[ii] = presets_find_element(nested, name);
-        if (indices[ii] == -1) {
-            g_free(indices);
-            return NULL;
+        else if (!strcasecmp(tok, "zerolatency"))
+        {
+            ghb_dict_set_bool(settings, "x264ZeroLatency", TRUE);
         }
-        dict = ghb_array_get(nested, indices[ii]);
-        folder = ghb_value_get_bool(ghb_dict_get(dict, "Folder"));
-        nested = NULL;
-        if (!folder)
-            break;
-        nested = ghb_dict_get(dict, "ChildrenArray");
+        else if (tune == NULL)
+        {
+            tune = g_strdup(tok);
+        }
+        else
+        {
+            ghb_log("Superfluous tunes! %s", tok);
+        }
+        tok = strtok_r(NULL, ",./-+", &saveptr);
     }
-    if (nested)
+    g_free(videoTune);
+    if (tune != NULL)
     {
-        const gchar *name;
-
-        name = ghb_value_get_string(ghb_array_get(path, count-1));
-        indices[ii] = single_find_pos(nested, name, type);
-        ii++;
+        ghb_dict_set_string(settings, "VideoTune", tune);
+        g_free(tune);
     }
-    *len = ii;
-    return indices;
-}
 
-static gint
-preset_tree_depth(GhbValue *dict)
-{
-    gboolean folder;
+    const char *videoProfile;
+    videoProfile = ghb_dict_get_string(settings, "VideoProfile");
+    if (videoProfile != NULL)
+        ghb_dict_set_string(settings, "VideoProfile", videoProfile);
+
+    const char *videoLevel;
+    videoLevel = ghb_dict_get_string(settings, "VideoLevel");
+    if (videoLevel != NULL)
+        ghb_dict_set_string(settings, "VideoLevel", videoLevel);
 
-    folder = ghb_value_get_bool(ghb_dict_get(dict, "Folder"));
-    if (folder)
+    if (ghb_dict_get(settings, "x264OptionExtra") != NULL)
     {
-        gint depth = 0;
-        gint count, ii;
-        GhbValue *presets;
+        const char *optionExtra;
+        optionExtra = ghb_dict_get_string(settings, "x264OptionExtra");
+        ghb_dict_set_string(settings, "VideoOptionExtra", optionExtra);
+    }
 
-        presets = ghb_dict_get(dict, "ChildrenArray");
-        count = ghb_array_len(presets);
+    // Extract copy mask to check box booleans
+    GhbValue *copy_mask;
+    copy_mask = ghb_dict_get(preset, "AudioCopyMask");
+    if (copy_mask != NULL)
+    {
+        int count = ghb_array_len(copy_mask);
+        int ii;
         for (ii = 0; ii < count; ii++)
         {
-            gint tmp;
-
-            dict = ghb_array_get(presets, ii);
-            tmp = preset_tree_depth(dict);
-            depth = MAX(depth, tmp);
+            GhbValue *val = ghb_array_get(copy_mask, ii);
+            const char *s = ghb_value_get_string(val);
+            int acodec = hb_audio_encoder_get_from_name(s);
+            switch (acodec)
+            {
+                default:
+                    break;
+                case HB_ACODEC_LAME:
+                case HB_ACODEC_MP3_PASS:
+                    ghb_dict_set_bool(settings, "AudioAllowMP3Pass", 1);
+                    break;
+                case HB_ACODEC_CA_AAC:
+                case HB_ACODEC_FDK_AAC:
+                case HB_ACODEC_FFAAC:
+                case HB_ACODEC_AAC_PASS:
+                    ghb_dict_set_bool(settings, "AudioAllowAACPass", 1);
+                    break;
+                case HB_ACODEC_AC3:
+                case HB_ACODEC_AC3_PASS:
+                    ghb_dict_set_bool(settings, "AudioAllowAC3Pass", 1);
+                    break;
+                case HB_ACODEC_DCA:
+                case HB_ACODEC_DCA_PASS:
+                    ghb_dict_set_bool(settings, "AudioAllowDTSPass", 1);
+                    break;
+                case HB_ACODEC_DCA_HD:
+                case HB_ACODEC_DCA_HD_PASS:
+                    ghb_dict_set_bool(settings, "AudioAllowDTSHDPass", 1);
+                    break;
+                case HB_ACODEC_FFEAC3:
+                case HB_ACODEC_EAC3_PASS:
+                    ghb_dict_set_bool(settings, "AudioAllowEAC3Pass", 1);
+                    break;
+                case HB_ACODEC_FFFLAC:
+                case HB_ACODEC_FFFLAC24:
+                case HB_ACODEC_FLAC_PASS:
+                    ghb_dict_set_bool(settings, "AudioAllowFLACPass", 1);
+                    break;
+                case HB_ACODEC_FFTRUEHD:
+                case HB_ACODEC_TRUEHD_PASS:
+                    ghb_dict_set_bool(settings, "AudioAllowTRUEHDPass", 1);
+                    break;
+            }
         }
-        return depth + 1;
-    }
-    else
-    {
-        return 1;
     }
 }
 
-static gboolean
-preset_is_default(GhbValue *dict)
+// Initialization order of some widgets matter because the value of
+// these widgets are used to establich limits on the values that
+// other widgets are allowed to take.
+//
+// So make sure these get initialized first.
+static const char *widget_priority_list[] =
 {
-    const GhbValue *val;
-
-    val = ghb_dict_get(dict, "Default");
-    return ghb_value_get_bool(val);
-}
+    "preview_count",
+    "PtoPType",
+    "VideoEncoder",
+    "VideoQualityGranularity",
+    "AudioEncoder",
+    NULL
+};
 
-static void
-presets_clear_default(GhbValue *presets)
+void
+ghb_settings_to_ui(signal_user_data_t *ud, GhbValue *dict)
 {
-    gint count, ii;
-
-    count = ghb_array_len(presets);
-    for (ii = 0; ii < count; ii++)
-    {
-        GhbValue *dict;
-        gboolean folder;
+    GhbDictIter  iter;
+    const gchar *key;
+    GhbValue    *gval;
+    int          ii;
+    GhbValue    *tmp = ghb_value_dup(dict);
 
-        dict = ghb_array_get(presets, ii);
-        folder = ghb_value_get_bool(ghb_dict_get(dict, "Folder"));
-        if (folder)
-        {
-            GhbValue *nested;
+    if (dict == NULL)
+        return;
 
-            nested = ghb_dict_get(dict, "ChildrenArray");
-            presets_clear_default(nested);
-        }
-        else
-        {
-            if (preset_is_default(dict))
-            {
-                ghb_dict_set(dict, "Default", ghb_bool_value_new(FALSE));
-            }
-        }
+    for (ii = 0; widget_priority_list[ii] != NULL; ii++)
+    {
+        key = widget_priority_list[ii];
+        gval = ghb_dict_get_value(tmp, key);
+        if (gval != NULL)
+            ghb_ui_settings_update(ud, dict, key, gval);
     }
-}
-
-static void
-presets_customize(GhbValue *presets)
-{
-    gint count, ii;
 
-    count = ghb_array_len(presets);
-    for (ii = 0; ii < count; ii++)
+    iter = ghb_dict_iter_init(tmp);
+    // middle (void*) cast prevents gcc warning "defreferencing type-punned
+    // pointer will break strict-aliasing rules"
+    while (ghb_dict_iter_next(tmp, &iter, &key, &gval))
     {
-        GhbValue *dict;
-        gboolean folder;
-        gint ptype;
-
-        dict = ghb_array_get(presets, ii);
-
-        ptype = ghb_value_get_int(ghb_dict_get(dict, "Type"));
-        if (ptype != PRESETS_CUSTOM)
-        {
-            ghb_dict_set(dict, "Type", ghb_int_value_new(PRESETS_CUSTOM));
-        }
-        folder = ghb_value_get_bool(ghb_dict_get(dict, "Folder"));
-        if (folder)
-        {
-            GhbValue *nested;
-
-            nested = ghb_dict_get(dict, "ChildrenArray");
-            presets_customize(nested);
-        }
+        ghb_ui_settings_update(ud, dict, key, gval);
     }
+    ghb_value_free(&tmp);
 }
 
-static gint*
-presets_find_default2(GhbValue *presets, gint *len)
+static void
+select_preset2(GtkBuilder *builder, hb_preset_index_t *path)
 {
-    gint count, ii;
-    gint *indices;
+    GtkTreeView      *treeview;
+    GtkTreeSelection *selection;
+    GtkTreeModel     *store;
+    GtkTreeIter       iter;
+    GtkTreePath      *treepath;
 
-    count = ghb_array_len(presets);
-    for (ii = 0; ii < count; ii++)
-    {
-        GhbValue *dict;
-        gboolean folder;
+    if (path == NULL || path->depth == 0)
+        return;
 
-        dict = ghb_array_get(presets, ii);
-        folder = ghb_value_get_bool(ghb_dict_get(dict, "Folder"));
-        if (folder)
+    treeview  = GTK_TREE_VIEW(GHB_WIDGET(builder, "presets_list"));
+    selection = gtk_tree_view_get_selection (treeview);
+    store     = gtk_tree_view_get_model (treeview);
+    treepath  = ghb_tree_path_new_from_index(path);
+    if (treepath != NULL)
+    {
+        gtk_tree_view_expand_to_path(treeview, treepath);
+        if (gtk_tree_model_get_iter(store, &iter, treepath))
         {
-            GhbValue *nested;
-            gint pos = *len;
-
-            nested = ghb_dict_get(dict, "ChildrenArray");
-            (*len)++;
-            indices = presets_find_default2(nested, len);
-            if (indices)
-            {
-                indices[pos] = ii;
-                return indices;
-            }
-            else
-                *len = pos;
+            gtk_tree_selection_select_iter(selection, &iter);
         }
         else
         {
-            if (preset_is_default(dict))
-            {
-                indices = g_malloc(MAX_NESTED_PRESET * sizeof(gint));
-                indices[*len] = ii;
-                (*len)++;
-                return indices;
-            }
+            if (gtk_tree_model_get_iter_first(store, &iter))
+                gtk_tree_selection_select_iter(selection, &iter);
         }
+        gtk_tree_path_free(treepath);
     }
-    return NULL;
 }
 
-static gint*
-presets_find_default(GhbValue *presets, gint *len)
+void
+ghb_select_preset(GtkBuilder *builder, const char *name)
 {
-    *len = 0;
-    return presets_find_default2(presets, len);
-}
+    hb_preset_index_t *path;
 
-gint*
-ghb_preset_indices_from_path(
-    GhbValue *presets,
-    const GhbValue *path,
-    gint *len)
-{
-    GhbValue *nested;
-    GhbValue *val;
-    gint count, ii;
-    gint *indices = NULL;
-    const gchar *name;
-    GhbValue *dict;
-    gboolean folder;
-
-    g_debug("ghb_preset_indices_from_path () ");
-    nested = presets;
-    count = ghb_array_len(path);
-    if (count)
-        indices = g_malloc(MAX_NESTED_PRESET * sizeof(gint));
-    *len = 0;
-    for (ii = 0; ii < count; ii++)
+    path = hb_preset_search_index(name, 1);
+    if (path != NULL)
     {
-        val = ghb_array_get(path, ii);
-        name = ghb_value_get_string(val);
-        indices[ii] = presets_find_element(nested, name);
-        if (indices[ii] == -1)
-        {
-            g_free(indices);
-            return NULL;
-        }
-        if (ii < count-1)
-        {
-            dict = ghb_array_get(nested, indices[ii]);
-            folder = ghb_value_get_bool(ghb_dict_get(dict, "Folder"));
-            if (!folder)
-            {
-                g_free(indices);
-                return NULL;
-            }
-            nested = ghb_dict_get(dict, "ChildrenArray");
-        }
+        select_preset2(builder, path);
+        free(path);
     }
-    *len = ii;
-    return indices;
 }
 
-static gint
-ghb_presets_get_type(
-    GhbValue *presets,
-    gint *indices,
-    gint len)
+void
+ghb_select_default_preset(GtkBuilder *builder)
 {
-    GhbValue *dict;
-    gint type = 0;
+    hb_preset_index_t *path;
 
-    dict = presets_get_dict(presets, indices, len);
-    if (dict)
-    {
-        type = ghb_preset_type(dict);
-    }
-    else
+    path = hb_presets_get_default_index();
+    if (path != NULL)
     {
-        g_warning("ghb_presets_get_type (): internal preset lookup error");
+        select_preset2(builder, path);
+        g_free(path);
     }
-    return type;
 }
 
-static gboolean
-ghb_presets_get_folder(
-    GhbValue *presets,
-    gint *indices,
-    gint len)
+gchar*
+ghb_get_user_config_dir(gchar *subdir)
 {
-    GhbValue *dict;
-    gboolean folder = FALSE;
+    const gchar *dir;
+    gchar       *config;
 
-    dict = presets_get_dict(presets, indices, len);
-    if (dict)
+    dir = g_get_user_config_dir();
+    if (!g_file_test(dir, G_FILE_TEST_IS_DIR))
     {
-        folder = ghb_preset_folder(dict);
+        dir    = g_get_home_dir();
+        config = g_strdup_printf ("%s/.ghb", dir);
+        if (!g_file_test(config, G_FILE_TEST_IS_DIR))
+            g_mkdir (config, 0755);
     }
     else
     {
-        g_warning("ghb_presets_get_folder (): internal preset lookup error");
+        config = g_strdup_printf ("%s/ghb", dir);
+        if (!g_file_test(config, G_FILE_TEST_IS_DIR))
+            g_mkdir (config, 0755);
     }
-    return folder;
-}
+    if (subdir)
+    {
+        gchar **split;
+        gint    ii;
 
-void
-presets_set_default(gint *indices, gint len)
-{
-    GhbValue *dict;
+        split = g_strsplit(subdir, G_DIR_SEPARATOR_S, -1);
+        for (ii = 0; split[ii] != NULL; ii++)
+        {
+            gchar *tmp;
 
-    g_debug("presets_set_default ()");
-    presets_clear_default(presetsPlist);
-    dict = presets_get_dict(presetsPlist, indices, len);
-    if (dict)
-    {
-        ghb_dict_set(dict, "Default", ghb_bool_value_new(TRUE));
+            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);
+        }
+        g_strfreev(split);
     }
-    store_presets();
+    return config;
 }
 
 static void
-presets_set_folder_open(gboolean open, gint *indices, gint len)
+write_config_file(const gchar *name, GhbValue *dict)
 {
-    GhbValue *dict;
+    gchar *config, *path;
 
-    g_debug("presets_set_folder_open ()");
-    dict = presets_get_dict(presetsPlist, indices, len);
-    if (dict)
-    {
-        ghb_dict_set(dict, "FolderOpen", ghb_bool_value_new(open));
-    }
+    config = ghb_get_user_config_dir(NULL);
+    path   = g_strdup_printf ("%s/%s", config, name);
+    g_free(config);
+    ghb_json_write_file(path, dict);
+    g_free(path);
 }
 
-static void init_settings_from_dict(
-    GhbValue *dest, GhbValue *template, GhbValue *dict, gboolean filter);
+void
+ghb_write_settings_file(const gchar *path, GhbValue *dict)
+{
+    ghb_json_write_file(path, dict);
+}
 
-static void
-init_settings_from_array(
-    GhbValue *dest,
-    GhbValue *template,
-    GhbValue *array,
-    gboolean filter)
+static int
+presets_add_config_file(const gchar *name)
 {
-    GhbValue *gval, *val, *new_val;
-    gint count, ii;
+    gchar      *config, *path;
+    hb_value_t *preset;
 
-    if (ghb_array_len(template) == 0)
+    config = ghb_get_user_config_dir(NULL);
+    path   = g_strdup_printf ("%s/%s", config, name);
+    g_free(config);
+    if (!g_file_test(path, G_FILE_TEST_IS_REGULAR))
+        return -1;
+    preset = hb_presets_read_file(path);
+    g_free(path);
+    if (preset != NULL)
     {
-        if (!filter)
-        {
-            count = ghb_array_len(array);
-            for (ii = 0; ii < count; ii++)
-            {
-                val = ghb_array_get(array, ii);
-                ghb_array_append(dest, ghb_value_dup(val));
-            }
-        }
-        return;
-    }
+        hb_presets_add(preset);
 
-    count = ghb_array_len(array);
-    // The first element of the template array is always the
-    // template for the allowed values
-    gval = ghb_array_get(template, 0);
-    for (ii = 0; ii < count; ii++)
-    {
-        val = ghb_array_get(array, ii);
-        if (ghb_value_type(gval) == GHB_DICT)
-        {
-            GhbValue *new_dict;
-            if (val != NULL && ghb_value_type(val) == GHB_DICT)
-            {
-                new_dict = ghb_dict_new();
-                init_settings_from_dict(new_dict, gval, val, filter);
-            }
-            else
-            {
-                new_dict = ghb_value_dup(gval);
-            }
-            new_val = new_dict;
-        }
-        else if (ghb_value_type(gval) == GHB_ARRAY)
-        {
-            GhbValue *new_array;
-            if (val != NULL && ghb_value_type(val) == GHB_ARRAY)
-            {
-                new_array = ghb_array_new();
-                init_settings_from_array(new_array, gval, val, filter);
-            }
-            else
-            {
-                new_array = ghb_value_dup(gval);
-            }
-            new_val = new_array;
-        }
-        else
+        int hb_major, hb_minor, hb_micro;
+        int major, minor, micro;
+        hb_presets_version(preset, &major, &minor, &micro);
+        hb_presets_current_version(&hb_major, &hb_minor, &hb_micro);
+        if (major != hb_major || minor != hb_minor || micro != hb_micro)
         {
-            if (val == NULL)
-                new_val = ghb_value_dup(gval);
-            else
-                new_val = ghb_value_dup(val);
+            // Reload hb builtin presets
+            hb_presets_builtin_update();
+            store_presets();
         }
-        ghb_array_append(dest, new_val);
+        return 0;
     }
+    return -1;
 }
 
-static void
-init_settings_from_dict(
-    GhbValue *dest,
-    GhbValue *template,
-    GhbValue *dict,
-    gboolean filter)
+static GhbValue*
+read_config_file(const gchar *name)
 {
-    GhbDictIter iter;
-    const gchar *key;
-    GhbValue *gval, *val, *new_val;
+    gchar    *config, *path;
+    GhbValue *gval = NULL;
 
-    iter = ghb_dict_iter_init(template);
-    // middle (void*) cast prevents gcc warning "defreferencing type-punned
-    // pointer will break strict-aliasing rules"
-    while (ghb_dict_iter_next(template, &iter, &key, &gval))
+    config = ghb_get_user_config_dir(NULL);
+    path   = g_strdup_printf ("%s/%s", config, name);
+    g_free(config);
+    if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
     {
-        val = NULL;
-        if (dict)
-            val = ghb_dict_get(dict, key);
-        if (ghb_value_type(gval) == GHB_DICT)
-        {
-            GhbValue *new_dict;
-            if (val != NULL && ghb_value_type(val) == GHB_DICT)
-            {
-                new_dict = ghb_dict_new();
-                init_settings_from_dict(new_dict, gval, val, filter);
-            }
-            else
-            {
-                new_dict = ghb_value_dup(gval);
-            }
-            new_val = new_dict;
-        }
-        else if (ghb_value_type(gval) == GHB_ARRAY)
-        {
-            GhbValue *new_array;
-            if (val != NULL && ghb_value_type(val) == GHB_ARRAY)
-            {
-                new_array = ghb_array_new();
-                init_settings_from_array(new_array, gval, val, filter);
-            }
-            else
-            {
-                new_array = ghb_value_dup(gval);
-            }
-            new_val = new_array;
-
-        }
-        else
-        {
-            if (val == NULL)
-                new_val = ghb_value_dup(gval);
-            else
-                new_val = ghb_value_dup(val);
-        }
-        ghb_dict_set(dest, key, new_val);
+        gval = ghb_json_parse_file(path);
+        if (gval == NULL)
+            gval = hb_plist_parse_file(path);
     }
+    g_free(path);
+    return gval;
+}
 
-    if (filter || dict == NULL)
-        return;
+GhbValue*
+ghb_read_settings_file(const gchar *path)
+{
+    GhbValue *gval = NULL;
 
-    // If not filtering the source, copy source elements that
-    // were not in the template.
-    iter = ghb_dict_iter_init(dict);
-    // middle (void*) cast prevents gcc warning "defreferencing type-punned
-    // pointer will break strict-aliasing rules"
-    while (ghb_dict_iter_next(dict, &iter, &key, &gval))
+    if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
     {
-        val = ghb_dict_get(template, key);
-        if (val == NULL)
-        {
-            ghb_dict_set(dest, key, ghb_value_dup(gval));
-        }
+        gval = ghb_json_parse_file(path);
+        if (gval == NULL)
+            gval = hb_plist_parse_file(path);
     }
+    return gval;
 }
 
-void
-ghb_preset_to_settings(GhbValue *settings, GhbValue *preset)
+#if 0
+// Currently unused, but keeping around just in case...
+gboolean
+ghb_lock_file(const gchar *name)
 {
-    // Initialize the ui from presets file.
-    GhbValue *internal;
-
-    // Get key list from internal default presets.  This way we do not
-    // load any unknown keys.
-    GhbValue *internalPlist = ghb_resource_get("internal-defaults");
-    if (internalPlist == NULL) return;
-    internal = plist_get_dict(internalPlist, "Presets");
-    if (preset == NULL)
-        preset = internal;
-
-    ghb_dict_remove(settings, "x264Option");
-    init_settings_from_dict(settings, preset, NULL, TRUE);
-}
-
-// Initialization order of some widgets matter because the value of
-// these widgets are used to establich limits on the values that
-// other widgets are allowed to take.
-//
-// So make sure these get initialized first.
-static const char *widget_priority_list[] = 
-{
-    "preview_count",
-    "PtoPType",
-    "VideoEncoder",
-    "VideoQualityGranularity",
-    "AudioEncoder",
-    NULL
-};
-
-void
-ghb_settings_to_ui(signal_user_data_t *ud, GhbValue *dict)
-{
-    GhbDictIter iter;
-    const gchar *key;
-    GhbValue *gval;
-    int ii;
-    GhbValue *tmp = ghb_value_dup(dict);
-
-    if (dict == NULL)
-        return;
-
-    for (ii = 0; widget_priority_list[ii] != NULL; ii++)
-    {
-        key = widget_priority_list[ii];
-        gval = ghb_dict_get_value(tmp, key);
-        if (gval != NULL)
-            ghb_ui_settings_update(ud, dict, key, gval);
-    }
-
-    iter = ghb_dict_iter_init(tmp);
-    // middle (void*) cast prevents gcc warning "defreferencing type-punned
-    // pointer will break strict-aliasing rules"
-    while (ghb_dict_iter_next(tmp, &iter, &key, &gval))
-    {
-        ghb_ui_settings_update(ud, dict, key, gval);
-    }
-    ghb_value_free(&tmp);
-}
-
-static GhbValue *current_preset = NULL;
-
-gboolean
-ghb_preset_is_custom()
-{
-    const GhbValue *val;
-
-    if (current_preset == NULL) return FALSE;
-    val = ghb_dict_get(current_preset, "Type");
-    return (ghb_value_get_int(val) == 1);
-}
-
-void
-ghb_set_preset_settings_from_indices(
-    signal_user_data_t *ud,
-    gint *indices,
-    gint len)
-{
-    GhbValue *dict = NULL;
-    gint fallback[2] = {0, -1};
-
-    if (indices)
-        dict = presets_get_dict(presetsPlist, indices, len);
-    if (dict == NULL)
-    {
-        indices = fallback;
-        len = 1;
-        dict = presets_get_dict(presetsPlist, indices, len);
-    }
-    if (dict == NULL)
-    {
-        ghb_preset_to_settings(ud->settings, NULL);
-        current_preset = NULL;
-    }
-    else
-    {
-        GhbValue *path;
-        gboolean folder;
-
-        current_preset = dict;
-        folder = ghb_value_get_bool(ghb_dict_get(dict, "Folder"));
-        if (folder)
-            ghb_preset_to_settings(ud->settings, NULL);
-        else
-            ghb_preset_to_settings(ud->settings, dict);
-        path = preset_path_from_indices(presetsPlist, indices, len);
-        ghb_dict_set(ud->settings, "preset", ghb_value_dup(path));
-        ghb_value_free(&path);
-    }
-}
-
-static const GhbValue*
-curr_preset_get_value(const gchar *key)
-{
-    if (current_preset == NULL) return NULL;
-    return ghb_dict_get(current_preset, key);
-}
-
-void
-ghb_update_from_preset(
-    signal_user_data_t *ud,
-    const gchar *key)
-{
-    const GhbValue *gval;
-
-    g_debug("ghb_update_from_preset() %s", key);
-    gval = curr_preset_get_value(key);
-    if (gval != NULL)
-    {
-        ghb_ui_update(ud, key, gval);
-    }
-}
-
-static void
-ghb_select_preset2(
-    GtkBuilder *builder,
-    gint *indices,
-    gint len)
-{
-    GtkTreeView *treeview;
-    GtkTreeSelection *selection;
-    GtkTreeModel *store;
-    GtkTreeIter iter;
-    GtkTreePath *path;
-
-    g_debug("ghb_select_preset2()");
-    treeview = GTK_TREE_VIEW(GHB_WIDGET(builder, "presets_list"));
-    selection = gtk_tree_view_get_selection (treeview);
-    store = gtk_tree_view_get_model (treeview);
-    path = ghb_tree_path_new_from_indices(indices, len);
-    if (path)
-    {
-        if (gtk_tree_model_get_iter(store, &iter, path))
-        {
-            gtk_tree_selection_select_iter (selection, &iter);
-        }
-        else
-        {
-            if (gtk_tree_model_get_iter_first(store, &iter))
-                gtk_tree_selection_select_iter (selection, &iter);
-        }
-        gtk_tree_path_free(path);
-    }
-}
-
-void
-ghb_select_preset(GtkBuilder *builder, const GhbValue *path)
-{
-    gint *indices, len;
-
-    g_debug("ghb_select_preset()");
-    indices = ghb_preset_indices_from_path(presetsPlist, path, &len);
-    if (indices)
-    {
-        ghb_select_preset2(builder, indices, len);
-        g_free(indices);
-    }
-}
-
-void
-ghb_select_default_preset(GtkBuilder *builder)
-{
-    gint *indices, len;
-
-    g_debug("ghb_select_default_preset()");
-    indices = presets_find_default(presetsPlist, &len);
-    if (indices)
-    {
-        ghb_select_preset2(builder, indices, len);
-        g_free(indices);
-    }
-}
-
-gchar*
-ghb_get_user_config_dir(gchar *subdir)
-{
-    const gchar *dir;
-    gchar *config;
-
-    dir = g_get_user_config_dir();
-    if (!g_file_test(dir, G_FILE_TEST_IS_DIR))
-    {
-        dir = g_get_home_dir();
-        config = g_strdup_printf ("%s/.ghb", dir);
-        if (!g_file_test(config, G_FILE_TEST_IS_DIR))
-            g_mkdir (config, 0755);
-    }
-    else
-    {
-        config = g_strdup_printf ("%s/ghb", dir);
-        if (!g_file_test(config, G_FILE_TEST_IS_DIR))
-            g_mkdir (config, 0755);
-    }
-    if (subdir)
-    {
-        gchar **split;
-        gint ii;
-
-        split = g_strsplit(subdir, G_DIR_SEPARATOR_S, -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);
-        }
-        g_strfreev(split);
-    }
-    return config;
-}
-
-static void
-write_config_file(const gchar *name, GhbValue *dict)
-{
-    gchar *config, *path;
-
-    config = ghb_get_user_config_dir(NULL);
-    path = g_strdup_printf ("%s/%s", config, name);
-    g_free(config);
-    ghb_json_write_file(path, dict);
-    g_free(path);
-}
-
-void
-ghb_write_settings_file(const gchar *path, GhbValue *dict)
-{
-    ghb_json_write_file(path, dict);
-}
-
-static void
-store_plist(const gchar *name, GhbValue *plist)
-{
-    gchar *config, *path;
-
-    config = ghb_get_user_config_dir(NULL);
-    path = g_strdup_printf ("%s/%s", config, name);
-    g_free(config);
-    ghb_plist_write_file(path, plist);
-    g_free(path);
-}
-
-static GhbValue*
-read_config_file(const gchar *name)
-{
-    gchar *config, *path;
-    GhbValue *gval = NULL;
-
-    config = ghb_get_user_config_dir(NULL);
-    path = g_strdup_printf ("%s/%s", config, name);
-    g_free(config);
-    if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
-    {
-        gval = ghb_json_parse_file(path);
-        if (gval == NULL)
-            gval = ghb_plist_parse_file(path);
-    }
-    g_free(path);
-    return gval;
-}
-
-GhbValue*
-ghb_read_settings_file(const gchar *path)
-{
-    GhbValue *gval = NULL;
-
-    if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
-    {
-        gval = ghb_json_parse_file(path);
-        if (gval == NULL)
-            gval = ghb_plist_parse_file(path);
-    }
-    return gval;
-}
-
-gboolean
-ghb_lock_file(const gchar *name)
-{
-#if !defined(_WIN32)
-    gchar *config, *path;
-    int fd, lock = 0;
+#if !defined(_WIN32)
+    gchar *config, *path;
+    int fd, lock = 0;
 
     config = ghb_get_user_config_dir(NULL);
     path = g_strdup_printf ("%s/%s", config, name);
@@ -1232,22 +736,22 @@ ghb_lock_file(const gchar *name)
     return 1;
 #endif
 }
+#endif
 
 void
 ghb_write_pid_file()
 {
 #if !defined(_WIN32)
     gchar *config, *path;
-    pid_t pid;
-    FILE *fp;
-    int fd;
-
-    pid = getpid();
+    pid_t  pid;
+    FILE  *fp;
+    int    fd;
 
+    pid    = getpid();
     config = ghb_get_user_config_dir(NULL);
-    path = g_strdup_printf ("%s/ghb.pid.%d", config, pid);
+    path   = g_strdup_printf ("%s/ghb.pid.%d", config, pid);
+    fp     = g_fopen(path, "w");
 
-    fp = g_fopen(path, "w");
     fprintf(fp, "%d\n", pid);
     fclose(fp);
 
@@ -1259,42 +763,26 @@ ghb_write_pid_file()
 #endif
 }
 
-void
-ghb_unlink_pid_file(int pid)
-{
-    gchar *config, *path;
-
-    config = ghb_get_user_config_dir(NULL);
-    path = g_strdup_printf ("%s/ghb.pid.%d", config, pid);
-
-    if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
-    {
-        g_unlink(path);
-    }
-
-    g_free(config);
-    g_free(path);
-}
-
 int
 ghb_find_pid_file()
 {
     const gchar *file;
-    gchar *config;
+    gchar       *config;
 
     config = ghb_get_user_config_dir(NULL);
 
     if (g_file_test(config, G_FILE_TEST_IS_DIR))
     {
-        GDir *gdir = g_dir_open(config, 0, NULL);
+        GDir *gdir;
+        gdir = g_dir_open(config, 0, NULL);
         file = g_dir_read_name(gdir);
         while (file)
         {
             if (strncmp(file, "ghb.pid.", 8) == 0)
             {
                 gchar *path;
-                pid_t my_pid;
-                int pid;
+                pid_t  my_pid;
+                int    pid;
 
                 sscanf(file, "ghb.pid.%d", &pid);
                 my_pid = getpid();
@@ -1346,7 +834,7 @@ remove_config_file(const gchar *name)
     gchar *config, *path;
 
     config = ghb_get_user_config_dir(NULL);
-    path = g_strdup_printf ("%s/%s", config, name);
+    path   = g_strdup_printf ("%s/%s", config, name);
     if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
     {
         g_unlink(path);
@@ -1355,33 +843,6 @@ remove_config_file(const gchar *name)
     g_free(config);
 }
 
-void
-ghb_prefs_save(GhbValue *settings)
-{
-    GhbValue *dict;
-    GhbValue *pref_dict;
-    GhbDictIter iter;
-    const gchar *key;
-    const GhbValue *value;
-
-    GhbValue *internalPlist = ghb_resource_get("internal-defaults");
-    dict = plist_get_dict(internalPlist, "Preferences");
-    if (dict == NULL) return;
-    pref_dict = plist_get_dict(prefsPlist, "Preferences");
-    if (pref_dict == NULL) return;
-    iter = ghb_dict_iter_init(dict);
-    while (ghb_dict_iter_next(dict, &iter, &key, NULL))
-    {
-        value = ghb_dict_get_value(settings, key);
-        if (value != NULL)
-        {
-            ghb_dict_set(pref_dict, key, ghb_value_dup(value));
-        }
-    }
-    store_prefs();
-    prefs_modified = FALSE;
-}
-
 void
 ghb_pref_save(GhbValue *settings, const gchar *key)
 {
@@ -1391,7 +852,7 @@ ghb_pref_save(GhbValue *settings, const gchar *key)
     if (value != NULL)
     {
         GhbValue *dict;
-        dict = plist_get_dict(prefsPlist, "Preferences");
+        dict = ghb_dict_get(prefsDict, "Preferences");
         if (dict == NULL) return;
         value2 = ghb_dict_get(dict, key);
         if (ghb_value_cmp(value, value2) != 0)
@@ -1412,7 +873,7 @@ ghb_pref_set(GhbValue *settings, const gchar *key)
     if (value != NULL)
     {
         GhbValue *dict;
-        dict = plist_get_dict(prefsPlist, "Preferences");
+        dict = ghb_dict_get(prefsDict, "Preferences");
         if (dict == NULL) return;
         value2 = ghb_dict_get(dict, key);
         if (ghb_value_cmp(value, value2) != 0)
@@ -1436,35 +897,23 @@ ghb_prefs_store(void)
 void
 ghb_settings_init(GhbValue *settings, const char *name)
 {
-    GhbValue *internal;
-    GhbDictIter iter;
-    const gchar *key;
-    GhbValue *gval;
+    GhbValue    *internal;
 
-    g_debug("ghb_settings_init");
-    GhbValue *internalPlist = ghb_resource_get("internal-defaults");
+    GhbValue *internalDict = ghb_resource_get("internal-defaults");
     // Setting a ui widget will cause the corresponding setting
     // to be set, but it also triggers a callback that can
     // have the side effect of using other settings values
     // that have not yet been set.  So set *all* settings first
     // then update the ui.
-    internal = plist_get_dict(internalPlist, name);
-    iter = ghb_dict_iter_init(internal);
-    // middle (void*) cast prevents gcc warning "defreferencing type-punned
-    // pointer will break strict-aliasing rules"
-    while (ghb_dict_iter_next(internal, &iter, &key, &gval))
-    {
-        ghb_dict_set(settings, key, ghb_value_dup(gval));
-    }
+    internal = ghb_dict_get(internalDict, name);
+    ghb_dict_copy(settings, internal);
 }
 
 void
 ghb_settings_close()
 {
-    if (presetsPlist)
-        ghb_value_free(&presetsPlist);
-    if (prefsPlist)
-        ghb_value_free(&prefsPlist);
+    if (prefsDict)
+        ghb_value_free(&prefsDict);
 }
 
 #if defined(_WIN32)
@@ -1498,47 +947,35 @@ FindFirstCDROM(void)
 void
 ghb_prefs_load(signal_user_data_t *ud)
 {
-    GhbValue *dict, *internal;
-    GhbDictIter iter;
-    const gchar *key;
-    GhbValue *gval;
-
-    g_debug("ghb_prefs_load");
-    GhbValue *internalPlist = ghb_resource_get("internal-defaults");
-    prefsPlist = read_config_file("preferences");
-    if (prefsPlist == NULL)
-        prefsPlist = ghb_dict_new();
-    dict = plist_get_dict(prefsPlist, "Preferences");
-    internal = plist_get_dict(internalPlist, "Preferences");
-    if (dict == NULL && internal)
-    {
-        dict = ghb_dict_new();
-        ghb_dict_set(prefsPlist, "Preferences", dict);
+    GhbValue    *dict, *internal;
+    GhbValue *internalDict;
 
-        // Get defaults from internal defaults
-        iter = ghb_dict_iter_init(internal);
-        // middle (void*) cast prevents gcc warning "defreferencing type-punned
-        // pointer will break strict-aliasing rules"
-        while (ghb_dict_iter_next(internal, &iter, &key, &gval))
-        {
-            ghb_dict_set(dict, key, ghb_value_dup(gval));
-        }
+    internalDict = ghb_resource_get("internal-defaults");
+    prefsDict    = read_config_file("preferences");
+    if (prefsDict == NULL)
+        prefsDict = ghb_dict_new();
+    dict     = ghb_dict_get(prefsDict, "Preferences");
+    internal = ghb_dict_get(internalDict, "Preferences");
+    if (dict == NULL && internal != NULL)
+    {
+        dict = ghb_value_dup(internal);
+        ghb_dict_set(prefsDict, "Preferences", dict);
 
         const gchar *dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
         if (dir == NULL)
         {
             dir = ".";
         }
-        ghb_dict_set(dict, "ExportDirectory", ghb_string_value_new(dir));
+        ghb_dict_set_string(dict, "ExportDirectory", dir);
 
         dir = g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS);
         if (dir == NULL)
         {
             dir = ".";
         }
-        ghb_dict_set(dict, "destination_dir", ghb_string_value_new(dir));
+        ghb_dict_set_string(dict, "destination_dir", dir);
 
-        ghb_dict_set(dict, "SrtDir", ghb_string_value_new(dir));
+        ghb_dict_set_string(dict, "SrtDir", dir);
 #if defined(_WIN32)
         gchar *source;
 
@@ -1547,7 +984,7 @@ ghb_prefs_load(signal_user_data_t *ud)
         {
             source = g_strdup("C:" G_DIR_SEPARATOR_S);
         }
-        ghb_dict_set(dict, "default_source", ghb_string_value_new(source));
+        ghb_dict_set_string(dict, "default_source", source);
         g_free(source);
 #endif
         store_prefs();
@@ -1558,34 +995,29 @@ void
 ghb_prefs_to_settings(GhbValue *settings)
 {
     // Initialize the ui from presets file.
-    GhbValue *internal, *dict;
+    GhbValue *dict;
 
-    if (prefsPlist == NULL)
+    if (prefsDict == NULL)
         return;
 
-    // Get key list from internal default presets.  This way we do not
-    // load any unknown keys.
-    GhbValue *internalPlist = ghb_resource_get("internal-defaults");
-    if (internalPlist == NULL) return;
-    internal = plist_get_dict(internalPlist, "Preferences");
-    dict = plist_get_dict(prefsPlist, "Preferences");
     // Setting a ui widget will cause the corresponding setting
     // to be set, but it also triggers a callback that can
     // have the side effect of using other settings values
     // that have not yet been set.  So set *all* settings first
     // then update the ui.
-    init_settings_from_dict(settings, internal, dict, TRUE);
+    dict     = ghb_dict_get(prefsDict, "Preferences");
+    ghb_dict_copy(settings, dict);
 }
 
 static const gchar*
-get_preset_color(gint type, gboolean folder)
+get_preset_color(gint type, gboolean is_folder)
 {
     const gchar *color;
 
     if (type == PRESETS_CUSTOM)
     {
         color = "DimGray";
-        if (folder)
+        if (is_folder)
         {
             color = "black";
         }
@@ -1593,7 +1025,7 @@ get_preset_color(gint type, gboolean folder)
     else
     {
         color = "blue";
-        if (folder)
+        if (is_folder)
         {
             color = "Navy";
         }
@@ -1602,1275 +1034,440 @@ get_preset_color(gint type, gboolean folder)
 }
 
 void
-ghb_presets_list_init(
-    signal_user_data_t *ud,
-    gint *indices,
-    gint len)
+ghb_presets_list_init(signal_user_data_t *ud, const hb_preset_index_t *path)
 {
-    GtkTreeView *treeview;
-    GtkTreeIter iter, titer, *piter;
+    hb_preset_index_t *next_path;
+    GhbValue          *folder;
+    GtkTreeView       *treeview;
+    GtkTreeStore      *store;
+    GtkTreePath       *parent_path;
+    GtkTreeIter        iter, *piter;
+    gint               count, ii;
 
-    GtkTreeStore *store;
-    const gchar *preset;
-    GtkTreePath *parent_path;
-    const gchar *description;
-    gboolean def;
-    gint count, ii;
-    GhbValue *dict;
-    gint *more_indices;
-    GhbValue *presets = NULL;
-
-    g_debug("ghb_presets_list_init ()");
-    more_indices = g_malloc((len+1)*sizeof(gint));
-    memcpy(more_indices, indices, len*sizeof(gint));
-    presets = presets_get_folder(presetsPlist, indices, len);
-    if (presets == NULL)
+    if (path == NULL)
     {
-        g_warning(_("Failed to find parent folder when adding child."));
-        g_free(more_indices);
+        hb_preset_index_t *p = hb_preset_index_init(NULL, 0);
+        ghb_presets_list_init(ud, p);
+        free(p);
         return;
     }
-    count = ghb_array_len(presets);
-    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
-    store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
-    parent_path = ghb_tree_path_new_from_indices(indices, len);
-    if (parent_path)
+    next_path = hb_preset_index_dup(path);
+    folder    = hb_presets_get_folder_children(path);
+    if (folder == NULL)
     {
-        gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &titer, parent_path);
-        piter = &titer;
+        g_warning(_("Failed to find parent folder when adding child."));
+        g_free(next_path);
+        return;
+    }
+    treeview    = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
+    store       = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
+    parent_path = ghb_tree_path_new_from_index(path);
+    if (parent_path != NULL)
+    {
+        GtkTreeIter tmp_iter;
+        gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &tmp_iter, parent_path);
+        piter = &tmp_iter;
         gtk_tree_path_free(parent_path);
     }
     else
     {
         piter = NULL;
     }
+    count = ghb_array_len(folder);
+    next_path->depth++;
     for (ii = 0; ii < count; ii++)
     {
+        GhbValue    *dict;
+        const gchar *name;
         const gchar *color;
-        gint type;
-        gboolean folder;
+        gint         type;
+        const gchar *description;
+        gboolean     is_folder;
+        gboolean     def;
+
+        next_path->index[next_path->depth-1] = ii;
 
         // Additional settings, add row
-        dict = ghb_array_get(presets, ii);
-        preset = preset_get_name(dict);
-        more_indices[len] = ii;
-        def = preset_is_default(dict);
+        dict        = ghb_array_get(folder, ii);
+        name        = ghb_dict_get_string(dict, "PresetName");
+        description = ghb_dict_get_string(dict, "PresetDescription");
+        type        = ghb_dict_get_int(dict, "Type");
+        is_folder   = ghb_dict_get_bool(dict, "Folder");
+        def         = ghb_dict_get_bool(dict, "Default");
+        color       = get_preset_color(type, is_folder);
 
-        description = ghb_value_get_string(
-                      ghb_dict_get(dict, "PresetDescription"));
         gtk_tree_store_append(store, &iter, piter);
-        type = ghb_preset_type(dict);
-        folder = ghb_preset_folder(dict);
-        color = get_preset_color(type, folder);
-        gtk_tree_store_set(store, &iter, 0, preset,
+        gtk_tree_store_set(store, &iter,
+                            0, name,
                             1, def ? 800 : 400,
-                            2, def ? 2 : 0,
+                            2, def ? 2   : 0,
                             3, color,
-                            4, description,
-                            5, type == PRESETS_BUILTIN ? 0 : 1,
-                            -1);
-        if (def && piter)
-        {
-            GtkTreePath *path;
-            GtkTreeIter ppiter;
-
-            if (gtk_tree_model_iter_parent(
-                GTK_TREE_MODEL(store), &ppiter, piter))
-            {
-                path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &ppiter);
-                gtk_tree_view_expand_row(treeview, path, FALSE);
-                gtk_tree_path_free(path);
-            }
-            path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), piter);
-            gtk_tree_view_expand_row(treeview, path, FALSE);
-            gtk_tree_path_free(path);
-        }
-        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 void
-presets_list_update_item(
-    signal_user_data_t *ud,
-    gint *indices,
-    gint len,
-    gboolean recurse)
-{
-    GtkTreeView *treeview;
-    GtkTreeStore *store;
-    GtkTreeIter iter;
-    GtkTreePath *treepath;
-    const gchar *name;
-    const gchar *description;
-    gint type;
-    gboolean def, folder;
-    GhbValue *dict;
-    const gchar *color;
-
-    g_debug("presets_list_update_item ()");
-    dict = presets_get_dict(presetsPlist, indices, len);
-    if (dict == NULL)
-        return;
-    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
-    store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
-    treepath = ghb_tree_path_new_from_indices(indices, len);
-    gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath);
-    // Additional settings, add row
-    name = preset_get_name(dict);
-    def = preset_is_default(dict);
-
-    description = ghb_value_get_string(ghb_dict_get(dict, "PresetDescription"));
-    type = ghb_preset_type(dict);
-    folder = ghb_preset_folder(dict);
-    color = get_preset_color(type, folder);
-    gtk_tree_store_set(store, &iter, 0, name,
-                        1, def ? 800 : 400,
-                        2, def ? 2 : 0,
-                        3, color,
-                        4, description,
-                        5, type == PRESETS_BUILTIN ? 0 : 1,
-                        -1);
-    if (recurse && folder)
-    {
-        ghb_presets_list_init(ud, indices, len);
-    }
-}
-
-static void
-presets_list_insert(
-    signal_user_data_t *ud,
-    gint *indices,
-    gint len)
-{
-    GtkTreeView *treeview;
-    GtkTreeIter iter, titer, *piter;
-    GtkTreeStore *store;
-    const gchar *preset;
-    const gchar *description;
-    gint type;
-    gboolean def, folder;
-    gint count;
-    GhbValue *presets;
-    GtkTreePath *parent_path;
-    GhbValue *dict;
-    const gchar *color;
-
-    g_debug("presets_list_insert ()");
-    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
-    store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
-    presets = presets_get_folder(presetsPlist, indices, len-1);
-    if (presets == NULL)
-    {
-        g_warning(_("Failed to find parent folder while adding child."));
-        return;
-    }
-    parent_path = ghb_tree_path_new_from_indices(indices, len-1);
-    if (parent_path)
-    {
-        gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &titer, parent_path);
-        piter = &titer;
-        gtk_tree_path_free(parent_path);
-    }
-    else
-    {
-        piter = NULL;
-    }
-    count = ghb_array_len(presets);
-    if (indices[len-1] >= count)
-        return;
-    // Additional settings, add row
-    dict = ghb_array_get(presets, indices[len-1]);
-    preset = preset_get_name(dict);
-    def = preset_is_default(dict);
-
-    description = ghb_value_get_string(ghb_dict_get(dict, "PresetDescription"));
-    gtk_tree_store_insert(store, &iter, piter, indices[len-1]);
-    type = ghb_preset_type(dict);
-    folder = ghb_preset_folder(dict);
-    color = get_preset_color(type, folder);
-    gtk_tree_store_set(store, &iter, 0, preset,
-                        1, def ? 800 : 400,
-                        2, def ? 2 : 0,
-                        3, color,
-                        4, description,
-                        5, type == PRESETS_BUILTIN ? 0 : 1,
-                        -1);
-    if (folder)
-    {
-        ghb_presets_list_init(ud, indices, len);
-    }
-}
-
-static void
-presets_list_remove(
-    signal_user_data_t *ud,
-    gint *indices,
-    gint len)
-{
-    GtkTreeView *treeview;
-    GtkTreePath *treepath;
-    GtkTreeIter iter;
-    GtkTreeStore *store;
-
-    g_debug("presets_list_remove ()");
-    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
-    store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
-    treepath = ghb_tree_path_new_from_indices(indices, len);
-    if (treepath)
-    {
-        if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath))
-            gtk_tree_store_remove(store, &iter);
-        gtk_tree_path_free(treepath);
-    }
-}
-
-static void
-remove_std_presets(signal_user_data_t *ud)
-{
-    gint count, ii;
-    gint indices = 0;
-
-    count = ghb_array_len(presetsPlist);
-    for (ii = count-1; ii >= 0; ii--)
-    {
-        GhbValue *dict;
-        gint ptype;
-
-        dict = ghb_array_get(presetsPlist, ii);
-        ptype = ghb_value_get_int(ghb_dict_get(dict, "Type"));
-        if (ptype == PRESETS_BUILTIN)
-        {
-            if (ghb_presets_remove(presetsPlist, &indices, 1))
-            {
-                presets_list_remove(ud, &indices, 1);
-            }
-        }
-    }
-}
-
-void
-ghb_save_queue(GhbValue *queue)
-{
-    pid_t pid;
-    char *name;
-
-    pid = getpid();
-    name = g_strdup_printf ("queue.%d", pid);
-    write_config_file(name, queue);
-    g_free(name);
-}
-
-GhbValue*
-ghb_load_queue()
-{
-    GhbValue *queue;
-    pid_t pid;
-    char *name;
-
-    pid = getpid();
-    name = g_strdup_printf ("queue.%d", pid);
-    queue = read_config_file(name);
-    g_free(name);
-    return queue;
-}
-
-GhbValue*
-ghb_load_old_queue(int pid)
-{
-    GhbValue *queue;
-    char *name;
-
-    name = g_strdup_printf ("queue.%d", pid);
-    queue = read_config_file(name);
-    g_free(name);
-    return queue;
-}
-
-void
-ghb_remove_old_queue_file(int pid)
-{
-    char *name;
-
-    name = g_strdup_printf ("queue.%d", pid);
-    remove_config_file(name);
-    g_free(name);
-}
-
-void
-ghb_remove_queue_file()
-{
-    pid_t pid;
-    char *name;
-
-    pid = getpid();
-    name = g_strdup_printf ("queue.%d", pid);
-    remove_config_file(name);
-    g_free(name);
-}
-
-typedef struct
-{
-    const gchar *mac_val;
-    const gchar *lin_val;
-} value_map_t;
-
-value_map_t deint_xlat[] =
-{
-    {"0", "off"},
-    {"1", "custom"},
-    {"2", "fast"},
-    {"3", "slow"},
-    {"4", "slower"},
-    {"5", "bob"},
-    {NULL, NULL}
-};
-
-value_map_t denoise_xlat[] =
-{
-    {"0", "off"},
-    {"1", "custom"},
-    {"2", "light"},
-    {"3", "medium"},
-    {"4", "strong"},
-    {"5", "ultralight"},
-    {NULL, NULL}
-};
-
-value_map_t detel_xlat[] =
-{
-    {"0", "off"},
-    {"1", "custom"},
-    {"2", "default"},
-    {NULL, NULL}
-};
-
-value_map_t decomb_xlat[] =
-{
-    {"0", "off"},
-    {"1", "custom"},
-    {"2", "default"},
-    {"3", "fast"},
-    {"4", "bob"},
-    {NULL, NULL}
-};
-
-static GhbValue*
-export_value_video_framerate(GhbValue *lin_val)
-{
-    GhbValue *sval = NULL;
-    gchar *str;
-    const gchar *fr;
-
-    str = ghb_value_get_string_xform(lin_val);
-    fr = hb_video_framerate_get_name(hb_video_framerate_get_from_name(str));
-    g_free(str);
-    if (fr != NULL)
-        sval = ghb_string_value_new(fr);
-
-    return sval;
-}
-
-static GhbValue*
-export_value_audio_samplerate(GhbValue *lin_val)
-{
-    GhbValue *sval = NULL;
-    gchar *str;
-    const gchar *sr;
-
-    str = ghb_value_get_string_xform(lin_val);
-    sr = hb_audio_samplerate_get_name(hb_audio_samplerate_get_from_name(str));
-    g_free(str);
-    if (sr != NULL)
-        sval = ghb_string_value_new(sr);
-
-    return sval;
-}
-
-static GhbValue*
-export_value_mixdown(GhbValue *lin_val)
-{
-    GhbValue *sval = NULL;
-    const gchar *str;
-    const gchar *mix;
-
-    str = ghb_value_get_string(lin_val);
-    mix = hb_mixdown_get_short_name(hb_mixdown_get_from_name(str));
-    if (mix != NULL)
-        sval = ghb_string_value_new(mix);
-
-    return sval;
-}
-
-static GhbValue*
-export_value_video_encoder(GhbValue *lin_val)
-{
-    GhbValue *sval = NULL;
-    const gchar *str;
-    const gchar *enc;
-
-    str = ghb_value_get_string(lin_val);
-    enc = hb_video_encoder_get_short_name(hb_video_encoder_get_from_name(str));
-    if (enc != NULL)
-        sval = ghb_string_value_new(enc);
-
-    return sval;
-}
-
-static GhbValue*
-export_value_audio_encoder(GhbValue *lin_val)
-{
-    GhbValue *sval = NULL;
-    const gchar *str;
-    const gchar *enc;
-
-    str = ghb_value_get_string(lin_val);
-    enc = hb_audio_encoder_get_short_name(hb_audio_encoder_get_from_name(str));
-    if (enc != NULL)
-        sval = ghb_string_value_new(enc);
-
-    return sval;
-}
-
-static GhbValue*
-export_value_container(GhbValue *lin_val)
-{
-    GhbValue *sval = NULL;
-    const gchar *str;
-    const gchar *mux;
-
-    str = ghb_value_get_string(lin_val);
-    mux = hb_container_get_short_name(hb_container_get_from_name(str));
-    if (mux != NULL)
-        sval = ghb_string_value_new(mux);
-
-    return sval;
-}
-
-// Translate values for compatibility with other platforms
-static void
-export_value_xlat(GhbValue *dict)
-{
-    GhbValue *lin_val, *gval;
-    const gchar *key;
-
-    // Convert PictureModulus to correct data type
-    key = "PictureModulus";
-    lin_val = ghb_dict_get(dict, key);
-    gval = ghb_value_xform(lin_val, GHB_INT);
-    if (gval)
-        ghb_dict_set(dict, key, gval);
-    key = "VideoEncoder";
-    lin_val = ghb_dict_get(dict, key);
-    gval = export_value_video_encoder(lin_val);
-    if (gval)
-        ghb_dict_set(dict, key, gval);
-    key = "FileFormat";
-    lin_val = ghb_dict_get(dict, key);
-    gval = export_value_container(lin_val);
-    if (gval)
-        ghb_dict_set(dict, key, gval);
-    key = "VideoFramerate";
-    lin_val = ghb_dict_get(dict, key);
-    gval = export_value_video_framerate(lin_val);
-    if (gval)
-        ghb_dict_set(dict, key, gval);
-
-    gint count, ii;
-    GhbValue *alist;
-    GhbValue *adict;
-
-    key = "AudioEncoderFallback";
-    lin_val = ghb_dict_get(dict, key);
-    gval = export_value_audio_encoder(lin_val);
-    if (gval)
-        ghb_dict_set(dict, key, gval);
-
-    alist = ghb_dict_get(dict, "AudioList");
-    count = ghb_array_len(alist);
-    for (ii = 0; ii < count; ii++)
-    {
-        adict = ghb_array_get(alist, ii);
-        key = "AudioEncoder";
-        lin_val = ghb_dict_get(adict, key);
-        gval = export_value_audio_encoder(lin_val);
-        if (gval)
-            ghb_dict_set(adict, key, gval);
-        key = "AudioSamplerate";
-        lin_val = ghb_dict_get(adict, key);
-        gval = export_value_audio_samplerate(lin_val);
-        if (gval)
-            ghb_dict_set(adict, key, gval);
-        key = "AudioMixdown";
-        lin_val = ghb_dict_get(adict, key);
-        gval = export_value_mixdown(lin_val);
-        if (gval)
-            ghb_dict_set(adict, key, gval);
-    }
-}
-
-
-static GhbValue*
-import_value_xlat2(
-    GhbValue *defaults,
-    value_map_t *value_map,
-    const gchar *key,
-    GhbValue *mac_val)
-{
-    GhbValue *gval, *def_val;
-
-    if (mac_val == NULL) return NULL;
-    def_val = ghb_dict_get(defaults, key);
-    if (def_val)
-    {
-        gint ii;
-        gchar *str;
-        GhbValue *sval;
-
-        str = ghb_value_get_string_xform(mac_val);
-        for (ii = 0; value_map[ii].mac_val; ii++)
-        {
-            if (strcmp(str, value_map[ii].mac_val) == 0 ||
-                strcmp(str, value_map[ii].lin_val) == 0)
-            {
-                sval = ghb_string_value_new(value_map[ii].lin_val);
-                g_free(str);
-                gval = ghb_value_xform(sval, ghb_value_type(def_val));
-                if (gval == NULL)
-                {
-                    g_warning("can't transform");
-                    ghb_value_free(&sval);
-                    return NULL;
-                }
-                ghb_value_free(&sval);
-                return gval;
-            }
-        }
-        g_free(str);
-        return ghb_value_dup(def_val);
-    }
-    else
-    {
-        gint ii;
-        gchar *str;
-        GhbValue *sval;
-
-        str = ghb_value_get_string_xform(mac_val);
-        for (ii = 0; value_map[ii].mac_val; ii++)
-        {
-            if (strcmp(str, value_map[ii].mac_val) == 0 ||
-                strcmp(str, value_map[ii].lin_val) == 0)
-            {
-                sval = ghb_string_value_new(value_map[ii].lin_val);
-                g_free(str);
-                gval = ghb_value_xform(sval, ghb_value_type(mac_val));
-                if (gval == NULL)
-                {
-                    g_warning("can't transform");
-                    ghb_value_free(&sval);
-                    return NULL;
-                }
-                ghb_value_free(&sval);
-                return gval;
-            }
-        }
-        g_free(str);
-    }
-    return NULL;
-}
-
-static GhbValue*
-import_value_video_framerate(GhbValue *mac_val)
-{
-    GhbValue *sval = NULL;
-    gchar *str;
-    const gchar *fr;
-
-    str = ghb_value_get_string_xform(mac_val);
-    fr = hb_video_framerate_get_name(hb_video_framerate_get_from_name(str));
-    g_free(str);
-
-    if (fr != NULL)
-        sval = ghb_string_value_new(fr);
-
-    return sval;
-}
-
-static GhbValue*
-import_value_audio_samplerate(GhbValue *mac_val)
-{
-    GhbValue *sval = NULL;
-    gchar *str;
-    const gchar *sr;
-
-    str = ghb_value_get_string_xform(mac_val);
-    sr = hb_audio_samplerate_get_name(hb_audio_samplerate_get_from_name(str));
-    g_free(str);
-
-    if (sr != NULL)
-        sval = ghb_string_value_new(sr);
-
-    return sval;
-}
-
-static GhbValue*
-import_value_mixdown(GhbValue *mac_val)
-{
-    GhbValue *sval = NULL;
-    const gchar *str;
-    const gchar *mix;
-
-    str = ghb_value_get_string(mac_val);
-    mix = hb_mixdown_get_short_name(hb_mixdown_get_from_name(str));
-
-    if (mix != NULL)
-        sval = ghb_string_value_new(mix);
-
-    return sval;
-}
-
-static GhbValue*
-import_value_video_encoder(GhbValue *mac_val)
-{
-    GhbValue *sval = NULL;
-    const gchar *str;
-    const gchar *enc;
-
-    str = ghb_value_get_string(mac_val);
-    enc = hb_video_encoder_get_short_name(hb_video_encoder_get_from_name(str));
-
-    if (enc != NULL)
-        sval = ghb_string_value_new(enc);
-
-    return sval;
-}
-
-static GhbValue*
-import_value_audio_encoder(GhbValue *mac_val)
-{
-    GhbValue *sval = NULL;
-    const gchar *str;
-    const gchar *enc;
-
-    str = ghb_value_get_string(mac_val);
-    enc = hb_audio_encoder_get_short_name(hb_audio_encoder_get_from_name(str));
-
-    if (enc != NULL)
-        sval = ghb_string_value_new(enc);
-
-    return sval;
-}
-
-static GhbValue*
-import_value_container(GhbValue *mac_val)
-{
-    GhbValue *sval = NULL;
-    const gchar *str;
-    const gchar *mux;
-
-    str = ghb_value_get_string(mac_val);
-    mux = hb_container_get_short_name(hb_container_get_from_name(str));
-
-    if (mux != NULL)
-        sval = ghb_string_value_new(mux);
-
-    return sval;
-}
-
-static void
-import_value_xlat(GhbValue *dict)
-{
-    GhbValue *defaults, *mac_val, *gval;
-    const gchar *key;
-
-    GhbValue *internalPlist = ghb_resource_get("internal-defaults");
-    defaults = plist_get_dict(internalPlist, "Presets");
-    key = "VideoEncoder";
-    mac_val = ghb_dict_get(dict, key);
-    gval = import_value_video_encoder(mac_val);
-    if (gval)
-        ghb_dict_set(dict, key, gval);
-    key = "FileFormat";
-    mac_val = ghb_dict_get(dict, key);
-    gval = import_value_container(mac_val);
-    if (gval)
-        ghb_dict_set(dict, key, gval);
-    key = "VideoFramerate";
-    mac_val = ghb_dict_get(dict, key);
-    gval = import_value_video_framerate(mac_val);
-    if (gval)
-        ghb_dict_set(dict, key, gval);
-    key = "PictureDetelecine";
-    mac_val = ghb_dict_get(dict, key);
-    gval = import_value_xlat2(defaults, detel_xlat, key, mac_val);
-    if (gval)
-        ghb_dict_set(dict, key, gval);
-    key = "PictureDecomb";
-    mac_val = ghb_dict_get(dict, key);
-    gval = import_value_xlat2(defaults, decomb_xlat, key, mac_val);
-    if (gval)
-        ghb_dict_set(dict, key, gval);
-    key = "PictureDeinterlace";
-    mac_val = ghb_dict_get(dict, key);
-    gval = import_value_xlat2(defaults, deint_xlat, key, mac_val);
-    if (gval)
-        ghb_dict_set(dict, key, gval);
-    key = "PictureDenoisePreset";
-    mac_val = ghb_dict_get(dict, key);
-    gval = import_value_xlat2(defaults, denoise_xlat, key, mac_val);
-    if (gval)
-        ghb_dict_set(dict, key, gval);
-
-    ghb_dict_remove(dict, "Subtitles");
-    ghb_dict_remove(dict, "SubtitlesForced");
-
-    gint count, ii;
-    GhbValue *alist;
-    GhbValue *adict;
-    GhbValue *adefaults;
-    GhbValue *adeflist;
-
-    key = "AudioEncoderFallback";
-    mac_val = ghb_dict_get(dict, key);
-    gval = import_value_audio_encoder(mac_val);
-    if (gval)
-        ghb_dict_set(dict, key, gval);
-
-    adeflist = ghb_dict_get(defaults, "AudioList");
-    if (adeflist)
-    {
-        adefaults = ghb_array_get(adeflist, 0);
-        alist = ghb_dict_get(dict, "AudioList");
-        count = ghb_array_len(alist);
-        for (ii = 0; ii < count; ii++)
-        {
-            adict = ghb_array_get(alist, ii);
-            key = "AudioEncoder";
-            mac_val = ghb_dict_get(adict, key);
-            gval = import_value_audio_encoder(mac_val);
-            if (gval == NULL)
-                gval = ghb_value_dup(ghb_dict_get(adefaults, key));
-            if (gval)
-                ghb_dict_set(adict, key, gval);
-            key = "AudioSamplerate";
-            mac_val = ghb_dict_get(adict, key);
-            gval = import_value_audio_samplerate(mac_val);
-            if (gval == NULL)
-                gval = ghb_value_dup(ghb_dict_get(adefaults, key));
-            if (gval)
-                ghb_dict_set(adict, key, gval);
-            key = "AudioMixdown";
-            mac_val = ghb_dict_get(adict, key);
-            gval = import_value_mixdown(mac_val);
-            if (gval == NULL)
-                gval = ghb_value_dup(ghb_dict_get(adefaults, key));
-            if (gval)
-                ghb_dict_set(adict, key, gval);
-
-            mac_val = ghb_dict_get(adict, "AudioTrackDRCSlider");
-            if (mac_val != NULL)
-            {
-                gdouble drc;
-                drc = ghb_value_get_double(mac_val);
-                if (drc < 1.0)
-                {
-                    ghb_dict_set(adict, "AudioTrackDRCSlider",
-                                    ghb_double_value_new(0.0));
-                }
-            }
-        }
-    }
-}
-
-static GhbValue*
-import_xlat_preset(GhbValue *user_preset)
-{
-    GhbValue *dict, *internal;
-
-    g_debug("import_xlat_preset ()");
-
-    dict = ghb_dict_new();
-
-    // First, initialize the preset with defaults.
-    // Then import user presets over top of defaults
-    GhbValue *internalPlist = ghb_resource_get("internal-defaults");
-    internal = plist_get_dict(internalPlist, "Presets");
-    init_settings_from_dict(dict, internal, user_preset, FALSE);
-
-    // Initialize the AudioLanguageList from preferences PreferredLanguage
-    // and translate old AudioDUB preference option if found
-    GhbValue *list = ghb_dict_get(dict, "AudioLanguageList");
-    if (list == NULL)
-    {
-        list = ghb_array_new();
-        ghb_dict_set(dict, "AudioLanguageList", list);
-    }
-    if (ghb_array_len(list) == 0)
-    {
-        GhbValue *prefs = plist_get_dict(prefsPlist, "Preferences");
-        GhbValue *gdub = ghb_dict_get(prefs, "AudioDUB");
-        GhbValue *glang = ghb_dict_get(prefs, "PreferredLanguage");
-        const char *lang = NULL;
-        if (glang != NULL)
-        {
-            lang = ghb_value_get_string(glang);
-        }
-        if (gdub != NULL && !ghb_value_get_bool(gdub))
-        {
-            if (lang == NULL || strncmp(lang, "und", 4))
-            {
-                ghb_array_append(list, ghb_string_value_new("und"));
-            }
-        }
-        if (glang != NULL)
-        {
-            ghb_array_append(list, ghb_value_dup(glang));
-        }
-    }
-
-    // Initialize the SubtitleLanguageList from preferences PreferredLanguage
-    // and translate old AudioDUB preference option if found
-    list = ghb_dict_get(dict, "SubtitleLanguageList");
-    if (list == NULL)
-    {
-        list = ghb_array_new();
-        ghb_dict_set(dict, "SubtitleLanguageList", list);
-    }
-    if (ghb_array_len(list) == 0)
-    {
-        GhbValue *prefs = plist_get_dict(prefsPlist, "Preferences");
-        GhbValue *val = ghb_dict_get(prefs, "PreferredLanguage");
-        if (val != NULL)
-        {
-            ghb_array_append(list, ghb_value_dup(val));
-
-            val = ghb_dict_get(prefs, "AudioDUB");
-            if (val != NULL && !ghb_value_get_bool(val))
-            {
-                ghb_dict_set(dict,
-                                "SubtitleAddForeignAudioSubtitle",
-                                ghb_bool_value_new(TRUE));
-            }
-        }
-    }
-
-    GhbValue *addCC = ghb_dict_get(dict, "SubtitleAddCC");
-    if (addCC == NULL)
-    {
-        GhbValue *prefs = plist_get_dict(prefsPlist, "Preferences");
-        GhbValue *val = ghb_dict_get(prefs, "AddCC");
-        if (val != NULL)
-        {
-            ghb_dict_set(dict, "SubtitleAddCC",
-                            ghb_value_dup(val));
-        }
-    }
-
-    import_value_xlat(dict);
-
-    // Fix up all the internal settings that are derived from preset values.
-    ghb_dict_set_bool(dict, "PictureDeinterlaceDecomb",
-        !ghb_dict_get_bool(dict, "PictureDecombDeinterlace"));
-
-    ghb_dict_set(dict, "scale_height", ghb_value_dup(
-        ghb_dict_get_value(dict, "PictureHeight")));
-
-    ghb_dict_set(dict, "scale_width", ghb_value_dup(
-        ghb_dict_get_value(dict, "PictureWidth")));
-
-    gint uses_pic;
-    gint vqtype;
-
-    uses_pic = ghb_dict_get_int(dict, "UsesPictureSettings");
-    vqtype = ghb_dict_get_int(dict, "VideoQualityType");
-
-    // "Use max" or "strict anamorphic" imply autoscale
-    if (uses_pic == 2)
-    {
-        ghb_dict_set_bool(dict, "autoscale", TRUE);
-    }
-    else if (uses_pic == 1)
-    {
-        ghb_dict_set_bool(dict, "autoscale", FALSE);
-    }
-
-    // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
-    // *note: target is no longer used
-    switch (vqtype)
-    {
-    case 0:
-    {
-        ghb_dict_set_bool(dict, "vquality_type_bitrate", TRUE);
-        ghb_dict_set_bool(dict, "vquality_type_constant", FALSE);
-    } break;
-    case 1:
-    {
-        ghb_dict_set_bool(dict, "vquality_type_bitrate", TRUE);
-        ghb_dict_set_bool(dict, "vquality_type_constant", FALSE);
-    } break;
-    case 2:
-    {
-        ghb_dict_set_bool(dict, "vquality_type_bitrate", FALSE);
-        ghb_dict_set_bool(dict, "vquality_type_constant", TRUE);
-    } break;
-    default:
+                            4, description,
+                            5, type == PRESETS_BUILTIN ? 0 : 1,
+                            -1);
+        if (is_folder)
+        {
+            ghb_presets_list_init(ud, next_path);
+            if (ghb_dict_get_bool(dict, "FolderOpen"))
+            {
+                GtkTreePath *path;
+                path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);
+                gtk_tree_view_expand_to_path(treeview, path);
+                gtk_tree_path_free(path);
+            }
+        }
+    }
+    g_free(next_path);
+    if (path == NULL)
     {
-        ghb_dict_set_bool(dict, "vquality_type_bitrate", FALSE);
-        ghb_dict_set_bool(dict, "vquality_type_constant", TRUE);
-    } break;
+        ghb_presets_list_show_default(ud);
     }
+}
 
-    const gchar *mode = ghb_dict_get_string(dict, "VideoFramerateMode");
-    if (strcmp(mode, "cfr") == 0)
+static void
+presets_list_clear(signal_user_data_t *ud)
+{
+    GtkTreeView  *treeview;
+    GtkTreeModel *store;
+    GtkTreeIter   iter;
+    gboolean      valid;
+
+    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
+    store    = gtk_tree_view_get_model(treeview);
+    valid    = gtk_tree_model_get_iter_first(store, &iter);
+    while (valid)
     {
-        ghb_dict_set_bool(dict, "VideoFramerateCFR", TRUE);
-        ghb_dict_set_bool(dict, "VideoFrameratePFR", FALSE);
-        ghb_dict_set_bool(dict, "VideoFramerateVFR", FALSE);
+        gtk_tree_store_remove(GTK_TREE_STORE(store), &iter);
+        valid = gtk_tree_model_get_iter_first(store, &iter);
     }
-    else if (strcmp(mode, "pfr") == 0)
+}
+
+void
+ghb_presets_list_reinit(signal_user_data_t *ud)
+{
+    presets_list_clear(ud);
+    ghb_presets_list_init(ud, NULL);
+}
+
+static void
+presets_list_update_item(
+    signal_user_data_t       *ud,
+    const hb_preset_index_t  *path,
+    gboolean                  recurse)
+{
+    GhbValue     *dict;
+    GtkTreeView  *treeview;
+    GtkTreeStore *store;
+    GtkTreePath  *treepath;
+    GtkTreeIter   iter;
+    const gchar  *name;
+    const gchar  *description;
+    gint          type;
+    gboolean      is_folder;
+    gboolean      def;
+    const gchar  *color;
+
+    dict = hb_preset_get(path);
+    if (dict == NULL)
+        return;
+
+    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
+    store    = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
+    treepath = ghb_tree_path_new_from_index(path);
+    gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath);
+
+    // Additional settings, add row
+    name        = ghb_dict_get_string(dict, "PresetName");
+    description = ghb_dict_get_string(dict, "PresetDescription");
+    type        = ghb_dict_get_int(dict, "Type");
+    is_folder   = ghb_dict_get_bool(dict, "Folder");
+    def         = ghb_dict_get_bool(dict, "Default");
+    color       = get_preset_color(type, is_folder);
+
+    gtk_tree_store_set(store, &iter,
+                        0, name,
+                        1, def ? 800 : 400,
+                        2, def ? 2   : 0,
+                        3, color,
+                        4, description,
+                        5, type == PRESETS_BUILTIN ? 0 : 1,
+                        -1);
+    if (recurse && is_folder)
     {
-        ghb_dict_set_bool(dict, "VideoFramerateCFR", FALSE);
-        ghb_dict_set_bool(dict, "VideoFrameratePFR", TRUE);
-        ghb_dict_set_bool(dict, "VideoFramerateVFR", FALSE);
+        ghb_presets_list_init(ud, path);
     }
-    else
+}
+
+static void
+presets_list_append(signal_user_data_t *ud, const hb_preset_index_t *path)
+{
+    hb_preset_index_t *folder_path;
+    hb_value_t        *dict;
+    GtkTreeView       *treeview;
+    GtkTreeStore      *store;
+    GtkTreePath       *folder_treepath;
+    GtkTreeIter        iter, *piter;
+    const gchar       *name;
+    const gchar       *description;
+    gint               type;
+    gboolean           is_folder;
+    gboolean           def;
+    const gchar       *color;
+
+    folder_path = hb_preset_index_dup(path);
+    folder_path->depth--;
+
+    dict = hb_preset_get(path);
+    if (dict == NULL)
     {
-        ghb_dict_set_bool(dict, "VideoFramerateCFR", FALSE);
-        ghb_dict_set_bool(dict, "VideoFrameratePFR", FALSE);
-        ghb_dict_set_bool(dict, "VideoFramerateVFR", TRUE);
+        g_message("Ack! Desync between presets and preset list");
+        return;
     }
 
-    if (ghb_dict_get_bool(dict, "x264UseAdvancedOptions"))
+    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
+    store    = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
+
+    folder_treepath = ghb_tree_path_new_from_index(folder_path);
+    if (folder_treepath != NULL)
     {
-        // Force preset/tune/profile/level/opts to conform to option string
-        ghb_dict_set_string(dict, "VideoPreset", "medium");
-        ghb_dict_set_string(dict, "VideoTune", "none");
-        ghb_dict_set_string(dict, "VideoProfile", "auto");
-        ghb_dict_set_string(dict, "VideoLevel", "auto");
-        ghb_dict_set(dict, "VideoOptionExtra", ghb_value_dup(
-            ghb_dict_get_value(dict, "x264Option")));
+        GtkTreeIter tmp_iter;
+        gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &tmp_iter,
+                                folder_treepath);
+        piter = &tmp_iter;
+        gtk_tree_path_free(folder_treepath);
     }
     else
     {
-        ghb_dict_remove(dict, "x264Option");
+        piter = NULL;
     }
 
-    int encoder = ghb_get_video_encoder(dict);
-    const char * const *videoPresets;
-    videoPresets = hb_video_encoder_get_presets(encoder);
-    const char *videoPreset;
-    if (ghb_dict_get(user_preset, "x264Preset") != NULL)
-        videoPreset = ghb_dict_get_string(dict, "x264Preset");
-    else
-        videoPreset = ghb_dict_get_string(dict, "VideoPreset");
-    int ii;
-    for (ii = 0; videoPreset && videoPresets && videoPresets[ii]; ii++)
+    // Additional settings, add row
+    name        = ghb_dict_get_string(dict, "PresetName");
+    description = ghb_dict_get_string(dict, "PresetDescription");
+    type        = ghb_dict_get_int(dict, "Type");
+    is_folder   = ghb_dict_get_bool(dict, "Folder");
+    def         = ghb_dict_get_bool(dict, "Default");
+    color       = get_preset_color(type, is_folder);
+
+    gtk_tree_store_append(store, &iter, piter);
+    gtk_tree_store_set(store, &iter,
+                        0, name,
+                        1, def ? 800 : 400,
+                        2, def ? 2   : 0,
+                        3, color,
+                        4, description,
+                        5, type == PRESETS_BUILTIN ? 0 : 1,
+                        -1);
+    if (is_folder)
     {
-        if (!strcasecmp(videoPreset, videoPresets[ii]))
-        {
-            ghb_dict_set_int(dict, "VideoPresetSlider", ii);
-            break;
-        }
+        ghb_presets_list_init(ud, path);
     }
-    if (videoPreset != NULL)
-        ghb_dict_set_string(dict, "VideoPreset", videoPreset);
+}
 
-    char *videoTune;
-    if (ghb_dict_get(user_preset, "x264Tune") != NULL)
-        videoTune = g_strdup(ghb_dict_get_string(dict, "x264Tune"));
-    else
-        videoTune = g_strdup(ghb_dict_get_string(dict, "VideoTune"));
-    char *tune = NULL;
-    char *saveptr;
-    char * tok = strtok_r(videoTune, ",./-+", &saveptr);
-    ghb_dict_set_bool(dict, "x264FastDecode", FALSE);
-    ghb_dict_set_bool(dict, "x264ZeroLatency", FALSE);
-    while (tok != NULL)
-    {
-        if (!strcasecmp(tok, "fastdecode"))
-        {
-            ghb_dict_set_bool(dict, "x264FastDecode", TRUE);
-        }
-        else if (!strcasecmp(tok, "zerolatency"))
-        {
-            ghb_dict_set_bool(dict, "x264ZeroLatency", TRUE);
-        }
-        else if (tune == NULL)
-        {
-            tune = g_strdup(tok);
-        }
-        else
-        {
-            ghb_log("Superfluous tunes! %s", tok);
-        }
-        tok = strtok_r(NULL, ",./-+", &saveptr);
-    }
-    g_free(videoTune);
-    if (tune != NULL)
+static void
+presets_list_remove(signal_user_data_t *ud, hb_preset_index_t *path)
+{
+    GtkTreeView  *treeview;
+    GtkTreePath  *treepath;
+    GtkTreeIter   iter;
+    GtkTreeStore *store;
+
+    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
+    store    = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
+    treepath = ghb_tree_path_new_from_index(path);
+    if (treepath)
     {
-        ghb_dict_set_string(dict, "VideoTune", tune);
-        g_free(tune);
+        if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath))
+            gtk_tree_store_remove(store, &iter);
+        gtk_tree_path_free(treepath);
     }
+}
 
-    const char *videoProfile;
-    if (ghb_dict_get(user_preset, "x264Profile") != NULL)
-        videoProfile = ghb_dict_get_string(dict, "x264Profile");
-    else
-        videoProfile = ghb_dict_get_string(dict, "VideoProfile");
-    if (videoProfile != NULL)
-        ghb_dict_set_string(dict, "VideoProfile", videoProfile);
+void
+ghb_save_queue(GhbValue *queue)
+{
+    pid_t  pid;
+    char  *name;
 
-    const char *videoLevel;
-    if (ghb_dict_get(user_preset, "x264Level") != NULL)
-        videoLevel = ghb_dict_get_string(dict, "x264Level");
-    else
-        videoLevel = ghb_dict_get_string(dict, "VideoLevel");
-    if (videoLevel != NULL)
-        ghb_dict_set_string(dict, "VideoLevel", videoLevel);
+    pid  = getpid();
+    name = g_strdup_printf ("queue.%d", pid);
+    write_config_file(name, queue);
+    g_free(name);
+}
 
-    if (ghb_dict_get(user_preset, "x264OptionExtra") != NULL)
-    {
-        const char *optionExtra;
-        optionExtra = ghb_dict_get_string(dict, "x264OptionExtra");
-        ghb_dict_set_string(dict, "VideoOptionExtra", optionExtra);
-    }
+GhbValue*
+ghb_load_old_queue(int pid)
+{
+    GhbValue *queue;
+    char     *name;
 
-    return dict;
+    name  = g_strdup_printf ("queue.%d", pid);
+    queue = read_config_file(name);
+    g_free(name);
+    return queue;
 }
 
-static void
-import_xlat_presets(GhbValue *presets)
+void
+ghb_remove_old_queue_file(int pid)
 {
-    gint count, ii;
-    GhbValue *dict;
-    gboolean folder;
-
-    g_debug("import_xlat_presets ()");
-    if (presets == NULL) return;
-    count = ghb_array_len(presets);
-    for (ii = 0; ii < count; ii++)
-    {
-        dict = ghb_array_get(presets, ii);
-        folder = ghb_value_get_bool(ghb_dict_get(dict, "Folder"));
-        if (folder)
-        {
-            GhbValue *nested;
+    char *name;
 
-            nested = ghb_dict_get(dict, "ChildrenArray");
-            import_xlat_presets(nested);
-        }
-        else
-        {
-            GhbValue *import_dict = import_xlat_preset(dict);
-            ghb_array_replace(presets, ii, import_dict);
-        }
-    }
+    name = g_strdup_printf ("queue.%d", pid);
+    remove_config_file(name);
+    g_free(name);
 }
 
 // Translate internal values to preset key, value pairs
-static void
-export_xlat_preset(GhbValue *dict)
+static GhbValue*
+settings_to_preset(GhbValue *settings)
 {
+    GhbValue *preset = ghb_value_dup(settings);
+
     gboolean autoscale, br, constant;
 
-    g_debug("export_xlat_prest ()");
-    autoscale = ghb_value_get_bool(ghb_dict_get(dict, "autoscale"));
-    br = ghb_value_get_bool(
-                ghb_dict_get(dict, "vquality_type_bitrate"));
-    constant = ghb_value_get_bool(
-                ghb_dict_get(dict, "vquality_type_constant"));
+    ghb_dict_set_bool(preset, "Default", 0);
+    ghb_dict_set_int(preset, "Type", PRESETS_CUSTOM);
+    if (!ghb_dict_get_bool(preset, "PictureWidthEnable"))
+    {
+        ghb_dict_remove(preset, "PictureWidth");
+    }
+    if (!ghb_dict_get_bool(preset, "PictureHeightEnable"))
+    {
+        ghb_dict_remove(preset, "PictureHeight");
+    }
+    autoscale = !ghb_dict_get_bool(preset, "PictureWidthEnable") &&
+                !ghb_dict_get_bool(preset, "PictureHeightEnable");
 
+    br = ghb_dict_get_bool(preset, "vquality_type_bitrate");
+    constant = ghb_dict_get_bool(preset, "vquality_type_constant");
     if (autoscale)
     {
-        ghb_dict_set(dict, "UsesPictureSettings", ghb_int_value_new(2));
+        ghb_dict_set_int(preset, "UsesPictureSettings", 2);
     }
     else
     {
-        ghb_dict_set(dict, "UsesPictureSettings", ghb_int_value_new(1));
+        ghb_dict_set_int(preset, "UsesPictureSettings", 1);
     }
 
     // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
     // *note: target is no longer used
     if (br)
     {
-        ghb_dict_set(dict, "VideoQualityType", ghb_int_value_new(1));
+        ghb_dict_set_int(preset, "VideoQualityType", 1);
     }
     else if (constant)
     {
-        ghb_dict_set(dict, "VideoQualityType", ghb_int_value_new(2));
+        ghb_dict_set_int(preset, "VideoQualityType", 2);
     }
 
-    if (ghb_value_get_bool(ghb_dict_get(dict, "VideoFramerateCFR")))
+    if (ghb_dict_get_bool(preset, "VideoFramerateCFR"))
     {
-        ghb_dict_set(dict, "VideoFramerateMode", ghb_string_value_new("cfr"));
+        ghb_dict_set_string(preset, "VideoFramerateMode", "cfr");
     }
-    else if (ghb_value_get_bool(ghb_dict_get(dict, "VideoFrameratePFR")))
+    else if (ghb_dict_get_bool(preset, "VideoFrameratePFR"))
     {
-        ghb_dict_set(dict, "VideoFramerateMode", ghb_string_value_new("pfr"));
+        ghb_dict_set_string(preset, "VideoFramerateMode", "pfr");
     }
     else
     {
-        ghb_dict_set(dict, "VideoFramerateMode", ghb_string_value_new("vfr"));
+        ghb_dict_set_string(preset, "VideoFramerateMode", "vfr");
     }
 
-    if (ghb_value_get_int(ghb_dict_get(dict, "PictureDeblock")) < 5)
+    if (ghb_dict_get_int(preset, "PictureDeblock") < 5)
     {
-        ghb_dict_set(dict, "PictureDeblock", ghb_int_value_new(0));
+        ghb_dict_set_int(preset, "PictureDeblock", 0);
     }
 
     GhbValue *alist, *adict;
     gint count, ii;
 
-    alist = ghb_dict_get(dict, "AudioList");
+    alist = ghb_dict_get(preset, "AudioList");
     count = ghb_array_len(alist);
     for (ii = 0; ii < count; ii++)
     {
         gdouble drc;
 
         adict = ghb_array_get(alist, ii);
-        drc = ghb_value_get_double(
-                ghb_dict_get(adict, "AudioTrackDRCSlider"));
+        drc = ghb_dict_get_double(adict, "AudioTrackDRCSlider");
         if (drc < 1.0)
         {
-            ghb_dict_set(adict, "AudioTrackDRCSlider",
-                            ghb_double_value_new(0.0));
+            ghb_dict_set_double(adict, "AudioTrackDRCSlider", 0.0);
         }
     }
 
     GhbValue *copy_mask = ghb_array_new();
-    if (ghb_value_get_bool(ghb_dict_get(dict, "AudioAllowMP3Pass")))
+    if (ghb_dict_get_bool(preset, "AudioAllowMP3Pass"))
     {
         ghb_array_append(copy_mask, ghb_string_value_new("copy:mp3"));
     }
-    if (ghb_value_get_bool(ghb_dict_get(dict, "AudioAllowAACPass")))
+    if (ghb_dict_get_bool(preset, "AudioAllowAACPass"))
     {
         ghb_array_append(copy_mask, ghb_string_value_new("copy:aac"));
     }
-    if (ghb_value_get_bool(ghb_dict_get(dict, "AudioAllowAC3Pass")))
+    if (ghb_dict_get_bool(preset, "AudioAllowAC3Pass"))
     {
         ghb_array_append(copy_mask, ghb_string_value_new("copy:ac3"));
     }
-    if (ghb_value_get_bool(ghb_dict_get(dict, "AudioAllowDTSPass")))
+    if (ghb_dict_get_bool(preset, "AudioAllowDTSPass"))
     {
         ghb_array_append(copy_mask, ghb_string_value_new("copy:dts"));
     }
-    if (ghb_value_get_bool(ghb_dict_get(dict, "AudioAllowDTSHDPass")))
+    if (ghb_dict_get_bool(preset, "AudioAllowDTSHDPass"))
     {
         ghb_array_append(copy_mask, ghb_string_value_new("copy:dtshd"));
     }
-    if (ghb_value_get_bool(ghb_dict_get(dict, "AudioAllowEAC3Pass")))
+    if (ghb_dict_get_bool(preset, "AudioAllowEAC3Pass"))
     {
         ghb_array_append(copy_mask, ghb_string_value_new("copy:eac3"));
     }
-    if (ghb_value_get_bool(ghb_dict_get(dict, "AudioAllowFLACPass")))
+    if (ghb_dict_get_bool(preset, "AudioAllowFLACPass"))
     {
         ghb_array_append(copy_mask, ghb_string_value_new("copy:flac"));
     }
-    if (ghb_value_get_bool(ghb_dict_get(dict, "AudioAllowTRUEHDPass")))
+    if (ghb_dict_get_bool(preset, "AudioAllowTRUEHDPass"))
     {
         ghb_array_append(copy_mask, ghb_string_value_new("copy:truehd"));
     }
-    ghb_dict_set(dict, "AudioCopyMask", copy_mask);
+    ghb_dict_set(preset, "AudioCopyMask", copy_mask);
 
-    if (ghb_value_get_bool(ghb_dict_get(dict, "x264UseAdvancedOptions")))
+    if (ghb_dict_get_bool(preset, "x264UseAdvancedOptions"))
     {
-        ghb_dict_remove(dict, "VideoPreset");
-        ghb_dict_remove(dict, "VideoTune");
-        ghb_dict_remove(dict, "VideoProfile");
-        ghb_dict_remove(dict, "VideoLevel");
-        ghb_dict_remove(dict, "VideoOptionExtra");
+        ghb_dict_remove(preset, "VideoPreset");
+        ghb_dict_remove(preset, "VideoTune");
+        ghb_dict_remove(preset, "VideoProfile");
+        ghb_dict_remove(preset, "VideoLevel");
+        ghb_dict_remove(preset, "VideoOptionExtra");
     }
-    const char *tune = ghb_value_get_string(ghb_dict_get(dict, "VideoTune"));
+    const char *tune = ghb_dict_get_string(preset, "VideoTune");
     if (tune != NULL)
     {
         GString *str = g_string_new("");
         char *tunes;
 
         g_string_append_printf(str, "%s", tune);
-        if (ghb_value_get_bool(ghb_dict_get(dict, "x264FastDecode")))
+        if (ghb_dict_get_bool(preset, "x264FastDecode"))
         {
             g_string_append_printf(str, ",%s", "fastdecode");
         }
-        if (ghb_value_get_bool(ghb_dict_get(dict, "x264ZeroLatency")))
+        if (ghb_dict_get_bool(preset, "x264ZeroLatency"))
         {
             g_string_append_printf(str, ",%s", "zerolatency");
         }
         tunes = g_string_free(str, FALSE);
-        ghb_dict_set(dict, "VideoTune", ghb_string_value_new(tunes));
+        ghb_dict_set_string(preset, "VideoTune", tunes);
 
         g_free(tunes);
     }
 
-    // Remove everything from dist that isn't in "Presets"
-    GhbValue *internal;
-    GhbValue *internalPlist = ghb_resource_get("internal-defaults");
-    internal = plist_get_dict(internalPlist, "Presets");
-    dict_clean(dict, internal);
-
-    export_value_xlat(dict);
-}
-
-static void export_xlat_presets(GhbValue *presets);
-
-static void
-export_xlat_dict(GhbValue *dict)
-{
-    gboolean folder;
-    folder = ghb_value_get_bool(ghb_dict_get(dict, "Folder"));
-    if (folder)
-    {
-        GhbValue *nested;
-
-        nested = ghb_dict_get(dict, "ChildrenArray");
-        export_xlat_presets(nested);
-    }
-    else
-    {
-        export_xlat_preset(dict);
-    }
-}
+    GhbValue *in_val, *out_val;
 
-static void
-export_xlat_presets(GhbValue *presets)
-{
-    gint count, ii;
-    GhbValue *dict;
+    // Convert PictureModulus to correct data type
+    in_val = ghb_dict_get(preset, "PictureModulus");
+    out_val = ghb_value_xform(in_val, GHB_INT);
+    if (out_val != NULL)
+        ghb_dict_set(preset, "PictureModulus", out_val);
 
-    if (presets == NULL) return;
-    if (ghb_value_type(presets) == GHB_DICT)
-    {
-        export_xlat_dict(presets);
-    }
-    else if (ghb_value_type(presets) == GHB_ARRAY)
-    {
-        count = ghb_array_len(presets);
-        for (ii = 0; ii < count; ii++)
-        {
-            dict = ghb_array_get(presets, ii);
-            export_xlat_dict(dict);
-        }
-    }
-    else
-    {
-        g_warning("export_xlat_presets: Invalid presets format");
-    }
+    return preset;
 }
 
 static guint prefs_timeout_id = 0;
@@ -2878,7 +1475,7 @@ static guint prefs_timeout_id = 0;
 static gboolean
 delayed_store_prefs(gpointer data)
 {
-    write_config_file("preferences", prefsPlist);
+    write_config_file("preferences", prefsDict);
     prefs_timeout_id = 0;
     return FALSE;
 }
@@ -2886,12 +1483,15 @@ delayed_store_prefs(gpointer data)
 static void
 store_presets()
 {
-    GhbValue *export;
+    gchar      *config, *path;
+    hb_value_t *presets;
 
-    export = ghb_value_dup(presetsPlist);
-    export_xlat_presets(export);
-    store_plist("presets", export);
-    ghb_value_free(&export);
+    config  = ghb_get_user_config_dir(NULL);
+    path    = g_strdup_printf ("%s/%s", config, "presets.json");
+    presets = hb_presets_get();
+    hb_presets_write_json(presets, path);
+    g_free(config);
+    g_free(path);
 }
 
 static void
@@ -2910,439 +1510,151 @@ store_prefs(void)
     prefs_timeout_id = g_timeout_add_seconds(1, (GSourceFunc)delayed_store_prefs, NULL);
 }
 
-void
-ghb_presets_reload(signal_user_data_t *ud)
-{
-    GhbValue *std_presets;
-    gint count, ii;
-    int *indices, len;
-
-    g_debug("ghb_presets_reload()\n");
-    std_presets = ghb_value_dup(ghb_resource_get("standard-presets"));
-    if (std_presets == NULL) return;
-
-    remove_std_presets(ud);
-    indices = presets_find_default(presetsPlist, &len);
-    if (indices)
-    {
-        presets_clear_default(std_presets);
-        g_free(indices);
-    }
-    // Merge the keyfile contents into our presets
-    count = ghb_array_len(std_presets);
-    for (ii = count-1; ii >= 0; ii--)
-    {
-        GhbValue *std_dict;
-        GhbValue *copy_dict;
-        gint indices = 0;
-
-        std_dict = ghb_array_get(std_presets, ii);
-        copy_dict = ghb_value_dup(std_dict);
-        ghb_presets_insert(presetsPlist, copy_dict, &indices, 1);
-        presets_list_insert(ud, &indices, 1);
-    }
-    import_xlat_presets(presetsPlist);
-    store_presets();
-    ghb_value_free(&std_presets);
-}
-
-static gboolean
-check_old_presets(GhbValue *presetsArray)
-{
-    gint count, ii;
-
-    count = ghb_array_len(presetsArray);
-    for (ii = count-1; ii >= 0; ii--)
-    {
-        GhbValue *dict;
-        GhbValue *type;
-
-        dict = ghb_array_get(presetsArray, ii);
-        type = ghb_dict_get(dict, "Type");
-        if (type == NULL)
-            return TRUE;
-    }
-    return FALSE;
-}
-
-static void
-replace_standard_presets(GhbValue *presetsArray)
-{
-    GhbValue *std_presets, *tmp;
-    int *indices, len;
-    gint count, ii;
-
-    // Remove existing standard presets
-    count = ghb_array_len(presetsArray);
-    for (ii = count-1; ii >= 0; ii--)
-    {
-        GhbValue *dict;
-        gint ptype;
-
-        dict = ghb_array_get(presetsArray, ii);
-        ptype = ghb_value_get_int(ghb_dict_get(dict, "Type"));
-        if (ptype == PRESETS_BUILTIN)
-        {
-            gint indices = 0;
-            ghb_presets_remove(presetsArray, &indices, 1);
-        }
-    }
-
-    // Get the default standard presets
-    tmp = ghb_resource_get("standard-presets");
-    if (tmp == NULL) return;
-    std_presets = ghb_value_dup(tmp);
-
-    // Clear the default in the standard presets if one is already set
-    // in custom presets
-    indices = presets_find_default(presetsArray, &len);
-    if (indices)
-    {
-        presets_clear_default(std_presets);
-        g_free(indices);
-    }
-
-    // Merge the keyfile contents into our presets
-    count = ghb_array_len(std_presets);
-    for (ii = count-1; ii >= 0; ii--)
-    {
-        GhbValue *std_dict;
-        GhbValue *copy_dict;
-        gint indices = 0;
-
-        std_dict = ghb_array_get(std_presets, ii);
-        copy_dict = ghb_value_dup(std_dict);
-        ghb_presets_insert(presetsArray, copy_dict, &indices, 1);
-    }
-    ghb_value_free(&std_presets);
-}
-
-static int
-update_standard_presets(signal_user_data_t *ud, GhbValue *presetsArray)
-{
-    gint count, ii;
-
-    count = ghb_array_len(presetsArray);
-    for (ii = count-1; ii >= 0; ii--)
-    {
-        GhbValue *dict;
-        const GhbValue *gval;
-        gint type;
-
-        dict = ghb_array_get(presetsArray, ii);
-        gval = ghb_dict_get(dict, "Type");
-        if (gval == NULL)
-        {
-            // Old preset that doesn't have a Type
-            replace_standard_presets(presetsArray);
-            return 1;
-        }
-
-        type = ghb_value_get_int(gval);
-        if (type == 0)
-        {
-            // TODO: check preset version
-#if 0
-            gint64 build;
-
-            gval = ghb_dict_get(dict, "PresetBuildNumber");
-            if (gval == NULL)
-            {
-                // Old preset that doesn't have a build number
-                replace_standard_presets(presetsArray);
-                return 1;
-            }
-
-            build = ghb_value_get_int(gval);
-            if (build != hb_get_build(NULL))
-            {
-                // Build number does not match
-                replace_standard_presets(presetsArray);
-                return 1;
-            }
-#endif
-        }
-    }
-    return 0;
-}
-
 void
 ghb_presets_load(signal_user_data_t *ud)
 {
-    gboolean store = FALSE;
-    presetsPlistFile = read_config_file("presets");
-    if ((presetsPlistFile == NULL) ||
-        (ghb_value_type(presetsPlistFile) == GHB_DICT) ||
-        (check_old_presets(presetsPlistFile)))
-    {
-        presetsPlistFile = ghb_resource_get("standard-presets");
-        store = TRUE;
-    }
-    else
+    if (presets_add_config_file("presets.json") < 0)
     {
-        update_standard_presets(ud, presetsPlistFile);
+        if (presets_add_config_file("presets") < 0)
+        {
+            g_warning("Failed to read preset file");
+        }
     }
-    presetsPlist = ghb_value_dup(presetsPlistFile);
-    import_xlat_presets(presetsPlist);
-    if (store)
-        store_presets();
-
 }
 
 static void
-settings_save(signal_user_data_t *ud, const GhbValue *path)
+settings_save(signal_user_data_t *ud, hb_preset_index_t *path, const char *name)
 {
     GhbValue *dict;
-    gint *indices, len, count;
-    const gchar *name;
-    gboolean replace = FALSE;
-
-    g_debug("settings_save");
-    GhbValue *internalPlist = ghb_resource_get("internal-defaults");
-    if (internalPlist == NULL) return;
-    count = ghb_array_len(path);
-    name = ghb_value_get_string(ghb_array_get(path, count-1));
-    indices = ghb_preset_indices_from_path(presetsPlist, path, &len);
-    if (indices)
-    {
-        if (ghb_presets_get_folder(presetsPlist, indices, len))
-        {
-            GtkWindow *hb_window;
-            gchar *message;
-            hb_window = GTK_WINDOW(GHB_WIDGET(ud->builder, "hb_window"));
-            message = g_strdup_printf(
-                      _("%s: Folder already exists.\n"
-                        "You can not replace it with a preset."),
-                        name);
-            ghb_message_dialog(hb_window, GTK_MESSAGE_ERROR,
-                               message, _("Cancel"), NULL);
-            g_free(message);
-            return;
-        }
-        dict = ghb_value_dup(ud->settings);
-        ghb_presets_replace(presetsPlist, dict, indices, len);
-        replace = TRUE;
-    }
-    else
+    gboolean  replace = FALSE;
+
+    dict = hb_preset_get(path);
+    if (dict != NULL)
     {
-        indices = presets_find_pos(path, PRESETS_CUSTOM, &len);
-        if (indices)
+        gboolean    is_folder;
+        int         type;
+        const char *s;
+
+        is_folder = ghb_dict_get_bool(dict, "Folder");
+        type      = ghb_dict_get_int(dict, "Type");
+        s         = ghb_dict_get_string(dict, "PresetName");
+        if (s == NULL || strcmp(s, name) || type != PRESETS_CUSTOM || is_folder)
         {
-            dict = ghb_value_dup(ud->settings);
-            ghb_presets_insert(presetsPlist, dict, indices, len);
+            // Name changed or original preset was builtin or original
+            // was a folder. Don't replace it.
+            replace = FALSE;
+            path->depth--;
+            if (type != PRESETS_CUSTOM)
+            {
+                // Don't put new custom presets in a builtin folder
+                path->depth = 1;
+            }
         }
         else
         {
-            g_warning("failed to find insert path");
-            return;
+            replace = TRUE;
         }
     }
-    current_preset = dict;
-    ghb_dict_set_int(dict, "Type", PRESETS_CUSTOM);
-
-    ghb_dict_set(dict, "PresetName", ghb_string_value_new(name));
+    dict = settings_to_preset(ud->settings);
+    ghb_dict_set_string(dict, "PresetName", name);
     if (replace)
     {
-        gint *def_indices, def_len;
-        def_indices = presets_find_default(presetsPlist, &def_len);
-        if (def_indices != NULL &&
-            preset_path_cmp(indices, len, def_indices, def_len) != 0)
+        // Already exists, update its description
+        if (hb_preset_set(path, dict) >= 0)
         {
-            ghb_dict_set(dict, "Default", ghb_bool_value_new(FALSE));
+            presets_list_update_item(ud, path, FALSE);
         }
-        presets_list_update_item(ud, indices, len, FALSE);
-        g_free(def_indices);
     }
     else
     {
-        ghb_dict_set(dict, "Default", ghb_bool_value_new(FALSE));
-        presets_list_insert(ud, indices, len);
-    }
-    if (!ghb_dict_get_bool(ud->settings, "PictureWidthEnable"))
-    {
-        ghb_dict_remove(dict, "PictureWidth");
-    }
-    if (!ghb_dict_get_bool(ud->settings, "PictureHeightEnable"))
-    {
-        ghb_dict_remove(dict, "PictureHeight");
+        // Append to the folder list the source came from
+        int index = hb_preset_append(path, dict);
+        if (index >= 0)
+        {
+            path->index[path->depth++] = index;
+            presets_list_append(ud, path);
+        }
     }
-    ghb_dict_set(dict, "autoscale",
-        ghb_bool_value_new(
-            !ghb_dict_get_bool(ud->settings, "PictureWidthEnable") &&
-            !ghb_dict_get_bool(ud->settings, "PictureHeightEnable")
-        )
-    );
-
+    ghb_value_free(&dict);
     store_presets();
 
     ud->dont_clear_presets = TRUE;
     // Make the new preset the selected item
-    ghb_select_preset2(ud->builder, indices, len);
-    g_free(indices);
+    select_preset2(ud->builder, path);
     ud->dont_clear_presets = FALSE;
     return;
 }
 
 static void
-folder_save(signal_user_data_t *ud, const GhbValue *path)
+folder_save(signal_user_data_t *ud, hb_preset_index_t *path, const char *name)
 {
-    GhbValue *dict, *folder;
-    gint *indices, len, count;
-    const gchar *name;
-
-    count = ghb_array_len(path);
-    name = ghb_value_get_string(ghb_array_get(path, count-1));
-    indices = ghb_preset_indices_from_path(presetsPlist, path, &len);
-    if (indices)
+    GhbValue *dict;
+
+    dict = hb_preset_get(path);
+    if (dict != NULL)
     {
-        if (!ghb_presets_get_folder(presetsPlist, indices, len))
+        gboolean    is_folder;
+        int         type;
+        const char *s;
+
+        is_folder = ghb_dict_get_bool(dict, "Folder");
+        type      = ghb_dict_get_int(dict, "Type");
+        s         = ghb_dict_get_string(dict, "PresetName");
+        if (s == NULL || strcmp(s, name) || type != PRESETS_CUSTOM || !is_folder)
         {
-            GtkWindow *hb_window;
-            gchar *message;
-            hb_window = GTK_WINDOW(GHB_WIDGET(ud->builder, "hb_window"));
-            message = g_strdup_printf(
-                      _("%s: Preset already exists.\n"
-                        "You can not replace it with a folder."),
-                        name);
-            ghb_message_dialog(hb_window, GTK_MESSAGE_ERROR,
-                               message, _("Cancel"), NULL);
-            g_free(message);
-            g_free(indices);
-            return;
+            // Name changed or original preset was builtin or original
+            // was a not a folder. Don't replace it.
+            dict = NULL;
+            path->depth--;
+            if (type != PRESETS_CUSTOM)
+            {
+                // Don't put new custom presets in a builtin folder
+                path->depth = 1;
+            }
         }
+    }
+    if (dict != NULL)
+    {
         // Already exists, update its description
-        dict = presets_get_dict(presetsPlist, indices, len);
+        dict = hb_preset_get(path);
         ghb_dict_set(dict, "PresetDescription",
-            ghb_value_dup(ghb_dict_get(
-                ud->settings, "PresetDescription")));
-        presets_list_update_item(ud, indices, len, FALSE);
-        g_free(indices);
-        store_presets();
-        return;
+            ghb_value_dup(ghb_dict_get(ud->settings, "PresetDescription")));
+        presets_list_update_item(ud, path, FALSE);
     }
     else
     {
-        indices = presets_find_pos(path, PRESETS_CUSTOM, &len);
-        if (indices)
-        {
-            dict = ghb_dict_new();
-            ghb_presets_insert(presetsPlist, dict, indices, len);
-        }
-        else
+        dict = ghb_dict_new();
+        ghb_dict_set(dict, "PresetDescription",
+            ghb_value_dup(ghb_dict_get(ud->settings, "PresetDescription")));
+        ghb_dict_set_string(dict, "PresetName", name);
+        ghb_dict_set(dict, "ChildrenArray", ghb_array_new());
+        ghb_dict_set_int(dict, "Type", PRESETS_CUSTOM);
+        ghb_dict_set_bool(dict, "Folder", TRUE);
+        int index = hb_preset_append(path, dict);
+        if (index >= 0)
         {
-            g_warning("failed to find insert path");
-            return;
+            path->index[path->depth++] = index;
+            presets_list_append(ud, path);
         }
+        ghb_value_free(&dict);
     }
-    ghb_dict_set(dict, "PresetDescription",
-        ghb_value_dup(ghb_dict_get(
-            ud->settings, "PresetDescription")));
-    ghb_dict_set(dict, "PresetName", ghb_string_value_new(name));
-    folder = ghb_array_new();
-    ghb_dict_set(dict, "ChildrenArray", folder);
-    ghb_dict_set(dict, "Type", ghb_int_value_new(PRESETS_CUSTOM));
-    ghb_dict_set(dict, "Folder", ghb_bool_value_new(TRUE));
-
-    presets_list_insert(ud, indices, len);
-    g_free(indices);
     store_presets();
-    return;
-}
-
-void
-ghb_presets_list_show_default(signal_user_data_t *ud)
-{
-    GtkTreeView *treeview;
-    GtkTreePath *treepath;
-    GtkTreeIter iter;
-    GtkTreeStore *store;
-    gint *indices, len;
-
-    g_debug("ghb_presets_list_show_default()");
-    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
-    store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
-    indices = presets_find_default(presetsPlist, &len);
-    if (indices == NULL) return;
-    treepath = ghb_tree_path_new_from_indices(indices, len);
-    if (treepath)
-    {
-        if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath))
-        {
-            gtk_tree_store_set(store, &iter,
-                        1, 800,
-                        2, 2 ,
-                        -1);
-        }
-        gtk_tree_path_free(treepath);
-    }
-    g_free(indices);
-}
 
-void
-ghb_presets_list_clear_default(signal_user_data_t *ud)
-{
-    GtkTreeView *treeview;
-    GtkTreePath *treepath;
-    GtkTreeIter iter;
-    GtkTreeStore *store;
-    gint *indices, len;
-
-    g_debug("ghb_presets_list_clear_default ()");
-    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
-    store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
-    indices = presets_find_default(presetsPlist, &len);
-    if (indices == NULL) return;
-    treepath = ghb_tree_path_new_from_indices(indices, len);
-    if (treepath)
-    {
-        if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath))
-        {
-            gtk_tree_store_set(store, &iter,
-                        1, 400,
-                        2, 0 ,
-                        -1);
-        }
-        gtk_tree_path_free(treepath);
-    }
-    g_free(indices);
-}
-
-static void
-update_subtitle_presets(signal_user_data_t *ud)
-{
-    g_debug("update_subtitle_presets");
-    const GhbValue *subtitle_list, *subtitle;
-    GhbValue *slist, *dict;
-    gint count, ii, source;
-
-    subtitle_list = ghb_dict_get_value(ud->settings, "subtitle_list");
-    slist = ghb_array_new();
-    count = ghb_array_len(subtitle_list);
-    for (ii = 0; ii < count; ii++)
-    {
-        subtitle = ghb_array_get(subtitle_list, ii);
-        source = ghb_dict_get_int(subtitle, "SubtitleSource");
-        if (source != SRTSUB)
-        {
-            dict = ghb_value_dup(subtitle);
-            ghb_array_append(slist, dict);
-        }
-    }
-    ghb_dict_set(ud->settings, "SubtitleList", slist);
+    return;
 }
 
 G_MODULE_EXPORT void
 preset_import_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
 {
-    GtkWidget *dialog;
-    GtkResponseType response;
-    const gchar *exportDir;
-    gchar *filename;
-    GtkFileFilter *filter;
-
-    g_debug("preset_import_clicked_cb ()");
+    GtkWindow       *hb_window;
+    GtkWidget       *dialog;
+    GtkResponseType  response;
+    const gchar     *exportDir;
+    gchar           *filename;
+    GtkFileFilter   *filter;
 
-    dialog = gtk_file_chooser_dialog_new("Import Preset", NULL,
+    hb_window = GTK_WINDOW(GHB_WIDGET(ud->builder, "hb_window"));
+    dialog = gtk_file_chooser_dialog_new("Import Preset", hb_window,
                 GTK_FILE_CHOOSER_ACTION_OPEN,
                 GHB_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                 GHB_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
@@ -3354,11 +1666,16 @@ preset_import_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
     gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
 
     filter = gtk_file_filter_new();
-    gtk_file_filter_set_name(filter, _("Presets (*.plist)"));
-    gtk_file_filter_add_pattern(filter, "*.plist");
+    gtk_file_filter_set_name(filter, _("Presets (*.json)"));
+    gtk_file_filter_add_pattern(filter, "*.json");
     gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
     gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
 
+    filter = gtk_file_filter_new();
+    gtk_file_filter_set_name(filter, _("Legacy Presets (*.plist)"));
+    gtk_file_filter_add_pattern(filter, "*.plist");
+    gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
+
     exportDir = ghb_dict_get_string(ud->prefs, "ExportDirectory");
     if (exportDir == NULL || exportDir[0] == '\0')
     {
@@ -3370,62 +1687,18 @@ preset_import_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
     gtk_widget_hide(dialog);
     if (response == GTK_RESPONSE_ACCEPT)
     {
-        GhbValue *dict, *array;
-        gchar  *dir;
-        gint count, ii;
+        gchar    *dir;
+        int       index;
 
         filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
-
-        // import the preset
         if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
         {
             gtk_widget_destroy(dialog);
             g_free(filename);
             return;
         }
-        array = ghb_read_settings_file(filename);
-
-        import_xlat_presets(array);
-        presets_clear_default(array);
-        presets_customize(array);
-
-        count = ghb_array_len(array);
-        for (ii = 0; ii < count; ii++)
-        {
-            GhbValue *path, *name;
-            gint *indices, len;
-            gint index = 1;
-
-            dict = ghb_array_get(array, ii);
-            path = ghb_array_new();
-            name = ghb_value_dup(ghb_dict_get(dict, "PresetName"));
-            ghb_array_append(path, name);
-            indices = ghb_preset_indices_from_path(presetsPlist, path, &len);
-            // Modify the preset name till we make it unique
-            while (indices != NULL)
-            {
-                const gchar *tmp = ghb_value_get_string(name);
-
-                ghb_value_free(&path);
-                g_free(indices);
-
-                char *str = g_strdup_printf("%s %d", tmp, index);
-                path = ghb_array_new();
-                name = ghb_string_value_new(str);
-                ghb_array_append(path, name);
-                g_free(str);
-
-                index++;
-                indices = ghb_preset_indices_from_path(presetsPlist, path, &len);
-            }
-            ghb_dict_set(dict, "PresetName", ghb_value_dup(name));
-            indices = presets_find_pos(path, PRESETS_CUSTOM, &len);
-            ghb_presets_insert(presetsPlist, ghb_value_dup(dict), indices, len);
-            presets_list_insert(ud, indices, len);
-            ghb_value_free(&path);
-            g_free(indices);
-        }
-        ghb_value_free(&array);
+        // import the preset
+        index = hb_presets_add_path(filename);
 
         exportDir = ghb_dict_get_string(ud->prefs, "ExportDirectory");
         dir = g_path_get_dirname(filename);
@@ -3437,32 +1710,37 @@ preset_import_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
         g_free(filename);
         g_free(dir);
         store_presets();
+
+        // Re-init the UI preset list
+        ghb_presets_list_reinit(ud);
+        if (index < 0)
+        {
+            ghb_select_default_preset(ud->builder);
+        }
+        else
+        {
+            hb_preset_index_t path;
+            path.index[0] = index;
+            path.depth = 1;
+            select_preset2(ud->builder, &path);
+        }
     }
     gtk_widget_destroy(dialog);
 }
 
-GhbValue*
+hb_preset_index_t *
 get_selected_path(signal_user_data_t *ud)
 {
-    GtkTreeView *treeview;
+    GtkTreeView      *treeview;
     GtkTreeSelection *selection;
-    GtkTreeModel *store;
-    GtkTreeIter iter;
+    GtkTreeModel     *store;
+    GtkTreeIter       iter;
 
-    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
+    treeview  = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
     selection = gtk_tree_view_get_selection(treeview);
     if (gtk_tree_selection_get_selected(selection, &store, &iter))
     {
-        GtkTreePath *treepath;
-        gint *indices, len;
-        GhbValue *path;
-
-        treepath = gtk_tree_model_get_path(store, &iter);
-        indices = gtk_tree_path_get_indices(treepath);
-        len = gtk_tree_path_get_depth(treepath);
-
-        path = preset_path_from_indices(presetsPlist, indices, len);
-        return path;
+        return ghb_tree_get_index(store, &iter);
     }
     return NULL;
 }
@@ -3470,29 +1748,31 @@ get_selected_path(signal_user_data_t *ud)
 G_MODULE_EXPORT void
 preset_export_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
 {
-    GtkWidget *dialog;
-    GtkResponseType response;
-    GhbValue *preset;
-    const gchar *name = "";
-    gint count, *indices, len;
-    const gchar *exportDir;
-    gchar *filename;
-
-    g_debug("preset_export_clicked_cb ()");
-    preset = get_selected_path(ud);
-    if (preset == NULL)
-        return;
+    hb_preset_index_t *path;
+    const gchar       *name;
+    GtkWindow         *hb_window;
+    GtkWidget         *dialog;
+    GtkResponseType    response;
+    const gchar       *exportDir;
+    gchar             *filename;
 
-    count = ghb_array_len(preset);
-    if (count <= 0)
+    path = get_selected_path(ud);
+    if (path == NULL || path->depth <= 0)
     {
-        ghb_value_free(&preset);
+        free(path);
         return;
     }
 
-    name = ghb_value_get_string(ghb_array_get(preset, count-1));
+    GhbValue *dict = hb_preset_get(path);
+    free(path);
+    if (dict == NULL)
+    {
+        return;
+    }
+    name = ghb_dict_get_string(dict, "PresetName");
 
-    dialog = gtk_file_chooser_dialog_new(_("Export Preset"), NULL,
+    hb_window = GTK_WINDOW(GHB_WIDGET(ud->builder, "hb_window"));
+    dialog = gtk_file_chooser_dialog_new(_("Export Preset"), hb_window,
                 GTK_FILE_CHOOSER_ACTION_SAVE,
                 GHB_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                 GHB_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
@@ -3508,30 +1788,16 @@ preset_export_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
     gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename);
     g_free(filename);
 
-    indices = ghb_preset_indices_from_path(presetsPlist, preset, &len);
-    if (indices == NULL)
-    {
-        ghb_value_free(&preset);
-        return;
-    }
-
     response = gtk_dialog_run(GTK_DIALOG(dialog));
     gtk_widget_hide(dialog);
     if (response == GTK_RESPONSE_ACCEPT)
     {
-        GhbValue *export, *dict;
-        gchar  *dir;
+        gchar    *dir;
 
         filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
 
         // export the preset
-        dict = presets_get_dict(presetsPlist, indices, len);
-
-        export = ghb_value_dup(dict);
-        export_xlat_presets(export);
-        hb_preset_write_json(export, filename);
-        ghb_value_free(&export);
-
+        hb_presets_write_json(dict, filename);
         exportDir = ghb_dict_get_string(ud->prefs, "ExportDirectory");
         dir = g_path_get_dirname(filename);
         if (strcmp(dir, exportDir) != 0)
@@ -3543,42 +1809,27 @@ preset_export_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
         g_free(filename);
     }
     gtk_widget_destroy(dialog);
-    g_free(indices);
-    ghb_value_free(&preset);
 }
 
 G_MODULE_EXPORT void
 presets_new_folder_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
 {
-    GtkWidget *dialog;
-    GtkEntry *entry;
-    GtkTextView *desc;
-    GtkResponseType response;
-    GhbValue *preset, *dict;
-    const gchar *name = "";
-    const gchar *description = "";
-    gint count, *indices, len;
-
-    g_debug("presets_new_folder_clicked_cb ()");
-    preset = get_selected_path(ud);
-    count = ghb_array_len(preset);
-    if (count > 0)
-        name = ghb_value_get_string(ghb_array_get(preset, count-1));
-    else
-        count = 1;
+    GtkWidget         *dialog;
+    GtkEntry          *entry;
+    GtkTextView       *desc;
+    GtkResponseType    response;
+    hb_preset_index_t *path;
+    const gchar       *name;
+    const gchar       *description;
 
-    indices = ghb_preset_indices_from_path(presetsPlist, preset, &len);
-    dict = presets_get_dict(presetsPlist, indices, len);
-    if (dict != NULL)
-    {
-        description = ghb_value_get_string(
-                            ghb_dict_get(dict, "PresetDescription"));
-        ghb_ui_update(ud, "FolderDescription", ghb_string_value(description));
-    }
+    path        = get_selected_path(ud);
+    name        = ghb_dict_get_string(ud->settings, "PresetName");
+    description = ghb_dict_get_string(ud->settings, "PresetDescription");
+    ghb_ui_update(ud, "FolderDescription", ghb_string_value(description));
 
-    desc = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "FolderDescription"));
+    desc   = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "FolderDescription"));
     dialog = GHB_WIDGET(ud->builder, "preset_new_folder_dialog");
-    entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "FolderName"));
+    entry  = GTK_ENTRY(GHB_WIDGET(ud->builder, "FolderName"));
     gtk_entry_set_text(entry, name);
     response = gtk_dialog_run(GTK_DIALOG(dialog));
     gtk_widget_hide(dialog);
@@ -3586,60 +1837,37 @@ presets_new_folder_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
     {
         // save the preset
         const gchar *name = gtk_entry_get_text(entry);
-        GhbValue *dest;
-
-        if (count > MAX_NESTED_PRESET-1)
-            count = MAX_NESTED_PRESET-1;
-
-        dest = ghb_array_new();
-        if (indices != NULL)
-        {
-            gint ptype;
-
-            ptype = ghb_presets_get_type(presetsPlist, indices, len);
-            if (ptype == PRESETS_CUSTOM)
-            {
-                ghb_array_copy(dest, preset, count-1);
-            }
-        }
-        ghb_array_append(dest, ghb_string_value_new(name));
-        GhbValue *val = ghb_widget_value(GTK_WIDGET(desc));
+        GhbValue *val     = ghb_widget_value(GTK_WIDGET(desc));
         ghb_dict_set(ud->settings, "PresetDescription", ghb_value_dup(val));
-        folder_save(ud, dest);
-        ghb_value_free(&dest);
+        folder_save(ud, path, name);
     }
-    g_free(indices);
-    ghb_value_free(&preset);
+    free(path);
 }
 
 G_MODULE_EXPORT void
 presets_save_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
 {
-    GtkWidget *dialog;
-    GtkEntry *entry;
-    GtkTextView *desc;
-    GtkResponseType response;
-    GhbValue *preset;
-    const gchar *name = "";
-    gint count, *indices, len;
-
-    g_debug("presets_save_clicked_cb ()");
-    preset = get_selected_path(ud);
-    if (preset == NULL)
-        preset = ghb_value_dup(ghb_dict_get_value(ud->settings, "preset"));
-
-    count = ghb_array_len(preset);
-    if (count > 0)
-        name = ghb_value_get_string(ghb_array_get(preset, count-1));
-    else
-        count = 1;
+    const gchar       *name;
+    const gchar       *fullname;
+    hb_preset_index_t *path;
+    int                width, height;
+    gboolean           autoscale;
+    GtkWidget         *dialog;
+    GtkEntry          *entry;
+    GtkTextView       *desc;
+    GtkResponseType    response;
+
+    name      = ghb_dict_get_string(ud->settings, "PresetName");
+    fullname  = ghb_dict_get_string(ud->settings, "PresetFullName");
+    width     = ghb_dict_get_int(ud->settings, "PictureWidth");
+    height    = ghb_dict_get_int(ud->settings, "PictureHeight");
+    autoscale = ghb_dict_get_bool(ud->settings, "autoscale");
 
-    desc = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "PresetDescription"));
-    int width = ghb_dict_get_int(ud->settings, "PictureWidth");
-    int height = ghb_dict_get_int(ud->settings, "PictureHeight");
-    gboolean autoscale = ghb_dict_get_bool(ud->settings, "autoscale");
     ghb_ui_update(ud, "PictureWidthEnable", ghb_boolean_value(!autoscale));
     ghb_ui_update(ud, "PictureHeightEnable", ghb_boolean_value(!autoscale));
+
+    path     = hb_preset_search_index(fullname, 0);
+    desc     = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "PresetDescription"));
     if (!width)
     {
         width = ghb_dict_get_int(ud->settings, "scale_width");
@@ -3650,39 +1878,20 @@ presets_save_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
         height = ghb_dict_get_int(ud->settings, "scale_height");
         ghb_ui_update(ud, "PictureHeight", ghb_int_value(height));
     }
-    dialog = GHB_WIDGET(ud->builder, "preset_save_dialog");
-    entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "PresetName"));
+
+    dialog   = GHB_WIDGET(ud->builder, "preset_save_dialog");
+    entry    = GTK_ENTRY(GHB_WIDGET(ud->builder, "PresetName"));
     gtk_entry_set_text(entry, name);
     response = gtk_dialog_run(GTK_DIALOG(dialog));
     gtk_widget_hide(dialog);
     if (response == GTK_RESPONSE_OK)
     {
         // save the preset
-        const gchar *name = gtk_entry_get_text(entry);
-        GhbValue *dest;
-
-        dest = ghb_array_new();
-        indices = ghb_preset_indices_from_path(presetsPlist, preset, &len);
-        if (indices)
-        {
-            gint ptype;
-
-            ptype = ghb_presets_get_type(presetsPlist, indices, len);
-            if (ptype == PRESETS_CUSTOM)
-            {
-                ghb_array_copy(dest, preset, count-1);
-            }
-            g_free(indices);
-        }
-        ghb_array_append(dest, ghb_string_value_new(name));
-
+        name = gtk_entry_get_text(entry);
         ghb_widget_to_setting(ud->settings, GTK_WIDGET(desc));
-
-        update_subtitle_presets(ud);
-        settings_save(ud, dest);
-        ghb_value_free(&dest);
+        settings_save(ud, path, name);
     }
-    ghb_value_free(&preset);
+    free(path);
 }
 
 G_MODULE_EXPORT void
@@ -3694,86 +1903,83 @@ preset_type_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
 G_MODULE_EXPORT void
 presets_restore_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
 {
-    GhbValue *preset;
-
-    g_debug("presets_restore_clicked_cb ()");
-    // Reload only the standard presets
-    ghb_presets_reload(ud);
-    // Updating the presets list shuffles things around
-    // need to make sure the proper preset is selected
-    preset = ghb_dict_get_value(ud->settings, "preset");
-    ghb_select_preset(ud->builder, preset);
+    // Reload the builtin presets
+    hb_presets_builtin_update();
+    store_presets();
+
+    ghb_presets_list_reinit(ud);
+    ghb_select_default_preset(ud->builder);
 }
 
 G_MODULE_EXPORT void
 presets_remove_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
 {
-    GtkTreeView *treeview;
+    GtkTreeView      *treeview;
     GtkTreeSelection *selection;
-    GtkTreeModel *store;
-    GtkTreeIter iter;
-    gchar *preset;
-    GtkResponseType response;
+    GtkTreeModel     *store;
+    GtkTreeIter       iter;
+    gchar            *preset;
+    GtkResponseType   response;
 
-    g_debug("presets_remove_clicked_cb ()");
-    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
+    treeview  = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
     selection = gtk_tree_view_get_selection (treeview);
     if (gtk_tree_selection_get_selected(selection, &store, &iter))
     {
-        GtkWindow *hb_window;
-        GtkWidget *dialog;
-        GtkTreePath *path;
-        gint *indices, len;
-        gboolean folder;
+        GtkWindow         *hb_window;
+        GtkWidget         *dialog;
+        gboolean           is_folder;
+        hb_preset_index_t *path;
 
         gtk_tree_model_get(store, &iter, 0, &preset, -1);
-        path = gtk_tree_model_get_path(store, &iter);
-        indices = gtk_tree_path_get_indices(path);
-        len = gtk_tree_path_get_depth(path);
 
-        folder = ghb_presets_get_folder(presetsPlist, indices, len);
+        path      = ghb_tree_get_index(store, &iter);
+        is_folder = preset_is_folder(path);
         hb_window = GTK_WINDOW(GHB_WIDGET(ud->builder, "hb_window"));
         dialog = gtk_message_dialog_new(hb_window, GTK_DIALOG_MODAL,
                             GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
                             _("Confirm deletion of %s:\n\n%s"),
-                            folder ? _("folder") : _("preset"),
+                            is_folder ? _("folder") : _("preset"),
                             preset);
         response = gtk_dialog_run(GTK_DIALOG(dialog));
         gtk_widget_destroy (dialog);
         if (response == GTK_RESPONSE_YES)
         {
             GtkTreeIter nextIter = iter;
-            gboolean valid = TRUE;
+            gboolean    valid    = TRUE;
+
+            // Determine which preset to highlight after deletion done
             if (!gtk_tree_model_iter_next(store, &nextIter))
             {
-                if (!gtk_tree_model_iter_parent(store, &nextIter, &iter))
+                nextIter = iter;
+                if (!gtk_tree_model_iter_previous(store, &nextIter))
                 {
-                    valid = FALSE;
+                    nextIter = iter;
+                    if (!gtk_tree_model_iter_parent(store, &nextIter, &iter))
+                    {
+                        nextIter = iter;
+                        valid = gtk_tree_model_get_iter_first(store, &nextIter);
+                    }
                 }
             }
+
             // Remove the selected item
             // First unselect it so that selecting the new item works properly
-            gtk_tree_selection_unselect_iter (selection, &iter);
-            if (ghb_presets_remove(presetsPlist, indices, len))
+            gtk_tree_selection_unselect_iter(selection, &iter);
+            if (hb_preset_delete(path) >= 0)
             {
                 store_presets();
-                presets_list_remove(ud, indices, len);
+                presets_list_remove(ud, path);
             }
-            if (!valid)
-                valid = gtk_tree_model_get_iter_first(store, &nextIter);
             if (valid)
             {
-                GtkTreePath *path;
-                gint *indices;
+                hb_preset_index_t *path;
 
-                path = gtk_tree_model_get_path(store, &nextIter);
-                indices = gtk_tree_path_get_indices(path);
-                len = gtk_tree_path_get_depth(path);
-                ghb_select_preset2(ud->builder, indices, len);
-                gtk_tree_path_free(path);
+                path = ghb_tree_get_index(store, &nextIter);
+                select_preset2(ud->builder, path);
+                free(path);
             }
         }
-        gtk_tree_path_free(path);
+        free(path);
         g_free(preset);
     }
 }
@@ -3781,52 +1987,55 @@ presets_remove_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
 // controls where valid drop locations are
 G_MODULE_EXPORT gboolean
 presets_drag_motion_cb(
-    GtkTreeView *tv,
-    GdkDragContext *ctx,
-    gint x,
-    gint y,
-    guint time,
+    GtkTreeView        *tv,
+    GdkDragContext     *ctx,
+    gint                x,
+    gint                y,
+    guint               time,
     signal_user_data_t *ud)
 {
-    GtkTreePath *path = NULL;
-    GtkTreeViewDropPosition drop_pos;
-    gint *indices, len;
-    GtkTreeIter iter;
-    GtkTreeView *srctv;
-    GtkTreeModel *model;
-    GtkTreeSelection *select;
-    gint src_ptype, dst_ptype;
-    gboolean src_folder, dst_folder;
-    GhbValue *preset;
-    gint tree_depth, ii;
-    GtkWidget *widget;
+    GtkTreeViewDropPosition  drop_pos;
+    GtkTreeIter              iter;
+    GtkTreeView             *srctv;
+    GtkTreeModel            *model;
+    GtkTreeSelection        *select;
+    GtkTreePath             *treepath;
+    hb_preset_index_t       *path;
+    gint                     src_ptype, dst_ptype;
+    gboolean                 src_folder, dst_folder;
+    GhbValue                *src_preset, *dst_preset;
+    gint                     tree_depth, ii;
+    GtkWidget               *widget;
 
     widget = gtk_drag_get_source_widget(ctx);
     if (widget == NULL || widget != GTK_WIDGET(tv))
         return TRUE;
 
     // Get the type of the object being dragged
-    srctv = GTK_TREE_VIEW(gtk_drag_get_source_widget(ctx));
-    select = gtk_tree_view_get_selection (srctv);
+    srctv  = GTK_TREE_VIEW(gtk_drag_get_source_widget(ctx));
+    select = gtk_tree_view_get_selection(srctv);
     gtk_tree_selection_get_selected (select, &model, &iter);
-    path = gtk_tree_model_get_path (model, &iter);
-    indices = gtk_tree_path_get_indices(path);
-    len = gtk_tree_path_get_depth(path);
+    path   = ghb_tree_get_index(model, &iter);
 
-    preset = presets_get_dict(presetsPlist, indices, len);
-    tree_depth = preset_tree_depth(preset);
+    src_preset = hb_preset_get(path);
+    free(path);
+    if (src_preset == NULL)
+    {
+        gdk_drag_status(ctx, 0, time);
+        return TRUE;
+    }
 
-    src_ptype = ghb_presets_get_type(presetsPlist, indices, len);
-    src_folder = ghb_presets_get_folder(presetsPlist, indices, len);
-    gtk_tree_path_free(path);
+    tree_depth = preset_tree_depth(src_preset);
+    src_ptype  = ghb_dict_get_int(src_preset, "Type");
+    src_folder = ghb_dict_get_bool(src_preset, "Folder");
 
     if (src_folder && tree_depth == 1)
         tree_depth = 2;
 
     // The rest checks that the destination is a valid position
     // in the list.
-    gtk_tree_view_get_dest_row_at_pos (tv, x, y, &path, &drop_pos);
-    if (path == NULL)
+    gtk_tree_view_get_dest_row_at_pos(tv, x, y, &treepath, &drop_pos);
+    if (treepath == NULL)
     {
         gdk_drag_status(ctx, 0, time);
         return TRUE;
@@ -3838,7 +2047,7 @@ presets_drag_motion_cb(
         return TRUE;
     }
 
-    len = gtk_tree_path_get_depth(path);
+    int len = gtk_tree_path_get_depth(treepath);
     if (len+tree_depth-1 >= MAX_NESTED_PRESET)
     {
         if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
@@ -3847,11 +2056,21 @@ presets_drag_motion_cb(
             drop_pos = GTK_TREE_VIEW_DROP_AFTER;
     }
     for (ii = len+tree_depth-1; ii > MAX_NESTED_PRESET; ii--)
-        gtk_tree_path_up(path);
-    indices = gtk_tree_path_get_indices(path);
-    len = gtk_tree_path_get_depth(path);
-    dst_ptype = ghb_presets_get_type(presetsPlist, indices, len);
-    dst_folder = ghb_presets_get_folder(presetsPlist, indices, len);
+        gtk_tree_path_up(treepath);
+    path = ghb_tree_path_get_index(treepath);
+
+    dst_preset = hb_preset_get(path);
+    free(path);
+    if (dst_preset != NULL)
+    {
+        dst_ptype = ghb_dict_get_int(dst_preset, "Type");
+        dst_folder = ghb_dict_get_bool(dst_preset, "Folder");
+    }
+    else
+    {
+        dst_ptype = PRESETS_CUSTOM;
+        dst_folder = FALSE;
+    }
 
     // Don't allow mixing custom presets in the builtins
     if (dst_ptype != PRESETS_CUSTOM)
@@ -3869,179 +2088,188 @@ presets_drag_motion_cb(
             drop_pos = GTK_TREE_VIEW_DROP_AFTER;
     }
 
-    len = gtk_tree_path_get_depth(path);
-    gtk_tree_view_set_drag_dest_row(tv, path, drop_pos);
-    gtk_tree_path_free(path);
+    len = gtk_tree_path_get_depth(treepath);
+    gtk_tree_view_set_drag_dest_row(tv, treepath, drop_pos);
+    gtk_tree_path_free(treepath);
     gdk_drag_status(ctx, GDK_ACTION_MOVE, time);
     return TRUE;
 }
 
 G_MODULE_EXPORT void
 presets_drag_cb(
-    GtkTreeView *dstwidget,
-    GdkDragContext *dc,
-    gint x, gint y,
-    GtkSelectionData *selection_data,
-    guint info, guint t,
+    GtkTreeView        *dst_widget,
+    GdkDragContext     *dc,
+    gint                x,
+    gint                y,
+    GtkSelectionData   *selection_data,
+    guint               info,
+    guint               t,
     signal_user_data_t *ud)
 {
-    GtkTreePath *path = NULL;
-    GtkTreeViewDropPosition drop_pos;
-    GtkTreeIter dstiter, srciter;
-    gint *dst_indices, dst_len, *src_indices, src_len;
-    gint src_ptype;
-    gboolean src_folder, dst_folder;
+    GtkTreePath             *dst_treepath = NULL;
+    GtkTreeViewDropPosition  drop_pos;
+    GtkTreeIter              dst_iter, src_iter;
+    gint                     src_ptype;
+    gboolean                 src_folder, dst_folder;
 
-    GtkTreeModel *dstmodel = gtk_tree_view_get_model(dstwidget);
+    GtkTreeModel *dst_model = gtk_tree_view_get_model(dst_widget);
 
-    g_debug("preset_drag_cb ()");
     // This doesn't work here for some reason...
     // gtk_tree_view_get_drag_dest_row(dstwidget, &path, &drop_pos);
-    gtk_tree_view_get_dest_row_at_pos (dstwidget, x, y, &path, &drop_pos);
+    gtk_tree_view_get_dest_row_at_pos(dst_widget, x, y,
+                                      &dst_treepath, &drop_pos);
     // This little hack is needed because attempting to drop after
-    // the last item gives us no path or drop_pos.
-    if (path == NULL)
+    // the last item gives us no dst_treepath or drop_pos.
+    if (dst_treepath == NULL)
     {
         gint n_children;
 
-        n_children = gtk_tree_model_iter_n_children(dstmodel, NULL);
+        n_children = gtk_tree_model_iter_n_children(dst_model, NULL);
         if (n_children)
         {
             drop_pos = GTK_TREE_VIEW_DROP_AFTER;
-            path = gtk_tree_path_new_from_indices(n_children-1, -1);
+            dst_treepath = gtk_tree_path_new_from_indices(n_children-1, -1);
         }
         else
         {
             drop_pos = GTK_TREE_VIEW_DROP_BEFORE;
-            path = gtk_tree_path_new_from_indices(0, -1);
+            dst_treepath = gtk_tree_path_new_from_indices(0, -1);
         }
     }
-    if (path)
+    if (dst_treepath)
     {
-        GtkTreeView *srcwidget;
-        GtkTreeModel *srcmodel;
-        GtkTreeSelection *select;
-        GtkTreePath *srcpath = NULL;
-        GhbValue *preset;
-        gint tree_depth, ii;
-
-        srcwidget = GTK_TREE_VIEW(gtk_drag_get_source_widget(dc));
-        select = gtk_tree_view_get_selection (srcwidget);
-        gtk_tree_selection_get_selected (select, &srcmodel, &srciter);
-
-        srcpath = gtk_tree_model_get_path (srcmodel, &srciter);
-        src_indices = gtk_tree_path_get_indices(srcpath);
-        src_len = gtk_tree_path_get_depth(srcpath);
-        src_ptype = ghb_presets_get_type(presetsPlist, src_indices, src_len);
-        src_folder = ghb_presets_get_folder(presetsPlist, src_indices, src_len);
-        preset = ghb_value_dup(
-                    presets_get_dict(presetsPlist, src_indices, src_len));
-        gtk_tree_path_free(srcpath);
+        GtkTreeView       *src_widget;
+        GtkTreeModel      *src_model;
+        GtkTreeSelection  *select;
+        gint               tree_depth, ii;
+        hb_preset_index_t *dst_path, *src_path;
+        hb_value_t        *src_preset;
+
+        src_widget = GTK_TREE_VIEW(gtk_drag_get_source_widget(dc));
+        select     = gtk_tree_view_get_selection (src_widget);
+        gtk_tree_selection_get_selected(select, &src_model, &src_iter);
+
+        src_path   = ghb_tree_get_index(src_model, &src_iter);
+        src_ptype  = preset_get_type(src_path);
+        src_folder = preset_is_folder(src_path);
 
         // Don't allow repositioning of builtin presets
         if (src_ptype != PRESETS_CUSTOM)
+        {
+            free(src_path);
             return;
+        }
 
-        tree_depth = preset_tree_depth(preset);
+        src_preset = hb_preset_get(src_path);
+        tree_depth = preset_tree_depth(src_preset);
         if (src_folder && tree_depth == 1)
             tree_depth = 2;
 
-        dst_len = gtk_tree_path_get_depth(path);
-        if (dst_len+tree_depth-1 >= MAX_NESTED_PRESET)
+        dst_path = ghb_tree_path_get_index(dst_treepath);
+        if (dst_path->depth + tree_depth - 1 >= MAX_NESTED_PRESET)
         {
             if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
                 drop_pos = GTK_TREE_VIEW_DROP_BEFORE;
-            if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
+            else if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
                 drop_pos = GTK_TREE_VIEW_DROP_AFTER;
         }
 
-        for (ii = dst_len+tree_depth-1; ii > MAX_NESTED_PRESET; ii--)
-            gtk_tree_path_up(path);
-        dst_indices = gtk_tree_path_get_indices(path);
-        dst_len = gtk_tree_path_get_depth(path);
-        dst_folder = ghb_presets_get_folder(presetsPlist, dst_indices, dst_len);
+        for (ii = dst_path->depth + tree_depth-1; ii > MAX_NESTED_PRESET; ii--)
+        {
+            gtk_tree_path_up(dst_treepath);
+            dst_path->depth--;
+        }
+
+        dst_folder = preset_is_folder(dst_path);
 
         // Only allow *drop into* for folders
         if (!dst_folder)
         {
             if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
                 drop_pos = GTK_TREE_VIEW_DROP_BEFORE;
-            if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
+            else if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
                 drop_pos = GTK_TREE_VIEW_DROP_AFTER;
         }
-        if (gtk_tree_model_get_iter (dstmodel, &dstiter, path))
+        free(dst_path);
+        if (gtk_tree_model_get_iter(dst_model, &dst_iter, dst_treepath))
         {
             GtkTreeIter iter;
-            GtkTreePath *dstpath = NULL;
 
+            // Insert new empty row in UI preset list
+            // This logic determines the final position of the preset,
+            // i.e. before, after or inside the target entry.
+            // So the dst_path to move the preset to must be computed
+            // after moving the entry in the UI list
             switch (drop_pos)
             {
                 case GTK_TREE_VIEW_DROP_BEFORE:
-                    gtk_tree_store_insert_before(GTK_TREE_STORE (dstmodel),
-                                                &iter, NULL, &dstiter);
+                    gtk_tree_store_insert_before(GTK_TREE_STORE(dst_model),
+                                                &iter, NULL, &dst_iter);
                     break;
 
                 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
-                    gtk_tree_store_insert(GTK_TREE_STORE (dstmodel),
-                                                &iter, &dstiter, 0);
+                    gtk_tree_store_insert(GTK_TREE_STORE(dst_model),
+                                                &iter, &dst_iter, 0);
                     break;
 
                 case GTK_TREE_VIEW_DROP_AFTER:
-                    gtk_tree_store_insert_after(GTK_TREE_STORE (dstmodel),
-                                                &iter, NULL, &dstiter);
+                    gtk_tree_store_insert_after(GTK_TREE_STORE(dst_model),
+                                                &iter, NULL, &dst_iter);
                     break;
 
                 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
-                    gtk_tree_store_insert_after(GTK_TREE_STORE (dstmodel),
-                                                &iter, &dstiter, 0);
+                    gtk_tree_store_insert_after(GTK_TREE_STORE(dst_model),
+                                                &iter, &dst_iter, NULL);
                     break;
 
                 default:
                     break;
             }
 
-            dstpath = gtk_tree_model_get_path (dstmodel, &iter);
-            dst_indices = gtk_tree_path_get_indices(dstpath);
-            dst_len = gtk_tree_path_get_depth(dstpath);
-            ghb_presets_insert(presetsPlist, preset, dst_indices, dst_len);
-            gtk_tree_path_free(dstpath);
-
-            srcpath = gtk_tree_model_get_path (srcmodel, &srciter);
-            src_indices = gtk_tree_path_get_indices(srcpath);
-            src_len = gtk_tree_path_get_depth(srcpath);
-            ghb_presets_remove(presetsPlist, src_indices, src_len);
-            gtk_tree_path_free(srcpath);
+            // Move source preset at the desired location
+            dst_path = ghb_tree_get_index(dst_model, &iter);
+            hb_preset_move(src_path, dst_path);
+            free(dst_path);
 
-            gtk_tree_store_remove (GTK_TREE_STORE (srcmodel), &srciter);
+            // Remove the old entry in the UI list
+            gtk_tree_store_remove(GTK_TREE_STORE(src_model), &src_iter);
 
-            dstpath = gtk_tree_model_get_path (dstmodel, &iter);
-            dst_indices = gtk_tree_path_get_indices(dstpath);
-            dst_len = gtk_tree_path_get_depth(dstpath);
-            presets_list_update_item(ud, dst_indices, dst_len, TRUE);
-            gtk_tree_path_free(dstpath);
+            // UI elements were shuffled again.  recompute dst_path
+            dst_path = ghb_tree_get_index(dst_model, &iter);
+            presets_list_update_item(ud, dst_path, TRUE);
+            select_preset2(ud->builder, dst_path);
+            free(dst_path);
 
             store_presets();
         }
-        gtk_tree_path_free(path);
+        gtk_tree_path_free(dst_treepath);
+        free(src_path);
     }
 }
 
 void
 presets_row_expanded_cb(
-    GtkTreeView *treeview,
-    GtkTreeIter *iter,
-    GtkTreePath *path,
+    GtkTreeView        *treeview,
+    GtkTreeIter        *iter,
+    GtkTreePath        *treepath,
     signal_user_data_t *ud)
 {
-    gint *indices, len;
-    gboolean expanded, folder;
-    GhbValue *dict;
+    hb_preset_index_t *path;
+    gboolean           expanded;
+    GhbValue          *dict;
 
-    expanded = gtk_tree_view_row_expanded(treeview, path);
-    indices = gtk_tree_path_get_indices(path);
-    len = gtk_tree_path_get_depth(path);
-    dict = presets_get_dict(presetsPlist, indices, len);
-    if (preset_folder_is_open(dict))
+    expanded = gtk_tree_view_row_expanded(treeview, treepath);
+    path     = ghb_tree_path_get_index(treepath);
+    dict     = hb_preset_get(path);
+    free(path);
+
+    // Sanity check
+    if (!ghb_dict_get_bool(dict, "Folder"))
+    {
+        g_warning("presets_row_expand_cb: Desync between presets and list");
+        return;
+    }
+    if (ghb_dict_get_bool(dict, "FolderOpen"))
     {
         if (expanded)
         {
@@ -4052,118 +2280,96 @@ presets_row_expanded_cb(
     {
         return;
     }
-    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)
-    {
-        GhbValue *presets = NULL;
-        gint *more_indices, count, ii;
+    ghb_dict_set_bool(dict, "FolderOpen", expanded);
+    store_presets();
+}
 
-        more_indices = g_malloc((len+1)*sizeof(gint));
-        memcpy(more_indices, indices, len*sizeof(gint));
+char*
+preset_get_fullname(hb_preset_index_t *path)
+{
+    int                ii;
+    GString           *gstr;
+    hb_preset_index_t *tmp;
+    GhbValue          *dict;
 
-        presets = presets_get_folder(presetsPlist, indices, len);
-        count = ghb_array_len(presets);
-        for (ii = 0; ii < count; ii++)
+    gstr = g_string_new("");
+    tmp  = hb_preset_index_dup(path);
+    for (ii = 1; ii <= path->depth; ii++)
+    {
+        const char *name;
+        tmp->depth = ii;
+        dict = hb_preset_get(tmp);
+        if (dict == NULL)
         {
-            dict = ghb_array_get(presets, ii);
-            folder = ghb_preset_folder(dict);
-            if (folder)
-            {
-                more_indices[len] = ii;
-                presets_set_folder_open(expanded, more_indices, len+1);
-            }
+            break;
+        }
+        name = ghb_dict_get_string(dict, "PresetName");
+        if (name != NULL)
+        {
+            g_string_append(gstr, "/");
+            g_string_append(gstr, name);
         }
-        g_free(more_indices);
     }
-    store_presets();
+    free(tmp);
+    char *str = g_string_free(gstr, FALSE);
+    return str;
 }
 
+// Makes a copy of the preset and assigns "PresetFullName" which
+// is use to look up the preset in the preset list should the need
+// arrise, e.g. saving changes to the preset.
 GhbValue*
 ghb_get_current_preset(signal_user_data_t *ud)
 {
-    GtkTreeView *tv;
-    GtkTreeModel *tm;
+    GtkTreeView      *tv;
+    GtkTreeModel     *tm;
     GtkTreeSelection *ts;
-    GtkTreeIter ti;
-    GhbValue *preset = NULL;
+    GtkTreeIter       ti;
+    GhbValue         *preset = NULL;
 
     tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
     ts = gtk_tree_view_get_selection(tv);
     if (gtk_tree_selection_get_selected(ts, &tm, &ti))
     {
-        GtkTreePath *tp;
-        gint *indices, len;
-
-        tp = gtk_tree_model_get_path(tm, &ti);
-        indices = gtk_tree_path_get_indices(tp);
-        len = gtk_tree_path_get_depth(tp);
-        preset = presets_get_dict(presetsPlist, indices, len);
-        gtk_tree_path_free(tp);
-    }
-    return preset;
-}
+        hb_preset_index_t *path;
 
-GhbValue*
-ghb_get_current_preset_path(signal_user_data_t *ud)
-{
-    GtkTreeView *tv;
-    GtkTreeModel *tm;
-    GtkTreeSelection *ts;
-    GtkTreeIter ti;
-    GhbValue *path = NULL;
+        path   = ghb_tree_get_index(tm, &ti);
+        preset = hb_preset_get(path);
+        if (preset != NULL)
+        {
+            char *fullname;
 
-    tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
-    ts = gtk_tree_view_get_selection(tv);
-    if (gtk_tree_selection_get_selected(ts, &tm, &ti))
-    {
-        GtkTreePath *tp;
-        gint *indices, len;
-
-        tp = gtk_tree_model_get_path(tm, &ti);
-        indices = gtk_tree_path_get_indices(tp);
-        len = gtk_tree_path_get_depth(tp);
-        path = preset_path_from_indices(presetsPlist, indices, len);
-        gtk_tree_path_free(tp);
+            preset   = hb_value_dup(preset);
+            fullname = preset_get_fullname(path);
+            ghb_dict_set_string(preset, "PresetFullName", fullname);
+            free(fullname);
+        }
+        free(path);
     }
-    return path;
+    return preset;
 }
 
 G_MODULE_EXPORT void
 presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
 {
-    GtkTreeModel *store;
-    GtkTreeIter iter;
-    GtkWidget *widget;
+    GtkWidget         *widget;
+    hb_preset_index_t *path;
 
-    g_debug("presets_list_selection_changed_cb ()");
     widget = GHB_WIDGET (ud->builder, "presets_remove");
-    if (gtk_tree_selection_get_selected(selection, &store, &iter))
+    path   = get_selected_path(ud);
+    if (path != NULL)
     {
-        GtkTreePath *treepath;
-        gint *indices, len;
-        gboolean folder;
-
-        treepath = gtk_tree_model_get_path(store, &iter);
-        indices = gtk_tree_path_get_indices(treepath);
-        len = gtk_tree_path_get_depth(treepath);
-
-        folder = ghb_presets_get_folder(presetsPlist, indices, len);
-        if (!folder && !ghb_dict_get_bool(ud->settings, "preset_reload"))
+        GhbValue *dict = hb_preset_get(path);
+        if (!ghb_dict_get_bool(dict, "Folder") &&
+            !ghb_dict_get_bool(ud->settings, "preset_reload"))
         {
-            ghb_set_preset_settings_from_indices(ud, indices, len);
-            ghb_dict_set_bool(ud->settings, "preset_modified", FALSE);
+            ghb_preset_to_settings(ud->settings, dict);
+            char *fullname = preset_get_fullname(path);
+            ghb_dict_set_string(ud->settings, "PresetFullName", fullname);
+            free(fullname);
             ghb_set_current_title_settings(ud);
-            ghb_load_settings(ud);
+            ghb_load_post_settings(ud);
         }
-        ghb_dict_set_bool(ud->settings, "preset_reload", FALSE);
-
-        gtk_tree_path_free(treepath);
         gtk_widget_set_sensitive(widget, TRUE);
     }
     else
@@ -4176,26 +2382,28 @@ presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_
 void
 ghb_clear_presets_selection(signal_user_data_t *ud)
 {
-    GtkTreeView *treeview;
+    GtkTreeView      *treeview;
     GtkTreeSelection *selection;
 
     if (ud->dont_clear_presets) return;
-    g_debug("ghb_clear_presets_selection()");
-    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
+    treeview  = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
     selection = gtk_tree_view_get_selection (treeview);
     gtk_tree_selection_unselect_all (selection);
     ghb_dict_set_bool(ud->settings, "preset_modified", TRUE);
 }
 
 G_MODULE_EXPORT void
-presets_frame_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation, signal_user_data_t *ud)
+presets_frame_size_allocate_cb(
+    GtkWidget          *widget,
+    GtkAllocation      *allocation,
+    signal_user_data_t *ud)
 {
-    GtkTreeView *treeview;
+    GtkTreeView      *treeview;
     GtkTreeSelection *selection;
-    GtkTreeModel *store;
-    GtkTreeIter iter;
+    GtkTreeModel     *store;
+    GtkTreeIter       iter;
 
-    treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
+    treeview  = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
     selection = gtk_tree_view_get_selection(treeview);
     if (gtk_tree_selection_get_selected(selection, &store, &iter))
     {
@@ -4210,72 +2418,53 @@ presets_frame_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation, sig
 G_MODULE_EXPORT void
 presets_default_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
 {
-    GhbValue *preset;
-    gint *indices, len;
-
-    g_debug("presets_default_clicked_cb ()");
-    preset = get_selected_path(ud);
-    indices = ghb_preset_indices_from_path(presetsPlist, preset, &len);
-    if (indices)
+    hb_preset_index_t *path = get_selected_path(ud);
+    if (path != NULL)
     {
-        if (!ghb_presets_get_folder(presetsPlist, indices, len))
+        hb_value_t *dict = hb_preset_get(path);
+        if (dict != NULL && !ghb_dict_get_bool(dict, "Folder"))
         {
             ghb_presets_list_clear_default(ud);
-            presets_set_default(indices, len);
+            ghb_dict_set_bool(dict, "Default", 1);
             ghb_presets_list_show_default(ud);
+            store_presets();
         }
-        g_free(indices);
+        g_free(path);
     }
-    ghb_value_free(&preset);
 }
 
 G_MODULE_EXPORT void
 preset_edited_cb(
     GtkCellRendererText *cell,
-    gchar *path,
-    gchar *text,
-    signal_user_data_t *ud)
+    gchar               *treepath_s,
+    gchar               *text,
+    signal_user_data_t  *ud)
 {
-    GtkTreePath *treepath;
-    GtkTreeStore *store;
-    GtkTreeView *treeview;
-    GtkTreeIter iter;
-    gint *indices, len, count;
-    GhbValue *dict;
-    GhbValue *preset, *dest;
-
-    g_debug("preset_edited_cb ()");
-    g_debug("path (%s)", path);
-    g_debug("text (%s)", text);
-
-    preset = get_selected_path(ud);
-    dest = ghb_array_new();
-    count = ghb_array_len(preset);
-    ghb_array_copy(dest, preset, count-1);
-    ghb_array_append(dest, ghb_string_value_new(text));
-    indices = ghb_preset_indices_from_path(presetsPlist, dest, &len);
-    ghb_value_free(&dest);
-    if (indices != NULL)
-    {
-        // Already exists
-        g_free(indices);
-        ghb_value_free(&preset);
-        return;
-    }
+    GtkTreePath       *treepath;
+    GtkTreeStore      *store;
+    GtkTreeView       *treeview;
+    GtkTreeIter        iter;
+    GhbValue          *dict;
+    hb_preset_index_t *path;
 
     treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
-    store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
-    treepath = gtk_tree_path_new_from_string (path);
-    indices = gtk_tree_path_get_indices(treepath);
-    len = gtk_tree_path_get_depth(treepath);
-    gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath);
-    gtk_tree_store_set(store, &iter, 0, text, -1);
+    store    = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
+    treepath = gtk_tree_path_new_from_string(treepath_s);
+    path     = ghb_tree_path_get_index(treepath);
+    if (path != NULL)
+    {
+        dict = hb_preset_get(path);
+        if (dict != NULL)
+        {
+            gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath);
+            gtk_tree_store_set(store, &iter, 0, text, -1);
 
-    dict = presets_get_dict(presetsPlist, indices, len);
-    ghb_dict_set(dict, "PresetName", ghb_string_value_new(text));
-    store_presets();
-    gtk_tree_path_free (treepath);
-    ghb_value_free(&preset);
+            ghb_dict_set_string(dict, "PresetName", text);
+            store_presets();
+        }
+    }
+    gtk_tree_path_free(treepath);
+    free(path);
 }
 
 G_MODULE_EXPORT void
index d9fe4e92fe1d3b858594f468ee3f75164aff39e9..791900541e8a34f6b689ee5594818ae601e2a60c 100644 (file)
 #if !defined(_GHB_PRESETS_H_)
 #define _GHB_PRESETS_H_
 
+#include "hb.h"
 #include "values.h"
 
-void ghb_settings_save(signal_user_data_t *ud, const gchar *name);
 void ghb_presets_load(signal_user_data_t *ud);
 void ghb_update_from_preset(signal_user_data_t *ud, const gchar *key);
 void ghb_settings_init(GhbValue *settings, const char *name);
 void ghb_settings_close();
-void ghb_globals_to_ui(signal_user_data_t *ud);
 void ghb_prefs_load(signal_user_data_t *ud);
-void ghb_prefs_to_ui(signal_user_data_t *ud);
-void ghb_prefs_save(GhbValue *settings);
 void ghb_pref_save(GhbValue *settings, const gchar *key);
 void ghb_pref_set(GhbValue *settings, const gchar *key);
 void ghb_prefs_store(void);
 void ghb_save_queue(GhbValue *queue);
-GhbValue* ghb_load_queue();
 GhbValue* ghb_load_old_queue(int pid);
-void ghb_remove_queue_file(void);
 void ghb_remove_old_queue_file(int pid);
 gchar* ghb_get_user_config_dir(gchar *subdir);
 void ghb_settings_to_ui(signal_user_data_t *ud, GhbValue *dict);
 void ghb_clear_presets_selection(signal_user_data_t *ud);
-void ghb_select_preset(GtkBuilder *builder, const GhbValue *preset);
+void ghb_select_preset(GtkBuilder *builder, const char *name);
 void ghb_select_default_preset(GtkBuilder *builder);
-void ghb_presets_list_init(signal_user_data_t *ud, gint *indices, gint len);
-GhbValue* ghb_parse_preset_path(const gchar *path);
-gchar* ghb_preset_path_string(const GhbValue *path);
-gboolean ghb_preset_is_custom(void);
-gboolean ghb_lock_file(const gchar *name);
+void ghb_presets_list_init(signal_user_data_t *ud,
+                           const hb_preset_index_t *path);
 int ghb_find_pid_file();
-void ghb_unlink_pid_file(int pid);
 void ghb_write_pid_file();
 GhbValue* ghb_get_current_preset(signal_user_data_t *ud);
-GhbValue* ghb_get_current_preset_path(signal_user_data_t *ud);
 void ghb_preset_to_settings(GhbValue *settings, GhbValue *preset);
 void ghb_prefs_to_settings(GhbValue *settings);
-void dump_preset_path(const gchar *msg, const GhbValue *path);
 GhbValue* ghb_read_settings_file(const gchar *path);
 void ghb_write_settings_file(const gchar *path, GhbValue *dict);
 
index 876d49ec9bc75b3307c07fc2b4919375bbd21b3c..64421f8d996296ac7b1e247ee0bd43f5e5cde21a 100644 (file)
@@ -168,10 +168,9 @@ add_to_queue_list(signal_user_data_t *ud, GhbValue *settings, GtkTreeIter *piter
 
     // Next line in the display
     // Preset: PresetName
-    gchar *preset;
+    const char *name;
     gboolean markers;
     gboolean preset_modified;
-    const GhbValue *path;
 
     const char *mux_id;
     const hb_container_t *mux;
@@ -180,19 +179,17 @@ add_to_queue_list(signal_user_data_t *ud, GhbValue *settings, GtkTreeIter *piter
     mux = ghb_lookup_container_by_name(mux_id);
 
     preset_modified = ghb_dict_get_bool(settings, "preset_modified");
-    path = ghb_dict_get_value(settings, "preset");
-    preset = ghb_preset_path_string(path);
+    name = ghb_dict_get_string(settings, "PresetFullName");
     markers = ghb_dict_get_bool(settings, "ChapterMarkers");
 
     if (preset_modified)
     {
-        XPRINT(_("<b>Modified Preset Based On:</b> <small>%s</small>\n"), preset);
+        XPRINT(_("<b>Modified Preset Based On:</b> <small>%s</small>\n"), name);
     }
     else
     {
-        XPRINT(_("<b>Preset:</b> <small>%s</small>\n"), preset);
+        XPRINT(_("<b>Preset:</b> <small>%s</small>\n"), name);
     }
-    g_free(preset);
 
     // Next line in the display (Container type)
     // Format: XXX Container
index 6683f1cd7197a095091d76506277c71d0020ab48..122a878d05f96803549699f4887ed3cbd72d1eaf 100644 (file)
@@ -43,13 +43,6 @@ ghb_resource_init()
     g_bytes_unref(gbytes);
     ghb_dict_set(resources, "internal-defaults", val);
 
-    gbytes = g_resource_lookup_data(data_res,
-                        "/org/handbrake/data/standard_presets.json", 0, NULL);
-    data = g_bytes_get_data(gbytes, &data_size);
-    val = ghb_json_parse(data);
-    g_bytes_unref(gbytes);
-    ghb_dict_set(resources, "standard-presets", val);
-
     gbytes = g_resource_lookup_data(data_res,
                         "/org/handbrake/data/widget.deps", 0, NULL);
     data = g_bytes_get_data(gbytes, &data_size);
diff --git a/gtk/src/standard_presets.json b/gtk/src/standard_presets.json
deleted file mode 100644 (file)
index 41c7be7..0000000
+++ /dev/null
@@ -1,867 +0,0 @@
-[
-    {
-        "ChildrenArray": [
-            {
-                "AudioAllowAACPass": 1,
-                "AudioAllowAC3Pass": 1,
-                "AudioAllowDTSHDPass": 1,
-                "AudioAllowDTSPass": 1,
-                "AudioAllowMP3Pass": 1,
-                "AudioEncoderFallback": "AC3 (ffmpeg)",
-                "AudioList": [
-                    {
-                        "AudioBitrate": "160",
-                        "AudioEncoder": "AAC (avcodec)",
-                        "AudioMixdown": "Dolby Pro Logic II",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    },
-                    {
-                        "AudioBitrate": "160",
-                        "AudioEncoder": "AC3 Passthru",
-                        "AudioMixdown": "None",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    }
-                ],
-                "ChapterMarkers": 1,
-                "Default": 0,
-                "FileFormat": "MP4 file",
-                "Folder": false,
-                "Mp4HttpOptimize": 0,
-                "Mp4iPodCompatible": 0,
-                "PictureAutoCrop": 1,
-                "PictureBottomCrop": 0,
-                "PictureDeblock": 0,
-                "PictureDecomb": 0,
-                "PictureDecombCustom": "",
-                "PictureDecombDeinterlace": 1,
-                "PictureDeinterlace": 0,
-                "PictureDeinterlaceCustom": "",
-                "PictureDenoiseFilter": "off",
-                "PictureDenoiseCustom": "",
-                "PictureDetelecine": 0,
-                "PictureDetelecineCustom": "",
-                "PictureHeight": 576,
-                "PictureKeepRatio": 0,
-                "PictureLeftCrop": 0,
-                "PictureModulus": 2,
-                "PicturePAR": "loose",
-                "PictureRightCrop": 0,
-                "PictureTopCrop": 0,
-                "PictureWidth": 720,
-                "PresetDescription": "HandBrake's settings for compatibility with all Apple devices (including the iPod 6G and later). Includes Dolby Digital audio for surround sound.",
-                "PresetName": "Universal",
-                "Subtitles": "None",
-                "Type": 0,
-                "UsesPictureFilters": true,
-                "UsesPictureSettings": 1,
-                "VideoAvgBitrate": "2500",
-                "VideoEncoder": "H.264 (x264)",
-                "VideoFramerate": "30",
-                "VideoFramerateMode": "pfr",
-                "VideoGrayScale": 0,
-                "VideoQualitySlider": 20.0,
-                "VideoQualityType": 2,
-                "VideoTurboTwoPass": 0,
-                "VideoTwoPass": 0,
-                "VideoLevel": "3.0",
-                "VideoProfile": "baseline",
-                "x264Option": "",
-                "VideoOptionExtra": "",
-                "VideoPreset": "fast",
-                "VideoTune": "",
-                "x264UseAdvancedOptions": 0
-            },
-            {
-                "AudioAllowAACPass": 1,
-                "AudioAllowAC3Pass": 1,
-                "AudioAllowDTSHDPass": 1,
-                "AudioAllowDTSPass": 1,
-                "AudioAllowMP3Pass": 1,
-                "AudioEncoderFallback": "AC3 (ffmpeg)",
-                "AudioList": [
-                    {
-                        "AudioBitrate": "160",
-                        "AudioEncoder": "AAC (avcodec)",
-                        "AudioMixdown": "Dolby Pro Logic II",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    }
-                ],
-                "ChapterMarkers": 1,
-                "Default": 0,
-                "FileFormat": "MP4 file",
-                "Folder": false,
-                "Mp4HttpOptimize": 0,
-                "Mp4iPodCompatible": 1,
-                "PictureAutoCrop": 1,
-                "PictureBottomCrop": 0,
-                "PictureDeblock": 0,
-                "PictureDecomb": 0,
-                "PictureDecombCustom": "",
-                "PictureDecombDeinterlace": 1,
-                "PictureDeinterlace": 0,
-                "PictureDeinterlaceCustom": "",
-                "PictureDenoiseFilter": "off",
-                "PictureDenoiseCustom": "",
-                "PictureDetelecine": 0,
-                "PictureDetelecineCustom": "",
-                "PictureHeight": 240,
-                "PictureKeepRatio": 1,
-                "PictureLeftCrop": 0,
-                "PictureModulus": 2,
-                "PicturePAR": "off",
-                "PictureRightCrop": 0,
-                "PictureTopCrop": 0,
-                "PictureWidth": 320,
-                "PresetDescription": "HandBrake's settings for playback on the iPod with Video (all generations).",
-                "PresetName": "iPod",
-                "Subtitles": "None",
-                "Type": 0,
-                "UsesPictureFilters": true,
-                "UsesPictureSettings": 1,
-                "VideoAvgBitrate": "2500",
-                "VideoEncoder": "H.264 (x264)",
-                "VideoFramerate": "30",
-                "VideoFramerateMode": "pfr",
-                "VideoGrayScale": 0,
-                "VideoQualitySlider": 22.0,
-                "VideoQualityType": 2,
-                "VideoTurboTwoPass": 0,
-                "VideoTwoPass": 0,
-                "VideoLevel": "1.3",
-                "VideoProfile": "baseline",
-                "x264Option": "",
-                "VideoOptionExtra": "",
-                "VideoPreset": "medium",
-                "VideoTune": "",
-                "x264UseAdvancedOptions": 0
-            },
-            {
-                "AudioAllowAACPass": 1,
-                "AudioAllowAC3Pass": 1,
-                "AudioAllowDTSHDPass": 1,
-                "AudioAllowDTSPass": 1,
-                "AudioAllowMP3Pass": 1,
-                "AudioEncoderFallback": "AC3 (ffmpeg)",
-                "AudioList": [
-                    {
-                        "AudioBitrate": "160",
-                        "AudioEncoder": "AAC (avcodec)",
-                        "AudioMixdown": "Dolby Pro Logic II",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    }
-                ],
-                "ChapterMarkers": 1,
-                "Default": 0,
-                "FileFormat": "MP4 file",
-                "Folder": false,
-                "Mp4HttpOptimize": 0,
-                "Mp4iPodCompatible": 0,
-                "PictureAutoCrop": 1,
-                "PictureBottomCrop": 0,
-                "PictureDeblock": 0,
-                "PictureDecomb": 0,
-                "PictureDecombCustom": "",
-                "PictureDecombDeinterlace": 1,
-                "PictureDeinterlace": 0,
-                "PictureDeinterlaceCustom": "",
-                "PictureDenoiseFilter": "off",
-                "PictureDenoiseCustom": "",
-                "PictureDetelecine": 0,
-                "PictureDetelecineCustom": "",
-                "PictureHeight": 640,
-                "PictureKeepRatio": 0,
-                "PictureLeftCrop": 0,
-                "PictureModulus": 2,
-                "PicturePAR": "loose",
-                "PictureRightCrop": 0,
-                "PictureTopCrop": 0,
-                "PictureWidth": 960,
-                "PresetDescription": "HandBrake's settings for handheld iOS devices (iPhone 4, iPod touch 3G and later).",
-                "PresetName": "iPhone & iPod touch",
-                "Subtitles": "None",
-                "Type": 0,
-                "UsesPictureFilters": true,
-                "UsesPictureSettings": 1,
-                "VideoAvgBitrate": "2500",
-                "VideoEncoder": "H.264 (x264)",
-                "VideoFramerate": "30",
-                "VideoFramerateMode": "pfr",
-                "VideoGrayScale": 0,
-                "VideoQualitySlider": 22.0,
-                "VideoQualityType": 2,
-                "VideoTurboTwoPass": 0,
-                "VideoTwoPass": 0,
-                "VideoLevel": "3.1",
-                "VideoProfile": "high",
-                "x264Option": "",
-                "VideoOptionExtra": "",
-                "VideoPreset": "medium",
-                "VideoTune": "",
-                "x264UseAdvancedOptions": 0
-            },
-            {
-                "AudioAllowAACPass": 1,
-                "AudioAllowAC3Pass": 1,
-                "AudioAllowDTSHDPass": 1,
-                "AudioAllowDTSPass": 1,
-                "AudioAllowMP3Pass": 1,
-                "AudioEncoderFallback": "AC3 (ffmpeg)",
-                "AudioList": [
-                    {
-                        "AudioBitrate": "160",
-                        "AudioEncoder": "AAC (avcodec)",
-                        "AudioMixdown": "Dolby Pro Logic II",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    }
-                ],
-                "ChapterMarkers": 1,
-                "Default": 0,
-                "FileFormat": "MP4 file",
-                "Folder": false,
-                "Mp4HttpOptimize": 0,
-                "Mp4iPodCompatible": 0,
-                "PictureAutoCrop": 1,
-                "PictureBottomCrop": 0,
-                "PictureDeblock": 0,
-                "PictureDecomb": 0,
-                "PictureDecombCustom": "",
-                "PictureDecombDeinterlace": 1,
-                "PictureDeinterlace": 0,
-                "PictureDeinterlaceCustom": "",
-                "PictureDenoiseFilter": "off",
-                "PictureDenoiseCustom": "",
-                "PictureDetelecine": 0,
-                "PictureDetelecineCustom": "",
-                "PictureHeight": 720,
-                "PictureKeepRatio": 0,
-                "PictureLeftCrop": 0,
-                "PictureModulus": 2,
-                "PicturePAR": "loose",
-                "PictureRightCrop": 0,
-                "PictureTopCrop": 0,
-                "PictureWidth": 1280,
-                "PresetDescription": "HandBrake's settings for playback on the iPad (all generations).",
-                "PresetName": "iPad",
-                "Subtitles": "None",
-                "Type": 0,
-                "UsesPictureFilters": true,
-                "UsesPictureSettings": 1,
-                "VideoAvgBitrate": "2500",
-                "VideoEncoder": "H.264 (x264)",
-                "VideoFramerate": "30",
-                "VideoFramerateMode": "pfr",
-                "VideoGrayScale": 0,
-                "VideoQualitySlider": 20.0,
-                "VideoQualityType": 2,
-                "VideoTurboTwoPass": 0,
-                "VideoTwoPass": 0,
-                "VideoLevel": "3.1",
-                "VideoProfile": "high",
-                "x264Option": "",
-                "VideoOptionExtra": "",
-                "VideoPreset": "medium",
-                "VideoTune": "",
-                "x264UseAdvancedOptions": 0
-            },
-            {
-                "AudioAllowAACPass": 1,
-                "AudioAllowAC3Pass": 1,
-                "AudioAllowDTSHDPass": 1,
-                "AudioAllowDTSPass": 1,
-                "AudioAllowMP3Pass": 1,
-                "AudioEncoderFallback": "AC3 (ffmpeg)",
-                "AudioList": [
-                    {
-                        "AudioBitrate": "160",
-                        "AudioEncoder": "AAC (avcodec)",
-                        "AudioMixdown": "Dolby Pro Logic II",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    },
-                    {
-                        "AudioBitrate": "160",
-                        "AudioEncoder": "AC3 Passthru",
-                        "AudioMixdown": "None",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    }
-                ],
-                "ChapterMarkers": 1,
-                "Default": 0,
-                "FileFormat": "MP4 file",
-                "Folder": false,
-                "Mp4HttpOptimize": 0,
-                "Mp4iPodCompatible": 0,
-                "PictureAutoCrop": 1,
-                "PictureBottomCrop": 0,
-                "PictureDeblock": 0,
-                "PictureDecomb": 0,
-                "PictureDecombCustom": "",
-                "PictureDecombDeinterlace": 1,
-                "PictureDeinterlace": 0,
-                "PictureDeinterlaceCustom": "",
-                "PictureDenoiseFilter": "off",
-                "PictureDenoiseCustom": "",
-                "PictureDetelecine": 0,
-                "PictureDetelecineCustom": "",
-                "PictureHeight": 720,
-                "PictureKeepRatio": 0,
-                "PictureLeftCrop": 0,
-                "PictureModulus": 2,
-                "PicturePAR": "loose",
-                "PictureRightCrop": 0,
-                "PictureTopCrop": 0,
-                "PictureWidth": 960,
-                "PresetDescription": "HandBrake's settings for the original AppleTV. Includes Dolby Digital audio for surround sound. Also compatible with iOS devices released since 2009.",
-                "PresetName": "AppleTV",
-                "Subtitles": "None",
-                "Type": 0,
-                "UsesPictureFilters": true,
-                "UsesPictureSettings": 1,
-                "VideoAvgBitrate": "2500",
-                "VideoEncoder": "H.264 (x264)",
-                "VideoFramerate": "30",
-                "VideoFramerateMode": "pfr",
-                "VideoGrayScale": 0,
-                "VideoQualitySlider": 20.0,
-                "VideoQualityType": 2,
-                "VideoTurboTwoPass": 0,
-                "VideoTwoPass": 0,
-                "VideoLevel": "3.1",
-                "VideoProfile": "high",
-                "x264Option": "",
-                "VideoOptionExtra": "qpmin=4:cabac=0:ref=2:b-pyramid=none:weightb=0:weightp=0:vbv-maxrate=9500:vbv-bufsize=9500",
-                "VideoPreset": "medium",
-                "VideoTune": "",
-                "x264UseAdvancedOptions": 0
-            },
-            {
-                "AudioAllowAACPass": 1,
-                "AudioAllowAC3Pass": 1,
-                "AudioAllowDTSHDPass": 1,
-                "AudioAllowDTSPass": 1,
-                "AudioAllowMP3Pass": 1,
-                "AudioEncoderFallback": "AC3 (ffmpeg)",
-                "AudioList": [
-                    {
-                        "AudioBitrate": "160",
-                        "AudioEncoder": "AAC (avcodec)",
-                        "AudioMixdown": "Dolby Pro Logic II",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    },
-                    {
-                        "AudioBitrate": "160",
-                        "AudioEncoder": "AC3 Passthru",
-                        "AudioMixdown": "None",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    }
-                ],
-                "ChapterMarkers": 1,
-                "Default": 0,
-                "FileFormat": "MP4 file",
-                "Folder": false,
-                "Mp4HttpOptimize": 0,
-                "Mp4iPodCompatible": 0,
-                "PictureAutoCrop": 1,
-                "PictureBottomCrop": 0,
-                "PictureDeblock": 0,
-                "PictureDecomb": 0,
-                "PictureDecombCustom": "",
-                "PictureDecombDeinterlace": 1,
-                "PictureDeinterlace": 0,
-                "PictureDeinterlaceCustom": "",
-                "PictureDenoiseFilter": "off",
-                "PictureDenoiseCustom": "",
-                "PictureDetelecine": 0,
-                "PictureDetelecineCustom": "",
-                "PictureHeight": 720,
-                "PictureKeepRatio": 0,
-                "PictureLeftCrop": 0,
-                "PictureModulus": 2,
-                "PicturePAR": "loose",
-                "PictureRightCrop": 0,
-                "PictureTopCrop": 0,
-                "PictureWidth": 1280,
-                "PresetDescription": "HandBrake's settings for the second-generation AppleTV. Includes Dolby Digital audio for surround sound. NOT compatible with the original AppleTV.",
-                "PresetName": "AppleTV 2",
-                "Subtitles": "None",
-                "Type": 0,
-                "UsesPictureFilters": true,
-                "UsesPictureSettings": 1,
-                "VideoAvgBitrate": "2500",
-                "VideoEncoder": "H.264 (x264)",
-                "VideoFramerate": "30",
-                "VideoFramerateMode": "pfr",
-                "VideoGrayScale": 0,
-                "VideoQualitySlider": 20.0,
-                "VideoQualityType": 2,
-                "VideoTurboTwoPass": 0,
-                "VideoTwoPass": 0,
-                "VideoLevel": "3.1",
-                "VideoProfile": "high",
-                "x264Option": "",
-                "VideoOptionExtra": "",
-                "VideoPreset": "medium",
-                "VideoTune": "",
-                "x264UseAdvancedOptions": 0
-            },
-            {
-                "AudioAllowAACPass": 1,
-                "AudioAllowAC3Pass": 1,
-                "AudioAllowDTSHDPass": 1,
-                "AudioAllowDTSPass": 1,
-                "AudioAllowMP3Pass": 1,
-                "AudioEncoderFallback": "AC3 (ffmpeg)",
-                "AudioList": [
-                    {
-                        "AudioBitrate": "160",
-                        "AudioEncoder": "AAC (avcodec)",
-                        "AudioMixdown": "Dolby Pro Logic II",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    },
-                    {
-                        "AudioBitrate": "160",
-                        "AudioEncoder": "AC3 Passthru",
-                        "AudioMixdown": "None",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    }
-                ],
-                "ChapterMarkers": 1,
-                "Default": 0,
-                "FileFormat": "MP4 file",
-                "Folder": false,
-                "Mp4HttpOptimize": 0,
-                "Mp4iPodCompatible": 0,
-                "PictureAutoCrop": 1,
-                "PictureBottomCrop": 0,
-                "PictureDeblock": 0,
-                "PictureDecomb": 3,
-                "PictureDecombCustom": "",
-                "PictureDecombDeinterlace": 1,
-                "PictureDeinterlace": 0,
-                "PictureDeinterlaceCustom": "",
-                "PictureDenoiseFilter": "off",
-                "PictureDenoiseCustom": "",
-                "PictureDetelecine": 0,
-                "PictureDetelecineCustom": "",
-                "PictureHeight": 1080,
-                "PictureKeepRatio": 0,
-                "PictureLeftCrop": 0,
-                "PictureModulus": 2,
-                "PicturePAR": "loose",
-                "PictureRightCrop": 0,
-                "PictureTopCrop": 0,
-                "PictureWidth": 1920,
-                "PresetDescription": "HandBrake's settings for the third-generation AppleTV. Includes Dolby Digital audio for surround sound. NOT compatible with the original AppleTV. May stutter on the second-generation AppleTV.",
-                "PresetName": "AppleTV 3",
-                "Subtitles": "None",
-                "Type": 0,
-                "UsesPictureFilters": true,
-                "UsesPictureSettings": 1,
-                "VideoAvgBitrate": "2500",
-                "VideoEncoder": "H.264 (x264)",
-                "VideoFramerate": "30",
-                "VideoFramerateMode": "pfr",
-                "VideoGrayScale": 0,
-                "VideoQualitySlider": 20.0,
-                "VideoQualityType": 2,
-                "VideoTurboTwoPass": 0,
-                "VideoTwoPass": 0,
-                "VideoLevel": "4.0",
-                "VideoProfile": "high",
-                "x264Option": "",
-                "VideoOptionExtra": "",
-                "VideoPreset": "medium",
-                "VideoTune": "",
-                "x264UseAdvancedOptions": 0
-            },
-            {
-                "AudioAllowAACPass": 1,
-                "AudioAllowAC3Pass": 1,
-                "AudioAllowDTSHDPass": 1,
-                "AudioAllowDTSPass": 1,
-                "AudioAllowMP3Pass": 1,
-                "AudioEncoderFallback": "AC3 (ffmpeg)",
-                "AudioList": [
-                    {
-                        "AudioBitrate": "128",
-                        "AudioEncoder": "AAC (avcodec)",
-                        "AudioMixdown": "Dolby Pro Logic II",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    }
-                ],
-                "ChapterMarkers": 0,
-                "Default": 0,
-                "FileFormat": "MP4 file",
-                "Folder": false,
-                "Mp4HttpOptimize": 0,
-                "Mp4iPodCompatible": 0,
-                "PictureAutoCrop": 1,
-                "PictureBottomCrop": 0,
-                "PictureDeblock": 0,
-                "PictureDecomb": 0,
-                "PictureDecombCustom": "",
-                "PictureDecombDeinterlace": 1,
-                "PictureDeinterlace": 0,
-                "PictureDeinterlaceCustom": "",
-                "PictureDenoiseFilter": "off",
-                "PictureDenoiseCustom": "",
-                "PictureDetelecine": 0,
-                "PictureDetelecineCustom": "",
-                "PictureHeight": 576,
-                "PictureKeepRatio": 0,
-                "PictureLeftCrop": 0,
-                "PictureModulus": 2,
-                "PicturePAR": "loose",
-                "PictureRightCrop": 0,
-                "PictureTopCrop": 0,
-                "PictureWidth": 720,
-                "PresetDescription": "HandBrake's settings for midrange devices running Android 2.3 or later.",
-                "PresetName": "Android",
-                "Subtitles": "None",
-                "Type": 0,
-                "UsesPictureFilters": true,
-                "UsesPictureSettings": 1,
-                "VideoAvgBitrate": "2500",
-                "VideoEncoder": "H.264 (x264)",
-                "VideoFramerate": "30",
-                "VideoFramerateMode": "pfr",
-                "VideoGrayScale": 0,
-                "VideoQualitySlider": 22.0,
-                "VideoQualityType": 2,
-                "VideoTurboTwoPass": 0,
-                "VideoTwoPass": 0,
-                "VideoLevel": "3.0",
-                "VideoProfile": "main",
-                "x264Option": "",
-                "VideoOptionExtra": "",
-                "VideoPreset": "medium",
-                "VideoTune": "",
-                "x264UseAdvancedOptions": 0
-            },
-            {
-                "AudioAllowAACPass": 1,
-                "AudioAllowAC3Pass": 1,
-                "AudioAllowDTSHDPass": 1,
-                "AudioAllowDTSPass": 1,
-                "AudioAllowMP3Pass": 1,
-                "AudioEncoderFallback": "AC3 (ffmpeg)",
-                "AudioList": [
-                    {
-                        "AudioBitrate": "128",
-                        "AudioEncoder": "AAC (avcodec)",
-                        "AudioMixdown": "Dolby Pro Logic II",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    }
-                ],
-                "ChapterMarkers": 0,
-                "Default": 0,
-                "FileFormat": "MP4 file",
-                "Folder": false,
-                "Mp4HttpOptimize": 0,
-                "Mp4iPodCompatible": 0,
-                "PictureAutoCrop": 1,
-                "PictureBottomCrop": 0,
-                "PictureDeblock": 0,
-                "PictureDecomb": 0,
-                "PictureDecombCustom": "",
-                "PictureDecombDeinterlace": 1,
-                "PictureDeinterlace": 0,
-                "PictureDeinterlaceCustom": "",
-                "PictureDenoiseFilter": "off",
-                "PictureDenoiseCustom": "",
-                "PictureDetelecine": 0,
-                "PictureDetelecineCustom": "",
-                "PictureHeight": 720,
-                "PictureKeepRatio": 0,
-                "PictureLeftCrop": 0,
-                "PictureModulus": 2,
-                "PicturePAR": "loose",
-                "PictureRightCrop": 0,
-                "PictureTopCrop": 0,
-                "PictureWidth": 1280,
-                "PresetDescription": "HandBrake's preset for tablets running Android 2.3 or later.",
-                "PresetName": "Android Tablet",
-                "Subtitles": "None",
-                "Type": 0,
-                "UsesPictureFilters": true,
-                "UsesPictureSettings": 1,
-                "VideoAvgBitrate": "2500",
-                "VideoEncoder": "H.264 (x264)",
-                "VideoFramerate": "30",
-                "VideoFramerateMode": "pfr",
-                "VideoGrayScale": 0,
-                "VideoQualitySlider": 22.0,
-                "VideoQualityType": 2,
-                "VideoTurboTwoPass": 0,
-                "VideoTwoPass": 0,
-                "VideoLevel": "3.1",
-                "VideoProfile": "main",
-                "x264Option": "",
-                "VideoOptionExtra": "",
-                "VideoPreset": "medium",
-                "VideoTune": "",
-                "x264UseAdvancedOptions": 0
-            },
-            {
-                "AudioAllowAACPass": 1,
-                "AudioAllowAC3Pass": 1,
-                "AudioAllowDTSHDPass": 1,
-                "AudioAllowDTSPass": 1,
-                "AudioAllowMP3Pass": 1,
-                "AudioEncoderFallback": "AC3 (ffmpeg)",
-                "AudioList": [
-                    {
-                        "AudioBitrate": "128",
-                        "AudioEncoder": "AAC (avcodec)",
-                        "AudioMixdown": "Dolby Pro Logic II",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    }
-                ],
-                "ChapterMarkers": 0,
-                "Default": 0,
-                "FileFormat": "MP4 file",
-                "Folder": false,
-                "Mp4HttpOptimize": 0,
-                "Mp4iPodCompatible": 0,
-                "PictureAutoCrop": 1,
-                "PictureBottomCrop": 0,
-                "PictureDeblock": 0,
-                "PictureDecomb": 0,
-                "PictureDecombCustom": "",
-                "PictureDecombDeinterlace": 1,
-                "PictureDeinterlace": 0,
-                "PictureDeinterlaceCustom": "",
-                "PictureDenoiseFilter": "off",
-                "PictureDenoiseCustom": "",
-                "PictureDetelecine": 0,
-                "PictureDetelecineCustom": "",
-                "PictureHeight": 720,
-                "PictureKeepRatio": 1,
-                "PictureLeftCrop": 0,
-                "PictureModulus": 2,
-                "PicturePAR": "off",
-                "PictureRightCrop": 0,
-                "PictureTopCrop": 0,
-                "PictureWidth": 1280,
-                "PresetDescription": "HandBrake's preset for Windows Phone 8 devices",
-                "PresetName": "Windows Phone 8",
-                "Subtitles": "None",
-                "Type": 0,
-                "UsesPictureFilters": true,
-                "UsesPictureSettings": 1,
-                "VideoAvgBitrate": "2500",
-                "VideoEncoder": "H.264 (x264)",
-                "VideoFramerate": "30",
-                "VideoFramerateMode": "pfr",
-                "VideoGrayScale": 0,
-                "VideoQualitySlider": 22.0,
-                "VideoQualityType": 2,
-                "VideoTurboTwoPass": 0,
-                "VideoTwoPass": 0,
-                "VideoLevel": "3.1",
-                "VideoProfile": "main",
-                "x264Option": "",
-                "VideoOptionExtra": "",
-                "VideoPreset": "medium",
-                "VideoTune": "",
-                "x264UseAdvancedOptions": 0
-            }
-        ],
-        "Default": 0,
-        "Folder": true,
-        "PresetName": "Devices",
-        "Type": 0
-    },
-    {
-        "ChildrenArray": [
-            {
-                "AudioAllowAACPass": 1,
-                "AudioAllowAC3Pass": 1,
-                "AudioAllowDTSHDPass": 1,
-                "AudioAllowDTSPass": 1,
-                "AudioAllowMP3Pass": 1,
-                "AudioEncoderFallback": "AC3 (ffmpeg)",
-                "AudioList": [
-                    {
-                        "AudioBitrate": "160",
-                        "AudioEncoder": "AAC (avcodec)",
-                        "AudioMixdown": "Dolby Pro Logic II",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    }
-                ],
-                "ChapterMarkers": 1,
-                "Default": 1,
-                "FileFormat": "MP4 file",
-                "Folder": false,
-                "Mp4HttpOptimize": 0,
-                "Mp4iPodCompatible": 0,
-                "PictureAutoCrop": 1,
-                "PictureBottomCrop": 0,
-                "PictureDeblock": 0,
-                "PictureDecomb": 0,
-                "PictureDecombCustom": "",
-                "PictureDecombDeinterlace": 1,
-                "PictureDeinterlace": 0,
-                "PictureDeinterlaceCustom": "",
-                "PictureDenoiseFilter": "off",
-                "PictureDenoiseCustom": "",
-                "PictureDetelecine": 0,
-                "PictureDetelecineCustom": "",
-                "PictureHeight": 0,
-                "PictureKeepRatio": 0,
-                "PictureLeftCrop": 0,
-                "PictureModulus": 2,
-                "PicturePAR": "loose",
-                "PictureRightCrop": 0,
-                "PictureTopCrop": 0,
-                "PictureWidth": 0,
-                "PresetDescription": "HandBrake's normal, default settings.",
-                "PresetName": "Normal",
-                "Subtitles": "None",
-                "Type": 0,
-                "UsesPictureFilters": true,
-                "UsesPictureSettings": 1,
-                "VideoAvgBitrate": "2500",
-                "VideoEncoder": "H.264 (x264)",
-                "VideoFramerate": "Same as source",
-                "VideoFramerateMode": "vfr",
-                "VideoGrayScale": 0,
-                "VideoQualitySlider": 20.0,
-                "VideoQualityType": 2,
-                "VideoTurboTwoPass": 0,
-                "VideoTwoPass": 0,
-                "VideoLevel": "4.0",
-                "VideoProfile": "main",
-                "x264Option": "",
-                "VideoOptionExtra": "",
-                "VideoPreset": "veryfast",
-                "VideoTune": "",
-                "x264UseAdvancedOptions": 0
-            },
-            {
-                "AudioAllowAACPass": 1,
-                "AudioAllowAC3Pass": 1,
-                "AudioAllowDTSHDPass": 1,
-                "AudioAllowDTSPass": 1,
-                "AudioAllowMP3Pass": 1,
-                "AudioEncoderFallback": "AC3 (ffmpeg)",
-                "AudioList": [
-                    {
-                        "AudioBitrate": "160",
-                        "AudioEncoder": "AAC (avcodec)",
-                        "AudioMixdown": "Dolby Pro Logic II",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    },
-                    {
-                        "AudioBitrate": "160",
-                        "AudioEncoder": "AC3 Passthru",
-                        "AudioMixdown": "None",
-                        "AudioSamplerate": "Auto",
-                        "AudioTrack": 1,
-                        "AudioTrackDRCSlider": 0.0,
-                        "AudioTrackGainSlider": 0.0
-                    }
-                ],
-                "ChapterMarkers": 1,
-                "Default": 0,
-                "FileFormat": "MP4 file",
-                "Folder": false,
-                "Mp4HttpOptimize": 0,
-                "Mp4iPodCompatible": 0,
-                "PictureAutoCrop": 1,
-                "PictureBottomCrop": 0,
-                "PictureDeblock": 0,
-                "PictureDecomb": 2,
-                "PictureDecombCustom": "",
-                "PictureDecombDeinterlace": 1,
-                "PictureDeinterlace": 0,
-                "PictureDeinterlaceCustom": "",
-                "PictureDenoiseFilter": "off",
-                "PictureDenoiseCustom": "",
-                "PictureDetelecine": 0,
-                "PictureDetelecineCustom": "",
-                "PictureHeight": 0,
-                "PictureKeepRatio": 0,
-                "PictureLeftCrop": 0,
-                "PictureModulus": 2,
-                "PicturePAR": "loose",
-                "PictureRightCrop": 0,
-                "PictureTopCrop": 0,
-                "PictureWidth": 0,
-                "PresetDescription": "HandBrake's general-purpose preset for High Profile H.264 video.",
-                "PresetName": "High Profile",
-                "Subtitles": "None",
-                "Type": 0,
-                "UsesPictureFilters": true,
-                "UsesPictureSettings": 1,
-                "VideoAvgBitrate": "2500",
-                "VideoEncoder": "H.264 (x264)",
-                "VideoFramerate": "Same as source",
-                "VideoFramerateMode": "vfr",
-                "VideoGrayScale": 0,
-                "VideoQualitySlider": 20.0,
-                "VideoQualityType": 2,
-                "VideoTurboTwoPass": 0,
-                "VideoTwoPass": 0,
-                "VideoLevel": "4.1",
-                "VideoProfile": "high",
-                "x264Option": "",
-                "VideoOptionExtra": "",
-                "VideoPreset": "medium",
-                "VideoTune": "",
-                "x264UseAdvancedOptions": 0
-            }
-        ],
-        "Default": 0,
-        "Folder": true,
-        "PresetName": "Regular",
-        "Type": 0
-    }
-]
index b413250ccfdcec21cecbf291cbf2614f4f895c39..a1206d9d03b24e6432a2bffc824d0c866262d25f 100644 (file)
@@ -224,3 +224,32 @@ ghb_dict_get_string_xform(const GhbValue *dict, const gchar *key)
     return ghb_value_get_string_xform(value);
 }
 
+void
+ghb_dict_copy(GhbValue *dst, const GhbValue *src)
+{
+    GhbDictIter iter;
+    const char *key;
+    GhbValue *val, *dst_val;
+
+    iter = ghb_dict_iter_init(src);
+    while (ghb_dict_iter_next(src, &iter, &key, &val))
+    {
+        dst_val = ghb_dict_get(dst, key);
+        if (ghb_value_type(val) == GHB_DICT)
+        {
+            if (dst_val == NULL || ghb_value_type(dst_val) != GHB_DICT)
+            {
+                dst_val = ghb_value_dup(val);
+                ghb_dict_set(dst, key, dst_val);
+            }
+            else if (ghb_value_type(dst_val) == GHB_DICT)
+            {
+                ghb_dict_copy(dst_val, val);
+            }
+        }
+        else
+        {
+            ghb_dict_set(dst, key, ghb_value_dup(val));
+        }
+    }
+}
index 87f7010ccff2c5b5cfe63ac62123bd8adb27bb47..0f62bcc880fc67d359a3e8d7a9b0e0b6a0b23e64 100644 (file)
@@ -84,6 +84,8 @@ GhbValue* ghb_boolean_value(gboolean bval);
 void debug_show_value(GhbValue *gval);
 void debug_show_type(GhbType tp);
 
+void ghb_dict_copy(GhbValue *dst, const GhbValue *src);
+
 void ghb_dict_set_string(GhbValue *dict, const gchar *key, const gchar *sval);
 void ghb_dict_set_double(GhbValue *dict, const gchar *key, gdouble dval);
 void ghb_dict_set_int(GhbValue *dict, const gchar *key, gint64 ival);
index b0b3e5cd843c9b5336e2d86d3cac0e3c56374bd6..fba7e1b67b3f0a213149a0e5d3752ad95b1567b7 100644 (file)
@@ -4,52 +4,45 @@ const char hb_builtin_presets_json[] =
 "        {\n"
 "            \"ChildrenArray\": [\n"
 "                {\n"
-"                    \"AudioAllowAACPass\": 1, \n"
-"                    \"AudioAllowAC3Pass\": 1, \n"
-"                    \"AudioAllowDTSHDPass\": 1, \n"
-"                    \"AudioAllowDTSPass\": 1, \n"
-"                    \"AudioAllowMP3Pass\": 1, \n"
 "                    \"AudioEncoderFallback\": \"ac3\", \n"
 "                    \"AudioList\": [\n"
 "                        {\n"
-"                            \"AudioBitrate\": \"160\", \n"
+"                            \"AudioBitrate\": 160, \n"
 "                            \"AudioEncoder\": \"aac\", \n"
 "                            \"AudioMixdown\": \"dpl2\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }, \n"
 "                        {\n"
-"                            \"AudioBitrate\": \"160\", \n"
+"                            \"AudioBitrate\": 160, \n"
 "                            \"AudioEncoder\": \"copy:ac3\", \n"
 "                            \"AudioMixdown\": \"none\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }\n"
 "                    ], \n"
-"                    \"ChapterMarkers\": 1, \n"
-"                    \"Default\": 0, \n"
+"                    \"ChapterMarkers\": true, \n"
+"                    \"Default\": false, \n"
 "                    \"FileFormat\": \"mp4\", \n"
 "                    \"Folder\": false, \n"
-"                    \"Mp4HttpOptimize\": 0, \n"
-"                    \"Mp4iPodCompatible\": 0, \n"
-"                    \"PictureAutoCrop\": 1, \n"
+"                    \"Mp4HttpOptimize\": false, \n"
+"                    \"Mp4iPodCompatible\": false, \n"
+"                    \"PictureAutoCrop\": true, \n"
 "                    \"PictureBottomCrop\": 0, \n"
 "                    \"PictureDeblock\": 0, \n"
-"                    \"PictureDecomb\": 0, \n"
+"                    \"PictureDecomb\": \"off\", \n"
 "                    \"PictureDecombCustom\": \"\", \n"
-"                    \"PictureDecombDeinterlace\": 1, \n"
-"                    \"PictureDeinterlace\": 0, \n"
+"                    \"PictureDecombDeinterlace\": true, \n"
+"                    \"PictureDeinterlace\": \"off\", \n"
 "                    \"PictureDeinterlaceCustom\": \"\", \n"
 "                    \"PictureDenoiseCustom\": \"\", \n"
 "                    \"PictureDenoiseFilter\": \"off\", \n"
-"                    \"PictureDetelecine\": 0, \n"
+"                    \"PictureDetelecine\": \"off\", \n"
 "                    \"PictureDetelecineCustom\": \"\", \n"
 "                    \"PictureHeight\": 576, \n"
-"                    \"PictureKeepRatio\": 0, \n"
+"                    \"PictureKeepRatio\": true, \n"
 "                    \"PictureLeftCrop\": 0, \n"
 "                    \"PictureModulus\": 2, \n"
 "                    \"PicturePAR\": \"loose\", \n"
@@ -59,13 +52,13 @@ const char hb_builtin_presets_json[] =
 "                    \"PresetDescription\": \"HandBrake's settings for compatibility with all Apple devices (including the iPod 6G and later). Includes Dolby Digital audio for surround sound.\", \n"
 "                    \"PresetName\": \"Universal\", \n"
 "                    \"Type\": 0, \n"
-"                    \"UsesPictureFilters\": 1, \n"
+"                    \"UsesPictureFilters\": true, \n"
 "                    \"UsesPictureSettings\": 1, \n"
-"                    \"VideoAvgBitrate\": \"2500\", \n"
+"                    \"VideoAvgBitrate\": 2500, \n"
 "                    \"VideoEncoder\": \"x264\", \n"
 "                    \"VideoFramerate\": \"30\", \n"
 "                    \"VideoFramerateMode\": \"pfr\", \n"
-"                    \"VideoGrayScale\": 0, \n"
+"                    \"VideoGrayScale\": false, \n"
 "                    \"VideoLevel\": \"3.0\", \n"
 "                    \"VideoOptionExtra\": \"\", \n"
 "                    \"VideoPreset\": \"fast\", \n"
@@ -73,49 +66,43 @@ const char hb_builtin_presets_json[] =
 "                    \"VideoQualitySlider\": 20.0, \n"
 "                    \"VideoQualityType\": 2, \n"
 "                    \"VideoTune\": \"\", \n"
-"                    \"VideoTurboTwoPass\": 0, \n"
-"                    \"VideoTwoPass\": 0, \n"
+"                    \"VideoTurboTwoPass\": false, \n"
+"                    \"VideoTwoPass\": false, \n"
 "                    \"x264Option\": \"\", \n"
-"                    \"x264UseAdvancedOptions\": 0\n"
+"                    \"x264UseAdvancedOptions\": false\n"
 "                }, \n"
 "                {\n"
-"                    \"AudioAllowAACPass\": 1, \n"
-"                    \"AudioAllowAC3Pass\": 1, \n"
-"                    \"AudioAllowDTSHDPass\": 1, \n"
-"                    \"AudioAllowDTSPass\": 1, \n"
-"                    \"AudioAllowMP3Pass\": 1, \n"
 "                    \"AudioEncoderFallback\": \"ac3\", \n"
 "                    \"AudioList\": [\n"
 "                        {\n"
-"                            \"AudioBitrate\": \"160\", \n"
+"                            \"AudioBitrate\": 160, \n"
 "                            \"AudioEncoder\": \"aac\", \n"
 "                            \"AudioMixdown\": \"dpl2\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }\n"
 "                    ], \n"
-"                    \"ChapterMarkers\": 1, \n"
-"                    \"Default\": 0, \n"
+"                    \"ChapterMarkers\": true, \n"
+"                    \"Default\": false, \n"
 "                    \"FileFormat\": \"mp4\", \n"
 "                    \"Folder\": false, \n"
-"                    \"Mp4HttpOptimize\": 0, \n"
-"                    \"Mp4iPodCompatible\": 1, \n"
-"                    \"PictureAutoCrop\": 1, \n"
+"                    \"Mp4HttpOptimize\": false, \n"
+"                    \"Mp4iPodCompatible\": true, \n"
+"                    \"PictureAutoCrop\": true, \n"
 "                    \"PictureBottomCrop\": 0, \n"
 "                    \"PictureDeblock\": 0, \n"
-"                    \"PictureDecomb\": 0, \n"
+"                    \"PictureDecomb\": \"off\", \n"
 "                    \"PictureDecombCustom\": \"\", \n"
-"                    \"PictureDecombDeinterlace\": 1, \n"
-"                    \"PictureDeinterlace\": 0, \n"
+"                    \"PictureDecombDeinterlace\": true, \n"
+"                    \"PictureDeinterlace\": \"off\", \n"
 "                    \"PictureDeinterlaceCustom\": \"\", \n"
 "                    \"PictureDenoiseCustom\": \"\", \n"
 "                    \"PictureDenoiseFilter\": \"off\", \n"
-"                    \"PictureDetelecine\": 0, \n"
+"                    \"PictureDetelecine\": \"off\", \n"
 "                    \"PictureDetelecineCustom\": \"\", \n"
 "                    \"PictureHeight\": 240, \n"
-"                    \"PictureKeepRatio\": 1, \n"
+"                    \"PictureKeepRatio\": true, \n"
 "                    \"PictureLeftCrop\": 0, \n"
 "                    \"PictureModulus\": 2, \n"
 "                    \"PicturePAR\": \"off\", \n"
@@ -125,13 +112,13 @@ const char hb_builtin_presets_json[] =
 "                    \"PresetDescription\": \"HandBrake's settings for playback on the iPod with Video (all generations).\", \n"
 "                    \"PresetName\": \"iPod\", \n"
 "                    \"Type\": 0, \n"
-"                    \"UsesPictureFilters\": 1, \n"
+"                    \"UsesPictureFilters\": true, \n"
 "                    \"UsesPictureSettings\": 1, \n"
-"                    \"VideoAvgBitrate\": \"2500\", \n"
+"                    \"VideoAvgBitrate\": 2500, \n"
 "                    \"VideoEncoder\": \"x264\", \n"
 "                    \"VideoFramerate\": \"30\", \n"
 "                    \"VideoFramerateMode\": \"pfr\", \n"
-"                    \"VideoGrayScale\": 0, \n"
+"                    \"VideoGrayScale\": false, \n"
 "                    \"VideoLevel\": \"1.3\", \n"
 "                    \"VideoOptionExtra\": \"\", \n"
 "                    \"VideoPreset\": \"medium\", \n"
@@ -139,49 +126,43 @@ const char hb_builtin_presets_json[] =
 "                    \"VideoQualitySlider\": 22.0, \n"
 "                    \"VideoQualityType\": 2, \n"
 "                    \"VideoTune\": \"\", \n"
-"                    \"VideoTurboTwoPass\": 0, \n"
-"                    \"VideoTwoPass\": 0, \n"
+"                    \"VideoTurboTwoPass\": false, \n"
+"                    \"VideoTwoPass\": false, \n"
 "                    \"x264Option\": \"\", \n"
-"                    \"x264UseAdvancedOptions\": 0\n"
+"                    \"x264UseAdvancedOptions\": false\n"
 "                }, \n"
 "                {\n"
-"                    \"AudioAllowAACPass\": 1, \n"
-"                    \"AudioAllowAC3Pass\": 1, \n"
-"                    \"AudioAllowDTSHDPass\": 1, \n"
-"                    \"AudioAllowDTSPass\": 1, \n"
-"                    \"AudioAllowMP3Pass\": 1, \n"
 "                    \"AudioEncoderFallback\": \"ac3\", \n"
 "                    \"AudioList\": [\n"
 "                        {\n"
-"                            \"AudioBitrate\": \"160\", \n"
+"                            \"AudioBitrate\": 160, \n"
 "                            \"AudioEncoder\": \"aac\", \n"
 "                            \"AudioMixdown\": \"dpl2\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }\n"
 "                    ], \n"
-"                    \"ChapterMarkers\": 1, \n"
-"                    \"Default\": 0, \n"
+"                    \"ChapterMarkers\": true, \n"
+"                    \"Default\": false, \n"
 "                    \"FileFormat\": \"mp4\", \n"
 "                    \"Folder\": false, \n"
-"                    \"Mp4HttpOptimize\": 0, \n"
-"                    \"Mp4iPodCompatible\": 0, \n"
-"                    \"PictureAutoCrop\": 1, \n"
+"                    \"Mp4HttpOptimize\": false, \n"
+"                    \"Mp4iPodCompatible\": false, \n"
+"                    \"PictureAutoCrop\": true, \n"
 "                    \"PictureBottomCrop\": 0, \n"
 "                    \"PictureDeblock\": 0, \n"
-"                    \"PictureDecomb\": 0, \n"
+"                    \"PictureDecomb\": \"off\", \n"
 "                    \"PictureDecombCustom\": \"\", \n"
-"                    \"PictureDecombDeinterlace\": 1, \n"
-"                    \"PictureDeinterlace\": 0, \n"
+"                    \"PictureDecombDeinterlace\": true, \n"
+"                    \"PictureDeinterlace\": \"off\", \n"
 "                    \"PictureDeinterlaceCustom\": \"\", \n"
 "                    \"PictureDenoiseCustom\": \"\", \n"
 "                    \"PictureDenoiseFilter\": \"off\", \n"
-"                    \"PictureDetelecine\": 0, \n"
+"                    \"PictureDetelecine\": \"off\", \n"
 "                    \"PictureDetelecineCustom\": \"\", \n"
 "                    \"PictureHeight\": 640, \n"
-"                    \"PictureKeepRatio\": 0, \n"
+"                    \"PictureKeepRatio\": true, \n"
 "                    \"PictureLeftCrop\": 0, \n"
 "                    \"PictureModulus\": 2, \n"
 "                    \"PicturePAR\": \"loose\", \n"
@@ -191,13 +172,13 @@ const char hb_builtin_presets_json[] =
 "                    \"PresetDescription\": \"HandBrake's settings for handheld iOS devices (iPhone 4, iPod touch 3G and later).\", \n"
 "                    \"PresetName\": \"iPhone & iPod touch\", \n"
 "                    \"Type\": 0, \n"
-"                    \"UsesPictureFilters\": 1, \n"
+"                    \"UsesPictureFilters\": true, \n"
 "                    \"UsesPictureSettings\": 1, \n"
-"                    \"VideoAvgBitrate\": \"2500\", \n"
+"                    \"VideoAvgBitrate\": 2500, \n"
 "                    \"VideoEncoder\": \"x264\", \n"
 "                    \"VideoFramerate\": \"30\", \n"
 "                    \"VideoFramerateMode\": \"pfr\", \n"
-"                    \"VideoGrayScale\": 0, \n"
+"                    \"VideoGrayScale\": false, \n"
 "                    \"VideoLevel\": \"3.1\", \n"
 "                    \"VideoOptionExtra\": \"\", \n"
 "                    \"VideoPreset\": \"medium\", \n"
@@ -205,49 +186,43 @@ const char hb_builtin_presets_json[] =
 "                    \"VideoQualitySlider\": 22.0, \n"
 "                    \"VideoQualityType\": 2, \n"
 "                    \"VideoTune\": \"\", \n"
-"                    \"VideoTurboTwoPass\": 0, \n"
-"                    \"VideoTwoPass\": 0, \n"
+"                    \"VideoTurboTwoPass\": false, \n"
+"                    \"VideoTwoPass\": false, \n"
 "                    \"x264Option\": \"\", \n"
-"                    \"x264UseAdvancedOptions\": 0\n"
+"                    \"x264UseAdvancedOptions\": false\n"
 "                }, \n"
 "                {\n"
-"                    \"AudioAllowAACPass\": 1, \n"
-"                    \"AudioAllowAC3Pass\": 1, \n"
-"                    \"AudioAllowDTSHDPass\": 1, \n"
-"                    \"AudioAllowDTSPass\": 1, \n"
-"                    \"AudioAllowMP3Pass\": 1, \n"
 "                    \"AudioEncoderFallback\": \"ac3\", \n"
 "                    \"AudioList\": [\n"
 "                        {\n"
-"                            \"AudioBitrate\": \"160\", \n"
+"                            \"AudioBitrate\": 160, \n"
 "                            \"AudioEncoder\": \"aac\", \n"
 "                            \"AudioMixdown\": \"dpl2\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }\n"
 "                    ], \n"
-"                    \"ChapterMarkers\": 1, \n"
-"                    \"Default\": 0, \n"
+"                    \"ChapterMarkers\": true, \n"
+"                    \"Default\": false, \n"
 "                    \"FileFormat\": \"mp4\", \n"
 "                    \"Folder\": false, \n"
-"                    \"Mp4HttpOptimize\": 0, \n"
-"                    \"Mp4iPodCompatible\": 0, \n"
-"                    \"PictureAutoCrop\": 1, \n"
+"                    \"Mp4HttpOptimize\": false, \n"
+"                    \"Mp4iPodCompatible\": false, \n"
+"                    \"PictureAutoCrop\": true, \n"
 "                    \"PictureBottomCrop\": 0, \n"
 "                    \"PictureDeblock\": 0, \n"
-"                    \"PictureDecomb\": 0, \n"
+"                    \"PictureDecomb\": \"off\", \n"
 "                    \"PictureDecombCustom\": \"\", \n"
-"                    \"PictureDecombDeinterlace\": 1, \n"
-"                    \"PictureDeinterlace\": 0, \n"
+"                    \"PictureDecombDeinterlace\": true, \n"
+"                    \"PictureDeinterlace\": \"off\", \n"
 "                    \"PictureDeinterlaceCustom\": \"\", \n"
 "                    \"PictureDenoiseCustom\": \"\", \n"
 "                    \"PictureDenoiseFilter\": \"off\", \n"
-"                    \"PictureDetelecine\": 0, \n"
+"                    \"PictureDetelecine\": \"off\", \n"
 "                    \"PictureDetelecineCustom\": \"\", \n"
 "                    \"PictureHeight\": 720, \n"
-"                    \"PictureKeepRatio\": 0, \n"
+"                    \"PictureKeepRatio\": true, \n"
 "                    \"PictureLeftCrop\": 0, \n"
 "                    \"PictureModulus\": 2, \n"
 "                    \"PicturePAR\": \"loose\", \n"
@@ -257,13 +232,13 @@ const char hb_builtin_presets_json[] =
 "                    \"PresetDescription\": \"HandBrake's settings for playback on the iPad (all generations).\", \n"
 "                    \"PresetName\": \"iPad\", \n"
 "                    \"Type\": 0, \n"
-"                    \"UsesPictureFilters\": 1, \n"
+"                    \"UsesPictureFilters\": true, \n"
 "                    \"UsesPictureSettings\": 1, \n"
-"                    \"VideoAvgBitrate\": \"2500\", \n"
+"                    \"VideoAvgBitrate\": 2500, \n"
 "                    \"VideoEncoder\": \"x264\", \n"
 "                    \"VideoFramerate\": \"30\", \n"
 "                    \"VideoFramerateMode\": \"pfr\", \n"
-"                    \"VideoGrayScale\": 0, \n"
+"                    \"VideoGrayScale\": false, \n"
 "                    \"VideoLevel\": \"3.1\", \n"
 "                    \"VideoOptionExtra\": \"\", \n"
 "                    \"VideoPreset\": \"medium\", \n"
@@ -271,58 +246,51 @@ const char hb_builtin_presets_json[] =
 "                    \"VideoQualitySlider\": 20.0, \n"
 "                    \"VideoQualityType\": 2, \n"
 "                    \"VideoTune\": \"\", \n"
-"                    \"VideoTurboTwoPass\": 0, \n"
-"                    \"VideoTwoPass\": 0, \n"
+"                    \"VideoTurboTwoPass\": false, \n"
+"                    \"VideoTwoPass\": false, \n"
 "                    \"x264Option\": \"\", \n"
-"                    \"x264UseAdvancedOptions\": 0\n"
+"                    \"x264UseAdvancedOptions\": false\n"
 "                }, \n"
 "                {\n"
-"                    \"AudioAllowAACPass\": 1, \n"
-"                    \"AudioAllowAC3Pass\": 1, \n"
-"                    \"AudioAllowDTSHDPass\": 1, \n"
-"                    \"AudioAllowDTSPass\": 1, \n"
-"                    \"AudioAllowMP3Pass\": 1, \n"
 "                    \"AudioEncoderFallback\": \"ac3\", \n"
 "                    \"AudioList\": [\n"
 "                        {\n"
-"                            \"AudioBitrate\": \"160\", \n"
+"                            \"AudioBitrate\": 160, \n"
 "                            \"AudioEncoder\": \"aac\", \n"
 "                            \"AudioMixdown\": \"dpl2\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }, \n"
 "                        {\n"
-"                            \"AudioBitrate\": \"160\", \n"
+"                            \"AudioBitrate\": 160, \n"
 "                            \"AudioEncoder\": \"copy:ac3\", \n"
 "                            \"AudioMixdown\": \"none\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }\n"
 "                    ], \n"
-"                    \"ChapterMarkers\": 1, \n"
-"                    \"Default\": 0, \n"
+"                    \"ChapterMarkers\": true, \n"
+"                    \"Default\": false, \n"
 "                    \"FileFormat\": \"mp4\", \n"
 "                    \"Folder\": false, \n"
-"                    \"Mp4HttpOptimize\": 0, \n"
-"                    \"Mp4iPodCompatible\": 0, \n"
-"                    \"PictureAutoCrop\": 1, \n"
+"                    \"Mp4HttpOptimize\": false, \n"
+"                    \"Mp4iPodCompatible\": false, \n"
+"                    \"PictureAutoCrop\": true, \n"
 "                    \"PictureBottomCrop\": 0, \n"
 "                    \"PictureDeblock\": 0, \n"
-"                    \"PictureDecomb\": 0, \n"
+"                    \"PictureDecomb\": \"off\", \n"
 "                    \"PictureDecombCustom\": \"\", \n"
-"                    \"PictureDecombDeinterlace\": 1, \n"
-"                    \"PictureDeinterlace\": 0, \n"
+"                    \"PictureDecombDeinterlace\": true, \n"
+"                    \"PictureDeinterlace\": \"off\", \n"
 "                    \"PictureDeinterlaceCustom\": \"\", \n"
 "                    \"PictureDenoiseCustom\": \"\", \n"
 "                    \"PictureDenoiseFilter\": \"off\", \n"
-"                    \"PictureDetelecine\": 0, \n"
+"                    \"PictureDetelecine\": \"off\", \n"
 "                    \"PictureDetelecineCustom\": \"\", \n"
 "                    \"PictureHeight\": 720, \n"
-"                    \"PictureKeepRatio\": 0, \n"
+"                    \"PictureKeepRatio\": true, \n"
 "                    \"PictureLeftCrop\": 0, \n"
 "                    \"PictureModulus\": 2, \n"
 "                    \"PicturePAR\": \"loose\", \n"
@@ -332,13 +300,13 @@ const char hb_builtin_presets_json[] =
 "                    \"PresetDescription\": \"HandBrake's settings for the original AppleTV. Includes Dolby Digital audio for surround sound. Also compatible with iOS devices released since 2009.\", \n"
 "                    \"PresetName\": \"AppleTV\", \n"
 "                    \"Type\": 0, \n"
-"                    \"UsesPictureFilters\": 1, \n"
+"                    \"UsesPictureFilters\": true, \n"
 "                    \"UsesPictureSettings\": 1, \n"
-"                    \"VideoAvgBitrate\": \"2500\", \n"
+"                    \"VideoAvgBitrate\": 2500, \n"
 "                    \"VideoEncoder\": \"x264\", \n"
 "                    \"VideoFramerate\": \"30\", \n"
 "                    \"VideoFramerateMode\": \"pfr\", \n"
-"                    \"VideoGrayScale\": 0, \n"
+"                    \"VideoGrayScale\": false, \n"
 "                    \"VideoLevel\": \"3.1\", \n"
 "                    \"VideoOptionExtra\": \"qpmin=4:cabac=0:ref=2:b-pyramid=none:weightb=0:weightp=0:vbv-maxrate=9500:vbv-bufsize=9500\", \n"
 "                    \"VideoPreset\": \"medium\", \n"
@@ -346,58 +314,51 @@ const char hb_builtin_presets_json[] =
 "                    \"VideoQualitySlider\": 20.0, \n"
 "                    \"VideoQualityType\": 2, \n"
 "                    \"VideoTune\": \"\", \n"
-"                    \"VideoTurboTwoPass\": 0, \n"
-"                    \"VideoTwoPass\": 0, \n"
+"                    \"VideoTurboTwoPass\": false, \n"
+"                    \"VideoTwoPass\": false, \n"
 "                    \"x264Option\": \"\", \n"
-"                    \"x264UseAdvancedOptions\": 0\n"
+"                    \"x264UseAdvancedOptions\": false\n"
 "                }, \n"
 "                {\n"
-"                    \"AudioAllowAACPass\": 1, \n"
-"                    \"AudioAllowAC3Pass\": 1, \n"
-"                    \"AudioAllowDTSHDPass\": 1, \n"
-"                    \"AudioAllowDTSPass\": 1, \n"
-"                    \"AudioAllowMP3Pass\": 1, \n"
 "                    \"AudioEncoderFallback\": \"ac3\", \n"
 "                    \"AudioList\": [\n"
 "                        {\n"
-"                            \"AudioBitrate\": \"160\", \n"
+"                            \"AudioBitrate\": 160, \n"
 "                            \"AudioEncoder\": \"aac\", \n"
 "                            \"AudioMixdown\": \"dpl2\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }, \n"
 "                        {\n"
-"                            \"AudioBitrate\": \"160\", \n"
+"                            \"AudioBitrate\": 160, \n"
 "                            \"AudioEncoder\": \"copy:ac3\", \n"
 "                            \"AudioMixdown\": \"none\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }\n"
 "                    ], \n"
-"                    \"ChapterMarkers\": 1, \n"
-"                    \"Default\": 0, \n"
+"                    \"ChapterMarkers\": true, \n"
+"                    \"Default\": false, \n"
 "                    \"FileFormat\": \"mp4\", \n"
 "                    \"Folder\": false, \n"
-"                    \"Mp4HttpOptimize\": 0, \n"
-"                    \"Mp4iPodCompatible\": 0, \n"
-"                    \"PictureAutoCrop\": 1, \n"
+"                    \"Mp4HttpOptimize\": false, \n"
+"                    \"Mp4iPodCompatible\": false, \n"
+"                    \"PictureAutoCrop\": true, \n"
 "                    \"PictureBottomCrop\": 0, \n"
 "                    \"PictureDeblock\": 0, \n"
-"                    \"PictureDecomb\": 0, \n"
+"                    \"PictureDecomb\": \"off\", \n"
 "                    \"PictureDecombCustom\": \"\", \n"
-"                    \"PictureDecombDeinterlace\": 1, \n"
-"                    \"PictureDeinterlace\": 0, \n"
+"                    \"PictureDecombDeinterlace\": true, \n"
+"                    \"PictureDeinterlace\": \"off\", \n"
 "                    \"PictureDeinterlaceCustom\": \"\", \n"
 "                    \"PictureDenoiseCustom\": \"\", \n"
 "                    \"PictureDenoiseFilter\": \"off\", \n"
-"                    \"PictureDetelecine\": 0, \n"
+"                    \"PictureDetelecine\": \"off\", \n"
 "                    \"PictureDetelecineCustom\": \"\", \n"
 "                    \"PictureHeight\": 720, \n"
-"                    \"PictureKeepRatio\": 0, \n"
+"                    \"PictureKeepRatio\": true, \n"
 "                    \"PictureLeftCrop\": 0, \n"
 "                    \"PictureModulus\": 2, \n"
 "                    \"PicturePAR\": \"loose\", \n"
@@ -407,13 +368,13 @@ const char hb_builtin_presets_json[] =
 "                    \"PresetDescription\": \"HandBrake's settings for the second-generation AppleTV. Includes Dolby Digital audio for surround sound. NOT compatible with the original AppleTV.\", \n"
 "                    \"PresetName\": \"AppleTV 2\", \n"
 "                    \"Type\": 0, \n"
-"                    \"UsesPictureFilters\": 1, \n"
+"                    \"UsesPictureFilters\": true, \n"
 "                    \"UsesPictureSettings\": 1, \n"
-"                    \"VideoAvgBitrate\": \"2500\", \n"
+"                    \"VideoAvgBitrate\": 2500, \n"
 "                    \"VideoEncoder\": \"x264\", \n"
 "                    \"VideoFramerate\": \"30\", \n"
 "                    \"VideoFramerateMode\": \"pfr\", \n"
-"                    \"VideoGrayScale\": 0, \n"
+"                    \"VideoGrayScale\": false, \n"
 "                    \"VideoLevel\": \"3.1\", \n"
 "                    \"VideoOptionExtra\": \"\", \n"
 "                    \"VideoPreset\": \"medium\", \n"
@@ -421,58 +382,51 @@ const char hb_builtin_presets_json[] =
 "                    \"VideoQualitySlider\": 20.0, \n"
 "                    \"VideoQualityType\": 2, \n"
 "                    \"VideoTune\": \"\", \n"
-"                    \"VideoTurboTwoPass\": 0, \n"
-"                    \"VideoTwoPass\": 0, \n"
+"                    \"VideoTurboTwoPass\": false, \n"
+"                    \"VideoTwoPass\": false, \n"
 "                    \"x264Option\": \"\", \n"
-"                    \"x264UseAdvancedOptions\": 0\n"
+"                    \"x264UseAdvancedOptions\": false\n"
 "                }, \n"
 "                {\n"
-"                    \"AudioAllowAACPass\": 1, \n"
-"                    \"AudioAllowAC3Pass\": 1, \n"
-"                    \"AudioAllowDTSHDPass\": 1, \n"
-"                    \"AudioAllowDTSPass\": 1, \n"
-"                    \"AudioAllowMP3Pass\": 1, \n"
 "                    \"AudioEncoderFallback\": \"ac3\", \n"
 "                    \"AudioList\": [\n"
 "                        {\n"
-"                            \"AudioBitrate\": \"160\", \n"
+"                            \"AudioBitrate\": 160, \n"
 "                            \"AudioEncoder\": \"aac\", \n"
 "                            \"AudioMixdown\": \"dpl2\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }, \n"
 "                        {\n"
-"                            \"AudioBitrate\": \"160\", \n"
+"                            \"AudioBitrate\": 160, \n"
 "                            \"AudioEncoder\": \"copy:ac3\", \n"
 "                            \"AudioMixdown\": \"none\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }\n"
 "                    ], \n"
-"                    \"ChapterMarkers\": 1, \n"
-"                    \"Default\": 0, \n"
+"                    \"ChapterMarkers\": true, \n"
+"                    \"Default\": false, \n"
 "                    \"FileFormat\": \"mp4\", \n"
 "                    \"Folder\": false, \n"
-"                    \"Mp4HttpOptimize\": 0, \n"
-"                    \"Mp4iPodCompatible\": 0, \n"
-"                    \"PictureAutoCrop\": 1, \n"
+"                    \"Mp4HttpOptimize\": false, \n"
+"                    \"Mp4iPodCompatible\": false, \n"
+"                    \"PictureAutoCrop\": true, \n"
 "                    \"PictureBottomCrop\": 0, \n"
 "                    \"PictureDeblock\": 0, \n"
-"                    \"PictureDecomb\": 3, \n"
+"                    \"PictureDecomb\": \"fast\", \n"
 "                    \"PictureDecombCustom\": \"\", \n"
-"                    \"PictureDecombDeinterlace\": 1, \n"
-"                    \"PictureDeinterlace\": 0, \n"
+"                    \"PictureDecombDeinterlace\": true, \n"
+"                    \"PictureDeinterlace\": \"off\", \n"
 "                    \"PictureDeinterlaceCustom\": \"\", \n"
 "                    \"PictureDenoiseCustom\": \"\", \n"
 "                    \"PictureDenoiseFilter\": \"off\", \n"
-"                    \"PictureDetelecine\": 0, \n"
+"                    \"PictureDetelecine\": \"off\", \n"
 "                    \"PictureDetelecineCustom\": \"\", \n"
 "                    \"PictureHeight\": 1080, \n"
-"                    \"PictureKeepRatio\": 0, \n"
+"                    \"PictureKeepRatio\": true, \n"
 "                    \"PictureLeftCrop\": 0, \n"
 "                    \"PictureModulus\": 2, \n"
 "                    \"PicturePAR\": \"loose\", \n"
@@ -482,13 +436,13 @@ const char hb_builtin_presets_json[] =
 "                    \"PresetDescription\": \"HandBrake's settings for the third-generation AppleTV. Includes Dolby Digital audio for surround sound. NOT compatible with the original AppleTV. May stutter on the second-generation AppleTV.\", \n"
 "                    \"PresetName\": \"AppleTV 3\", \n"
 "                    \"Type\": 0, \n"
-"                    \"UsesPictureFilters\": 1, \n"
+"                    \"UsesPictureFilters\": true, \n"
 "                    \"UsesPictureSettings\": 1, \n"
-"                    \"VideoAvgBitrate\": \"2500\", \n"
+"                    \"VideoAvgBitrate\": 2500, \n"
 "                    \"VideoEncoder\": \"x264\", \n"
 "                    \"VideoFramerate\": \"30\", \n"
 "                    \"VideoFramerateMode\": \"pfr\", \n"
-"                    \"VideoGrayScale\": 0, \n"
+"                    \"VideoGrayScale\": false, \n"
 "                    \"VideoLevel\": \"4.0\", \n"
 "                    \"VideoOptionExtra\": \"\", \n"
 "                    \"VideoPreset\": \"medium\", \n"
@@ -496,49 +450,43 @@ const char hb_builtin_presets_json[] =
 "                    \"VideoQualitySlider\": 20.0, \n"
 "                    \"VideoQualityType\": 2, \n"
 "                    \"VideoTune\": \"\", \n"
-"                    \"VideoTurboTwoPass\": 0, \n"
-"                    \"VideoTwoPass\": 0, \n"
+"                    \"VideoTurboTwoPass\": false, \n"
+"                    \"VideoTwoPass\": false, \n"
 "                    \"x264Option\": \"\", \n"
-"                    \"x264UseAdvancedOptions\": 0\n"
+"                    \"x264UseAdvancedOptions\": false\n"
 "                }, \n"
 "                {\n"
-"                    \"AudioAllowAACPass\": 1, \n"
-"                    \"AudioAllowAC3Pass\": 1, \n"
-"                    \"AudioAllowDTSHDPass\": 1, \n"
-"                    \"AudioAllowDTSPass\": 1, \n"
-"                    \"AudioAllowMP3Pass\": 1, \n"
 "                    \"AudioEncoderFallback\": \"ac3\", \n"
 "                    \"AudioList\": [\n"
 "                        {\n"
-"                            \"AudioBitrate\": \"128\", \n"
+"                            \"AudioBitrate\": 128, \n"
 "                            \"AudioEncoder\": \"aac\", \n"
 "                            \"AudioMixdown\": \"dpl2\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }\n"
 "                    ], \n"
-"                    \"ChapterMarkers\": 0, \n"
-"                    \"Default\": 0, \n"
+"                    \"ChapterMarkers\": false, \n"
+"                    \"Default\": false, \n"
 "                    \"FileFormat\": \"mp4\", \n"
 "                    \"Folder\": false, \n"
-"                    \"Mp4HttpOptimize\": 0, \n"
-"                    \"Mp4iPodCompatible\": 0, \n"
-"                    \"PictureAutoCrop\": 1, \n"
+"                    \"Mp4HttpOptimize\": false, \n"
+"                    \"Mp4iPodCompatible\": false, \n"
+"                    \"PictureAutoCrop\": true, \n"
 "                    \"PictureBottomCrop\": 0, \n"
 "                    \"PictureDeblock\": 0, \n"
-"                    \"PictureDecomb\": 0, \n"
+"                    \"PictureDecomb\": \"off\", \n"
 "                    \"PictureDecombCustom\": \"\", \n"
-"                    \"PictureDecombDeinterlace\": 1, \n"
-"                    \"PictureDeinterlace\": 0, \n"
+"                    \"PictureDecombDeinterlace\": true, \n"
+"                    \"PictureDeinterlace\": \"off\", \n"
 "                    \"PictureDeinterlaceCustom\": \"\", \n"
 "                    \"PictureDenoiseCustom\": \"\", \n"
 "                    \"PictureDenoiseFilter\": \"off\", \n"
-"                    \"PictureDetelecine\": 0, \n"
+"                    \"PictureDetelecine\": \"off\", \n"
 "                    \"PictureDetelecineCustom\": \"\", \n"
 "                    \"PictureHeight\": 576, \n"
-"                    \"PictureKeepRatio\": 0, \n"
+"                    \"PictureKeepRatio\": true, \n"
 "                    \"PictureLeftCrop\": 0, \n"
 "                    \"PictureModulus\": 2, \n"
 "                    \"PicturePAR\": \"loose\", \n"
@@ -548,13 +496,13 @@ const char hb_builtin_presets_json[] =
 "                    \"PresetDescription\": \"HandBrake's settings for midrange devices running Android 2.3 or later.\", \n"
 "                    \"PresetName\": \"Android\", \n"
 "                    \"Type\": 0, \n"
-"                    \"UsesPictureFilters\": 1, \n"
+"                    \"UsesPictureFilters\": true, \n"
 "                    \"UsesPictureSettings\": 1, \n"
-"                    \"VideoAvgBitrate\": \"2500\", \n"
+"                    \"VideoAvgBitrate\": 2500, \n"
 "                    \"VideoEncoder\": \"x264\", \n"
 "                    \"VideoFramerate\": \"30\", \n"
 "                    \"VideoFramerateMode\": \"pfr\", \n"
-"                    \"VideoGrayScale\": 0, \n"
+"                    \"VideoGrayScale\": false, \n"
 "                    \"VideoLevel\": \"3.0\", \n"
 "                    \"VideoOptionExtra\": \"\", \n"
 "                    \"VideoPreset\": \"medium\", \n"
@@ -562,49 +510,43 @@ const char hb_builtin_presets_json[] =
 "                    \"VideoQualitySlider\": 22.0, \n"
 "                    \"VideoQualityType\": 2, \n"
 "                    \"VideoTune\": \"\", \n"
-"                    \"VideoTurboTwoPass\": 0, \n"
-"                    \"VideoTwoPass\": 0, \n"
+"                    \"VideoTurboTwoPass\": false, \n"
+"                    \"VideoTwoPass\": false, \n"
 "                    \"x264Option\": \"\", \n"
-"                    \"x264UseAdvancedOptions\": 0\n"
+"                    \"x264UseAdvancedOptions\": false\n"
 "                }, \n"
 "                {\n"
-"                    \"AudioAllowAACPass\": 1, \n"
-"                    \"AudioAllowAC3Pass\": 1, \n"
-"                    \"AudioAllowDTSHDPass\": 1, \n"
-"                    \"AudioAllowDTSPass\": 1, \n"
-"                    \"AudioAllowMP3Pass\": 1, \n"
 "                    \"AudioEncoderFallback\": \"ac3\", \n"
 "                    \"AudioList\": [\n"
 "                        {\n"
-"                            \"AudioBitrate\": \"128\", \n"
+"                            \"AudioBitrate\": 128, \n"
 "                            \"AudioEncoder\": \"aac\", \n"
 "                            \"AudioMixdown\": \"dpl2\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }\n"
 "                    ], \n"
-"                    \"ChapterMarkers\": 0, \n"
-"                    \"Default\": 0, \n"
+"                    \"ChapterMarkers\": false, \n"
+"                    \"Default\": false, \n"
 "                    \"FileFormat\": \"mp4\", \n"
 "                    \"Folder\": false, \n"
-"                    \"Mp4HttpOptimize\": 0, \n"
-"                    \"Mp4iPodCompatible\": 0, \n"
-"                    \"PictureAutoCrop\": 1, \n"
+"                    \"Mp4HttpOptimize\": false, \n"
+"                    \"Mp4iPodCompatible\": false, \n"
+"                    \"PictureAutoCrop\": true, \n"
 "                    \"PictureBottomCrop\": 0, \n"
 "                    \"PictureDeblock\": 0, \n"
-"                    \"PictureDecomb\": 0, \n"
+"                    \"PictureDecomb\": \"off\", \n"
 "                    \"PictureDecombCustom\": \"\", \n"
-"                    \"PictureDecombDeinterlace\": 1, \n"
-"                    \"PictureDeinterlace\": 0, \n"
+"                    \"PictureDecombDeinterlace\": true, \n"
+"                    \"PictureDeinterlace\": \"off\", \n"
 "                    \"PictureDeinterlaceCustom\": \"\", \n"
 "                    \"PictureDenoiseCustom\": \"\", \n"
 "                    \"PictureDenoiseFilter\": \"off\", \n"
-"                    \"PictureDetelecine\": 0, \n"
+"                    \"PictureDetelecine\": \"off\", \n"
 "                    \"PictureDetelecineCustom\": \"\", \n"
 "                    \"PictureHeight\": 720, \n"
-"                    \"PictureKeepRatio\": 0, \n"
+"                    \"PictureKeepRatio\": true, \n"
 "                    \"PictureLeftCrop\": 0, \n"
 "                    \"PictureModulus\": 2, \n"
 "                    \"PicturePAR\": \"loose\", \n"
@@ -614,13 +556,13 @@ const char hb_builtin_presets_json[] =
 "                    \"PresetDescription\": \"HandBrake's preset for tablets running Android 2.3 or later.\", \n"
 "                    \"PresetName\": \"Android Tablet\", \n"
 "                    \"Type\": 0, \n"
-"                    \"UsesPictureFilters\": 1, \n"
+"                    \"UsesPictureFilters\": true, \n"
 "                    \"UsesPictureSettings\": 1, \n"
-"                    \"VideoAvgBitrate\": \"2500\", \n"
+"                    \"VideoAvgBitrate\": 2500, \n"
 "                    \"VideoEncoder\": \"x264\", \n"
 "                    \"VideoFramerate\": \"30\", \n"
 "                    \"VideoFramerateMode\": \"pfr\", \n"
-"                    \"VideoGrayScale\": 0, \n"
+"                    \"VideoGrayScale\": false, \n"
 "                    \"VideoLevel\": \"3.1\", \n"
 "                    \"VideoOptionExtra\": \"\", \n"
 "                    \"VideoPreset\": \"medium\", \n"
@@ -628,49 +570,43 @@ const char hb_builtin_presets_json[] =
 "                    \"VideoQualitySlider\": 22.0, \n"
 "                    \"VideoQualityType\": 2, \n"
 "                    \"VideoTune\": \"\", \n"
-"                    \"VideoTurboTwoPass\": 0, \n"
-"                    \"VideoTwoPass\": 0, \n"
+"                    \"VideoTurboTwoPass\": false, \n"
+"                    \"VideoTwoPass\": false, \n"
 "                    \"x264Option\": \"\", \n"
-"                    \"x264UseAdvancedOptions\": 0\n"
+"                    \"x264UseAdvancedOptions\": false\n"
 "                }, \n"
 "                {\n"
-"                    \"AudioAllowAACPass\": 1, \n"
-"                    \"AudioAllowAC3Pass\": 1, \n"
-"                    \"AudioAllowDTSHDPass\": 1, \n"
-"                    \"AudioAllowDTSPass\": 1, \n"
-"                    \"AudioAllowMP3Pass\": 1, \n"
 "                    \"AudioEncoderFallback\": \"ac3\", \n"
 "                    \"AudioList\": [\n"
 "                        {\n"
-"                            \"AudioBitrate\": \"128\", \n"
+"                            \"AudioBitrate\": 128, \n"
 "                            \"AudioEncoder\": \"aac\", \n"
 "                            \"AudioMixdown\": \"dpl2\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }\n"
 "                    ], \n"
-"                    \"ChapterMarkers\": 0, \n"
-"                    \"Default\": 0, \n"
+"                    \"ChapterMarkers\": false, \n"
+"                    \"Default\": false, \n"
 "                    \"FileFormat\": \"mp4\", \n"
 "                    \"Folder\": false, \n"
-"                    \"Mp4HttpOptimize\": 0, \n"
-"                    \"Mp4iPodCompatible\": 0, \n"
-"                    \"PictureAutoCrop\": 1, \n"
+"                    \"Mp4HttpOptimize\": false, \n"
+"                    \"Mp4iPodCompatible\": false, \n"
+"                    \"PictureAutoCrop\": true, \n"
 "                    \"PictureBottomCrop\": 0, \n"
 "                    \"PictureDeblock\": 0, \n"
-"                    \"PictureDecomb\": 0, \n"
+"                    \"PictureDecomb\": \"off\", \n"
 "                    \"PictureDecombCustom\": \"\", \n"
-"                    \"PictureDecombDeinterlace\": 1, \n"
-"                    \"PictureDeinterlace\": 0, \n"
+"                    \"PictureDecombDeinterlace\": true, \n"
+"                    \"PictureDeinterlace\": \"off\", \n"
 "                    \"PictureDeinterlaceCustom\": \"\", \n"
 "                    \"PictureDenoiseCustom\": \"\", \n"
 "                    \"PictureDenoiseFilter\": \"off\", \n"
-"                    \"PictureDetelecine\": 0, \n"
+"                    \"PictureDetelecine\": \"off\", \n"
 "                    \"PictureDetelecineCustom\": \"\", \n"
 "                    \"PictureHeight\": 720, \n"
-"                    \"PictureKeepRatio\": 1, \n"
+"                    \"PictureKeepRatio\": true, \n"
 "                    \"PictureLeftCrop\": 0, \n"
 "                    \"PictureModulus\": 2, \n"
 "                    \"PicturePAR\": \"off\", \n"
@@ -680,13 +616,13 @@ const char hb_builtin_presets_json[] =
 "                    \"PresetDescription\": \"HandBrake's preset for Windows Phone 8 devices\", \n"
 "                    \"PresetName\": \"Windows Phone 8\", \n"
 "                    \"Type\": 0, \n"
-"                    \"UsesPictureFilters\": 1, \n"
+"                    \"UsesPictureFilters\": true, \n"
 "                    \"UsesPictureSettings\": 1, \n"
-"                    \"VideoAvgBitrate\": \"2500\", \n"
+"                    \"VideoAvgBitrate\": 2500, \n"
 "                    \"VideoEncoder\": \"x264\", \n"
 "                    \"VideoFramerate\": \"30\", \n"
 "                    \"VideoFramerateMode\": \"pfr\", \n"
-"                    \"VideoGrayScale\": 0, \n"
+"                    \"VideoGrayScale\": false, \n"
 "                    \"VideoLevel\": \"3.1\", \n"
 "                    \"VideoOptionExtra\": \"\", \n"
 "                    \"VideoPreset\": \"medium\", \n"
@@ -694,13 +630,12 @@ const char hb_builtin_presets_json[] =
 "                    \"VideoQualitySlider\": 22.0, \n"
 "                    \"VideoQualityType\": 2, \n"
 "                    \"VideoTune\": \"\", \n"
-"                    \"VideoTurboTwoPass\": 0, \n"
-"                    \"VideoTwoPass\": 0, \n"
+"                    \"VideoTurboTwoPass\": false, \n"
+"                    \"VideoTwoPass\": false, \n"
 "                    \"x264Option\": \"\", \n"
-"                    \"x264UseAdvancedOptions\": 0\n"
+"                    \"x264UseAdvancedOptions\": false\n"
 "                }\n"
 "            ], \n"
-"            \"Default\": 0, \n"
 "            \"Folder\": true, \n"
 "            \"PresetName\": \"Devices\", \n"
 "            \"Type\": 0\n"
@@ -708,43 +643,37 @@ const char hb_builtin_presets_json[] =
 "        {\n"
 "            \"ChildrenArray\": [\n"
 "                {\n"
-"                    \"AudioAllowAACPass\": 1, \n"
-"                    \"AudioAllowAC3Pass\": 1, \n"
-"                    \"AudioAllowDTSHDPass\": 1, \n"
-"                    \"AudioAllowDTSPass\": 1, \n"
-"                    \"AudioAllowMP3Pass\": 1, \n"
 "                    \"AudioEncoderFallback\": \"ac3\", \n"
 "                    \"AudioList\": [\n"
 "                        {\n"
-"                            \"AudioBitrate\": \"160\", \n"
+"                            \"AudioBitrate\": 160, \n"
 "                            \"AudioEncoder\": \"aac\", \n"
 "                            \"AudioMixdown\": \"dpl2\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }\n"
 "                    ], \n"
-"                    \"ChapterMarkers\": 1, \n"
-"                    \"Default\": 1, \n"
+"                    \"ChapterMarkers\": true, \n"
+"                    \"Default\": true, \n"
 "                    \"FileFormat\": \"mp4\", \n"
 "                    \"Folder\": false, \n"
-"                    \"Mp4HttpOptimize\": 0, \n"
-"                    \"Mp4iPodCompatible\": 0, \n"
-"                    \"PictureAutoCrop\": 1, \n"
+"                    \"Mp4HttpOptimize\": false, \n"
+"                    \"Mp4iPodCompatible\": false, \n"
+"                    \"PictureAutoCrop\": true, \n"
 "                    \"PictureBottomCrop\": 0, \n"
 "                    \"PictureDeblock\": 0, \n"
-"                    \"PictureDecomb\": 0, \n"
+"                    \"PictureDecomb\": \"off\", \n"
 "                    \"PictureDecombCustom\": \"\", \n"
-"                    \"PictureDecombDeinterlace\": 1, \n"
-"                    \"PictureDeinterlace\": 0, \n"
+"                    \"PictureDecombDeinterlace\": true, \n"
+"                    \"PictureDeinterlace\": \"off\", \n"
 "                    \"PictureDeinterlaceCustom\": \"\", \n"
 "                    \"PictureDenoiseCustom\": \"\", \n"
 "                    \"PictureDenoiseFilter\": \"off\", \n"
-"                    \"PictureDetelecine\": 0, \n"
+"                    \"PictureDetelecine\": \"off\", \n"
 "                    \"PictureDetelecineCustom\": \"\", \n"
 "                    \"PictureHeight\": 0, \n"
-"                    \"PictureKeepRatio\": 0, \n"
+"                    \"PictureKeepRatio\": true, \n"
 "                    \"PictureLeftCrop\": 0, \n"
 "                    \"PictureModulus\": 2, \n"
 "                    \"PicturePAR\": \"loose\", \n"
@@ -754,13 +683,13 @@ const char hb_builtin_presets_json[] =
 "                    \"PresetDescription\": \"HandBrake's normal, default settings.\", \n"
 "                    \"PresetName\": \"Normal\", \n"
 "                    \"Type\": 0, \n"
-"                    \"UsesPictureFilters\": 1, \n"
+"                    \"UsesPictureFilters\": true, \n"
 "                    \"UsesPictureSettings\": 1, \n"
-"                    \"VideoAvgBitrate\": \"2500\", \n"
+"                    \"VideoAvgBitrate\": 2500, \n"
 "                    \"VideoEncoder\": \"x264\", \n"
 "                    \"VideoFramerate\": \"auto\", \n"
 "                    \"VideoFramerateMode\": \"vfr\", \n"
-"                    \"VideoGrayScale\": 0, \n"
+"                    \"VideoGrayScale\": false, \n"
 "                    \"VideoLevel\": \"4.0\", \n"
 "                    \"VideoOptionExtra\": \"\", \n"
 "                    \"VideoPreset\": \"veryfast\", \n"
@@ -768,58 +697,51 @@ const char hb_builtin_presets_json[] =
 "                    \"VideoQualitySlider\": 20.0, \n"
 "                    \"VideoQualityType\": 2, \n"
 "                    \"VideoTune\": \"\", \n"
-"                    \"VideoTurboTwoPass\": 0, \n"
-"                    \"VideoTwoPass\": 0, \n"
+"                    \"VideoTurboTwoPass\": false, \n"
+"                    \"VideoTwoPass\": false, \n"
 "                    \"x264Option\": \"\", \n"
-"                    \"x264UseAdvancedOptions\": 0\n"
+"                    \"x264UseAdvancedOptions\": false\n"
 "                }, \n"
 "                {\n"
-"                    \"AudioAllowAACPass\": 1, \n"
-"                    \"AudioAllowAC3Pass\": 1, \n"
-"                    \"AudioAllowDTSHDPass\": 1, \n"
-"                    \"AudioAllowDTSPass\": 1, \n"
-"                    \"AudioAllowMP3Pass\": 1, \n"
 "                    \"AudioEncoderFallback\": \"ac3\", \n"
 "                    \"AudioList\": [\n"
 "                        {\n"
-"                            \"AudioBitrate\": \"160\", \n"
+"                            \"AudioBitrate\": 160, \n"
 "                            \"AudioEncoder\": \"aac\", \n"
 "                            \"AudioMixdown\": \"dpl2\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }, \n"
 "                        {\n"
-"                            \"AudioBitrate\": \"160\", \n"
+"                            \"AudioBitrate\": 160, \n"
 "                            \"AudioEncoder\": \"copy:ac3\", \n"
 "                            \"AudioMixdown\": \"none\", \n"
 "                            \"AudioSamplerate\": \"auto\", \n"
-"                            \"AudioTrack\": 1, \n"
 "                            \"AudioTrackDRCSlider\": 0.0, \n"
 "                            \"AudioTrackGainSlider\": 0.0\n"
 "                        }\n"
 "                    ], \n"
-"                    \"ChapterMarkers\": 1, \n"
-"                    \"Default\": 0, \n"
+"                    \"ChapterMarkers\": true, \n"
+"                    \"Default\": false, \n"
 "                    \"FileFormat\": \"mp4\", \n"
 "                    \"Folder\": false, \n"
-"                    \"Mp4HttpOptimize\": 0, \n"
-"                    \"Mp4iPodCompatible\": 0, \n"
-"                    \"PictureAutoCrop\": 1, \n"
+"                    \"Mp4HttpOptimize\": false, \n"
+"                    \"Mp4iPodCompatible\": false, \n"
+"                    \"PictureAutoCrop\": true, \n"
 "                    \"PictureBottomCrop\": 0, \n"
 "                    \"PictureDeblock\": 0, \n"
-"                    \"PictureDecomb\": 2, \n"
+"                    \"PictureDecomb\": \"default\", \n"
 "                    \"PictureDecombCustom\": \"\", \n"
-"                    \"PictureDecombDeinterlace\": 1, \n"
-"                    \"PictureDeinterlace\": 0, \n"
+"                    \"PictureDecombDeinterlace\": true, \n"
+"                    \"PictureDeinterlace\": \"off\", \n"
 "                    \"PictureDeinterlaceCustom\": \"\", \n"
 "                    \"PictureDenoiseCustom\": \"\", \n"
 "                    \"PictureDenoiseFilter\": \"off\", \n"
-"                    \"PictureDetelecine\": 0, \n"
+"                    \"PictureDetelecine\": \"off\", \n"
 "                    \"PictureDetelecineCustom\": \"\", \n"
 "                    \"PictureHeight\": 0, \n"
-"                    \"PictureKeepRatio\": 0, \n"
+"                    \"PictureKeepRatio\": true, \n"
 "                    \"PictureLeftCrop\": 0, \n"
 "                    \"PictureModulus\": 2, \n"
 "                    \"PicturePAR\": \"loose\", \n"
@@ -829,13 +751,13 @@ const char hb_builtin_presets_json[] =
 "                    \"PresetDescription\": \"HandBrake's general-purpose preset for High Profile H.264 video.\", \n"
 "                    \"PresetName\": \"High Profile\", \n"
 "                    \"Type\": 0, \n"
-"                    \"UsesPictureFilters\": 1, \n"
+"                    \"UsesPictureFilters\": true, \n"
 "                    \"UsesPictureSettings\": 1, \n"
-"                    \"VideoAvgBitrate\": \"2500\", \n"
+"                    \"VideoAvgBitrate\": 2500, \n"
 "                    \"VideoEncoder\": \"x264\", \n"
 "                    \"VideoFramerate\": \"auto\", \n"
 "                    \"VideoFramerateMode\": \"vfr\", \n"
-"                    \"VideoGrayScale\": 0, \n"
+"                    \"VideoGrayScale\": false, \n"
 "                    \"VideoLevel\": \"4.1\", \n"
 "                    \"VideoOptionExtra\": \"\", \n"
 "                    \"VideoPreset\": \"medium\", \n"
@@ -843,13 +765,12 @@ const char hb_builtin_presets_json[] =
 "                    \"VideoQualitySlider\": 20.0, \n"
 "                    \"VideoQualityType\": 2, \n"
 "                    \"VideoTune\": \"\", \n"
-"                    \"VideoTurboTwoPass\": 0, \n"
-"                    \"VideoTwoPass\": 0, \n"
+"                    \"VideoTurboTwoPass\": false, \n"
+"                    \"VideoTwoPass\": false, \n"
 "                    \"x264Option\": \"\", \n"
-"                    \"x264UseAdvancedOptions\": 0\n"
+"                    \"x264UseAdvancedOptions\": false\n"
 "                }\n"
 "            ], \n"
-"            \"Default\": 0, \n"
 "            \"Folder\": true, \n"
 "            \"PresetName\": \"Regular\", \n"
 "            \"Type\": 0\n"
@@ -857,14 +778,6 @@ const char hb_builtin_presets_json[] =
 "    ], \n"
 "    \"PresetTemplate\": {\n"
 "        \"Preset\": {\n"
-"            \"AudioAllowAACPass\": false, \n"
-"            \"AudioAllowAC3Pass\": true, \n"
-"            \"AudioAllowDTSHDPass\": false, \n"
-"            \"AudioAllowDTSPass\": false, \n"
-"            \"AudioAllowEAC3Pass\": false, \n"
-"            \"AudioAllowFLACPass\": false, \n"
-"            \"AudioAllowMP3Pass\": false, \n"
-"            \"AudioAllowTRUEHDPass\": false, \n"
 "            \"AudioCopyMask\": [], \n"
 "            \"AudioEncoderFallback\": \"ac3\", \n"
 "            \"AudioLanguageList\": [\n"
@@ -872,7 +785,7 @@ const char hb_builtin_presets_json[] =
 "            ], \n"
 "            \"AudioList\": [\n"
 "                {\n"
-"                    \"AudioBitrate\": \"192\", \n"
+"                    \"AudioBitrate\": 192, \n"
 "                    \"AudioCompressionLevel\": -1.0, \n"
 "                    \"AudioDitherMethod\": \"auto\", \n"
 "                    \"AudioEncoder\": \"copy:ac3\", \n"
@@ -888,9 +801,11 @@ const char hb_builtin_presets_json[] =
 "            \"AudioSecondaryEncoderMode\": true, \n"
 "            \"AudioTrackSelectionBehavior\": \"first\", \n"
 "            \"ChapterMarkers\": true, \n"
+"            \"ChildrenArray\": [], \n"
 "            \"Default\": false, \n"
 "            \"FileFormat\": \"mp4\", \n"
 "            \"Folder\": false, \n"
+"            \"FolderOpen\": false, \n"
 "            \"Mp4HttpOptimize\": false, \n"
 "            \"Mp4iPodCompatible\": false, \n"
 "            \"PictureAutoCrop\": true, \n"
index 215455cda56504da3dfd1035d584386b66b0f12b..a838c943d3df35b34ee88d93693ab264ca4cb292 100644 (file)
@@ -20,6 +20,7 @@ extern "C" {
 #include "hb_dict.h"
 #include "hb_json.h"
 #include "preset.h"
+#include "plist.h"
 #include "param.h"
 
 /* hb_init()
index 866803f58833cc0b6a46a6f056e5eefbe79dfe26..634b25b091d4df7d51f33aa306f49d735a91f969 100644 (file)
@@ -32,10 +32,9 @@ hb_value_t * hb_value_dup(const hb_value_t *value)
     return json_deep_copy(value);
 }
 
-void hb_value_incref(hb_value_t *value)
+hb_value_t* hb_value_incref(hb_value_t *value)
 {
-    if (value == NULL) return;
-    json_incref(value);
+    return json_incref(value);
 }
 
 void hb_value_decref(hb_value_t *value)
@@ -89,11 +88,6 @@ hb_value_t * hb_value_read_json(const char *path)
 {
     json_error_t error;
     hb_value_t *val = json_load_file(path, 0, &error);
-    if (val == NULL)
-    {
-        hb_error("hb_value_read_json: Failed, path (%s), error %s",
-                 path, error.text);
-    }
     return val;
 }
 
@@ -484,7 +478,7 @@ hb_value_t * hb_dict_iter_value(const hb_dict_iter_t iter)
 }
 
 int
-hb_dict_iter_next_ex(hb_dict_t *dict, hb_dict_iter_t *iter,
+hb_dict_iter_next_ex(const hb_dict_t *dict, hb_dict_iter_t *iter,
                      const char **key, hb_value_t **val)
 {
     if (*iter == NULL)
@@ -493,7 +487,7 @@ hb_dict_iter_next_ex(hb_dict_t *dict, hb_dict_iter_t *iter,
         *key = json_object_iter_key(*iter);
     if (val != NULL)
         *val = json_object_iter_value(*iter);
-    *iter = json_object_iter_next(dict, *iter);
+    *iter = json_object_iter_next((hb_dict_t*)dict, *iter);
     return 1;
 }
 
index 2a4f71cfe09dd0829728b0c9a3583145abc495dd..243d8885d62dd8335e75f0b0db28424df0c58648 100644 (file)
@@ -52,7 +52,8 @@ hb_value_t *      hb_dict_get(const hb_dict_t * dict, const char * key);
  */
 hb_dict_iter_t    hb_dict_iter_init(const hb_dict_t *dict);
 hb_dict_iter_t    hb_dict_iter_next(const hb_dict_t *dict, hb_dict_iter_t iter);
-int               hb_dict_iter_next_ex(hb_dict_t *dict, hb_dict_iter_t *iter,
+int               hb_dict_iter_next_ex(const hb_dict_t *dict,
+                                       hb_dict_iter_t *iter,
                                        const char **key, hb_value_t **val);
 /* get key from iter */
 const char *      hb_dict_iter_key(const hb_dict_iter_t iter);
@@ -86,7 +87,7 @@ size_t             hb_value_array_len(const hb_value_array_t *array);
 int          hb_value_type(const hb_value_t *value);
 int          hb_value_is_number(const hb_value_t *value);
 hb_value_t * hb_value_dup(const hb_value_t *value);
-void         hb_value_incref(hb_value_t *value);
+hb_value_t * hb_value_incref(hb_value_t *value);
 void         hb_value_decref(hb_value_t *value);
 void         hb_value_free(hb_value_t **value);
 
index f610145377d34defd049cb07e351eb79e7eae570..bc6c9d1bd8a9b1eeb7c4eaaa310fff36eacb5364 100644 (file)
@@ -1,3 +1,12 @@
+/* plist.c
+
+   Copyright (c) 2003-2015 HandBrake Team
+   This file is part of the HandBrake source code
+   Homepage: <http://handbrake.fr/>.
+   It may be used under the terms of the GNU General Public License v2.
+   For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <fcntl.h>
@@ -454,10 +463,18 @@ text_data(
 {
     char *text = (char*)xtext;
     parse_data_t *pd = (parse_data_t*)ud;
-    if (pd->value) free(pd->value);
-    pd->value = malloc(len + 1);
-    strncpy(pd->value, text, len);
-    pd->value[len] = 0;
+
+    int pos = 0;
+    if (pd->value != NULL)
+    {
+        pos = strlen(pd->value);
+    }
+    char *tmp = realloc(pd->value, pos + len + 1);
+    if (tmp == NULL)
+        return;
+    pd->value = tmp;
+    strncpy(pd->value + pos, text, len);
+    pd->value[pos + len] = 0;
 }
 
 static void
index 901aeb4b06328be1f9c412da7fd6468a103eb4b5..47a5e5e089b242f464877415424066477c77321d 100644 (file)
@@ -1,3 +1,12 @@
+/* plist.h
+
+   Copyright (c) 2003-2015 HandBrake Team
+   This file is part of the HandBrake source code
+   Homepage: <http://handbrake.fr/>.
+   It may be used under the terms of the GNU General Public License v2.
+   For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
+ */
+
 #if !defined(_HB_PLIST_H_)
 #define _HB_PLIST_H_
 
index 97a647214a9e1bbe3f4a2f49c9de1d6423345826..8a3f59059771324edef44b03300268c181781315 100644 (file)
@@ -1,4 +1,4 @@
-/* hb_preset.c
+/* preset.c
 
    Copyright (c) 2003-2015 HandBrake Team
    This file is part of the HandBrake source code
@@ -28,9 +28,254 @@ int hb_preset_version_micro;
 
 static hb_value_t *hb_preset_template = NULL;
 static hb_value_t *hb_presets = NULL;
-static hb_value_t *hb_presets_custom = NULL;
 static hb_value_t *hb_presets_builtin = NULL;
 
+static void preset_clean(hb_value_t *preset, hb_value_t *template);
+static void preset_import(hb_value_t *preset, int major, int minor, int micro);
+
+enum
+{
+    PRESET_DO_SUCCESS,
+    PRESET_DO_FAIL,
+    PRESET_DO_PARTIAL,
+    PRESET_DO_NEXT,
+    PRESET_DO_SKIP,
+    PRESET_DO_DELETE,
+    PRESET_DO_DONE
+};
+
+typedef struct
+{
+    hb_preset_index_t path;
+} preset_do_context_t;
+
+typedef struct
+{
+    preset_do_context_t  do_ctx;
+    hb_value_t          *template;
+} preset_clean_context_t;
+
+typedef struct
+{
+    preset_do_context_t  do_ctx;
+    int                  major;
+    int                  minor;
+    int                  micro;
+} preset_import_context_t;
+
+typedef struct
+{
+    preset_do_context_t  do_ctx;
+    const char          *name;
+    int                  recurse;
+    int                  last_match_idx;
+} preset_search_context_t;
+
+typedef int (*preset_do_f)(hb_value_t *preset, preset_do_context_t *ctx);
+
+static int preset_cmp_idx(hb_value_t *preset, int idx, const char *name)
+{
+    const char *next, *preset_name;
+    int  ii, len;
+
+    // Strip leading '/'
+    if (name[0] == '/')
+        name++;
+
+    // Find the part of the "name" path we want to match.
+    for (ii = 0; ii < idx; ii++)
+    {
+        next = strchr(name, '/');
+        if (next == NULL)
+            return PRESET_DO_SKIP;
+        next++;
+        name = next;
+    }
+
+    // Find the end of the part we want to match
+    next = strchr(name, '/');
+    if (next != NULL)
+        len = next - name;
+    else
+        len = strlen(name);
+    if (len <= 0)
+        return PRESET_DO_SKIP;
+
+    preset_name = hb_value_get_string(hb_dict_get(preset, "PresetName"));
+    if (strlen(preset_name) > len)
+        len = strlen(preset_name);
+
+    // If match found and it's the last component of the "name", success!
+    if (!strncmp(name, preset_name, len))
+    {
+        if (name[len] == 0)
+            return PRESET_DO_SUCCESS;
+        else
+            return PRESET_DO_PARTIAL;
+    }
+    return PRESET_DO_NEXT;
+}
+
+static int do_preset_search(hb_value_t *preset, preset_do_context_t *do_ctx)
+{
+    preset_search_context_t *ctx = (preset_search_context_t*)do_ctx;
+    int idx, result;
+
+    idx = ctx->do_ctx.path.depth - 1;
+    if (ctx->last_match_idx >= 0 && idx > ctx->last_match_idx)
+    {
+        // If there was a previous partial match, try to continue the match
+        idx -= ctx->last_match_idx;
+    }
+
+    result = preset_cmp_idx(preset, idx, ctx->name);
+    if (ctx->recurse && result == PRESET_DO_SKIP)
+    {
+        result = preset_cmp_idx(preset, 0, ctx->name);
+        ctx->last_match_idx = idx;
+    }
+    if (result == PRESET_DO_PARTIAL)
+    {
+        return PRESET_DO_NEXT;
+    }
+    else
+    {
+        ctx->last_match_idx = -1;
+    }
+
+    return result;
+}
+
+static int do_preset_import(hb_value_t *preset, preset_do_context_t *do_ctx)
+{
+    preset_import_context_t *ctx = (preset_import_context_t*)do_ctx;
+    preset_import(preset, ctx->major, ctx->minor, ctx->micro);
+    return PRESET_DO_NEXT;
+}
+
+static int do_preset_clean(hb_value_t *preset, preset_do_context_t *do_ctx)
+{
+    preset_clean_context_t *ctx = (preset_clean_context_t*)do_ctx;
+    preset_clean(preset, ctx->template);
+    return PRESET_DO_NEXT;
+}
+
+static int do_delete_builtin(hb_value_t *preset, preset_do_context_t *ctx)
+{
+    if (hb_value_get_int(hb_dict_get(preset, "Type")) == 0)
+        return PRESET_DO_DELETE;
+    return PRESET_DO_NEXT;
+}
+
+static int do_clear_default(hb_value_t *preset, preset_do_context_t *ctx)
+{
+    hb_dict_set(preset, "Default", hb_value_bool(0));
+    return PRESET_DO_NEXT;
+}
+
+static int do_find_default(hb_value_t *preset, preset_do_context_t *ctx)
+{
+    if (!hb_value_get_bool(hb_dict_get(preset, "Folder")) &&
+        hb_value_get_bool(hb_dict_get(preset, "Default")))
+    {
+        return PRESET_DO_SUCCESS;
+    }
+    return PRESET_DO_NEXT;
+}
+
+static int presets_do(preset_do_f do_func, hb_value_t *preset,
+                      preset_do_context_t *ctx)
+{
+    int result;
+    hb_value_t *next;
+
+    if (hb_value_type(preset) == HB_VALUE_TYPE_ARRAY)
+    {
+        // An array of presets, clean each one
+        int ii;
+
+        for (ii = 0; ii < hb_value_array_len(preset); )
+        {
+            ctx->path.index[ctx->path.depth-1] = ii;
+            next = hb_value_array_get(preset, ii);
+            result = presets_do(do_func, next, ctx);
+            if (result == PRESET_DO_DELETE)
+            {
+                hb_value_array_remove(preset, ii);
+                continue;
+            }
+            ii++;
+            if (result != PRESET_DO_NEXT)
+                return result;
+        }
+        return PRESET_DO_NEXT;
+    }
+    else if (hb_value_type(preset) == HB_VALUE_TYPE_DICT &&
+             hb_dict_get(preset, "VersionMajor") != NULL)
+    {
+        // A packaged preset list
+        next = hb_dict_get(preset, "PresetList");
+        return presets_do(do_func, next, ctx);
+    }
+    else if (hb_value_type(preset) == HB_VALUE_TYPE_DICT &&
+             hb_value_get_bool(hb_dict_get(preset, "Folder")))
+    {
+        // Perform do_func on the folder...
+        result = do_func(preset, ctx);
+        if (result != PRESET_DO_NEXT)
+            return result;
+
+        // Then perform preset action on the children of the folder
+        ctx->path.depth++;
+        next = hb_dict_get(preset, "ChildrenArray");
+        result = presets_do(do_func, next, ctx);
+        if (result == PRESET_DO_SUCCESS)
+            return result;
+        ctx->path.depth--;
+        return result;
+    }
+    else if (hb_value_type(preset) == HB_VALUE_TYPE_DICT &&
+             hb_dict_get(preset, "PresetName") != NULL)
+    {
+        // An individual, non-folder, preset
+        return do_func(preset, ctx);
+    }
+    else
+    {
+        hb_error("Error: invalid preset format in presets_do()");
+        return PRESET_DO_NEXT;
+    }
+    return PRESET_DO_DONE;
+}
+
+hb_preset_index_t* hb_preset_index_init(const int *index, int depth)
+{
+    hb_preset_index_t *path;
+    path = malloc(sizeof(hb_preset_index_t));
+    path->depth = depth;
+    if (index != NULL)
+        memcpy(path->index, index, depth * sizeof(int));
+    return path;
+}
+
+hb_preset_index_t* hb_preset_index_dup(const hb_preset_index_t *path)
+{
+    if (path == NULL)
+        return NULL;
+    return hb_preset_index_init(path->index, path->depth);
+}
+
+void hb_preset_index_append(hb_preset_index_t *dst,
+                            const hb_preset_index_t *src)
+{
+    int ii;
+    for (ii = 0; ii < src->depth &&
+                 dst->depth < HB_MAX_PRESET_FOLDER_DEPTH; ii++, dst->depth++)
+    {
+        dst->index[dst->depth] = src->index[ii];
+    }
+}
+
 static int get_job_mux(hb_dict_t *job_dict)
 {
     int mux;
@@ -59,13 +304,14 @@ static int get_job_mux(hb_dict_t *job_dict)
     return mux;
 }
 
-static int get_audio_copy_mask(hb_dict_t * preset)
+static int get_audio_copy_mask(const hb_dict_t * preset)
 {
     int mask = HB_ACODEC_PASS_FLAG;
 
     hb_value_array_t *copy_mask_array = hb_dict_get(preset, "AudioCopyMask");
     if (copy_mask_array != NULL)
     {
+        mask = HB_ACODEC_PASS_FLAG;
         int count = hb_value_array_len(copy_mask_array);
         int ii;
         for (ii = 0; ii < count; ii++)
@@ -99,25 +345,6 @@ static int get_audio_copy_mask(hb_dict_t * preset)
             mask |= codec;
         }
     }
-    else
-    {
-        mask |= hb_value_get_bool(hb_dict_get(preset, "AudioAllowMP3Pass")) *
-                HB_ACODEC_MP3;
-        mask |= hb_value_get_bool(hb_dict_get(preset, "AudioAllowAACPass")) *
-                HB_ACODEC_FFAAC;
-        mask |= hb_value_get_bool(hb_dict_get(preset, "AudioAllowAC3Pass")) *
-                HB_ACODEC_AC3;
-        mask |= hb_value_get_bool(hb_dict_get(preset, "AudioAllowDTSPass")) *
-                HB_ACODEC_DCA;
-        mask |= hb_value_get_bool(hb_dict_get(preset, "AudioAllowDTSHDPass")) *
-                HB_ACODEC_DCA_HD;
-        mask |= hb_value_get_bool(hb_dict_get(preset, "AudioAllowEAC3Pass")) *
-                HB_ACODEC_FFEAC3;
-        mask |= hb_value_get_bool(hb_dict_get(preset, "AudioAllowFLACPass")) *
-                HB_ACODEC_FFFLAC;
-        mask |= hb_value_get_bool(hb_dict_get(preset, "AudioAllowTRUEHDPass")) *
-                HB_ACODEC_FFTRUEHD;
-    }
     return mask;
 }
 
@@ -158,7 +385,7 @@ static int find_audio_track(const hb_title_t *title,
     return -1;
 }
 
-static int validate_audio_encoders(hb_dict_t *preset)
+static int validate_audio_encoders(const hb_dict_t *preset)
 {
     hb_value_array_t * encoder_list = hb_dict_get(preset, "AudioList");
     int count = hb_value_array_len(encoder_list);
@@ -264,7 +491,7 @@ static int sanitize_audio_codec(int in_codec, int out_codec,
     return codec;
 }
 
-static void add_audio_for_lang(hb_value_array_t *list, hb_dict_t *preset,
+static void add_audio_for_lang(hb_value_array_t *list, const hb_dict_t *preset,
                                hb_title_t *title, int mux, int copy_mask,
                                int fallback, const char *lang,
                                int behavior, int mode, hb_dict_t *track_dict)
@@ -383,7 +610,7 @@ static void add_audio_for_lang(hb_value_array_t *list, hb_dict_t *preset,
 // This function assumes that Mux has already been initialized in
 // the job_dict
 int hb_preset_job_add_audio(hb_handle_t *h, int title_index,
-                            hb_dict_t *preset, hb_dict_t *job_dict)
+                            const hb_dict_t *preset, hb_dict_t *job_dict)
 {
     hb_title_t *title = hb_find_title_by_index(h, title_index);
     if (title == NULL)
@@ -557,7 +784,7 @@ static void add_subtitle_for_lang(hb_value_array_t *list, hb_title_t *title,
 // This function assumes that the AudioList and Mux have already been
 // initialized in the job_dict
 int hb_preset_job_add_subtitles(hb_handle_t *h, int title_index,
-                                hb_dict_t *preset, hb_dict_t *job_dict)
+                                const hb_dict_t *preset, hb_dict_t *job_dict)
 {
     hb_title_t *title = hb_find_title_by_index(h, title_index);
     if (title == NULL)
@@ -812,7 +1039,8 @@ static int get_video_framerate(hb_value_t *rate_value)
  *                        in json representation of a title.
  * @param preset        - Preset to initialize job with
  */
-hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index, hb_dict_t *preset)
+hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
+                              const hb_dict_t *preset)
 {
     hb_title_t *title = hb_find_title_by_index(h, title_index);
     if (title == NULL)
@@ -1433,6 +1661,8 @@ dict_clean(hb_value_t *dict, hb_value_t *template)
     if (val != NULL)
         preset_name = hb_value_get_string(val);
 
+    // Remove keys that are not in the template and translate compatible
+    // data types to the types used in the template.
     for (iter = hb_dict_iter_init(tmp);
          iter != HB_DICT_ITER_DONE;
          iter = hb_dict_iter_next(tmp, iter))
@@ -1506,6 +1736,28 @@ dict_clean(hb_value_t *dict, hb_value_t *template)
         }
     }
     hb_value_free(&tmp);
+
+    if (!hb_value_get_bool(hb_dict_get(dict, "Folder")))
+    {
+        // Add key/value pairs that are in the template but not in the dict.
+        for (iter = hb_dict_iter_init(template);
+             iter != HB_DICT_ITER_DONE;
+             iter = hb_dict_iter_next(template, iter))
+        {
+            key          = hb_dict_iter_key(iter);
+            template_val = hb_dict_iter_value(iter);
+
+            if (hb_value_type(template_val) != HB_VALUE_TYPE_ARRAY &&
+                hb_value_type(template_val) != HB_VALUE_TYPE_DICT)
+            {
+                val = hb_dict_get(dict, key);
+                if (val == NULL)
+                {
+                    hb_dict_set(dict, key, hb_value_dup(template_val));
+                }
+            }
+        }
+    }
 }
 
 static void preset_clean(hb_value_t *preset, hb_value_t *template)
@@ -1538,6 +1790,11 @@ static void preset_clean(hb_value_t *preset, hb_value_t *template)
         val = hb_value_string(mux);
         hb_dict_set(preset, "FileFormat", val);
     }
+    else
+    {
+        const hb_container_t *c = hb_container_get_next(NULL);
+        muxer = c->format;
+    }
     val = hb_dict_get(preset, "VideoEncoder");
     if (val != NULL)
     {
@@ -1564,10 +1821,13 @@ static void preset_clean(hb_value_t *preset, hb_value_t *template)
             int fr = hb_video_framerate_get_from_name(s);
             if (fr < 0)
             {
+                if (strcasecmp(s, "same as source"))
+                {
+                    hb_error("Preset %s: Invalid video framerate (%s)",
+                             preset_name, s);
+                }
                 val = hb_value_string("auto");
                 hb_dict_set(preset, "VideoFramerate", val);
-                hb_error("Preset %s: Invalid video framerate (%s)",
-                         preset_name, s);
             }
         }
     }
@@ -1609,7 +1869,7 @@ static void preset_clean(hb_value_t *preset, hb_value_t *template)
             }
             enc = hb_audio_encoder_get_short_name(acodec);
             val = hb_value_string(enc);
-            hb_dict_set(preset, "AudioEncoder", val);
+            hb_dict_set(adict, "AudioEncoder", val);
         }
         val = hb_dict_get(adict, "AudioSamplerate");
         if (val != NULL)
@@ -1618,13 +1878,13 @@ static void preset_clean(hb_value_t *preset, hb_value_t *template)
             s = hb_value_get_string(val);
             if (strcasecmp(s, "auto"))
             {
-                int sr = hb_video_framerate_get_from_name(s);
+                int sr = hb_audio_samplerate_get_from_name(s);
                 if (sr < 0)
                 {
-                    val = hb_value_string("auto");
-                    hb_dict_set(preset, "AudioSamplerate", val);
                     hb_error("Preset %s: Invalid audio samplerate (%s)",
                              preset_name, s);
+                    val = hb_value_string("auto");
+                    hb_dict_set(adict, "AudioSamplerate", val);
                 }
             }
         }
@@ -1650,57 +1910,320 @@ static void preset_clean(hb_value_t *preset, hb_value_t *template)
 
 static void presets_clean(hb_value_t *presets, hb_value_t *template)
 {
-    if (hb_value_type(presets) == HB_VALUE_TYPE_ARRAY)
+    preset_clean_context_t ctx;
+    ctx.do_ctx.path.depth = 1;
+    ctx.template = template;
+    presets_do(do_preset_clean, presets, (preset_do_context_t*)&ctx);
+}
+
+void hb_presets_clean(hb_value_t *preset)
+{
+    presets_clean(preset, hb_preset_template);
+}
+
+static const char* import_indexed_filter(int filter_id, int index)
+{
+    hb_filter_param_t *filter_presets;
+    filter_presets = hb_filter_param_get_presets(filter_id);
+
+    int ii;
+    for (ii = 0; filter_presets[ii].name != NULL; ii++)
     {
-        // An array of presets, clean each one
-        int ii, count;
-        count = hb_value_array_len(presets);
-        for (ii = 0; ii < count; ii++)
+        if (filter_presets[ii].index == index)
+            break;
+    }
+    return filter_presets[ii].short_name;
+}
+
+static void import_decomb(hb_value_t *preset)
+{
+    hb_value_t *val = hb_dict_get(preset, "PictureDecomb");
+    if (hb_value_is_number(val))
+    {
+        const char *s;
+        int index = hb_value_get_int(val);
+        s = import_indexed_filter(HB_FILTER_DECOMB, index);
+        if (s != NULL)
         {
-            hb_value_t *preset = hb_value_array_get(presets, ii);
-            preset_clean(preset, template);
+            hb_dict_set(preset, "PictureDecomb", hb_value_string(s));
+        }
+        else
+        {
+            hb_error("Invalid decomb index %d", index);
+            hb_dict_set(preset, "PictureDecomb", hb_value_string("off"));
         }
     }
-    else if (hb_value_type(presets) == HB_VALUE_TYPE_DICT &&
-             hb_dict_get(presets, "VersionMajor") != NULL)
+}
+
+static void import_deint(hb_value_t *preset)
+{
+    hb_value_t *val = hb_dict_get(preset, "PictureDeinterlace");
+    if (hb_value_is_number(val))
     {
-        // A packaged preset list
-        hb_value_t *list = hb_dict_get(presets, "PresetList");
-        presets_clean(list, template);
+        const char *s;
+        int index = hb_value_get_int(val);
+        s = import_indexed_filter(HB_FILTER_DEINTERLACE, index);
+        if (s != NULL)
+        {
+            hb_dict_set(preset, "PictureDeinterlace", hb_value_string(s));
+        }
+        else
+        {
+            hb_error("Invalid deinterlace index %d", index);
+            hb_dict_set(preset, "PictureDeinterlace", hb_value_string("off"));
+        }
+    }
+}
+
+static void import_detel(hb_value_t *preset)
+{
+    hb_value_t *val = hb_dict_get(preset, "PictureDetelecine");
+    if (hb_value_is_number(val))
+    {
+        const char *s;
+        int index = hb_value_get_int(val);
+        s = import_indexed_filter(HB_FILTER_DETELECINE, index);
+        if (s != NULL)
+        {
+            hb_dict_set(preset, "PictureDetelecine", hb_value_string(s));
+        }
+        else
+        {
+            hb_error("Invalid detelecine index %d", index);
+            hb_dict_set(preset, "PictureDetelecine", hb_value_string("off"));
+        }
+    }
+}
+
+static void import_denoise(hb_value_t *preset)
+{
+    hb_value_t *val = hb_dict_get(preset, "PictureDenoise");
+    if (hb_value_is_number(val))
+    {
+        const char *s;
+        int index = hb_value_get_int(val);
+        s = import_indexed_filter(HB_FILTER_HQDN3D, index);
+        if (s != NULL)
+        {
+            hb_dict_set(preset, "PictureDenoiseFilter",
+                        hb_value_string("hqdn3d"));
+            hb_dict_set(preset, "PictureDenoisePreset", hb_value_string(s));
+        }
+        else
+        {
+            if (index != 0)
+                hb_error("Invalid denoise index %d", index);
+            hb_dict_set(preset, "PictureDenoiseFilter", hb_value_string("off"));
+        }
     }
-    else if (hb_value_type(presets) == HB_VALUE_TYPE_DICT &&
-             hb_dict_get(presets, "PresetName") != NULL)
+}
+
+static void import_pic(hb_value_t *preset)
+{
+    if (hb_value_get_bool(hb_dict_get(preset, "UsesMaxPictureSettings")))
     {
-        // An individual preset
-        preset_clean(presets, template);
+        // UsesMaxPictureSettings was deprecated
+        hb_dict_set(preset, "UsesPictureSettings", hb_value_int(2));
     }
-    else
+
+    hb_value_t *val = hb_dict_get(preset, "PicturePAR");
+    if (hb_value_is_number(val))
+    {
+        const char *s;
+        int pic_par = hb_value_get_int(val);
+        switch (pic_par)
+        {
+            default:
+            case 0:
+                s = "off";
+                break;
+            case 1:
+                s = "strict";
+                break;
+            case 2:
+                s = "loose";
+                break;
+            case 3:
+                s = "custom";
+                break;
+        }
+        hb_dict_set(preset, "PicturePAR", hb_value_string(s));
+    }
+}
+
+static void import_audio(hb_value_t *preset)
+{
+    hb_value_t *copy = hb_dict_get(preset, "AudioCopyMask");
+    if (copy != NULL)
+        return;
+
+    copy = hb_value_array_init();
+    hb_dict_set(preset, "AudioCopyMask", copy);
+    if (hb_value_get_bool(hb_dict_get(preset, "AudioAllowMP3Pass")))
+        hb_value_array_append(copy, hb_value_string("copy:mp3"));
+    if (hb_value_get_bool(hb_dict_get(preset, "AudioAllowAACPass")))
+        hb_value_array_append(copy, hb_value_string("copy:aac"));
+    if (hb_value_get_bool(hb_dict_get(preset, "AudioAllowAC3Pass")))
+        hb_value_array_append(copy, hb_value_string("copy:ac3"));
+    if (hb_value_get_bool(hb_dict_get(preset, "AudioAllowDTSPass")))
+        hb_value_array_append(copy, hb_value_string("copy:dts"));
+    if (hb_value_get_bool(hb_dict_get(preset, "AudioAllowDTSHDPass")))
+        hb_value_array_append(copy, hb_value_string("copy:dtshd"));
+    if (hb_value_get_bool(hb_dict_get(preset, "AudioAllowEAC3Pass")))
+        hb_value_array_append(copy, hb_value_string("copy:eac3"));
+    if (hb_value_get_bool(hb_dict_get(preset, "AudioAllowFLACPass")))
+        hb_value_array_append(copy, hb_value_string("copy:flac"));
+    if (hb_value_get_bool(hb_dict_get(preset, "AudioAllowTRUEHDPass")))
+        hb_value_array_append(copy, hb_value_string("copy:truehd"));
+}
+
+static void import_video(hb_value_t *preset)
+{
+    hb_value_t *val;
+
+    if ((val = hb_dict_get(preset, "x264Preset")) != NULL)
+         hb_dict_set(preset, "VideoPreset", hb_value_dup(val));
+    if ((val = hb_dict_get(preset, "x264Tune")) != NULL)
+         hb_dict_set(preset, "VideoTune", hb_value_dup(val));
+    if ((val = hb_dict_get(preset, "h264Profile")) != NULL)
+         hb_dict_set(preset, "VideoProfile", hb_value_dup(val));
+    if ((val = hb_dict_get(preset, "h264Level")) != NULL)
+         hb_dict_set(preset, "VideoLevel", hb_value_dup(val));
+    if ((val = hb_dict_get(preset, "x264OptionExtra")) != NULL)
+        hb_dict_set(preset, "VideoOptionExtra", hb_value_dup(val));
+
+    if (hb_value_get_int(hb_dict_get(preset, "VideoQualityType")) == 0)
+    {
+        // Target size no longer supported
+        hb_dict_set(preset, "VideoQualityType", hb_value_int(1));
+    }
+
+    if (hb_value_get_bool(hb_dict_get(preset, "VideoFrameratePFR")))
+    {
+        hb_dict_set(preset, "VideoFramerateMode", hb_value_string("pfr"));
+    }
+    else if (hb_value_get_bool(hb_dict_get(preset, "VideoFramerateCFR")))
+    {
+        hb_dict_set(preset, "VideoFramerateMode", hb_value_string("cfr"));
+    }
+    else if (hb_value_get_bool(hb_dict_get(preset, "VideoFramerateVFR")))
+    {
+        hb_dict_set(preset, "VideoFramerateMode", hb_value_string("vfr"));
+    }
+
+    const char *enc;
+    int codec;
+    enc = hb_value_get_string(hb_dict_get(preset, "VideoEncoder"));
+    codec = hb_video_encoder_get_from_name(enc);
+    if (codec & HB_VCODEC_FFMPEG_MASK)
+    {
+        if ((val = hb_dict_get(preset, "lavcOption")) != NULL)
+            hb_dict_set(preset, "VideoOptionExtra", hb_value_dup(val));
+    }
+}
+
+static void preset_import(hb_value_t *preset, int major, int minor, int micro)
+{
+    if (!hb_value_get_bool(hb_dict_get(preset, "Folder")))
+    {
+        if (major == 0 && minor == 0 && micro == 0)
+        {
+            // Convert legacy presets (before versioning introduced)
+            import_video(preset);
+            import_pic(preset);
+            import_audio(preset);
+            import_decomb(preset);
+            import_deint(preset);
+            import_detel(preset);
+            import_denoise(preset);
+        }
+        preset_clean(preset, hb_preset_template);
+    }
+}
+
+int hb_presets_version(hb_value_t *preset, int *major, int *minor, int *micro)
+{
+    *major = 0; *minor = 0; *micro = 0;
+    if (hb_value_type(preset) == HB_VALUE_TYPE_DICT)
     {
-        hb_error("Error: invalid preset format in presets_clean()");
+        // Is this a single preset or a packaged collection of presets?
+        hb_value_t *val = hb_dict_get(preset, "PresetName");
+        if (val == NULL)
+        {
+            val = hb_dict_get(preset, "VersionMajor");
+            if (val != NULL)
+            {
+                *major = hb_value_get_int(hb_dict_get(preset, "VersionMajor"));
+                *minor = hb_value_get_int(hb_dict_get(preset, "VersionMinor"));
+                *micro = hb_value_get_int(hb_dict_get(preset, "VersionMicro"));
+                return 0;
+            }
+        }
     }
+    return -1;
+}
+
+void hb_presets_import(hb_value_t *preset)
+{
+    preset_import_context_t ctx;
+
+    ctx.do_ctx.path.depth = 1;
+    hb_presets_version(preset, &ctx.major, &ctx.minor, &ctx.micro);
+    presets_do(do_preset_import, preset, (preset_do_context_t*)&ctx);
+}
+
+char * hb_presets_import_json(const char *json)
+{
+    hb_value_t * dict = hb_value_json(json);
+    if (dict == NULL)
+        return NULL;
+
+    hb_presets_import(dict);
+    char * result = hb_value_get_json(dict);
+    hb_value_free(&dict);
+    return result;
+}
+
+char * hb_presets_clean_json(const char *json)
+{
+    hb_value_t * dict = hb_value_json(json);
+    if (dict == NULL)
+        return NULL;
+
+    presets_clean(dict, hb_preset_template);
+    char * result = hb_value_get_json(dict);
+    hb_value_free(&dict);
+    return result;
 }
 
 // Note that unpackage does not make any copies.
 // In one increases the reference count.
-static hb_value_t * preset_unpackage(hb_value_t *packaged_presets)
+static hb_value_t * presets_unpackage(const hb_value_t *packaged_presets)
 {
-    // TODO: Verify compatible version number.
-    //       Do any desired legacy translations.
-    if (hb_value_type(packaged_presets) == HB_VALUE_TYPE_ARRAY)
+    // Do any legacy translations.
+    hb_value_t *tmp = hb_value_dup(packaged_presets);
+    hb_presets_import(tmp);
+    if (hb_value_type(tmp) == HB_VALUE_TYPE_ARRAY)
     {
         // Not packaged
-        hb_value_incref(packaged_presets);
-        return packaged_presets;
+        return tmp;
+    }
+    if (hb_dict_get(tmp, "PresetName") != NULL)
+    {
+        // Bare single preset
+        return tmp;
     }
-    hb_value_t *presets = hb_dict_get(packaged_presets, "PresetList");
+    hb_value_t *presets = hb_dict_get(tmp, "PresetList");
     hb_value_incref(presets);
+    hb_value_free(&tmp);
     return presets;
 }
 
-static hb_value_t * preset_package(hb_value_t *presets)
+static hb_value_t * presets_package(const hb_value_t *presets)
 {
     hb_dict_t *packaged_presets;
-    if (hb_dict_get(presets, "VersionMajor") == NULL)
+    if (hb_value_type(presets) != HB_VALUE_TYPE_DICT ||
+        hb_dict_get(presets, "VersionMajor") == NULL)
     {
         // Preset is not packaged
         packaged_presets = hb_dict_init();
@@ -1711,14 +2234,14 @@ static hb_value_t * preset_package(hb_value_t *presets)
         hb_dict_set(packaged_presets, "VersionMicro",
                     hb_value_int(hb_preset_version_micro));
 
-        // TODO: What else to we want in the preset containers header?
+        // TODO: What else do we want in the preset containers header?
+        hb_dict_t *tmp = hb_value_dup(presets);
         if (hb_value_type(presets) == HB_VALUE_TYPE_DICT)
         {
-            hb_value_array_t *tmp = hb_value_array_init();
-            hb_value_array_append(tmp, presets);
-            presets = tmp;
+            hb_value_array_t *array = hb_value_array_init();
+            hb_value_array_append(array, tmp);
+            tmp = array;
         }
-        hb_dict_t *tmp = hb_value_dup(presets);
         presets_clean(tmp, hb_preset_template);
         hb_dict_set(packaged_presets, "PresetList", tmp);
     }
@@ -1745,12 +2268,17 @@ void hb_presets_builtin_init(void)
     hb_preset_template = hb_value_dup(hb_dict_get(template, "Preset"));
 
     hb_presets_builtin = hb_value_dup(hb_dict_get(dict, "PresetBuiltin"));
-    hb_value_free(&dict);
+    hb_presets_clean(hb_presets_builtin);
 
-    // Make a dup, never change contents of hb_presets_builtin
-    hb_presets = hb_value_dup(hb_presets_builtin);
-    hb_presets_custom = hb_value_array_init();
+    hb_presets = hb_value_array_init();
+    hb_value_free(&dict);
+}
 
+void hb_presets_current_version(int *major, int* minor, int *micro)
+{
+    *major = hb_preset_version_major;
+    *minor = hb_preset_version_minor;
+    *micro = hb_preset_version_micro;
 }
 
 int hb_presets_gui_init(void)
@@ -1761,29 +2289,12 @@ int hb_presets_gui_init(void)
 #if defined(HB_PRESET_JSON_FILE)
     hb_get_user_config_filename(path, "%s", HB_PRESET_JSON_FILE);
     dict = hb_value_read_json(path);
-    if (dict != NULL)
-    {
-        hb_value_t *preset = preset_unpackage(dict);
-        // Unpackaging does some validity checks and can fail
-        if (preset == NULL)
-            return -1;
-        int result = hb_presets_add(preset);
-        hb_value_free(&preset);
-        hb_value_free(&dict);
-        return result;
-    }
 #endif
 #if defined(HB_PRESET_PLIST_FILE)
     if (dict == NULL)
     {
         hb_get_user_config_filename(path, "%s", HB_PRESET_PLIST_FILE);
         dict = hb_plist_parse_file(path);
-        if (dict != NULL)
-        {
-            int result = hb_presets_add(dict);
-            hb_value_free(&dict);
-            return result;
-        }
     }
 #endif
     if (dict == NULL)
@@ -1797,6 +2308,15 @@ int hb_presets_gui_init(void)
 #endif
         return -1;
     }
+    else
+    {
+        preset_do_context_t ctx;
+        ctx.path.depth = 1;
+        presets_do(do_delete_builtin, dict, &ctx);
+        int result = hb_presets_add(dict);
+        hb_value_free(&dict);
+        return result;
+    }
     return -1;
 }
 
@@ -1811,49 +2331,31 @@ char * hb_presets_builtin_get_json(void)
     return json;
 }
 
-static hb_value_t * preset_lookup(hb_value_t *list, const char *name,
-                                  int def, int folder, int recurse)
+// Lookup a preset in the preset list.  The "name" may contain '/'
+// separators to explicitely specify a preset within the preset lists
+// folder structure.
+//
+// If 'recurse' is specified, a recursive search for the first component
+// in the name will be performed.
+//
+// I assume that the actual preset name does not include any '/'
+//
+// A reference to the preset is returned
+static hb_preset_index_t * preset_lookup_path(const char *name, int recurse)
 {
-    int count = hb_value_array_len(list);
-    int ii;
-    for (ii = 0; ii < count; ii++)
-    {
-        int d;
-        const char *n;
-        hb_dict_t *preset_dict = hb_value_array_get(list, ii);
-        n = hb_value_get_string(hb_dict_get(preset_dict, "PresetName"));
-        d = hb_value_get_bool(hb_dict_get(preset_dict, "Default"));
-        if (hb_value_get_bool(hb_dict_get(preset_dict, "Folder")))
-        {
-            if (folder && !def && n != NULL && !strncmp(name, n, 80))
-                return preset_dict;
-
-            if (recurse)
-            {
-                hb_value_array_t *children;
-                children = hb_dict_get(preset_dict, "ChildrenArray");
-                if (children == NULL)
-                    continue;
-                preset_dict = preset_lookup(children, name, def,
-                                            folder, recurse);
-                if (preset_dict != NULL)
-                    return preset_dict;
-            }
-        }
-        else if (!folder)
-        {
-            if (!def && n != NULL && !strncmp(n, name, 80))
-            {
-                // preset is not a folder and we found a matching preset name
-                return preset_dict;
-            }
-            else if (def && d)
-            {
-                return preset_dict;
-            }
-        }
-    }
-    return NULL;
+    preset_search_context_t ctx;
+    int result;
+
+    ctx.do_ctx.path.depth = 1;
+    ctx.name = name;
+    ctx.recurse = recurse;
+    ctx.last_match_idx = -1;
+    result = presets_do(do_preset_search, hb_presets,
+                        (preset_do_context_t*)&ctx);
+    if (result != PRESET_DO_SUCCESS)
+        ctx.do_ctx.path.depth = 0;
+
+    return hb_preset_index_dup(&ctx.do_ctx.path);
 }
 
 // Lookup a preset in the preset list.  The "name" may contain '/'
@@ -1864,182 +2366,128 @@ static hb_value_t * preset_lookup(hb_value_t *list, const char *name,
 // in the name will be performed.
 //
 // I assume that the actual preset name does not include any '/'
-hb_value_t * hb_preset_get(const char *name, int recurse)
+//
+// A copy of the preset is returned
+hb_preset_index_t * hb_preset_search_index(const char *name, int recurse)
 {
-    if (name == NULL || name[0] == 0)
-    {
-        // bad input.
-        return NULL;
-    }
-
-    char *tmp = strdup(name);
-    char *part, *next;
-    hb_value_t *list;
-
-    list = hb_presets;
-    part = tmp;
-    next = strchr(name, '/');
-    if (next == NULL)
-    {
-        // Only preset name was specified, so do a recursive search
-        hb_value_t *preset = preset_lookup(list, part, 0, 0, recurse);
-        free(tmp);
-        if (preset == NULL)
-        {
-            return NULL;
-        }
-        return hb_value_dup(preset);
-    }
-    // Found folder separator in name, do explicit path search
-    while (part)
-    {
-        *next = 0;
-        next++;
-        if (next[0] == 0)
-        {
-            // name ends in a folder separator '/'. Invalid input
-            free(tmp);
-            return NULL;
-        }
+    return preset_lookup_path(name, recurse);
+}
 
-        // We have a folder part.  Lookup the folder.
-        // First try non-recursive so that we match top level folders first
-        hb_dict_t *folder = preset_lookup(list, part, 0, 1, 0);
-        if (folder == NULL && recurse)
-        {
-            // Try a recursive search for the folder
-            folder = preset_lookup(list, part, 0, 1, recurse);
-        }
-        if (folder == NULL)
-        {
-            // Not found
-            free(tmp);
-            return NULL;
-        }
-        list = hb_dict_get(folder, "ChildrenArray");
-        if (list == NULL)
-        {
-            // Folder found, but it has no children
-            free(tmp);
-            return NULL;
-        }
-        // Folder found, continue the search
-        part = next;
-        next = strchr(name, '/');
-        if (next == NULL)
-        {
-            // We have reached the final component of the path
-            // which is the preset name.  Do a non-recursive search.
-            // If the preset is not in the specified folder, will
-            // return NULL
-            hb_value_t *preset = preset_lookup(list, part, 0, 0, 0);
-            free(tmp);
-            if (preset == NULL)
-            {
-                return NULL;
-            }
-            return hb_value_dup(preset);
-        }
-    }
-    // This should never be reached, but some compilers might complain
-    // without a final return.
-    free(tmp);
-    return NULL;
+hb_value_t * hb_preset_search(const char *name, int recurse)
+{
+    hb_preset_index_t *path = preset_lookup_path(name, recurse);
+    hb_value_t *preset = hb_preset_get(path);
+    free(path);
+    return preset;
 }
 
-char * hb_preset_get_json(const char *name, int recurse)
+char * hb_preset_search_json(const char *name, int recurse)
 {
     hb_value_t * preset;
     char *json;
-    preset = hb_preset_get(name, recurse);
+    preset = hb_preset_search(name, recurse);
     if (preset == NULL)
         return NULL;
     json = hb_value_get_json(preset);
-    hb_value_free(&preset);
     return json;
 }
 
-static hb_dict_t * find_first_preset(hb_value_array_t *list)
+static hb_preset_index_t * lookup_default_index(hb_value_t *list)
 {
-    int count, ii;
-    count = hb_value_array_len(list);
-    for (ii = 0; ii < count; ii++)
-    {
-        hb_dict_t *preset_dict = hb_value_array_get(list, ii);
-        if (hb_value_get_bool(hb_dict_get(preset_dict, "Folder")))
-        {
-            hb_value_array_t *children;
-            children = hb_dict_get(preset_dict, "ChildrenArray");
-            if (children == NULL)
-                continue;
-            preset_dict = find_first_preset(children);
-            if (preset_dict != NULL)
-                return preset_dict;
-        }
-        else
-        {
-            return preset_dict;
-        }
-    }
-    return NULL;
+    preset_do_context_t ctx;
+    int result;
+
+    ctx.path.depth = 1;
+    result = presets_do(do_find_default, list, &ctx);
+    if (result != PRESET_DO_SUCCESS)
+        ctx.path.depth = 0;
+    return hb_preset_index_dup(&ctx.path);
+}
+
+hb_preset_index_t * hb_presets_get_default_index(void)
+{
+    hb_preset_index_t *path = lookup_default_index(hb_presets);
+    return path;
 }
 
 hb_dict_t * hb_presets_get_default(void)
 {
-    // Look for preset with 'Default' flag set
-    hb_value_t *preset =  preset_lookup(hb_presets, NULL, 1, 0, 1);
-    if (preset == NULL)
-    {
-        // Look for preset named 'Normal' flag set
-        preset =  preset_lookup(hb_presets, "Normal", 0, 0, 1);
-        if (preset == NULL)
-        {
-            // Just grab the first preset available
-            preset = find_first_preset(hb_presets);
-            if (preset == NULL)
-                return NULL;
-        }
-    }
-    return hb_value_dup(preset);
+    hb_preset_index_t *path = hb_presets_get_default_index();
+    return hb_preset_get(path);
 }
 
 char * hb_presets_get_default_json(void)
 {
-    hb_value_t *preset =  preset_lookup(hb_presets, NULL, 1, 0, 1);
-    if (preset == NULL)
-        return NULL;
-    return hb_value_get_json(preset);
+    // Look for default preset
+    hb_value_t *def = hb_presets_get_default();
+    return hb_value_get_json(def);
 }
 
-// Return:
-//      0 upon success
-//      1 if preset name could not be found
-int hb_presets_set_default(const char *name, int recurse)
+void hb_presets_clear_default()
 {
-    hb_value_t *preset =  preset_lookup(hb_presets, NULL, 1, 0, 1);
-    if (preset != NULL)
+    preset_do_context_t ctx;
+    ctx.path.depth = 1;
+    presets_do(do_clear_default, hb_presets, &ctx);
+}
+
+void hb_presets_builtin_update(void)
+{
+    preset_do_context_t ctx;
+    hb_preset_index_t *path;
+    hb_value_t *builtin;
+    int ii;
+
+    ctx.path.depth = 1;
+    presets_do(do_delete_builtin, hb_presets, &ctx);
+
+    builtin = hb_value_dup(hb_presets_builtin);
+    path = lookup_default_index(hb_presets);
+    if (path != NULL && path->depth != 0)
     {
-        // Mark old defalt as not
-        hb_dict_set(preset, "Default", hb_value_bool(0));
+        // The "Default" preset is an existing custom preset.
+        // Clear the default preset in builtins
+        ctx.path.depth = 1;
+        presets_do(do_clear_default, builtin, &ctx);
     }
-    preset = preset_lookup(hb_presets, name, 0, 0, recurse);
-    if (preset == NULL)
-        return -1;
-    hb_dict_set(preset, "Default", hb_value_bool(1));
-    return 0;
+    free(path);
+
+    for (ii = hb_value_array_len(builtin) - 1; ii >= 0; ii--)
+    {
+        hb_value_t *dict;
+        dict = hb_value_array_get(builtin, ii);
+        hb_value_incref(dict);
+        hb_value_array_insert(hb_presets, 0, dict);
+    }
+    hb_value_free(&builtin);
 }
 
 int hb_presets_add(hb_value_t *preset)
 {
+    hb_preset_index_t *path;
+    int                added = 0;
+
     if (preset == NULL)
         return -1;
-    // TODO: validity checking of input preset
+
+    preset = presets_unpackage(preset);
+    if (preset == NULL)
+        return -1;
+
+    path = lookup_default_index(preset);
+    if (path != NULL && path->depth != 0)
+    {
+        // There is a "Default" preset in the preset(s) being added.
+        // Clear any existing default preset.
+        hb_presets_clear_default();
+    }
+    free(path);
+
+    int index = hb_value_array_len(hb_presets);
     if (hb_value_type(preset) == HB_VALUE_TYPE_DICT)
     {
         // A standalone preset or folder of presets.  Add to preset array.
-        // Only allow custom presets to be added
-        if (hb_value_get_int(hb_dict_get(preset, "Type")) == 1)
-            hb_value_array_append(hb_presets_custom, hb_value_dup(preset));
+        hb_value_array_append(hb_presets, hb_value_dup(preset));
+        added++;
     }
     else if (hb_value_type(preset) == HB_VALUE_TYPE_ARRAY)
     {
@@ -2049,48 +2497,69 @@ int hb_presets_add(hb_value_t *preset)
         for (ii = 0; ii < count; ii++)
         {
             hb_value_t *value = hb_value_array_get(preset, ii);
-            hb_value_array_append(hb_presets_custom, hb_value_dup(value));
+            hb_value_array_append(hb_presets, hb_value_dup(value));
+            added++;
         }
     }
 
-    // Reconstruct global list
-    hb_value_decref(hb_presets);
-    hb_presets = hb_value_dup(hb_presets_builtin);
-    // Append custom presets
-    int count = hb_value_array_len(hb_presets_custom);
-    int ii;
-    for (ii = 0; ii < count; ii++)
+    hb_value_free(&preset);
+    if (added == 0)
     {
-        hb_value_t *value = hb_value_array_get(hb_presets_custom, ii);
-        // Only allow custom presets to be added
-        if (hb_value_get_int(hb_dict_get(value, "Type")) == 1)
-            hb_value_array_append(hb_presets, hb_value_dup(value));
+        return -1;
     }
-    return 0;
+
+    return index;
 }
 
 int hb_presets_add_json(const char *json)
 {
-    hb_value_t *packaged_preset = hb_value_json(json);
-    hb_value_t *preset = preset_unpackage(packaged_preset);
+    hb_value_t *preset = hb_value_json(json);
     if (preset == NULL)
         return -1;
     int result = hb_presets_add(preset);
     hb_value_free(&preset);
-    hb_value_free(&packaged_preset);
     return result;
 }
 
+int hb_presets_version_file(const char *filename,
+                            int *major, int *minor, int *micro)
+{
+    int result;
+
+    hb_value_t *preset = hb_value_read_json(filename);
+    if (preset == NULL)
+        preset = hb_plist_parse_file(filename);
+    if (preset == NULL)
+        return -1;
+
+    result = hb_presets_version(preset, major, minor, micro);
+    hb_value_free(&preset);
+
+    return result;
+}
+
+hb_value_t* hb_presets_read_file(const char *filename)
+{
+    hb_value_t *preset = hb_value_read_json(filename);
+    if (preset == NULL)
+        preset = hb_plist_parse_file(filename);
+    if (preset == NULL)
+        return NULL;
+
+    return preset;
+}
+
 int hb_presets_add_file(const char *filename)
 {
-    hb_value_t *packaged_preset = hb_value_read_json(filename);
-    hb_value_t *preset = preset_unpackage(packaged_preset);
-    // Unpackaging does some validity checks and can fail
+    hb_value_t *preset = hb_value_read_json(filename);
+    if (preset == NULL)
+        preset = hb_plist_parse_file(filename);
     if (preset == NULL)
         return -1;
+
     int result = hb_presets_add(preset);
     hb_value_free(&preset);
-    hb_value_free(&packaged_preset);
+
     return result;
 }
 
@@ -2169,7 +2638,7 @@ int hb_presets_add_path(char * path)
     {
         int res = hb_presets_add_file(files[ii]);
         // return success if any one of the files is successfully loaded
-        if (res == 0)
+        if (res >= 0)
             result = res;
     }
     hb_closedir( dir );
@@ -2180,17 +2649,20 @@ int hb_presets_add_path(char * path)
 
 hb_value_t * hb_presets_get(void)
 {
-    return hb_value_dup(hb_presets);
+    return hb_presets;
 }
 
 char * hb_presets_get_json(void)
 {
-    return hb_value_get_json(hb_presets);
+    char * result;
+    hb_value_t *presets = hb_presets_get();
+    result = hb_value_get_json(presets);
+    return result;
 }
 
-int hb_preset_write_json(hb_value_t *preset, const char *path)
+int hb_presets_write_json(const hb_value_t *preset, const char *path)
 {
-    hb_value_t *packaged_preset = preset_package(preset);
+    hb_value_t *packaged_preset = presets_package(preset);
     // Packaging does some validity checks and can fail
     if (packaged_preset == NULL)
         return -1;
@@ -2199,21 +2671,247 @@ int hb_preset_write_json(hb_value_t *preset, const char *path)
     return result;
 }
 
-char * hb_preset_package_json(hb_value_t *preset)
+char * hb_presets_package_json(const hb_value_t *preset)
 {
-    hb_value_t *packaged_preset = preset_package(preset);
+    hb_value_t *packaged_preset = presets_package(preset);
     // Packaging does some validity checks and can fail
     if (packaged_preset == NULL)
         return NULL;
-    char *json = hb_value_get_json(packaged_preset);
+    char *out_json = hb_value_get_json(packaged_preset);
     hb_value_free(&packaged_preset);
-    return json;
+    return out_json;
+}
+
+char * hb_presets_json_package(const char *in_json)
+{
+    hb_value_t *preset = hb_value_json(in_json);
+    hb_value_t *packaged_preset = presets_package(preset);
+    // Packaging does some validity checks and can fail
+    if (packaged_preset == NULL)
+        return NULL;
+    char *out_json = hb_value_get_json(packaged_preset);
+    hb_value_free(&packaged_preset);
+    hb_value_free(&preset);
+    return out_json;
 }
 
 void hb_presets_free(void)
 {
     hb_value_free(&hb_preset_template);
     hb_value_free(&hb_presets);
-    hb_value_free(&hb_presets_custom);
     hb_value_free(&hb_presets_builtin);
 }
+
+hb_value_t *
+hb_presets_get_folder_children(const hb_preset_index_t *path)
+{
+    int ii, count, folder;
+    hb_value_t *dict;
+
+    if (path == NULL)
+        return hb_presets;
+
+    hb_value_t *presets = hb_presets;
+    for (ii = 0; ii < path->depth; ii++)
+    {
+        count = hb_value_array_len(presets);
+        if (path->index[ii] >= count) return NULL;
+        dict = hb_value_array_get(presets, path->index[ii]);
+        folder = hb_value_get_bool(hb_dict_get(dict, "Folder"));
+        if (!folder)
+            break;
+        presets = hb_dict_get(dict, "ChildrenArray");
+    }
+    if (ii < path->depth)
+        return NULL;
+    return presets;
+}
+
+hb_value_t *
+hb_preset_get(const hb_preset_index_t *path)
+{
+    hb_value_t *folder = NULL;
+
+    if (path == NULL || path->depth <= 0)
+        return NULL;
+
+    hb_preset_index_t folder_path = *path;
+    folder_path.depth--;
+    folder = hb_presets_get_folder_children(&folder_path);
+    if (folder)
+    {
+        if (hb_value_array_len(folder) <= path->index[path->depth-1])
+        {
+            hb_error("hb_preset_get: not found");
+        }
+        else
+        {
+            return hb_value_array_get(folder, path->index[path->depth-1]);
+        }
+    }
+    else
+    {
+        hb_error("hb_preset_get: not found");
+    }
+    return NULL;
+}
+
+int
+hb_preset_set(const hb_preset_index_t *path, const hb_value_t *dict)
+{
+    hb_value_t *folder = NULL;
+
+    if (dict == NULL || path == NULL || path->depth <= 0)
+        return -1;
+
+    hb_preset_index_t folder_path = *path;
+    folder_path.depth--;
+    folder = hb_presets_get_folder_children(&folder_path);
+    if (folder)
+    {
+        if (hb_value_array_len(folder) <= path->index[path->depth-1])
+        {
+            hb_error("hb_preset_replace: not found");
+            return -1;
+        }
+        else
+        {
+            hb_value_t *dup = hb_value_dup(dict);
+            presets_clean(dup, hb_preset_template);
+            hb_value_array_set(folder, path->index[path->depth-1], dup);
+        }
+    }
+    else
+    {
+        hb_error("hb_preset_replace: not found");
+        return -1;
+    }
+    return 0;
+}
+
+int hb_preset_insert(const hb_preset_index_t *path, const hb_value_t *dict)
+{
+    hb_value_t *folder = NULL;
+
+    if (dict == NULL || path == NULL || path->depth < 0)
+        return -1;
+
+    int index = path->index[path->depth - 1];
+    hb_preset_index_t folder_path = *path;
+    folder_path.depth--;
+    folder = hb_presets_get_folder_children(&folder_path);
+    if (folder)
+    {
+        hb_value_t *dup = hb_value_dup(dict);
+        presets_clean(dup, hb_preset_template);
+        if (hb_value_array_len(folder) <= index)
+        {
+            index = hb_value_array_len(folder);
+            hb_value_array_append(folder, dup);
+        }
+        else
+        {
+            hb_value_array_insert(folder, index, dup);
+        }
+    }
+    else
+    {
+        hb_error("hb_preset_insert: not found");
+        return -1;
+    }
+    return index;
+}
+
+int hb_preset_append(const hb_preset_index_t *path, const hb_value_t *dict)
+{
+    hb_value_t *folder = NULL;
+
+    if (dict == NULL)
+        return -1;
+
+    folder = hb_presets_get_folder_children(path);
+    if (folder)
+    {
+        int index;
+        hb_value_t *dup = hb_value_dup(dict);
+        presets_clean(dup, hb_preset_template);
+        index = hb_value_array_len(folder);
+        hb_value_array_append(folder, dup);
+        return index;
+    }
+    else
+    {
+        hb_error("hb_preset_append: not found");
+        return -1;
+    }
+    return 0;
+}
+
+int
+hb_preset_delete(const hb_preset_index_t *path)
+{
+    hb_value_t *folder = NULL;
+
+    if (path == NULL)
+        return -1;
+
+    hb_preset_index_t folder_path = *path;
+    folder_path.depth--;
+    folder = hb_presets_get_folder_children(&folder_path);
+    if (folder)
+    {
+        if (hb_value_array_len(folder) <= path->index[path->depth-1])
+        {
+            hb_error("hb_preset_delete: not found");
+            return -1;
+        }
+        else
+        {
+            hb_value_array_remove(folder, path->index[path->depth-1]);
+        }
+    }
+    else
+    {
+        hb_error("hb_preset_delete: not found");
+        return -1;
+    }
+    return 0;
+}
+
+int hb_preset_move(const hb_preset_index_t *src_path,
+                   const hb_preset_index_t *dst_path)
+{
+    hb_value_t *src_folder = NULL;
+    hb_value_t *dst_folder = NULL;
+
+    hb_preset_index_t src_folder_path = *src_path;
+    hb_preset_index_t dst_folder_path = *dst_path;
+    src_folder_path.depth--;
+    dst_folder_path.depth--;
+    src_folder = hb_presets_get_folder_children(&src_folder_path);
+    dst_folder = hb_presets_get_folder_children(&dst_folder_path);
+    if (src_folder == NULL || dst_folder == NULL)
+    {
+        hb_error("hb_preset_move: not found");
+        return -1;
+    }
+
+    hb_value_t *dict;
+    int         src_index, dst_index;
+
+    src_index = src_path->index[src_path->depth-1];
+    dst_index = dst_path->index[src_path->depth-1];
+    dict      = hb_value_array_get(src_folder, src_index);
+    hb_value_incref(dict);
+    hb_value_array_remove(src_folder, src_index);
+
+    // Be careful about indexes in the case that they are in the same folder
+    if (src_folder == dst_folder && src_index < dst_index)
+        dst_index--;
+    if (hb_value_array_len(dst_folder) <= dst_index)
+        hb_value_array_append(dst_folder, dict);
+    else
+        hb_value_array_insert(dst_folder, dst_index, dict);
+
+    return 0;
+}
index 5e7c460b6ce70cc3ce580439187e6db17a02740b..a24b45cf2d0059b29847c8e7436407b32368ccdc 100644 (file)
@@ -1,4 +1,4 @@
-/* hb_preset.h
+/* preset.h
 
    Copyright (c) 2003-2015 HandBrake Team
    This file is part of the HandBrake source code
 #include "common.h"
 #include "hb_dict.h"
 
+#define HB_MAX_PRESET_FOLDER_DEPTH  8
+
+typedef struct hb_preset_index_s hb_preset_index_t;
+
+// A preset index is a list of indexes that specifies a path to a
+// specific preset in a preset list.  Since a preset list can have
+// folders that contain sub-lists, multiple index values are needed
+// to create a complete path.
+struct hb_preset_index_s
+{
+    int depth;
+    int index[HB_MAX_PRESET_FOLDER_DEPTH];
+};
+
+#ifdef __LIBHB__
+// Preset APIs reserved for libhb
+
 // Initialize the hb_value_array_t that holds HandBrake builtin presets
+// These presets come from a json string embedded in libhb and can be
+// retrieved with hb_presets_builtin_get() after initialization.
 void         hb_presets_builtin_init(void);
 
-// Load presets from GUI presets file if possible
-int          hb_presets_gui_init(void);
-
-// Free all libhb presets
+// Free all libhb presets. This should only be called when closing
+// an hb_handle_t.
 void         hb_presets_free(void);
 
-// Get list of HandBrake builtin presets as hb_value_array_t
+#endif // __LIBHB__
+
+// Get the currently supported preset format version
+void hb_presets_current_version(int *major, int* minor, int *micro);
+
+// Get the format version of a preset dict
+int hb_presets_version(hb_value_t *preset, int *major, int *minor, int *micro);
+
+// Initialize a new preset index.  "index" may be NULL
+hb_preset_index_t * hb_preset_index_init(const int *index, int depth);
+
+// Duplicate a preset index
+hb_preset_index_t * hb_preset_index_dup(const hb_preset_index_t *path);
+
+// Append one index to another
+void                hb_preset_index_append(hb_preset_index_t *dst,
+                                           const hb_preset_index_t *src);
+
+// Load presets list from GUI presets file if it exists. This should probably
+// only be used by the CLI.
+int          hb_presets_gui_init(void);
+
+// Get HandBrake builtin presets list as hb_value_array_t
 hb_value_t * hb_presets_builtin_get(void);
 
-// Get list of HandBrake builtin presets as json string
+// Get HandBrake builtin presets list as json string
 char       * hb_presets_builtin_get_json(void);
 
-// Register new presets with libhb from
-// hb_dict_t (single preset) or hb_value_array_t (list of presets)
-int          hb_presets_add(hb_value_t *preset);
+// Load default builtin presets list over the top of any builtins in the
+// current preset list. This should be used by a frontend when it recognizes
+// that it's preset file is from an older version of HandBrake.
+void         hb_presets_builtin_update(void);
+
+// Clean presets.  Removes unknown keys and normalizes values.
+// This should be applied before exporting a preset and is applied
+// for you by hb_presets_write_json() and hb_preset_package_json().
+void         hb_presets_clean(hb_value_t *preset);
+
+// Clean json presets.  Removes unknown keys and normalizes values.
+// This should be applied before exporting a preset and is applied
+// for you by hb_presets_write_json() and hb_preset_package_json().
+char       * hb_presets_clean_json(const char *json);
+
+// Import a preset.  Sanitizes and converts old key/value pairs
+// to new key/value pairs.  This is applied for you by hb_presets_add(),
+// hb_presets_add_json(), hb_presets_add_file(), and hb_presets_add_path()
+void         hb_presets_import(hb_value_t *preset);
+
+// Import a json preset.  Sanitizes and converts old key/value pairs
+// to new key/value pairs.
+char       * hb_presets_import_json(const char *json);
 
 // Register new presets with libhb from json string
 int          hb_presets_add_json(const char *json);
 
+// Read a preset file.  Does not add to internal preset list.
+hb_value_t*  hb_presets_read_file(const char *filename);
+
+// Register new presets with libhb from a preset dict
+int          hb_presets_add(hb_value_t *preset);
+
 // Register new presets with libhb from json file
 int          hb_presets_add_file(const char *filename);
 
@@ -45,16 +110,21 @@ int          hb_presets_add_path(char * path);
 // Get list of all presets registered with libhb as hb_value_array_t
 hb_value_t * hb_presets_get(void);
 
+
 // Get list of all presets registered with libhb as json string
 char       * hb_presets_get_json(void);
 
 // Initialize a job from the given title and preset
 hb_dict_t  * hb_preset_job_init(hb_handle_t *h, int title_index,
-                                hb_dict_t *preset);
+                                const hb_dict_t *preset);
+
+// Reinitialize subtitles from preset defaults.
 int hb_preset_job_add_subtitles(hb_handle_t *h, int title_index,
-                                hb_dict_t *preset, hb_dict_t *job_dict);
+                                const hb_dict_t *preset, hb_dict_t *job_dict);
+
+// Reinitialize audio from preset defaults.
 int hb_preset_job_add_audio(hb_handle_t *h, int title_index,
-                            hb_dict_t *preset, hb_dict_t *job_dict);
+                            const hb_dict_t *preset, hb_dict_t *job_dict);
 
 // Lookup a preset in the preset list.  The "name" may contain '/'
 // separators to explicitely specify a preset within the preset lists
@@ -64,21 +134,37 @@ int hb_preset_job_add_audio(hb_handle_t *h, int title_index,
 // in the name will be performed.
 //
 // I assume that the actual preset name does not include any '/'
-hb_value_t * hb_preset_get(const char *name, int recurse);
-char       * hb_preset_get_json(const char *name, int recurse);
+hb_preset_index_t * hb_preset_search_index(const char *name, int recurse);
+hb_value_t        * hb_preset_search(const char *name, int recurse);
+char              * hb_preset_search_json(const char *name, int recurse);
+
+hb_value_t * hb_presets_get_folder_children(const hb_preset_index_t *path);
+hb_value_t * hb_preset_get(const hb_preset_index_t *path);
+int          hb_preset_delete(const hb_preset_index_t *path);
+int          hb_preset_set(const hb_preset_index_t *path,
+                           const hb_value_t *dict);
+int          hb_preset_insert(const hb_preset_index_t *path,
+                              const hb_value_t *dict);
+int          hb_preset_append(const hb_preset_index_t *path,
+                              const hb_value_t *dict);
+int          hb_preset_move(const hb_preset_index_t *src_path,
+                            const hb_preset_index_t *dst_path);
 
 // Recursively lookup the preset that is marked as 'Default'
-hb_dict_t  * hb_presets_get_default(void);
-char       * hb_presets_get_default_json(void);
-
-// Set the preset that is marked as 'Default'
-int          hb_presets_set_default(const char *name, int recurse);
+hb_dict_t         * hb_presets_get_default(void);
+char              * hb_presets_get_default_json(void);
+hb_preset_index_t * hb_presets_get_default_index(void);
 
 // Package the provided preset (wrap in dict and add version etc)
 // and write to json file
-int          hb_preset_write_json(hb_value_t *preset, const char *path);
+int          hb_presets_write_json(const hb_value_t *preset, const char *path);
+
 // Package the provided preset (wrap in dict and add version etc)
 // and return as json string
-char       * hb_preset_package_json(hb_value_t *preset);
+char       * hb_presets_package_json(const hb_value_t *presets);
+
+// Package the provided json presets list (wrap in dict and add version etc)
+// and return as json string
+char       * hb_presets_json_package(const char *json_presets);
 
 #endif // HB_PRESET_H
index 5bf5d4d8a007fc142531ac8f6498813551ef28e2..cc16e0f89e61309103b4f2f9ef8ab4eba8778833 100644 (file)
@@ -2,52 +2,45 @@
         {
             "ChildrenArray": [
                 {
-                    "AudioAllowAACPass": 1,
-                    "AudioAllowAC3Pass": 1,
-                    "AudioAllowDTSHDPass": 1,
-                    "AudioAllowDTSPass": 1,
-                    "AudioAllowMP3Pass": 1,
                     "AudioEncoderFallback": "ac3",
                     "AudioList": [
                         {
-                            "AudioBitrate": "160",
+                            "AudioBitrate": 160,
                             "AudioEncoder": "aac",
                             "AudioMixdown": "dpl2",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         },
                         {
-                            "AudioBitrate": "160",
+                            "AudioBitrate": 160,
                             "AudioEncoder": "copy:ac3",
                             "AudioMixdown": "none",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         }
                     ],
-                    "ChapterMarkers": 1,
-                    "Default": 0,
+                    "ChapterMarkers": true,
+                    "Default": false,
                     "FileFormat": "mp4",
                     "Folder": false,
-                    "Mp4HttpOptimize": 0,
-                    "Mp4iPodCompatible": 0,
-                    "PictureAutoCrop": 1,
+                    "Mp4HttpOptimize": false,
+                    "Mp4iPodCompatible": false,
+                    "PictureAutoCrop": true,
                     "PictureBottomCrop": 0,
                     "PictureDeblock": 0,
-                    "PictureDecomb": 0,
+                    "PictureDecomb": "off",
                     "PictureDecombCustom": "",
-                    "PictureDecombDeinterlace": 1,
-                    "PictureDeinterlace": 0,
+                    "PictureDecombDeinterlace": true,
+                    "PictureDeinterlace": "off",
                     "PictureDeinterlaceCustom": "",
                     "PictureDenoiseCustom": "",
                     "PictureDenoiseFilter": "off",
-                    "PictureDetelecine": 0,
+                    "PictureDetelecine": "off",
                     "PictureDetelecineCustom": "",
                     "PictureHeight": 576,
-                    "PictureKeepRatio": 0,
+                    "PictureKeepRatio": true,
                     "PictureLeftCrop": 0,
                     "PictureModulus": 2,
                     "PicturePAR": "loose",
                     "PresetDescription": "HandBrake's settings for compatibility with all Apple devices (including the iPod 6G and later). Includes Dolby Digital audio for surround sound.",
                     "PresetName": "Universal",
                     "Type": 0,
-                    "UsesPictureFilters": 1,
+                    "UsesPictureFilters": true,
                     "UsesPictureSettings": 1,
-                    "VideoAvgBitrate": "2500",
+                    "VideoAvgBitrate": 2500,
                     "VideoEncoder": "x264",
                     "VideoFramerate": "30",
                     "VideoFramerateMode": "pfr",
-                    "VideoGrayScale": 0,
+                    "VideoGrayScale": false,
                     "VideoLevel": "3.0",
                     "VideoOptionExtra": "",
                     "VideoPreset": "fast",
                     "VideoQualitySlider": 20.0,
                     "VideoQualityType": 2,
                     "VideoTune": "",
-                    "VideoTurboTwoPass": 0,
-                    "VideoTwoPass": 0,
+                    "VideoTurboTwoPass": false,
+                    "VideoTwoPass": false,
                     "x264Option": "",
-                    "x264UseAdvancedOptions": 0
+                    "x264UseAdvancedOptions": false
                 },
                 {
-                    "AudioAllowAACPass": 1,
-                    "AudioAllowAC3Pass": 1,
-                    "AudioAllowDTSHDPass": 1,
-                    "AudioAllowDTSPass": 1,
-                    "AudioAllowMP3Pass": 1,
                     "AudioEncoderFallback": "ac3",
                     "AudioList": [
                         {
-                            "AudioBitrate": "160",
+                            "AudioBitrate": 160,
                             "AudioEncoder": "aac",
                             "AudioMixdown": "dpl2",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         }
                     ],
-                    "ChapterMarkers": 1,
-                    "Default": 0,
+                    "ChapterMarkers": true,
+                    "Default": false,
                     "FileFormat": "mp4",
                     "Folder": false,
-                    "Mp4HttpOptimize": 0,
-                    "Mp4iPodCompatible": 1,
-                    "PictureAutoCrop": 1,
+                    "Mp4HttpOptimize": false,
+                    "Mp4iPodCompatible": true,
+                    "PictureAutoCrop": true,
                     "PictureBottomCrop": 0,
                     "PictureDeblock": 0,
-                    "PictureDecomb": 0,
+                    "PictureDecomb": "off",
                     "PictureDecombCustom": "",
-                    "PictureDecombDeinterlace": 1,
-                    "PictureDeinterlace": 0,
+                    "PictureDecombDeinterlace": true,
+                    "PictureDeinterlace": "off",
                     "PictureDeinterlaceCustom": "",
                     "PictureDenoiseCustom": "",
                     "PictureDenoiseFilter": "off",
-                    "PictureDetelecine": 0,
+                    "PictureDetelecine": "off",
                     "PictureDetelecineCustom": "",
                     "PictureHeight": 240,
-                    "PictureKeepRatio": 1,
+                    "PictureKeepRatio": true,
                     "PictureLeftCrop": 0,
                     "PictureModulus": 2,
                     "PicturePAR": "off",
                     "PresetDescription": "HandBrake's settings for playback on the iPod with Video (all generations).",
                     "PresetName": "iPod",
                     "Type": 0,
-                    "UsesPictureFilters": 1,
+                    "UsesPictureFilters": true,
                     "UsesPictureSettings": 1,
-                    "VideoAvgBitrate": "2500",
+                    "VideoAvgBitrate": 2500,
                     "VideoEncoder": "x264",
                     "VideoFramerate": "30",
                     "VideoFramerateMode": "pfr",
-                    "VideoGrayScale": 0,
+                    "VideoGrayScale": false,
                     "VideoLevel": "1.3",
                     "VideoOptionExtra": "",
                     "VideoPreset": "medium",
                     "VideoQualitySlider": 22.0,
                     "VideoQualityType": 2,
                     "VideoTune": "",
-                    "VideoTurboTwoPass": 0,
-                    "VideoTwoPass": 0,
+                    "VideoTurboTwoPass": false,
+                    "VideoTwoPass": false,
                     "x264Option": "",
-                    "x264UseAdvancedOptions": 0
+                    "x264UseAdvancedOptions": false
                 },
                 {
-                    "AudioAllowAACPass": 1,
-                    "AudioAllowAC3Pass": 1,
-                    "AudioAllowDTSHDPass": 1,
-                    "AudioAllowDTSPass": 1,
-                    "AudioAllowMP3Pass": 1,
                     "AudioEncoderFallback": "ac3",
                     "AudioList": [
                         {
-                            "AudioBitrate": "160",
+                            "AudioBitrate": 160,
                             "AudioEncoder": "aac",
                             "AudioMixdown": "dpl2",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         }
                     ],
-                    "ChapterMarkers": 1,
-                    "Default": 0,
+                    "ChapterMarkers": true,
+                    "Default": false,
                     "FileFormat": "mp4",
                     "Folder": false,
-                    "Mp4HttpOptimize": 0,
-                    "Mp4iPodCompatible": 0,
-                    "PictureAutoCrop": 1,
+                    "Mp4HttpOptimize": false,
+                    "Mp4iPodCompatible": false,
+                    "PictureAutoCrop": true,
                     "PictureBottomCrop": 0,
                     "PictureDeblock": 0,
-                    "PictureDecomb": 0,
+                    "PictureDecomb": "off",
                     "PictureDecombCustom": "",
-                    "PictureDecombDeinterlace": 1,
-                    "PictureDeinterlace": 0,
+                    "PictureDecombDeinterlace": true,
+                    "PictureDeinterlace": "off",
                     "PictureDeinterlaceCustom": "",
                     "PictureDenoiseCustom": "",
                     "PictureDenoiseFilter": "off",
-                    "PictureDetelecine": 0,
+                    "PictureDetelecine": "off",
                     "PictureDetelecineCustom": "",
                     "PictureHeight": 640,
-                    "PictureKeepRatio": 0,
+                    "PictureKeepRatio": true,
                     "PictureLeftCrop": 0,
                     "PictureModulus": 2,
                     "PicturePAR": "loose",
                     "PresetDescription": "HandBrake's settings for handheld iOS devices (iPhone 4, iPod touch 3G and later).",
                     "PresetName": "iPhone & iPod touch",
                     "Type": 0,
-                    "UsesPictureFilters": 1,
+                    "UsesPictureFilters": true,
                     "UsesPictureSettings": 1,
-                    "VideoAvgBitrate": "2500",
+                    "VideoAvgBitrate": 2500,
                     "VideoEncoder": "x264",
                     "VideoFramerate": "30",
                     "VideoFramerateMode": "pfr",
-                    "VideoGrayScale": 0,
+                    "VideoGrayScale": false,
                     "VideoLevel": "3.1",
                     "VideoOptionExtra": "",
                     "VideoPreset": "medium",
                     "VideoQualitySlider": 22.0,
                     "VideoQualityType": 2,
                     "VideoTune": "",
-                    "VideoTurboTwoPass": 0,
-                    "VideoTwoPass": 0,
+                    "VideoTurboTwoPass": false,
+                    "VideoTwoPass": false,
                     "x264Option": "",
-                    "x264UseAdvancedOptions": 0
+                    "x264UseAdvancedOptions": false
                 },
                 {
-                    "AudioAllowAACPass": 1,
-                    "AudioAllowAC3Pass": 1,
-                    "AudioAllowDTSHDPass": 1,
-                    "AudioAllowDTSPass": 1,
-                    "AudioAllowMP3Pass": 1,
                     "AudioEncoderFallback": "ac3",
                     "AudioList": [
                         {
-                            "AudioBitrate": "160",
+                            "AudioBitrate": 160,
                             "AudioEncoder": "aac",
                             "AudioMixdown": "dpl2",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         }
                     ],
-                    "ChapterMarkers": 1,
-                    "Default": 0,
+                    "ChapterMarkers": true,
+                    "Default": false,
                     "FileFormat": "mp4",
                     "Folder": false,
-                    "Mp4HttpOptimize": 0,
-                    "Mp4iPodCompatible": 0,
-                    "PictureAutoCrop": 1,
+                    "Mp4HttpOptimize": false,
+                    "Mp4iPodCompatible": false,
+                    "PictureAutoCrop": true,
                     "PictureBottomCrop": 0,
                     "PictureDeblock": 0,
-                    "PictureDecomb": 0,
+                    "PictureDecomb": "off",
                     "PictureDecombCustom": "",
-                    "PictureDecombDeinterlace": 1,
-                    "PictureDeinterlace": 0,
+                    "PictureDecombDeinterlace": true,
+                    "PictureDeinterlace": "off",
                     "PictureDeinterlaceCustom": "",
                     "PictureDenoiseCustom": "",
                     "PictureDenoiseFilter": "off",
-                    "PictureDetelecine": 0,
+                    "PictureDetelecine": "off",
                     "PictureDetelecineCustom": "",
                     "PictureHeight": 720,
-                    "PictureKeepRatio": 0,
+                    "PictureKeepRatio": true,
                     "PictureLeftCrop": 0,
                     "PictureModulus": 2,
                     "PicturePAR": "loose",
                     "PresetDescription": "HandBrake's settings for playback on the iPad (all generations).",
                     "PresetName": "iPad",
                     "Type": 0,
-                    "UsesPictureFilters": 1,
+                    "UsesPictureFilters": true,
                     "UsesPictureSettings": 1,
-                    "VideoAvgBitrate": "2500",
+                    "VideoAvgBitrate": 2500,
                     "VideoEncoder": "x264",
                     "VideoFramerate": "30",
                     "VideoFramerateMode": "pfr",
-                    "VideoGrayScale": 0,
+                    "VideoGrayScale": false,
                     "VideoLevel": "3.1",
                     "VideoOptionExtra": "",
                     "VideoPreset": "medium",
                     "VideoQualitySlider": 20.0,
                     "VideoQualityType": 2,
                     "VideoTune": "",
-                    "VideoTurboTwoPass": 0,
-                    "VideoTwoPass": 0,
+                    "VideoTurboTwoPass": false,
+                    "VideoTwoPass": false,
                     "x264Option": "",
-                    "x264UseAdvancedOptions": 0
+                    "x264UseAdvancedOptions": false
                 },
                 {
-                    "AudioAllowAACPass": 1,
-                    "AudioAllowAC3Pass": 1,
-                    "AudioAllowDTSHDPass": 1,
-                    "AudioAllowDTSPass": 1,
-                    "AudioAllowMP3Pass": 1,
                     "AudioEncoderFallback": "ac3",
                     "AudioList": [
                         {
-                            "AudioBitrate": "160",
+                            "AudioBitrate": 160,
                             "AudioEncoder": "aac",
                             "AudioMixdown": "dpl2",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         },
                         {
-                            "AudioBitrate": "160",
+                            "AudioBitrate": 160,
                             "AudioEncoder": "copy:ac3",
                             "AudioMixdown": "none",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         }
                     ],
-                    "ChapterMarkers": 1,
-                    "Default": 0,
+                    "ChapterMarkers": true,
+                    "Default": false,
                     "FileFormat": "mp4",
                     "Folder": false,
-                    "Mp4HttpOptimize": 0,
-                    "Mp4iPodCompatible": 0,
-                    "PictureAutoCrop": 1,
+                    "Mp4HttpOptimize": false,
+                    "Mp4iPodCompatible": false,
+                    "PictureAutoCrop": true,
                     "PictureBottomCrop": 0,
                     "PictureDeblock": 0,
-                    "PictureDecomb": 0,
+                    "PictureDecomb": "off",
                     "PictureDecombCustom": "",
-                    "PictureDecombDeinterlace": 1,
-                    "PictureDeinterlace": 0,
+                    "PictureDecombDeinterlace": true,
+                    "PictureDeinterlace": "off",
                     "PictureDeinterlaceCustom": "",
                     "PictureDenoiseCustom": "",
                     "PictureDenoiseFilter": "off",
-                    "PictureDetelecine": 0,
+                    "PictureDetelecine": "off",
                     "PictureDetelecineCustom": "",
                     "PictureHeight": 720,
-                    "PictureKeepRatio": 0,
+                    "PictureKeepRatio": true,
                     "PictureLeftCrop": 0,
                     "PictureModulus": 2,
                     "PicturePAR": "loose",
                     "PresetDescription": "HandBrake's settings for the original AppleTV. Includes Dolby Digital audio for surround sound. Also compatible with iOS devices released since 2009.",
                     "PresetName": "AppleTV",
                     "Type": 0,
-                    "UsesPictureFilters": 1,
+                    "UsesPictureFilters": true,
                     "UsesPictureSettings": 1,
-                    "VideoAvgBitrate": "2500",
+                    "VideoAvgBitrate": 2500,
                     "VideoEncoder": "x264",
                     "VideoFramerate": "30",
                     "VideoFramerateMode": "pfr",
-                    "VideoGrayScale": 0,
+                    "VideoGrayScale": false,
                     "VideoLevel": "3.1",
                     "VideoOptionExtra": "qpmin=4:cabac=0:ref=2:b-pyramid=none:weightb=0:weightp=0:vbv-maxrate=9500:vbv-bufsize=9500",
                     "VideoPreset": "medium",
                     "VideoQualitySlider": 20.0,
                     "VideoQualityType": 2,
                     "VideoTune": "",
-                    "VideoTurboTwoPass": 0,
-                    "VideoTwoPass": 0,
+                    "VideoTurboTwoPass": false,
+                    "VideoTwoPass": false,
                     "x264Option": "",
-                    "x264UseAdvancedOptions": 0
+                    "x264UseAdvancedOptions": false
                 },
                 {
-                    "AudioAllowAACPass": 1,
-                    "AudioAllowAC3Pass": 1,
-                    "AudioAllowDTSHDPass": 1,
-                    "AudioAllowDTSPass": 1,
-                    "AudioAllowMP3Pass": 1,
                     "AudioEncoderFallback": "ac3",
                     "AudioList": [
                         {
-                            "AudioBitrate": "160",
+                            "AudioBitrate": 160,
                             "AudioEncoder": "aac",
                             "AudioMixdown": "dpl2",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         },
                         {
-                            "AudioBitrate": "160",
+                            "AudioBitrate": 160,
                             "AudioEncoder": "copy:ac3",
                             "AudioMixdown": "none",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         }
                     ],
-                    "ChapterMarkers": 1,
-                    "Default": 0,
+                    "ChapterMarkers": true,
+                    "Default": false,
                     "FileFormat": "mp4",
                     "Folder": false,
-                    "Mp4HttpOptimize": 0,
-                    "Mp4iPodCompatible": 0,
-                    "PictureAutoCrop": 1,
+                    "Mp4HttpOptimize": false,
+                    "Mp4iPodCompatible": false,
+                    "PictureAutoCrop": true,
                     "PictureBottomCrop": 0,
                     "PictureDeblock": 0,
-                    "PictureDecomb": 0,
+                    "PictureDecomb": "off",
                     "PictureDecombCustom": "",
-                    "PictureDecombDeinterlace": 1,
-                    "PictureDeinterlace": 0,
+                    "PictureDecombDeinterlace": true,
+                    "PictureDeinterlace": "off",
                     "PictureDeinterlaceCustom": "",
                     "PictureDenoiseCustom": "",
                     "PictureDenoiseFilter": "off",
-                    "PictureDetelecine": 0,
+                    "PictureDetelecine": "off",
                     "PictureDetelecineCustom": "",
                     "PictureHeight": 720,
-                    "PictureKeepRatio": 0,
+                    "PictureKeepRatio": true,
                     "PictureLeftCrop": 0,
                     "PictureModulus": 2,
                     "PicturePAR": "loose",
                     "PresetDescription": "HandBrake's settings for the second-generation AppleTV. Includes Dolby Digital audio for surround sound. NOT compatible with the original AppleTV.",
                     "PresetName": "AppleTV 2",
                     "Type": 0,
-                    "UsesPictureFilters": 1,
+                    "UsesPictureFilters": true,
                     "UsesPictureSettings": 1,
-                    "VideoAvgBitrate": "2500",
+                    "VideoAvgBitrate": 2500,
                     "VideoEncoder": "x264",
                     "VideoFramerate": "30",
                     "VideoFramerateMode": "pfr",
-                    "VideoGrayScale": 0,
+                    "VideoGrayScale": false,
                     "VideoLevel": "3.1",
                     "VideoOptionExtra": "",
                     "VideoPreset": "medium",
                     "VideoQualitySlider": 20.0,
                     "VideoQualityType": 2,
                     "VideoTune": "",
-                    "VideoTurboTwoPass": 0,
-                    "VideoTwoPass": 0,
+                    "VideoTurboTwoPass": false,
+                    "VideoTwoPass": false,
                     "x264Option": "",
-                    "x264UseAdvancedOptions": 0
+                    "x264UseAdvancedOptions": false
                 },
                 {
-                    "AudioAllowAACPass": 1,
-                    "AudioAllowAC3Pass": 1,
-                    "AudioAllowDTSHDPass": 1,
-                    "AudioAllowDTSPass": 1,
-                    "AudioAllowMP3Pass": 1,
                     "AudioEncoderFallback": "ac3",
                     "AudioList": [
                         {
-                            "AudioBitrate": "160",
+                            "AudioBitrate": 160,
                             "AudioEncoder": "aac",
                             "AudioMixdown": "dpl2",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         },
                         {
-                            "AudioBitrate": "160",
+                            "AudioBitrate": 160,
                             "AudioEncoder": "copy:ac3",
                             "AudioMixdown": "none",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         }
                     ],
-                    "ChapterMarkers": 1,
-                    "Default": 0,
+                    "ChapterMarkers": true,
+                    "Default": false,
                     "FileFormat": "mp4",
                     "Folder": false,
-                    "Mp4HttpOptimize": 0,
-                    "Mp4iPodCompatible": 0,
-                    "PictureAutoCrop": 1,
+                    "Mp4HttpOptimize": false,
+                    "Mp4iPodCompatible": false,
+                    "PictureAutoCrop": true,
                     "PictureBottomCrop": 0,
                     "PictureDeblock": 0,
-                    "PictureDecomb": 3,
+                    "PictureDecomb": "fast",
                     "PictureDecombCustom": "",
-                    "PictureDecombDeinterlace": 1,
-                    "PictureDeinterlace": 0,
+                    "PictureDecombDeinterlace": true,
+                    "PictureDeinterlace": "off",
                     "PictureDeinterlaceCustom": "",
                     "PictureDenoiseCustom": "",
                     "PictureDenoiseFilter": "off",
-                    "PictureDetelecine": 0,
+                    "PictureDetelecine": "off",
                     "PictureDetelecineCustom": "",
                     "PictureHeight": 1080,
-                    "PictureKeepRatio": 0,
+                    "PictureKeepRatio": true,
                     "PictureLeftCrop": 0,
                     "PictureModulus": 2,
                     "PicturePAR": "loose",
                     "PresetDescription": "HandBrake's settings for the third-generation AppleTV. Includes Dolby Digital audio for surround sound. NOT compatible with the original AppleTV. May stutter on the second-generation AppleTV.",
                     "PresetName": "AppleTV 3",
                     "Type": 0,
-                    "UsesPictureFilters": 1,
+                    "UsesPictureFilters": true,
                     "UsesPictureSettings": 1,
-                    "VideoAvgBitrate": "2500",
+                    "VideoAvgBitrate": 2500,
                     "VideoEncoder": "x264",
                     "VideoFramerate": "30",
                     "VideoFramerateMode": "pfr",
-                    "VideoGrayScale": 0,
+                    "VideoGrayScale": false,
                     "VideoLevel": "4.0",
                     "VideoOptionExtra": "",
                     "VideoPreset": "medium",
                     "VideoQualitySlider": 20.0,
                     "VideoQualityType": 2,
                     "VideoTune": "",
-                    "VideoTurboTwoPass": 0,
-                    "VideoTwoPass": 0,
+                    "VideoTurboTwoPass": false,
+                    "VideoTwoPass": false,
                     "x264Option": "",
-                    "x264UseAdvancedOptions": 0
+                    "x264UseAdvancedOptions": false
                 },
                 {
-                    "AudioAllowAACPass": 1,
-                    "AudioAllowAC3Pass": 1,
-                    "AudioAllowDTSHDPass": 1,
-                    "AudioAllowDTSPass": 1,
-                    "AudioAllowMP3Pass": 1,
                     "AudioEncoderFallback": "ac3",
                     "AudioList": [
                         {
-                            "AudioBitrate": "128",
+                            "AudioBitrate": 128,
                             "AudioEncoder": "aac",
                             "AudioMixdown": "dpl2",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         }
                     ],
-                    "ChapterMarkers": 0,
-                    "Default": 0,
+                    "ChapterMarkers": false,
+                    "Default": false,
                     "FileFormat": "mp4",
                     "Folder": false,
-                    "Mp4HttpOptimize": 0,
-                    "Mp4iPodCompatible": 0,
-                    "PictureAutoCrop": 1,
+                    "Mp4HttpOptimize": false,
+                    "Mp4iPodCompatible": false,
+                    "PictureAutoCrop": true,
                     "PictureBottomCrop": 0,
                     "PictureDeblock": 0,
-                    "PictureDecomb": 0,
+                    "PictureDecomb": "off",
                     "PictureDecombCustom": "",
-                    "PictureDecombDeinterlace": 1,
-                    "PictureDeinterlace": 0,
+                    "PictureDecombDeinterlace": true,
+                    "PictureDeinterlace": "off",
                     "PictureDeinterlaceCustom": "",
                     "PictureDenoiseCustom": "",
                     "PictureDenoiseFilter": "off",
-                    "PictureDetelecine": 0,
+                    "PictureDetelecine": "off",
                     "PictureDetelecineCustom": "",
                     "PictureHeight": 576,
-                    "PictureKeepRatio": 0,
+                    "PictureKeepRatio": true,
                     "PictureLeftCrop": 0,
                     "PictureModulus": 2,
                     "PicturePAR": "loose",
                     "PresetDescription": "HandBrake's settings for midrange devices running Android 2.3 or later.",
                     "PresetName": "Android",
                     "Type": 0,
-                    "UsesPictureFilters": 1,
+                    "UsesPictureFilters": true,
                     "UsesPictureSettings": 1,
-                    "VideoAvgBitrate": "2500",
+                    "VideoAvgBitrate": 2500,
                     "VideoEncoder": "x264",
                     "VideoFramerate": "30",
                     "VideoFramerateMode": "pfr",
-                    "VideoGrayScale": 0,
+                    "VideoGrayScale": false,
                     "VideoLevel": "3.0",
                     "VideoOptionExtra": "",
                     "VideoPreset": "medium",
                     "VideoQualitySlider": 22.0,
                     "VideoQualityType": 2,
                     "VideoTune": "",
-                    "VideoTurboTwoPass": 0,
-                    "VideoTwoPass": 0,
+                    "VideoTurboTwoPass": false,
+                    "VideoTwoPass": false,
                     "x264Option": "",
-                    "x264UseAdvancedOptions": 0
+                    "x264UseAdvancedOptions": false
                 },
                 {
-                    "AudioAllowAACPass": 1,
-                    "AudioAllowAC3Pass": 1,
-                    "AudioAllowDTSHDPass": 1,
-                    "AudioAllowDTSPass": 1,
-                    "AudioAllowMP3Pass": 1,
                     "AudioEncoderFallback": "ac3",
                     "AudioList": [
                         {
-                            "AudioBitrate": "128",
+                            "AudioBitrate": 128,
                             "AudioEncoder": "aac",
                             "AudioMixdown": "dpl2",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         }
                     ],
-                    "ChapterMarkers": 0,
-                    "Default": 0,
+                    "ChapterMarkers": false,
+                    "Default": false,
                     "FileFormat": "mp4",
                     "Folder": false,
-                    "Mp4HttpOptimize": 0,
-                    "Mp4iPodCompatible": 0,
-                    "PictureAutoCrop": 1,
+                    "Mp4HttpOptimize": false,
+                    "Mp4iPodCompatible": false,
+                    "PictureAutoCrop": true,
                     "PictureBottomCrop": 0,
                     "PictureDeblock": 0,
-                    "PictureDecomb": 0,
+                    "PictureDecomb": "off",
                     "PictureDecombCustom": "",
-                    "PictureDecombDeinterlace": 1,
-                    "PictureDeinterlace": 0,
+                    "PictureDecombDeinterlace": true,
+                    "PictureDeinterlace": "off",
                     "PictureDeinterlaceCustom": "",
                     "PictureDenoiseCustom": "",
                     "PictureDenoiseFilter": "off",
-                    "PictureDetelecine": 0,
+                    "PictureDetelecine": "off",
                     "PictureDetelecineCustom": "",
                     "PictureHeight": 720,
-                    "PictureKeepRatio": 0,
+                    "PictureKeepRatio": true,
                     "PictureLeftCrop": 0,
                     "PictureModulus": 2,
                     "PicturePAR": "loose",
                     "PresetDescription": "HandBrake's preset for tablets running Android 2.3 or later.",
                     "PresetName": "Android Tablet",
                     "Type": 0,
-                    "UsesPictureFilters": 1,
+                    "UsesPictureFilters": true,
                     "UsesPictureSettings": 1,
-                    "VideoAvgBitrate": "2500",
+                    "VideoAvgBitrate": 2500,
                     "VideoEncoder": "x264",
                     "VideoFramerate": "30",
                     "VideoFramerateMode": "pfr",
-                    "VideoGrayScale": 0,
+                    "VideoGrayScale": false,
                     "VideoLevel": "3.1",
                     "VideoOptionExtra": "",
                     "VideoPreset": "medium",
                     "VideoQualitySlider": 22.0,
                     "VideoQualityType": 2,
                     "VideoTune": "",
-                    "VideoTurboTwoPass": 0,
-                    "VideoTwoPass": 0,
+                    "VideoTurboTwoPass": false,
+                    "VideoTwoPass": false,
                     "x264Option": "",
-                    "x264UseAdvancedOptions": 0
+                    "x264UseAdvancedOptions": false
                 },
                 {
-                    "AudioAllowAACPass": 1,
-                    "AudioAllowAC3Pass": 1,
-                    "AudioAllowDTSHDPass": 1,
-                    "AudioAllowDTSPass": 1,
-                    "AudioAllowMP3Pass": 1,
                     "AudioEncoderFallback": "ac3",
                     "AudioList": [
                         {
-                            "AudioBitrate": "128",
+                            "AudioBitrate": 128,
                             "AudioEncoder": "aac",
                             "AudioMixdown": "dpl2",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         }
                     ],
-                    "ChapterMarkers": 0,
-                    "Default": 0,
+                    "ChapterMarkers": false,
+                    "Default": false,
                     "FileFormat": "mp4",
                     "Folder": false,
-                    "Mp4HttpOptimize": 0,
-                    "Mp4iPodCompatible": 0,
-                    "PictureAutoCrop": 1,
+                    "Mp4HttpOptimize": false,
+                    "Mp4iPodCompatible": false,
+                    "PictureAutoCrop": true,
                     "PictureBottomCrop": 0,
                     "PictureDeblock": 0,
-                    "PictureDecomb": 0,
+                    "PictureDecomb": "off",
                     "PictureDecombCustom": "",
-                    "PictureDecombDeinterlace": 1,
-                    "PictureDeinterlace": 0,
+                    "PictureDecombDeinterlace": true,
+                    "PictureDeinterlace": "off",
                     "PictureDeinterlaceCustom": "",
                     "PictureDenoiseCustom": "",
                     "PictureDenoiseFilter": "off",
-                    "PictureDetelecine": 0,
+                    "PictureDetelecine": "off",
                     "PictureDetelecineCustom": "",
                     "PictureHeight": 720,
-                    "PictureKeepRatio": 1,
+                    "PictureKeepRatio": true,
                     "PictureLeftCrop": 0,
                     "PictureModulus": 2,
                     "PicturePAR": "off",
                     "PresetDescription": "HandBrake's preset for Windows Phone 8 devices",
                     "PresetName": "Windows Phone 8",
                     "Type": 0,
-                    "UsesPictureFilters": 1,
+                    "UsesPictureFilters": true,
                     "UsesPictureSettings": 1,
-                    "VideoAvgBitrate": "2500",
+                    "VideoAvgBitrate": 2500,
                     "VideoEncoder": "x264",
                     "VideoFramerate": "30",
                     "VideoFramerateMode": "pfr",
-                    "VideoGrayScale": 0,
+                    "VideoGrayScale": false,
                     "VideoLevel": "3.1",
                     "VideoOptionExtra": "",
                     "VideoPreset": "medium",
                     "VideoQualitySlider": 22.0,
                     "VideoQualityType": 2,
                     "VideoTune": "",
-                    "VideoTurboTwoPass": 0,
-                    "VideoTwoPass": 0,
+                    "VideoTurboTwoPass": false,
+                    "VideoTwoPass": false,
                     "x264Option": "",
-                    "x264UseAdvancedOptions": 0
+                    "x264UseAdvancedOptions": false
                 }
             ],
-            "Default": 0,
             "Folder": true,
             "PresetName": "Devices",
             "Type": 0
         {
             "ChildrenArray": [
                 {
-                    "AudioAllowAACPass": 1,
-                    "AudioAllowAC3Pass": 1,
-                    "AudioAllowDTSHDPass": 1,
-                    "AudioAllowDTSPass": 1,
-                    "AudioAllowMP3Pass": 1,
                     "AudioEncoderFallback": "ac3",
                     "AudioList": [
                         {
-                            "AudioBitrate": "160",
+                            "AudioBitrate": 160,
                             "AudioEncoder": "aac",
                             "AudioMixdown": "dpl2",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         }
                     ],
-                    "ChapterMarkers": 1,
-                    "Default": 1,
+                    "ChapterMarkers": true,
+                    "Default": true,
                     "FileFormat": "mp4",
                     "Folder": false,
-                    "Mp4HttpOptimize": 0,
-                    "Mp4iPodCompatible": 0,
-                    "PictureAutoCrop": 1,
+                    "Mp4HttpOptimize": false,
+                    "Mp4iPodCompatible": false,
+                    "PictureAutoCrop": true,
                     "PictureBottomCrop": 0,
                     "PictureDeblock": 0,
-                    "PictureDecomb": 0,
+                    "PictureDecomb": "off",
                     "PictureDecombCustom": "",
-                    "PictureDecombDeinterlace": 1,
-                    "PictureDeinterlace": 0,
+                    "PictureDecombDeinterlace": true,
+                    "PictureDeinterlace": "off",
                     "PictureDeinterlaceCustom": "",
                     "PictureDenoiseCustom": "",
                     "PictureDenoiseFilter": "off",
-                    "PictureDetelecine": 0,
+                    "PictureDetelecine": "off",
                     "PictureDetelecineCustom": "",
                     "PictureHeight": 0,
-                    "PictureKeepRatio": 0,
+                    "PictureKeepRatio": true,
                     "PictureLeftCrop": 0,
                     "PictureModulus": 2,
                     "PicturePAR": "loose",
                     "PresetDescription": "HandBrake's normal, default settings.",
                     "PresetName": "Normal",
                     "Type": 0,
-                    "UsesPictureFilters": 1,
+                    "UsesPictureFilters": true,
                     "UsesPictureSettings": 1,
-                    "VideoAvgBitrate": "2500",
+                    "VideoAvgBitrate": 2500,
                     "VideoEncoder": "x264",
                     "VideoFramerate": "auto",
                     "VideoFramerateMode": "vfr",
-                    "VideoGrayScale": 0,
+                    "VideoGrayScale": false,
                     "VideoLevel": "4.0",
                     "VideoOptionExtra": "",
                     "VideoPreset": "veryfast",
                     "VideoQualitySlider": 20.0,
                     "VideoQualityType": 2,
                     "VideoTune": "",
-                    "VideoTurboTwoPass": 0,
-                    "VideoTwoPass": 0,
+                    "VideoTurboTwoPass": false,
+                    "VideoTwoPass": false,
                     "x264Option": "",
-                    "x264UseAdvancedOptions": 0
+                    "x264UseAdvancedOptions": false
                 },
                 {
-                    "AudioAllowAACPass": 1,
-                    "AudioAllowAC3Pass": 1,
-                    "AudioAllowDTSHDPass": 1,
-                    "AudioAllowDTSPass": 1,
-                    "AudioAllowMP3Pass": 1,
                     "AudioEncoderFallback": "ac3",
                     "AudioList": [
                         {
-                            "AudioBitrate": "160",
+                            "AudioBitrate": 160,
                             "AudioEncoder": "aac",
                             "AudioMixdown": "dpl2",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         },
                         {
-                            "AudioBitrate": "160",
+                            "AudioBitrate": 160,
                             "AudioEncoder": "copy:ac3",
                             "AudioMixdown": "none",
                             "AudioSamplerate": "auto",
-                            "AudioTrack": 1,
                             "AudioTrackDRCSlider": 0.0,
                             "AudioTrackGainSlider": 0.0
                         }
                     ],
-                    "ChapterMarkers": 1,
-                    "Default": 0,
+                    "ChapterMarkers": true,
+                    "Default": false,
                     "FileFormat": "mp4",
                     "Folder": false,
-                    "Mp4HttpOptimize": 0,
-                    "Mp4iPodCompatible": 0,
-                    "PictureAutoCrop": 1,
+                    "Mp4HttpOptimize": false,
+                    "Mp4iPodCompatible": false,
+                    "PictureAutoCrop": true,
                     "PictureBottomCrop": 0,
                     "PictureDeblock": 0,
-                    "PictureDecomb": 2,
+                    "PictureDecomb": "default",
                     "PictureDecombCustom": "",
-                    "PictureDecombDeinterlace": 1,
-                    "PictureDeinterlace": 0,
+                    "PictureDecombDeinterlace": true,
+                    "PictureDeinterlace": "off",
                     "PictureDeinterlaceCustom": "",
                     "PictureDenoiseCustom": "",
                     "PictureDenoiseFilter": "off",
-                    "PictureDetelecine": 0,
+                    "PictureDetelecine": "off",
                     "PictureDetelecineCustom": "",
                     "PictureHeight": 0,
-                    "PictureKeepRatio": 0,
+                    "PictureKeepRatio": true,
                     "PictureLeftCrop": 0,
                     "PictureModulus": 2,
                     "PicturePAR": "loose",
                     "PresetDescription": "HandBrake's general-purpose preset for High Profile H.264 video.",
                     "PresetName": "High Profile",
                     "Type": 0,
-                    "UsesPictureFilters": 1,
+                    "UsesPictureFilters": true,
                     "UsesPictureSettings": 1,
-                    "VideoAvgBitrate": "2500",
+                    "VideoAvgBitrate": 2500,
                     "VideoEncoder": "x264",
                     "VideoFramerate": "auto",
                     "VideoFramerateMode": "vfr",
-                    "VideoGrayScale": 0,
+                    "VideoGrayScale": false,
                     "VideoLevel": "4.1",
                     "VideoOptionExtra": "",
                     "VideoPreset": "medium",
                     "VideoQualitySlider": 20.0,
                     "VideoQualityType": 2,
                     "VideoTune": "",
-                    "VideoTurboTwoPass": 0,
-                    "VideoTwoPass": 0,
+                    "VideoTurboTwoPass": false,
+                    "VideoTwoPass": false,
                     "x264Option": "",
-                    "x264UseAdvancedOptions": 0
+                    "x264UseAdvancedOptions": false
                 }
             ],
-            "Default": 0,
             "Folder": true,
             "PresetName": "Regular",
             "Type": 0
index 30449e437edd3bdae53ec0de1b97ec65929f7dc5..c0a650703088cfd5306804e11446206cf706e860 100644 (file)
@@ -1,12 +1,4 @@
     {
-        "AudioAllowMP3Pass": false,
-        "AudioAllowAACPass": false,
-        "AudioAllowAC3Pass": true,
-        "AudioAllowDTSPass": false,
-        "AudioAllowDTSHDPass": false,
-        "AudioAllowEAC3Pass": false,
-        "AudioAllowFLACPass": false,
-        "AudioAllowTRUEHDPass": false,
         "AudioCopyMask": [
         ],
         "AudioEncoderFallback": "ac3",
@@ -15,7 +7,7 @@
         ],
         "AudioList": [
             {
-                "AudioBitrate": "192",
+                "AudioBitrate": 192,
                 "AudioCompressionLevel": -1.0,
                 "AudioDitherMethod": "auto",
                 "AudioEncoder": "copy:ac3",
         "AudioSecondaryEncoderMode": true,
         "AudioTrackSelectionBehavior": "first",
         "ChapterMarkers": true,
+        "ChildrenArray": [
+        ],
         "Default": false,
         "FileFormat": "mp4",
         "Folder": false,
+        "FolderOpen": false,
         "Mp4HttpOptimize": false,
         "Mp4iPodCompatible": false,
         "PictureAutoCrop": true,
index 3168e1fde7303a98fab284dbb879ed587e5862a2..6d891b42618c3507de58b8de30f483792e6bde8b 100644 (file)
@@ -233,10 +233,19 @@ void hb_display_job_info(hb_job_t *job)
         sec_stop = (float)stop / 90000.0 - min_stop * 60;
         min_stop %= 60;
 
-        hb_log("   + title %d, start %02d:%02d:%02.2f stop %02d:%02d:%02.2f",
-               title->index,
-               hr_start, min_start, sec_start,
-               hr_stop,  min_stop,  sec_stop);
+        if (job->pts_to_stop)
+        {
+            hb_log("   + title %d, start %02d:%02d:%02.2f stop %02d:%02d:%02.2f",
+                   title->index,
+                   hr_start, min_start, sec_start,
+                   hr_stop,  min_stop,  sec_stop);
+        }
+        else
+        {
+            hb_log("   + title %d, start %02d:%02d:%02.2f",
+                   title->index,
+                   hr_start, min_start, sec_start);
+        }
     }
     else if( job->frame_to_start || job->frame_to_stop )
     {
index 95921d31774599360f50667357a6ed322c067aab..26f7acd1cdc75dd2c832a82840dedeea1d217952 100755 (executable)
@@ -58,7 +58,7 @@ def start_element_handler(tag, attr):
         elif fname == None:
             print >> sys.stderr, ( "Error: No such plist file %s" % fbase )
             sys.exit(1)
-    elif tag == "string":
+    elif tag == "text":
         fbase = attr["file"]
         fname = find_file(fbase)
         key = attr["name"]
@@ -72,6 +72,9 @@ def start_element_handler(tag, attr):
         elif fname == None:
             print >> sys.stderr, ( "Error: No such string file %s" % fbase )
             sys.exit(1)
+    elif tag == "string":
+        key = attr["name"]
+        val = attr["value"]
 
     if val != None:
         if type(current) == types.DictType:
index 1026eae9359bfd8e16795529a402f03593ec4f66..eb49183191746cc237a9a215c691efd56d161152 100644 (file)
@@ -255,7 +255,7 @@ int main( int argc, char ** argv )
     char        * version;
 
     hb_global_init();
-
+    hb_presets_builtin_update();
 
     // Get utf8 command line if windows
     get_argv_utf8(&argc, &argv);
@@ -326,12 +326,12 @@ int main( int argc, char ** argv )
         }
         if (preset_export_file != NULL)
         {
-            hb_preset_write_json(preset_dict, preset_export_file);
+            hb_presets_write_json(preset_dict, preset_export_file);
         }
         else
         {
             char *json;
-            json = hb_preset_package_json(preset_dict);
+            json = hb_presets_package_json(preset_dict);
             fprintf(stdout, "%s\n", json);
         }
         // If the user requested to export a preset, but not to
@@ -2776,7 +2776,7 @@ static hb_dict_t * PreparePreset(const char *preset_name)
 
     if (preset_name != NULL)
     {
-        preset = hb_preset_get(preset_name, 1 /*recurse*/);
+        preset = hb_preset_search(preset_name, 1 /*recurse*/);
         if (preset == NULL)
         {
             fprintf(stderr, "Invalid preset %s\n"
@@ -2794,6 +2794,7 @@ static hb_dict_t * PreparePreset(const char *preset_name)
         fprintf(stderr, "Error loading presets! Aborting.\n");
         return NULL;
     }
+    preset = hb_value_dup(preset);
 
     int subtitle_track_count = count_subtitles(subtracks);
     // Apply any overrides that can be made directly to the preset