#include <string.h>
#include <locale.h>
#include <pthread.h>
+#include <float.h>
/** Bit pattern used internally to indicated representations available.
mlt_prop_position = 4,//!< set as a position
mlt_prop_double = 8, //!< set as a floating point
mlt_prop_data = 16, //!< set as opaque binary
- mlt_prop_int64 = 32 //!< set as a 64-bit integer
+ mlt_prop_int64 = 32, //!< set as a 64-bit integer
+ mlt_prop_rect = 64 //!< set as a mlt_rect
}
mlt_property_type;
return ( int )self->prop_position;
else if ( self->types & mlt_prop_int64 )
return ( int )self->prop_int64;
+ else if ( self->types & mlt_prop_rect && self->data )
+ return ( int ) ( (mlt_rect*) self->data )->x;
else if ( ( self->types & mlt_prop_string ) && self->prop_string )
return mlt_property_atoi( self->prop_string, fps, locale );
return 0;
return ( double )self->prop_position;
else if ( self->types & mlt_prop_int64 )
return ( double )self->prop_int64;
+ else if ( self->types & mlt_prop_rect && self->data )
+ return ( (mlt_rect*) self->data )->x;
else if ( ( self->types & mlt_prop_string ) && self->prop_string )
return mlt_property_atof( self->prop_string, fps, locale );
return 0;
return ( mlt_position )self->prop_double;
else if ( self->types & mlt_prop_int64 )
return ( mlt_position )self->prop_int64;
+ else if ( self->types & mlt_prop_rect && self->data )
+ return ( mlt_position ) ( (mlt_rect*) self->data )->x;
else if ( ( self->types & mlt_prop_string ) && self->prop_string )
return ( mlt_position )mlt_property_atoi( self->prop_string, fps, locale );
return 0;
return ( int64_t )self->prop_double;
else if ( self->types & mlt_prop_position )
return ( int64_t )self->prop_position;
+ else if ( self->types & mlt_prop_rect && self->data )
+ return ( int64_t ) ( (mlt_rect*) self->data )->x;
else if ( ( self->types & mlt_prop_string ) && self->prop_string )
return mlt_property_atoll( self->prop_string );
return 0;
if ( that->prop_string != NULL )
self->prop_string = strdup( that->prop_string );
}
+ else if ( that->types & mlt_prop_rect )
+ {
+ mlt_property_clear( self );
+ self->types = mlt_prop_rect | mlt_prop_data;
+ self->length = that->length;
+ self->data = calloc( 1, self->length );
+ memcpy( self->data, that->data, self->length );
+ self->destructor = free;
+ self->serialiser = that->serialiser;
+ }
else if ( self->types & mlt_prop_data && self->serialiser != NULL )
{
self->types = mlt_prop_string;
int result = ( self->types & mlt_prop_int ) ||
( self->types & mlt_prop_int64 ) ||
( self->types & mlt_prop_double ) ||
- ( self->types & mlt_prop_position );
+ ( self->types & mlt_prop_position ) ||
+ ( self->types & mlt_prop_rect );
// If not already numeric but string is numeric.
if ( ( !result && self->types & mlt_prop_string ) && self->prop_string )
if ( interp != mlt_keyframe_discrete &&
is_property_numeric( p[1], locale ) && is_property_numeric( p[2], locale ) )
{
- double value;
- if ( interp == mlt_keyframe_linear )
+ if ( self->types & mlt_prop_rect )
{
- double points[2];
- points[0] = p[1]? mlt_property_get_double( p[1], fps, locale ) : 0;
- points[1] = p[2]? mlt_property_get_double( p[2], fps, locale ) : 0;
- value = p[2]? linear_interpolate( points[0], points[1], progress ) : points[0];
+ 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 )
+ {
+ 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;
+ }
+ }
+ 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 )
+ {
+ 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;
+ }
+ }
+ error = mlt_property_set_rect( self, value );
}
- else if ( interp == mlt_keyframe_smooth )
+ else
{
- double points[4];
- points[0] = p[0]? mlt_property_get_double( p[0], fps, locale ) : 0;
- points[1] = p[1]? mlt_property_get_double( p[1], fps, locale ) : 0;
- points[2] = p[2]? mlt_property_get_double( p[2], fps, locale ) : 0;
- points[3] = p[3]? mlt_property_get_double( p[3], fps, locale ) : 0;
- value = p[2]? catmull_rom_interpolate( points[0], points[1], points[2], points[3], progress ) : points[1];
+ double value;
+ if ( interp == mlt_keyframe_linear )
+ {
+ double points[2];
+ points[0] = p[1]? mlt_property_get_double( p[1], fps, locale ) : 0;
+ points[1] = p[2]? mlt_property_get_double( p[2], fps, locale ) : 0;
+ value = p[2]? linear_interpolate( points[0], points[1], progress ) : points[0];
+ }
+ else if ( interp == mlt_keyframe_smooth )
+ {
+ double points[4];
+ points[0] = p[0]? mlt_property_get_double( p[0], fps, locale ) : 0;
+ points[1] = p[1]? mlt_property_get_double( p[1], fps, locale ) : 0;
+ points[2] = p[2]? mlt_property_get_double( p[2], fps, locale ) : 0;
+ points[3] = p[3]? mlt_property_get_double( p[3], fps, locale ) : 0;
+ value = p[2]? catmull_rom_interpolate( points[0], points[1], points[2], points[3], progress ) : points[1];
+ }
+ error = mlt_property_set_double( self, value );
}
- error = mlt_property_set_double( self, value );
}
else
{
return result;
}
+
+static char* serialise_mlt_rect( mlt_rect *rect, int length )
+{
+ char* result = calloc( 1, 100 );
+ if ( rect->x != DBL_MIN )
+ sprintf( result + strlen( result ), "%g", rect->x );
+ if ( rect->y != DBL_MIN )
+ sprintf( result + strlen( result ), " %g", rect->y );
+ if ( rect->w != DBL_MIN )
+ sprintf( result + strlen( result ), " %g", rect->w );
+ if ( rect->h != DBL_MIN )
+ sprintf( result + strlen( result ), " %g", rect->h );
+ if ( rect->o != DBL_MIN )
+ sprintf( result + strlen( result ), " %g", rect->o );
+ return result;
+}
+
+/** Set a property to a mlt_rect rectangle.
+ *
+ * \public \memberof mlt_property_s
+ * \param self a property
+ * \param value a mlt_rect
+ * \return false
+ */
+
+int mlt_property_set_rect( mlt_property self, mlt_rect value )
+{
+ pthread_mutex_lock( &self->mutex );
+ mlt_property_clear( self );
+ self->types = mlt_prop_rect | mlt_prop_data;
+ self->length = sizeof(value);
+ self->data = calloc( 1, self->length );
+ memcpy( self->data, &value, self->length );
+ self->destructor = free;
+ self->serialiser = (mlt_serialiser) serialise_mlt_rect;
+ pthread_mutex_unlock( &self->mutex );
+ return 0;
+}
+
+/** Get the property as a floating point.
+ *
+ * \public \memberof mlt_property_s
+ * \param self a property
+ * \param fps frames per second, used when converting from time value
+ * \param locale the locale to use for this conversion
+ * \return a rectangle value
+ */
+
+mlt_rect mlt_property_get_rect( mlt_property self, locale_t locale )
+{
+ mlt_rect rect = { DBL_MIN, DBL_MIN, DBL_MIN, DBL_MIN, DBL_MIN };
+ if ( self->types & mlt_prop_rect )
+ rect = *( (mlt_rect*) self->data );
+ else if ( self->types & mlt_prop_double )
+ rect.x = self->prop_double;
+ else if ( self->types & mlt_prop_int )
+ rect.x = ( double )self->prop_int;
+ else if ( self->types & mlt_prop_position )
+ rect.x = ( double )self->prop_position;
+ else if ( self->types & mlt_prop_int64 )
+ rect.x = ( double )self->prop_int64;
+ else if ( ( self->types & mlt_prop_string ) && self->prop_string )
+ {
+ //return mlt_property_atof( self->prop_string, fps, locale );
+ char *value = self->prop_string;
+ char *p = NULL;
+ int count = 0;
+ while ( *value )
+ {
+ double temp;
+#if defined(__GLIBC__) || defined(__DARWIN__)
+ if ( locale )
+ temp = strtod_l( value, &p, locale );
+#endif
+ else
+ temp = strtod( value, &p );
+ if ( p != value )
+ {
+ if ( *p ) p ++;
+ switch( count )
+ {
+ case 0: rect.x = temp; break;
+ case 1: rect.y = temp; break;
+ case 2: rect.w = temp; break;
+ case 3: rect.h = temp; break;
+ case 4: rect.o = temp; break;
+ }
+ }
+ else
+ {
+ p++;
+ }
+ value = p;
+ count ++;
+ }
+ }
+ return rect;
+}
#include <framework/mlt_property.h>
#include <framework/mlt_animation.h>
}
+#include <cfloat>
class TestProperties: public QObject
{
Q_OBJECT
+ locale_t locale;
public:
- TestProperties() {}
+ TestProperties() {
+#if defined(__linux__) || defined(__DARWIN__)
+ locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL );
+#endif
+ }
private Q_SLOTS:
void InstantiationIsAReference()
void DoubleAnimation()
{
- locale_t locale;
-#if defined(__linux__) || defined(__DARWIN__)
- locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL );
-#endif
double fps = 25.0;
mlt_animation a = mlt_animation_new();
struct mlt_animation_item_s item;
void IntAnimation()
{
- locale_t locale;
-#if defined(__linux__) || defined(__DARWIN__)
- locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL );
-#endif
double fps = 25.0;
mlt_animation a = mlt_animation_new();
struct mlt_animation_item_s item;
void AnimationWithTimeValueKeyframes()
{
- locale_t locale;
-#if defined(__linux__) || defined(__DARWIN__)
- locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL );
-#endif
double fps = 25.0;
mlt_animation a = mlt_animation_new();
struct mlt_animation_item_s item;
void DiscreteIntAnimation()
{
- locale_t locale;
-#if defined(__linux__) || defined(__DARWIN__)
- locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL );
-#endif
double fps = 25.0;
mlt_animation a = mlt_animation_new();
struct mlt_animation_item_s item;
void StringAnimation()
{
- locale_t locale;
-#if defined(__linux__) || defined(__DARWIN__)
- locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL );
-#endif
double fps = 25.0;
mlt_animation a = mlt_animation_new();
struct mlt_animation_item_s item;
void test_property_get_double_pos()
{
- locale_t locale;
-#if defined(__linux__) || defined(__DARWIN__)
- locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL );
-#endif
double fps = 25.0;
mlt_property p = mlt_property_init();
mlt_property_set_string(p, "10=100; 20=200");
void test_property_get_int_pos()
{
- locale_t locale;
-#if defined(__linux__) || defined(__DARWIN__)
- locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL );
-#endif
double fps = 25.0;
mlt_property p = mlt_property_init();
mlt_property_set_string(p, "10=100; 20=200");
void SmoothIntAnimation()
{
- locale_t locale;
-#if defined(__linux__) || defined(__DARWIN__)
- locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL );
-#endif
double fps = 25.0;
mlt_animation a = mlt_animation_new();
struct mlt_animation_item_s item;
void test_property_set_double_pos()
{
- locale_t locale;
-#if defined(__linux__) || defined(__DARWIN__)
- locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL );
-#endif
double fps = 25.0;
mlt_property p = mlt_property_init();
mlt_property_set_string(p, "10=100; 20=200");
void test_property_set_int_pos()
{
- locale_t locale;
-#if defined(__linux__) || defined(__DARWIN__)
- locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL );
-#endif
double fps = 25.0;
mlt_property p = mlt_property_init();
mlt_property_set_string(p, "10=100; 20=200");
QCOMPARE(p.get_int("foo", 25, len), 150);
QCOMPARE(p.get_int("foo", 50, len), 200);
}
+
+ void test_mlt_rect()
+ {
+ mlt_property p = mlt_property_init();
+ mlt_rect r = { 1, 2, 3, 4, 5 };
+
+ mlt_property_set_rect( p, r );
+ QCOMPARE(mlt_property_get_string(p), "1 2 3 4 5");
+ r.o = DBL_MIN;
+ mlt_property_set_rect( p, r );
+ QCOMPARE(mlt_property_get_string(p), "1 2 3 4");
+ r.w = DBL_MIN;
+ r.h = DBL_MIN;
+ mlt_property_set_rect( p, r );
+ QCOMPARE(mlt_property_get_string(p), "1 2");
+
+ mlt_property_set_string(p, "1.1/2.2:3.3x4.4:5.5");
+ r = mlt_property_get_rect(p, locale);
+ QCOMPARE(r.x, 1.1);
+ QCOMPARE(r.y, 2.2);
+ QCOMPARE(r.w, 3.3);
+ QCOMPARE(r.h, 4.4);
+ QCOMPARE(r.o, 5.5);
+
+ mlt_property_set_string(p, "1.1 2.2");
+ r = mlt_property_get_rect(p, locale);
+ QCOMPARE(r.x, 1.1);
+ QCOMPARE(r.y, 2.2);
+ QCOMPARE(r.w, DBL_MIN);
+
+ mlt_property_set_int64(p, UINT_MAX);
+ r = mlt_property_get_rect(p, locale);
+ QCOMPARE(r.x, double(UINT_MAX));
+
+ mlt_property_close(p);
+ }
+
+ void SetAndGetRect()
+ {
+ Properties p;
+ mlt_rect r;
+ r.x = 1.1;
+ r.y = 2.2;
+ r.w = 3.3;
+ r.h = 4.4;
+ r.o = 5.5;
+ p.set("key", r);
+ mlt_rect q = p.get_rect("key");
+ QCOMPARE(q.x, 1.1);
+ QCOMPARE(q.y, 2.2);
+ QCOMPARE(q.w, 3.3);
+ QCOMPARE(q.h, 4.4);
+ QCOMPARE(q.o, 5.5);
+ p.set("key", 10, 20, 30, 40);
+ q = p.get_rect("key");
+ QCOMPARE(q.x, 10.0);
+ QCOMPARE(q.y, 20.0);
+ QCOMPARE(q.w, 30.0);
+ QCOMPARE(q.h, 40.0);
+ }
+
+ void RectFromString()
+ {
+ Properties p;
+ p.set_lcnumeric("POSIX");
+ const char *s = "1.1 2.2 3.3 4.4 5.5";
+ mlt_rect r = { 1.1, 2.2, 3.3, 4.4, 5.5 };
+ p.set("key", r);
+ QCOMPARE(p.get("key"), s);
+ p.set("key", s);
+ r = p.get_rect("key");
+ QCOMPARE(r.x, 1.1);
+ QCOMPARE(r.y, 2.2);
+ QCOMPARE(r.w, 3.3);
+ QCOMPARE(r.h, 4.4);
+ QCOMPARE(r.o, 5.5);
+ }
};
QTEST_APPLESS_MAIN(TestProperties)