mlt_position frame_in;
mlt_position frame_out;
mlt_position frame_count;
+ int repeat;
mlt_position producer_length;
mlt_event event;
int mix_in_length;
this->list[ i ]->frame_out != mlt_producer_get_out( producer ) ) )
{
// This clip should be removed...
- if ( current_length == 1 )
+ if ( current_length < 1 )
{
this->list[ i ]->frame_in = 0;
- this->list[ i ]->frame_out = 0;
+ this->list[ i ]->frame_out = -1;
this->list[ i ]->frame_count = 0;
}
else
this->list[ i ]->producer_length = current_length;
}
+ // Calculate the frame_count
+ this->list[ i ]->frame_count = ( this->list[ i ]->frame_out - this->list[ i ]->frame_in + 1 ) * this->list[ i ]->repeat;
+
// Update the frame_count for this clip
frame_count += this->list[ i ]->frame_count;
}
static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer source, mlt_position in, mlt_position out )
{
+ char *resource = source != NULL ? mlt_properties_get( mlt_producer_properties( source ), "resource" ) : NULL;
mlt_producer producer = NULL;
mlt_properties properties = NULL;
// If we have a cut, then use the in/out points from the cut
- if ( &this->blank == source )
+ if ( resource == NULL || !strcmp( resource, "blank" ) )
{
- producer = source;
+ producer = &this->blank;
properties = mlt_producer_properties( producer );
mlt_properties_inc_ref( properties );
}
properties = mlt_producer_properties( producer );
}
-
// Check that we have room
if ( this->count >= this->size )
{
this->list[ this->count ]->frame_in = in;
this->list[ this->count ]->frame_out = out;
this->list[ this->count ]->frame_count = out - in + 1;
+ this->list[ this->count ]->repeat = 1;
this->list[ this->count ]->producer_length = mlt_producer_get_out( producer ) - mlt_producer_get_in( producer ) + 1;
this->list[ this->count ]->event = mlt_events_listen( properties, this, "producer-changed", ( mlt_listener )mlt_playlist_listener );
mlt_event_inc_ref( this->list[ this->count ]->event );
- mlt_properties_set( mlt_producer_properties( source ), "eof", "pause" );
mlt_properties_set( properties, "eof", "pause" );
-
- mlt_producer_set_speed( source, 0 );
mlt_producer_set_speed( producer, 0 );
this->count ++;
total += this->list[ i ]->frame_count;
// Check if the position indicates that we have found the clip
+ // Note that 0 length clips get skipped automatically
if ( position < this->list[ i ]->frame_count )
{
// Found it, now break
// Seek in real producer to relative position
if ( producer != NULL )
{
- mlt_producer_seek( producer, position );
+ int count = this->list[ i ]->frame_count / this->list[ i ]->repeat;
+ mlt_producer_seek( producer, position % count );
}
else if ( !strcmp( eof, "pause" ) && total > 0 )
{
info->frame_in = this->list[ index ]->frame_in;
info->frame_out = this->list[ index ]->frame_out;
info->frame_count = this->list[ index ]->frame_count;
+ info->repeat = this->list[ index ]->repeat;
info->length = mlt_producer_get_length( producer );
info->fps = mlt_producer_get_fps( producer );
- info->event = this->list[ index ]->event;
}
return error;
return 0;
}
-/** Resize the current clip.
+/** Repeat the specified clip n times.
+*/
+
+int mlt_playlist_repeat_clip( mlt_playlist this, int clip, int repeat )
+{
+ int error = repeat < 1 || clip < 0 || clip >= this->count;
+ if ( error == 0 )
+ {
+ playlist_entry *entry = this->list[ clip ];
+ entry->repeat = repeat;
+ mlt_playlist_virtual_refresh( this );
+ }
+ return error;
+}
+
+/** Resize the specified clip.
*/
int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_position out )
playlist_entry *entry = this->list[ clip ];
if ( position > 0 && position < entry->frame_count )
{
- mlt_producer parent = mlt_producer_cut_parent( entry->producer );
mlt_producer split = NULL;
int in = entry->frame_in;
int out = entry->frame_out;
mlt_events_block( mlt_playlist_properties( this ), this );
mlt_playlist_resize_clip( this, clip, in, in + position );
- split = mlt_producer_cut( parent, in + position + 1, out );
- mlt_playlist_insert( this, split, clip + 1, -1, -1 );
+ split = mlt_producer_cut( entry->producer, in + position + 1, out );
+ mlt_playlist_insert( this, split, clip + 1, 0, -1 );
mlt_events_unblock( mlt_playlist_properties( this ), this );
mlt_events_fire( mlt_playlist_properties( this ), "producer-changed", NULL );
}
int mlt_playlist_join( mlt_playlist this, int clip, int count, int merge )
{
- int error = clip < 0 || ( clip + 1 ) >= this->count;
+ int error = clip < 0 || ( clip ) >= this->count;
if ( error == 0 )
{
int i = clip;
{
playlist_entry *entry = this->list[ clip ];
mlt_playlist_append( new_clip, entry->producer );
+ mlt_playlist_repeat_clip( new_clip, i, entry->repeat );
mlt_playlist_remove( this, clip );
}
mlt_events_unblock( mlt_playlist_properties( this ), this );
mlt_position frame_count;
mlt_position length;
float fps;
- mlt_event event;
+ int repeat;
}
mlt_playlist_clip_info;
extern int mlt_playlist_remove( mlt_playlist self, int where );
extern int mlt_playlist_move( mlt_playlist self, int from, int to );
extern int mlt_playlist_resize_clip( mlt_playlist self, int clip, mlt_position in, mlt_position out );
+extern int mlt_playlist_repeat_clip( mlt_playlist self, int clip, int repeat );
extern int mlt_playlist_split( mlt_playlist self, int clip, mlt_position position );
extern int mlt_playlist_join( mlt_playlist self, int clip, int count, int merge );
extern int mlt_playlist_mix( mlt_playlist self, int clip, int length, mlt_transition transition );
mlt_properties_inherit( properties, group );
}
}
+ else if ( !strcmp( argv[ i ], "-repeat" ) )
+ {
+ int repeat = atoi( argv[ ++ i ] );
+ if ( producer != NULL && !mlt_producer_is_cut( producer ) )
+ mlt_playlist_append( playlist, producer );
+ producer = NULL;
+ if ( mlt_playlist_count( playlist ) > 0 )
+ {
+ mlt_playlist_clip_info info;
+ mlt_playlist_repeat_clip( playlist, mlt_playlist_count( playlist ) - 1, repeat );
+ mlt_playlist_get_clip_info( playlist, &info, mlt_playlist_count( playlist ) - 1 );
+ producer = info.cut;
+ properties = mlt_producer_properties( producer );
+ }
+ }
+ else if ( !strcmp( argv[ i ], "-split" ) )
+ {
+ int split = atoi( argv[ ++ i ] );
+ if ( producer != NULL && !mlt_producer_is_cut( producer ) )
+ mlt_playlist_append( playlist, producer );
+ producer = NULL;
+ if ( mlt_playlist_count( playlist ) > 0 )
+ {
+ mlt_playlist_clip_info info;
+ mlt_playlist_get_clip_info( playlist, &info, mlt_playlist_count( playlist ) - 1 );
+ split = split < 0 ? info.frame_out + split : split;
+ mlt_playlist_split( playlist, mlt_playlist_count( playlist ) - 1, split );
+ mlt_playlist_get_clip_info( playlist, &info, mlt_playlist_count( playlist ) - 1 );
+ producer = info.cut;
+ properties = mlt_producer_properties( producer );
+ }
+ }
+ else if ( !strcmp( argv[ i ], "-join" ) )
+ {
+ int clips = atoi( argv[ ++ i ] );
+ if ( producer != NULL && !mlt_producer_is_cut( producer ) )
+ mlt_playlist_append( playlist, producer );
+ producer = NULL;
+ if ( mlt_playlist_count( playlist ) > 0 )
+ {
+ mlt_playlist_clip_info info;
+ mlt_playlist_join( playlist, mlt_playlist_count( playlist ) - clips - 1, clips, 0 );
+ mlt_playlist_get_clip_info( playlist, &info, mlt_playlist_count( playlist ) - 1 );
+ producer = info.cut;
+ properties = mlt_producer_properties( producer );
+ }
+ }
else if ( !strcmp( argv[ i ], "-mix" ) )
{
int length = atoi( argv[ ++ i ] );
- if ( producer != NULL )
+ if ( producer != NULL && !mlt_producer_is_cut( producer ) )
mlt_playlist_append( playlist, producer );
producer = NULL;
if ( mlt_playlist_count( playlist ) >= 2 )
}
else if ( !strcmp( argv[ i ], "-blank" ) )
{
- if ( producer != NULL )
+ if ( producer != NULL && !mlt_producer_is_cut( producer ) )
mlt_playlist_append( playlist, producer );
producer = NULL;
mlt_playlist_blank( playlist, atof( argv[ ++ i ] ) );
!strcmp( argv[ i ], "-hide-video" ) ||
!strcmp( argv[ i ], "-hide-audio" ) )
{
- if ( producer != NULL )
+ if ( producer != NULL && !mlt_producer_is_cut( producer ) )
mlt_playlist_append( playlist, producer );
producer = NULL;
mlt_multitrack_connect( multitrack, mlt_playlist_producer( playlist ), track ++ );
}
else if ( argv[ i ][ 0 ] != '-' )
{
- if ( producer != NULL )
+ if ( producer != NULL && !mlt_producer_is_cut( producer ) )
mlt_playlist_append( playlist, producer );
if ( title == NULL )
title = argv[ i ];
}
// Connect last producer to playlist
- if ( producer != NULL )
+ if ( producer != NULL && !mlt_producer_is_cut( producer ) )
mlt_playlist_append( playlist, producer );
// Track the last playlist too
serialise_tractor( context, MLT_SERVICE( producer ), node );
context->pass --;
}
+ else if ( resource_s != NULL && !strcmp( resource_s, "<playlist>" ) )
+ serialise_playlist( context, MLT_SERVICE( producer ), node );
else if ( service_s != NULL && strcmp( service_s, "blank" ) != 0 )
serialise_service( context, MLT_SERVICE( producer ), node );
}
xmlNewProp( entry, "in", temp );
sprintf( temp, "%d", info.frame_out );
xmlNewProp( entry, "out", temp );
+ if ( info.repeat > 1 )
+ {
+ sprintf( temp, "%d", info.repeat );
+ xmlNewProp( entry, "repeat", temp );
+ }
if ( mlt_producer_is_cut( info.cut ) )
serialise_service_filters( context, mlt_producer_service( info.cut ), entry );
}
mlt_playlist_append( MLT_PLAYLIST( parent ), producer );
}
+ // Handle the repeat property
+ if ( mlt_properties_get_int( temp, "repeat" ) > 0 )
+ {
+ mlt_playlist_repeat_clip( MLT_PLAYLIST( parent ),
+ mlt_playlist_count( MLT_PLAYLIST( parent ) ) - 1,
+ mlt_properties_get_int( temp, "repeat" ) );
+ }
+
mlt_playlist_get_clip_info( MLT_PLAYLIST( parent ), &info, mlt_playlist_count( MLT_PLAYLIST( parent ) ) - 1 );
entry = info.cut;
}