]> granicus.if.org Git - handbrake/commitdiff
presets: enforce 2 level hierarchy when importing presets
authorJohn Stebbins <jstebbins.hb@gmail.com>
Fri, 29 Sep 2017 23:32:07 +0000 (16:32 -0700)
committerJohn Stebbins <jstebbins.hb@gmail.com>
Mon, 6 Nov 2017 16:19:49 +0000 (08:19 -0800)
See https://github.com/HandBrake/HandBrake/issues/833#issuecomment-333193971

libhb/hb_dict.h
libhb/preset.c
libhb/preset_builtin.h
preset/preset_builtin.list

index ef17113aecfa8e7a8a2f2bc07ea5bfc0d191a138..0696455eb672708d63b754696ffe7fbe234aea3a 100644 (file)
@@ -159,4 +159,10 @@ char      * hb_dict_to_encopts(const hb_dict_t * dict);
 #define hb_dict_get_double(dict, key) hb_value_get_double(hb_dict_get(dict, key))
 #define hb_dict_get_bool(dict, key) hb_value_get_bool(hb_dict_get(dict, key))
 
+#define hb_dict_set_string(dict, key, val) hb_dict_set(dict, key, hb_value_string(val))
+#define hb_dict_set_int(dict, key, val) hb_dict_set(dict, key, hb_value_int(val))
+#define hb_dict_set_double(dict, key, val) hb_dict_set(dict, key, hb_value_double(val))
+#define hb_dict_set_bool(dict, key, val) hb_dict_set(dict, key, hb_value_bool(val))
+
+
 #endif // !defined(HB_DICT_H)
index 19a013211944e101b4c321a52712eccc5d387915..4f8a62534bb2e2d746618e6ebb35f15413d9a0eb 100644 (file)
@@ -2223,6 +2223,190 @@ void hb_presets_clean(hb_value_t *preset)
     presets_clean(preset, hb_preset_template);
 }
 
+static char * fix_name_collisions(hb_value_t * list, const char * name)
+{
+    char * new_name = strdup(name);
+    int    ii, jj, count;
+
+    count = hb_value_array_len(list);
+    for (ii = 0, jj = 0; ii < count; ii++)
+    {
+        hb_value_t * item = hb_value_array_get(list, ii);
+        const char * preset_name;
+
+        preset_name = hb_dict_get_string(item, "PresetName");
+        if (!strcmp(new_name, preset_name))
+        {
+            // Collision, add a number and try again
+            free(new_name);
+            new_name = hb_strdup_printf("%s - %d", name, jj++);
+            ii = -1;
+        }
+    }
+    return new_name;
+}
+
+static void import_folder_hierarchy_29_0_0(const char * name,
+                                    hb_value_t * new_list, hb_value_t * folder)
+{
+    hb_value_t * list = hb_dict_get(folder, "ChildrenArray");
+    int          ii, count;
+
+    count = hb_value_array_len(list);
+    for (ii = 0; ii < count;)
+    {
+        hb_value_t * item = hb_value_array_get(list, ii);
+
+        if (hb_dict_get_bool(item, "Folder"))
+        {
+            const char * folder_name;
+            char       * new_name;
+            int          pos = hb_value_array_len(new_list);
+
+            folder_name = hb_dict_get_string(item, "PresetName");
+            new_name = hb_strdup_printf("%s - %s", name, folder_name);
+            import_folder_hierarchy_29_0_0(new_name, new_list, item);
+
+            hb_value_t * children = hb_dict_get(item, "ChildrenArray");
+            if (hb_value_array_len(children) > 0)
+            {
+                // If the folder has any children, move it to the
+                // top level folder list.
+                char * unique_name = fix_name_collisions(new_list, new_name);
+                hb_dict_set_string(item, "PresetName", unique_name);
+                hb_value_incref(item);
+                hb_value_array_remove(list, ii);
+                hb_value_array_insert(new_list, pos, item);
+                free(unique_name);
+            }
+            else
+            {
+                hb_value_array_remove(list, ii);
+            }
+            free(new_name);
+        }
+        else
+        {
+            ii++;
+        }
+    }
+}
+
+static hb_value_t * import_hierarchy_29_0_0(hb_value_t *presets)
+{
+    hb_value_t * list = presets;
+    hb_value_t * my_presets = NULL;
+    hb_value_t * my_presets_list;
+    hb_value_t * new_list;
+    int          ii, count;
+
+    if (hb_value_type(presets) == HB_VALUE_TYPE_DICT &&
+        hb_dict_get(presets, "VersionMajor") != NULL)
+    {
+        // A packaged preset list
+        list = hb_dict_get(presets, "PresetList");
+    }
+
+    // Copy official presets to new list
+    new_list = hb_value_array_init();
+    count = hb_value_array_len(list);
+    for (ii = 0; ii < count; ii++)
+    {
+        hb_value_t * item = hb_value_array_get(list, ii);
+        if (hb_dict_get_int(item, "Type") != HB_PRESET_TYPE_OFFICIAL)
+        {
+            continue;
+        }
+        hb_value_array_append(new_list, hb_value_dup(item));
+    }
+
+    // First process any custom folder named "My Presets".
+    // Any existing "My Presets" folder is sanitized for subfolders.
+    // If "My Presets" doesn't exist, one is created.
+    count = hb_value_array_len(list);
+    for (ii = 0; ii < count; ii++)
+    {
+        hb_value_t * item = hb_value_array_get(list, ii);
+
+        if (hb_dict_get_int(item, "Type") == HB_PRESET_TYPE_OFFICIAL)
+        {
+            // Skip official presets.  The don't need to be restructured.
+            continue;
+        }
+        if (hb_dict_get_bool(item, "Folder"))
+        {
+            int          pos = hb_value_array_len(new_list);
+            const char * name = hb_dict_get_string(item, "PresetName");
+            if (strcmp(name, "My Presets"))
+            {
+                continue;
+            }
+            import_folder_hierarchy_29_0_0(name, new_list, item);
+
+            my_presets = hb_value_dup(item);
+            hb_value_array_insert(new_list, pos, my_presets);
+            hb_value_array_remove(list, ii);
+            break;
+        }
+    }
+    if (my_presets == NULL)
+    {
+        my_presets = hb_dict_init();
+        hb_dict_set_string(my_presets, "PresetName", "My Presets");
+        hb_dict_set(my_presets, "ChildrenArray", hb_value_array_init());
+        hb_dict_set_int(my_presets, "Type", HB_PRESET_TYPE_CUSTOM);
+        hb_dict_set_bool(my_presets, "Folder", 1);
+        hb_value_array_append(new_list, my_presets);
+    }
+    my_presets_list = hb_dict_get(my_presets, "ChildrenArray");
+
+    // Sanitize all other custom folders
+    count = hb_value_array_len(list);
+    for (ii = 0; ii < count; ii++)
+    {
+        hb_value_t * item = hb_value_array_get(list, ii);
+
+        if (hb_dict_get_int(item, "Type") == HB_PRESET_TYPE_OFFICIAL)
+        {
+            // Skip official presets.  The don't need to be restructured.
+            continue;
+        }
+        if (hb_dict_get_bool(item, "Folder"))
+        {
+            int          pos  = hb_value_array_len(new_list);
+            const char * name = hb_dict_get_string(item, "PresetName");
+            import_folder_hierarchy_29_0_0(name, new_list, item);
+
+            hb_value_t * children = hb_dict_get(item, "ChildrenArray");
+            if (hb_value_array_len(children) > 0)
+            {
+                // If the folder has any children, move it to the
+                // top level folder list.
+                char * unique_name = fix_name_collisions(new_list, name);
+                hb_dict_set_string(item, "PresetName", unique_name);
+                hb_value_array_insert(new_list, pos, hb_value_dup(item));
+                free(unique_name);
+            }
+        }
+        else
+        {
+            hb_value_array_append(my_presets_list, hb_value_dup(item));
+        }
+    }
+
+    if (hb_value_type(presets) == HB_VALUE_TYPE_DICT &&
+        hb_dict_get(presets, "VersionMajor") != NULL)
+    {
+        // A packaged preset list
+        hb_dict_set(presets, "PresetList", new_list);
+    }
+    else
+    {
+        presets = new_list;
+    }
+    return hb_value_dup(presets);
+}
+
 static void import_video_scaler_25_0_0(hb_value_t *preset)
 {
     hb_dict_set(preset, "VideoScaler", hb_value_string("swscale"));
@@ -3016,7 +3200,15 @@ int hb_presets_import(const hb_value_t *in, hb_value_t **out)
     dup = hb_value_dup(in);
     hb_presets_version(dup, &ctx.major, &ctx.minor, &ctx.micro);
     presets_do(do_preset_import, dup, (preset_do_context_t*)&ctx);
-    if (ctx.result)
+    if (cmpVersion(ctx.major, ctx.minor, ctx.micro, 29, 0, 0) <= 0)
+    {
+        hb_value_t * tmp;
+
+        tmp  = import_hierarchy_29_0_0(dup);
+        *out = hb_presets_update_version(tmp);
+        hb_value_free(&tmp);
+    }
+    else if (ctx.result)
     {
         *out = hb_presets_update_version(dup);
     }
index a0c82766af8b3b349d090e9a5e79bf7a0fe5b4df..20c1f71fbbeb9a3505fcc3f6d9c97877afb282f9 100644 (file)
@@ -8327,7 +8327,7 @@ const char hb_builtin_presets_json[] =
 "            \"x264Option\": \"\", \n"
 "            \"x264UseAdvancedOptions\": false\n"
 "        }, \n"
-"        \"VersionMajor\": 29, \n"
+"        \"VersionMajor\": 30, \n"
 "        \"VersionMicro\": 0, \n"
 "        \"VersionMinor\": 0\n"
 "    }\n"
index ff85b96b2255509e27307d626967d5f13d7f97ad..74d159ec7f6d64a3bb7f1607f65df829d004e2f6 100644 (file)
@@ -1,6 +1,6 @@
 <resources>
     <section name="PresetTemplate">
-        <integer name="VersionMajor" value="29" />
+        <integer name="VersionMajor" value="30" />
         <integer name="VersionMinor" value="0" />
         <integer name="VersionMicro" value="0" />
         <json name="Preset" file="preset_template.json" />