]> git.sesse.net Git - mlt/blobdiff - src/miracle/miracle_unit.c
miracle part 1
[mlt] / src / miracle / miracle_unit.c
index bc8adcfb13b26d4e72c1d76e4aa5817eff1b72dd..31c01cf7cdb869a7be8a787a3caf5f2e0978e217 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * dvunit.c -- DV Transmission Unit Implementation
+ * miracle_unit.c -- DV Transmission Unit Implementation
  * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
  * Author: Dan Dennedy <dan@dennedy.org>
  *
 #include <errno.h>
 #include <signal.h>
 
-#include <libdv/dv1394.h>
-#include <libraw1394/raw1394.h>
-#include <libavc1394/avc1394_vcr.h>
 #include <sys/mman.h>
 
-#include "dvunit.h"
-#include "dvframe.h"
-#include "dvframepool.h"
-#include "dvqueue.h"
-#include "dvpump.h"
-#include "dverror.h"
-#include "dvplayer.h"
-#include "raw1394util.h"
-#include "log.h"
-#include "dvlocal.h"
+#include "miracle_unit.h"
+#include "miracle_log.h"
+#include "miracle_local.h"
+
+#include <framework/mlt.h>
 
 /* Forward references */
-static void dv_unit_status_communicate( dv_unit );
+static void miracle_unit_status_communicate( miracle_unit );
+
+/** Allocate a new DV transmission unit.
+
+    \return A new miracle_unit handle.
+*/
+
+miracle_unit miracle_unit_init( int index, char *constructor )
+{
+       miracle_unit this = NULL;
+       mlt_consumer consumer = NULL;
+
+       char *id = strdup( constructor );
+       char *arg = strchr( id, ':' );
+
+       if ( arg != NULL )
+               *arg ++ = '\0';
 
-/** dv1394 device file names based upon devfs default names. */
+       consumer = mlt_factory_consumer( id, arg );
 
-static char *devices[4][4] = {
+       if ( consumer != NULL )
        {
-       "/dev/ieee1394/dv/host0/NTSC/in",
-       "/dev/ieee1394/dv/host0/NTSC/out",
-       "/dev/ieee1394/dv/host0/PAL/in",
-       "/dev/ieee1394/dv/host0/PAL/out",
-       },{
-       "/dev/ieee1394/dv/host1/NTSC/in",
-       "/dev/ieee1394/dv/host1/NTSC/out",
-       "/dev/ieee1394/dv/host1/PAL/in",
-       "/dev/ieee1394/dv/host1/PAL/out"
-       },{
-       "/dev/ieee1394/dv/host2/NTSC/in",
-       "/dev/ieee1394/dv/host2/NTSC/out",
-       "/dev/ieee1394/dv/host2/PAL/in",
-       "/dev/ieee1394/dv/host2/PAL/out"
-       },{
-       "/dev/ieee1394/dv/host3/NTSC/in",
-       "/dev/ieee1394/dv/host3/NTSC/out",
-       "/dev/ieee1394/dv/host3/PAL/in",
-       "/dev/ieee1394/dv/host3/PAL/out"
+               mlt_playlist playlist = mlt_playlist_init( );
+               this = calloc( sizeof( miracle_unit_t ), 1 );
+               this->properties = mlt_properties_new( );
+               this->producers = mlt_properties_new( );
+               mlt_properties_init( this->properties, this );
+               mlt_properties_set_int( this->properties, "unit", index );
+               mlt_properties_set_int( this->properties, "generation", 0 );
+               mlt_properties_set( this->properties, "constructor", constructor );
+               mlt_properties_set( this->properties, "id", id );
+               mlt_properties_set( this->properties, "arg", arg );
+               mlt_properties_set_data( this->properties, "consumer", consumer, 0, ( mlt_destructor )mlt_consumer_close, NULL );
+               mlt_properties_set_data( this->properties, "playlist", playlist, 0, ( mlt_destructor )mlt_playlist_close, NULL );
+               mlt_consumer_connect( consumer, mlt_playlist_service( playlist ) );
        }
-};
 
-static int device_count[4] = {0,0,0,0};
-
-/** Allocate a new DV transmission unit.
+       return this;
+}
 
-    \param dv1394d_fd The file descriptor of a dv1394 device file to 
-                      use for transmission.
-    \param guid The node GUID of the receiving device.
-    \param channel The channel to use for transmission.
-    \return A new dv_unit handle.
+/** Communicate the current status to all threads waiting on the notifier.
 */
 
-dv_unit dv_unit_init( octlet_t guid, int channel )
+static void miracle_unit_status_communicate( miracle_unit unit )
 {
-       dv_unit unit = malloc( sizeof( dv_unit_t ) );
        if ( unit != NULL )
        {
-               int node_id;
-               
-               memset( unit, 0, sizeof( dv_unit_t ) );
-               unit->guid = guid;
-               unit->buffer_size = 25;
-               unit->is_terminated = 1;
-               unit->channel = channel;
-               unit->dv1394_fd = -1;
-               unit->n_frames = DV1394_MAX_FRAMES / 2;
-               unit->n_fill = 1;
-
-               /* get a raw1394 handle for plug control */
-               if ( ( node_id = raw1394_find_node( &(unit->raw1394), guid ) ) != -1 )
-               {
-                       if ( dv_unit_online( unit ) == 1 )
-                               dv1394d_log( LOG_DEBUG, "Added online unit with GUID %08x%08x", 
-                                       (quadlet_t) (unit->guid>>32), (quadlet_t) (unit->guid & 0xffffffff) );
-                       else
-                       {
-                               dv_unit_close( unit );
-                               unit = NULL;
-                       }
-               }
-               else
+               mlt_properties properties = unit->properties;
+               char *root_dir = mlt_properties_get( properties, "root" );
+               valerie_notifier notifier = mlt_properties_get_data( properties, "notifier", NULL );
+               valerie_status_t status;
+
+               if ( root_dir != NULL && notifier != NULL )
                {
-                       dv1394d_log( LOG_DEBUG, "Added offline unit with GUID %08x%08x", 
-                               (quadlet_t) (unit->guid>>32), (quadlet_t) (unit->guid & 0xffffffff) );
+                       if ( miracle_unit_get_status( unit, &status ) == 0 )
+                               /* if ( !( ( status.status == unit_playing || status.status == unit_paused ) &&
+                                               strcmp( status.clip, "" ) && 
+                                       !strcmp( status.tail_clip, "" ) && 
+                                               status.position == 0 && 
+                                               status.in == 0 && 
+                                               status.out == 0 ) ) */
+                                       valerie_notifier_put( notifier, &status );
                }
        }
-       return unit;
 }
 
-/** Allow stdin to feed the unit (redundant now that senddv has been dropped).
+/** Set the notifier info
 */
 
-void dv_unit_allow_stdin( dv_unit unit, int flag )
+void miracle_unit_set_notifier( miracle_unit this, valerie_notifier notifier, char *root_dir )
 {
-       unit->allow_stdin = flag;
+       mlt_properties properties = this->properties;
+       mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+       mlt_properties playlist_properties = mlt_playlist_properties( playlist );
+
+       mlt_properties_set( properties, "root", root_dir );
+       mlt_properties_set_data( properties, "notifier", notifier, 0, NULL, NULL );
+       mlt_properties_set_data( playlist_properties, "notifier_arg", this, 0, NULL, NULL );
+       mlt_properties_set_data( playlist_properties, "notifier", miracle_unit_status_communicate, 0, NULL, NULL );
+
+       miracle_unit_status_communicate( this );
 }
 
-/** Override the default buffer/pump size - this must be done prior to the pumps
-       creation.
+/** Create or locate a producer for the file specified.
 */
 
-void dv_unit_set_buffer_size( dv_unit unit, int size )
+static mlt_producer create_producer( miracle_unit unit, char *file )
 {
-       if ( size > 0 )
+       // Get the unit properties
+       mlt_properties properties = unit->producers;
+
+       // Check if we already have loaded this file
+       mlt_producer result = mlt_properties_get_data( properties, file, NULL );
+
+       if ( result == NULL )
        {
-               if ( unit->pump == NULL )
-                       unit->buffer_size = size;
-               else
-                       unit->buffer_size = dv_pump_resize( unit->pump, size );
+               // 1st Line preferences
+               if ( strstr( file, ".mpg" ) )
+                       result = mlt_factory_producer( "mcmpeg", file );
+               else if ( strstr( file, ".mpeg" ) )
+                       result = mlt_factory_producer( "mcmpeg", file );
+               else if ( strstr( file, ".dv" ) )
+                       result = mlt_factory_producer( "mcdv", file );
+               else if ( strstr( file, ".dif" ) )
+                       result = mlt_factory_producer( "mcdv", file );
+               else if ( strstr( file, ".jpg" ) )
+                       result = mlt_factory_producer( "pixbuf", file );
+               else if ( strstr( file, ".JPG" ) )
+                       result = mlt_factory_producer( "pixbuf", file );
+               else if ( strstr( file, ".jpeg" ) )
+                       result = mlt_factory_producer( "pixbuf", file );
+               else if ( strstr( file, ".png" ) )
+                       result = mlt_factory_producer( "pixbuf", file );
+       
+               // 2nd Line fallbacks
+               if ( result == NULL && strstr( file, ".dv" ) )
+                       result = mlt_factory_producer( "libdv", file );
+               else if ( result == NULL && strstr( file, ".dif" ) )
+                       result = mlt_factory_producer( "libdv", file );
+       
+               // 3rd line fallbacks 
+               if ( result == NULL )
+                       result = mlt_factory_producer( "ffmpeg", file );
+
+               // Now store the result
+               mlt_properties_set_data( properties, file, result, 0, ( mlt_destructor )mlt_producer_close, NULL );
        }
-}
 
-int dv_unit_get_buffer_size( dv_unit unit )
-{
-       return unit->buffer_size;
+       return result;
 }
 
-void dv_unit_set_n_frames( dv_unit unit, int size )
-{
-       if ( size > 0 && size <= DV1394_MAX_FRAMES / 2 )
-               unit->n_frames = size;
-}
+/** Update the generation count.
+*/
 
-int dv_unit_get_n_frames( dv_unit unit )
+static void update_generation( miracle_unit unit )
 {
-       return unit->n_frames;
+       mlt_properties properties = unit->properties;
+       int generation = mlt_properties_get_int( properties, "generation" );
+       mlt_properties_set_int( properties, "generation", ++ generation );
 }
 
-void dv_unit_set_n_fill( dv_unit unit, int size )
+static void clear_unit( miracle_unit unit )
 {
-       unit->n_fill = size;
-}
+       mlt_properties properties = unit->properties;
+       mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+       mlt_producer producer = mlt_playlist_producer( playlist );
 
-int dv_unit_get_n_fill( dv_unit unit )
-{
-       return unit->n_fill;
-}
+       mlt_playlist_clear( playlist );
+       mlt_producer_seek( producer, 0 );
 
-/** Set the notifier info
-*/
+       if ( unit->old_producers != NULL )
+               mlt_properties_close( unit->old_producers );
+       unit->old_producers = unit->producers;
+       unit->producers = mlt_properties_new( );
 
-void dv_unit_set_notifier( dv_unit this, dv1394_notifier notifier, char *root_dir )
-{
-       this->notifier = notifier;
-       this->root_dir = root_dir;
-       dv_unit_status_communicate( this );
+       update_generation( unit );
 }
 
-/** Communicate the current status to all threads waiting on the notifier.
+/** Generate a report on all loaded clips.
 */
 
-static void dv_unit_status_communicate( dv_unit unit )
+void miracle_unit_report_list( miracle_unit unit, valerie_response response )
 {
-       if ( unit != NULL && unit->notifier != NULL && unit->root_dir != NULL )
+       int i;
+       mlt_properties properties = unit->properties;
+       int generation = mlt_properties_get_int( properties, "generation" );
+       mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+
+       valerie_response_printf( response, 1024, "%d\n", generation );
+               
+       for ( i = 0; i < mlt_playlist_count( playlist ); i ++ )
        {
-               dv1394_status_t status;
-               if ( dv_unit_get_status( unit, &status ) == 0 )
-                       if ( !( ( status.status == unit_playing || status.status == unit_paused ) &&
-                                       strcmp( status.clip, "" ) && 
-                                   !strcmp( status.tail_clip, "" ) && 
-                                       status.position == 0 && 
-                                       status.in == 0 && 
-                                       status.out == 0 ) )
-                               dv1394_notifier_put( unit->notifier, &status );
+               mlt_playlist_clip_info info;
+               mlt_playlist_get_clip_info( playlist , &info, i );
+               valerie_response_printf( response, 10240, "%d \"%s\" %e %e %e %e %.2f\n", 
+                                                                i, info.resource, info.in, info.out, info.playtime, info.length, info.fps );
        }
 }
 
 /** Load a clip into the unit clearing existing play list.
 
     \todo error handling
-    \param unit A dv_unit handle.
+    \param unit A miracle_unit handle.
     \param clip The absolute file name of the clip to load.
     \param in   The starting frame (-1 for 0)
        \param out  The ending frame (-1 for maximum)
 */
 
-dv_error_code dv_unit_load( dv_unit unit, const char *clip, long in, long out, int flush )
+valerie_error_code miracle_unit_load( miracle_unit unit, char *clip, double in, double out, int flush )
 {
-       dv_player player = dv_unit_get_dv_player( unit );
-       dv_error_code error = dv_player_get_error( player );
-       if ( error == dv_pump_ok )
+       // Have to clear the unit first
+       clear_unit( unit );
+
+       // Now try to create an producer
+       mlt_producer instance = create_producer( unit, clip );
+
+       if ( instance != NULL )
        {
-               error = dv_player_replace_file( player, (char*) clip, in, out, flush );
-               dv1394d_log( LOG_DEBUG, "loaded clip %s", clip );
-               if ( unit->is_terminated )
-                       dv_unit_status_communicate( unit );
+               mlt_properties properties = unit->properties;
+               mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+               mlt_playlist_append_io( playlist, instance, in, out );
+               miracle_log( LOG_DEBUG, "loaded clip %s", clip );
+               miracle_unit_status_communicate( unit );
+               return valerie_ok;
        }
-       return error;
+
+       return valerie_invalid_file;
 }
 
-dv_error_code dv_unit_insert( dv_unit unit, const char *clip, int index, long in, long out )
+valerie_error_code miracle_unit_insert( miracle_unit unit, const char *clip, int index, double in, double out )
 {
-       dv_player player = dv_unit_get_dv_player( unit );
-       dv_error_code error = dv_player_get_error( player );
+       /*
+       dv_player player = miracle_unit_get_dv_player( unit );
+       valerie_error_code error = dv_player_get_error( player );
        if ( error == dv_pump_ok )
        {
                error = dv_player_insert_file( player, (char*) clip, index, in, out );
                dv1394d_log( LOG_DEBUG, "inserted clip %s", clip );
                if ( unit->is_terminated )
-                       dv_unit_status_communicate( unit );
+                       miracle_unit_status_communicate( unit );
        }
        return error;
+       */
+       return valerie_ok;
 }
 
-dv_error_code dv_unit_remove( dv_unit unit, int index )
+valerie_error_code miracle_unit_remove( miracle_unit unit, int index )
 {
-       dv_player player = dv_unit_get_dv_player( unit );
-       dv_error_code error = dv_player_get_error( player );
+       /*
+       dv_player player = miracle_unit_get_dv_player( unit );
+       valerie_error_code error = dv_player_get_error( player );
        if ( error == dv_pump_ok )
        {
                error = dv_player_remove_clip( player, index );
                dv1394d_log( LOG_DEBUG, "removed clip %d", index );
                if ( unit->is_terminated )
-                       dv_unit_status_communicate( unit );
+                       miracle_unit_status_communicate( unit );
        }
        return error;
+       */
+       return valerie_ok;
 }
 
-dv_error_code dv_unit_clean( dv_unit unit )
+valerie_error_code miracle_unit_clean( miracle_unit unit )
 {
-       dv_player player = dv_unit_get_dv_player( unit );
-       dv_error_code error = dv_player_get_error( player );
-       if ( error == dv_pump_ok )
-       {
-               error = dv_player_clean( player );
-               dv1394d_log( LOG_DEBUG, "Cleaned playlist" );
-               if ( unit->is_terminated )
-                       dv_unit_status_communicate( unit );
-       }
-       return error;
+       clear_unit( unit );
+       miracle_log( LOG_DEBUG, "Cleaned playlist" );
+       return valerie_ok;
 }
 
-dv_error_code dv_unit_move( dv_unit unit, int src, int dest )
+valerie_error_code miracle_unit_move( miracle_unit unit, int src, int dest )
 {
-       dv_player player = dv_unit_get_dv_player( unit );
-       dv_error_code error = dv_player_get_error( player );
+       /*
+       dv_player player = miracle_unit_get_dv_player( unit );
+       valerie_error_code error = dv_player_get_error( player );
        if ( error == dv_pump_ok )
        {
                error = dv_player_move_clip( player, src, dest );
                dv1394d_log( LOG_DEBUG, "moved clip %d to %d", src, dest );
                if ( unit->is_terminated )
-                       dv_unit_status_communicate( unit );
+                       miracle_unit_status_communicate( unit );
        }
        return error;
+       */
+       return valerie_ok;
 }
 
 /** Add a clip to the unit play list.
 
     \todo error handling
-    \param unit A dv_unit handle.
+    \param unit A miracle_unit handle.
     \param clip The absolute file name of the clip to load.
     \param in   The starting frame (-1 for 0)
        \param out  The ending frame (-1 for maximum)
 */
 
-dv_error_code dv_unit_append( dv_unit unit, const char *clip, long in, long out )
+valerie_error_code miracle_unit_append( miracle_unit unit, char *clip, double in, double out )
 {
-       dv_player player = dv_unit_get_dv_player( unit );
-       dv_error_code error = dv_player_add_file( player, (char*) clip, in, out );
-       dv_unit_status_communicate( unit );
-       return error;
-}
+       mlt_producer instance = create_producer( unit, clip );
 
-void *output_cleanup( void *arg )
-{
-       dv_unit unit = arg;
-       if ( unit != NULL && unit->mmap != NULL )
+       if ( instance != NULL )
        {
-               unit->is_terminated = 1;
-               dv_unit_status_communicate( unit );
-               munmap( unit->mmap, unit->mmap_length );
-               /* this actually stops transmission as opposed to allowing the 
-                  last frame to loop in the OHCI DMA context. */
-               ioctl( unit->dv1394_fd, DV1394_SHUTDOWN, NULL );
+               mlt_properties properties = unit->properties;
+               mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+               mlt_playlist_append_io( playlist, instance, in, out );
+               miracle_log( LOG_DEBUG, "appended clip %s", clip );
+               miracle_unit_status_communicate( unit );
+               return valerie_ok;
        }
 
-       return NULL;
-}
-
-/** The dv1394 transmission thread.
-
-    \param arg A dv_unit handle.
-*/
-
-static void *output( void *arg )
-{
-       dv_unit unit = arg;
-       dv_frame frames[ DV1394_MAX_FRAMES ];
-       int frames_dropped = 0; /* count of total frames dropped (repeated) */
-       struct dv1394_status status;
-       char errstr[64];
-       int n_fill = unit->n_fill;
-       int n_frames = unit->n_frames;
-       
-       /* Determine the number of frames to wait for/fill on each iteration */
-       if ( n_fill < 1 )
-               n_fill = 1;
-       else if ( n_fill > unit->n_frames )
-               n_fill = n_frames / 2;
-
-       unit->mmap = mmap( NULL,unit->mmap_length,PROT_WRITE,MAP_SHARED,unit->dv1394_fd,0 );
-       if ( unit->mmap == MAP_FAILED || unit->mmap == NULL )
-       {
-               perror( "mmap" );
-               return NULL;
-       }
-
-       pthread_cleanup_push( output_cleanup, (void *)arg );
-
-       while ( dv_pump_get_available_output_count( unit->pump ) || 
-               !( dv_unit_has_terminated( unit ) || dv_pump_has_terminated( unit->pump) ) )
-       {
-               int available = 0;
-
-               if ( ioctl( unit->dv1394_fd, DV1394_WAIT_FRAMES, n_fill ) < 0)
-                       perror( "DV1394_WAIT_FRAMES" );
-
-               pthread_testcancel();
-
-               /* update the status for the next iteration and detect dropped frames */
-               if ( ioctl( unit->dv1394_fd, DV1394_GET_STATUS, &status ) >= 0)
-               {
-                       pthread_testcancel();
-
-                       /*
-                       printf( "dv1394 status: active=%02d, #clear=%02d, first clear=%02d\n", 
-                               status.active_frame, status.n_clear_frames, status.first_clear_frame);
-                       */
-               
-                       /* report dropped frames */
-                       if( status.dropped_frames > 0 )
-                       {
-                               frames_dropped += status.dropped_frames;
-                               dv1394d_log( LOG_WARNING, "dv1394 repeated %d frames with %d available.", 
-                                                        status.dropped_frames, dv_pump_get_available_output_count( unit->pump ) );
-                       }
-
-                       available = dv_pump_get_output_block( unit->pump, (void **)frames, n_fill );
-
-                       dv_unit_status_communicate( unit );
-                       
-                       /* The only time we get 0 frames is when the unit is being stopped. */
-                       if ( available != 0 )
-                       {
-                               int size = dv_frame_size( frames[ 0 ] );
-                               int pos = status.first_clear_frame;
-                               int index = 0;
-
-                               for ( index = 0; index < available; index ++ )
-                                       memcpy( unit->mmap + ( ( pos + index ) % n_frames ) * size, dv_frame_data( frames[ index ] ), size );
-
-                               if ( ioctl( unit->dv1394_fd, DV1394_SUBMIT_FRAMES, available ) >= 0)
-                               {
-                                       for ( index = 0; index < available - 1; index ++ )
-                                       {
-                                               dv_frame_clear_error( frames[ index ] );
-                                               dv_frame_id_clear( dv_frame_get_id( frames[ index ] ) );
-                                       }                       
-                                       dv_pump_return_output_block( unit->pump );
-                                       pthread_testcancel();
-                               }
-                               else
-                               {
-                                       dv1394d_log( LOG_ERR, "failed to write frames to dv1394: %s.", strerror_r( errno, errstr, 63 ) );
-                                       dv_pump_terminate( unit->pump );
-                                       dv_pump_flush( unit->pump );
-                                       pthread_testcancel();
-                               }
-                       }
-               }
-               else
-               {
-                       dv1394d_log( LOG_ERR, "failed to get dv1394 status: %s.", strerror_r( errno, errstr, 63 ) );
-                       dv_pump_return_used_output( unit->pump );
-               }
-       }
-
-       if ( frames_dropped > 0 )
-               dv1394d_log( LOG_WARNING, "dv1394 repeated %d frames total during this transmission.", frames_dropped );
-
-       pthread_cleanup_pop( 1 );
-
-       return NULL;
+       return valerie_invalid_file;
 }
 
 /** Start playing the clip.
@@ -428,317 +341,92 @@ static void *output( void *arg )
     Start a dv-pump and commence dv1394 transmission.
 
     \todo error handling
-    \param unit A dv_unit handle.
+    \param unit A miracle_unit handle.
     \param speed An integer that specifies the playback rate as a
                  percentage multiplied by 100.
 */
 
-void dv_unit_play( dv_unit_t *unit, int speed )
+void miracle_unit_play( miracle_unit_t *unit, int speed )
 {
-       dv_player player = dv_unit_get_dv_player( unit );
-
-       if ( unit->is_terminated == 1 && ( dv_player_get_total_frames( player ) > 0 || unit->allow_stdin ) )
-       {
-               int retval;
-               dv_frame frame = NULL;
-               struct dv1394_init setup =
-               {
-                       api_version: DV1394_API_VERSION,
-                       channel: unit->channel,
-                       /* this only sets the *requested* size of the ringbuffer,
-                          in frames */ 
-                       n_frames: unit->n_frames,
-                       /* we set the format later */
-                       cip_n: unit->dv1394_cip_n,
-                       cip_d: unit->dv1394_cip_d,
-                       syt_offset: unit->dv1394_syt_offset
-               };
-               pthread_attr_t attr;
-
-               if ( unit->in == NULL )
-               {
-                       if ( !unit->allow_stdin || dv_player_get_total_frames( player ) != 0 )
-                               unit->in = dv_player_get_dv_input( player );
-                       else
-                               unit->in = dv_input_init( unit->pump );
-               }
-               else
-               {
-                       dv_input_join_thread( unit->in );
-                       pthread_join( unit->out, NULL );
-               }
-
-               unit->is_terminated = 0;
-               dv_pump_restart( unit->pump );
-               dv_input_start_thread( unit->in );
-               dv_player_set_speed( player, (double) speed/1000.0 );
-
-               /* first we read a little data to see if this is PAL or NTSC
-                  so we can initialize dv1394 properly */
-               frame = dv_pump_get_available_output( unit->pump );
-       
-               /* initialize dv1394 */
-               setup.format = dv_frame_is_pal(frame) ? DV1394_PAL : DV1394_NTSC;
-               
-               retval = ioctl( unit->dv1394_fd, DV1394_INIT, &setup );
-               if (retval < 0)
-               {
-                       perror( "DV1394_INIT" );
-                       return;
-               }
-
-               unit->mmap_length = unit->n_frames * dv_frame_size( frame );
-
-               pthread_attr_init( &attr );
-               pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
-               pthread_attr_setinheritsched( &attr, PTHREAD_INHERIT_SCHED );
-               pthread_create( &unit->out, &attr, output, unit );
-       }
-       else 
-       {
-               dv_player_set_speed( player, (double) speed/1000.0 );
-       }
-       dv_unit_status_communicate( unit );
+       mlt_properties properties = unit->properties;
+       mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+       mlt_producer producer = mlt_playlist_producer( playlist );
+       mlt_producer_set_speed( producer, ( double )speed / 1000 );
+       miracle_unit_status_communicate( unit );
 }
 
 /** Stop playback.
 
     Terminates the dv_pump and halts dv1394 transmission.
 
-    \param unit A dv_unit handle.
+    \param unit A miracle_unit handle.
 */
 
-void dv_unit_terminate( dv_unit unit )
+void miracle_unit_terminate( miracle_unit unit )
 {
-       unit->is_terminated = 1;
-       if ( unit->pump != NULL )
-       {
-               dv_pump_terminate( unit->pump );
-               dv_pump_flush( unit->pump );
-       }
 }
 
 /** Query the status of unit playback.
 
-    \param unit A dv_unit handle.
+    \param unit A miracle_unit handle.
     \return 1 if the unit is not playing, 0 if playing.
 */
 
-int dv_unit_has_terminated( dv_unit unit )
+int miracle_unit_has_terminated( miracle_unit unit )
 {
-       return unit->is_terminated;
-}
-
-/** Get the dv_player from the dv_unit.
-
-    \param unit A dv_unit handle.
-    \return A dv_player handle.
-*/
-
-dv_player dv_unit_get_dv_player( dv_unit unit )
-{
-       if ( unit != NULL )
-       {
-               if ( unit->pump == NULL )
-               {
-                       unit->pump = dv_pump_init( unit->buffer_size );
-                       if ( unit->pump != NULL )
-                               unit->player = dv_player_init( unit->pump );
-               }
-               return unit->player;
-       }
-       return NULL;
+       return 0;
 }
 
-
 /** Transfer the currently loaded clip to another unit
 */
 
-int dv_unit_transfer( dv_unit dest_unit, dv_unit src_unit )
+int miracle_unit_transfer( miracle_unit dest_unit, miracle_unit src_unit )
 {
-       dv_player src_player = dv_unit_get_dv_player( src_unit );
-       dv_player dest_player = dv_unit_get_dv_player( dest_unit );
-
-       if( dest_player != NULL && src_player != NULL )
-               dv_player_replace_player( dest_player, src_player );
-
        return 0;
 }
 
-/** Get the guid associated to this unit.
-*/
-
-octlet_t dv_unit_get_guid( dv_unit unit )
-{
-       return unit->guid;
-}
-
-/** Get the node id associated to this unit.
-*/
-
-int dv_unit_get_nodeid( dv_unit unit )
-{
-       return (unit->node_id & 0x3f);
-}
-
-/** Get the channel associated to this unit.
-*/
-
-int dv_unit_get_channel( dv_unit unit )
-{
-       return (unit->channel);
-}
-
-/** Turn unit online.
-*/
-
-int dv_unit_online( dv_unit unit )
-{
-       int result = 0;
-       int port, node_id;
-       
-       if ( unit->raw1394 != NULL )
-               raw1394_close( unit->raw1394 );
-       
-       node_id = raw1394_find_node( &(unit->raw1394), unit->guid );
-       if ( node_id != -1 )
-       {
-               unit->node_id = 0xffc0 | node_id;       
-               port = dv_unit_get_port( unit );
-       
-               unit->dv1394_fd = open( devices[ port ][ device_count[port] ], O_RDWR );
-               if ( unit->dv1394_fd < 0 )
-               {
-                       dv1394d_log( LOG_ERR, "failed to open dv1394 device - %s\n", devices[ port ][ device_count[port] ] );
-                       dv_unit_close( unit );
-               }
-               else
-               {
-                       device_count[ port ] ++;
-                       if ( establish_p2p_connection( unit->raw1394, unit->node_id, (unsigned int *) &(unit->channel) ) )
-                       {
-                               avc1394_vcr_record( unit->raw1394, unit->node_id );
-                               unit->online = 1;
-                               dv_unit_status_communicate( unit );
-                               result = 1;
-                       }
-               }
-       }
-                               
-       return result;
-}
-
-/** Turn unit offline.
-*/
-
-void dv_unit_offline( dv_unit unit )
-{
-       if ( unit->online == 1 )
-       {
-               if ( unit->is_terminated == 0 )
-                       dv_unit_terminate( unit );
-               unit->online = 0;
-               if ( unit->raw1394 != NULL )
-               {
-                       avc1394_vcr_stop( unit->raw1394, unit->node_id );
-                       break_p2p_connection( unit->raw1394, unit->node_id, unit->channel );
-               }
-               if ( unit->dv1394_fd > -1 )
-               {
-                       close( unit->dv1394_fd );
-                       device_count[ dv_unit_get_port( unit ) ] --;
-               }
-               dv_unit_status_communicate( unit );
-               dv1394d_log( LOG_DEBUG, "Unit with GUID %08x%08x is now offline.",
-                       (quadlet_t) (unit->guid>>32), (quadlet_t) (unit->guid & 0xffffffff) );
-       }
-}
-
 /** Determine if unit is offline.
 */
 
-int dv_unit_is_offline( dv_unit unit )
+int miracle_unit_is_offline( miracle_unit unit )
 {
-       return (unit->online == 0);
+       return 0;
 }
 
 /** Obtain the status for a given unit
 */
 
-int dv_unit_get_status( dv_unit unit, dv1394_status status )
+int miracle_unit_get_status( miracle_unit unit, valerie_status status )
 {
-       int error = -1;
+       int error = unit == NULL;
 
-       memset( status, 0, sizeof( dv1394_status_t ) );
+       memset( status, 0, sizeof( valerie_status_t ) );
 
-       if ( unit != NULL )
+       if ( !error )
        {
-               dv_player player = dv_unit_get_dv_player( unit );
+               mlt_properties properties = unit->properties;
+               mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+               mlt_producer producer = mlt_playlist_producer( playlist );
+               mlt_producer clip = mlt_playlist_current( playlist );
 
-               error = 0;
+               mlt_playlist_clip_info info;
+               int clip_index = mlt_playlist_current_clip( playlist );
+               mlt_playlist_get_clip_info( playlist, &info, clip_index );
 
-               if ( player != NULL )
+               if ( info.resource != NULL && strcmp( info.resource, "" ) )
                {
-                       dv_frame head = dv_pump_get_head( player->pump );
-                       dv_frame tail = dv_pump_get_tail( player->pump );
-
-                       status->speed = (int)( dv_player_get_speed( player ) * 1000.0 );
-                       status->fps = dv_player_frames_per_second( player, 0 );
-
-                       if ( head != NULL )
-                       {
-                               dv_frame_id id = dv_frame_get_id( head );
-                               if ( id->resource != NULL )
-                               {
-                                       const char *resource = id->resource;
-                                       if ( resource != NULL && unit->root_dir != NULL )
-                                               resource += strlen( unit->root_dir ) - ( unit->root_dir[ strlen( unit->root_dir ) - 1 ] == '/' );
-                                       strncpy( status->clip, resource, sizeof( status->clip ) );
-                               }
-                               else
-                               {
-                                       char *title = dv_player_get_name( player, dv_player_get_clip_containing( player, 0 ), unit->root_dir );
-                                       if ( title != NULL )
-                                               strncpy( status->clip, title, sizeof( status->clip ) );
-                               }
-
-                               status->position = id->relative;
-                               status->in = id->in;
-                               status->out = id->out;
-                               status->length = id->length;
-                               status->seek_flag = id->seek_flag;
-                       }
-                       else
-                       {
-                               char *title = dv_player_get_name( player, dv_player_get_clip_containing( player, 0 ), unit->root_dir );
-                               if ( title != NULL )
-                                       strncpy( status->clip, title, sizeof( status->clip ) );
-                       }
-
-                       if ( tail != NULL )
-                       {
-                               dv_frame_id id = dv_frame_get_id( tail );
-                               const char *resource = id->resource;
-                               if ( resource != NULL && unit->root_dir != NULL )
-                                       resource += strlen( unit->root_dir ) - ( unit->root_dir[ strlen( unit->root_dir ) - 1 ] == '/' );
-                               if ( resource != NULL )
-                                       strncpy( status->tail_clip, resource, sizeof( status->clip ) );
-                               status->tail_position = id->relative;
-                               status->tail_in = id->in;
-                               status->tail_out = id->out;
-                               status->tail_length = id->length;
-                       }
-                       
-                       status->generation = player->generation;
-                       status->clip_index = dv_unit_get_current_clip( unit );
+                       strncpy( status->clip, info.resource, sizeof( status->clip ) );
+                       status->speed = (int)( mlt_producer_get_speed( producer ) * 1000.0 );
+                       status->fps = mlt_producer_get_fps( producer );
+                       status->in = info.in;
+                       status->out = info.in + info.playtime;
+                       status->position = mlt_producer_position( clip );
+                       status->length = mlt_producer_get_length( clip );
+                       status->seek_flag = 1;
                }
 
-               if ( dv_unit_is_offline( unit ) )
-                       status->status = unit_offline;
-               else if ( !strcmp( status->clip, "" ) )
+               if ( !strcmp( status->clip, "" ) )
                        status->status = unit_not_loaded;
-               else if ( dv_unit_has_terminated( unit ) )
-                       status->status = unit_stopped;
                else if ( status->speed == 0 )
                        status->status = unit_paused;
                else
@@ -749,7 +437,7 @@ int dv_unit_get_status( dv_unit unit, dv1394_status status )
                status->status = unit_undefined;
        }
 
-       status->unit = unit->unit;
+       status->unit = mlt_properties_get_int( unit->properties, "unit" );
 
        return error;
 }
@@ -757,344 +445,104 @@ int dv_unit_get_status( dv_unit unit, dv1394_status status )
 /** Change position in the playlist.
 */
 
-void dv_unit_change_position( dv_unit unit, int clip, long position )
+void miracle_unit_change_position( miracle_unit unit, int clip, double position )
 {
-       dv_player player = dv_unit_get_dv_player( unit );
-       dv_player_set_clip_position( player, clip, position );
-       dv_unit_status_communicate( unit );
+       miracle_unit_status_communicate( unit );
 }
 
 /** Change speed.
 */
 
-void dv_unit_change_speed( dv_unit unit, int speed )
+void miracle_unit_change_speed( miracle_unit unit, int speed )
 {
-       if ( dv_unit_has_terminated( unit ) )
-               dv_unit_change_position( unit, 0, 0 );
-       else
-               dv_unit_play( unit, speed );
 }
 
-int    dv_unit_get_current_clip( dv_unit unit )
+int    miracle_unit_get_current_clip( miracle_unit unit )
 {
-       dv_player player = dv_unit_get_dv_player( unit );
-       unsigned long position = dv_player_get_position( player );
-       return dv_player_get_clip_containing( player, position );
+       return 0;
 }
 
 /** Set a clip's in point
 */
 
-int dv_unit_set_clip_in( dv_unit unit, int index, long position )
+int miracle_unit_set_clip_in( miracle_unit unit, int index, double position )
 {
        int error = 0;
-       dv_player player = dv_unit_get_dv_player( unit );
-
-       if ( player != NULL )
-       {
-               dv_unit_change_speed( unit, 0 );
-               if ( dv_player_set_in_point( player, index, (unsigned long) position ) == position )
-                       dv_player_set_clip_position( player, index, position );
-               else
-                       error = -2;
-       }
-       else
-       {
-               error = -1;
-       }
-
-       dv_unit_status_communicate( unit );
-
        return error;
-
 }
 
 /** Set a clip's out point.
 */
 
-int dv_unit_set_clip_out( dv_unit unit, int index, long position )
+int miracle_unit_set_clip_out( miracle_unit unit, int index, double position )
 {
        int error = 0;
-       dv_player player = dv_unit_get_dv_player( unit );
-
-       if ( player != NULL )
-       {
-               dv_unit_change_speed( unit, 0 );
-               if ( dv_player_set_out_point( player, index, position ) == position )
-                       dv_player_set_clip_position( player, index, position );
-               else
-                       error = -2;
-       }
-       else
-       {
-               error = -1;
-       }
-
-       dv_unit_status_communicate( unit );
-
        return error;
 }
 
 /** Step by specified position.
 */
 
-void dv_unit_step( dv_unit unit, int offset )
+void miracle_unit_step( miracle_unit unit, double offset )
 {
-       dv_player player = dv_unit_get_dv_player( unit );
-       dv_player_change_position( player, dv_seek_relative, offset );
 }
 
 /** Set the unit's clip mode regarding in and out points.
 */
 
-void dv_unit_set_mode( dv_unit unit, dv_player_clip_mode mode )
-{
-       dv_player player = dv_unit_get_dv_player( unit );
-       if ( player != NULL )
-               dv_player_set_clip_mode( player, mode );
-       dv_unit_status_communicate( unit );
-}
+//void miracle_unit_set_mode( miracle_unit unit, dv_player_clip_mode mode )
+//{
+       //dv_player player = miracle_unit_get_dv_player( unit );
+       //if ( player != NULL )
+               //dv_player_set_clip_mode( player, mode );
+       //miracle_unit_status_communicate( unit );
+//}
 
 /** Get the unit's clip mode regarding in and out points.
 */
 
-dv_player_clip_mode dv_unit_get_mode( dv_unit unit )
-{
-       dv_player player = dv_unit_get_dv_player( unit );
-       return dv_player_get_clip_mode( player );
-}
+//dv_player_clip_mode miracle_unit_get_mode( miracle_unit unit )
+//{
+       //dv_player player = miracle_unit_get_dv_player( unit );
+       //return dv_player_get_clip_mode( player );
+//}
 
 /** Set the unit's clip mode regarding eof handling.
 */
 
-void dv_unit_set_eof_action( dv_unit unit, dv_player_eof_action action )
-{
-       dv_player player = dv_unit_get_dv_player( unit );
-       dv_player_set_eof_action( player, action );
-       dv_unit_status_communicate( unit );
-}
+//void miracle_unit_set_eof_action( miracle_unit unit, dv_player_eof_action action )
+//{
+       //dv_player player = miracle_unit_get_dv_player( unit );
+       //dv_player_set_eof_action( player, action );
+       //miracle_unit_status_communicate( unit );
+//}
 
 /** Get the unit's clip mode regarding eof handling.
 */
 
-dv_player_eof_action dv_unit_get_eof_action( dv_unit unit )
-{
-       dv_player player = dv_unit_get_dv_player( unit );
-       return dv_player_get_eof_action( player );
-}
+//dv_player_eof_action miracle_unit_get_eof_action( miracle_unit unit )
+//{
+       //dv_player player = miracle_unit_get_dv_player( unit );
+       //return dv_player_get_eof_action( player );
+//}
 
 /** Release the unit
 
     \todo error handling
-    \param unit A dv_unit handle.
+    \param unit A miracle_unit handle.
 */
 
-void dv_unit_close( dv_unit unit )
+void miracle_unit_close( miracle_unit unit )
 {
        if ( unit != NULL )
        {
-               dv1394d_log( LOG_DEBUG, "closing unit..." );
-               dv_unit_offline( unit );
-               if ( unit->pump != NULL )
-               {
-                       dv_pump_terminate( unit->pump );
-                       dv_pump_flush( unit->pump );
-                       dv_pump_return_used_output( unit->pump );
-                       dv_input_join_thread( unit->in );
-                       if ( !unit->is_terminated )
-                               pthread_join( unit->out, NULL );
-                       dv_pump_close( unit->pump );
-                       unit->pump = NULL;
-               }
-               raw1394_close( unit->raw1394 );
+               miracle_log( LOG_DEBUG, "closing unit..." );
+               if ( unit->old_producers != NULL )
+                       mlt_properties_close( unit->old_producers );
+               mlt_properties_close( unit->properties );
+               mlt_properties_close( unit->producers );
                free( unit );
-               dv1394d_log( LOG_DEBUG, "... unit closed." );
-       }
-}
-
-/** Get the raw1394 port associated to this unit.
-*/
-
-int dv_unit_get_port( dv_unit unit )
-{
-       if ( unit->raw1394 != NULL )
-               return (int) raw1394_get_userdata( unit->raw1394 );
-       else
-               return -1;
-}
-
-/** Set the dv1394 file descriptor for the unit.
-*/
-
-void dv_unit_set_dv1394_fd( dv_unit unit, int fd )
-{
-       unit->dv1394_fd = fd;
-}
-
-/** Get the dv1394 syt_offset (timestamp latency) property.
-*/
-
-unsigned int dv_unit_get_syt_offset( dv_unit unit )
-{
-       return unit->dv1394_syt_offset;
-}
-
-/** Get the dv1394 cip_n (timing numerator) property.
-*/
-
-unsigned int dv_unit_get_cip_n( dv_unit unit )
-{
-       return unit->dv1394_cip_n;
-}
-
-/** Get the dv1394 cip_d (timing denominator) property.
-*/
-
-unsigned int dv_unit_get_cip_d( dv_unit unit )
-{
-       return unit->dv1394_cip_d;
-}
-
-/** Set the dv1394 syt_offset (timestamp latency) property.
-
-    Stops and restarts the unit if playing.
-*/
-
-void dv_unit_set_syt_offset( dv_unit unit, unsigned int syt_offset )
-{
-       int restart = !unit->is_terminated;
-       int speed = (int)( dv_player_get_speed( dv_unit_get_dv_player(unit) ) * 1000.0 );
-       
-       dv_unit_terminate( unit );
-       unit->dv1394_syt_offset = syt_offset;
-       if ( restart )
-               dv_unit_play( unit, speed );
-}
-       
-/** Set the dv1394 cip_n (timing numerator) property.
-
-    Stops and restarts the unit if playing.
-*/
-
-void dv_unit_set_cip_n( dv_unit unit, unsigned int cip_n )
-{
-       int restart = !unit->is_terminated;
-       int speed = (int)( dv_player_get_speed( dv_unit_get_dv_player(unit) ) * 1000.0 );
-       
-       dv_unit_terminate( unit );
-       unit->dv1394_cip_n = cip_n;
-       if ( restart )
-               dv_unit_play( unit, speed );
-}
-
-/** Set the dv1394 cip_d (timing denominator) property.
-
-    Stops and restarts the unit if playing.
-*/
-
-void dv_unit_set_cip_d( dv_unit unit, unsigned int cip_d )
-{
-       int restart = !unit->is_terminated;
-       int speed = (int)( dv_player_get_speed( dv_unit_get_dv_player(unit) ) * 1000.0 );
-       
-       dv_unit_terminate( unit );
-       unit->dv1394_cip_d = cip_d;
-       if ( restart )
-               dv_unit_play( unit, speed );
-}
-
-/** Terminate, but only the output thread and close dv1394.
-*/
-
-void dv_unit_suspend( dv_unit unit )
-{
-       if ( unit->is_terminated == 0 )
-       {
-               unit->is_terminated = 1;
-               unit->is_suspended = 1;
-               dv_pump_terminate( unit->pump );
-               dv_pump_flush( unit->pump );
-               pthread_cancel( unit->out );
-       }
-       if ( unit->dv1394_fd > -1 )
-       {
-               close( unit->dv1394_fd );
-               device_count[ dv_unit_get_port( unit ) ] --;
+               miracle_log( LOG_DEBUG, "... unit closed." );
        }
-       unit->dv1394_fd = -1;
-       dv_unit_status_communicate( unit );
 }
 
-
-/** Restore unit on the bus, re-open dv1394, start playback if pump is running.
-*/
-
-void dv_unit_restore( dv_unit unit )
-{
-       int result = 0;
-       int port, node_id;
-       
-       if ( unit->raw1394 != NULL )
-               raw1394_close( unit->raw1394 );
-       
-       node_id = raw1394_find_node( &(unit->raw1394), unit->guid );
-       if ( node_id != -1 )
-       {
-               unit->node_id = 0xffc0 | node_id;       
-               port = dv_unit_get_port( unit );
-       
-               unit->dv1394_fd = open( devices[ port ][ device_count[port] ], O_RDWR );
-               if ( unit->dv1394_fd < 0 )
-               {
-                       dv1394d_log( LOG_ERR, "failed to open dv1394 device - %s\n", devices[ port ][ device_count[port] ] );
-                       dv_unit_close( unit );
-               }
-               else
-               {
-                       device_count[ port ] ++;
-                       break_p2p_connection( unit->raw1394, unit->node_id, unit->channel );
-                       if ( establish_p2p_connection( unit->raw1394, unit->node_id, (unsigned int *) &(unit->channel) ) )
-                       {
-                               avc1394_vcr_record( unit->raw1394, unit->node_id );
-                               unit->online = 1;
-                               result = 1;
-                       }
-               }
-       }
-       if ( unit->is_suspended == 1 )
-       {
-               int retval;
-               dv_frame frame = dv_pump_get_available_output( unit->pump );
-               struct dv1394_init setup =
-               {
-                       api_version: DV1394_API_VERSION,
-                       channel: unit->channel,
-                       /* this only sets the *requested* size of the ringbuffer,
-                          in frames */ 
-                       n_frames: unit->n_frames,
-                       format: dv_frame_is_pal(frame) ? DV1394_PAL : DV1394_NTSC,
-                       cip_n: unit->dv1394_cip_n,
-                       cip_d: unit->dv1394_cip_d,
-                       syt_offset: unit->dv1394_syt_offset
-               };
-               pthread_attr_t attr;
-
-               dv_input_join_thread( unit->in );
-               unit->is_terminated = 0;
-               unit->is_suspended = 0;
-               dv_pump_restart( unit->pump );
-               dv_input_start_thread( unit->in );
-               
-               /* initialize dv1394 */
-               retval = ioctl( unit->dv1394_fd, DV1394_INIT, &setup );
-               if ( retval < 0 )
-                       return;
-               
-               pthread_attr_init( &attr );
-               pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
-               pthread_attr_setinheritsched( &attr, PTHREAD_INHERIT_SCHED );
-               /* pthread_attr_setschedpolicy( &attr, SCHED_RR ); */
-               pthread_create( &unit->out, &attr, output, unit );
-       }
-       dv_unit_status_communicate( unit );
-}