mlt_consumer consumer;
int multi_consumer;
int consumer_count;
+ int seekable;
};
typedef struct deserialise_context_s *deserialise_context;
{
mlt_service result = NULL;
- *type = invalid_type;
+ if ( type ) *type = invalid_type;
if ( context->stack_service_size > 0 )
{
result = context->stack_service[ -- context->stack_service_size ];
if ( type != NULL )
*type = context->stack_types[ context->stack_service_size ];
// Set the service's profile and locale so mlt_property time-to-position conversions can get fps
- mlt_properties_set_data( MLT_SERVICE_PROPERTIES( result ), "_profile", context->profile, 0, NULL, NULL );
- mlt_properties_set_lcnumeric( MLT_SERVICE_PROPERTIES( result ), context->lc_numeric );
+ if ( result )
+ {
+ mlt_properties_set_data( MLT_SERVICE_PROPERTIES( result ), "_profile", context->profile, 0, NULL, NULL );
+ mlt_properties_set_lcnumeric( MLT_SERVICE_PROPERTIES( result ), context->lc_numeric );
+ }
}
return result;
}
static void on_start_playlist( deserialise_context context, const xmlChar *name, const xmlChar **atts)
{
- mlt_playlist playlist = mlt_playlist_init( );
+ mlt_playlist playlist = mlt_playlist_new( context->profile );
mlt_service service = MLT_PLAYLIST_SERVICE( playlist );
mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
// 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" );
// Propagate the properties
qualify_property( context, properties, "resource" );
// Get the playlist from the stack
enum service_type type;
mlt_service service = context_pop_service( context, &type );
- mlt_position length = 0;
if ( type == mlt_playlist_type && service != NULL )
{
{
if ( xmlStrcmp( atts[0], _x("length") ) == 0 )
{
- length = atoll( _s(atts[1]) );
+ // Append a blank to the playlist
+ mlt_playlist_blank_time( MLT_PLAYLIST( service ), _s(atts[1]) );
break;
}
}
- // Append a blank to the playlist
- mlt_playlist_blank( MLT_PLAYLIST( service ), length - 1 );
-
// Push the playlist back onto the stack
context_push_service( context, service, type );
}
{
struct _xmlParserCtxt *xmlcontext = ( struct _xmlParserCtxt* )ctx;
deserialise_context context = ( deserialise_context )( xmlcontext->_private );
- char *value = calloc( len + 1, 1 );
+ char *value = calloc( 1, len + 1 );
enum service_type type;
mlt_service service = context_pop_service( context, &type );
mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
if ( s != NULL )
{
// Append new text to existing content
- char *new = calloc( strlen( s ) + len + 1, 1 );
+ char *new = calloc( 1, strlen( s ) + len + 1 );
strcat( new, s );
strcat( new, value );
mlt_properties_set( properties, context->property, new );
case ':':
case '=':
- url[ i++ ] = '\0';
- value = &url[ i ];
+#ifdef WIN32
+ if ( url[i] == ':' && url[i + 1] != '/' )
+ {
+#endif
+ url[ i++ ] = '\0';
+ value = &url[ i ];
+#ifdef WIN32
+ }
+#endif
break;
case '&':
mlt_producer producer_xml_init( mlt_profile profile, mlt_service_type servtype, const char *id, char *data )
{
- xmlSAXHandler *sax = calloc( 1, sizeof( xmlSAXHandler ) );
- struct deserialise_context_s *context = calloc( 1, sizeof( struct deserialise_context_s ) );
+ xmlSAXHandler *sax, *sax_orig;
+ struct deserialise_context_s *context;
mlt_properties properties = NULL;
int i = 0;
struct _xmlParserCtxt *xmlcontext;
int well_formed = 0;
char *filename = NULL;
- int info = strcmp( id, "xml-string" ) ? 0 : 1;
+ int is_filename = strcmp( id, "xml-string" );
- if ( data == NULL || !strcmp( data, "" ) || ( info == 0 && !file_exists( data ) ) )
+ // Strip file:// prefix
+ if ( data && strlen( data ) >= 7 && strncmp( data, "file://", 7 ) == 0 )
+ data += 7;
+
+ if ( data == NULL || !strcmp( data, "" ) || ( is_filename && !file_exists( data ) ) )
return NULL;
context = calloc( 1, sizeof( struct deserialise_context_s ) );
context->destructors = mlt_properties_new();
context->params = mlt_properties_new();
context->profile = profile;
+ context->seekable = 1;
// Decode URL and parse parameters
mlt_properties_set( context->producer_map, "root", "" );
- if ( info == 0 )
+ if ( is_filename )
{
filename = strdup( data );
parse_url( context->params, url_decode( filename, data ) );
mlt_properties_set_int( context->destructors, "registered", 0 );
// Setup SAX callbacks for first pass
+ sax = calloc( 1, sizeof( xmlSAXHandler ) );
sax->startElement = on_start_element;
sax->warning = on_error;
sax->error = on_error;
xmlSubstituteEntitiesDefault( 1 );
// This is used to facilitate entity substitution in the SAX parser
context->entity_doc = xmlNewDoc( _x("1.0") );
- if ( info == 0 )
+ if ( is_filename )
xmlcontext = xmlCreateFileParserCtxt( filename );
else
xmlcontext = xmlCreateMemoryParserCtxt( data, strlen( data ) );
}
// Parse
+ sax_orig = xmlcontext->sax;
xmlcontext->sax = sax;
xmlcontext->_private = ( void* )context;
xmlParseDocument( xmlcontext );
well_formed = xmlcontext->wellFormed;
// Cleanup after parsing
- xmlcontext->sax = NULL;
+ xmlcontext->sax = sax_orig;
xmlcontext->_private = NULL;
+ if ( xmlcontext->myDoc )
+ xmlFreeDoc( xmlcontext->myDoc );
xmlFreeParserCtxt( xmlcontext );
context->stack_node_size = 0;
context->stack_service_size = 0;
// Setup the second pass
context->pass ++;
- if ( info == 0 )
+ if ( is_filename )
xmlcontext = xmlCreateFileParserCtxt( filename );
else
xmlcontext = xmlCreateMemoryParserCtxt( data, strlen( data ) );
sax->getEntity = on_get_entity;
// Parse
+ sax_orig = xmlcontext->sax;
xmlcontext->sax = sax;
xmlcontext->_private = ( void* )context;
xmlParseDocument( xmlcontext );
xmlFreeDoc( context->entity_doc );
free( sax );
xmlMemoryDump( ); // for debugging
+ xmlcontext->sax = sax_orig;
+ xmlcontext->_private = NULL;
+ if ( xmlcontext->myDoc )
+ xmlFreeDoc( xmlcontext->myDoc );
+ xmlFreeParserCtxt( xmlcontext );
// Get the last producer on the stack
enum service_type type;
if ( getenv( "MLT_XML_DEEP" ) == NULL )
{
// Now assign additional properties
- if ( info == 0 )
+ if ( is_filename && (
+ mlt_service_identify( service ) == tractor_type ||
+ mlt_service_identify( service ) == playlist_type ||
+ mlt_service_identify( service ) == multitrack_type ) )
+ {
+ mlt_properties_set_int( properties, "_original_type",
+ mlt_service_identify( service ) );
+ mlt_properties_set( properties, "_original_resource",
+ mlt_properties_get( properties, "resource" ) );
mlt_properties_set( properties, "resource", data );
+ }
// This tells consumer_xml not to deep copy
mlt_properties_set( properties, "xml", "was here" );
mlt_properties_inc_ref( MLT_CONSUMER_PROPERTIES( context->consumer ) );
mlt_properties_set_data( properties, "consumer", context->consumer, 0,
(mlt_destructor) mlt_consumer_close, NULL );
+
+ mlt_properties_set_int( properties, "seekable", context->seekable );
}
else
{