rc/framework/mlt_frame.c
[melted] / src / framework / mlt_playlist.c
index d563d7d..ddb84a3 100644 (file)
@@ -263,6 +263,19 @@ static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer source,
        // Fetch the cuts parent properties
        parent = MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( producer ) );
 
+       // Remove fezzik normalisers for fx cuts
+       if ( mlt_properties_get_int( parent, "meta.fx_cut" ) )
+       {
+               mlt_service service = MLT_PRODUCER_SERVICE( mlt_producer_cut_parent( producer ) );
+               mlt_filter filter = mlt_service_filter( service, 0 );
+               while ( filter != NULL && mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "_fezzik" ) )
+               {
+                       mlt_service_detach( service, filter );
+                       filter = mlt_service_filter( service, 0 );
+               }
+               mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( producer ), "meta.fx_cut", 1 );
+       }
+
        // Check that we have room
        if ( this->count >= this->size )
        {
@@ -755,6 +768,9 @@ int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_
        {
                playlist_entry *entry = this->list[ clip ];
                mlt_producer producer = entry->producer;
+               mlt_properties properties = MLT_PLAYLIST_PROPERTIES( this );
+
+               mlt_events_block( properties, properties );
 
                if ( mlt_producer_is_blank( producer ) )
                {
@@ -762,9 +778,9 @@ int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_
                        if ( out - in + 1 > mlt_producer_get_length( &this->blank ) )
                        {
                                mlt_properties blank_props = MLT_PRODUCER_PROPERTIES( &this->blank );
-                               mlt_events_block( blank_props, blank_props );
-                               mlt_producer_set_in_and_out( &this->blank, in, out );
-                               mlt_events_unblock( blank_props, blank_props );
+                               mlt_properties_set_int( blank_props, "length", out - in + 1 );
+                               mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( producer ), "length", out - in + 1 );
+                               mlt_producer_set_in_and_out( &this->blank, 0, out - in );
                        }
                }
 
@@ -781,6 +797,8 @@ int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_
                }
 
                mlt_producer_set_in_and_out( producer, in, out );
+               mlt_events_unblock( properties, properties );
+               mlt_playlist_virtual_refresh( this );
        }
        return error;
 }
@@ -795,7 +813,7 @@ int mlt_playlist_split( mlt_playlist this, int clip, mlt_position position )
        {
                playlist_entry *entry = this->list[ clip ];
                position = position < 0 ? entry->frame_count + position - 1 : position;
-               if ( position >= 0 && position <= entry->frame_count )
+               if ( position >= 0 && position < entry->frame_count - 1 )
                {
                        int in = entry->frame_in;
                        int out = entry->frame_out;
@@ -803,8 +821,17 @@ int mlt_playlist_split( mlt_playlist this, int clip, mlt_position position )
                        mlt_playlist_resize_clip( this, clip, in, in + position );
                        if ( !mlt_producer_is_blank( entry->producer ) )
                        {
+                               int i = 0;
+                               mlt_properties entry_properties = MLT_PRODUCER_PROPERTIES( entry->producer );
                                mlt_producer split = mlt_producer_cut( entry->producer, in + position + 1, out );
+                               mlt_properties split_properties = MLT_PRODUCER_PROPERTIES( split );
                                mlt_playlist_insert( this, split, clip + 1, 0, -1 );
+                               for ( i = 0; i < mlt_properties_count( entry_properties ); i ++ )
+                               {
+                                       char *name = mlt_properties_get_name( entry_properties, i );
+                                       if ( name != NULL && !strncmp( name, "meta.", 5 ) )
+                                               mlt_properties_set( split_properties, name, mlt_properties_get_value( entry_properties, i ) );
+                               }
                                mlt_producer_close( split );
                        }
                        else
@@ -822,19 +849,50 @@ int mlt_playlist_split( mlt_playlist this, int clip, mlt_position position )
        return error;
 }
 
+/** Split the playlist at the absolute position.
+*/
+
+int mlt_playlist_split_at( mlt_playlist this, mlt_position position, int left )
+{
+       int result = this == NULL ? -1 : 0;
+       if ( !result )
+       {
+               if ( position >= 0 && position < mlt_producer_get_playtime( MLT_PLAYLIST_PRODUCER( this ) ) )
+               {
+                       int clip = mlt_playlist_get_clip_index_at( this, position );
+                       mlt_playlist_clip_info info;
+                       mlt_playlist_get_clip_info( this, &info, clip );
+                       if ( left && position != info.start )
+                               mlt_playlist_split( this, clip, position - info.start - 1 );
+                       else if ( !left )
+                               mlt_playlist_split( this, clip, position - info.start );
+                       result = position;
+               }
+               else if ( position <= 0 )
+               {
+                       result = 0;
+               }
+               else
+               {
+                       result = mlt_producer_get_playtime( MLT_PLAYLIST_PRODUCER( this ) );
+               }
+       }
+       return result;
+}
+
 /** Join 1 or more consecutive clips.
 */
 
 int mlt_playlist_join( mlt_playlist this, int clip, int count, int merge )
 {
-       int error = clip < 0 || ( clip ) >= this->count;
+       int error = clip < 0 || clip >= this->count;
        if ( error == 0 )
        {
                int i = clip;
                mlt_playlist new_clip = mlt_playlist_init( );
                mlt_events_block( MLT_PLAYLIST_PROPERTIES( this ), this );
                if ( clip + count >= this->count )
-                       count = this->count - clip;
+                       count = this->count - clip - 1;
                for ( i = 0; i <= count; i ++ )
                {
                        playlist_entry *entry = this->list[ clip ];
@@ -1120,15 +1178,14 @@ void mlt_playlist_consolidate_blanks( mlt_playlist this, int keep_length )
                        playlist_entry *left = this->list[ i - 1 ];
                        playlist_entry *right = this->list[ i ];
 
-                       if ( mlt_producer_cut_parent( left->producer ) == mlt_producer_cut_parent( right->producer ) && 
-                                mlt_producer_is_blank( left->producer ) )
+                       if ( mlt_producer_is_blank( left->producer ) && mlt_producer_is_blank( right->producer ) )
                        {
                                mlt_playlist_resize_clip( this, i - 1, 0, left->frame_count + right->frame_count - 1 );
                                mlt_playlist_remove( this, i -- );
                        }
                }
 
-               if ( !keep_length )
+               if ( !keep_length && this->count > 0 )
                {
                        playlist_entry *last = this->list[ this->count - 1 ];
                        if ( mlt_producer_is_blank( last->producer ) )
@@ -1148,6 +1205,14 @@ int mlt_playlist_is_blank( mlt_playlist this, int clip )
        return this == NULL || mlt_producer_is_blank( mlt_playlist_get_clip( this, clip ) );
 }
 
+/** Determine if the specified position is a blank.
+*/
+
+int mlt_playlist_is_blank_at( mlt_playlist this, int position )
+{
+       return this == NULL || mlt_producer_is_blank( mlt_playlist_get_clip_at( this, position ) );
+}
+
 /** Replace the specified clip with a blank and return the clip.
 */
 
@@ -1166,16 +1231,16 @@ mlt_producer mlt_playlist_replace_with_blank( mlt_playlist this, int clip )
                mlt_playlist_remove( this, clip );
                mlt_playlist_blank( this, out - in );
                mlt_playlist_move( this, this->count - 1, clip );
-               mlt_producer_set_in_and_out( producer, in, out );
                mlt_events_unblock( properties, properties );
                mlt_playlist_virtual_refresh( this );
+               mlt_producer_set_in_and_out( producer, in, out );
        }
        return producer;
 }
 
 void mlt_playlist_insert_blank( mlt_playlist this, int clip, int length )
 {
-       if ( this != NULL && length > 0 )
+       if ( this != NULL && length >= 0 )
        {
                mlt_properties properties = MLT_PLAYLIST_PROPERTIES( this );
                mlt_events_block( properties, properties );
@@ -1226,11 +1291,18 @@ int mlt_playlist_insert_at( mlt_playlist this, int position, mlt_producer produc
                mlt_events_block( properties, this );
                if ( clip < this->count && mlt_playlist_is_blank( this, clip ) )
                {
-                       mlt_playlist_split( this, clip, position - info.start );
-                       mlt_playlist_get_clip_info( this, &info, ++ clip );
+                       // Split and move to new clip if need be
+                       if ( position != info.start && mlt_playlist_split( this, clip, position - info.start ) == 0 )
+                               mlt_playlist_get_clip_info( this, &info, ++ clip );
+
+                       // Split again if need be
                        if ( length < info.frame_count )
-                               mlt_playlist_split( this, clip, length );
+                               mlt_playlist_split( this, clip, length - 1 );
+
+                       // Remove
                        mlt_playlist_remove( this, clip );
+
+                       // Insert
                        mlt_playlist_insert( this, producer, clip, -1, -1 );
                        ret = clip;
                }
@@ -1270,7 +1342,7 @@ int mlt_playlist_clip_start( mlt_playlist this, int clip )
        mlt_playlist_clip_info info;
        if ( mlt_playlist_get_clip_info( this, &info, clip ) == 0 )
                return info.start;
-       return 0;
+       return clip < 0 ? 0 : mlt_producer_get_playtime( MLT_PLAYLIST_PRODUCER( this ) );
 }
 
 int mlt_playlist_clip_length( mlt_playlist this, int clip )
@@ -1379,7 +1451,22 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
        }
 
        // Get the frame
-       mlt_service_get_frame( real, frame, index );
+       if ( !mlt_properties_get_int( MLT_SERVICE_PROPERTIES( real ), "meta.fx_cut" ) )
+       {
+               mlt_service_get_frame( real, frame, index );
+       }
+       else
+       {
+               mlt_producer parent = mlt_producer_cut_parent( ( mlt_producer )real );
+               *frame = mlt_frame_init( );
+               mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "fx_cut", 1 );
+               mlt_frame_push_service( *frame, NULL );
+               mlt_frame_push_audio( *frame, NULL );
+               mlt_service_apply_filters( parent, *frame, 0 );
+               mlt_service_apply_filters( real, *frame, 0 );
+               mlt_deque_pop_front( MLT_FRAME_IMAGE_STACK( *frame ) );
+               mlt_deque_pop_front( MLT_FRAME_AUDIO_STACK( *frame ) );
+       }
 
        // Check if we're at the end of the clip
        mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );