adding the rock thrower...
[melted] / src / miracle / miracle_unit.c
index f7d5509..255dad4 100644 (file)
@@ -33,6 +33,7 @@
 #include <string.h>
 #include <errno.h>
 #include <signal.h>
+#include <limits.h>
 
 #include <sys/mman.h>
 
@@ -126,10 +127,15 @@ void miracle_unit_set_notifier( miracle_unit this, valerie_notifier notifier, ch
        miracle_unit_status_communicate( this );
 }
 
+static mlt_producer create_producer( char *file )
+{
+       return mlt_factory_producer( "fezzik", file );
+}
+
 /** Create or locate a producer for the file specified.
 */
 
-static mlt_producer create_producer( miracle_unit unit, char *file )
+static mlt_producer locate_producer( miracle_unit unit, char *file )
 {
        // Get the unit properties
        mlt_properties properties = unit->producers;
@@ -139,36 +145,12 @@ static mlt_producer create_producer( miracle_unit unit, char *file )
 
        if ( result == NULL )
        {
-               // 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 );
+               // Create the producer
+               result = create_producer( file );
 
                // Now store the result
-               mlt_properties_set_data( properties, file, result, 0, ( mlt_destructor )mlt_producer_close, NULL );
+               if ( result != NULL )
+                       mlt_properties_set_data( properties, file, result, 0, ( mlt_destructor )mlt_producer_close, NULL );
        }
 
        return result;
@@ -184,6 +166,9 @@ static void update_generation( miracle_unit unit )
        mlt_properties_set_int( properties, "generation", ++ generation );
 }
 
+/** Wipe all clips on the playlist for this unit.
+*/
+
 static void clear_unit( miracle_unit unit )
 {
        mlt_properties properties = unit->properties;
@@ -217,8 +202,13 @@ void miracle_unit_report_list( miracle_unit unit, valerie_response response )
        {
                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 );
+               valerie_response_printf( response, 10240, "%d \"%s\" %lld %lld %lld %lld %.2f\n", 
+                                                                i, info.resource, 
+                                                                info.frame_in, 
+                                                                info.frame_out,
+                                                                info.frame_count, 
+                                                                info.length, 
+                                                                info.fps );
        }
 }
 
@@ -231,17 +221,16 @@ void miracle_unit_report_list( miracle_unit unit, valerie_response response )
        \param out  The ending frame (-1 for maximum)
 */
 
-valerie_error_code miracle_unit_load( miracle_unit unit, char *clip, double in, double out, int flush )
+valerie_error_code miracle_unit_load( miracle_unit unit, char *clip, int64_t in, int64_t out, int flush )
 {
-       // Have to clear the unit first
-       clear_unit( unit );
-
        // Now try to create an producer
-       mlt_producer instance = create_producer( unit, clip );
+       mlt_producer instance = create_producer( clip );
 
        if ( instance != NULL )
        {
+               clear_unit( unit );
                mlt_properties properties = unit->properties;
+               mlt_properties_set_data( unit->producers, clip, instance, 0, ( mlt_destructor )mlt_producer_close, NULL );
                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 );
@@ -252,9 +241,9 @@ valerie_error_code miracle_unit_load( miracle_unit unit, char *clip, double in,
        return valerie_invalid_file;
 }
 
-valerie_error_code miracle_unit_insert( miracle_unit unit, char *clip, int index, double in, double out )
+valerie_error_code miracle_unit_insert( miracle_unit unit, char *clip, int index, int64_t in, int64_t out )
 {
-       mlt_producer instance = create_producer( unit, clip );
+       mlt_producer instance = locate_producer( unit, clip );
 
        if ( instance != NULL )
        {
@@ -262,6 +251,7 @@ valerie_error_code miracle_unit_insert( miracle_unit unit, char *clip, int index
                mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
                mlt_playlist_insert( playlist, instance, index, in, out );
                miracle_log( LOG_DEBUG, "inserted clip %s at %d", clip, index );
+               update_generation( unit );
                miracle_unit_status_communicate( unit );
                return valerie_ok;
        }
@@ -275,6 +265,7 @@ valerie_error_code miracle_unit_remove( miracle_unit unit, int index )
        mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
        mlt_playlist_remove( playlist, index );
        miracle_log( LOG_DEBUG, "removed clip at %d", index );
+       update_generation( unit );
        miracle_unit_status_communicate( unit );
        return valerie_ok;
 }
@@ -283,6 +274,7 @@ valerie_error_code miracle_unit_clean( miracle_unit unit )
 {
        clear_unit( unit );
        miracle_log( LOG_DEBUG, "Cleaned playlist" );
+       miracle_unit_status_communicate( unit );
        return valerie_ok;
 }
 
@@ -292,6 +284,7 @@ valerie_error_code miracle_unit_move( miracle_unit unit, int src, int dest )
        mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
        mlt_playlist_move( playlist, src, dest );
        miracle_log( LOG_DEBUG, "moved clip %d to %d", src, dest );
+       update_generation( unit );
        miracle_unit_status_communicate( unit );
        return valerie_ok;
 }
@@ -305,9 +298,9 @@ valerie_error_code miracle_unit_move( miracle_unit unit, int src, int dest )
        \param out  The ending frame (-1 for maximum)
 */
 
-valerie_error_code miracle_unit_append( miracle_unit unit, char *clip, double in, double out )
+valerie_error_code miracle_unit_append( miracle_unit unit, char *clip, int64_t in, int64_t out )
 {
-       mlt_producer instance = create_producer( unit, clip );
+       mlt_producer instance = locate_producer( unit, clip );
 
        if ( instance != NULL )
        {
@@ -315,6 +308,7 @@ valerie_error_code miracle_unit_append( miracle_unit unit, char *clip, double in
                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 );
+               update_generation( unit );
                miracle_unit_status_communicate( unit );
                return valerie_ok;
        }
@@ -322,9 +316,7 @@ valerie_error_code miracle_unit_append( miracle_unit unit, char *clip, double in
        return valerie_invalid_file;
 }
 
-/** Start playing the clip.
-
-    Start a dv-pump and commence dv1394 transmission.
+/** Start playing the unit.
 
     \todo error handling
     \param unit A miracle_unit handle.
@@ -337,7 +329,9 @@ void miracle_unit_play( miracle_unit_t *unit, int speed )
        mlt_properties properties = unit->properties;
        mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
        mlt_producer producer = mlt_playlist_producer( playlist );
+       mlt_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL );
        mlt_producer_set_speed( producer, ( double )speed / 1000 );
+       mlt_consumer_start( consumer );
        miracle_unit_status_communicate( unit );
 }
 
@@ -350,6 +344,9 @@ void miracle_unit_play( miracle_unit_t *unit, int speed )
 
 void miracle_unit_terminate( miracle_unit unit )
 {
+       mlt_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL );
+       mlt_consumer_stop( consumer );
+       miracle_unit_status_communicate( unit );
 }
 
 /** Query the status of unit playback.
@@ -360,7 +357,8 @@ void miracle_unit_terminate( miracle_unit unit )
 
 int miracle_unit_has_terminated( miracle_unit unit )
 {
-       return 0;
+       mlt_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL );
+       return mlt_consumer_is_stopped( consumer );
 }
 
 /** Transfer the currently loaded clip to another unit
@@ -404,14 +402,24 @@ int miracle_unit_get_status( miracle_unit unit, valerie_status status )
                        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->in = info.frame_in;
+                       status->out = info.frame_out;
                        status->position = mlt_producer_position( clip );
                        status->length = mlt_producer_get_length( clip );
+                       strncpy( status->tail_clip, info.resource, sizeof( status->tail_clip ) );
+                       status->tail_in = info.frame_in;
+                       status->tail_out = info.frame_out;
+                       status->tail_position = mlt_producer_position( clip );
+                       status->tail_length = mlt_producer_get_length( clip );
+                       status->clip_index = mlt_playlist_current_clip( playlist );
                        status->seek_flag = 1;
                }
 
-               if ( !strcmp( status->clip, "" ) )
+               status->generation = mlt_properties_get_int( properties, "generation" );
+
+               if ( miracle_unit_has_terminated( unit ) )
+                       status->status = unit_stopped;
+               else if ( !strcmp( status->clip, "" ) )
                        status->status = unit_not_loaded;
                else if ( status->speed == 0 )
                        status->status = unit_paused;
@@ -431,8 +439,39 @@ int miracle_unit_get_status( miracle_unit unit, valerie_status status )
 /** Change position in the playlist.
 */
 
-void miracle_unit_change_position( miracle_unit unit, int clip, double position )
+void miracle_unit_change_position( miracle_unit unit, int clip, int64_t position )
 {
+       mlt_properties properties = unit->properties;
+       mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+       mlt_producer producer = mlt_playlist_producer( playlist );
+       mlt_playlist_clip_info info;
+
+       if ( clip < 0 )
+       {
+               clip = 0;
+               position = 0;
+       }
+       else if ( clip >= mlt_playlist_count( playlist ) )
+       {
+               clip = mlt_playlist_count( playlist ) - 1;
+               position = LONG_MAX;
+       }
+
+       if ( mlt_playlist_get_clip_info( playlist, &info, clip ) == 0 )
+       {
+               int64_t frame_start = info.start;
+               int64_t frame_offset = position;
+
+               if ( frame_offset < 0 )
+                       frame_offset = info.frame_out;
+               if ( frame_offset < info.frame_in )
+                       frame_offset = info.frame_in;
+               if ( frame_offset >= info.frame_out )
+                       frame_offset = info.frame_out;
+               
+               mlt_producer_seek( producer, frame_start + frame_offset - info.frame_in );
+       }
+
        miracle_unit_status_communicate( unit );
 }
 
@@ -450,26 +489,56 @@ int       miracle_unit_get_current_clip( miracle_unit unit )
 /** Set a clip's in point
 */
 
-int miracle_unit_set_clip_in( miracle_unit unit, int index, double position )
+int miracle_unit_set_clip_in( miracle_unit unit, int index, int64_t position )
 {
-       int error = 0;
+       mlt_properties properties = unit->properties;
+       mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+       mlt_playlist_clip_info info;
+       int error = mlt_playlist_get_clip_info( playlist, &info, index );
+
+       if ( error == 0 )
+       {
+               miracle_unit_play( unit, 0 );
+               error = mlt_playlist_resize_clip( playlist, index, position, info.frame_out );
+               update_generation( unit );
+               miracle_unit_change_position( unit, index, 0 );
+       }
+
        return error;
 }
 
 /** Set a clip's out point.
 */
 
-int miracle_unit_set_clip_out( miracle_unit unit, int index, double position )
+int miracle_unit_set_clip_out( miracle_unit unit, int index, int64_t position )
 {
-       int error = 0;
+       mlt_properties properties = unit->properties;
+       mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+       mlt_playlist_clip_info info;
+       int error = mlt_playlist_get_clip_info( playlist, &info, index );
+
+       if ( error == 0 )
+       {
+               miracle_unit_play( unit, 0 );
+               error = mlt_playlist_resize_clip( playlist, index, info.frame_in, position );
+               update_generation( unit );
+               miracle_unit_status_communicate( unit );
+               miracle_unit_change_position( unit, index, -1 );
+       }
+
        return error;
 }
 
 /** Step by specified position.
 */
 
-void miracle_unit_step( miracle_unit unit, double offset )
+void miracle_unit_step( miracle_unit unit, int64_t offset )
 {
+       mlt_properties properties = unit->properties;
+       mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
+       mlt_producer producer = mlt_playlist_producer( playlist );
+       mlt_position position = mlt_producer_frame( producer );
+       mlt_producer_seek( producer, position + offset );
 }
 
 /** Set the unit's clip mode regarding in and out points.
@@ -511,6 +580,20 @@ void miracle_unit_step( miracle_unit unit, double offset )
        //return dv_player_get_eof_action( player );
 //}
 
+int miracle_unit_set( miracle_unit unit, char *name_value )
+{
+       mlt_playlist playlist = mlt_properties_get_data( unit->properties, "playlist", NULL );
+       mlt_properties properties = mlt_playlist_properties( playlist );
+       return mlt_properties_parse( properties, name_value );
+}
+
+char *miracle_unit_get( miracle_unit unit, char *name )
+{
+       mlt_playlist playlist = mlt_properties_get_data( unit->properties, "playlist", NULL );
+       mlt_properties properties = mlt_playlist_properties( playlist );
+       return mlt_properties_get( properties, name );
+}
+
 /** Release the unit
 
     \todo error handling