else
{
// Parse an absolute time value.
- mlt_property_set_string( item->property, value );
+ // Null terminate the string at the equal sign to prevent interpreting
+ // a colon in the part to the right of the equal sign as indicative of a
+ // a time value string.
+ char *s = strdup( value );
+ p = strchr( s, '=' );
+ p[0] = '\0';
+ mlt_property_set_string( item->property, s );
item->frame = mlt_property_get_int( item->property, self->fps, self->locale );
+ free( s );
}
// The character preceeding the equal sign indicates interpolation method.
mlt_rect rect = { DBL_MIN, DBL_MIN, DBL_MIN, DBL_MIN, DBL_MIN };
return value == NULL ? rect : mlt_property_get_rect( value, list->locale );
}
+
+/** Set a property to a rectangle value at a frame position.
+ *
+ * \public \memberof mlt_properties_s
+ * \param self a properties list
+ * \param name the property to set
+ * \param value the rectangle
+ * \return true if error
+ */
+
+extern int mlt_properties_set_rect_pos( mlt_properties self, const char *name, mlt_rect value, mlt_keyframe_type keyframe_type, int position, int length )
+{
+ int error = 1;
+
+ if ( !self || !name ) return error;
+
+ // Fetch the property to work with
+ mlt_property property = mlt_properties_fetch( self, name );
+
+ // Set it if not NULL
+ if ( property != NULL )
+ {
+ mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL );
+ double fps = mlt_profile_fps( profile );
+ property_list *list = self->local;
+ error = mlt_property_set_rect_pos( property, value, fps, list->locale, keyframe_type, position, length );
+ mlt_properties_do_mirror( self, name );
+ }
+
+ mlt_events_fire( self, "property-changed", name, NULL );
+
+ return error;
+}
+
+/** Get a rectangle associated to the name.
+ *
+ * \public \memberof mlt_properties_s
+ * \param self a properties list
+ * \param name the property to get
+ * \return The rectangle value, the rectangle fields will be DBL_MIN if not found
+ */
+
+extern mlt_rect mlt_properties_get_rect_pos( mlt_properties self, const char *name, int position, int length )
+{
+ mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL );
+ double fps = mlt_profile_fps( profile );
+ property_list *list = self->local;
+ mlt_property value = mlt_properties_find( self, name );
+ mlt_rect rect = { DBL_MIN, DBL_MIN, DBL_MIN, DBL_MIN, DBL_MIN };
+ return value == NULL ? rect : mlt_property_get_rect_pos( value, fps, list->locale, position, length );
+}
extern int mlt_properties_set_rect( mlt_properties self, const char *name, mlt_rect value );
extern mlt_rect mlt_properties_get_rect( mlt_properties self, const char *name );
+extern int mlt_properties_set_rect_pos( mlt_properties self, const char *name, mlt_rect value, mlt_keyframe_type keyframe_type, int position, int length );
+extern mlt_rect mlt_properties_get_rect_pos( mlt_properties self, const char *name, int position, int length );
+
#endif
#endif
else
result = strtod( value, &end );
- if ( *end && end[0] == '%' )
+ if ( end && end[0] == '%' )
result /= 100.0;
return result;
}
mlt_rect value = { DBL_MIN, DBL_MIN, DBL_MIN, DBL_MIN, DBL_MIN };
if ( interp == mlt_keyframe_linear )
{
- int i = 5;
mlt_rect points[2];
mlt_rect zero = {0, 0, 0, 0, 0};
points[0] = p[1]? mlt_property_get_rect( p[1], locale ) : zero;
- points[1] = p[2]? mlt_property_get_rect( p[2], locale ) : zero;
- while ( i-- ) switch ( i )
+ if ( p[2] )
{
- case 0: value.x = p[2]?
- linear_interpolate( points[0].x, points[1].x, progress ):
- points[0].x;
- break;
- case 1: value.y = p[2]?
- linear_interpolate( points[0].y, points[1].y, progress ):
- points[0].y;
- break;
- case 2: value.w = p[2]?
- linear_interpolate( points[0].w, points[1].w, progress ):
- points[0].w;
- break;
- case 3: value.h = p[2]?
- linear_interpolate( points[0].h, points[1].h, progress ):
- points[0].h;
- break;
- case 4: value.o = p[2]?
- linear_interpolate( points[0].o, points[1].o, progress ):
- points[0].o;
- break;
+ points[1] = mlt_property_get_rect( p[2], locale );
+ value.x = linear_interpolate( points[0].x, points[1].x, progress );
+ value.y = linear_interpolate( points[0].y, points[1].y, progress );
+ value.w = linear_interpolate( points[0].w, points[1].w, progress );
+ value.h = linear_interpolate( points[0].h, points[1].h, progress );
+ value.o = linear_interpolate( points[0].o, points[1].o, progress );
+ }
+ else
+ {
+ value = points[0];
}
}
else if ( interp == mlt_keyframe_smooth )
{
- int i = 5;
mlt_rect points[4];
mlt_rect zero = {0, 0, 0, 0, 0};
- points[0] = p[0]? mlt_property_get_rect( p[0], locale ) : zero;
points[1] = p[1]? mlt_property_get_rect( p[1], locale ) : zero;
- points[2] = p[2]? mlt_property_get_rect( p[2], locale ) : zero;
- points[3] = p[3]? mlt_property_get_rect( p[3], locale ) : zero;
- while ( i-- ) switch ( i )
+ if ( p[2] )
+ {
+ points[0] = p[0]? mlt_property_get_rect( p[0], locale ) : zero;
+ points[2] = p[2]? mlt_property_get_rect( p[2], locale ) : zero;
+ points[3] = p[3]? mlt_property_get_rect( p[3], locale ) : zero;
+ value.x = catmull_rom_interpolate( points[0].x, points[1].x, points[2].x, points[3].x, progress );
+ value.y = catmull_rom_interpolate( points[0].y, points[1].y, points[2].y, points[3].y, progress );
+ value.w = catmull_rom_interpolate( points[0].w, points[1].w, points[2].w, points[3].w, progress );
+ value.h = catmull_rom_interpolate( points[0].h, points[1].h, points[2].h, points[3].h, progress );
+ value.o = catmull_rom_interpolate( points[0].o, points[1].o, points[2].o, points[3].o, progress );
+ }
+ else
{
- case 0: value.x = p[2]?
- catmull_rom_interpolate( points[0].x, points[1].x, points[2].x, points[3].x, progress ):
- points[1].x;
- break;
- case 1: value.y = p[2]?
- catmull_rom_interpolate( points[0].y, points[1].y, points[2].y, points[3].y, progress ):
- points[1].y;
- break;
- case 2: value.w = p[2]?
- catmull_rom_interpolate( points[0].w, points[1].w, points[2].w, points[3].w, progress ):
- points[1].w;
- break;
- case 3: value.h = p[2]?
- catmull_rom_interpolate( points[0].h, points[1].h, points[2].h, points[3].h, progress ):
- points[1].h;
- break;
- case 4: value.o = p[2]?
- catmull_rom_interpolate( points[0].o, points[1].o, points[2].o, points[3].o, progress ):
- points[1].o;
- break;
+ value = points[1];
}
}
error = mlt_property_set_rect( self, value );
temp = strtod( value, &p );
if ( p != value )
{
+ if ( p[0] == '%' )
+ temp /= 100.0;
if ( *p ) p ++;
switch( count )
{
}
return rect;
}
+
+/** Set a property animation keyframe to a rectangle.
+ *
+ * \public \memberof mlt_property_s
+ * \param self a property
+ * \param value a rectangle
+ * \return false if successful, true to indicate error
+ */
+
+int mlt_property_set_rect_pos( mlt_property self, mlt_rect value, double fps, locale_t locale,
+ mlt_keyframe_type keyframe_type, int position, int length )
+{
+ int result;
+ struct mlt_animation_item_s item;
+
+ item.property = mlt_property_init();
+ item.frame = position;
+ item.keyframe_type = keyframe_type;
+ mlt_property_set_rect( item.property, value );
+
+ refresh_animation( self, fps, locale, length );
+ result = mlt_animation_insert( self->animation, &item );
+ mlt_animation_interpolate( self->animation );
+ mlt_property_close( item.property );
+
+ return result;
+}
+
+mlt_rect mlt_property_get_rect_pos( mlt_property self, double fps, locale_t locale, int position, int length )
+{
+ mlt_rect result;
+ if ( self->animation || ( ( self->types & mlt_prop_string ) && self->prop_string ) )
+ {
+ struct mlt_animation_item_s item;
+ item.property = mlt_property_init();
+ item.property->types = mlt_prop_rect;
+
+ refresh_animation( self, fps, locale, length );
+ mlt_animation_get_item( self->animation, &item, position );
+ result = mlt_property_get_rect( item.property, locale );
+
+ mlt_property_close( item.property );
+ }
+ else
+ {
+ result = mlt_property_get_rect( self, locale );
+ }
+ return result;
+}
mlt_keyframe_type keyframe_type, int position, int length );
extern int mlt_property_set_rect( mlt_property self, mlt_rect value );
extern mlt_rect mlt_property_get_rect( mlt_property self, locale_t locale );
+extern int mlt_property_set_rect_pos( mlt_property self, mlt_rect value, double fps, locale_t locale,
+ mlt_keyframe_type keyframe_type, int position, int length );
+extern mlt_rect mlt_property_get_rect_pos( mlt_property self, double fps, locale_t locale, int position, int length );
+
#endif
{
return mlt_properties_get_rect( get_properties(), name );
}
+
+int Properties::set(const char *name, mlt_rect value, int position, int length, mlt_keyframe_type keyframe_type)
+{
+ return mlt_properties_set_rect_pos( get_properties(), name, value, keyframe_type, position, length );
+}
+
+mlt_rect Properties::get_rect(const char *name, int position, int length)
+{
+ return mlt_properties_get_rect_pos( get_properties(), name, position, length );
+}
int set( const char *name, mlt_rect value );
int set( const char *name, double x, double y, double w, double h, double opacity = 1.0 );
mlt_rect get_rect( const char* name );
+ int set( const char *name, mlt_rect value, int position, int length,
+ mlt_keyframe_type keyframe_type = mlt_keyframe_linear );
+ mlt_rect get_rect( const char *name, int position, int length );
};
}
QCOMPARE(r.h, 4.4);
QCOMPARE(r.o, 5.5);
}
+
+ void RectAnimation()
+ {
+ int len = 50;
+ mlt_rect r1 = { 0, 0, 200, 200, 0 };
+ mlt_rect r2 = { 100, 100, 400, 400, 1.0 };
+ Properties p;
+ p.set_lcnumeric("POSIX");
+
+ // Construct animation from scratch
+ p.set("key", r1, 0, len);
+ p.set("key", r2, 50, len);
+ QCOMPARE(p.get_rect("key", 0, len).x, 0.0);
+ QCOMPARE(p.get_rect("key", 25, len).x, 50.0);
+ QCOMPARE(p.get_rect("key", 25, len).y, 50.0);
+ QCOMPARE(p.get_rect("key", 25, len).w, 300.0);
+ QCOMPARE(p.get_rect("key", 25, len).h, 300.0);
+ QCOMPARE(p.get_rect("key", 25, len).o, 0.5);
+ QCOMPARE(p.get_rect("key", 50, len).x, 100.0);
+ QCOMPARE(p.get("key"), "0=0 0 200 200 0;50=100 100 400 400 1");
+
+ // Animation from string value
+ QCOMPARE(p.get_rect("key", 0, len).x, 0.0);
+ QCOMPARE(p.get_rect("key", 0, len).y, 0.0);
+ QCOMPARE(p.get_rect("key", 0, len).w, 200.0);
+ QCOMPARE(p.get_rect("key", 0, len).h, 200.0);
+ QCOMPARE(p.get_rect("key", 0, len).o, 0.0);
+ QCOMPARE(p.get_rect("key", 50, len).x, 100.0);
+ QCOMPARE(p.get_rect("key", 50, len).y, 100.0);
+ QCOMPARE(p.get_rect("key", 50, len).w, 400.0);
+ QCOMPARE(p.get_rect("key", 50, len).h, 400.0);
+ QCOMPARE(p.get_rect("key", 50, len).o, 1.0);
+ QCOMPARE(p.get_rect("key", 15, len).x, 30.0);
+ QCOMPARE(p.get_rect("key", 15, len).y, 30.0);
+ QCOMPARE(p.get_rect("key", 15, len).w, 260.0);
+ QCOMPARE(p.get_rect("key", 15, len).h, 260.0);
+ QCOMPARE(p.get_rect("key", 15, len).o, 0.3);
+
+ // Smooth animation
+ p.set("key", "0~=0/0:200x200:0; 50=100/100:400x400:1");
+ QCOMPARE(p.get_rect("key", 0, len).x, 0.0);
+ QCOMPARE(p.get_rect("key", 0, len).y, 0.0);
+ QCOMPARE(p.get_rect("key", 0, len).w, 200.0);
+ QCOMPARE(p.get_rect("key", 0, len).h, 200.0);
+ QCOMPARE(p.get_rect("key", 0, len).o, 0.0);
+ QCOMPARE(p.get_rect("key", 50, len).x, 100.0);
+ QCOMPARE(p.get_rect("key", 50, len).y, 100.0);
+ QCOMPARE(p.get_rect("key", 50, len).w, 400.0);
+ QCOMPARE(p.get_rect("key", 50, len).h, 400.0);
+ QCOMPARE(p.get_rect("key", 50, len).o, 1.0);
+ QCOMPARE(p.get_rect("key", 15, len).x, 25.8);
+ QCOMPARE(p.get_rect("key", 15, len).y, 25.8);
+ QCOMPARE(p.get_rect("key", 15, len).w, 251.6);
+ QCOMPARE(p.get_rect("key", 15, len).h, 251.6);
+ QCOMPARE(p.get_rect("key", 15, len).o, 0.258);
+
+ // Using percentages
+ p.set("key", "0=0 0; 50=100% 200%");
+ QCOMPARE(p.get_rect("key", 25, len).x, 0.5);
+ QCOMPARE(p.get_rect("key", 25, len).y, 1.0);
+ }
+
};
QTEST_APPLESS_MAIN(TestProperties)