/** 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 );
+ }
}
}
}
{
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( );
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 );
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 ) );
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 );
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;
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.
*/
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 );
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;
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.
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 );
}
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 );
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,
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;
}
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;
}
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
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;
}
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 );
{
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." );
}
typedef struct
{
mlt_properties properties;
- mlt_properties producers;
- mlt_properties old_producers;
+ mlt_playlist old_playlist;
}
miracle_unit_t, *miracle_unit;
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 );
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);
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
}
rm -f .depend
clean:
+ if [ $(LOCAL_FFMPEG) ] ; then $(MAKE) -C ffmpeg clean ; fi
rm -f $(OBJS) $(TARGET)
install: all
{
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
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 );
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;
}
{
rgba_color result = { 0xff, 0xff, 0xff, 0xff };
+ if ( strchr( color, '/' ) )
+ color = strrchr( color, '/' ) + 1;
+
if ( !strncmp( color, "0x", 2 ) )
{
unsigned int temp = 0;
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 :-).
*/
// 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 );
*/
#include <string.h>
-
+#include <gdk-pixbuf/gdk-pixbuf.h>
#include "producer_pixbuf.h"
#include "producer_pango.h"
#include "filter_rescale.h"
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 );
{
if ( producer != NULL )
mlt_playlist_append( playlist, producer );
+ if ( title == NULL )
+ title = argv[ i ];
producer = create_producer( field, argv[ i ] );
if ( producer != NULL )
{
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;
}
{
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
}
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 )
LDFLAGS += -lst -lpopt -lvorbis -logg -lvorbisfile -lvorbisenc
-LDFLAGS+=-L../../framework -lmlt -lmad
+LDFLAGS+=-L../../framework -lmlt -lmp3lame
SRCS := $(OBJS:.o=.c)
--- /dev/null
+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
--- /dev/null
+#!/bin/sh
+
+if [ "$help" != "1" ]
+then
+
+cat << EOF >> ../consumers.dat
+valerie libmltvalerie.so
+EOF
+
+fi
+
--- /dev/null
+/*
+ * consumer_westley.c -- a libxml2 serialiser of mlt service networks
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Dan Dennedy <dan@dennedy.org>
+ *
+ * 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 <valerie/valerie.h>
+#include <valerie/valerie_remote.h>
+#include <framework/mlt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+
+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;
+}
--- /dev/null
+/*
+ * consumer_valerie.h -- pushes a service via valerie
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@telenet.be>
+ *
+ * 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 <framework/mlt_consumer.h>
+
+extern mlt_consumer consumer_valerie_init( char * );
+
+#endif
--- /dev/null
+/*
+ * factory.c -- the factory method interfaces
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * 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 <string.h>
+
+#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;
+}
+
cat << EOF >> ../producers.dat
westley libmltwestley.so
+westley-xml libmltwestley.so
EOF
cat << EOF >> ../consumers.dat
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
+#include <unistd.h>
#include <libxml/tree.h>
#define ID_SIZE 128
int transition_count;
int pass;
mlt_properties hide_map;
+ char *root;
};
typedef struct serialise_context_s* serialise_context;
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;
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 );
}
}
}
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 );
}
}
// 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
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 );
}
}
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 );
}
}
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();
// 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;
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 );
}
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;
}
#include <string.h>
#include <stdio.h>
#include <ctype.h>
+#include <unistd.h>
#include <libxml/parser.h>
#include <libxml/parserInternals.h> // for xmlCreateFileParserCtxt
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
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 )
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 ) );
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;
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;
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;
// 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" );
#include <framework/mlt_producer.h>
-extern mlt_producer producer_westley_init( char *filename );
+extern mlt_producer producer_westley_init( int type, char *data );
#endif
SRCS := $(OBJS:.o=.c)
-LDFLAGS += -lpthread
+CFLAGS += -I.. -rdynamic
+LDFLAGS += -L ../framework -lmlt -lpthread
all: $(TARGET)
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.
*/
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.
*/
/* System header files */
#include <limits.h>
+/* MLT Header files. */
+#include <framework/mlt.h>
+
/* Application header files */
#include "valerie_parser.h"
#include "valerie_status.h"
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 );
/* 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 );
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.
*/
#ifndef _VALERIE_PARSER_H_
#define _VALERIE_PARSER_H_
+/* MLT Header files */
+#include <framework/mlt.h>
+
/* Application header files */
#include "valerie_response.h"
#include "valerie_notifier.h"
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.
{
parser_connect connect;
parser_execute execute;
+ parser_push push;
parser_close close;
void *real;
valerie_notifier notifier;
*/
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 * );
#include <pthread.h>
/* Application header files */
+#include <framework/mlt.h>
#include "valerie_remote.h"
#include "valerie_socket.h"
#include "valerie_tokeniser.h"
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 );
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;
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.
*/
{
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;