diff --git a/src/framework/metaschema.yaml b/src/framework/metaschema.yaml index ce349e10b..dd6d95817 100644 --- a/src/framework/metaschema.yaml +++ b/src/framework/metaschema.yaml @@ -184,4 +184,6 @@ mapping: "normalized_coordinates": # For types that represent coordinates, whether values are normalized to 0..1 type: bool default: no - + "normalized_default": # Whether the default value is normalized to 0..1 + type: bool + default: no diff --git a/src/modules/openfx/filter_openfx.c b/src/modules/openfx/filter_openfx.c index 7f65c3cdb..19bb1f313 100644 --- a/src/modules/openfx/filter_openfx.c +++ b/src/modules/openfx/filter_openfx.c @@ -223,19 +223,31 @@ static void update_plugin_params(mlt_properties properties, if (!mlt_properties_exists(properties, param_name)) continue; char *type = mlt_properties_get(param, "type"); - char *widget = mlt_properties_get(param, "widget"); if (!type) continue; - if (widget && (strcmp(widget, "point") == 0 || strcmp(widget, "size") == 0) - && strcmp(type, "float") == 0) { + if (strcmp(type, "rect") == 0) { mlt_rect value = mlt_properties_anim_get_rect(properties, param_name, position, length); - mltofx_param_set_value(image_effect_params, param_name, mltofx_prop_double2d, value); - } else if (widget && (strcmp(widget, "point") == 0 || strcmp(widget, "size") == 0) - && strcmp(type, "integer") == 0) { - mlt_rect value = mlt_properties_anim_get_rect(properties, param_name, position, length); - int x = (int) value.x; - int y = (int) value.y; - mltofx_param_set_value(image_effect_params, param_name, mltofx_prop_int2d, x, y); + // Look up the native OFX param type to select the correct setter + mlt_properties ofx_param = mlt_properties_get_properties(image_effect_params, + param_name); + const char *ofx_type = ofx_param ? mlt_properties_get(ofx_param, "t") : NULL; + if (ofx_type && strcmp(ofx_type, kOfxParamTypeInteger2D) == 0) + mltofx_param_set_value(image_effect_params, + param_name, + mltofx_prop_int2d, + (int) value.x, + (int) value.y); + else if (ofx_type && strcmp(ofx_type, kOfxParamTypeDouble3D) == 0) + mltofx_param_set_value(image_effect_params, param_name, mltofx_prop_double3d, value); + else if (ofx_type && strcmp(ofx_type, kOfxParamTypeInteger3D) == 0) + mltofx_param_set_value(image_effect_params, + param_name, + mltofx_prop_int3d, + (int) value.x, + (int) value.y, + (int) value.w); + else + mltofx_param_set_value(image_effect_params, param_name, mltofx_prop_double2d, value); } else if (strcmp(type, "float") == 0) { double value = mlt_properties_anim_get_double(properties, param_name, position, length); mltofx_param_set_value(image_effect_params, param_name, mltofx_prop_double, value); diff --git a/src/modules/openfx/mlt_openfx.c b/src/modules/openfx/mlt_openfx.c index ee2245f2a..fd8abdd9c 100644 --- a/src/modules/openfx/mlt_openfx.c +++ b/src/modules/openfx/mlt_openfx.c @@ -731,6 +731,8 @@ static OfxStatus paramDefine(OfxParamSetHandle paramSet, mlt_properties param_props = mlt_properties_new(); mlt_properties_set_properties(pt, "p", param_props); mlt_properties_close(param_props); + // Back-reference to the paramSet so paramGetValueImpl can navigate to image_effect. + mlt_properties_set_data(pt, "_ps", params, 0, NULL, NULL); mlt_properties_set_properties(params, name, pt); mlt_properties_close(pt); @@ -1039,6 +1041,53 @@ static OfxStatus paramGetValueImpl(OfxParamHandle paramHandle, va_list ap) if (status != kOfxStatOK) { *X = 0.0; *Y = 0.0; + } else { + // If the default was declared in normalised coordinates, convert to canonical. + // kOfxParamPropDefaultCoordinateSystem may be set on the effect descriptor + // (via getPropertySet) rather than on the individual param descriptor. + mlt_properties paramset = mlt_properties_get_data(param, "_ps", NULL); + mlt_properties plugin_props = paramset + ? mlt_properties_get_properties(paramset, + "plugin_props") + : NULL; + mlt_properties ie = plugin_props + ? (mlt_properties) mlt_properties_get_data(plugin_props, + "_ie", + NULL) + : NULL; + char *coord_sys = kOfxParamCoordinatesCanonical; + OfxStatus cs_on_param = propGetString((OfxPropertySetHandle) param_props, + kOfxParamPropDefaultCoordinateSystem, + 0, + &coord_sys); + if (cs_on_param != kOfxStatOK) { + coord_sys = kOfxParamCoordinatesCanonical; + if (ie) { + mlt_properties effect_props = mlt_properties_get_properties(ie, "props"); + if (effect_props) + propGetString((OfxPropertySetHandle) effect_props, + kOfxParamPropDefaultCoordinateSystem, + 0, + &coord_sys); + } + } + if (strcmp(coord_sys, kOfxParamCoordinatesNormalised) == 0) { + if (ie) { + double ext_w = 0.0, ext_h = 0.0; + propGetDouble((OfxPropertySetHandle) ie, + kOfxImageEffectPropProjectExtent, + 0, + &ext_w); + propGetDouble((OfxPropertySetHandle) ie, + kOfxImageEffectPropProjectExtent, + 1, + &ext_h); + if (ext_w > 0.0) + *X *= ext_w; + if (ext_h > 0.0) + *Y *= ext_h; + } + } } } } else if (strcmp(param_type, kOfxParamTypeInteger2D) == 0) { @@ -2912,6 +2961,9 @@ void *mltofx_fetch_params(OfxPlugin *plugin, mlt_properties params, mlt_properti mlt_properties_set_properties(image_effect, "params", iparams); mlt_properties_set_properties(iparams, "plugin_props", props); mlt_properties_set_properties(image_effect, "mltofx_params", params); + // Back-reference to image_effect stored on plugin_props so paramGetValueImpl + // can access project extent without disturbing the param iteration loop. + mlt_properties_set_data(props, "_ie", image_effect, 0, NULL, NULL); propSetString((OfxPropertySetHandle) props, kOfxImageEffectPropContext, @@ -3067,32 +3119,42 @@ void *mltofx_fetch_params(OfxPlugin *plugin, mlt_properties params, mlt_properti || strcmp(param_type, kOfxParamTypeRGB) == 0) { mlt_properties_set(p, "type", "color"); mlt_properties_set(p, "widget", "color"); - } else if (strcmp(param_type, kOfxParamTypeDouble2D) - == 0) { // can be rendered as 2 double number input fields - mlt_properties_set(p, "type", "float"); + } else if (strcmp(param_type, kOfxParamTypeDouble2D) == 0) { + mlt_properties_set(p, "type", "rect"); char *type = kOfxParamDoubleTypeXY; - char *coordinate_system = kOfxParamCoordinatesCanonical; propGetString((OfxPropertySetHandle) ppp, kOfxParamPropDoubleType, 0, &type); - propGetString((OfxPropertySetHandle) ppp, - kOfxParamPropDefaultCoordinateSystem, - 0, - &coordinate_system); - if (strcmp(type, kOfxParamDoubleTypeXYAbsolute) == 0) { mlt_properties_set(p, "widget", "point"); + mlt_properties_set(p, "normalized_coordinates", "no"); } else if (strcmp(type, kOfxParamDoubleTypeXY) == 0) { mlt_properties_set(p, "widget", "size"); + mlt_properties_set(p, "normalized_coordinates", "no"); } - if (strcmp(coordinate_system, kOfxParamCoordinatesCanonical) == 0) { - mlt_properties_set(p, "normalized_coordinates", "no"); - } else if (strcmp(coordinate_system, kOfxParamCoordinatesNormalised) == 0) { - mlt_properties_set(p, "normalized_coordinates", "yes"); + char *default_coords = ""; + OfxStatus status = propGetString((OfxPropertySetHandle) ppp, + kOfxParamPropDefaultCoordinateSystem, + 0, + &default_coords); + if (status == kOfxStatOK) { + if (!strcmp(default_coords, kOfxParamCoordinatesCanonical)) { + mlt_properties_set(p, "normalized_default", "no"); + } else if (!strcmp(default_coords, kOfxParamCoordinatesNormalised)) { + mlt_properties_set(p, "normalized_default", "yes"); + } + } else if (plugin && plugin->pluginIdentifier + && !strcmp("net.sf.openfx.CropPlugin", plugin->pluginIdentifier)) { + // Workaround for the crop plugin which does not report + // default coordinates, but uses normalized. + mlt_properties_set(p, "normalized_default", "yes"); } } else if (strcmp(param_type, kOfxParamTypeInteger2D) == 0) { - // can be rendered as 2 integer number input fields - mlt_properties_set(p, "type", "integer"); + mlt_properties_set(p, "type", "rect"); + } else if (strcmp(param_type, kOfxParamTypeDouble3D) == 0) { + mlt_properties_set(p, "type", "rect"); + } else if (strcmp(param_type, kOfxParamTypeInteger3D) == 0) { + mlt_properties_set(p, "type", "rect"); } int layout_hint = 0; @@ -3155,26 +3217,54 @@ void *mltofx_fetch_params(OfxPlugin *plugin, mlt_properties params, mlt_properti propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &default_value); mlt_properties_set_double(p, "default", default_value); } else if (strcmp(param_type, kOfxParamTypeDouble2D) == 0) { - double default_value1 = 0.0, default_value2 = 0.0; - - propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &default_value1); - propGetDouble((OfxPropertySetHandle) ppp, p_name, 1, &default_value2); - - // for some reason with DBL_MIN DBL_MAX it segfault - if (!isnormal(default_value1) || default_value1 <= FLT_MIN - || default_value1 >= FLT_MAX) - default_value1 = 0.0; - if (!isnormal(default_value2) || default_value2 <= FLT_MIN - || default_value2 >= FLT_MAX) - default_value2 = 0.0; - - char default_value[90] = ""; - snprintf(default_value, - sizeof(default_value), - "%.4f %.4f", - default_value1, - default_value2); - mlt_properties_set(p, "default", default_value); + double x = 0.0, y = 0.0; + + propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &x); + propGetDouble((OfxPropertySetHandle) ppp, p_name, 1, &y); + + // Validate and sanitize values + if (!isnormal(x) || x <= FLT_MIN || x >= FLT_MAX) + x = 0.0; + if (!isnormal(y) || y <= FLT_MIN || y >= FLT_MAX) + y = 0.0; + + char rect_str[100]; + snprintf(rect_str, sizeof(rect_str), "%g %g", x, y); + mlt_properties_set(p, "default", rect_str); + + } else if (strcmp(param_type, kOfxParamTypeInteger2D) == 0) { + int ix = 0, iy = 0; + propGetInt((OfxPropertySetHandle) ppp, p_name, 0, &ix); + propGetInt((OfxPropertySetHandle) ppp, p_name, 1, &iy); + char rect_str[100]; + snprintf(rect_str, sizeof(rect_str), "%d %d", ix, iy); + mlt_properties_set(p, "default", rect_str); + + } else if (strcmp(param_type, kOfxParamTypeDouble3D) == 0) { + double x3 = 0.0, y3 = 0.0, z3 = 0.0; + propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &x3); + propGetDouble((OfxPropertySetHandle) ppp, p_name, 1, &y3); + propGetDouble((OfxPropertySetHandle) ppp, p_name, 2, &z3); + if (!isnormal(x3) || x3 <= FLT_MIN || x3 >= FLT_MAX) + x3 = 0.0; + if (!isnormal(y3) || y3 <= FLT_MIN || y3 >= FLT_MAX) + y3 = 0.0; + if (!isnormal(z3) || z3 <= FLT_MIN || z3 >= FLT_MAX) + z3 = 0.0; + // rect.w holds the third dimension + char rect_str[100]; + snprintf(rect_str, sizeof(rect_str), "%g %g %g", x3, y3, z3); + mlt_properties_set(p, "default", rect_str); + + } else if (strcmp(param_type, kOfxParamTypeInteger3D) == 0) { + int ix = 0, iy = 0, iz = 0; + propGetInt((OfxPropertySetHandle) ppp, p_name, 0, &ix); + propGetInt((OfxPropertySetHandle) ppp, p_name, 1, &iy); + propGetInt((OfxPropertySetHandle) ppp, p_name, 2, &iz); + // rect.w holds the third dimension + char rect_str[100]; + snprintf(rect_str, sizeof(rect_str), "%d %d %d", ix, iy, iz); + mlt_properties_set(p, "default", rect_str); } else if (strcmp(param_type, kOfxParamTypeString) == 0) { char *default_value = ""; @@ -3251,6 +3341,16 @@ void *mltofx_fetch_params(OfxPlugin *plugin, mlt_properties params, mlt_properti double minimum_value = 0.0; propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &minimum_value); mlt_properties_set_double(p, "minimum", minimum_value); + } else if (strcmp(param_type, kOfxParamTypeDouble2D) == 0) { + min_set = 1; + double minimum_value = 0.0; + propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &minimum_value); + mlt_properties_set_double(p, "minimum", minimum_value); + } else if (strcmp(param_type, kOfxParamTypeInteger2D) == 0) { + min_set = 1; + int minimum_value = 0; + propGetInt((OfxPropertySetHandle) ppp, p_name, 0, &minimum_value); + mlt_properties_set_int(p, "minimum", minimum_value); } else if (strcmp(param_type, kOfxParamTypeString) == 0) { char *minimum_value = ""; propGetString((OfxPropertySetHandle) ppp, p_name, 0, &minimum_value); @@ -3269,6 +3369,16 @@ void *mltofx_fetch_params(OfxPlugin *plugin, mlt_properties params, mlt_properti double maximum_value = 0.0; propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &maximum_value); mlt_properties_set_double(p, "maximum", maximum_value); + } else if (strcmp(param_type, kOfxParamTypeDouble2D) == 0) { + max_set = 1; + double maximum_value = 0.0; + propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &maximum_value); + mlt_properties_set_double(p, "maximum", maximum_value); + } else if (strcmp(param_type, kOfxParamTypeInteger2D) == 0) { + max_set = 1; + int maximum_value = 0; + propGetInt((OfxPropertySetHandle) ppp, p_name, 0, &maximum_value); + mlt_properties_set_int(p, "maximum", maximum_value); } else if (strcmp(param_type, kOfxParamTypeString) == 0) { char *maximum_value = ""; propGetString((OfxPropertySetHandle) ppp, p_name, 0, &maximum_value); @@ -3353,6 +3463,22 @@ void mltofx_param_set_value(mlt_properties params, char *key, mltofx_property_ty propSetInt((OfxPropertySetHandle) param_props, "MltOfxParamValue", 1, y); } break; + case mltofx_prop_double3d: { + mlt_rect value = va_arg(ap, mlt_rect); + propSetDouble((OfxPropertySetHandle) param_props, "MltOfxParamValue", 0, value.x); + propSetDouble((OfxPropertySetHandle) param_props, "MltOfxParamValue", 1, value.y); + propSetDouble((OfxPropertySetHandle) param_props, "MltOfxParamValue", 2, value.w); + } break; + + case mltofx_prop_int3d: { + int x = va_arg(ap, int); + int y = va_arg(ap, int); + int z = va_arg(ap, int); + propSetInt((OfxPropertySetHandle) param_props, "MltOfxParamValue", 0, x); + propSetInt((OfxPropertySetHandle) param_props, "MltOfxParamValue", 1, y); + propSetInt((OfxPropertySetHandle) param_props, "MltOfxParamValue", 2, z); + } break; + default: break; } diff --git a/src/modules/openfx/mlt_openfx.h b/src/modules/openfx/mlt_openfx.h index f3d5e1751..1b27bf973 100644 --- a/src/modules/openfx/mlt_openfx.h +++ b/src/modules/openfx/mlt_openfx.h @@ -41,6 +41,8 @@ typedef enum { mltofx_prop_color = 32, mltofx_prop_double2d = 64, mltofx_prop_int2d = 128, + mltofx_prop_double3d = 256, + mltofx_prop_int3d = 512, } mltofx_property_type; typedef enum {