incomplete next/prev clip behaviour
[melted] / src / framework / mlt_playlist.c
index b2f9bc8..ed33da9 100644 (file)
@@ -73,6 +73,9 @@ mlt_playlist mlt_playlist_init( )
 
                // Initialise blank
                mlt_producer_init( &this->blank, NULL );
+
+               // Indicate that this producer is a playlist
+               mlt_properties_set_data( mlt_playlist_properties( this ), "playlist", this, 0, NULL, NULL );
        }
        
        return this;
@@ -116,7 +119,7 @@ static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer
                // Inherit it from the producer
                fps = mlt_producer_get_fps( producer );
        }
-       else
+       else if ( fps != mlt_properties_get_double( mlt_producer_properties( producer ), "fps" ) )
        {
                // Generate a warning for now - the following attempt to fix may fail
                fprintf( stderr, "Warning: fps mismatch on playlist producer %d\n", this->count );
@@ -184,6 +187,106 @@ static mlt_producer mlt_playlist_virtual_seek( mlt_playlist this )
        return producer;
 }
 
+static mlt_producer mlt_playlist_virtual_set_out( mlt_playlist this )
+{
+       // Default producer to blank
+       mlt_producer producer = &this->blank;
+
+       // Map playlist position to real producer in virtual playlist
+       mlt_timecode position = mlt_producer_position( &this->parent );
+
+       // Loop through the virtual playlist
+       int i = 0;
+
+       for ( i = 0; i < this->count; i ++ )
+       {
+               if ( position < this->list[ i ]->playtime )
+               {
+                       // Found it, now break
+                       producer = this->list[ i ]->producer;
+                       position += this->list[ i ]->in;
+                       break;
+               }
+               else
+               {
+                       // Decrement position by length of this entry
+                       position -= this->list[ i ]->playtime;
+               }
+       }
+
+       // Seek in real producer to relative position
+       if ( i < this->count )
+       {
+               fprintf( stderr, "END OF CLIP %d AT %e\n", i, position );
+               this->list[ i ]->playtime = position - this->list[ i ]->in;
+       }
+
+       return producer;
+}
+
+static int mlt_playlist_current_clip( mlt_playlist this )
+{
+       // Map playlist position to real producer in virtual playlist
+       mlt_timecode position = mlt_producer_position( &this->parent );
+
+       // Loop through the virtual playlist
+       int i = 0;
+
+       for ( i = 0; i < this->count; i ++ )
+       {
+               if ( position < this->list[ i ]->playtime )
+               {
+                       // Found it, now break
+                       break;
+               }
+               else
+               {
+                       // Decrement position by length of this entry
+                       position -= this->list[ i ]->playtime;
+               }
+       }
+
+       return i;
+}
+
+/** Get the timecode which corresponds to the start of the next clip.
+*/
+
+mlt_timecode mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index )
+{
+       mlt_timecode position = 0;
+       int absolute_clip = index;
+       int i = 0;
+
+       // Determine the absolute clip
+       switch ( whence )
+       {
+               case mlt_whence_relative_start:
+                       absolute_clip = index;
+                       break;
+
+               case mlt_whence_relative_current:
+                       absolute_clip = mlt_playlist_current_clip( this ) + index;
+                       break;
+
+               case mlt_whence_relative_end:
+                       absolute_clip = this->count - index;
+                       break;
+       }
+
+       // Check that we're in a valid range
+       if ( absolute_clip < 0 )
+               absolute_clip = 0;
+       else if ( absolute_clip > this->count )
+               absolute_clip = this->count;
+
+       // Now determine the timecode
+       for ( i = 0; i < absolute_clip; i ++ )
+               position += this->list[ i ]->playtime;
+
+       return position;
+}
+
 /** Append a producer to the playlist.
 */
 
@@ -216,6 +319,11 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
        // Get the frame
        mlt_service_get_frame( mlt_producer_service( real ), frame, index );
 
+       // Check if we're at the end of the clip
+       mlt_properties properties = mlt_frame_properties( *frame );
+       if ( mlt_properties_get_int( properties, "end_of_clip" ) )
+               mlt_playlist_virtual_set_out( this );
+
        // Update timecode on the frame we're creating
        mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );