static mlt_repository filters = NULL;
static mlt_repository transitions = NULL;
static mlt_repository consumers = NULL;
+static mlt_properties event_object = NULL;
static int unique_id = 0;
+/** Event transmitters.
+*/
+
+static void mlt_factory_create_request( mlt_listener listener, mlt_properties owner, mlt_service this, void **args )
+{
+ if ( listener != NULL )
+ listener( owner, this, ( char * )args[ 0 ], ( char * )args[ 1 ], ( mlt_service * )args[ 2 ] );
+}
+
+static void mlt_factory_create_done( mlt_listener listener, mlt_properties owner, mlt_service this, void **args )
+{
+ if ( listener != NULL )
+ listener( owner, this, ( char * )args[ 0 ], ( char * )args[ 1 ], ( mlt_service )args[ 2 ] );
+}
+
/** Construct the factories.
*/
// Initialise the pool
mlt_pool_init( );
+ // Create and set up the events object
+ event_object = mlt_properties_new( );
+ mlt_events_init( event_object );
+ mlt_events_register( event_object, "producer-create-request", ( mlt_transmitter )mlt_factory_create_request );
+ mlt_events_register( event_object, "producer-create-done", ( mlt_transmitter )mlt_factory_create_done );
+ mlt_events_register( event_object, "filter-create-request", ( mlt_transmitter )mlt_factory_create_request );
+ mlt_events_register( event_object, "filter-create-done", ( mlt_transmitter )mlt_factory_create_done );
+ mlt_events_register( event_object, "transition-create-request", ( mlt_transmitter )mlt_factory_create_request );
+ mlt_events_register( event_object, "transition-create-done", ( mlt_transmitter )mlt_factory_create_done );
+ mlt_events_register( event_object, "consumer-create-request", ( mlt_transmitter )mlt_factory_create_request );
+ mlt_events_register( event_object, "consumer-create-done", ( mlt_transmitter )mlt_factory_create_done );
+
// Create the global properties
global_properties = mlt_properties_new( );
mlt_properties_set_or_default( global_properties, "MLT_NORMALISATION", getenv( "MLT_NORMALISATION" ), "PAL" );
return 0;
}
+/** Fetch the events object.
+*/
+
+mlt_properties mlt_factory_event_object( )
+{
+ return event_object;
+}
+
/** Fetch the prefix used in this instance.
*/
if ( service == NULL )
service = mlt_environment( "MLT_PRODUCER" );
- // Try to instantiate via the specified service
- obj = mlt_repository_fetch( producers, service, input );
+ // Offer the application the chance to 'create'
+ mlt_events_fire( event_object, "producer-create-request", service, input, &obj, NULL );
- if ( obj != NULL )
+ // Try to instantiate via the specified service
+ if ( obj == NULL )
{
- mlt_properties properties = mlt_producer_properties( obj );
- mlt_properties_set_int( properties, "_unique_id", ++ unique_id );
- mlt_properties_set( properties, "mlt_type", "producer" );
- if ( mlt_properties_get_int( properties, "_mlt_service_hidden" ) == 0 )
- mlt_properties_set( properties, "mlt_service", service );
+ obj = mlt_repository_fetch( producers, service, input );
+ mlt_events_fire( event_object, "producer-create-done", service, input, obj, NULL );
+ if ( obj != NULL )
+ {
+ mlt_properties properties = mlt_producer_properties( obj );
+ mlt_properties_set_int( properties, "_unique_id", ++ unique_id );
+ mlt_properties_set( properties, "mlt_type", "producer" );
+ if ( mlt_properties_get_int( properties, "_mlt_service_hidden" ) == 0 )
+ mlt_properties_set( properties, "mlt_service", service );
+ }
}
return obj;
}
mlt_filter mlt_factory_filter( char *service, void *input )
{
- mlt_filter obj = mlt_repository_fetch( filters, service, input );
+ mlt_filter obj = NULL;
+
+ // Offer the application the chance to 'create'
+ mlt_events_fire( event_object, "filter-create-request", service, input, &obj, NULL );
+
+ if ( obj == NULL )
+ {
+ obj = mlt_repository_fetch( filters, service, input );
+ mlt_events_fire( event_object, "filter-create-done", service, input, obj, NULL );
+ }
+
if ( obj != NULL )
{
mlt_properties properties = mlt_filter_properties( obj );
mlt_transition mlt_factory_transition( char *service, void *input )
{
- mlt_transition obj = mlt_repository_fetch( transitions, service, input );
+ mlt_transition obj = NULL;
+
+ // Offer the application the chance to 'create'
+ mlt_events_fire( event_object, "transition-create-request", service, input, &obj, NULL );
+
+ if ( obj == NULL )
+ {
+ obj = mlt_repository_fetch( transitions, service, input );
+ mlt_events_fire( event_object, "transition-create-done", service, input, obj, NULL );
+ }
+
if ( obj != NULL )
{
mlt_properties properties = mlt_transition_properties( obj );
if ( service == NULL )
service = mlt_environment( "MLT_CONSUMER" );
- obj = mlt_repository_fetch( consumers, service, input );
+ // Offer the application the chance to 'create'
+ mlt_events_fire( event_object, "consumer-create-request", service, input, &obj, NULL );
+
+ if ( obj == NULL )
+ {
+ obj = mlt_repository_fetch( consumers, service, input );
+ mlt_events_fire( event_object, "consumer-create-done", service, input, obj, NULL );
+ }
if ( obj != NULL )
{
{
if ( mlt_prefix != NULL )
{
+ mlt_properties_close( event_object );
mlt_repository_close( producers );
mlt_repository_close( filters );
mlt_repository_close( transitions );
extern int mlt_factory_init( char *prefix );
extern const char *mlt_factory_prefix( );
extern char *mlt_environment( char *name );
+extern mlt_properties mlt_factory_event_object( );
extern mlt_producer mlt_factory_producer( char *name, void *input );
extern mlt_filter mlt_factory_filter( char *name, void *input );
extern mlt_transition mlt_factory_transition( char *name, void *input );
mlt_properties_set_data( properties, "multitrack", this, 0, NULL, NULL );
mlt_properties_set( properties, "log_id", "multitrack" );
mlt_properties_set( properties, "resource", "<multitrack>" );
+ mlt_properties_set_int( properties, "in", 0 );
+ mlt_properties_set_int( properties, "out", -1 );
+ mlt_properties_set_int( properties, "length", 0 );
+ producer->close = ( mlt_destructor )mlt_multitrack_close;
}
else
{
}
// Close the producer
+ this->parent.close = NULL;
mlt_producer_close( &this->parent );
// Free the list
{
if ( this != NULL )
{
- mlt_playlist temp = mlt_playlist_init( );
- int original_size = mlt_producer_get_playtime( mlt_playlist_producer( temp ) );
- mlt_playlist_close( temp );
}
return 0;
}
if ( in <= 0 )
in = 0;
if ( ( out < 0 || out >= mlt_producer_get_playtime( parent ) ) && !mlt_producer_is_blank( this ) )
- out = mlt_producer_get_playtime( parent );
+ out = mlt_producer_get_playtime( parent ) - 1;
mlt_properties_inc_ref( parent_props );
mlt_properties_set_int( properties, "_cut", 1 );
mlt_properties_set_data( properties, "_cut_parent", parent, 0, ( mlt_destructor )mlt_producer_close, NULL );
mlt_properties_set_position( properties, "length", mlt_properties_get_position( parent_props, "length" ) );
- mlt_properties_set_position( properties, "in", 0 );
- mlt_properties_set_position( properties, "out", 0 );
mlt_producer_set_in_and_out( result, in, out );
return result;
// Correct ins and outs if necessary
if ( in < 0 )
in = 0;
- else if ( in > mlt_producer_get_length( this ) )
- in = mlt_producer_get_length( this );
+ else if ( in >= mlt_producer_get_length( this ) )
+ in = mlt_producer_get_length( this ) - 1;
if ( out < 0 )
out = 0;
- else if ( out > mlt_producer_get_length( this ) && !mlt_producer_is_blank( this ) )
- out = mlt_producer_get_length( this );
- else if ( out >= mlt_producer_get_length( this ) - 1 && mlt_producer_is_blank( this ) )
+ else if ( out >= mlt_producer_get_length( this ) && !mlt_producer_is_blank( this ) )
+ out = mlt_producer_get_length( this ) - 1;
+ else if ( out >= mlt_producer_get_length( this ) && mlt_producer_is_blank( this ) )
mlt_properties_set_position( mlt_producer_properties( this ), "length", out + 1 );
// Swap ins and outs if wrong
char *resource = mlt_properties_get( properties, "resource" );
char *service = mlt_properties_get( properties, "mlt_service" );
+ mlt_events_block( mlt_factory_event_object( ), mlt_factory_event_object( ) );
+
if ( service != NULL )
clone = mlt_factory_producer( service, resource );
if ( clone != NULL )
mlt_properties_inherit( mlt_producer_properties( clone ), properties );
+ mlt_events_unblock( mlt_factory_event_object( ), mlt_factory_event_object( ) );
+
return clone;
}
void mlt_properties_debug( mlt_properties this, char *title, FILE *output )
{
- fprintf( stderr, "%s: ", title );
+ fprintf( output, "%s: ", title );
if ( this != NULL )
{
property_list *list = this->local;
fprintf( output, ", %s=%p", list->name[ i ], mlt_properties_get_data( this, list->name[ i ], NULL ) );
fprintf( output, " ]" );
}
- fprintf( stderr, "\n" );
+ fprintf( output, "\n" );
}
/** Close the list.
}
else
{
- fprintf( stderr, "Ugh case\n" );
mlt_service_close( this );
}
return result;
mlt_producer producer = &this->parent;
if ( mlt_producer_init( producer, this ) == 0 )
{
- mlt_properties_set( mlt_producer_properties( producer ), "resource", "<tractor>" );
- mlt_properties_set( mlt_producer_properties( producer ), "mlt_type", "mlt_producer" );
- mlt_properties_set( mlt_producer_properties( producer ), "mlt_service", "tractor" );
+ mlt_properties properties = mlt_producer_properties( producer );
+
+ mlt_properties_set( properties, "resource", "<tractor>" );
+ mlt_properties_set( properties, "mlt_type", "mlt_producer" );
+ mlt_properties_set( properties, "mlt_service", "tractor" );
+ mlt_properties_set_int( properties, "in", 0 );
+ mlt_properties_set_int( properties, "out", -1 );
+ mlt_properties_set_int( properties, "length", 0 );
producer->get_frame = producer_get_frame;
producer->close = ( mlt_destructor )mlt_tractor_close;
// internal intialization
mlt_frame frame = NULL;
- struct timespec tm = { 0, 1000000 };
+ struct timespec tm = { 0, 10000000 };
if ( mlt_properties_get_int( mlt_consumer_properties( consumer ), "sdl_started" ) == 0 )
{
int pass;
mlt_properties hide_map;
char *root;
+ char *store;
};
typedef struct serialise_context_s* serialise_context;
}
}
+static inline void serialise_store_properties( serialise_context context, mlt_properties properties, xmlNode *node )
+{
+ int i;
+ xmlNode *p;
+
+ // Enumerate the properties
+ for ( i = 0; context->store != NULL && i < mlt_properties_count( properties ); i++ )
+ {
+ char *name = mlt_properties_get_name( properties, i );
+ if ( !strncmp( name, context->store, strlen( context->store ) ) )
+ {
+ char *value = mlt_properties_get_value( properties, i );
+ if ( value != NULL )
+ {
+ p = xmlNewChild( node, NULL, "property", NULL );
+ xmlNewProp( p, "name", mlt_properties_get_name( properties, i ) );
+ if ( context->root != NULL && strcmp( context->root, "" ) && !strncmp( value, context->root, strlen( context->root ) ) )
+ xmlNodeSetContent( p, value + strlen( context->root ) + 1 );
+ else
+ xmlNodeSetContent( p, value );
+ }
+ }
+ }
+}
+
static inline void serialise_service_filters( serialise_context context, mlt_service service, xmlNode *node )
{
int i;
// Set the id
xmlNewProp( child, "id", id );
+ // Store application specific properties
+ serialise_store_properties( context, properties, child );
+
// Add producer to the map
mlt_properties_set_int( context->hide_map, id, mlt_properties_get_int( properties, "hide" ) );
xmlNewProp( child, "in", mlt_properties_get( properties, "in" ) );
xmlNewProp( child, "out", mlt_properties_get( properties, "out" ) );
+ // Store application specific properties
+ serialise_store_properties( context, mlt_service_properties( service ), child );
+
// Recurse on connected producer
serialise_service( context, mlt_service_producer( service ), child );
serialise_service_filters( context, service, child );
}
}
-xmlDocPtr westley_make_doc( mlt_service service )
+xmlDocPtr westley_make_doc( mlt_consumer consumer, mlt_service service )
{
mlt_properties properties = mlt_service_properties( service );
xmlDocPtr doc = xmlNewDoc( "1.0" );
context->root = strdup( "" );
}
+ // Assign the additional 'storage' pattern for properties
+ context->store = mlt_properties_get( mlt_consumer_properties( consumer ), "store" );
+
// Assign a title property
if ( mlt_properties_get( properties, "title" ) != NULL )
xmlNewProp( root, "title", mlt_properties_get( properties, "title" ) );
}
// Make the document
- doc = westley_make_doc( service );
+ doc = westley_make_doc( this, service );
// Handle the output
if ( resource == NULL || !strcmp( resource, "" ) )
track_service( context->destructors, service, (mlt_destructor) mlt_tractor_close );
- mlt_properties_set_position( properties, "length", 0 );
-
for ( ; atts != NULL && *atts != NULL; atts += 2 )
mlt_properties_set( mlt_service_properties( service ), (char*) atts[0], (char*) atts[1] );
- if ( mlt_properties_get_position( properties, "length" ) < mlt_properties_get_position( properties, "out" ) )
- {
- mlt_position length = mlt_properties_get_position( properties, "out" ) + 1;
- mlt_properties_set_position( properties, "length", length );
- }
-
if ( mlt_properties_get( properties, "id" ) != NULL )
mlt_properties_set_data( context->producer_map, mlt_properties_get( properties, "id" ), service, 0, NULL, NULL );
{
mlt_service service = MLT_SERVICE( mlt_tractor_multitrack( MLT_TRACTOR( parent ) ) );
mlt_properties properties = mlt_service_properties( service );
- mlt_properties_set_position( properties, "length", 0 );
for ( ; atts != NULL && *atts != NULL; atts += 2 )
mlt_properties_set( properties, (char*) atts[0], (char*) atts[1] );
track_service( context->destructors, service, (mlt_destructor) mlt_playlist_close );
- mlt_properties_set_position( properties, "length", 0 );
-
for ( ; atts != NULL && *atts != NULL; atts += 2 )
{
mlt_properties_set( properties, ( char* )atts[0], ( char* )atts[1] );
{
mlt_properties properties = mlt_service_properties( service );
mlt_position in = mlt_properties_get_position( properties, "in" );
- mlt_position out;
+ mlt_position out = mlt_properties_get_position( properties, "out" );
- if ( mlt_properties_get( properties, "_westley.out" ) != NULL )
- out = mlt_properties_get_position( properties, "_westley.out" );
- else
- out = mlt_properties_get_position( properties, "length" ) - 1;
-
- if ( mlt_properties_get_position( properties, "length" ) < out )
- mlt_properties_set_position( properties, "length", out + 1 );
-
- mlt_producer_set_in_and_out( MLT_PRODUCER( service ), in, out );
-
// See if the playlist should be added to a playlist or multitrack
if ( add_producer( context, service, in, out ) == 0 )
context_push_service( context, service, type );
if ( mlt_properties_get( track_props, "in" ) != NULL ||
mlt_properties_get( track_props, "out" ) != NULL )
{
- if ( mlt_properties_get( track_props, "out" ) == NULL )
- mlt_properties_set_position( track_props, "out", mlt_properties_get_position( track_props, "length" ) - 1 );
mlt_producer cut = mlt_producer_cut( MLT_PRODUCER( producer ),
mlt_properties_get_position( track_props, "in" ),
mlt_properties_get_position( track_props, "out" ) );
else
xmlcontext = xmlCreateMemoryParserCtxt( data, strlen( data ) );
+ // Invalid context - clean up and return NULL
+ if ( xmlcontext == NULL )
+ {
+ mlt_properties_close( context->producer_map );
+ mlt_properties_close( context->destructors );
+ mlt_properties_close( context->params );
+ free( context );
+ free( sax );
+ free( filename );
+ return NULL;
+ }
+
xmlcontext->sax = sax;
xmlcontext->_private = ( void* )context;
// Set this var to service properties for convenience
properties = mlt_service_properties( service );
- // make the returned service destroy the connected services
- mlt_properties_set_data( properties, "__destructors__", context->destructors, 0, (mlt_destructor) mlt_properties_close, NULL );
-
// Assign the title
mlt_properties_set( properties, "title", title );
{
// Return null if not well formed
service = NULL;
-
- // Clean up
- mlt_properties_close( context->destructors );
}
// Clean up
mlt_properties_close( context->producer_map );
if ( context->params != NULL )
mlt_properties_close( context->params );
+ mlt_properties_close( context->destructors );
free( context );
free( filename );