Cleanup license declarations and remove dv1394d references.
[melted] / src / modules / westley / producer_westley.c
index 276eecf..75fd541 100644 (file)
@@ -3,19 +3,19 @@
  * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
  * Author: Dan Dennedy <dan@dennedy.org>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful,
+ * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 // TODO: destroy unreferenced producers (they are currently destroyed
@@ -294,7 +294,9 @@ static void on_start_tractor( deserialise_context context, const xmlChar *name,
        track_service( context->destructors, service, (mlt_destructor) mlt_tractor_close );
 
        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] );
+
+       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 );
@@ -348,7 +350,7 @@ static void on_start_multitrack( deserialise_context context, const xmlChar *nam
                mlt_service service = MLT_SERVICE( mlt_tractor_multitrack( MLT_TRACTOR( parent ) ) );
                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 );
@@ -382,7 +384,7 @@ 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] );
+               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 )
@@ -428,7 +430,45 @@ static void on_start_producer( deserialise_context context, const xmlChar *name,
        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] );
+}
+
+// Parse a SMIL clock value (as produced by Kino 0.9.1) and return position in frames
+static mlt_position parse_clock_value( char *value, double fps )
+{
+       // This implementation expects a fully specified clock value - no optional
+       // parts (e.g. 1:05)
+       char *pos, *copy = strdup( value );
+       int hh, mm, ss, ms;
+       mlt_position result = -1;
+
+       value = copy;
+       pos = strchr( value, ':' );
+       if ( !pos )
+               return result;
+       *pos = '\0';
+       hh = atoi( value );
+       value = pos + 1;
+
+       pos = strchr( value, ':' );
+       if ( !pos )
+               return result;
+       *pos = '\0';
+       mm = atoi( value );
+       value = pos + 1;
+       
+       pos = strchr( value, '.' );
+       if ( !pos )
+               return result;
+       *pos = '\0';
+       ss = atoi( value );
+       value = pos + 1;
+       
+       ms = atoi( value );
+       free( copy );
+       result = ( fps * ( ( (hh * 3600) + (mm * 60) + ss ) * 1000  + ms ) / 1000 + 0.5 );
+       
+       return result;
 }
 
 static void on_end_producer( deserialise_context context, const xmlChar *name )
@@ -471,6 +511,9 @@ static void on_end_producer( deserialise_context context, const xmlChar *name )
                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 );
 
@@ -490,14 +533,29 @@ static void on_end_producer( deserialise_context context, const xmlChar *name )
                        in = mlt_properties_get_position( properties, "in" );
                // Let Kino-SMIL clipBegin be a synonym for in
                if ( mlt_properties_get( properties, "clipBegin" ) != NULL )
-                       in = mlt_properties_get_position( properties, "clipBegin" );
+               {
+                       if ( strchr( mlt_properties_get( properties, "clipBegin" ), ':' ) )
+                               // Parse clock value
+                               in = parse_clock_value( mlt_properties_get( properties, "clipBegin" ),
+                                       mlt_properties_get_double( mlt_producer_properties( MLT_PRODUCER( producer ) ), "fps" ) );
+                       else
+                               // Parse frames value
+                               in = mlt_properties_get_position( properties, "clipBegin" );
+               }
                // Get out
                if ( mlt_properties_get( properties, "out" ) != NULL )
                        out = mlt_properties_get_position( properties, "out" );
                // Let Kino-SMIL clipEnd be a synonym for out
                if ( mlt_properties_get( properties, "clipEnd" ) != NULL )
-                       out = mlt_properties_get_position( properties, "clipEnd" );
-       
+               {
+                       if ( strchr( mlt_properties_get( properties, "clipEnd" ), ':' ) )
+                               // Parse clock value
+                               out = parse_clock_value( mlt_properties_get( properties, "clipEnd" ),
+                                       mlt_properties_get_double( mlt_producer_properties( MLT_PRODUCER( producer ) ), "fps" ) );
+                       else
+                               // Parse frames value
+                               out = mlt_properties_get_position( properties, "clipEnd" );
+               }
                // Remove in and out
                mlt_properties_set( properties, "in", NULL );
                mlt_properties_set( properties, "out", NULL );
@@ -596,7 +654,7 @@ static void on_start_entry( deserialise_context context, const xmlChar *name, co
 
        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 )
@@ -679,7 +737,7 @@ static void on_start_track( deserialise_context context, const xmlChar *name, co
        
        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 )
@@ -929,9 +987,9 @@ static void on_start_property( deserialise_context context, const xmlChar *name,
                                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;
 
@@ -967,7 +1025,7 @@ static void on_end_property( deserialise_context context, const xmlChar *name )
                        xmlFreeDoc( context->value_doc );
                        context->value_doc = NULL;
                }
-       
+
                // Close this property handling
                free( context->property );
                context->property = NULL;
@@ -1145,6 +1203,8 @@ static void on_internal_subset( void *ctx, const xmlChar* name,
        params_to_entities( context );
 }
 
+// TODO: Check this with Dan... I think this is for westley parameterisation
+// but it's breaking standard escaped entities (like &lt; etc).
 static void on_entity_declaration( void *ctx, const xmlChar* name, int type, 
        const xmlChar* publicId, const xmlChar* systemId, xmlChar* content)
 {
@@ -1154,7 +1214,8 @@ static void on_entity_declaration( void *ctx, const xmlChar* name, int type,
        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 );
@@ -1171,11 +1232,15 @@ xmlEntityPtr on_get_entity( void *ctx, const xmlChar* name )
        // 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;
 }
@@ -1247,10 +1312,25 @@ static void parse_url( mlt_properties properties, char *url )
                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;
@@ -1259,6 +1339,13 @@ mlt_producer producer_westley_init( int info, char *data )
        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();