diff options
author | John Stebbins <[email protected]> | 2017-09-29 16:32:07 -0700 |
---|---|---|
committer | John Stebbins <[email protected]> | 2017-11-06 08:19:49 -0800 |
commit | d438e35c7edf9a94cddb7853fe68a50207d1027d (patch) | |
tree | 285bcb1d34757cbf409f57e6172a810f32865830 /libhb | |
parent | 42da759bcff01de6c4a7b6311312e0d2fbbf76fe (diff) |
presets: enforce 2 level hierarchy when importing presets
See https://github.com/HandBrake/HandBrake/issues/833#issuecomment-333193971
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/hb_dict.h | 6 | ||||
-rw-r--r-- | libhb/preset.c | 194 | ||||
-rw-r--r-- | libhb/preset_builtin.h | 2 |
3 files changed, 200 insertions, 2 deletions
diff --git a/libhb/hb_dict.h b/libhb/hb_dict.h index ef17113ae..0696455eb 100644 --- a/libhb/hb_dict.h +++ b/libhb/hb_dict.h @@ -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) diff --git a/libhb/preset.c b/libhb/preset.c index 19a013211..4f8a62534 100644 --- a/libhb/preset.c +++ b/libhb/preset.c @@ -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); } diff --git a/libhb/preset_builtin.h b/libhb/preset_builtin.h index a0c82766a..20c1f71fb 100644 --- a/libhb/preset_builtin.h +++ b/libhb/preset_builtin.h @@ -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" |