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,
this->stack_types[ this->stack_service_size++ ] = type;
// Record the tree branch on which this service lives
- if ( that != NULL && mlt_properties_get( mlt_service_properties( that ), "_westley_branch" ) == NULL )
+ if ( that != NULL && mlt_properties_get( MLT_SERVICE_PROPERTIES( that ), "_westley_branch" ) == NULL )
{
char s[ BRANCH_SIG_LEN ];
- mlt_properties_set( mlt_service_properties( that ), "_westley_branch", serialise_branch( this, s ) );
+ mlt_properties_set( MLT_SERVICE_PROPERTIES( that ), "_westley_branch", serialise_branch( this, s ) );
}
}
return ret;
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" );
+ 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 );
+ 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
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 ) );
+ attach_filters( MLT_FILTER_SERVICE( filter ), MLT_FILTER_SERVICE( filter ) );
}
}
}
static void on_start_tractor( deserialise_context context, const xmlChar *name, const xmlChar **atts)
{
- mlt_service service = mlt_tractor_service( mlt_tractor_new( ) );
- mlt_properties properties = mlt_service_properties( service );
+ mlt_tractor tractor = mlt_tractor_new( );
+ mlt_service service = MLT_TRACTOR_SERVICE( tractor );
+ mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
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] );
+ mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), (char*) atts[0], atts[1] == NULL ? "" : (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 );
- }
+ mlt_properties_set_int( MLT_TRACTOR_PROPERTIES( tractor ), "global_feed", 1 );
if ( mlt_properties_get( properties, "id" ) != NULL )
mlt_properties_set_data( context->producer_map, mlt_properties_get( properties, "id" ), service, 0, NULL, NULL );
if ( add_producer( context, tractor, 0, mlt_producer_get_out( MLT_PRODUCER( tractor ) ) ) == 0 )
context_push_service( context, tractor, type );
}
+ else
+ {
+ fprintf( stderr, "Invalid state for tractor\n" );
+ }
}
static void on_start_multitrack( deserialise_context context, const xmlChar *name, const xmlChar **atts)
// If we don't have a parent, then create one now, providing we're in a state where we can
if ( parent == NULL || ( type == mlt_playlist_type || type == mlt_multitrack_type ) )
{
+ mlt_tractor tractor = NULL;
// Push the parent back
if ( parent != NULL )
context_push_service( context, parent, type );
// Create a tractor to contain the multitrack
- parent = mlt_tractor_service( mlt_tractor_new( ) );
+ tractor = mlt_tractor_new( );
+ parent = MLT_TRACTOR_SERVICE( tractor );
track_service( context->destructors, parent, (mlt_destructor) mlt_tractor_close );
type = mlt_tractor_type;
// Flag it as a synthesised tractor for clean up later
- mlt_properties_set_int( mlt_service_properties( parent ), "fezzik_synth", 1 );
+ mlt_properties_set_int( MLT_SERVICE_PROPERTIES( parent ), "fezzik_synth", 1 );
}
if ( type == mlt_tractor_type )
{
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 );
+ mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
for ( ; atts != NULL && *atts != NULL; atts += 2 )
- mlt_properties_set( properties, (char*) atts[0], (char*) atts[1] );
+ mlt_properties_set( properties, (char*) atts[0], atts[1] == NULL ? "" : (char*) atts[1] );
if ( mlt_properties_get( properties, "id" ) != NULL )
mlt_properties_set_data( context->producer_map, mlt_properties_get( properties,"id" ), service, 0, NULL, NULL );
static void on_start_playlist( deserialise_context context, const xmlChar *name, const xmlChar **atts)
{
- mlt_service service = mlt_playlist_service( mlt_playlist_init() );
- mlt_properties properties = mlt_service_properties( service );
+ mlt_playlist playlist = mlt_playlist_init( );
+ mlt_service service = MLT_PLAYLIST_SERVICE( playlist );
+ mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
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_set( properties, (char*) atts[0], atts[1] == NULL ? "" : (char*) atts[1] );
// Out will be overwritten later as we append, so we need to save it
if ( strcmp( atts[ 0 ], "out" ) == 0 )
if ( service != NULL && type == mlt_playlist_type )
{
- mlt_properties properties = mlt_service_properties( service );
+ 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 );
mlt_service service = calloc( 1, sizeof( struct mlt_service_s ) );
mlt_service_init( service, NULL );
- mlt_properties properties = mlt_service_properties( service );
+ mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
context_push_service( context, service, mlt_dummy_producer_type );
for ( ; atts != NULL && *atts != NULL; atts += 2 )
- mlt_properties_set( properties, (char*) atts[0], (char*) atts[1] );
+ mlt_properties_set( properties, (char*) atts[0], atts[1] == NULL ? "" : (char*) atts[1] );
}
static void on_end_producer( deserialise_context context, const xmlChar *name )
{
enum service_type type;
mlt_service service = context_pop_service( context, &type );
- mlt_properties properties = mlt_service_properties( service );
+ mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
if ( service != NULL && type == mlt_dummy_producer_type )
{
if ( producer == NULL && resource != NULL )
producer = MLT_SERVICE( mlt_factory_producer( "fezzik", resource ) );
+ if ( producer == NULL )
+ producer = MLT_SERVICE( mlt_factory_producer( "fezzik", "+INVALID.txt" ) );
+
+ if ( producer == NULL )
+ producer = MLT_SERVICE( mlt_factory_producer( "fezzik", "colour:red" ) );
+
// Track this producer
track_service( context->destructors, producer, (mlt_destructor) mlt_producer_close );
mlt_properties_set( properties, "out", NULL );
// Inherit the properties
- mlt_properties_inherit( mlt_service_properties( producer ), properties );
+ mlt_properties_inherit( MLT_SERVICE_PROPERTIES( producer ), properties );
// Attach all filters from service onto producer
attach_filters( producer, service );
if ( parent != NULL )
{
// Get the parent properties
- properties = mlt_service_properties( parent );
+ properties = MLT_SERVICE_PROPERTIES( parent );
char *resource = mlt_properties_get( properties, "resource" );
else
{
// Otherwise, set in and out on producer directly
- mlt_producer_set_in_and_out( MLT_PRODUCER( service ), in, out );
+ mlt_producer_set_in_and_out( MLT_PRODUCER( producer ), in, out );
}
}
else
mlt_producer_set_in_and_out( MLT_PRODUCER( producer ), in, out );
}
}
-
+
// Push the producer onto the stack
context_push_service( context, producer, mlt_producer_type );
}
for ( ; atts != NULL && *atts != NULL; atts += 2 )
{
- mlt_properties_set( temp, (char*) atts[0], (char*) atts[1] );
+ mlt_properties_set( temp, (char*) atts[0], atts[1] == NULL ? "" : (char*) atts[1] );
// Look for the producer attribute
if ( strcmp( atts[ 0 ], "producer" ) == 0 )
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.producer;
+ entry = info.cut;
}
else
{
}
// Push the cut onto the stack
- context_push_service( context, mlt_producer_service( entry ), mlt_entry_type );
+ context_push_service( context, MLT_PRODUCER_SERVICE( entry ), mlt_entry_type );
mlt_properties_close( temp );
}
// Push the dummy service onto the stack
context_push_service( context, service, mlt_entry_type );
- mlt_properties_set( mlt_service_properties( service ), "resource", "<track>" );
+ mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "resource", "<track>" );
for ( ; atts != NULL && *atts != NULL; atts += 2 )
{
- mlt_properties_set( mlt_service_properties( service ), (char*) atts[0], (char*) atts[1] );
+ mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), (char*) atts[0], atts[1] == NULL ? "" : (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( mlt_service_properties( service ), "producer", producer, 0, NULL, NULL );
+ mlt_properties_set_data( MLT_SERVICE_PROPERTIES( service ), "producer", producer, 0, NULL, NULL );
}
}
}
if ( track != NULL && track_type == mlt_entry_type )
{
- mlt_properties track_props = mlt_service_properties( track );
+ mlt_properties track_props = MLT_SERVICE_PROPERTIES( track );
enum service_type parent_type;
mlt_service parent = context_pop_service( context, &parent_type );
mlt_multitrack multitrack = NULL;
mlt_producer producer = mlt_properties_get_data( track_props, "producer", NULL );
- mlt_properties producer_props = mlt_producer_properties( producer );
+ mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
if ( parent_type == mlt_tractor_type )
multitrack = mlt_tractor_multitrack( MLT_TRACTOR( parent ) );
if ( multitrack != NULL )
{
- // Set the track on the 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 cut = mlt_producer_cut( MLT_PRODUCER( producer ),
mlt_properties_get_position( track_props, "in" ),
mlt_properties_get_position( track_props, "out" ) );
mlt_multitrack_connect( multitrack, cut, mlt_multitrack_count( multitrack ) );
+ mlt_properties_inherit( MLT_PRODUCER_PROPERTIES( cut ), track_props );
+ track_props = MLT_PRODUCER_PROPERTIES( cut );
mlt_producer_close( cut );
}
else
mlt_service service = calloc( 1, sizeof( struct mlt_service_s ) );
mlt_service_init( service, NULL );
- mlt_properties properties = mlt_service_properties( service );
+ mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
context_push_service( context, service, mlt_dummy_filter_type );
{
enum service_type type;
mlt_service service = context_pop_service( context, &type );
- mlt_properties properties = mlt_service_properties( service );
+ mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
enum service_type parent_type;
mlt_service parent = context_pop_service( context, &parent_type );
if ( service != NULL && type == mlt_dummy_filter_type )
{
mlt_service filter = MLT_SERVICE( mlt_factory_filter( mlt_properties_get( properties, "mlt_service" ), NULL ) );
- mlt_properties filter_props = mlt_service_properties( filter );
+ mlt_properties filter_props = MLT_SERVICE_PROPERTIES( filter );
track_service( context->destructors, filter, (mlt_destructor) mlt_filter_close );
mlt_service service = calloc( 1, sizeof( struct mlt_service_s ) );
mlt_service_init( service, NULL );
- mlt_properties properties = mlt_service_properties( service );
+ mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
context_push_service( context, service, mlt_dummy_transition_type );
{
enum service_type type;
mlt_service service = context_pop_service( context, &type );
- mlt_properties properties = mlt_service_properties( service );
+ mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
enum service_type parent_type;
mlt_service parent = context_pop_service( context, &parent_type );
if ( service != NULL && type == mlt_dummy_transition_type )
{
mlt_service effect = MLT_SERVICE( mlt_factory_transition(mlt_properties_get(properties,"mlt_service"), NULL ) );
- mlt_properties effect_props = mlt_service_properties( effect );
+ mlt_properties effect_props = MLT_SERVICE_PROPERTIES( effect );
track_service( context->destructors, effect, (mlt_destructor) mlt_transition_close );
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" ) );
{
enum service_type type;
mlt_service service = context_pop_service( context, &type );
- mlt_properties properties = mlt_service_properties( service );
+ mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
char *value = NULL;
if ( service != NULL )
value = (char*) atts[ 1 ];
}
- if ( context->property != NULL && value != NULL )
- mlt_properties_set( properties, context->property, value );
-
+ if ( context->property != NULL )
+ mlt_properties_set( properties, context->property, value == NULL ? "" : value );
+
// Tell parser to collect any further nodes for serialisation
context->is_value = 1;
{
enum service_type type;
mlt_service service = context_pop_service( context, &type );
- mlt_properties properties = mlt_service_properties( service );
+ mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
if ( service != NULL )
{
xmlFreeDoc( context->value_doc );
context->value_doc = NULL;
}
-
+
// Close this property handling
free( context->property );
context->property = NULL;
char *value = calloc( len + 1, 1 );
enum service_type type;
mlt_service service = context_pop_service( context, &type );
- mlt_properties properties = mlt_service_properties( service );
+ mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
if ( service != NULL )
context_push_service( context, service, type );
params_to_entities( context );
}
+// TODO: Check this with Dan... I think this is for westley parameterisation
+// but it's breaking standard escaped entities (like < etc).
static void on_entity_declaration( void *ctx, const xmlChar* name, int type,
const xmlChar* publicId, const xmlChar* systemId, xmlChar* content)
{
xmlAddDocEntity( context->entity_doc, name, type, publicId, systemId, content );
}
-xmlEntityPtr on_get_entity( void *ctx, const xmlChar* name )
+// TODO: Check this functionality (see on_entity_declaration)
+static xmlEntityPtr on_get_entity( void *ctx, const xmlChar* name )
{
struct _xmlParserCtxt *xmlcontext = ( struct _xmlParserCtxt* )ctx;
deserialise_context context = ( deserialise_context )( xmlcontext->_private );
// Add our parameters if not already
params_to_entities( context );
- e = xmlGetDocEntity( context->entity_doc, name );
+ e = xmlGetPredefinedEntity( name );
// Send signal to on_characters that an entity substitutin is pending
- if ( e != NULL )
- context->entity_is_replace = 1;
+ if ( e == NULL )
+ {
+ e = xmlGetDocEntity( context->entity_doc, name );
+ if ( e != NULL )
+ context->entity_is_replace = 1;
+ }
return e;
}
mlt_properties_set( properties, name, value );
}
+// Quick workaround to avoid unecessary libxml2 warnings
+static int file_exists( char *file )
+{
+ char *name = strdup( file );
+ int exists = 0;
+ if ( name != NULL && strchr( name, '?' ) )
+ *( strchr( name, '?' ) ) = '\0';
+ if ( name != NULL )
+ {
+ FILE *f = fopen( name, "r" );
+ exists = f != NULL;
+ if ( exists ) fclose( f );
+ }
+ free( name );
+ return exists;
+}
+
mlt_producer producer_westley_init( int info, char *data )
{
- if ( data == NULL )
- return NULL;
xmlSAXHandler *sax = calloc( 1, sizeof( xmlSAXHandler ) );
struct deserialise_context_s *context = calloc( 1, sizeof( struct deserialise_context_s ) );
mlt_properties properties = NULL;
struct _xmlParserCtxt *xmlcontext;
int well_formed = 0;
char *filename = NULL;
-
+
+ if ( data == NULL || !strcmp( data, "" ) || ( info == 0 && !file_exists( data ) ) )
+ return NULL;
+
+ context = calloc( 1, sizeof( struct deserialise_context_s ) );
+ if ( context == NULL )
+ return NULL;
+
context->producer_map = mlt_properties_new();
context->destructors = mlt_properties_new();
context->params = mlt_properties_new();
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;
{
// Verify it is a producer service (mlt_type="mlt_producer")
// (producer, playlist, multitrack)
- char *type = mlt_properties_get( mlt_service_properties( service ), "mlt_type" );
+ char *type = mlt_properties_get( MLT_SERVICE_PROPERTIES( service ), "mlt_type" );
if ( type == NULL || ( strcmp( type, "mlt_producer" ) != 0 && strcmp( type, "producer" ) != 0 ) )
service = NULL;
}
// We are done referencing destructor property list
// Set this var to service properties for convenience
- properties = mlt_service_properties( service );
+ 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 );
+ // Optimise for overlapping producers
+ mlt_producer_optimise( MLT_PRODUCER( service ) );
+
// Handle deep copies
if ( getenv( "MLT_WESTLEY_DEEP" ) == NULL )
{
else
{
// Allow the project to be edited
+ mlt_properties_set( properties, "_westley", "was here" );
mlt_properties_set_int( properties, "_mlt_service_hidden", 1 );
}
}
{
// 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 );