X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fframework%2Fmlt_properties.c;h=2a37ab4d9f84613752bb5288874114d781dc5aa6;hb=1aa26da9547caaa99cf76ad28e1c609a75a3f554;hp=4f21d68cffdd94da5d0a8b4829d0e0f2f84e8049;hpb=98bb7d4fff7fb6ecb424c13519b8ec7e36448244;p=mlt diff --git a/src/framework/mlt_properties.c b/src/framework/mlt_properties.c index 4f21d68c..2a37ab4d 100644 --- a/src/framework/mlt_properties.c +++ b/src/framework/mlt_properties.c @@ -3,7 +3,7 @@ * \brief Properties class definition * \see mlt_properties_s * - * Copyright (C) 2003-2009 Ushodaya Enterprises Limited + * Copyright (C) 2003-2013 Ushodaya Enterprises Limited * \author Charles Yates * \author Dan Dennedy * @@ -22,6 +22,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +// For strtod_l +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + #include "mlt_properties.h" #include "mlt_property.h" #include "mlt_deque.h" @@ -39,6 +44,7 @@ #include #include #include +#include #define PRESETS_DIR "/presets" @@ -322,11 +328,10 @@ int mlt_properties_preset( mlt_properties self, const char *name ) static inline int generate_hash( const char *name ) { - int hash = 0; - int i = 1; + unsigned int hash = 5381; while ( *name ) - hash = ( hash + ( i ++ * ( *name ++ & 31 ) ) ) % 199; - return hash; + hash = hash * 33 + (unsigned int) ( *name ++ ); + return hash % 199; } /** Copy a serializable property to a properties list that is mirroring this one. @@ -341,6 +346,7 @@ static inline int generate_hash( const char *name ) static inline void mlt_properties_do_mirror( mlt_properties self, const char *name ) { + if ( !self ) return; property_list *list = self->local; if ( list->mirror != NULL ) { @@ -418,6 +424,7 @@ int mlt_properties_ref_count( mlt_properties self ) void mlt_properties_mirror( mlt_properties self, mlt_properties that ) { + if ( !self ) return; property_list *list = self->local; list->mirror = that; } @@ -427,11 +434,12 @@ void mlt_properties_mirror( mlt_properties self, mlt_properties that ) * \public \memberof mlt_properties_s * \param self The properties to copy to * \param that The properties to copy from - * \return false + * \return true if error */ int mlt_properties_inherit( mlt_properties self, mlt_properties that ) { + if ( !self || !that ) return 1; int count = mlt_properties_count( that ); int i = 0; for ( i = 0; i < count; i ++ ) @@ -448,15 +456,19 @@ int mlt_properties_inherit( mlt_properties self, mlt_properties that ) /** Pass all serializable properties that match a prefix to another properties object * + * \warning The prefix is stripped from the name when it is set on the \p self properties list! + * For example a property named "foo.bar" will match prefix "foo.", but the property + * will be named simply "bar" on the receiving properties object. * \public \memberof mlt_properties_s * \param self the properties to copy to * \param that The properties to copy from * \param prefix the property names to match (required) - * \return false + * \return true if error */ int mlt_properties_pass( mlt_properties self, mlt_properties that, const char *prefix ) { + if ( !self || !that ) return 1; int count = mlt_properties_count( that ); int length = strlen( prefix ); int i = 0; @@ -483,6 +495,7 @@ int mlt_properties_pass( mlt_properties self, mlt_properties that, const char *p static inline mlt_property mlt_properties_find( mlt_properties self, const char *name ) { + if ( !self || !name ) return NULL; property_list *list = self->local; mlt_property value = NULL; int key = generate_hash( name ); @@ -596,12 +609,13 @@ void mlt_properties_pass_property( mlt_properties self, mlt_properties that, con * \param self the properties to copy to * \param that the properties to copy from * \param list a delimited list of property names - * \return false + * \return true if error */ int mlt_properties_pass_list( mlt_properties self, mlt_properties that, const char *list ) { + if ( !self || !that || !list ) return 1; char *props = strdup( list ); char *ptr = props; const char *delim = " ,\t\n"; // Any combination of spaces, commas, tabs, and newlines @@ -648,6 +662,8 @@ int mlt_properties_set( mlt_properties self, const char *name, const char *value { int error = 1; + if ( !self || !name ) return error; + // Fetch the property to work with mlt_property property = mlt_properties_fetch( self, name ); @@ -688,9 +704,19 @@ int mlt_properties_set( mlt_properties self, const char *name, const char *value // Determine the value if ( isdigit( id[ 0 ] ) ) - current = atof( id ); + { +#if defined(__GLIBC__) || defined(__DARWIN__) + property_list *list = self->local; + if ( list->locale ) + current = strtod_l( id, NULL, list->locale ); + else +#endif + current = strtod( id, NULL ); + } else + { current = mlt_properties_get_double( self, id ); + } // Apply the operation switch( op ) @@ -750,9 +776,14 @@ int mlt_properties_set_or_default( mlt_properties self, const char *name, const char *mlt_properties_get( mlt_properties self, const char *name ) { + char *result = NULL; mlt_property value = mlt_properties_find( self, name ); - property_list *list = self->local; - return value == NULL ? NULL : mlt_property_get_string_l( value, list->locale ); + if ( value ) + { + property_list *list = self->local; + result = mlt_property_get_string_l( value, list->locale ); + } + return result; } /** Get a property name by index. @@ -766,6 +797,7 @@ char *mlt_properties_get( mlt_properties self, const char *name ) char *mlt_properties_get_name( mlt_properties self, int index ) { + if ( !self ) return NULL; property_list *list = self->local; if ( index >= 0 && index < list->count ) return list->name[ index ]; @@ -783,6 +815,7 @@ char *mlt_properties_get_name( mlt_properties self, int index ) char *mlt_properties_get_value( mlt_properties self, int index ) { + if ( !self ) return NULL; property_list *list = self->local; if ( index >= 0 && index < list->count ) return mlt_property_get_string_l( list->value[ index ], list->locale ); @@ -801,6 +834,7 @@ char *mlt_properties_get_value( mlt_properties self, int index ) void *mlt_properties_get_data_at( mlt_properties self, int index, int *size ) { + if ( !self ) return NULL; property_list *list = self->local; if ( index >= 0 && index < list->count ) return mlt_property_get_data( list->value[ index ], size ); @@ -811,11 +845,12 @@ void *mlt_properties_get_data_at( mlt_properties self, int index, int *size ) * * \public \memberof mlt_properties_s * \param self a properties list - * \return the number of property objects + * \return the number of property objects or -1 if error */ int mlt_properties_count( mlt_properties self ) { + if ( !self ) return -1; property_list *list = self->local; return list->count; } @@ -830,6 +865,7 @@ int mlt_properties_count( mlt_properties self ) int mlt_properties_parse( mlt_properties self, const char *namevalue ) { + if ( !self ) return 1; char *name = strdup( namevalue ); char *value = NULL; int error = 0; @@ -874,11 +910,16 @@ int mlt_properties_parse( mlt_properties self, const char *namevalue ) int mlt_properties_get_int( mlt_properties self, const char *name ) { - mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL ); - double fps = mlt_profile_fps( profile ); - property_list *list = self->local; + int result = 0; mlt_property value = mlt_properties_find( self, name ); - return value == NULL ? 0 : mlt_property_get_int( value, fps, list->locale ); + if ( value ) + { + mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL ); + double fps = mlt_profile_fps( profile ); + property_list *list = self->local; + result = mlt_property_get_int( value, fps, list->locale ); + } + return result; } /** Set a property to an integer value. @@ -894,6 +935,8 @@ int mlt_properties_set_int( mlt_properties self, const char *name, int value ) { int error = 1; + if ( !self || !name ) return error; + // Fetch the property to work with mlt_property property = mlt_properties_fetch( self, name ); @@ -936,6 +979,8 @@ int mlt_properties_set_int64( mlt_properties self, const char *name, int64_t val { int error = 1; + if ( !self || !name ) return error; + // Fetch the property to work with mlt_property property = mlt_properties_fetch( self, name ); @@ -961,11 +1006,16 @@ int mlt_properties_set_int64( mlt_properties self, const char *name, int64_t val double mlt_properties_get_double( mlt_properties self, const char *name ) { - mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL ); - double fps = mlt_profile_fps( profile ); + double result = 0; mlt_property value = mlt_properties_find( self, name ); - property_list *list = self->local; - return value == NULL ? 0 : mlt_property_get_double( value, fps, list->locale ); + if ( value ) + { + mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL ); + double fps = mlt_profile_fps( profile ); + property_list *list = self->local; + result = mlt_property_get_double( value, fps, list->locale ); + } + return result; } /** Set a property to a floating point value. @@ -981,6 +1031,8 @@ int mlt_properties_set_double( mlt_properties self, const char *name, double val { int error = 1; + if ( !self || !name ) return error; + // Fetch the property to work with mlt_property property = mlt_properties_fetch( self, name ); @@ -1006,11 +1058,16 @@ int mlt_properties_set_double( mlt_properties self, const char *name, double val mlt_position mlt_properties_get_position( mlt_properties self, const char *name ) { - mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL ); - double fps = mlt_profile_fps( profile ); - property_list *list = self->local; + mlt_position result = 0; mlt_property value = mlt_properties_find( self, name ); - return value == NULL ? 0 : mlt_property_get_position( value, fps, list->locale ); + if ( value ) + { + mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL ); + double fps = mlt_profile_fps( profile ); + property_list *list = self->local; + result = mlt_property_get_position( value, fps, list->locale ); + } + return result; } /** Set a property to a position value. @@ -1026,6 +1083,8 @@ int mlt_properties_set_position( mlt_properties self, const char *name, mlt_posi { int error = 1; + if ( !self || !name ) return error; + // Fetch the property to work with mlt_property property = mlt_properties_fetch( self, name ); @@ -1073,6 +1132,8 @@ int mlt_properties_set_data( mlt_properties self, const char *name, void *value, { int error = 1; + if ( !self || !name ) return error; + // Fetch the property to work with mlt_property property = mlt_properties_fetch( self, name ); @@ -1130,6 +1191,7 @@ int mlt_properties_rename( mlt_properties self, const char *source, const char * void mlt_properties_dump( mlt_properties self, FILE *output ) { + if ( !self || !output ) return; property_list *list = self->local; int i = 0; for ( i = 0; i < list->count; i ++ ) @@ -1147,6 +1209,7 @@ void mlt_properties_dump( mlt_properties self, FILE *output ) */ void mlt_properties_debug( mlt_properties self, const char *title, FILE *output ) { + if ( !self || !output ) return; if ( output == NULL ) output = stderr; fprintf( output, "%s: ", title ); if ( self != NULL ) @@ -1176,6 +1239,7 @@ void mlt_properties_debug( mlt_properties self, const char *title, FILE *output int mlt_properties_save( mlt_properties self, const char *filename ) { int error = 1; + if ( !self || !filename ) return error; FILE *f = fopen( filename, "w" ); if ( f != NULL ) { @@ -1384,7 +1448,8 @@ struct yaml_parser_context { mlt_deque stack; unsigned int level; - unsigned int index; + int index; + mlt_deque index_stack; char block; char *block_name; unsigned int block_indent; @@ -1440,7 +1505,7 @@ static int parse_yaml( yaml_parser context, const char *namevalue ) int error = 0; char *ptr = strchr( name, ':' ); unsigned int indent = ltrim( &name ); - mlt_properties properties = mlt_deque_peek_front( context->stack ); + mlt_properties properties = mlt_deque_peek_back( context->stack ); // Ascending one more levels in the tree if ( indent < context->level ) @@ -1448,8 +1513,11 @@ static int parse_yaml( yaml_parser context, const char *namevalue ) unsigned int i; unsigned int n = ( context->level - indent ) / 2; for ( i = 0; i < n; i++ ) - mlt_deque_pop_front( context->stack ); - properties = mlt_deque_peek_front( context->stack ); + { + mlt_deque_pop_back( context->stack ); + context->index = mlt_deque_pop_back_int( context->index_stack ); + } + properties = mlt_deque_peek_back( context->stack ); context->level = indent; } @@ -1491,7 +1559,8 @@ static int parse_yaml( yaml_parser context, const char *namevalue ) mlt_properties_set_lcnumeric( child, mlt_properties_get_lcnumeric( properties ) ); mlt_properties_set_data( properties, name, child, 0, ( mlt_destructor )mlt_properties_close, NULL ); - mlt_deque_push_front( context->stack, child ); + mlt_deque_push_back( context->stack, child ); + mlt_deque_push_back_int( context->index_stack, context->index ); context->index = 0; free( name_ ); return error; @@ -1507,7 +1576,8 @@ static int parse_yaml( yaml_parser context, const char *namevalue ) snprintf( key, sizeof(key), "%d", context->index++ ); mlt_properties_set_data( properties, key, child, 0, ( mlt_destructor )mlt_properties_close, NULL ); - mlt_deque_push_front( context->stack, child ); + mlt_deque_push_back( context->stack, child ); + mlt_deque_push_back_int( context->index_stack, context->index ); name ++; context->level += ltrim( &name ) + 1; @@ -1681,7 +1751,9 @@ mlt_properties mlt_properties_parse_yaml( const char *filename ) // Parser context yaml_parser context = calloc( 1, sizeof( struct yaml_parser_context ) ); context->stack = mlt_deque_init(); - mlt_deque_push_front( context->stack, self ); + context->index_stack = mlt_deque_init(); + mlt_deque_push_back( context->stack, self ); + mlt_deque_push_back_int( context->index_stack, 0 ); // Read each string from the file while( fgets( temp, 1024, file ) ) @@ -1702,6 +1774,7 @@ mlt_properties mlt_properties_parse_yaml( const char *filename ) // Close the file fclose( file ); mlt_deque_close( context->stack ); + mlt_deque_close( context->index_stack ); if ( context->block_name ) free( context->block_name ); free( context ); @@ -1802,6 +1875,23 @@ static inline void indent_yaml( strbuf output, int indent ) strbuf_printf( output, " " ); } +static void strbuf_escape( strbuf output, const char *value, char c ) +{ + char *v = strdup( value ); + char *s = v; + char *found = strchr( s, c ); + + while ( found ) + { + *found = '\0'; + strbuf_printf( output, "%s\\%c", s, c ); + s = found + 1; + found = strchr( s, c ); + } + strbuf_printf( output, "%s", s ); + free( v ); +} + /** Convert a line string into a YAML block literal. * * \private \memberof strbuf_s @@ -1826,6 +1916,7 @@ static void output_yaml_block_literal( strbuf output, const char *value, int ind } indent_yaml( output, indent ); strbuf_printf( output, "%s\n", sol ); + free( v ); } /** Recursively serialize a properties list into a string buffer as YAML Tiny. @@ -1867,6 +1958,12 @@ static void serialise_yaml( mlt_properties self, strbuf output, int indent, int strbuf_printf( output, "|\n" ); output_yaml_block_literal( output, value, indent + strlen( list->name[ i ] ) + strlen( "|" ) ); } + else if ( strchr( value, ':' ) || strchr( value, '[' ) ) + { + strbuf_printf( output, "\"" ); + strbuf_escape( output, value, '"' ); + strbuf_printf( output, "\"\n", value ); + } else { strbuf_printf( output, "%s\n", value ); @@ -1897,6 +1994,12 @@ static void serialise_yaml( mlt_properties self, strbuf output, int indent, int strbuf_printf( output, "%s: |\n", list->name[ i ] ); output_yaml_block_literal( output, value, indent + strlen( list->name[ i ] ) + strlen( ": " ) ); } + else if ( strchr( value, ':' ) || strchr( value, '[' ) ) + { + strbuf_printf( output, "%s: \"", list->name[ i ] ); + strbuf_escape( output, value, '"' ); + strbuf_printf( output, "\"\n" ); + } else { strbuf_printf( output, "%s: %s\n", list->name[ i ], value ); @@ -1928,6 +2031,7 @@ static void serialise_yaml( mlt_properties self, strbuf output, int indent, int char *mlt_properties_serialise_yaml( mlt_properties self ) { + if ( !self ) return NULL; const char *lc_numeric = mlt_properties_get_lcnumeric( self ); strbuf b = strbuf_new(); strbuf_printf( b, "---\n" ); @@ -1986,3 +2090,421 @@ char *mlt_properties_get_time( mlt_properties self, const char* name, mlt_time_f } return NULL; } + +/** Convert a frame count to a time string. + * + * Do not free the returned string. It's lifetime is controlled by the property. + * \public \memberof mlt_properties_s + * \param self a properties list + * \param frames the frame count to convert + * \param format the time format that you want + * \return the time string or NULL if error, e.g. there is no profile + */ + +char *mlt_properties_frames_to_time( mlt_properties self, mlt_position frames, mlt_time_format format ) +{ + const char *name = "_mlt_properties_time"; + mlt_properties_set_position( self, name, frames ); + return mlt_properties_get_time( self, name, format ); +} + +/** Convert a time string to a frame count. + * + * \public \memberof mlt_properties_s + * \param self a properties list + * \param time the time string to convert + * \return a frame count or a negative value if error, e.g. there is no profile + */ + +mlt_position mlt_properties_time_to_frames( mlt_properties self, const char *time ) +{ + const char *name = "_mlt_properties_time"; + mlt_properties_set( self, name, time ); + return mlt_properties_get_position( self, name ); +} + +/** Convert a numeric property to a tuple of color components. + * + * If the property's string is red, green, blue, white, or black, then it + * is converted to the corresponding opaque color tuple. Otherwise, the property + * is fetched as an integer and then converted. + * \public \memberof mlt_properties_s + * \param self a properties list + * \param name the property to get + * \return a color structure + */ + +mlt_color mlt_properties_get_color( mlt_properties self, const char* name ) +{ + 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_color result = { 0xff, 0xff, 0xff, 0xff }; + if ( value ) + { + const char *color = mlt_property_get_string_l( value, list->locale ); + unsigned int color_int = mlt_property_get_int( value, fps, list->locale ); + + if ( !strcmp( color, "red" ) ) + { + result.r = 0xff; + result.g = 0x00; + result.b = 0x00; + } + else if ( !strcmp( color, "green" ) ) + { + result.r = 0x00; + result.g = 0xff; + result.b = 0x00; + } + else if ( !strcmp( color, "blue" ) ) + { + result.r = 0x00; + result.g = 0x00; + result.b = 0xff; + } + else if ( !strcmp( color, "black" ) ) + { + result.r = 0x00; + result.g = 0x00; + result.b = 0x00; + } + else if ( strcmp( color, "white" ) ) + { + result.r = ( color_int >> 24 ) & 0xff; + result.g = ( color_int >> 16 ) & 0xff; + result.b = ( color_int >> 8 ) & 0xff; + result.a = ( color_int ) & 0xff; + } + } + return result; +} + +/** Set a property to an integer value by color. + * + * \public \memberof mlt_properties_s + * \param self a properties list + * \param name the property to set + * \param color the color + * \return true if error + */ + +int mlt_properties_set_color( mlt_properties self, const char *name, mlt_color color ) +{ + 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 ) + { + uint32_t value = ( color.r << 24 ) | ( color.g << 16 ) | ( color.b << 8 ) | color.a; + error = mlt_property_set_int( property, value ); + mlt_properties_do_mirror( self, name ); + } + + mlt_events_fire( self, "property-changed", name, NULL ); + + return error; +} + +/** Get a string value by name at a frame position. + * + * Do not free the returned string. It's lifetime is controlled by the property + * and this properties object. + * \public \memberof mlt_properties_s + * \param self a properties list + * \param name the property to get + * \param position the frame number + * \param length the maximum number of frames when interpreting negative keyframe times, + * <=0 if you don't care or need that + * \return the property's string value or NULL if it does not exist + */ + +char* mlt_properties_anim_get( 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 ); + mlt_property value = mlt_properties_find( self, name ); + property_list *list = self->local; + return value == NULL ? NULL : mlt_property_anim_get_string( value, fps, list->locale, position, length ); +} + +/** Set a property to a string at a frame position. + * + * The event "property-changed" is fired after the property has been set. + * + * This makes a copy of the string value you supply. + * \public \memberof mlt_properties_s + * \param self a properties list + * \param name the property to set + * \param value the property's new value + * \param position the frame number + * \param length the maximum number of frames when interpreting negative keyframe times, + * <=0 if you don't care or need that + * \return true if error + */ + +int mlt_properties_anim_set( mlt_properties self, const char *name, const char *value, 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 ) + { + mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL ); + double fps = mlt_profile_fps( profile ); + property_list *list = self->local; + error = mlt_property_anim_set_string( property, value, + fps, list->locale, position, length ); + mlt_properties_do_mirror( self, name ); + } + + mlt_events_fire( self, "property-changed", name, NULL ); + + return error; +} + +/** Get an integer associated to the name at a frame position. + * + * \public \memberof mlt_properties_s + * \param self a properties list + * \param name the property to get + * \param position the frame number + * \param length the maximum number of frames when interpreting negative keyframe times, + * <=0 if you don't care or need that + * \return the integer value, 0 if not found (which may also be a legitimate value) + */ + +int mlt_properties_anim_get_int( 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 ); + return value == NULL ? 0 : mlt_property_anim_get_int( value, fps, list->locale, position, length ); +} + +/** Set a property to an integer value at a frame position. + * + * \public \memberof mlt_properties_s + * \param self a properties list + * \param name the property to set + * \param value the integer + * \param position the frame number + * \param length the maximum number of frames when interpreting negative keyframe times, + * <=0 if you don't care or need that + * \param keyframe_type the interpolation method for this keyframe + * \return true if error + */ + +int mlt_properties_anim_set_int( mlt_properties self, const char *name, int value, + int position, int length, mlt_keyframe_type keyframe_type ) +{ + 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_anim_set_int( property, value, fps, list->locale, position, length, keyframe_type ); + mlt_properties_do_mirror( self, name ); + } + + mlt_events_fire( self, "property-changed", name, NULL ); + + return error; +} + +/** Get a real number associated to the name at a frame position. + * + * \public \memberof mlt_properties_s + * \param self a properties list + * \param name the property to get + * \param position the frame number + * \param length the maximum number of frames when interpreting negative keyframe times, + * <=0 if you don't care or need that + * \return the real number, 0 if not found (which may also be a legitimate value) + */ + +double mlt_properties_anim_get_double( 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 ); + return value == NULL ? 0.0 : mlt_property_anim_get_double( value, fps, list->locale, position, length ); +} + +/** Set a property to a real number at a frame position. + * + * \public \memberof mlt_properties_s + * \param self a properties list + * \param name the property to set + * \param value the real number + * \param position the frame number + * \param length the maximum number of frames when interpreting negative keyframe times, + * <=0 if you don't care or need that + * \param keyframe_type the interpolation method for this keyframe + * \return true if error + */ + +int mlt_properties_anim_set_double( mlt_properties self, const char *name, double value, + int position, int length, mlt_keyframe_type keyframe_type ) +{ + 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_anim_set_double( property, value, fps, list->locale, position, length, keyframe_type ); + mlt_properties_do_mirror( self, name ); + } + + mlt_events_fire( self, "property-changed", name, NULL ); + + return error; +} + +/** Get the animation associated to the name. + * + * \public \memberof mlt_properties_s + * \param self a properties list + * \param name the property to get + * \return The animation object or NULL if the property has no animation + */ + +mlt_animation mlt_properties_get_animation( mlt_properties self, const char *name ) +{ + mlt_property value = mlt_properties_find( self, name ); + return value == NULL ? NULL : mlt_property_get_animation( value ); +} + +/** Set a property to a rectangle value. + * + * \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( mlt_properties self, const char *name, mlt_rect value ) +{ + 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 ) + { + error = mlt_property_set_rect( property, value ); + 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( mlt_properties self, const char* name ) +{ + 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( 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 + * \param position the frame number + * \param length the maximum number of frames when interpreting negative keyframe times, + * <=0 if you don't care or need that + * \param keyframe_type the interpolation method for this keyframe + * \return true if error + */ + +extern int mlt_properties_anim_set_rect( mlt_properties self, const char *name, mlt_rect value, + int position, int length , mlt_keyframe_type keyframe_type ) +{ + 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_anim_set_rect( property, value, fps, list->locale, position, length, keyframe_type ); + mlt_properties_do_mirror( self, name ); + } + + mlt_events_fire( self, "property-changed", name, NULL ); + + return error; +} + +/** Get a rectangle associated to the name at a frame position. + * + * \public \memberof mlt_properties_s + * \param self a properties list + * \param name the property to get + * \param position the frame number + * \param length the maximum number of frames when interpreting negative keyframe times, + * <=0 if you don't care or need that + * \return the rectangle value, the rectangle fields will be DBL_MIN if not found + */ + +extern mlt_rect mlt_properties_anim_get_rect( 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_anim_get_rect( value, fps, list->locale, position, length ); +}