* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+// For strtod_l
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
#include "mlt_property.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <locale.h>
+#include <pthread.h>
/** Bit pattern used internally to indicated representations available.
int length;
mlt_destructor destructor;
mlt_serialiser serialiser;
+
+ pthread_mutex_t mutex;
};
/** Construct a property and initialize it
self->length = 0;
self->destructor = NULL;
self->serialiser = NULL;
+ pthread_mutex_init( &self->mutex, NULL );
}
return self;
}
int mlt_property_set_int( mlt_property self, int value )
{
+ pthread_mutex_lock( &self->mutex );
mlt_property_clear( self );
self->types = mlt_prop_int;
self->prop_int = value;
+ pthread_mutex_unlock( &self->mutex );
return 0;
}
int mlt_property_set_double( mlt_property self, double value )
{
+ pthread_mutex_lock( &self->mutex );
mlt_property_clear( self );
self->types = mlt_prop_double;
self->prop_double = value;
+ pthread_mutex_unlock( &self->mutex );
return 0;
}
int mlt_property_set_position( mlt_property self, mlt_position value )
{
+ pthread_mutex_lock( &self->mutex );
mlt_property_clear( self );
self->types = mlt_prop_position;
self->prop_position = value;
+ pthread_mutex_unlock( &self->mutex );
return 0;
}
int mlt_property_set_string( mlt_property self, const char *value )
{
+ pthread_mutex_lock( &self->mutex );
if ( value != self->prop_string )
{
mlt_property_clear( self );
{
self->types = mlt_prop_string;
}
+ pthread_mutex_unlock( &self->mutex );
return self->prop_string == NULL;
}
int mlt_property_set_int64( mlt_property self, int64_t value )
{
+ pthread_mutex_lock( &self->mutex );
mlt_property_clear( self );
self->types = mlt_prop_int64;
self->prop_int64 = value;
+ pthread_mutex_unlock( &self->mutex );
return 0;
}
int mlt_property_set_data( mlt_property self, void *value, int length, mlt_destructor destructor, mlt_serialiser serialiser )
{
+ pthread_mutex_lock( &self->mutex );
if ( self->data == value )
self->destructor = NULL;
mlt_property_clear( self );
self->length = length;
self->destructor = destructor;
self->serialiser = serialiser;
+ pthread_mutex_unlock( &self->mutex );
return 0;
}
return 0;
}
+/** Get the property (with locale) as a floating point.
+ *
+ * \public \memberof mlt_property_s
+ * \param self a property
+ * \param locale the locale to use for this conversion
+ * \return a floating point value
+ */
+
+double mlt_property_get_double_l( mlt_property self, locale_t locale )
+{
+ if ( self->types & mlt_prop_double )
+ return self->prop_double;
+ else if ( self->types & mlt_prop_int )
+ return ( double )self->prop_int;
+ else if ( self->types & mlt_prop_position )
+ return ( double )self->prop_position;
+ else if ( self->types & mlt_prop_int64 )
+ return ( double )self->prop_int64;
+#if defined(__GLIBC__) || defined(__DARWIN__)
+ else if ( locale && ( self->types & mlt_prop_string ) && self->prop_string )
+ return strtod_l( self->prop_string, NULL, locale );
+#endif
+ else if ( ( self->types & mlt_prop_string ) && self->prop_string )
+ return strtod( self->prop_string, NULL );
+ return 0;
+}
+
/** Get the property as a position.
*
* A position is an offset time in terms of frame units.
// Construct a string if need be
if ( ! ( self->types & mlt_prop_string ) )
{
+ pthread_mutex_lock( &self->mutex );
if ( self->types & mlt_prop_int )
{
self->types |= mlt_prop_string;
{
self->types |= mlt_prop_string;
self->prop_string = malloc( 32 );
- sprintf( self->prop_string, "%d", (int)self->prop_position ); /* I don't know if self is wanted. -Zach */
+ sprintf( self->prop_string, "%d", (int)self->prop_position );
}
else if ( self->types & mlt_prop_int64 )
{
self->types |= mlt_prop_string;
self->prop_string = malloc( 32 );
- sprintf( self->prop_string, "%lld", (long long int)self->prop_int64 );
+ sprintf( self->prop_string, "%"PRId64, self->prop_int64 );
}
else if ( self->types & mlt_prop_data && self->serialiser != NULL )
{
self->types |= mlt_prop_string;
self->prop_string = self->serialiser( self->data, self->length );
}
+ pthread_mutex_unlock( &self->mutex );
+ }
+
+ // Return the string (may be NULL)
+ return self->prop_string;
+}
+
+/** Get the property as a string (with locale).
+ *
+ * The caller is not responsible for deallocating the returned string!
+ * The string is deallocated when the Property is closed.
+ * This tries its hardest to convert the property to string including using
+ * a serialization function for binary data, if supplied.
+ * \public \memberof mlt_property_s
+ * \param self a property
+ * \param locale the locale to use for this conversion
+ * \return a string representation of the property or NULL if failed
+ */
+
+char *mlt_property_get_string_l( mlt_property self, locale_t locale )
+{
+ // Optimization for no locale
+ if ( !locale )
+ return mlt_property_get_string( self );
+
+ // Construct a string if need be
+ if ( ! ( self->types & mlt_prop_string ) )
+ {
+ // TODO: when glibc gets sprintf_l, start using it! For now, hack on setlocale.
+ // Save the current locale
+#if defined(__DARWIN__)
+ const char *localename = querylocale( LC_NUMERIC, locale );
+#elif defined(__GLIBC__)
+ const char *localename = locale->__names[ LC_NUMERIC ];
+#else
+ // TODO: not yet sure what to do on other platforms
+ const char *localename = "";
+#endif
+ // Protect damaging the global locale from a temporary locale on another thread.
+ pthread_mutex_lock( &self->mutex );
+
+ // Get the current locale
+ char *orig_localename = strdup( setlocale( LC_NUMERIC, NULL ) );
+
+ // Set the new locale
+ setlocale( LC_NUMERIC, localename );
+
+ if ( self->types & mlt_prop_int )
+ {
+ self->types |= mlt_prop_string;
+ self->prop_string = malloc( 32 );
+ sprintf( self->prop_string, "%d", self->prop_int );
+ }
+ else if ( self->types & mlt_prop_double )
+ {
+ self->types |= mlt_prop_string;
+ self->prop_string = malloc( 32 );
+ sprintf( self->prop_string, "%f", self->prop_double );
+ }
+ else if ( self->types & mlt_prop_position )
+ {
+ self->types |= mlt_prop_string;
+ self->prop_string = malloc( 32 );
+ sprintf( self->prop_string, "%d", (int)self->prop_position );
+ }
+ else if ( self->types & mlt_prop_int64 )
+ {
+ self->types |= mlt_prop_string;
+ self->prop_string = malloc( 32 );
+ sprintf( self->prop_string, "%"PRId64, self->prop_int64 );
+ }
+ else if ( self->types & mlt_prop_data && self->serialiser != NULL )
+ {
+ self->types |= mlt_prop_string;
+ self->prop_string = self->serialiser( self->data, self->length );
+ }
+ // Restore the current locale
+ setlocale( LC_NUMERIC, orig_localename );
+ free( orig_localename );
+ pthread_mutex_unlock( &self->mutex );
}
// Return the string (may be NULL)
void mlt_property_close( mlt_property self )
{
mlt_property_clear( self );
+ pthread_mutex_destroy( &self->mutex );
free( self );
}
*/
void mlt_property_pass( mlt_property self, mlt_property that )
{
+ pthread_mutex_lock( &self->mutex );
mlt_property_clear( self );
self->types = that->types;
self->prop_double = that->prop_double;
else if ( self->types & mlt_prop_position )
self->prop_position = that->prop_position;
- else if ( self->types & mlt_prop_string )
+ if ( self->types & mlt_prop_string )
{
if ( that->prop_string != NULL )
self->prop_string = strdup( that->prop_string );
self->types = mlt_prop_string;
self->prop_string = self->serialiser( self->data, self->length );
}
+ pthread_mutex_unlock( &self->mutex );
}