X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fmodules%2Fwestley%2Fproducer_westley.c;h=1d427543622b06cc86d05035cfbacc527f604af8;hb=4580365ba2f57f530aa4bdeb57788822fab09e2f;hp=4d862dda5153a0f1ae49f0e689a9e7fecf3c8155;hpb=2f768c42c67ec9802222032f6d2bc63d7a3c6afb;p=melted diff --git a/src/modules/westley/producer_westley.c b/src/modules/westley/producer_westley.c index 4d862dd..1d42754 100644 --- a/src/modules/westley/producer_westley.c +++ b/src/modules/westley/producer_westley.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include // for xmlCreateFileParserCtxt @@ -53,7 +54,7 @@ enum service_type mlt_transition_type, mlt_consumer_type, mlt_field_type, - mlt_service_type, + mlt_services_type, mlt_dummy_filter_type, mlt_dummy_transition_type, mlt_dummy_producer_type, @@ -172,13 +173,14 @@ static inline void qualify_property( deserialise_context context, mlt_properties if ( resource != NULL ) { // Qualify file name properties - char *root = mlt_properties_get( context->producer_map, "_root" ); - if ( root != NULL ) + char *root = mlt_properties_get( context->producer_map, "root" ); + if ( root != NULL && strcmp( root, "" ) ) { - char *full_resource = malloc( strlen( root ) + strlen( resource ) + 1 ); - if ( resource[ 0 ] != '/' ) + char *full_resource = malloc( strlen( root ) + strlen( resource ) + 2 ); + if ( resource[ 0 ] != '/' && strchr( resource, ':' ) == NULL ) { strcpy( full_resource, root ); + strcat( full_resource, "/" ); strcat( full_resource, resource ); } else @@ -597,7 +599,84 @@ static void on_start_blank( deserialise_context context, const xmlChar *name, co } } -static void on_start_entry_track( deserialise_context context, const xmlChar *name, const xmlChar **atts) +static void on_start_entry( deserialise_context context, const xmlChar *name, const xmlChar **atts) +{ + mlt_producer entry = NULL; + mlt_properties temp = mlt_properties_new( ); + + for ( ; atts != NULL && *atts != NULL; atts += 2 ) + { + mlt_properties_set( temp, (char*) atts[0], (char*) atts[1] ); + + // Look for the producer attribute + if ( strcmp( atts[ 0 ], "producer" ) == 0 ) + { + mlt_producer producer = mlt_properties_get_data( context->producer_map, (char*) atts[1], NULL ); + if ( producer != NULL ) + mlt_properties_set_data( temp, "producer", producer, 0, NULL, NULL ); + } + } + + // If we have a valid entry + if ( mlt_properties_get_data( temp, "producer", NULL ) != NULL ) + { + mlt_playlist_clip_info info; + enum service_type parent_type; + mlt_service parent = context_pop_service( context, &parent_type ); + mlt_producer producer = mlt_properties_get_data( temp, "producer", NULL ); + + if ( parent_type == mlt_playlist_type ) + { + // Append the producer to the playlist + if ( mlt_properties_get( temp, "in" ) != NULL || mlt_properties_get( temp, "out" ) != NULL ) + { + mlt_playlist_append_io( MLT_PLAYLIST( parent ), producer, + mlt_properties_get_position( temp, "in" ), + mlt_properties_get_position( temp, "out" ) ); + } + else + { + mlt_playlist_append( MLT_PLAYLIST( parent ), producer ); + } + + // Handle the repeat property + if ( mlt_properties_get_int( temp, "repeat" ) > 0 ) + { + mlt_playlist_repeat_clip( MLT_PLAYLIST( parent ), + mlt_playlist_count( MLT_PLAYLIST( parent ) ) - 1, + mlt_properties_get_int( temp, "repeat" ) ); + } + + mlt_playlist_get_clip_info( MLT_PLAYLIST( parent ), &info, mlt_playlist_count( MLT_PLAYLIST( parent ) ) - 1 ); + entry = info.cut; + } + else + { + fprintf( stderr, "Entry not part of a playlist...\n" ); + } + + context_push_service( context, parent, parent_type ); + } + + // Push the cut onto the stack + context_push_service( context, mlt_producer_service( entry ), mlt_entry_type ); + + mlt_properties_close( temp ); +} + +static void on_end_entry( deserialise_context context, const xmlChar *name ) +{ + // Get the entry from the stack + enum service_type entry_type; + mlt_service entry = context_pop_service( context, &entry_type ); + + if ( entry == NULL && entry_type != mlt_entry_type ) + { + fprintf( stderr, "Invalid state at end of entry\n" ); + } +} + +static void on_start_track( deserialise_context context, const xmlChar *name, const xmlChar **atts) { // use a dummy service to hold properties to allow arbitrary nesting mlt_service service = calloc( 1, sizeof( struct mlt_service_s ) ); @@ -606,10 +685,7 @@ static void on_start_entry_track( deserialise_context context, const xmlChar *na // Push the dummy service onto the stack context_push_service( context, service, mlt_entry_type ); - if ( strcmp( name, "entry" ) == 0 ) - mlt_properties_set( mlt_service_properties( service ), "resource", "" ); - else - mlt_properties_set( mlt_service_properties( service ), "resource", "" ); + mlt_properties_set( mlt_service_properties( service ), "resource", "" ); for ( ; atts != NULL && *atts != NULL; atts += 2 ) { @@ -650,18 +726,24 @@ static void on_end_track( deserialise_context context, const xmlChar *name ) if ( multitrack != NULL ) { - // Set the track on the multitrack - mlt_multitrack_connect( multitrack, producer, mlt_multitrack_count( multitrack ) ); - // Set producer i/o if specified if ( mlt_properties_get( track_props, "in" ) != NULL || - mlt_properties_get( track_props, "out" ) != NULL ) + mlt_properties_get( track_props, "out" ) != NULL ) { - mlt_producer_set_in_and_out( MLT_PRODUCER( producer ), + 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" ) ); + mlt_properties_set_int( mlt_producer_properties( cut ), "cut", 1 ); + mlt_multitrack_connect( multitrack, cut, mlt_multitrack_count( multitrack ) ); + mlt_producer_close( cut ); } - + else + { + mlt_multitrack_connect( multitrack, producer, mlt_multitrack_count( multitrack ) ); + } + // Set the hide state of the track producer char *hide_s = mlt_properties_get( track_props, "hide" ); if ( hide_s != NULL ) @@ -686,50 +768,6 @@ static void on_end_track( deserialise_context context, const xmlChar *name ) } } -static void on_end_entry( deserialise_context context, const xmlChar *name ) -{ - // Get the entry from the stack - enum service_type entry_type; - mlt_service entry = context_pop_service( context, &entry_type ); - - if ( entry != NULL && entry_type == mlt_entry_type ) - { - mlt_properties entry_props = mlt_service_properties( entry ); - enum service_type parent_type; - mlt_service parent = context_pop_service( context, &parent_type ); - mlt_producer producer = mlt_properties_get_data( entry_props, "producer", NULL ); - - if ( parent_type == mlt_playlist_type ) - { - // Append the producer to the playlist - if ( mlt_properties_get( mlt_service_properties( entry ), "in" ) != NULL || - mlt_properties_get( mlt_service_properties( entry ), "out" ) != NULL ) - { - mlt_playlist_append_io( MLT_PLAYLIST( parent ), producer, - mlt_properties_get_position( mlt_service_properties( entry ), "in" ), - mlt_properties_get_position( mlt_service_properties( entry ), "out" ) ); - } - else - { - mlt_playlist_append( MLT_PLAYLIST( parent ), producer ); - } - } - else - { - fprintf( stderr, "Invalid position for an entry...\n" ); - } - - if ( parent != NULL ) - context_push_service( context, parent, parent_type ); - - mlt_service_close( entry ); - } - else - { - fprintf( stderr, "Invalid state at end of entry\n" ); - } -} - static void on_start_filter( deserialise_context context, const xmlChar *name, const xmlChar **atts) { // use a dummy service to hold properties to allow arbitrary nesting @@ -853,6 +891,8 @@ static void on_end_transition( deserialise_context context, const xmlChar *name if ( parent_type == mlt_tractor_type ) { mlt_field field = mlt_tractor_field( MLT_TRACTOR( parent ) ); + if ( mlt_properties_get_int( properties, "a_track" ) == mlt_properties_get_int( properties, "b_track" ) ) + mlt_properties_set_int( properties, "b_track", mlt_properties_get_int( properties, "a_track" ) + 1 ); mlt_field_plant_transition( field, MLT_TRANSITION( effect ), mlt_properties_get_int( properties, "a_track" ), mlt_properties_get_int( properties, "b_track" ) ); @@ -992,14 +1032,19 @@ static void on_start_element( void *ctx, const xmlChar *name, const xmlChar **at on_start_producer( context, name, atts ); else if ( strcmp( name, "blank" ) == 0 ) on_start_blank( context, name, atts ); - else if ( strcmp( name, "entry" ) == 0 || strcmp( name, "track" ) == 0 ) - on_start_entry_track( context, name, atts ); + else if ( strcmp( name, "entry" ) == 0 ) + on_start_entry( context, name, atts ); + else if ( strcmp( name, "track" ) == 0 ) + on_start_track( context, name, atts ); else if ( strcmp( name, "filter" ) == 0 ) on_start_filter( context, name, atts ); else if ( strcmp( name, "transition" ) == 0 ) on_start_transition( context, name, atts ); else if ( strcmp( name, "property" ) == 0 ) on_start_property( context, name, atts ); + else if ( strcmp( name, "westley" ) == 0 ) + for ( ; atts != NULL && *atts != NULL; atts += 2 ) + mlt_properties_set( context->producer_map, ( char * )atts[ 0 ], ( char * )atts[ 1 ] ); } static void on_end_element( void *ctx, const xmlChar *name ) @@ -1213,9 +1258,9 @@ static void parse_url( mlt_properties properties, char *url ) mlt_properties_set( properties, name, value ); } -mlt_producer producer_westley_init( char *url ) +mlt_producer producer_westley_init( int info, char *data ) { - if ( url == NULL ) + if ( data == NULL ) return NULL; xmlSAXHandler *sax = calloc( 1, sizeof( xmlSAXHandler ) ); struct deserialise_context_s *context = calloc( 1, sizeof( struct deserialise_context_s ) ); @@ -1223,28 +1268,43 @@ mlt_producer producer_westley_init( char *url ) int i = 0; struct _xmlParserCtxt *xmlcontext; int well_formed = 0; - char *filename = strdup( url ); + char *filename = NULL; context->producer_map = mlt_properties_new(); context->destructors = mlt_properties_new(); context->params = mlt_properties_new(); - // Decode URL and parse parameters - parse_url( context->params, url_decode( filename, url ) ); + // Decode URL and parse parameters + mlt_properties_set( context->producer_map, "root", "" ); + if ( info == 0 ) + { + filename = strdup( data ); + parse_url( context->params, url_decode( filename, data ) ); - // We need to track the number of registered filters - mlt_properties_set_int( context->destructors, "registered", 0 ); + // We need the directory prefix which was used for the westley + if ( strchr( filename, '/' ) ) + { + char *root = NULL; + mlt_properties_set( context->producer_map, "root", filename ); + root = mlt_properties_get( context->producer_map, "root" ); + *( strrchr( root, '/' ) ) = '\0'; - // We need the directory prefix which was used for the westley - mlt_properties_set( context->producer_map, "_root", "" ); - if ( strchr( filename, '/' ) ) - { - char *root = NULL; - mlt_properties_set( context->producer_map, "_root", filename ); - root = mlt_properties_get( context->producer_map, "_root" ); - *( strrchr( root, '/' ) + 1 ) = '\0'; + // If we don't have an absolute path here, we're heading for disaster... + if ( root[ 0 ] != '/' ) + { + char *cwd = getcwd( NULL, 0 ); + char *real = malloc( strlen( cwd ) + strlen( root ) + 2 ); + sprintf( real, "%s/%s", cwd, root ); + mlt_properties_set( context->producer_map, "root", real ); + free( real ); + free( cwd ); + } + } } + // We need to track the number of registered filters + mlt_properties_set_int( context->destructors, "registered", 0 ); + // Setup SAX callbacks sax->startElement = on_start_element; sax->endElement = on_end_element; @@ -1259,7 +1319,11 @@ mlt_producer producer_westley_init( char *url ) xmlSubstituteEntitiesDefault( 1 ); // This is used to facilitate entity substitution in the SAX parser context->entity_doc = xmlNewDoc( "1.0" ); - xmlcontext = xmlCreateFileParserCtxt( filename ); + if ( info == 0 ) + xmlcontext = xmlCreateFileParserCtxt( filename ); + else + xmlcontext = xmlCreateMemoryParserCtxt( data, strlen( data ) ); + xmlcontext->sax = sax; xmlcontext->_private = ( void* )context; @@ -1296,6 +1360,7 @@ mlt_producer producer_westley_init( char *url ) if ( well_formed && service != NULL ) { + char *title = mlt_properties_get( context->producer_map, "title" ); // Need the complete producer list for various reasons properties = context->destructors; @@ -1318,11 +1383,28 @@ mlt_producer producer_westley_init( char *url ) // make the returned service destroy the connected services mlt_properties_set_data( properties, "__destructors__", context->destructors, 0, (mlt_destructor) mlt_properties_close, NULL ); - // Now assign additional properties - mlt_properties_set( properties, "resource", url ); + // Assign the title + mlt_properties_set( properties, "title", title ); - // This tells consumer_westley not to deep copy - mlt_properties_set( properties, "westley", "was here" ); + // Optimise for overlapping producers + mlt_producer_optimise( MLT_PRODUCER( service ) ); + + // Handle deep copies + if ( getenv( "MLT_WESTLEY_DEEP" ) == NULL ) + { + // Now assign additional properties + if ( info == 0 ) + mlt_properties_set( properties, "resource", data ); + + // This tells consumer_westley not to deep copy + mlt_properties_set( properties, "westley", "was here" ); + } + else + { + // Allow the project to be edited + mlt_properties_set( properties, "_westley", "was here" ); + mlt_properties_set_int( properties, "_mlt_service_hidden", 1 ); + } } else {