]> git.sesse.net Git - mlt/blobdiff - src/miracle/miracle_unit.c
Merge ../mlt++
[mlt] / src / miracle / miracle_unit.c
index ce9dac819568ef620a72969c2fbea08d13463c80..4974e387170cbac0110a872ecb9facb96679b2fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * miracle_unit.c -- DV Transmission Unit Implementation
+ * miracle_unit.c -- Transmission Unit Implementation
  * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
  * Author: Dan Dennedy <dan@dennedy.org>
  *
@@ -62,14 +62,13 @@ miracle_unit miracle_unit_init( int index, char *constructor )
        if ( arg != NULL )
                *arg ++ = '\0';
 
-       consumer = mlt_factory_consumer( id, arg );
+       consumer = mlt_factory_consumer( NULL, id, arg );
 
        if ( consumer != NULL )
        {
                mlt_playlist playlist = mlt_playlist_init( );
                this = calloc( sizeof( miracle_unit_t ), 1 );
                this->properties = mlt_properties_new( );
-               this->producers = mlt_properties_new( );
                mlt_properties_init( this->properties, this );
                mlt_properties_set_int( this->properties, "unit", index );
                mlt_properties_set_int( this->properties, "generation", 0 );
@@ -78,7 +77,7 @@ miracle_unit miracle_unit_init( int index, char *constructor )
                mlt_properties_set( this->properties, "arg", arg );
                mlt_properties_set_data( this->properties, "consumer", consumer, 0, ( mlt_destructor )mlt_consumer_close, NULL );
                mlt_properties_set_data( this->properties, "playlist", playlist, 0, ( mlt_destructor )mlt_playlist_close, NULL );
-               mlt_consumer_connect( consumer, mlt_playlist_service( playlist ) );
+               mlt_consumer_connect( consumer, MLT_PLAYLIST_SERVICE( playlist ) );
        }
 
        return this;
@@ -132,7 +131,7 @@ void miracle_unit_set_notifier( miracle_unit this, valerie_notifier notifier, ch
 {
        mlt_properties properties = this->properties;
        mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
-       mlt_properties playlist_properties = mlt_playlist_properties( playlist );
+       mlt_properties playlist_properties = MLT_PLAYLIST_PROPERTIES( playlist );
 
        mlt_properties_set( properties, "root", root_dir );
        mlt_properties_set_data( properties, "notifier", notifier, 0, NULL, NULL );
@@ -142,33 +141,20 @@ void miracle_unit_set_notifier( miracle_unit this, valerie_notifier notifier, ch
        miracle_unit_status_communicate( this );
 }
 
-static mlt_producer create_producer( char *file )
-{
-       return mlt_factory_producer( "fezzik", file );
-}
-
 /** Create or locate a producer for the file specified.
 */
 
 static mlt_producer locate_producer( miracle_unit unit, char *file )
 {
-       // Get the unit properties
-       mlt_properties properties = unit->producers;
-
-       // Check if we already have loaded this file
-       mlt_producer result = mlt_properties_get_data( properties, file, NULL );
+       // Try to get the profile from the consumer
+       mlt_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL );
+       mlt_profile profile = NULL;
 
-       if ( result == NULL )
+       if ( consumer != NULL )
        {
-               // Create the producer
-               result = create_producer( file );
-
-               // Now store the result
-               if ( result != NULL )
-                       mlt_properties_set_data( properties, file, result, 0, ( mlt_destructor )mlt_producer_close, NULL );
+               profile = mlt_service_profile( MLT_CONSUMER_SERVICE( consumer ) );
        }
-
-       return result;
+       return mlt_factory_producer( profile, "fezzik", file );
 }
 
 /** Update the generation count.
@@ -188,15 +174,12 @@ static void clear_unit( miracle_unit unit )
 {
        mlt_properties properties = unit->properties;
        mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
-       mlt_producer producer = mlt_playlist_producer( playlist );
+       mlt_producer producer = MLT_PLAYLIST_PRODUCER( playlist );
 
+       mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
        mlt_playlist_clear( playlist );
        mlt_producer_seek( producer, 0 );
-
-       if ( unit->old_producers != NULL )
-               mlt_properties_close( unit->old_producers );
-       unit->old_producers = unit->producers;
-       unit->producers = mlt_properties_new( );
+       mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
 
        update_generation( unit );
 }
@@ -210,21 +193,43 @@ static void clean_unit( miracle_unit unit )
        mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
        mlt_playlist_clip_info info;
        int current = mlt_playlist_current_clip( playlist );
-       mlt_producer producer = mlt_playlist_producer( playlist );
+       mlt_producer producer = MLT_PLAYLIST_PRODUCER( playlist );
        mlt_position position = mlt_producer_frame( producer );
        double speed = mlt_producer_get_speed( producer );
        mlt_playlist_get_clip_info( playlist, &info, current );
 
-       if ( info.resource != NULL )
+       if ( info.producer != NULL )
        {
-               void *instance = mlt_properties_get_data( unit->producers, info.resource, NULL );
+               mlt_properties_inc_ref( MLT_PRODUCER_PROPERTIES( info.producer ) );
                position -= info.start;
-               mlt_properties_set_data( unit->producers, info.resource, instance, 0, NULL, NULL );
                clear_unit( unit );
-               mlt_playlist_append_io( playlist, instance, info.frame_in, info.frame_out );
-               mlt_properties_set_data( unit->producers, info.resource, instance, 0, ( mlt_destructor )mlt_producer_close, NULL );
+               mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
+               mlt_playlist_append_io( playlist, info.producer, info.frame_in, info.frame_out );
                mlt_producer_seek( producer, position );
                mlt_producer_set_speed( producer, speed );
+               mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
+               mlt_producer_close( info.producer );
+       }
+       
+       update_generation( unit );
+}
+
+/** Remove everything up to the current clip from the unit.
+*/
+
+static void wipe_unit( miracle_unit unit )
+{
+       mlt_properties properties = unit->properties;
+       mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+       mlt_playlist_clip_info info;
+       int current = mlt_playlist_current_clip( playlist );
+       mlt_playlist_get_clip_info( playlist, &info, current );
+
+       if ( info.producer != NULL && info.start > 0 )
+       {
+               mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
+               mlt_playlist_remove_region( playlist, 0, info.start - 1 );
+               mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
        }
        
        update_generation( unit );
@@ -245,10 +250,14 @@ void miracle_unit_report_list( miracle_unit unit, valerie_response response )
        for ( i = 0; i < mlt_playlist_count( playlist ); i ++ )
        {
                mlt_playlist_clip_info info;
+               char *title;
                mlt_playlist_get_clip_info( playlist , &info, i );
+               title = mlt_properties_get( MLT_PRODUCER_PROPERTIES( info.producer ), "title" );
+               if ( title == NULL )
+                       title = strip_root( unit, info.resource );
                valerie_response_printf( response, 10240, "%d \"%s\" %d %d %d %d %.2f\n", 
                                                                 i, 
-                                                                strip_root( unit, info.resource ), 
+                                                                title,
                                                                 info.frame_in, 
                                                                 info.frame_out,
                                                                 info.frame_count, 
@@ -269,18 +278,22 @@ void miracle_unit_report_list( miracle_unit unit, valerie_response response )
 
 valerie_error_code miracle_unit_load( miracle_unit unit, char *clip, int32_t in, int32_t out, int flush )
 {
-       // Now try to create an producer
-       mlt_producer instance = create_producer( clip );
+       // Now try to create a producer
+       mlt_producer instance = locate_producer( unit, clip );
 
        if ( instance != NULL )
        {
-               clear_unit( unit );
                mlt_properties properties = unit->properties;
-               mlt_properties_set_data( unit->producers, clip, instance, 0, ( mlt_destructor )mlt_producer_close, NULL );
                mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+               int original = mlt_producer_get_playtime( MLT_PLAYLIST_PRODUCER( playlist ) );
+               mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
                mlt_playlist_append_io( playlist, instance, in, out );
+               mlt_playlist_remove_region( playlist, 0, original );
+               mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
                miracle_log( LOG_DEBUG, "loaded clip %s", clip );
+               update_generation( unit );
                miracle_unit_status_communicate( unit );
+               mlt_producer_close( instance );
                return valerie_ok;
        }
 
@@ -296,10 +309,13 @@ valerie_error_code miracle_unit_insert( miracle_unit unit, char *clip, int index
                mlt_properties properties = unit->properties;
                mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
                fprintf( stderr, "inserting clip %s before %d\n", clip, index );
+               mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
                mlt_playlist_insert( playlist, instance, index, in, out );
+               mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
                miracle_log( LOG_DEBUG, "inserted clip %s at %d", clip, index );
                update_generation( unit );
                miracle_unit_status_communicate( unit );
+               mlt_producer_close( instance );
                return valerie_ok;
        }
 
@@ -310,7 +326,9 @@ valerie_error_code miracle_unit_remove( miracle_unit unit, int index )
 {
        mlt_properties properties = unit->properties;
        mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+       mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
        mlt_playlist_remove( playlist, index );
+       mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
        miracle_log( LOG_DEBUG, "removed clip at %d", index );
        update_generation( unit );
        miracle_unit_status_communicate( unit );
@@ -325,9 +343,19 @@ valerie_error_code miracle_unit_clean( miracle_unit unit )
        return valerie_ok;
 }
 
+valerie_error_code miracle_unit_wipe( miracle_unit unit )
+{
+       wipe_unit( unit );
+       miracle_log( LOG_DEBUG, "Wiped playlist" );
+       miracle_unit_status_communicate( unit );
+       return valerie_ok;
+}
+
 valerie_error_code miracle_unit_clear( miracle_unit unit )
 {
+       mlt_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL );
        clear_unit( unit );
+       mlt_consumer_purge( consumer );
        miracle_log( LOG_DEBUG, "Cleared playlist" );
        miracle_unit_status_communicate( unit );
        return valerie_ok;
@@ -337,7 +365,9 @@ valerie_error_code miracle_unit_move( miracle_unit unit, int src, int dest )
 {
        mlt_properties properties = unit->properties;
        mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+       mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
        mlt_playlist_move( playlist, src, dest );
+       mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
        miracle_log( LOG_DEBUG, "moved clip %d to %d", src, dest );
        update_generation( unit );
        miracle_unit_status_communicate( unit );
@@ -361,16 +391,38 @@ valerie_error_code miracle_unit_append( miracle_unit unit, char *clip, int32_t i
        {
                mlt_properties properties = unit->properties;
                mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+               mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
                mlt_playlist_append_io( playlist, instance, in, out );
                miracle_log( LOG_DEBUG, "appended clip %s", clip );
+               mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
                update_generation( unit );
                miracle_unit_status_communicate( unit );
+               mlt_producer_close( instance );
                return valerie_ok;
        }
 
        return valerie_invalid_file;
 }
 
+/** Add an mlt_service to the playlist
+
+    \param unit A miracle_unit handle.
+    \param service the service to add
+*/
+
+valerie_error_code miracle_unit_append_service( miracle_unit unit, mlt_service service )
+{
+       mlt_properties properties = unit->properties;
+       mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+       mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
+       mlt_playlist_append( playlist, ( mlt_producer )service );
+       mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
+       miracle_log( LOG_DEBUG, "appended clip" );
+       update_generation( unit );
+       miracle_unit_status_communicate( unit );
+       return valerie_ok;
+}
+
 /** Start playing the unit.
 
     \todo error handling
@@ -383,7 +435,7 @@ void miracle_unit_play( miracle_unit_t *unit, int speed )
 {
        mlt_properties properties = unit->properties;
        mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
-       mlt_producer producer = mlt_playlist_producer( playlist );
+       mlt_producer producer = MLT_PLAYLIST_PRODUCER( playlist );
        mlt_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL );
        mlt_producer_set_speed( producer, ( double )speed / 1000 );
        mlt_consumer_start( consumer );
@@ -401,7 +453,7 @@ void miracle_unit_terminate( miracle_unit unit )
 {
        mlt_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL );
        mlt_playlist playlist = mlt_properties_get_data( unit->properties, "playlist", NULL );
-       mlt_producer producer = mlt_playlist_producer( playlist );
+       mlt_producer producer = MLT_PLAYLIST_PRODUCER( playlist );
        mlt_producer_set_speed( producer, 0 );
        mlt_consumer_stop( consumer );
        miracle_unit_status_communicate( unit );
@@ -429,23 +481,35 @@ int miracle_unit_transfer( miracle_unit dest_unit, miracle_unit src_unit )
        mlt_playlist dest_playlist = mlt_properties_get_data( dest_properties, "playlist", NULL );
        mlt_properties src_properties = src_unit->properties;
        mlt_playlist src_playlist = mlt_properties_get_data( src_properties, "playlist", NULL );
+       mlt_playlist tmp_playlist = mlt_playlist_init( );
 
        for ( i = 0; i < mlt_playlist_count( src_playlist ); i ++ )
        {
                mlt_playlist_clip_info info;
                mlt_playlist_get_clip_info( src_playlist, &info, i );
-               mlt_producer producer = locate_producer( dest_unit, info.resource );
-               if ( producer != NULL )
-               {
-                       mlt_playlist_append_io( dest_playlist, producer, info.frame_in, info.frame_out );
-                       if ( i == 0 )
-                       {
-                               miracle_unit_change_position( dest_unit, mlt_playlist_count( dest_playlist ) - 1, 0 );
-                               clean_unit( dest_unit );
-                       }
-               }
+               if ( info.producer != NULL )
+                       mlt_playlist_append_io( tmp_playlist, info.producer, info.frame_in, info.frame_out );
+       }
+
+       clear_unit( src_unit );
+
+       mlt_service_lock( MLT_PLAYLIST_SERVICE( dest_playlist ) );
+
+       for ( i = 0; i < mlt_playlist_count( tmp_playlist ); i ++ )
+       {
+               mlt_playlist_clip_info info;
+               mlt_playlist_get_clip_info( tmp_playlist, &info, i );
+               if ( info.producer != NULL )
+                       mlt_playlist_append_io( dest_playlist, info.producer, info.frame_in, info.frame_out );
        }
 
+       mlt_service_unlock( MLT_PLAYLIST_SERVICE( dest_playlist ) );
+
+       update_generation( dest_unit );
+       miracle_unit_status_communicate( dest_unit );
+
+       mlt_playlist_close( tmp_playlist );
+
        return 0;
 }
 
@@ -470,7 +534,7 @@ int miracle_unit_get_status( miracle_unit unit, valerie_status status )
        {
                mlt_properties properties = unit->properties;
                mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
-               mlt_producer producer = mlt_playlist_producer( playlist );
+               mlt_producer producer = MLT_PLAYLIST_PRODUCER( playlist );
                mlt_producer clip = mlt_playlist_current( playlist );
 
                mlt_playlist_clip_info info;
@@ -479,17 +543,20 @@ int miracle_unit_get_status( miracle_unit unit, valerie_status status )
 
                if ( info.resource != NULL && strcmp( info.resource, "" ) )
                {
-                       strncpy( status->clip, strip_root( unit, info.resource ), sizeof( status->clip ) );
+                       char *title = mlt_properties_get( MLT_PRODUCER_PROPERTIES( info.producer ), "title" );
+                       if ( title == NULL )
+                               title = strip_root( unit, info.resource );
+                       strncpy( status->clip, title, sizeof( status->clip ) );
                        status->speed = (int)( mlt_producer_get_speed( producer ) * 1000.0 );
                        status->fps = mlt_producer_get_fps( producer );
                        status->in = info.frame_in;
                        status->out = info.frame_out;
-                       status->position = mlt_producer_position( clip );
+                       status->position = mlt_producer_frame( clip );
                        status->length = mlt_producer_get_length( clip );
-                       strncpy( status->tail_clip, strip_root( unit, info.resource ), sizeof( status->tail_clip ) );
+                       strncpy( status->tail_clip, title, sizeof( status->tail_clip ) );
                        status->tail_in = info.frame_in;
                        status->tail_out = info.frame_out;
-                       status->tail_position = mlt_producer_position( clip );
+                       status->tail_position = mlt_producer_frame( clip );
                        status->tail_length = mlt_producer_get_length( clip );
                        status->clip_index = mlt_playlist_current_clip( playlist );
                        status->seek_flag = 1;
@@ -523,7 +590,7 @@ void miracle_unit_change_position( miracle_unit unit, int clip, int32_t position
 {
        mlt_properties properties = unit->properties;
        mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
-       mlt_producer producer = mlt_playlist_producer( playlist );
+       mlt_producer producer = MLT_PLAYLIST_PRODUCER( playlist );
        mlt_playlist_clip_info info;
 
        if ( clip < 0 )
@@ -534,7 +601,7 @@ void miracle_unit_change_position( miracle_unit unit, int clip, int32_t position
        else if ( clip >= mlt_playlist_count( playlist ) )
        {
                clip = mlt_playlist_count( playlist ) - 1;
-               position = LONG_MAX;
+               position = INT_MAX;
        }
 
        if ( mlt_playlist_get_clip_info( playlist, &info, clip ) == 0 )
@@ -579,7 +646,9 @@ int miracle_unit_set_clip_in( miracle_unit unit, int index, int32_t position )
        if ( error == 0 )
        {
                miracle_unit_play( unit, 0 );
+               mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
                error = mlt_playlist_resize_clip( playlist, index, position, info.frame_out );
+               mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
                update_generation( unit );
                miracle_unit_change_position( unit, index, 0 );
        }
@@ -600,7 +669,9 @@ int miracle_unit_set_clip_out( miracle_unit unit, int index, int32_t position )
        if ( error == 0 )
        {
                miracle_unit_play( unit, 0 );
+               mlt_service_lock( MLT_PLAYLIST_SERVICE( playlist ) );
                error = mlt_playlist_resize_clip( playlist, index, info.frame_in, position );
+               mlt_service_unlock( MLT_PLAYLIST_SERVICE( playlist ) );
                update_generation( unit );
                miracle_unit_status_communicate( unit );
                miracle_unit_change_position( unit, index, -1 );
@@ -616,7 +687,7 @@ void miracle_unit_step( miracle_unit unit, int32_t offset )
 {
        mlt_properties properties = unit->properties;
        mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
-       mlt_producer producer = mlt_playlist_producer( playlist );
+       mlt_producer producer = MLT_PLAYLIST_PRODUCER( playlist );
        mlt_position position = mlt_producer_frame( producer );
        mlt_producer_seek( producer, position + offset );
 }
@@ -667,12 +738,12 @@ int miracle_unit_set( miracle_unit unit, char *name_value )
        if ( strncmp( name_value, "consumer.", 9 ) )
        {
                mlt_playlist playlist = mlt_properties_get_data( unit->properties, "playlist", NULL );
-               properties = mlt_playlist_properties( playlist );
+               properties = MLT_PLAYLIST_PROPERTIES( playlist );
        }
        else
        {
                mlt_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL );
-               properties = mlt_consumer_properties( consumer );
+               properties = MLT_CONSUMER_PROPERTIES( consumer );
                name_value += 9;
        }
 
@@ -682,7 +753,7 @@ int miracle_unit_set( miracle_unit unit, char *name_value )
 char *miracle_unit_get( miracle_unit unit, char *name )
 {
        mlt_playlist playlist = mlt_properties_get_data( unit->properties, "playlist", NULL );
-       mlt_properties properties = mlt_playlist_properties( playlist );
+       mlt_properties properties = MLT_PLAYLIST_PROPERTIES( playlist );
        return mlt_properties_get( properties, name );
 }
 
@@ -698,10 +769,7 @@ void miracle_unit_close( miracle_unit unit )
        {
                miracle_log( LOG_DEBUG, "closing unit..." );
                miracle_unit_terminate( unit );
-               if ( unit->old_producers != NULL )
-                       mlt_properties_close( unit->old_producers );
                mlt_properties_close( unit->properties );
-               mlt_properties_close( unit->producers );
                free( unit );
                miracle_log( LOG_DEBUG, "... unit closed." );
        }