From 90da79f8e465d43102645de7323d15c12801515f Mon Sep 17 00:00:00 2001 From: lilo_booter Date: Thu, 25 Nov 2004 13:41:20 +0000 Subject: [PATCH] Extendable factories; general producer related modifications; westley storage; sdl_still increased latency git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@536 d19143bc-622f-0410-bfdd-b5b2a6649095 --- src/framework/mlt_factory.c | 92 ++++++++++++++++++++++++++++---- src/framework/mlt_factory.h | 1 + src/framework/mlt_multitrack.c | 5 ++ src/framework/mlt_playlist.c | 3 - src/framework/mlt_producer.c | 18 ++++--- src/framework/mlt_properties.c | 4 +- src/framework/mlt_service.c | 1 - src/framework/mlt_tractor.c | 11 +++- src/modules/sdl/consumer_sdl_still.c | 2 +- src/modules/westley/consumer_westley.c | 39 +++++++++++++- src/modules/westley/producer_westley.c | 44 +++++---------- 11 files changed, 159 insertions(+), 61 deletions(-) diff --git a/src/framework/mlt_factory.c b/src/framework/mlt_factory.c index dbaf2db..8766fd6 100644 --- a/src/framework/mlt_factory.c +++ b/src/framework/mlt_factory.c @@ -36,8 +36,24 @@ static mlt_repository producers = NULL; 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. */ @@ -60,6 +76,18 @@ int mlt_factory_init( char *prefix ) // 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" ); @@ -83,6 +111,14 @@ int mlt_factory_init( char *prefix ) return 0; } +/** Fetch the events object. +*/ + +mlt_properties mlt_factory_event_object( ) +{ + return event_object; +} + /** Fetch the prefix used in this instance. */ @@ -110,16 +146,22 @@ mlt_producer mlt_factory_producer( char *service, void *input ) 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; } @@ -129,7 +171,17 @@ mlt_producer mlt_factory_producer( char *service, void *input ) 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 ); @@ -145,7 +197,17 @@ mlt_filter mlt_factory_filter( char *service, void *input ) 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 ); @@ -166,7 +228,14 @@ mlt_consumer mlt_factory_consumer( char *service, void *input ) 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 ) { @@ -198,6 +267,7 @@ void mlt_factory_close( ) { if ( mlt_prefix != NULL ) { + mlt_properties_close( event_object ); mlt_repository_close( producers ); mlt_repository_close( filters ); mlt_repository_close( transitions ); diff --git a/src/framework/mlt_factory.h b/src/framework/mlt_factory.h index e2842ce..219e5f5 100644 --- a/src/framework/mlt_factory.h +++ b/src/framework/mlt_factory.h @@ -26,6 +26,7 @@ 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 ); diff --git a/src/framework/mlt_multitrack.c b/src/framework/mlt_multitrack.c index d274dbc..7e16e04 100644 --- a/src/framework/mlt_multitrack.c +++ b/src/framework/mlt_multitrack.c @@ -70,6 +70,10 @@ mlt_multitrack mlt_multitrack_init( ) mlt_properties_set_data( properties, "multitrack", this, 0, NULL, NULL ); mlt_properties_set( properties, "log_id", "multitrack" ); mlt_properties_set( properties, "resource", "" ); + 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 { @@ -459,6 +463,7 @@ void mlt_multitrack_close( mlt_multitrack this ) } // Close the producer + this->parent.close = NULL; mlt_producer_close( &this->parent ); // Free the list diff --git a/src/framework/mlt_playlist.c b/src/framework/mlt_playlist.c index 2cf7e86..e59b05c 100644 --- a/src/framework/mlt_playlist.c +++ b/src/framework/mlt_playlist.c @@ -1359,9 +1359,6 @@ int mlt_playlist_move_region( mlt_playlist this, int position, int length, int n { 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; } diff --git a/src/framework/mlt_producer.c b/src/framework/mlt_producer.c index 50d1222..58594b8 100644 --- a/src/framework/mlt_producer.c +++ b/src/framework/mlt_producer.c @@ -196,14 +196,12 @@ mlt_producer mlt_producer_cut( mlt_producer this, int in, int out ) 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; @@ -313,14 +311,14 @@ int mlt_producer_set_in_and_out( mlt_producer this, mlt_position in, mlt_positio // 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 @@ -544,6 +542,8 @@ static mlt_producer mlt_producer_clone( mlt_producer this ) 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 ); @@ -553,6 +553,8 @@ static mlt_producer mlt_producer_clone( mlt_producer this ) if ( clone != NULL ) mlt_properties_inherit( mlt_producer_properties( clone ), properties ); + mlt_events_unblock( mlt_factory_event_object( ), mlt_factory_event_object( ) ); + return clone; } diff --git a/src/framework/mlt_properties.c b/src/framework/mlt_properties.c index e84ee07..0bad06b 100644 --- a/src/framework/mlt_properties.c +++ b/src/framework/mlt_properties.c @@ -666,7 +666,7 @@ void mlt_properties_dump( mlt_properties this, FILE *output ) 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; @@ -679,7 +679,7 @@ void mlt_properties_debug( mlt_properties this, char *title, FILE *output ) 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. diff --git a/src/framework/mlt_service.c b/src/framework/mlt_service.c index afc671d..93ee56b 100644 --- a/src/framework/mlt_service.c +++ b/src/framework/mlt_service.c @@ -380,7 +380,6 @@ int mlt_service_get_frame( mlt_service this, mlt_frame_ptr frame, int index ) } else { - fprintf( stderr, "Ugh case\n" ); mlt_service_close( this ); } return result; diff --git a/src/framework/mlt_tractor.c b/src/framework/mlt_tractor.c index 6ad86fc..92533de 100644 --- a/src/framework/mlt_tractor.c +++ b/src/framework/mlt_tractor.c @@ -55,9 +55,14 @@ mlt_tractor mlt_tractor_init( ) mlt_producer producer = &this->parent; if ( mlt_producer_init( producer, this ) == 0 ) { - mlt_properties_set( mlt_producer_properties( producer ), "resource", "" ); - 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", "" ); + 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; diff --git a/src/modules/sdl/consumer_sdl_still.c b/src/modules/sdl/consumer_sdl_still.c index 13f73ee..3ac12c0 100644 --- a/src/modules/sdl/consumer_sdl_still.c +++ b/src/modules/sdl/consumer_sdl_still.c @@ -533,7 +533,7 @@ static void *consumer_thread( void *arg ) // 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 ) { diff --git a/src/modules/westley/consumer_westley.c b/src/modules/westley/consumer_westley.c index 63e320e..a5aaaf8 100644 --- a/src/modules/westley/consumer_westley.c +++ b/src/modules/westley/consumer_westley.c @@ -42,6 +42,7 @@ struct serialise_context_s int pass; mlt_properties hide_map; char *root; + char *store; }; typedef struct serialise_context_s* serialise_context; @@ -198,6 +199,31 @@ static inline void serialise_properties( serialise_context context, mlt_properti } } +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; @@ -353,6 +379,9 @@ static void serialise_playlist( serialise_context context, mlt_service service, // 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" ) ); @@ -425,6 +454,9 @@ static void serialise_tractor( serialise_context context, mlt_service service, x 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 ); @@ -569,7 +601,7 @@ static void serialise_service( serialise_context context, mlt_service service, x } } -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" ); @@ -589,6 +621,9 @@ xmlDocPtr westley_make_doc( mlt_service service ) 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" ) ); @@ -649,7 +684,7 @@ static int consumer_start( mlt_consumer this ) } // Make the document - doc = westley_make_doc( service ); + doc = westley_make_doc( this, service ); // Handle the output if ( resource == NULL || !strcmp( resource, "" ) ) diff --git a/src/modules/westley/producer_westley.c b/src/modules/westley/producer_westley.c index 40e94c1..2f3a458 100644 --- a/src/modules/westley/producer_westley.c +++ b/src/modules/westley/producer_westley.c @@ -292,17 +292,9 @@ static void on_start_tractor( deserialise_context context, const xmlChar *name, 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 ); @@ -348,7 +340,6 @@ static void on_start_multitrack( deserialise_context context, const xmlChar *nam { 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] ); @@ -381,8 +372,6 @@ static void on_start_playlist( deserialise_context context, const xmlChar *name, 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] ); @@ -408,18 +397,8 @@ static void on_end_playlist( deserialise_context context, const xmlChar *name ) { 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 ); @@ -730,8 +709,6 @@ static void on_end_track( deserialise_context context, const xmlChar *name ) 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" ) ); @@ -1324,6 +1301,18 @@ mlt_producer producer_westley_init( int info, char *data ) 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; @@ -1380,9 +1369,6 @@ mlt_producer producer_westley_init( int info, char *data ) // 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 ); @@ -1410,15 +1396,13 @@ mlt_producer producer_westley_init( int info, char *data ) { // 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 ); -- 1.7.4.4