Multitrack rearrangement and tractor cleanup
[melted] / src / framework / mlt_playlist.c
index c2f4191..222d5bf 100644 (file)
@@ -43,6 +43,7 @@ typedef struct playlist_entry_s
        int repeat;
        mlt_position producer_length;
        mlt_event event;
+       int preservation_hack;
 }
 playlist_entry;
 
@@ -615,21 +616,25 @@ int mlt_playlist_remove( mlt_playlist this, int where )
                        this->list[ i - 1 ] = this->list[ i ];
                this->count --;
 
-               // Decouple from mix_in/out if necessary
-               if ( mlt_properties_get_data( properties, "mix_in", NULL ) != NULL )
+               if ( entry->preservation_hack == 0 )
                {
-                       mlt_properties mix = mlt_properties_get_data( properties, "mix_in", NULL );
-                       mlt_properties_set_data( mix, "mix_out", NULL, 0, NULL, NULL );
-               }
-               if ( mlt_properties_get_data( properties, "mix_out", NULL ) != NULL )
-               {
-                       mlt_properties mix = mlt_properties_get_data( properties, "mix_out", NULL );
-                       mlt_properties_set_data( mix, "mix_in", NULL, 0, NULL, NULL );
+                       // Decouple from mix_in/out if necessary
+                       if ( mlt_properties_get_data( properties, "mix_in", NULL ) != NULL )
+                       {
+                               mlt_properties mix = mlt_properties_get_data( properties, "mix_in", NULL );
+                               mlt_properties_set_data( mix, "mix_out", NULL, 0, NULL, NULL );
+                       }
+                       if ( mlt_properties_get_data( properties, "mix_out", NULL ) != NULL )
+                       {
+                               mlt_properties mix = mlt_properties_get_data( properties, "mix_out", NULL );
+                               mlt_properties_set_data( mix, "mix_in", NULL, 0, NULL, NULL );
+                       }
+       
+                       mlt_producer_clear( entry->producer );
                }
 
                // Close the producer associated to the clip info
                mlt_event_close( entry->event );
-               mlt_producer_clear( entry->producer );
                mlt_producer_close( entry->producer );
 
                // Correct position
@@ -760,7 +765,8 @@ int mlt_playlist_split( mlt_playlist this, int clip, mlt_position position )
        if ( error == 0 )
        {
                playlist_entry *entry = this->list[ clip ];
-               if ( position >= 0 && position < entry->frame_count )
+               position = position < 0 ? entry->frame_count + position - 1 : position;
+               if ( position >= 0 && position <= entry->frame_count )
                {
                        mlt_producer split = NULL;
                        int in = entry->frame_in;
@@ -799,6 +805,9 @@ int mlt_playlist_join( mlt_playlist this, int clip, int count, int merge )
                        playlist_entry *entry = this->list[ clip ];
                        mlt_playlist_append( new_clip, entry->producer );
                        mlt_playlist_repeat_clip( new_clip, i, entry->repeat );
+                       if ( entry->frame_count == entry->repeat )
+                               mlt_properties_set_int( mlt_playlist_properties( new_clip ), "hide", 2 );
+                       entry->preservation_hack = 1;
                        mlt_playlist_remove( this, clip );
                }
                mlt_events_unblock( mlt_playlist_properties( this ), this );
@@ -829,10 +838,6 @@ int mlt_playlist_mix( mlt_playlist this, int clip, int length, mlt_transition tr
                track_a = mlt_producer_cut( clip_a->producer, clip_a->frame_out - length + 1, clip_a->frame_out );
                track_b = mlt_producer_cut( clip_b->producer, clip_b->frame_in, clip_b->frame_in + length - 1 );
 
-               // Temporary - for the benefit of westley serialisation
-               mlt_properties_set_int( mlt_producer_properties( track_a ), "cut", 1 );
-               mlt_properties_set_int( mlt_producer_properties( track_b ), "cut", 1 );
-
                // Set the tracks on the tractor
                mlt_tractor_set_track( tractor, track_a, 0 );
                mlt_tractor_set_track( tractor, track_b, 1 );
@@ -884,6 +889,45 @@ int mlt_playlist_mix( mlt_playlist this, int clip, int length, mlt_transition tr
        return error;
 }
 
+/** Add a transition to an existing mix.
+*/
+
+int mlt_playlist_mix_add( mlt_playlist this, int clip, mlt_transition transition )
+{
+       mlt_producer producer = mlt_producer_cut_parent( mlt_playlist_get_clip( this, clip ) );
+       mlt_properties properties = producer != NULL ? mlt_producer_properties( producer ) : NULL;
+       mlt_tractor tractor = properties != NULL ? mlt_properties_get_data( properties, "mlt_mix", NULL ) : NULL;
+       int error = transition == NULL || tractor == NULL;
+       if ( error == 0 )
+       {
+               mlt_field field = mlt_tractor_field( tractor );
+               mlt_field_plant_transition( field, transition, 0, 1 );
+               mlt_transition_set_in_and_out( transition, 0, this->list[ clip ]->frame_count - 1 );
+       }
+       return error;
+}
+
+/** Return the clip at the position.
+*/
+
+mlt_producer mlt_playlist_get_clip( mlt_playlist this, int clip )
+{
+       if ( clip >= 0 && clip < this->count )
+               return this->list[ clip ]->producer;
+       return NULL;
+}
+
+/** Determine if the clip is a mix.
+*/
+
+int mlt_playlist_clip_is_mix( mlt_playlist this, int clip )
+{
+       mlt_producer producer = mlt_producer_cut_parent( mlt_playlist_get_clip( this, clip ) );
+       mlt_properties properties = producer != NULL ? mlt_producer_properties( producer ) : NULL;
+       mlt_tractor tractor = properties != NULL ? mlt_properties_get_data( properties, "mlt_mix", NULL ) : NULL;
+       return tractor != NULL;
+}
+
 /** Remove a mixed clip - ensure that the cuts included in the mix find their way
        back correctly on to the playlist.
 */