+ // Get the parent of this cut
+ mlt_producer parent = mlt_producer_cut_parent( this );
+
+ // Get the properties of the parent
+ mlt_properties parent_properties = mlt_producer_properties( parent );
+
+ // Get the properties of the cut
+ mlt_properties properties = mlt_producer_properties( this );
+
+ // Determine the clone index
+ int clone_index = mlt_properties_get_int( properties, "_clone" );
+
+ // Determine the clone to use
+ mlt_producer clone = this;
+
+ if ( clone_index > 0 )
+ {
+ char key[ 25 ];
+ sprintf( key, "_clone.%d", clone_index - 1 );
+ clone = mlt_properties_get_data( mlt_producer_properties( mlt_producer_cut_parent( this ) ), key, NULL );
+ if ( clone == NULL ) fprintf( stderr, "requested clone doesn't exist %d\n", clone_index );
+ clone = clone == NULL ? this : clone;
+ }
+ else
+ {
+ clone = parent;
+ }
+
+ // We need to seek to the correct position in the clone
+ mlt_producer_seek( clone, mlt_producer_get_in( this ) + mlt_properties_get_int( properties, "_position" ) );
+
+ // Assign the clone property to the parent
+ mlt_properties_set_data( parent_properties, "use_clone", clone, 0, NULL, NULL );
+
+ // Now get the frame from the parents service
+ result = mlt_service_get_frame( mlt_producer_service( parent ), frame, index );
+
+ // We're done with the clone now
+ mlt_properties_set_data( parent_properties, "use_clone", NULL, 0, NULL, NULL );
+ }
+
+ return result;
+}
+
+/** Attach a filter.
+*/
+
+int mlt_producer_attach( mlt_producer this, mlt_filter filter )
+{
+ return mlt_service_attach( mlt_producer_service( this ), filter );
+}
+
+/** Detach a filter.
+*/
+
+int mlt_producer_detach( mlt_producer this, mlt_filter filter )
+{
+ return mlt_service_detach( mlt_producer_service( this ), filter );
+}
+
+/** Retrieve a filter.
+*/
+
+mlt_filter mlt_producer_filter( mlt_producer this, int index )
+{
+ return mlt_service_filter( mlt_producer_service( this ), index );
+}
+
+/** Clone this producer.
+*/
+
+static mlt_producer mlt_producer_clone( mlt_producer this )
+{
+ mlt_producer clone = NULL;
+ mlt_properties properties = mlt_producer_properties( this );
+ char *resource = mlt_properties_get( properties, "resource" );
+ char *service = mlt_properties_get( properties, "mlt_service" );
+
+ if ( service != NULL )
+ clone = mlt_factory_producer( service, resource );
+
+ if ( clone == NULL && resource != NULL )
+ clone = mlt_factory_producer( "fezzik", resource );
+
+ if ( clone != NULL )
+ mlt_properties_inherit( mlt_producer_properties( clone ), properties );
+
+ return clone;
+}
+
+/** Create clones.
+*/
+
+static void mlt_producer_set_clones( mlt_producer this, int clones )
+{
+ mlt_producer parent = mlt_producer_cut_parent( this );
+ mlt_properties properties = mlt_producer_properties( parent );
+ int existing = mlt_properties_get_int( properties, "_clones" );
+ int i = 0;
+ char key[ 25 ];
+
+ // If the number of existing clones is different, then create/remove as necessary
+ if ( existing != clones )
+ {
+ if ( existing < clones )
+ {
+ for ( i = existing; i < clones; i ++ )
+ {
+ mlt_producer clone = mlt_producer_clone( parent );
+ sprintf( key, "_clone.%d", i );
+ mlt_properties_set_data( properties, key, clone, 0, ( mlt_destructor )mlt_producer_close, NULL );
+ }
+ }
+ else
+ {
+ for ( i = clones; i < existing; i ++ )
+ {
+ sprintf( key, "_clone.%d", i );
+ mlt_properties_set_data( properties, key, NULL, 0, NULL, NULL );
+ }
+ }