in point fix, low latency sdl, minor fixes
[melted] / src / modules / westley / producer_westley.c
index ad21f93..094558b 100644 (file)
@@ -18,7 +18,9 @@
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-// TODO: destroy unreferenced producers
+// TODO: destroy unreferenced producers (they are currently destroyed
+//       when the returned producer is closed).
+// TODO: try using XmlReader interface to avoid global context issues in sax.
  
 #include "producer_westley.h"
 #include <framework/mlt.h>
@@ -91,6 +93,9 @@ static void on_start_tractor( deserialise_context context, const xmlChar *name,
                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 );
+       
        context_push_service( context, service );
 }
 
@@ -121,6 +126,8 @@ static void on_start_playlist( deserialise_context context, const xmlChar *name,
        for ( ; atts != NULL && *atts != NULL; atts += 2 )
        {
                mlt_properties_set( properties, ( char* )atts[0], ( char* )atts[1] );
+
+               // Out will be overwritten later as we append, so we need to save it
                if ( strcmp( atts[ 0 ], "out" ) == 0 )
                        mlt_properties_set( properties, "_westley.out", ( char* )atts[ 1 ] );
        }
@@ -166,15 +173,23 @@ 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)
 {
-       // Look for the producer attribute
+       // Use a dummy service to hold properties to allow arbitratry nesting
+       mlt_service service = calloc( 1, sizeof( struct mlt_service_s ) );
+       mlt_service_init( service, NULL );
+
+       // Push the dummy service onto the stack
+       context_push_service( context, service );
+       
        for ( ; atts != NULL && *atts != NULL; atts += 2 )
        {
-               if ( strcmp( atts[0], "producer" ) == 0 )
+               mlt_properties_set( mlt_service_properties( service ), (char*) atts[0], (char*) atts[1] );
+               
+               // Look for the producer attribute
+               if ( strcmp( atts[ 0 ], "producer" ) == 0 )
                {
                        if ( mlt_properties_get_data( context->producer_map, (char*) atts[1], NULL ) !=  NULL )
                                // Push the referenced producer onto the stack
                                context_push_service( context, MLT_SERVICE( mlt_properties_get_data( context->producer_map, (char*) atts[1], NULL ) ) );
-                       break;
                }
        }
 }
@@ -270,6 +285,9 @@ static void on_end_track( deserialise_context context, const xmlChar *name )
        // Get the producer from the stack
        mlt_service producer = context_pop_service( context );
 
+       // Get the dummy track service from the stack
+       mlt_service track = context_pop_service( context );
+
        // Get the multitrack from the stack
        mlt_service service = context_pop_service( context );
 
@@ -278,8 +296,19 @@ static void on_end_track( deserialise_context context, const xmlChar *name )
                MLT_PRODUCER( producer ),
                mlt_multitrack_count( MLT_MULTITRACK( service ) ) );
 
+       // Set producer i/o if specified
+       if ( mlt_properties_get( mlt_service_properties( track ), "in" ) != NULL ||
+               mlt_properties_get( mlt_service_properties( track ), "out" ) != NULL )
+       {
+               mlt_producer_set_in_and_out( MLT_PRODUCER( producer ),
+                       mlt_properties_get_position( mlt_service_properties( track ), "in" ),
+                       mlt_properties_get_position( mlt_service_properties( track ), "out" ) );
+       }
+
        // Push the multitrack back onto the stack
        context_push_service( context, service );
+
+       mlt_service_close( track );
 }
 
 static void on_end_entry( deserialise_context context, const xmlChar *name )
@@ -287,17 +316,30 @@ static void on_end_entry( deserialise_context context, const xmlChar *name )
        // Get the producer from the stack
        mlt_service producer = context_pop_service( context );
 
+       // Get the dummy entry service from the stack
+       mlt_service entry = context_pop_service( context );
+
        // Get the playlist from the stack
        mlt_service service = context_pop_service( context );
 
        // Append the producer to the playlist
-       mlt_playlist_append_io( MLT_PLAYLIST( service ),
-               MLT_PRODUCER( producer ),
-               mlt_properties_get_position( mlt_service_properties( producer ), "in" ),
-               mlt_properties_get_position( mlt_service_properties( producer ), "out" ) );
+       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( service ),
+                       MLT_PRODUCER( 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( service ), MLT_PRODUCER( producer ) );
+       }
 
        // Push the playlist back onto the stack
        context_push_service( context, service );
+
+       mlt_service_close( entry );
 }
 
 static void on_end_tractor( deserialise_context context, const xmlChar *name )
@@ -334,13 +376,27 @@ static void on_end_producer( deserialise_context context, const xmlChar *name )
        if ( properties == NULL )
                return;
                
-       // Instatiate the producer
-       service = MLT_SERVICE( mlt_factory_producer( "fezzik", mlt_properties_get( properties, "resource" ) ) );
-       
-       if ( service == NULL && mlt_properties_get( properties, "mlt_service" ) != NULL )
+       // Instantiate the producer
+       if ( mlt_properties_get( properties, "mlt_service" ) != NULL )
        {
-               service = MLT_SERVICE( mlt_factory_producer( mlt_properties_get( properties, "mlt_service" ),
-                       mlt_properties_get( properties, "resource" ) ) );
+               service = MLT_SERVICE( mlt_factory_producer( "fezzik", mlt_properties_get( properties, "mlt_service" ) ) );
+       }
+       if ( service == NULL && mlt_properties_get( properties, "resource" ) != NULL )
+       {
+               char *root = mlt_properties_get( context->producer_map, "_root" );
+               char *resource = mlt_properties_get( properties, "resource" );
+               char *full_resource = malloc( strlen( root ) + strlen( resource ) + 1 );
+               if ( resource[ 0 ] != '/' )
+               {
+                       strcpy( full_resource, root );
+                       strcat( full_resource, resource );
+               }
+               else
+               {
+                       strcpy( full_resource, resource );
+               }
+               service = MLT_SERVICE( mlt_factory_producer( "fezzik", full_resource ) );
+               free( full_resource );
        }
 
        track_service( context->destructors, service, (mlt_destructor) mlt_producer_close );
@@ -399,7 +455,7 @@ static void on_end_filter( deserialise_context context, const xmlChar *name )
        properties = mlt_service_properties( service );
 
        // Set in and out
-//fprintf( stderr, "setting filter in %lld out %lld\n", mlt_properties_get_position( properties, "in" ), mlt_properties_get_position( properties, "out" ) );
+//fprintf( stderr, "setting filter in %d out %d\n", mlt_properties_get_position( properties, "in" ), mlt_properties_get_position( properties, "out" ) );
        mlt_filter_set_in_and_out( MLT_FILTER( service ), 
                mlt_properties_get_position( properties, "in" ),
                mlt_properties_get_position( properties, "out" ) );
@@ -418,7 +474,7 @@ static void on_end_filter( deserialise_context context, const xmlChar *name )
                context_push_service( context, tractor );
        }
 
-//fprintf( stderr, "setting filter in %lld out %lld\n", mlt_properties_get_position( properties, "in" ), mlt_properties_get_position( properties, "out" ) );
+//fprintf( stderr, "setting filter in %d out %d\n", mlt_properties_get_position( properties, "in" ), mlt_properties_get_position( properties, "out" ) );
        // If a producer alias is in the producer_map, get it
        snprintf( key, 10, "%p", producer );
        if ( mlt_properties_get_data( context->producer_map, key, NULL ) != NULL )
@@ -545,7 +601,6 @@ static void on_characters( void *ctx, const xmlChar *ch, int len )
 
 mlt_producer producer_westley_init( char *filename )
 {
-       static int init = 0;
        xmlSAXHandler *sax = calloc( 1, sizeof( xmlSAXHandler ) );
        struct deserialise_context_s *context = calloc( 1, sizeof( struct deserialise_context_s ) );
        mlt_properties properties = NULL;
@@ -553,17 +608,27 @@ mlt_producer producer_westley_init( char *filename )
 
        context->producer_map = mlt_properties_new();
        context->destructors = mlt_properties_new();
+
        // 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
+       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';
+       }
+
        sax->startElement = on_start_element;
        sax->endElement = on_end_element;
        sax->characters = on_characters;
+       sax->cdataBlock = on_characters;
 
-       if ( !init )
-       {
-               xmlInitParser();
-               //init = 1;
-       }
+       // I REALLY DON'T GET THIS - HOW THE HELL CAN YOU REFERENCE A WESTLEY IN A WESTLEY???
+       xmlInitParser();
 
        xmlSAXUserParseFile( sax, context, filename );
 
@@ -610,10 +675,9 @@ mlt_producer producer_westley_init( char *filename )
        mlt_properties_close( context->producer_map );
        //free( context );
        free( sax );
-       xmlCleanupParser();
+       //xmlCleanupParser();
        xmlMemoryDump( );
 
 
        return MLT_PRODUCER( service );
 }
-