// 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 )
{
{
int count = this->list[ i ]->frame_count / this->list[ i ]->repeat;
*progressive = count == 1;
- mlt_producer_seek( producer, position % count );
+ mlt_producer_seek( producer, (int)position % count );
}
else if ( !strcmp( eof, "pause" ) && total > 0 )
{
mlt_producer this_producer = MLT_PLAYLIST_PRODUCER( this );
mlt_producer_seek( this_producer, original - 1 );
producer = entry->producer;
- mlt_producer_seek( producer, entry->frame_out % count );
+ mlt_producer_seek( producer, (int)entry->frame_out % count );
mlt_producer_set_speed( this_producer, 0 );
mlt_producer_set_speed( producer, 0 );
*progressive = count == 1;
{
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 ) )
{
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 );
}
}
}
mlt_producer_set_in_and_out( producer, in, out );
+ mlt_events_unblock( properties, properties );
+ mlt_playlist_virtual_refresh( this );
}
return error;
}
{
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;
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
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 ];
/** Return the clip at the specified position.
*/
-mlt_producer mlt_playlist_get_clip_at( mlt_playlist this, int position )
+mlt_producer mlt_playlist_get_clip_at( mlt_playlist this, mlt_position position )
{
int index = 0, total = 0;
return mlt_playlist_locate( this, &position, &index, &total );
/** Return the clip index of the specified position.
*/
-int mlt_playlist_get_clip_index_at( mlt_playlist this, int position )
+int mlt_playlist_get_clip_index_at( mlt_playlist this, mlt_position position )
{
int index = 0, total = 0;
mlt_playlist_locate( this, &position, &index, &total );
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 ) )
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, mlt_position 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.
*/
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 );
}
}
-void mlt_playlist_pad_blanks( mlt_playlist this, int position, int length, int find )
+void mlt_playlist_pad_blanks( mlt_playlist this, mlt_position position, int length, int find )
{
if ( this != NULL && length != 0 )
{
}
}
-int mlt_playlist_insert_at( mlt_playlist this, int position, mlt_producer producer, int mode )
+int mlt_playlist_insert_at( mlt_playlist this, mlt_position position, mlt_producer producer, int mode )
{
int ret = this == NULL || position < 0 || producer == NULL;
if ( ret == 0 )
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;
}
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 )
return count;
}
-int mlt_playlist_remove_region( mlt_playlist this, int position, int length )
+int mlt_playlist_remove_region( mlt_playlist this, mlt_position position, int length )
{
int index = mlt_playlist_get_clip_index_at( this, position );
if ( index >= 0 && index < this->count )
return index;
}
-int mlt_playlist_move_region( mlt_playlist this, int position, int length, int new_position )
+int mlt_playlist_move_region( mlt_playlist this, mlt_position position, int length, int new_position )
{
if ( this != NULL )
{
}
// 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( MLT_PRODUCER_SERVICE( 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 );