Merge mlt++/CUSTOMISING into docs/melted++.
[melted] / src / miracle / miracle_local.c
index 71b7b77..c1029a1 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
+
+/* Needed for backtrace on linux */
+#ifdef linux
 #include <execinfo.h>
+#endif
 
 /* Valerie header files */
 #include <valerie/valerie_util.h>
@@ -56,6 +60,8 @@ 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 valerie_response miracle_local_receive( miracle_local, char *, char * );
 static void miracle_local_close( miracle_local );
 response_codes miracle_help( command_argument arg );
 response_codes miracle_run( command_argument arg );
@@ -75,6 +81,8 @@ 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->received = (parser_received)miracle_local_receive;
                parser->close = (parser_close)miracle_local_close;
                parser->real = local;
 
@@ -97,7 +105,7 @@ valerie_parser miracle_parser_init_local( )
 typedef struct 
 {
        int code;
-       char *message;
+       const char *message;
 } 
 responses_t;
 
@@ -127,7 +135,8 @@ typedef enum
        ATYPE_NONE,
        ATYPE_FLOAT,
        ATYPE_STRING,
-       ATYPE_INT
+       ATYPE_INT,
+       ATYPE_PAIR
 } 
 arguments_types;
 
@@ -137,7 +146,7 @@ arguments_types;
 typedef struct 
 {
 /* The command string corresponding to this operation (e.g. "play") */
-       char *command;
+       const char *command;
 /* The function associated with it */
        response_codes (*operation) ( command_argument );
 /* a boolean to indicate if this is a unit or global command
@@ -146,7 +155,7 @@ typedef struct
 /* What type is the argument (RTTI :-) ATYPE_whatever */
        int type;
 /* online help information */
-       char *help;
+       const char *help;
 } 
 command_t;
 
@@ -165,7 +174,7 @@ static command_t vocabulary[] =
        {"UADD", miracle_add_unit, 0, ATYPE_STRING, "Create a new DV unit (virtual VTR) to transmit to receiver specified in GUID argument."},
        {"ULS", miracle_list_units, 0, ATYPE_NONE, "Lists the units that have already been added to the server."},
        {"CLS", miracle_list_clips, 0, ATYPE_STRING, "Lists the clips at directory name argument."},
-       {"SET", miracle_set_global_property, 0, ATYPE_STRING, "Set a server configuration property."},
+       {"SET", miracle_set_global_property, 0, ATYPE_PAIR, "Set a server configuration property."},
        {"GET", miracle_get_global_property, 0, ATYPE_STRING, "Get a server configuration property."},
        {"RUN", miracle_run, 0, ATYPE_STRING, "Run a batch file." },
        {"LIST", miracle_list, 1, ATYPE_NONE, "List the playlist associated to a unit."},
@@ -173,6 +182,8 @@ static command_t vocabulary[] =
        {"INSERT", miracle_insert, 1, ATYPE_STRING, "Insert a clip at the given clip index."},
        {"REMOVE", miracle_remove, 1, ATYPE_NONE, "Remove a clip at the given clip index."},
        {"CLEAN", miracle_clean, 1, ATYPE_NONE, "Clean a unit by removing all but the currently playing clip."},
+       {"WIPE", miracle_wipe, 1, ATYPE_NONE, "Clean a unit by removing everything before the currently playing clip."},
+       {"CLEAR", miracle_clear, 1, ATYPE_NONE, "Clear a unit by removing all clips."},
        {"MOVE", miracle_move, 1, ATYPE_INT, "Move a clip to another clip index."},
        {"APND", miracle_append, 1, ATYPE_STRING, "Append a clip specified in absolute filename argument."},
        {"PLAY", miracle_play, 1, ATYPE_NONE, "Play a loaded clip at speed -2000 to 2000 where 1000 = normal forward speed."},
@@ -185,7 +196,7 @@ static command_t vocabulary[] =
        {"SIN", miracle_set_in_point, 1, ATYPE_INT, "Set the IN point of the loaded clip to frame number argument. -1 = reset in point to 0"},
        {"SOUT", miracle_set_out_point, 1, ATYPE_INT, "Set the OUT point of the loaded clip to frame number argument. -1 = reset out point to maximum."},
        {"USTA", miracle_get_unit_status, 1, ATYPE_NONE, "Report information about the unit."},
-       {"USET", miracle_set_unit_property, 1, ATYPE_STRING, "Set a unit configuration property."},
+       {"USET", miracle_set_unit_property, 1, ATYPE_PAIR, "Set a unit configuration property."},
        {"UGET", miracle_get_unit_property, 1, ATYPE_STRING, "Get a unit configuration property."},
        {"XFER", miracle_transfer, 1, ATYPE_STRING, "Transfer the unit's clip to another unit specified as argument."},
        {"SHUTDOWN", miracle_shutdown, 0, ATYPE_NONE, "Shutdown the server."},
@@ -206,7 +217,7 @@ static char helpstr [] =
 /** Lookup the response message for a status code.
 */
 
-inline char *get_response_msg( int code )
+inline const char *get_response_msg( int code )
 {
        int i = 0;
        for ( i = 0; responses[ i ].message != NULL && code != responses[ i ].code; i ++ ) ;
@@ -289,6 +300,7 @@ void signal_handler( int sig )
 
 static void sigsegv_handler()
 {
+#ifdef linux
        void *array[ 10 ];
        size_t size;
        char **strings;
@@ -307,6 +319,9 @@ static void sigsegv_handler()
        free( strings );
 
        miracle_log( LOG_CRIT, "\nDone dumping - exiting.\n" );
+#else
+       miracle_log( LOG_CRIT, "\a\nMiracle experienced a segmentation fault.\n" );
+#endif
        exit( EXIT_FAILURE );
 }
 
@@ -359,7 +374,7 @@ int miracle_command_parse_unit( command_argument cmd, int argument )
 /** Parse a normal argument.
 */
 
-void *miracle_command_parse_argument( command_argument cmd, int argument, arguments_types type )
+void *miracle_command_parse_argument( command_argument cmd, int argument, arguments_types type, char *command )
 {
        void *ret = NULL;
        char *value = valerie_tokeniser_get_string( cmd->tokeniser, argument );
@@ -381,6 +396,19 @@ void *miracle_command_parse_argument( command_argument cmd, int argument, argume
                                ret = strdup( value );
                                break;
                                        
+                       case ATYPE_PAIR:
+                               if ( strchr( command, '=' ) )
+                               {
+                                       char *ptr = strchr( command, '=' );
+                                       while ( *( ptr - 1 ) != ' ' ) 
+                                               ptr --;
+                                       ret = strdup( ptr );
+                                       ptr = ret;
+                                       while( ptr[ strlen( ptr ) - 1 ] == ' ' )
+                                               ptr[ strlen( ptr ) - 1 ] = '\0';
+                               }
+                               break;
+
                        case ATYPE_INT:
                                ret = malloc( sizeof( int ) );
                                if ( ret != NULL )
@@ -453,7 +481,7 @@ static valerie_response miracle_local_execute( miracle_local local, char *comman
 
                        if ( miracle_command_get_error( &cmd ) == RESPONSE_SUCCESS )
                        {
-                               cmd.argument = miracle_command_parse_argument( &cmd, position, vocabulary[ index ].type );
+                               cmd.argument = miracle_command_parse_argument( &cmd, position, vocabulary[ index ].type, command );
                                if ( cmd.argument == NULL && vocabulary[ index ].type != ATYPE_NONE )
                                        miracle_command_set_error( &cmd, RESPONSE_MISSING_ARG );
                                position ++;
@@ -474,14 +502,96 @@ static valerie_response miracle_local_execute( miracle_local local, char *comman
        return cmd.response;
 }
 
+static valerie_response miracle_local_receive( miracle_local local, char *command, char *doc )
+{
+       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_receive( &cmd, doc );
+               miracle_command_set_error( &cmd, RESPONSE_SUCCESS );
+
+               free( cmd.argument );
+       }
+
+       valerie_tokeniser_close( cmd.tokeniser );
+
+       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.
 */
 
 static void miracle_local_close( miracle_local local )
 {
        miracle_delete_all_units();
-       pthread_kill_other_threads_np();
+#ifdef linux
+       //pthread_kill_other_threads_np();
        miracle_log( LOG_DEBUG, "Clean shutdown." );
-       free( local );
+       //free( local );
        //mlt_factory_close( );
+#endif
 }