From 8cf0f77981284b7549c811b67283eb73d0c520d6 Mon Sep 17 00:00:00 2001 From: lilo_booter Date: Fri, 17 Sep 2004 12:15:22 +0000 Subject: [PATCH] Consumer valerie, pushes, and assorted modifications git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@418 d19143bc-622f-0410-bfdd-b5b2a6649095 --- src/framework/mlt_service.c | 24 ++++-- src/framework/mlt_service.h | 1 + src/miracle/miracle_connection.c | 30 +++++++- src/miracle/miracle_local.c | 42 ++++++++++ src/miracle/miracle_unit.c | 121 ++++++++++++++++------------ src/miracle/miracle_unit.h | 4 +- src/miracle/miracle_unit_commands.c | 9 ++ src/miracle/miracle_unit_commands.h | 1 + src/modules/avformat/Makefile | 1 + src/modules/core/filter_watermark.c | 7 ++ src/modules/core/producer_colour.c | 3 + src/modules/core/transition_region.c | 19 +---- src/modules/gtk2/factory.c | 2 +- src/modules/inigo/producer_inigo.c | 5 + src/modules/plus/transition_affine.c | 6 +- src/modules/sdl/consumer_sdl.c | 15 ++-- src/modules/sox/Makefile | 2 +- src/modules/valerie/Makefile | 33 ++++++++ src/modules/valerie/configure | 11 +++ src/modules/valerie/consumer_valerie.c | 133 ++++++++++++++++++++++++++++++++ src/modules/valerie/consumer_valerie.h | 28 +++++++ src/modules/valerie/factory.c | 46 +++++++++++ src/modules/westley/configure | 1 + src/modules/westley/consumer_westley.c | 87 ++++++++++++++++++--- src/modules/westley/factory.c | 4 +- src/modules/westley/producer_westley.c | 72 ++++++++++++----- src/modules/westley/producer_westley.h | 2 +- src/valerie/Makefile | 3 +- src/valerie/valerie.c | 39 +++++++++ src/valerie/valerie.h | 5 + src/valerie/valerie_parser.c | 8 ++ src/valerie/valerie_parser.h | 6 ++ src/valerie/valerie_remote.c | 44 +++++++++-- 33 files changed, 682 insertions(+), 132 deletions(-) create mode 100644 src/modules/valerie/Makefile create mode 100755 src/modules/valerie/configure create mode 100644 src/modules/valerie/consumer_valerie.c create mode 100644 src/modules/valerie/consumer_valerie.h create mode 100644 src/modules/valerie/factory.c diff --git a/src/framework/mlt_service.c b/src/framework/mlt_service.c index bc0cf33..9ea9b66 100644 --- a/src/framework/mlt_service.c +++ b/src/framework/mlt_service.c @@ -263,21 +263,31 @@ mlt_properties mlt_service_properties( mlt_service self ) /** Recursively apply attached filters */ -static void apply_filters( mlt_service this, mlt_frame frame, int index ) +void mlt_service_apply_filters( mlt_service this, mlt_frame frame, int index ) { - mlt_properties properties = mlt_service_properties( this ); - mlt_service_base *base = this->local; int i; + mlt_properties frame_properties = mlt_frame_properties( frame ); + mlt_properties filter_properties = mlt_service_properties( this ); + mlt_service_base *base = this->local; + mlt_position position = mlt_properties_get_position( frame_properties, "_position" ); - if ( mlt_properties_get_int( properties, "_filter_private" ) == 0 ) + if ( index == 0 || mlt_properties_get_int( filter_properties, "_filter_private" ) == 0 ) { // Process the frame with the attached filters for ( i = 0; i < base->filter_count; i ++ ) { if ( base->filters[ i ] != NULL ) { - mlt_filter_process( base->filters[ i ], frame ); - apply_filters( mlt_filter_service( base->filters[ i ] ), frame, index ); + mlt_properties properties = mlt_filter_properties( base->filters[ i ] ); + mlt_position in = mlt_properties_get_position( properties, "in" ); + mlt_position out = mlt_properties_get_position( properties, "out" ); + if ( ( in == 0 && out == 0 ) || ( position >= in && position <= out ) ) + { + mlt_properties_set_position( frame_properties, "_position", position - in ); + mlt_filter_process( base->filters[ i ], frame ); + mlt_service_apply_filters( mlt_filter_service( base->filters[ i ] ), frame, index + 1 ); + mlt_properties_set_position( frame_properties, "_position", position + in ); + } } } } @@ -292,7 +302,7 @@ int mlt_service_get_frame( mlt_service this, mlt_frame_ptr frame, int index ) { int result = this->get_frame( this, frame, index ); if ( result == 0 ) - apply_filters( this, *frame, index ); + mlt_service_apply_filters( this, *frame, 1 ); return result; } *frame = mlt_frame_init( ); diff --git a/src/framework/mlt_service.h b/src/framework/mlt_service.h index 47cd929..00e5001 100644 --- a/src/framework/mlt_service.h +++ b/src/framework/mlt_service.h @@ -52,6 +52,7 @@ extern mlt_service mlt_service_consumer( mlt_service self ); extern mlt_service mlt_service_producer( mlt_service self ); extern int mlt_service_attach( mlt_service self, mlt_filter filter ); extern int mlt_service_detach( mlt_service self, mlt_filter filter ); +extern void mlt_service_apply_filters( mlt_service self, mlt_frame frame, int index ); extern mlt_filter mlt_service_filter( mlt_service self, int index ); extern void mlt_service_close( mlt_service self ); diff --git a/src/miracle/miracle_connection.c b/src/miracle/miracle_connection.c index 82a5b59..6bf496c 100644 --- a/src/miracle/miracle_connection.c +++ b/src/miracle/miracle_connection.c @@ -223,7 +223,35 @@ void *parser_thread( void *arg ) while( !error && connection_read( fd, command, 1024 ) ) { - if ( strncmp( command, "STATUS", 6 ) ) + if ( !strncmp( command, "PUSH ", 5 ) ) + { + char temp[ 20 ]; + int bytes; + char *buffer = NULL; + int total = 0; + mlt_service service = NULL; + + connection_read( fd, temp, 20 ); + bytes = atoi( temp ); + buffer = malloc( bytes + 1 ); + while ( total < bytes ) + { + int count = read( fd, buffer + total, bytes - total ); + if ( count >= 0 ) + total += count; + else + break; + } + buffer[ bytes ] = '\0'; + if ( bytes > 0 && total == bytes ) + service = ( mlt_service )mlt_factory_producer( "westley-xml", buffer ); + response = valerie_parser_push( parser, command, service ); + error = connection_send( fd, response ); + valerie_response_close( response ); + mlt_service_close( service ); + free( buffer ); + } + else if ( strncmp( command, "STATUS", 6 ) ) { response = valerie_parser_execute( parser, command ); miracle_log( LOG_INFO, "%s \"%s\" %d", address, command, valerie_response_get_error_code( response ) ); diff --git a/src/miracle/miracle_local.c b/src/miracle/miracle_local.c index 374d5fd..9f3e706 100644 --- a/src/miracle/miracle_local.c +++ b/src/miracle/miracle_local.c @@ -60,6 +60,7 @@ typedef struct static valerie_response miracle_local_connect( miracle_local ); static valerie_response miracle_local_execute( miracle_local, char * ); +static valerie_response miracle_local_push( miracle_local, char *, mlt_service ); static void miracle_local_close( miracle_local ); response_codes miracle_help( command_argument arg ); response_codes miracle_run( command_argument arg ); @@ -79,6 +80,7 @@ valerie_parser miracle_parser_init_local( ) parser->connect = (parser_connect)miracle_local_connect; parser->execute = (parser_execute)miracle_local_execute; + parser->push = (parser_push)miracle_local_push; parser->close = (parser_close)miracle_local_close; parser->real = local; @@ -497,6 +499,46 @@ static valerie_response miracle_local_execute( miracle_local local, char *comman return cmd.response; } +static valerie_response miracle_local_push( miracle_local local, char *command, mlt_service service ) +{ + command_argument_t cmd; + cmd.parser = local->parser; + cmd.response = valerie_response_init( ); + cmd.tokeniser = valerie_tokeniser_init( ); + cmd.command = command; + cmd.unit = -1; + cmd.argument = NULL; + cmd.root_dir = local->root_dir; + + /* Set the default error */ + miracle_command_set_error( &cmd, RESPONSE_SUCCESS ); + + /* Parse the command */ + if ( valerie_tokeniser_parse_new( cmd.tokeniser, command, " " ) > 0 ) + { + int index = 0; + int position = 1; + + /* Strip quotes from all tokens */ + for ( index = 0; index < valerie_tokeniser_count( cmd.tokeniser ); index ++ ) + valerie_util_strip( valerie_tokeniser_get_string( cmd.tokeniser, index ), '\"' ); + + cmd.unit = miracle_command_parse_unit( &cmd, position ); + if ( cmd.unit == -1 ) + miracle_command_set_error( &cmd, RESPONSE_MISSING_ARG ); + position ++; + + miracle_push( &cmd, service ); + miracle_command_set_error( &cmd, RESPONSE_SUCCESS ); + + free( cmd.argument ); + } + + valerie_tokeniser_close( cmd.tokeniser ); + + return cmd.response; +} + /** Close the parser. */ diff --git a/src/miracle/miracle_unit.c b/src/miracle/miracle_unit.c index 2fe0c7a..18f19ac 100644 --- a/src/miracle/miracle_unit.c +++ b/src/miracle/miracle_unit.c @@ -69,7 +69,7 @@ miracle_unit miracle_unit_init( int index, char *constructor ) mlt_playlist playlist = mlt_playlist_init( ); this = calloc( sizeof( miracle_unit_t ), 1 ); this->properties = mlt_properties_new( ); - this->producers = mlt_properties_new( ); + this->old_playlist = mlt_playlist_init( ); mlt_properties_init( this->properties, this ); mlt_properties_set_int( this->properties, "unit", index ); mlt_properties_set_int( this->properties, "generation", 0 ); @@ -84,6 +84,19 @@ miracle_unit miracle_unit_init( int index, char *constructor ) return this; } +static void copy_playlist( mlt_playlist dest, mlt_playlist src ) +{ + int i; + + for ( i = 0; i < mlt_playlist_count( src ); i ++ ) + { + mlt_playlist_clip_info info; + mlt_playlist_get_clip_info( src, &info, i ); + if ( info.producer != NULL ) + mlt_playlist_append_io( dest, info.producer, info.frame_in, info.frame_out ); + } +} + static char *strip_root( miracle_unit unit, char *file ) { mlt_properties properties = unit->properties; @@ -142,33 +155,12 @@ 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 locate_producer( miracle_unit unit, char *file ) { - // 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 ) - { - // Create the producer - result = create_producer( file ); - - // Now store the result - if ( result != NULL ) - mlt_properties_set_data( properties, file, result, 0, ( mlt_destructor )mlt_producer_close, NULL ); - } - - return result; + return mlt_factory_producer( "fezzik", file ); } /** Update the generation count. @@ -190,14 +182,11 @@ static void clear_unit( miracle_unit unit ) mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL ); mlt_producer producer = mlt_playlist_producer( playlist ); + mlt_playlist_clear( unit->old_playlist ); + copy_playlist( unit->old_playlist, playlist ); mlt_playlist_clear( playlist ); mlt_producer_seek( producer, 0 ); - if ( unit->old_producers != NULL ) - mlt_properties_close( unit->old_producers ); - unit->old_producers = unit->producers; - unit->producers = mlt_properties_new( ); - update_generation( unit ); } @@ -215,16 +204,15 @@ static void clean_unit( miracle_unit unit ) double speed = mlt_producer_get_speed( producer ); mlt_playlist_get_clip_info( playlist, &info, current ); - if ( info.resource != NULL ) + if ( info.producer != NULL ) { - void *instance = mlt_properties_get_data( unit->producers, info.resource, NULL ); + mlt_properties_inc_ref( mlt_producer_properties( info.producer ) ); position -= info.start; - mlt_properties_set_data( unit->producers, info.resource, instance, 0, NULL, NULL ); clear_unit( unit ); - mlt_playlist_append_io( playlist, instance, info.frame_in, info.frame_out ); - mlt_properties_set_data( unit->producers, info.resource, instance, 0, ( mlt_destructor )mlt_producer_close, NULL ); + mlt_playlist_append_io( playlist, info.producer, info.frame_in, info.frame_out ); mlt_producer_seek( producer, position ); mlt_producer_set_speed( producer, speed ); + mlt_producer_close( info.producer ); } update_generation( unit ); @@ -245,10 +233,14 @@ void miracle_unit_report_list( miracle_unit unit, valerie_response response ) for ( i = 0; i < mlt_playlist_count( playlist ); i ++ ) { mlt_playlist_clip_info info; + char *title; mlt_playlist_get_clip_info( playlist , &info, i ); + title = mlt_properties_get( mlt_producer_properties( info.producer ), "title" ); + if ( title == NULL ) + title = strip_root( unit, info.resource ); valerie_response_printf( response, 10240, "%d \"%s\" %d %d %d %d %.2f\n", i, - strip_root( unit, info.resource ), + title, info.frame_in, info.frame_out, info.frame_count, @@ -269,20 +261,20 @@ void miracle_unit_report_list( miracle_unit unit, valerie_response response ) valerie_error_code miracle_unit_load( miracle_unit unit, char *clip, int32_t in, int32_t out, int flush ) { - // Now try to create an producer - mlt_producer instance = create_producer( clip ); + // Now try to create a producer + mlt_producer instance = locate_producer( unit, 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_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL ); mlt_consumer_purge( consumer ); mlt_playlist_append_io( playlist, instance, in, out ); miracle_log( LOG_DEBUG, "loaded clip %s", clip ); miracle_unit_status_communicate( unit ); + mlt_producer_close( instance ); return valerie_ok; } @@ -302,6 +294,7 @@ valerie_error_code miracle_unit_insert( miracle_unit unit, char *clip, int index miracle_log( LOG_DEBUG, "inserted clip %s at %d", clip, index ); update_generation( unit ); miracle_unit_status_communicate( unit ); + mlt_producer_close( instance ); return valerie_ok; } @@ -369,12 +362,30 @@ valerie_error_code miracle_unit_append( miracle_unit unit, char *clip, int32_t i miracle_log( LOG_DEBUG, "appended clip %s", clip ); update_generation( unit ); miracle_unit_status_communicate( unit ); + mlt_producer_close( instance ); return valerie_ok; } return valerie_invalid_file; } +/** Add an mlt_service to the playlist + + \param unit A miracle_unit handle. + \param service the service to add +*/ + +valerie_error_code miracle_unit_append_service( miracle_unit unit, mlt_service service ) +{ + mlt_properties properties = unit->properties; + mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL ); + mlt_playlist_append( playlist, ( mlt_producer )service ); + miracle_log( LOG_DEBUG, "appended clip" ); + update_generation( unit ); + miracle_unit_status_communicate( unit ); + return valerie_ok; +} + /** Start playing the unit. \todo error handling @@ -433,23 +444,28 @@ int miracle_unit_transfer( miracle_unit dest_unit, miracle_unit src_unit ) mlt_playlist dest_playlist = mlt_properties_get_data( dest_properties, "playlist", NULL ); mlt_properties src_properties = src_unit->properties; mlt_playlist src_playlist = mlt_properties_get_data( src_properties, "playlist", NULL ); + mlt_playlist tmp_playlist = mlt_playlist_init( ); for ( i = 0; i < mlt_playlist_count( src_playlist ); i ++ ) { mlt_playlist_clip_info info; mlt_playlist_get_clip_info( src_playlist, &info, i ); - mlt_producer producer = locate_producer( dest_unit, info.resource ); - if ( producer != NULL ) - { - mlt_playlist_append_io( dest_playlist, producer, info.frame_in, info.frame_out ); - if ( i == 0 ) - { - miracle_unit_change_position( dest_unit, mlt_playlist_count( dest_playlist ) - 1, 0 ); - clean_unit( dest_unit ); - } - } + if ( info.producer != NULL ) + mlt_playlist_append_io( tmp_playlist, info.producer, info.frame_in, info.frame_out ); + } + + clear_unit( src_unit ); + + for ( i = 0; i < mlt_playlist_count( tmp_playlist ); i ++ ) + { + mlt_playlist_clip_info info; + mlt_playlist_get_clip_info( tmp_playlist, &info, i ); + if ( info.producer != NULL ) + mlt_playlist_append_io( dest_playlist, info.producer, info.frame_in, info.frame_out ); } + mlt_playlist_close( tmp_playlist ); + return 0; } @@ -483,14 +499,17 @@ int miracle_unit_get_status( miracle_unit unit, valerie_status status ) if ( info.resource != NULL && strcmp( info.resource, "" ) ) { - strncpy( status->clip, strip_root( unit, info.resource ), sizeof( status->clip ) ); + char *title = mlt_properties_get( mlt_producer_properties( info.producer ), "title" ); + if ( title == NULL ) + title = strip_root( unit, info.resource ); + strncpy( status->clip, title, sizeof( status->clip ) ); status->speed = (int)( mlt_producer_get_speed( producer ) * 1000.0 ); status->fps = mlt_producer_get_fps( producer ); 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, strip_root( unit, info.resource ), sizeof( status->tail_clip ) ); + strncpy( status->tail_clip, title, sizeof( status->tail_clip ) ); status->tail_in = info.frame_in; status->tail_out = info.frame_out; status->tail_position = mlt_producer_position( clip ); @@ -702,10 +721,8 @@ void miracle_unit_close( miracle_unit unit ) { miracle_log( LOG_DEBUG, "closing unit..." ); miracle_unit_terminate( unit ); - if ( unit->old_producers != NULL ) - mlt_properties_close( unit->old_producers ); + mlt_playlist_close( unit->old_playlist ); mlt_properties_close( unit->properties ); - mlt_properties_close( unit->producers ); free( unit ); miracle_log( LOG_DEBUG, "... unit closed." ); } diff --git a/src/miracle/miracle_unit.h b/src/miracle/miracle_unit.h index 3ba8751..7879268 100644 --- a/src/miracle/miracle_unit.h +++ b/src/miracle/miracle_unit.h @@ -34,8 +34,7 @@ extern "C" typedef struct { mlt_properties properties; - mlt_properties producers; - mlt_properties old_producers; + mlt_playlist old_playlist; } miracle_unit_t, *miracle_unit; @@ -45,6 +44,7 @@ extern void miracle_unit_allow_stdin( miracle_unit unit, int fla extern valerie_error_code miracle_unit_load( miracle_unit unit, char *clip, int32_t in, int32_t out, int flush ); extern valerie_error_code miracle_unit_insert( miracle_unit unit, char *clip, int index, int32_t in, int32_t out ); extern valerie_error_code miracle_unit_append( miracle_unit unit, char *clip, int32_t in, int32_t out ); +extern valerie_error_code miracle_unit_append_service( miracle_unit unit, mlt_service service ); extern valerie_error_code miracle_unit_remove( miracle_unit unit, int index ); extern valerie_error_code miracle_unit_clean( miracle_unit unit ); extern valerie_error_code miracle_unit_clear( miracle_unit unit ); diff --git a/src/miracle/miracle_unit_commands.c b/src/miracle/miracle_unit_commands.c index 53966d4..c810c0a 100644 --- a/src/miracle/miracle_unit_commands.c +++ b/src/miracle/miracle_unit_commands.c @@ -254,6 +254,15 @@ int miracle_append( command_argument cmd_arg ) return RESPONSE_SUCCESS; } +int miracle_push( command_argument cmd_arg, mlt_service service ) +{ + miracle_unit unit = miracle_get_unit(cmd_arg->unit); + if ( unit != NULL && service != NULL ) + if ( miracle_unit_append_service( unit, service ) == valerie_ok ) + return RESPONSE_SUCCESS; + return RESPONSE_BAD_FILE; +} + int miracle_play( command_argument cmd_arg ) { miracle_unit unit = miracle_get_unit(cmd_arg->unit); diff --git a/src/miracle/miracle_unit_commands.h b/src/miracle/miracle_unit_commands.h index b4bde3a..461c51a 100644 --- a/src/miracle/miracle_unit_commands.h +++ b/src/miracle/miracle_unit_commands.h @@ -50,6 +50,7 @@ extern response_codes miracle_get_unit_status( command_argument ); extern response_codes miracle_set_unit_property( command_argument ); extern response_codes miracle_get_unit_property( command_argument ); extern response_codes miracle_transfer( command_argument ); +extern response_codes miracle_push( command_argument, mlt_service ); #ifdef __cplusplus } diff --git a/src/modules/avformat/Makefile b/src/modules/avformat/Makefile index 6f25d6f..aba87af 100644 --- a/src/modules/avformat/Makefile +++ b/src/modules/avformat/Makefile @@ -32,6 +32,7 @@ dist-clean: clean rm -f .depend clean: + if [ $(LOCAL_FFMPEG) ] ; then $(MAKE) -C ffmpeg clean ; fi rm -f $(OBJS) $(TARGET) install: all diff --git a/src/modules/core/filter_watermark.c b/src/modules/core/filter_watermark.c index 883db69..f4a87ea 100644 --- a/src/modules/core/filter_watermark.c +++ b/src/modules/core/filter_watermark.c @@ -134,6 +134,10 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format { if ( mlt_properties_get_int( properties, "reverse" ) == 0 ) { + // Apply all filters that are attached to this filter to the b frame + mlt_service_apply_filters( mlt_filter_service( this ), b_frame, 0 ); + + // Process the frame mlt_transition_process( composite, frame, b_frame ); // Get the image @@ -147,6 +151,7 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format mlt_properties_set( a_props, "rescale.interp", "nearest" ); mlt_properties_set( b_props, "rescale.interp", "nearest" ); mlt_properties_set_int( b_props, "consumer_aspect_ratio", 1 ); + mlt_service_apply_filters( mlt_filter_service( this ), frame, 0 ); error = mlt_frame_get_image( b_frame, image, format, width, height, 1 ); mlt_properties_set_data( b_props, "image", *image, 0, NULL, NULL ); mlt_properties_set_data( a_props, "image", *image, *width * *height * 2, mlt_pool_release, NULL ); @@ -203,6 +208,8 @@ mlt_filter filter_watermark_init( void *arg ) mlt_properties_set( properties, "factory", "fezzik" ); if ( arg != NULL ) mlt_properties_set( properties, "resource", arg ); + // Ensure that attached filters are handled privately + mlt_properties_set_int( properties, "_filter_private", 1 ); } return this; } diff --git a/src/modules/core/producer_colour.c b/src/modules/core/producer_colour.c index 29bde44..2cc6779 100644 --- a/src/modules/core/producer_colour.c +++ b/src/modules/core/producer_colour.c @@ -60,6 +60,9 @@ rgba_color parse_color( char *color ) { rgba_color result = { 0xff, 0xff, 0xff, 0xff }; + if ( strchr( color, '/' ) ) + color = strrchr( color, '/' ) + 1; + if ( !strncmp( color, "0x", 2 ) ) { unsigned int temp = 0; diff --git a/src/modules/core/transition_region.c b/src/modules/core/transition_region.c index aa7b660..1e2f824 100644 --- a/src/modules/core/transition_region.c +++ b/src/modules/core/transition_region.c @@ -129,23 +129,6 @@ static uint8_t *filter_get_alpha_mask( mlt_frame this ) return alpha; } -static void apply_filters( mlt_filter this, mlt_frame frame, int index ) -{ - mlt_service service = mlt_filter_service( this ); - mlt_properties properties = mlt_filter_properties( this ); - int i; - - if ( index == 0 || mlt_properties_get_int( properties, "_filter_private" ) == 0 ) - { - mlt_filter filter = NULL; - for ( i = 0; ( filter = mlt_service_filter( service, i ) ) != NULL; i ++ ) - { - mlt_filter_process( filter, frame ); - apply_filters( filter, frame, 1 ); - } - } -} - /** Do it :-). */ @@ -317,7 +300,7 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for // Allow filters to be attached to a region filter filter = mlt_properties_get_data( properties, "_region_filter", NULL ); if ( filter != NULL ) - apply_filters( filter, b_frame, 0 ); + mlt_service_apply_filters( mlt_filter_service( filter ), b_frame, 0 ); // Hmm - this is probably going to go wrong.... mlt_frame_set_position( frame, position ); diff --git a/src/modules/gtk2/factory.c b/src/modules/gtk2/factory.c index 554a600..82ed3d4 100644 --- a/src/modules/gtk2/factory.c +++ b/src/modules/gtk2/factory.c @@ -19,7 +19,7 @@ */ #include - +#include #include "producer_pixbuf.h" #include "producer_pango.h" #include "filter_rescale.h" diff --git a/src/modules/inigo/producer_inigo.c b/src/modules/inigo/producer_inigo.c index 212aea8..ce25564 100644 --- a/src/modules/inigo/producer_inigo.c +++ b/src/modules/inigo/producer_inigo.c @@ -129,6 +129,7 @@ mlt_producer producer_inigo_init( char **argv ) mlt_field field = mlt_tractor_field( tractor ); mlt_properties field_properties = mlt_field_properties( field ); mlt_multitrack multitrack = mlt_tractor_multitrack( tractor ); + char *title = NULL; // We need to track the number of registered filters mlt_properties_set_int( field_properties, "registered", 0 ); @@ -265,6 +266,8 @@ mlt_producer producer_inigo_init( char **argv ) { if ( producer != NULL ) mlt_playlist_append( playlist, producer ); + if ( title == NULL ) + title = argv[ i ]; producer = create_producer( field, argv[ i ] ); if ( producer != NULL ) { @@ -303,6 +306,8 @@ mlt_producer producer_inigo_init( char **argv ) mlt_properties_set_position( props, "length", mlt_producer_get_out( mlt_multitrack_producer( multitrack ) ) + 1 ); mlt_producer_set_in_and_out( prod, 0, mlt_producer_get_out( mlt_multitrack_producer( multitrack ) ) ); mlt_properties_set_double( props, "fps", mlt_producer_get_fps( mlt_multitrack_producer( multitrack ) ) ); + if ( title != NULL ) + mlt_properties_set( props, "title", strchr( title, '/' ) ? strrchr( title, '/' ) + 1 : title ); return prod; } diff --git a/src/modules/plus/transition_affine.c b/src/modules/plus/transition_affine.c index f95b148..6154771 100644 --- a/src/modules/plus/transition_affine.c +++ b/src/modules/plus/transition_affine.c @@ -634,8 +634,10 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f { mix = ( float )*( alpha + dy * b_width + dx ) / 255.0; dx += dx & 1; - *p ++ = *p * ( 1 - mix ) + mix * *( b_image + dy * b_stride + ( dx << 1 ) ); - *p ++ = *p * ( 1 - mix ) + mix * *( b_image + dy * b_stride + ( dx << 1 ) + ( ( x & 1 ) << 1 ) + 1 ); + *p = *p * ( 1 - mix ) + mix * *( b_image + dy * b_stride + ( dx << 1 ) ); + p ++; + *p = *p * ( 1 - mix ) + mix * *( b_image + dy * b_stride + ( dx << 1 ) + ( ( x & 1 ) << 1 ) + 1 ); + p ++; } } else diff --git a/src/modules/sdl/consumer_sdl.c b/src/modules/sdl/consumer_sdl.c index dfce3d1..3b94043 100644 --- a/src/modules/sdl/consumer_sdl.c +++ b/src/modules/sdl/consumer_sdl.c @@ -433,15 +433,14 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame ) } if ( width != this->width || height != this->height || - ( int )( this->last_frame_aspect * 1000 ) != ( int )( mlt_frame_get_aspect_ratio( frame ) * 1000 ) ) + ( ( int )( this->last_frame_aspect * 1000 ) != ( int )( mlt_frame_get_aspect_ratio( frame ) * 1000 ) && + ( mlt_frame_get_aspect_ratio( frame ) != 1.0 || this->last_frame_aspect == 0.0 ) ) ) + { - if ( mlt_frame_get_aspect_ratio( frame ) != 1.0 || this->last_frame_aspect == 0.0 ) - { - this->width = width; - this->height = height; - this->last_frame_aspect = mlt_frame_get_aspect_ratio( frame ); - changed = 1; - } + this->width = width; + this->height = height; + this->last_frame_aspect = mlt_frame_get_aspect_ratio( frame ); + changed = 1; } if ( this->sdl_screen == NULL || changed ) diff --git a/src/modules/sox/Makefile b/src/modules/sox/Makefile index fa78655..e156567 100644 --- a/src/modules/sox/Makefile +++ b/src/modules/sox/Makefile @@ -9,7 +9,7 @@ CFLAGS += -I../../ -I/usr/include/sox LDFLAGS += -lst -lpopt -lvorbis -logg -lvorbisfile -lvorbisenc -LDFLAGS+=-L../../framework -lmlt -lmad +LDFLAGS+=-L../../framework -lmlt -lmp3lame SRCS := $(OBJS:.o=.c) diff --git a/src/modules/valerie/Makefile b/src/modules/valerie/Makefile new file mode 100644 index 0000000..9cd7e57 --- /dev/null +++ b/src/modules/valerie/Makefile @@ -0,0 +1,33 @@ +include ../../../config.mak + +TARGET = ../libmltvalerie.so + +OBJS = factory.o \ + consumer_valerie.o + +CFLAGS += -I../../ + +LDFLAGS+=-L../../valerie -lvalerie -L../../framework -lmlt + +SRCS := $(OBJS:.o=.c) + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) -shared -o $@ $(OBJS) $(LDFLAGS) + +depend: $(SRCS) + $(CC) -MM $(CFLAGS) $^ 1>.depend + +dist-clean: clean + rm -f .depend + +clean: + rm -f $(OBJS) $(TARGET) + +install: all + install -m 755 $(TARGET) "$(prefix)/share/mlt/modules" + +ifneq ($(wildcard .depend),) +include .depend +endif diff --git a/src/modules/valerie/configure b/src/modules/valerie/configure new file mode 100755 index 0000000..1ebe527 --- /dev/null +++ b/src/modules/valerie/configure @@ -0,0 +1,11 @@ +#!/bin/sh + +if [ "$help" != "1" ] +then + +cat << EOF >> ../consumers.dat +valerie libmltvalerie.so +EOF + +fi + diff --git a/src/modules/valerie/consumer_valerie.c b/src/modules/valerie/consumer_valerie.c new file mode 100644 index 0000000..e473584 --- /dev/null +++ b/src/modules/valerie/consumer_valerie.c @@ -0,0 +1,133 @@ +/* + * consumer_westley.c -- a libxml2 serialiser of mlt service networks + * Copyright (C) 2003-2004 Ushodaya Enterprises Limited + * Author: Dan Dennedy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "consumer_valerie.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static int consumer_is_stopped( mlt_consumer this ); +static int consumer_start( mlt_consumer this ); + +/** This is what will be called by the factory +*/ + +mlt_consumer consumer_valerie_init( char *arg ) +{ + // Create the consumer object + mlt_consumer this = calloc( sizeof( struct mlt_consumer_s ), 1 ); + + // If no malloc'd and consumer init ok + if ( this != NULL && mlt_consumer_init( this, NULL ) == 0 ) + { + // Allow thread to be started/stopped + this->start = consumer_start; + this->is_stopped = consumer_is_stopped; + + mlt_properties_set( mlt_consumer_properties( this ), "server", arg == NULL ? "localhost" : arg ); + mlt_properties_set_int( mlt_consumer_properties( this ), "port", 5250 ); + mlt_properties_set_int( mlt_consumer_properties( this ), "unit", 0 ); + mlt_properties_set( mlt_consumer_properties( this ), "command", "append" ); + + // Return the consumer produced + return this; + } + + // malloc or consumer init failed + free( this ); + + // Indicate failure + return NULL; +} + +static int consumer_start( mlt_consumer this ) +{ + // Get the producer service + mlt_service service = mlt_service_producer( mlt_consumer_service( this ) ); + + // Get the properties object + mlt_properties properties = mlt_consumer_properties( this ); + + // Get all the properties now + char *server = mlt_properties_get( properties, "server" ); + int port = mlt_properties_get_int( properties, "port" ); + char *command = mlt_properties_get( properties, "command" ); + int unit = mlt_properties_get_int( properties, "unit" ); + char *title = mlt_properties_get( properties, "title" ); + + // If this is a reuse, then a valerie object will exist + valerie connection = mlt_properties_get_data( properties, "connection", NULL ); + + if ( service != NULL ) + { + // Initiate the connection if required + if ( connection == NULL ) + { + valerie_parser parser = valerie_parser_init_remote( server, port ); + connection = valerie_init( parser ); + if ( valerie_connect( connection ) == valerie_ok ) + { + mlt_properties_set_data( properties, "connection", connection, 0, ( mlt_destructor )valerie_close, NULL ); + mlt_properties_set_data( properties, "parser", parser, 0, ( mlt_destructor )valerie_parser_close, NULL ); + } + else + { + fprintf( stderr, "Unable to connect to the server at %s:%d\n", server, port ); + valerie_close( connection ); + valerie_parser_close( parser ); + connection = NULL; + } + } + + // If we have connection, push the service over + if ( connection != NULL ) + { + int error; + + // Set the title if provided + if ( title != NULL ) + mlt_properties_set( mlt_service_properties( service ), "title", title ); + else if ( mlt_properties_get( mlt_service_properties( service ), "title" ) == NULL ) + mlt_properties_set( mlt_service_properties( service ), "title", "Anonymous Submission" ); + + // Push the service + error = valerie_unit_push( connection, unit, command, service ); + + // Report error + if ( error != valerie_ok ) + fprintf( stderr, "Push failed on %s:%d %s u%d (%d)\n", server, port, command, unit, error ); + } + } + + mlt_consumer_stop( this ); + mlt_consumer_stopped( this ); + + return 0; +} + +static int consumer_is_stopped( mlt_consumer this ) +{ + return 1; +} diff --git a/src/modules/valerie/consumer_valerie.h b/src/modules/valerie/consumer_valerie.h new file mode 100644 index 0000000..8fa274c --- /dev/null +++ b/src/modules/valerie/consumer_valerie.h @@ -0,0 +1,28 @@ +/* + * consumer_valerie.h -- pushes a service via valerie + * Copyright (C) 2003-2004 Ushodaya Enterprises Limited + * Author: Charles Yates + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _CONSUMER_VALERIE_H_ +#define _CONSUMER_VALERIE_H_ + +#include + +extern mlt_consumer consumer_valerie_init( char * ); + +#endif diff --git a/src/modules/valerie/factory.c b/src/modules/valerie/factory.c new file mode 100644 index 0000000..5a5de3a --- /dev/null +++ b/src/modules/valerie/factory.c @@ -0,0 +1,46 @@ +/* + * factory.c -- the factory method interfaces + * Copyright (C) 2003-2004 Ushodaya Enterprises Limited + * Author: Charles Yates + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#include "consumer_valerie.h" + +void *mlt_create_producer( char *id, void *arg ) +{ + return NULL; +} + +void *mlt_create_filter( char *id, void *arg ) +{ + return NULL; +} + +void *mlt_create_transition( char *id, void *arg ) +{ + return NULL; +} + +void *mlt_create_consumer( char *id, void *arg ) +{ + if ( !strcmp( id, "valerie" ) ) + return consumer_valerie_init( arg ); + return NULL; +} + diff --git a/src/modules/westley/configure b/src/modules/westley/configure index ac2e83f..af068dd 100755 --- a/src/modules/westley/configure +++ b/src/modules/westley/configure @@ -5,6 +5,7 @@ then cat << EOF >> ../producers.dat westley libmltwestley.so +westley-xml libmltwestley.so EOF cat << EOF >> ../consumers.dat diff --git a/src/modules/westley/consumer_westley.c b/src/modules/westley/consumer_westley.c index bfb8591..4d095f8 100644 --- a/src/modules/westley/consumer_westley.c +++ b/src/modules/westley/consumer_westley.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #define ID_SIZE 128 @@ -40,6 +41,7 @@ struct serialise_context_s int transition_count; int pass; mlt_properties hide_map; + char *root; }; typedef struct serialise_context_s* serialise_context; @@ -165,7 +167,7 @@ mlt_consumer consumer_westley_init( char *arg ) return NULL; } -static inline void serialise_properties( mlt_properties properties, xmlNode *node ) +static inline void serialise_properties( serialise_context context, mlt_properties properties, xmlNode *node ) { int i; xmlNode *p; @@ -181,12 +183,17 @@ static inline void serialise_properties( mlt_properties properties, xmlNode *nod strcmp( name, "in" ) != 0 && strcmp( name, "out" ) != 0 && strcmp( name, "id" ) != 0 && + strcmp( name, "root" ) != 0 && strcmp( name, "width" ) != 0 && strcmp( name, "height" ) != 0 ) { + char *value = mlt_properties_get_value( properties, i ); p = xmlNewChild( node, NULL, "property", NULL ); xmlNewProp( p, "name", mlt_properties_get_name( properties, i ) ); - xmlNodeSetContent( p, mlt_properties_get_value( properties, i ) ); + if ( strcmp( context->root, "" ) && !strncmp( value, context->root, strlen( context->root ) ) ) + xmlNodeSetContent( p, value + strlen( context->root ) + 1 ); + else + xmlNodeSetContent( p, value ); } } } @@ -207,9 +214,19 @@ static inline void serialise_service_filters( serialise_context context, mlt_ser char *id = westley_get_id( context, mlt_filter_service( filter ), westley_filter ); if ( id != NULL ) { + int in = mlt_properties_get_position( properties, "in" ); + int out = mlt_properties_get_position( properties, "out" ); p = xmlNewChild( node, NULL, "filter", NULL ); xmlNewProp( p, "id", id ); - serialise_properties( properties, p ); + if ( in != 0 || out != 0 ) + { + char temp[ 20 ]; + sprintf( temp, "%d", in ); + xmlNewProp( p, "in", temp ); + sprintf( temp, "%d", out ); + xmlNewProp( p, "out", temp ); + } + serialise_properties( context, properties, p ); serialise_service_filters( context, mlt_filter_service( filter ), p ); } } @@ -232,7 +249,7 @@ static void serialise_producer( serialise_context context, mlt_service service, // Set the id xmlNewProp( child, "id", id ); - serialise_properties( properties, child ); + serialise_properties( context, properties, child ); serialise_service_filters( context, service, child ); // Add producer to the map @@ -418,7 +435,7 @@ static void serialise_filter( serialise_context context, mlt_service service, xm xmlNewProp( child, "in", mlt_properties_get( properties, "in" ) ); xmlNewProp( child, "out", mlt_properties_get( properties, "out" ) ); - serialise_properties( properties, child ); + serialise_properties( context, properties, child ); serialise_service_filters( context, service, child ); } } @@ -445,7 +462,7 @@ static void serialise_transition( serialise_context context, mlt_service service xmlNewProp( child, "in", mlt_properties_get( properties, "in" ) ); xmlNewProp( child, "out", mlt_properties_get( properties, "out" ) ); - serialise_properties( properties, child ); + serialise_properties( context, properties, child ); serialise_service_filters( context, service, child ); } } @@ -519,12 +536,28 @@ static void serialise_service( serialise_context context, mlt_service service, x xmlDocPtr westley_make_doc( mlt_service service ) { + mlt_properties properties = mlt_service_properties( service ); xmlDocPtr doc = xmlNewDoc( "1.0" ); xmlNodePtr root = xmlNewNode( NULL, "westley" ); struct serialise_context_s *context = calloc( 1, sizeof( struct serialise_context_s ) ); xmlDocSetRootElement( doc, root ); - + + // If we have root, then deal with it now + if ( mlt_properties_get( properties, "root" ) != NULL ) + { + xmlNewProp( root, "root", mlt_properties_get( properties, "root" ) ); + context->root = strdup( mlt_properties_get( properties, "root" ) ); + } + else + { + context->root = strdup( "" ); + } + + // Assign a title property + if ( mlt_properties_get( properties, "title" ) != NULL ) + xmlNewProp( root, "title", mlt_properties_get( properties, "title" ) ); + // Construct the context maps context->id_map = mlt_properties_new(); context->hide_map = mlt_properties_new(); @@ -544,12 +577,12 @@ xmlDocPtr westley_make_doc( mlt_service service ) // Cleanup resource mlt_properties_close( context->id_map ); mlt_properties_close( context->hide_map ); + free( context->root ); free( context ); return doc; } - static int consumer_start( mlt_consumer this ) { xmlDocPtr doc = NULL; @@ -558,15 +591,49 @@ static int consumer_start( mlt_consumer this ) mlt_service service = mlt_service_producer( mlt_consumer_service( this ) ); if ( service != NULL ) { - char *resource = mlt_properties_get( mlt_consumer_properties( this ), "resource" ); + mlt_properties properties = mlt_consumer_properties( this ); + char *resource = mlt_properties_get( properties, "resource" ); + + // Set the title if provided + if ( mlt_properties_get( properties, "title" ) ) + mlt_properties_set( mlt_service_properties( service ), "title", mlt_properties_get( properties, "title" ) ); + else if ( mlt_properties_get( mlt_service_properties( service ), "title" ) == NULL ) + mlt_properties_set( mlt_service_properties( service ), "title", "Anonymous Submission" ); + // Check for a root on the consumer properties and pass to service + if ( mlt_properties_get( properties, "root" ) ) + mlt_properties_set( mlt_service_properties( service ), "root", mlt_properties_get( properties, "root" ) ); + + // Specify roots in other cases... + if ( resource != NULL && mlt_properties_get( properties, "root" ) == NULL ) + { + // Get the current working directory + char *cwd = getcwd( NULL, 0 ); + mlt_properties_set( mlt_service_properties( service ), "root", cwd ); + free( cwd ); + } + + // Make the document doc = westley_make_doc( service ); - + + // Handle the output if ( resource == NULL || !strcmp( resource, "" ) ) + { xmlDocFormatDump( stdout, doc, 1 ); + } + else if ( !strcmp( resource, "buffer" ) ) + { + xmlChar *buffer = NULL; + int length = 0; + xmlDocDumpMemory( doc, &buffer, &length ); + mlt_properties_set_data( properties, "buffer", buffer, length, xmlFree, NULL ); + } else + { xmlSaveFormatFile( resource, doc, 1 ); + } + // Close the document xmlFreeDoc( doc ); } diff --git a/src/modules/westley/factory.c b/src/modules/westley/factory.c index e60cd56..4e88388 100644 --- a/src/modules/westley/factory.c +++ b/src/modules/westley/factory.c @@ -26,7 +26,9 @@ void *mlt_create_producer( char *id, void *arg ) { if ( !strcmp( id, "westley" ) ) - return producer_westley_init( arg ); + return producer_westley_init( 0, arg ); + if ( !strcmp( id, "westley-xml" ) ) + return producer_westley_init( 1, arg ); return NULL; } diff --git a/src/modules/westley/producer_westley.c b/src/modules/westley/producer_westley.c index 8705035..46fd809 100644 --- a/src/modules/westley/producer_westley.c +++ b/src/modules/westley/producer_westley.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include // for xmlCreateFileParserCtxt @@ -172,13 +173,14 @@ static inline void qualify_property( deserialise_context context, mlt_properties if ( resource != NULL ) { // Qualify file name properties - char *root = mlt_properties_get( context->producer_map, "_root" ); - if ( root != NULL ) + char *root = mlt_properties_get( context->producer_map, "root" ); + if ( root != NULL && strcmp( root, "" ) ) { - char *full_resource = malloc( strlen( root ) + strlen( resource ) + 1 ); - if ( resource[ 0 ] != '/' ) + char *full_resource = malloc( strlen( root ) + strlen( resource ) + 2 ); + if ( resource[ 0 ] != '/' && strchr( resource, ':' ) == NULL ) { strcpy( full_resource, root ); + strcat( full_resource, "/" ); strcat( full_resource, resource ); } else @@ -1000,6 +1002,9 @@ static void on_start_element( void *ctx, const xmlChar *name, const xmlChar **at on_start_transition( context, name, atts ); else if ( strcmp( name, "property" ) == 0 ) on_start_property( context, name, atts ); + else if ( strcmp( name, "westley" ) == 0 ) + for ( ; atts != NULL && *atts != NULL; atts += 2 ) + mlt_properties_set( context->producer_map, ( char * )atts[ 0 ], ( char * )atts[ 1 ] ); } static void on_end_element( void *ctx, const xmlChar *name ) @@ -1213,9 +1218,9 @@ static void parse_url( mlt_properties properties, char *url ) mlt_properties_set( properties, name, value ); } -mlt_producer producer_westley_init( char *url ) +mlt_producer producer_westley_init( int info, char *data ) { - if ( url == NULL ) + if ( data == NULL ) return NULL; xmlSAXHandler *sax = calloc( 1, sizeof( xmlSAXHandler ) ); struct deserialise_context_s *context = calloc( 1, sizeof( struct deserialise_context_s ) ); @@ -1223,28 +1228,43 @@ mlt_producer producer_westley_init( char *url ) int i = 0; struct _xmlParserCtxt *xmlcontext; int well_formed = 0; - char *filename = strdup( url ); + char *filename = NULL; context->producer_map = mlt_properties_new(); context->destructors = mlt_properties_new(); context->params = mlt_properties_new(); - // Decode URL and parse parameters - parse_url( context->params, url_decode( filename, url ) ); + // Decode URL and parse parameters + mlt_properties_set( context->producer_map, "root", "" ); + if ( info == 0 ) + { + filename = strdup( data ); + parse_url( context->params, url_decode( filename, data ) ); - // We need to track the number of registered filters - mlt_properties_set_int( context->destructors, "registered", 0 ); + // We need the directory prefix which was used for the westley + if ( strchr( filename, '/' ) ) + { + char *root = NULL; + mlt_properties_set( context->producer_map, "root", filename ); + root = mlt_properties_get( context->producer_map, "root" ); + *( strrchr( root, '/' ) ) = '\0'; - // We need the directory prefix which was used for the westley - mlt_properties_set( context->producer_map, "_root", "" ); - if ( strchr( filename, '/' ) ) - { - char *root = NULL; - mlt_properties_set( context->producer_map, "_root", filename ); - root = mlt_properties_get( context->producer_map, "_root" ); - *( strrchr( root, '/' ) + 1 ) = '\0'; + // If we don't have an absolute path here, we're heading for disaster... + if ( root[ 0 ] != '/' ) + { + char *cwd = getcwd( NULL, 0 ); + char *real = malloc( strlen( cwd ) + strlen( root ) + 2 ); + sprintf( real, "%s/%s", cwd, root ); + mlt_properties_set( context->producer_map, "root", real ); + free( real ); + free( cwd ); + } + } } + // We need to track the number of registered filters + mlt_properties_set_int( context->destructors, "registered", 0 ); + // Setup SAX callbacks sax->startElement = on_start_element; sax->endElement = on_end_element; @@ -1259,7 +1279,11 @@ mlt_producer producer_westley_init( char *url ) xmlSubstituteEntitiesDefault( 1 ); // This is used to facilitate entity substitution in the SAX parser context->entity_doc = xmlNewDoc( "1.0" ); - xmlcontext = xmlCreateFileParserCtxt( filename ); + if ( info == 0 ) + xmlcontext = xmlCreateFileParserCtxt( filename ); + else + xmlcontext = xmlCreateMemoryParserCtxt( data, strlen( data ) ); + xmlcontext->sax = sax; xmlcontext->_private = ( void* )context; @@ -1296,6 +1320,7 @@ mlt_producer producer_westley_init( char *url ) if ( well_formed && service != NULL ) { + char *title = mlt_properties_get( context->producer_map, "title" ); // Need the complete producer list for various reasons properties = context->destructors; @@ -1318,10 +1343,15 @@ mlt_producer producer_westley_init( char *url ) // make the returned service destroy the connected services mlt_properties_set_data( properties, "__destructors__", context->destructors, 0, (mlt_destructor) mlt_properties_close, NULL ); + // Assign the title + mlt_properties_set( properties, "title", title ); + + // Handle deep copies if ( getenv( "MLT_WESTLEY_DEEP" ) == NULL ) { // Now assign additional properties - mlt_properties_set( properties, "resource", url ); + if ( info == 0 ) + mlt_properties_set( properties, "resource", data ); // This tells consumer_westley not to deep copy mlt_properties_set( properties, "westley", "was here" ); diff --git a/src/modules/westley/producer_westley.h b/src/modules/westley/producer_westley.h index 979a0d7..8f8a485 100644 --- a/src/modules/westley/producer_westley.h +++ b/src/modules/westley/producer_westley.h @@ -23,6 +23,6 @@ #include -extern mlt_producer producer_westley_init( char *filename ); +extern mlt_producer producer_westley_init( int type, char *data ); #endif diff --git a/src/valerie/Makefile b/src/valerie/Makefile index 67b6cf7..8d96f0c 100644 --- a/src/valerie/Makefile +++ b/src/valerie/Makefile @@ -24,7 +24,8 @@ INCS = valerie.h \ SRCS := $(OBJS:.o=.c) -LDFLAGS += -lpthread +CFLAGS += -I.. -rdynamic +LDFLAGS += -L ../framework -lmlt -lpthread all: $(TARGET) diff --git a/src/valerie/valerie.c b/src/valerie/valerie.c index ba8e228..8499f44 100644 --- a/src/valerie/valerie.c +++ b/src/valerie/valerie.c @@ -145,6 +145,37 @@ valerie_error_code valerie_execute( valerie this, size_t size, char *format, ... return error; } +/** Execute a command. +*/ + +valerie_error_code valerie_push( valerie this, mlt_service service, size_t size, char *format, ... ) +{ + valerie_error_code error = valerie_server_unavailable; + char *command = malloc( size ); + if ( this != NULL && command != NULL ) + { + va_list list; + va_start( list, format ); + if ( vsnprintf( command, size, format, list ) != 0 ) + { + valerie_response response = valerie_parser_push( this->parser, command, service ); + valerie_set_last_response( this, response ); + error = valerie_get_error_code( this, response ); + } + else + { + error = valerie_invalid_command; + } + va_end( list ); + } + else + { + error = valerie_malloc_failed; + } + free( command ); + return error; +} + /** Set a global property. */ @@ -252,6 +283,14 @@ valerie_error_code valerie_unit_append( valerie this, int unit, char *file, int3 return valerie_execute( this, 10240, "APND U%d \"%s\" %d %d", unit, file, in, out ); } +/** Push a service on to a unit. +*/ + +valerie_error_code valerie_unit_push( valerie this, int unit, char *command, mlt_service service ) +{ + return valerie_push( this, service, 10240, "PUSH U%d %s", unit, command ); +} + /** Clean the unit - this function removes all but the currently playing clip. */ diff --git a/src/valerie/valerie.h b/src/valerie/valerie.h index 663b6c2..eb3c9bf 100644 --- a/src/valerie/valerie.h +++ b/src/valerie/valerie.h @@ -24,6 +24,9 @@ /* System header files */ #include +/* MLT Header files. */ +#include + /* Application header files */ #include "valerie_parser.h" #include "valerie_status.h" @@ -94,6 +97,7 @@ extern valerie_error_code valerie_unit_load_clipped( valerie, int, char *, int32 extern valerie_error_code valerie_unit_load_back( valerie, int, char * ); extern valerie_error_code valerie_unit_load_back_clipped( valerie, int, char *, int32_t, int32_t ); extern valerie_error_code valerie_unit_append( valerie, int, char *, int32_t, int32_t ); +extern valerie_error_code valerie_unit_push( valerie, int, char *, mlt_service ); extern valerie_error_code valerie_unit_clean( valerie, int ); extern valerie_error_code valerie_unit_clear( valerie, int ); extern valerie_error_code valerie_unit_clip_move( valerie, int, valerie_clip_offset, int, valerie_clip_offset, int ); @@ -246,6 +250,7 @@ extern char *valerie_error_description( valerie_error_code ); /* Courtesy functions. */ extern valerie_error_code valerie_execute( valerie, size_t, char *, ... ); +extern valerie_error_code valerie_push( valerie, mlt_service, size_t, char *, ... ); /* Close function. */ extern void valerie_close( valerie ); diff --git a/src/valerie/valerie_parser.c b/src/valerie/valerie_parser.c index 4ead1c0..2b90fed 100644 --- a/src/valerie/valerie_parser.c +++ b/src/valerie/valerie_parser.c @@ -44,6 +44,14 @@ valerie_response valerie_parser_execute( valerie_parser parser, char *command ) return parser->execute( parser->real, command ); } +/** Push a service via the parser. +*/ + +valerie_response valerie_parser_push( valerie_parser parser, char *command, mlt_service service ) +{ + return parser->push( parser->real, command, service ); +} + /** Execute a formatted command via the parser. */ diff --git a/src/valerie/valerie_parser.h b/src/valerie/valerie_parser.h index 71446d9..3e1a17b 100644 --- a/src/valerie/valerie_parser.h +++ b/src/valerie/valerie_parser.h @@ -21,6 +21,9 @@ #ifndef _VALERIE_PARSER_H_ #define _VALERIE_PARSER_H_ +/* MLT Header files */ +#include + /* Application header files */ #include "valerie_response.h" #include "valerie_notifier.h" @@ -35,6 +38,7 @@ extern "C" typedef valerie_response (*parser_connect)( void * ); typedef valerie_response (*parser_execute)( void *, char * ); +typedef valerie_response (*parser_push)( void *, char *, mlt_service ); typedef void (*parser_close)( void * ); /** Structure for the valerie parser. @@ -44,6 +48,7 @@ typedef struct { parser_connect connect; parser_execute execute; + parser_push push; parser_close close; void *real; valerie_notifier notifier; @@ -54,6 +59,7 @@ typedef struct */ extern valerie_response valerie_parser_connect( valerie_parser ); +extern valerie_response valerie_parser_push( valerie_parser, char *, mlt_service ); extern valerie_response valerie_parser_execute( valerie_parser, char * ); extern valerie_response valerie_parser_executef( valerie_parser, char *, ... ); extern valerie_response valerie_parser_run( valerie_parser, char * ); diff --git a/src/valerie/valerie_remote.c b/src/valerie/valerie_remote.c index 4b5023e..f770035 100644 --- a/src/valerie/valerie_remote.c +++ b/src/valerie/valerie_remote.c @@ -27,6 +27,7 @@ #include /* Application header files */ +#include #include "valerie_remote.h" #include "valerie_socket.h" #include "valerie_tokeniser.h" @@ -54,6 +55,7 @@ typedef struct static valerie_response valerie_remote_connect( valerie_remote ); static valerie_response valerie_remote_execute( valerie_remote, char * ); +static valerie_response valerie_remote_push( valerie_remote, char *, mlt_service ); static void valerie_remote_close( valerie_remote ); static int valerie_remote_read_response( valerie_socket, valerie_response ); @@ -62,21 +64,19 @@ static int valerie_remote_read_response( valerie_socket, valerie_response ); valerie_parser valerie_parser_init_remote( char *server, int port ) { - valerie_parser parser = malloc( sizeof( valerie_parser_t ) ); - valerie_remote remote = malloc( sizeof( valerie_remote_t ) ); + valerie_parser parser = calloc( 1, sizeof( valerie_parser_t ) ); + valerie_remote remote = calloc( 1, sizeof( valerie_remote_t ) ); if ( parser != NULL ) { - memset( parser, 0, sizeof( valerie_parser_t ) ); - parser->connect = (parser_connect)valerie_remote_connect; parser->execute = (parser_execute)valerie_remote_execute; + parser->push = (parser_push)valerie_remote_push; parser->close = (parser_close)valerie_remote_close; parser->real = remote; if ( remote != NULL ) { - memset( remote, 0, sizeof( valerie_remote_t ) ); remote->parser = parser; remote->server = strdup( server ); remote->port = port; @@ -194,6 +194,37 @@ static valerie_response valerie_remote_execute( valerie_remote remote, char *com return response; } +/** Push a producer to the server. +*/ + +static valerie_response valerie_remote_push( valerie_remote remote, char *command, mlt_service service ) +{ + valerie_response response = NULL; + pthread_mutex_lock( &remote->mutex ); + if ( valerie_socket_write_data( remote->socket, command, strlen( command ) ) == strlen( command ) ) + { + mlt_consumer consumer = mlt_factory_consumer( "westley", "buffer" ); + mlt_properties properties = mlt_consumer_properties( consumer ); + char temp[ 20 ]; + char *buffer = NULL; + int length = 0; + mlt_consumer_connect( consumer, service ); + response = valerie_response_init( ); + valerie_socket_write_data( remote->socket, "\r\n", 2 ); + mlt_consumer_start( consumer ); + buffer = mlt_properties_get_data( properties, "buffer", &length ); + sprintf( temp, "%d", length ); + valerie_socket_write_data( remote->socket, temp, strlen( temp ) ); + valerie_socket_write_data( remote->socket, "\r\n", 2 ); + valerie_socket_write_data( remote->socket, buffer, length ); + valerie_socket_write_data( remote->socket, "\r\n", 2 ); + valerie_remote_read_response( remote->socket, response ); + mlt_consumer_close( consumer ); + } + pthread_mutex_unlock( &remote->mutex ); + return response; +} + /** Disconnect. */ @@ -201,7 +232,8 @@ static void valerie_remote_disconnect( valerie_remote remote ) { if ( remote != NULL && remote->terminated ) { - pthread_join( remote->thread, NULL ); + if ( remote->connected ) + pthread_join( remote->thread, NULL ); valerie_socket_close( remote->status ); valerie_socket_close( remote->socket ); remote->connected = 0; -- 1.7.4.4