int multi_consumer;
int consumer_count;
int seekable;
+ mlt_consumer qglsl;
};
typedef struct deserialise_context_s *deserialise_context;
{
mlt_service result = NULL;
- if ( type ) *type = invalid_type;
+ if ( type ) *type = mlt_invalid_type;
if ( context->stack_service_size > 0 )
{
result = context->stack_service[ -- context->stack_service_size ];
mlt_service producer = NULL;
qualify_property( context, properties, "resource" );
- char *resource = trim( mlt_properties_get( properties, "resource" ) );
+ char *resource = mlt_properties_get( properties, "resource" );
// Let Kino-SMIL src be a synonym for resource
if ( resource == NULL )
{
qualify_property( context, properties, "src" );
- resource = trim( mlt_properties_get( properties, "src" ) );
+ resource = mlt_properties_get( properties, "src" );
}
// Instantiate the producer
if ( !producer )
{
mlt_service_close( service );
+ free( service );
return;
}
// Track this producer
track_service( context->destructors, producer, (mlt_destructor) mlt_producer_close );
mlt_properties_set_lcnumeric( MLT_SERVICE_PROPERTIES( producer ), context->lc_numeric );
- context->seekable &= mlt_properties_get_int( MLT_SERVICE_PROPERTIES( producer ), "seekable" );
+ if ( mlt_properties_get( MLT_SERVICE_PROPERTIES( producer ), "seekable" ) )
+ context->seekable &= mlt_properties_get_int( MLT_SERVICE_PROPERTIES( producer ), "seekable" );
// Propagate the properties
qualify_property( context, properties, "resource" );
// Get the parent properties
properties = MLT_SERVICE_PROPERTIES( parent );
- char *resource = trim( mlt_properties_get( properties, "resource" ) );
+ char *resource = mlt_properties_get( properties, "resource" );
// Put the parent producer back
context_push_service( context, parent, type );
// Push the producer onto the stack
context_push_service( context, producer, mlt_producer_type );
}
+ }
+ if ( service )
+ {
mlt_service_close( service );
+ free( service );
}
}
if ( mlt_properties_get_data( temp, "producer", NULL ) != NULL )
{
mlt_playlist_clip_info info;
- enum service_type parent_type = invalid_type;
+ enum service_type parent_type = mlt_invalid_type;
mlt_service parent = context_pop_service( context, &parent_type );
mlt_producer producer = mlt_properties_get_data( temp, "producer", NULL );
static void on_end_entry( deserialise_context context, const xmlChar *name )
{
// Get the entry from the stack
- enum service_type entry_type = invalid_type;
+ enum service_type entry_type = mlt_invalid_type;
mlt_service entry = context_pop_service( context, &entry_type );
if ( entry == NULL && entry_type != mlt_entry_type )
if ( track != NULL && track_type == mlt_entry_type )
{
mlt_properties track_props = MLT_SERVICE_PROPERTIES( track );
- enum service_type parent_type = invalid_type;
+ enum service_type parent_type = mlt_invalid_type;
mlt_service parent = context_pop_service( context, &parent_type );
mlt_multitrack multitrack = NULL;
if ( parent != NULL )
context_push_service( context, parent, parent_type );
-
- mlt_service_close( track );
}
else
{
mlt_log_error( NULL, "[producer_xml] Invalid state at end of track\n" );
}
+
+ if ( track )
+ {
+ mlt_service_close( track );
+ free( track );
+ }
}
static void on_start_filter( deserialise_context context, const xmlChar *name, const xmlChar **atts)
mlt_service service = context_pop_service( context, &type );
mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
- enum service_type parent_type = invalid_type;
+ enum service_type parent_type = mlt_invalid_type;
mlt_service parent = context_pop_service( context, &parent_type );
if ( service != NULL && type == mlt_dummy_filter_type )
if ( parent )
context_push_service( context, parent, parent_type );
mlt_service_close( service );
+ free( service );
return;
}
{
mlt_log_error( NULL, "[producer_xml] filter closed with invalid parent...\n" );
}
-
- // Close the dummy filter service
- mlt_service_close( service );
}
else
{
mlt_log_error( NULL, "[producer_xml] Invalid top of stack on filter close\n" );
}
+
+ if ( service )
+ {
+ mlt_service_close( service );
+ free(service);
+ }
}
static void on_start_transition( deserialise_context context, const xmlChar *name, const xmlChar **atts)
mlt_service service = context_pop_service( context, &type );
mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
- enum service_type parent_type = invalid_type;
+ enum service_type parent_type = mlt_invalid_type;
mlt_service parent = context_pop_service( context, &parent_type );
if ( service != NULL && type == mlt_dummy_transition_type )
if ( parent )
context_push_service( context, parent, parent_type );
mlt_service_close( service );
+ free( service );
return;
}
track_service( context->destructors, effect, (mlt_destructor) mlt_transition_close );
mlt_log_error( NULL, "[producer_xml] transition closed with invalid parent...\n" );
}
- // Close the dummy filter service
- mlt_service_close( service );
}
else
{
mlt_log_error( NULL, "[producer_xml] Invalid top of stack on transition close\n" );
}
+
+ if ( service )
+ {
+ mlt_service_close( service );
+ free( service );
+ }
}
static void on_start_consumer( deserialise_context context, const xmlChar *name, const xmlChar **atts)
{
if ( context->pass == 1 )
{
- mlt_consumer consumer = mlt_consumer_new( context->profile );
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
+ mlt_properties properties = mlt_properties_new();
mlt_properties_set_lcnumeric( properties, context->lc_numeric );
- context_push_service( context, MLT_CONSUMER_SERVICE(consumer), mlt_dummy_consumer_type );
+ context_push_service( context, (mlt_service) properties, mlt_dummy_consumer_type );
// Set the properties from attributes
for ( ; atts != NULL && *atts != NULL; atts += 2 )
{
// Get the consumer from the stack
enum service_type type;
- mlt_service service = context_pop_service( context, &type );
+ mlt_properties properties = (mlt_properties) context_pop_service( context, &type );
- if ( service && type == mlt_dummy_consumer_type )
+ if ( properties && type == mlt_dummy_consumer_type )
{
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
qualify_property( context, properties, "resource" );
qualify_property( context, properties, "target" );
- char *resource = trim( mlt_properties_get( properties, "resource" ) );
+ char *resource = mlt_properties_get( properties, "resource" );
- if ( context->multi_consumer > 1 )
+ if ( context->multi_consumer > 1 || context->qglsl )
{
// Instantiate the multi consumer
if ( !context->consumer )
{
- context->consumer = mlt_factory_consumer( context->profile, "multi", NULL );
+ if ( context->qglsl )
+ context->consumer = context->qglsl;
+ else
+ context->consumer = mlt_factory_consumer( context->profile, "multi", NULL );
if ( context->consumer )
{
// Track this consumer
}
if ( context->consumer )
{
- // Set this service instance on multi consumer
+ // Set this properties object on multi consumer
char key[20];
snprintf( key, sizeof(key), "%d", context->consumer_count++ );
- mlt_properties_set_data( MLT_CONSUMER_PROPERTIES(context->consumer), key, service, 0,
- (mlt_destructor) mlt_service_close, NULL );
+ mlt_properties_inc_ref( properties );
+ mlt_properties_set_data( MLT_CONSUMER_PROPERTIES(context->consumer), key, properties, 0,
+ (mlt_destructor) mlt_properties_close, NULL );
}
}
else
// Inherit the properties
mlt_properties_inherit( MLT_CONSUMER_PROPERTIES(context->consumer), properties );
}
- // Close the dummy
- mlt_service_close( service );
}
}
+ // Close the dummy
+ if ( properties )
+ mlt_properties_close( properties );
}
}
on_start_profile( context, name, atts );
if ( xmlStrcmp( name, _x("consumer") ) == 0 )
context->multi_consumer++;
+
+ // Check for a service beginning with glsl. or movit.
+ for ( ; atts != NULL && *atts != NULL; atts += 2 ) {
+ if ( !xmlStrncmp( atts[1], _x("glsl."), 5 ) || !xmlStrncmp( atts[1], _x("movit."), 6 ) ) {
+ mlt_properties_set_int( context->params, "qglsl", 1 );
+ break;
+ }
+ }
return;
}
context->branch[ context->depth ] ++;
mlt_properties_set( properties, context->property, value );
}
context->entity_is_replace = 0;
-
+
+ // Check for a service beginning with glsl. or movit.
+ if ( !strncmp( value, "glsl.", 5 ) || !strncmp( value, "movit.", 6 ) )
+ mlt_properties_set_int( context->params, "qglsl", 1 );
+
free( value);
}
return exists;
}
+// This function will add remaing services in the context service stack marked
+// with a "xml_retain" property to a property named "xml_retain" on the returned
+// service. The property is a mlt_properties data property.
+
+static void retain_services( struct deserialise_context_s *context, mlt_service service )
+{
+ mlt_properties retain_list = mlt_properties_new();
+ enum service_type type;
+ mlt_service retain_service = context_pop_service( context, &type );
+
+ while ( retain_service )
+ {
+ mlt_properties retain_properties = MLT_SERVICE_PROPERTIES( retain_service );
+
+ if ( mlt_properties_get_int( retain_properties, "xml_retain" ) )
+ {
+ // Remove the retained service from the destructors list.
+ int i;
+ for ( i = mlt_properties_count( context->destructors ) - 1; i >= 1; i -- )
+ {
+ const char *name = mlt_properties_get_name( context->destructors, i );
+ if ( mlt_properties_get_data_at( context->destructors, i, NULL ) == retain_service )
+ {
+ mlt_properties_set_data( context->destructors, name, retain_service, 0, NULL, NULL );
+ break;
+ }
+ }
+ const char *name = mlt_properties_get( retain_properties, "id" );
+ if ( name )
+ mlt_properties_set_data( retain_list, name, retain_service, 0,
+ (mlt_destructor) mlt_service_close, NULL );
+ }
+ retain_service = context_pop_service( context, &type );
+ }
+ if ( mlt_properties_count( retain_list ) > 0 )
+ {
+ mlt_properties_set_data( MLT_SERVICE_PROPERTIES(service), "xml_retain", retain_list, 0,
+ (mlt_destructor) mlt_properties_close, NULL );
+ }
+}
+
mlt_producer producer_xml_init( mlt_profile profile, mlt_service_type servtype, const char *id, char *data )
{
xmlSAXHandler *sax, *sax_orig;
// Setup SAX callbacks for first pass
sax = calloc( 1, sizeof( xmlSAXHandler ) );
sax->startElement = on_start_element;
+ sax->characters = on_characters;
sax->warning = on_error;
sax->error = on_error;
sax->fatalError = on_error;
return NULL;
}
+ // Create the qglsl consumer now, if requested, so that glsl.manager
+ // may exist when trying to load glsl. or movit. services.
+ // The "if requested" part can come from query string qglsl=1 or when
+ // a service beginning with glsl. or movit. appears in the XML.
+ if ( mlt_properties_get_int( context->params, "qglsl" ) && strcmp( id, "xml-nogl" ) )
+ context->qglsl = mlt_factory_consumer( profile, "qglsl", NULL );
+
// Setup SAX callbacks for second pass
sax->endElement = on_end_element;
- sax->characters = on_characters;
sax->cdataBlock = on_characters;
sax->internalSubset = on_internal_subset;
sax->entityDecl = on_entity_declaration;
(mlt_destructor) mlt_consumer_close, NULL );
mlt_properties_set_int( properties, "seekable", context->seekable );
+
+ retain_services( context, service );
}
else
{
}
// Clean up
+ if ( context->qglsl && context->consumer != context->qglsl )
+ mlt_consumer_close( context->qglsl );
mlt_properties_close( context->producer_map );
if ( context->params != NULL )
mlt_properties_close( context->params );