+
+// Prepend the property value with the document root
+static inline void qualify_property( deserialise_context context, mlt_properties properties, char *name )
+{
+ char *resource = mlt_properties_get( properties, name );
+ if ( resource != NULL )
+ {
+ // Qualify file name properties
+ char *root = mlt_properties_get( context->producer_map, "_root" );
+ if ( root != NULL )
+ {
+ 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 );
+ }
+ mlt_properties_set( properties, name, full_resource );
+ free( full_resource );
+ }
+ }
+}
+
+
+/** This function adds a producer to a playlist or multitrack when
+ there is no entry or track element.
+*/
+
+static int add_producer( deserialise_context context, mlt_service service, mlt_position in, mlt_position out )
+{
+ // Return value (0 = service remains top of stack, 1 means it can be removed)
+ int result = 0;
+
+ // Get the parent producer
+ enum service_type type;
+ mlt_service container = context_pop_service( context, &type );
+ int contained = 0;
+
+ if ( service != NULL && container != NULL )
+ {
+ char *container_branch = mlt_properties_get( mlt_service_properties( container ), "_westley_branch" );
+ char *service_branch = mlt_properties_get( mlt_service_properties( service ), "_westley_branch" );
+ contained = !strncmp( container_branch, service_branch, strlen( container_branch ) );
+ }
+
+ if ( contained )
+ {
+ mlt_properties properties = mlt_service_properties( service );
+ char *hide_s = mlt_properties_get( properties, "hide" );
+
+ // Indicate that this service is no longer top of stack
+ result = 1;
+
+ switch( type )
+ {
+ case mlt_tractor_type:
+ {
+ mlt_multitrack multitrack = mlt_tractor_multitrack( MLT_TRACTOR( container ) );
+ mlt_multitrack_connect( multitrack, MLT_PRODUCER( service ), mlt_multitrack_count( multitrack ) );
+ }
+ break;
+ case mlt_multitrack_type:
+ {
+ mlt_multitrack_connect( MLT_MULTITRACK( container ),
+ MLT_PRODUCER( service ),
+ mlt_multitrack_count( MLT_MULTITRACK( container ) ) );
+ }
+ break;
+ case mlt_playlist_type:
+ {
+ mlt_playlist_append_io( MLT_PLAYLIST( container ), MLT_PRODUCER( service ), in, out );
+ }
+ break;
+ default:
+ result = 0;
+ fprintf( stderr, "Producer defined inside something that isn't a container\n" );
+ break;
+ };
+
+ // Set the hide state of the track producer
+ if ( hide_s != NULL )
+ {
+ if ( strcmp( hide_s, "video" ) == 0 )
+ mlt_properties_set_int( properties, "hide", 1 );
+ else if ( strcmp( hide_s, "audio" ) == 0 )
+ mlt_properties_set_int( properties, "hide", 2 );
+ else if ( strcmp( hide_s, "both" ) == 0 )
+ mlt_properties_set_int( properties, "hide", 3 );
+ }
+ }
+
+ // Put the parent producer back
+ if ( container != NULL )
+ context_push_service( context, container, type );
+
+ return result;
+}
+
+/** Attach filters defined on that to this.
+*/
+
+static void attach_filters( mlt_service this, mlt_service that )
+{
+ if ( that != NULL )
+ {
+ int i = 0;
+ mlt_filter filter = NULL;
+ for ( i = 0; ( filter = mlt_service_filter( that, i ) ) != NULL; i ++ )
+ {
+ mlt_service_attach( this, filter );
+ attach_filters( mlt_filter_service( filter ), mlt_filter_service( filter ) );
+ }
+ }
+}
+