2 * valerie.c -- High Level Client API for miracle
3 * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
4 * Author: Charles Yates <charles.yates@pandora.be>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 /* System header files */
27 /* Application header files */
29 #include "valerie_tokeniser.h"
30 #include "valerie_util.h"
32 /** Initialise the valerie structure.
35 valerie valerie_init( valerie_parser parser )
37 valerie this = malloc( sizeof( valerie_t ) );
40 memset( this, 0, sizeof( valerie_t ) );
41 this->parser = parser;
46 /** Set the response structure associated to the last command.
49 static void valerie_set_last_response( valerie this, valerie_response response )
53 if ( this->last_response != NULL )
54 valerie_response_close( this->last_response );
55 this->last_response = response;
59 /** Connect to the parser.
62 valerie_error_code valerie_connect( valerie this )
64 valerie_error_code error = valerie_server_unavailable;
65 valerie_response response = valerie_parser_connect( this->parser );
66 if ( response != NULL )
68 valerie_set_last_response( this, response );
69 if ( valerie_response_get_error_code( response ) == 100 )
75 /** Interpret a non-context sensitive error code.
78 static valerie_error_code valerie_get_error_code( valerie this, valerie_response response )
80 valerie_error_code error = valerie_server_unavailable;
81 switch( valerie_response_get_error_code( response ) )
84 error = valerie_server_unavailable;
87 error = valerie_no_response;
95 error = valerie_invalid_command;
98 error = valerie_server_timeout;
101 error = valerie_missing_argument;
104 error = valerie_unit_unavailable;
107 error = valerie_invalid_file;
111 error = valerie_unknown_error;
117 /** Execute a command.
120 valerie_error_code valerie_execute( valerie this, size_t size, const char *format, ... )
122 valerie_error_code error = valerie_server_unavailable;
123 char *command = malloc( size );
124 if ( this != NULL && command != NULL )
127 va_start( list, format );
128 if ( vsnprintf( command, size, format, list ) != 0 )
130 valerie_response response = valerie_parser_execute( this->parser, command );
131 valerie_set_last_response( this, response );
132 error = valerie_get_error_code( this, response );
136 error = valerie_invalid_command;
142 error = valerie_malloc_failed;
148 /** Execute a command.
151 valerie_error_code valerie_receive( valerie this, char *doc, size_t size, const char *format, ... )
153 valerie_error_code error = valerie_server_unavailable;
154 char *command = malloc( size );
155 if ( this != NULL && command != NULL )
158 va_start( list, format );
159 if ( vsnprintf( command, size, format, list ) != 0 )
161 valerie_response response = valerie_parser_received( this->parser, command, doc );
162 valerie_set_last_response( this, response );
163 error = valerie_get_error_code( this, response );
167 error = valerie_invalid_command;
173 error = valerie_malloc_failed;
179 /** Execute a command.
182 valerie_error_code valerie_push( valerie this, mlt_service service, size_t size, const char *format, ... )
184 valerie_error_code error = valerie_server_unavailable;
185 char *command = malloc( size );
186 if ( this != NULL && command != NULL )
189 va_start( list, format );
190 if ( vsnprintf( command, size, format, list ) != 0 )
192 valerie_response response = valerie_parser_push( this->parser, command, service );
193 valerie_set_last_response( this, response );
194 error = valerie_get_error_code( this, response );
198 error = valerie_invalid_command;
204 error = valerie_malloc_failed;
210 /** Set a global property.
213 valerie_error_code valerie_set( valerie this, char *property, char *value )
215 return valerie_execute( this, 1024, "SET %s=%s", property, value );
218 /** Get a global property.
221 valerie_error_code valerie_get( valerie this, char *property, char *value, int length )
223 valerie_error_code error = valerie_execute( this, 1024, "GET %s", property );
224 if ( error == valerie_ok )
226 valerie_response response = valerie_get_last_response( this );
227 strncpy( value, valerie_response_get_line( response, 1 ), length );
235 valerie_error_code valerie_run( valerie this, char *file )
237 return valerie_execute( this, 10240, "RUN \"%s\"", file );
243 valerie_error_code valerie_unit_add( valerie this, char *guid, int *unit )
245 valerie_error_code error = valerie_execute( this, 1024, "UADD %s", guid );
246 if ( error == valerie_ok )
248 int length = valerie_response_count( this->last_response );
249 char *line = valerie_response_get_line( this->last_response, length - 1 );
250 if ( line == NULL || sscanf( line, "U%d", unit ) != 1 )
251 error = valerie_unit_creation_failed;
255 if ( error == valerie_unknown_error )
256 error = valerie_unit_creation_failed;
261 /** Load a file on the specified unit.
264 valerie_error_code valerie_unit_load( valerie this, int unit, char *file )
266 return valerie_execute( this, 10240, "LOAD U%d \"%s\"", unit, file );
269 static void valerie_interpret_clip_offset( char *output, valerie_clip_offset offset, int clip )
273 case valerie_absolute:
274 sprintf( output, "%d", clip );
276 case valerie_relative:
278 sprintf( output, "%d", clip );
280 sprintf( output, "+%d", clip );
285 /** Load a file on the specified unit with the specified in/out points.
288 valerie_error_code valerie_unit_load_clipped( valerie this, int unit, char *file, int32_t in, int32_t out )
290 return valerie_execute( this, 10240, "LOAD U%d \"%s\" %d %d", unit, file, in, out );
293 /** Load a file on the specified unit at the end of the current pump.
296 valerie_error_code valerie_unit_load_back( valerie this, int unit, char *file )
298 return valerie_execute( this, 10240, "LOAD U%d \"!%s\"", unit, file );
301 /** Load a file on the specified unit at the end of the pump with the specified in/out points.
304 valerie_error_code valerie_unit_load_back_clipped( valerie this, int unit, char *file, int32_t in, int32_t out )
306 return valerie_execute( this, 10240, "LOAD U%d \"!%s\" %d %d", unit, file, in, out );
309 /** Append a file on the specified unit.
312 valerie_error_code valerie_unit_append( valerie this, int unit, char *file, int32_t in, int32_t out )
314 return valerie_execute( this, 10240, "APND U%d \"%s\" %d %d", unit, file, in, out );
317 /** Push a service on to a unit.
320 valerie_error_code valerie_unit_receive( valerie this, int unit, char *command, char *doc )
322 return valerie_receive( this, doc, 10240, "PUSH U%d %s", unit, command );
325 /** Push a service on to a unit.
328 valerie_error_code valerie_unit_push( valerie this, int unit, char *command, mlt_service service )
330 return valerie_push( this, service, 10240, "PUSH U%d %s", unit, command );
333 /** Clean the unit - this function removes all but the currently playing clip.
336 valerie_error_code valerie_unit_clean( valerie this, int unit )
338 return valerie_execute( this, 1024, "CLEAN U%d", unit );
341 /** Clear the unit - this function removes all clips.
344 valerie_error_code valerie_unit_clear( valerie this, int unit )
346 return valerie_execute( this, 1024, "CLEAR U%d", unit );
349 /** Wipe the unit - this function removes all clips before the current one.
352 valerie_error_code valerie_unit_wipe( valerie this, int unit )
354 return valerie_execute( this, 1024, "WIPE U%d", unit );
357 /** Move clips on the units playlist.
360 valerie_error_code valerie_unit_clip_move( valerie this, int unit, valerie_clip_offset src_offset, int src, valerie_clip_offset dest_offset, int dest )
364 valerie_interpret_clip_offset( temp1, src_offset, src );
365 valerie_interpret_clip_offset( temp2, dest_offset, dest );
366 return valerie_execute( this, 1024, "MOVE U%d %s %s", unit, temp1, temp2 );
369 /** Remove clip at the specified position.
372 valerie_error_code valerie_unit_clip_remove( valerie this, int unit, valerie_clip_offset offset, int clip )
375 valerie_interpret_clip_offset( temp, offset, clip );
376 return valerie_execute( this, 1024, "REMOVE U%d %s", unit, temp );
379 /** Remove the currently playing clip.
382 valerie_error_code valerie_unit_remove_current_clip( valerie this, int unit )
384 return valerie_execute( this, 1024, "REMOVE U%d", unit );
387 /** Insert clip at the specified position.
390 valerie_error_code valerie_unit_clip_insert( valerie this, int unit, valerie_clip_offset offset, int clip, char *file, int32_t in, int32_t out )
393 valerie_interpret_clip_offset( temp, offset, clip );
394 return valerie_execute( this, 1024, "INSERT U%d \"%s\" %s %d %d", unit, file, temp, in, out );
397 /** Play the unit at normal speed.
400 valerie_error_code valerie_unit_play( valerie this, int unit )
402 return valerie_execute( this, 1024, "PLAY U%d 1000", unit );
405 /** Play the unit at specified speed.
408 valerie_error_code valerie_unit_play_at_speed( valerie this, int unit, int speed )
410 return valerie_execute( this, 10240, "PLAY U%d %d", unit, speed );
413 /** Stop playback on the specified unit.
416 valerie_error_code valerie_unit_stop( valerie this, int unit )
418 return valerie_execute( this, 1024, "STOP U%d", unit );
421 /** Pause playback on the specified unit.
424 valerie_error_code valerie_unit_pause( valerie this, int unit )
426 return valerie_execute( this, 1024, "PAUSE U%d", unit );
429 /** Rewind the specified unit.
432 valerie_error_code valerie_unit_rewind( valerie this, int unit )
434 return valerie_execute( this, 1024, "REW U%d", unit );
437 /** Fast forward the specified unit.
440 valerie_error_code valerie_unit_fast_forward( valerie this, int unit )
442 return valerie_execute( this, 1024, "FF U%d", unit );
445 /** Step by the number of frames on the specified unit.
448 valerie_error_code valerie_unit_step( valerie this, int unit, int32_t step )
450 return valerie_execute( this, 1024, "STEP U%d %d", unit, step );
453 /** Goto the specified frame on the specified unit.
456 valerie_error_code valerie_unit_goto( valerie this, int unit, int32_t position )
458 return valerie_execute( this, 1024, "GOTO U%d %d", unit, position );
461 /** Goto the specified frame in the clip on the specified unit.
464 valerie_error_code valerie_unit_clip_goto( valerie this, int unit, valerie_clip_offset offset, int clip, int32_t position )
467 valerie_interpret_clip_offset( temp, offset, clip );
468 return valerie_execute( this, 1024, "GOTO U%d %d %s", unit, position, temp );
471 /** Set the in point of the loaded file on the specified unit.
474 valerie_error_code valerie_unit_set_in( valerie this, int unit, int32_t in )
476 return valerie_execute( this, 1024, "SIN U%d %d", unit, in );
479 /** Set the in point of the clip on the specified unit.
482 valerie_error_code valerie_unit_clip_set_in( valerie this, int unit, valerie_clip_offset offset, int clip, int32_t in )
485 valerie_interpret_clip_offset( temp, offset, clip );
486 return valerie_execute( this, 1024, "SIN U%d %d %s", unit, in, temp );
489 /** Set the out point of the loaded file on the specified unit.
492 valerie_error_code valerie_unit_set_out( valerie this, int unit, int32_t out )
494 return valerie_execute( this, 1024, "SOUT U%d %d", unit, out );
497 /** Set the out point of the clip on the specified unit.
500 valerie_error_code valerie_unit_clip_set_out( valerie this, int unit, valerie_clip_offset offset, int clip, int32_t in )
503 valerie_interpret_clip_offset( temp, offset, clip );
504 return valerie_execute( this, 1024, "SOUT U%d %d %s", unit, in, temp );
507 /** Clear the in point of the loaded file on the specified unit.
510 valerie_error_code valerie_unit_clear_in( valerie this, int unit )
512 return valerie_execute( this, 1024, "SIN U%d -1", unit );
515 /** Clear the out point of the loaded file on the specified unit.
518 valerie_error_code valerie_unit_clear_out( valerie this, int unit )
520 return valerie_execute( this, 1024, "SOUT U%d -1", unit );
523 /** Clear the in and out points on the loaded file on the specified unit.
526 valerie_error_code valerie_unit_clear_in_out( valerie this, int unit )
528 valerie_error_code error = valerie_unit_clear_out( this, unit );
529 if ( error == valerie_ok )
530 error = valerie_unit_clear_in( this, unit );
534 /** Set a unit configuration property.
537 valerie_error_code valerie_unit_set( valerie this, int unit, const char *name, const char *value )
539 return valerie_execute( this, 1024, "USET U%d %s=%s", unit, name, value );
542 /** Get a unit configuration property.
545 valerie_error_code valerie_unit_get( valerie this, int unit, char *name )
547 return valerie_execute( this, 1024, "UGET U%d %s", unit, name );
550 /** Get a units status.
553 valerie_error_code valerie_unit_status( valerie this, int unit, valerie_status status )
555 valerie_error_code error = valerie_execute( this, 1024, "USTA U%d", unit );
556 int error_code = valerie_response_get_error_code( this->last_response );
558 memset( status, 0, sizeof( valerie_status_t ) );
560 if ( error_code == 202 && valerie_response_count( this->last_response ) == 2 )
561 valerie_status_parse( status, valerie_response_get_line( this->last_response, 1 ) );
562 else if ( error_code == 403 )
563 status->status = unit_undefined;
568 /** Transfer the current settings of unit src to unit dest.
571 valerie_error_code valerie_unit_transfer( valerie this, int src, int dest )
573 return valerie_execute( this, 1024, "XFER U%d U%d", src, dest );
576 /** Obtain the parsers notifier.
579 valerie_notifier valerie_get_notifier( valerie this )
582 return valerie_parser_get_notifier( this->parser );
587 /** List the contents of the specified directory.
590 valerie_dir valerie_dir_init( valerie this, const char *directory )
592 valerie_dir dir = malloc( sizeof( valerie_dir_t ) );
595 memset( dir, 0, sizeof( valerie_dir_t ) );
596 dir->directory = strdup( directory );
597 dir->response = valerie_parser_executef( this->parser, "CLS \"%s\"", directory );
602 /** Return the error code associated to the dir.
605 valerie_error_code valerie_dir_get_error_code( valerie_dir dir )
608 return valerie_get_error_code( NULL, dir->response );
610 return valerie_malloc_failed;
613 /** Get a particular file entry in the directory.
616 valerie_error_code valerie_dir_get( valerie_dir dir, int index, valerie_dir_entry entry )
618 valerie_error_code error = valerie_ok;
619 memset( entry, 0, sizeof( valerie_dir_entry_t ) );
620 if ( index < valerie_dir_count( dir ) )
622 char *line = valerie_response_get_line( dir->response, index + 1 );
623 valerie_tokeniser tokeniser = valerie_tokeniser_init( );
624 valerie_tokeniser_parse_new( tokeniser, line, " " );
626 if ( valerie_tokeniser_count( tokeniser ) > 0 )
628 valerie_util_strip( valerie_tokeniser_get_string( tokeniser, 0 ), '\"' );
629 strcpy( entry->full, dir->directory );
630 if ( entry->full[ strlen( entry->full ) - 1 ] != '/' )
631 strcat( entry->full, "/" );
632 strcpy( entry->name, valerie_tokeniser_get_string( tokeniser, 0 ) );
633 strcat( entry->full, entry->name );
635 switch ( valerie_tokeniser_count( tokeniser ) )
641 entry->size = strtoull( valerie_tokeniser_get_string( tokeniser, 1 ), NULL, 10 );
644 error = valerie_invalid_file;
648 valerie_tokeniser_close( tokeniser );
653 /** Get the number of entries in the directory
656 int valerie_dir_count( valerie_dir dir )
658 if ( dir != NULL && valerie_response_count( dir->response ) >= 2 )
659 return valerie_response_count( dir->response ) - 2;
664 /** Close the directory structure.
667 void valerie_dir_close( valerie_dir dir )
671 free( dir->directory );
672 valerie_response_close( dir->response );
677 /** List the playlist of the specified unit.
680 valerie_list valerie_list_init( valerie this, int unit )
682 valerie_list list = calloc( 1, sizeof( valerie_list_t ) );
685 list->response = valerie_parser_executef( this->parser, "LIST U%d", unit );
686 if ( valerie_response_count( list->response ) >= 2 )
687 list->generation = atoi( valerie_response_get_line( list->response, 1 ) );
692 /** Return the error code associated to the list.
695 valerie_error_code valerie_list_get_error_code( valerie_list list )
698 return valerie_get_error_code( NULL, list->response );
700 return valerie_malloc_failed;
703 /** Get a particular file entry in the list.
706 valerie_error_code valerie_list_get( valerie_list list, int index, valerie_list_entry entry )
708 valerie_error_code error = valerie_ok;
709 memset( entry, 0, sizeof( valerie_list_entry_t ) );
710 if ( index < valerie_list_count( list ) )
712 char *line = valerie_response_get_line( list->response, index + 2 );
713 valerie_tokeniser tokeniser = valerie_tokeniser_init( );
714 valerie_tokeniser_parse_new( tokeniser, line, " " );
716 if ( valerie_tokeniser_count( tokeniser ) > 0 )
718 entry->clip = atoi( valerie_tokeniser_get_string( tokeniser, 0 ) );
719 valerie_util_strip( valerie_tokeniser_get_string( tokeniser, 1 ), '\"' );
720 strcpy( entry->full, valerie_tokeniser_get_string( tokeniser, 1 ) );
721 entry->in = atol( valerie_tokeniser_get_string( tokeniser, 2 ) );
722 entry->out = atol( valerie_tokeniser_get_string( tokeniser, 3 ) );
723 entry->max = atol( valerie_tokeniser_get_string( tokeniser, 4 ) );
724 entry->size = atol( valerie_tokeniser_get_string( tokeniser, 5 ) );
725 entry->fps = atof( valerie_tokeniser_get_string( tokeniser, 6 ) );
727 valerie_tokeniser_close( tokeniser );
732 /** Get the number of entries in the list
735 int valerie_list_count( valerie_list list )
737 if ( list != NULL && valerie_response_count( list->response ) >= 3 )
738 return valerie_response_count( list->response ) - 3;
743 /** Close the list structure.
746 void valerie_list_close( valerie_list list )
750 valerie_response_close( list->response );
755 /** List the currently connected nodes.
758 valerie_nodes valerie_nodes_init( valerie this )
760 valerie_nodes nodes = malloc( sizeof( valerie_nodes_t ) );
763 memset( nodes, 0, sizeof( valerie_nodes_t ) );
764 nodes->response = valerie_parser_executef( this->parser, "NLS" );
769 /** Return the error code associated to the nodes list.
772 valerie_error_code valerie_nodes_get_error_code( valerie_nodes nodes )
775 return valerie_get_error_code( NULL, nodes->response );
777 return valerie_malloc_failed;
780 /** Get a particular node entry.
783 valerie_error_code valerie_nodes_get( valerie_nodes nodes, int index, valerie_node_entry entry )
785 valerie_error_code error = valerie_ok;
786 memset( entry, 0, sizeof( valerie_node_entry_t ) );
787 if ( index < valerie_nodes_count( nodes ) )
789 char *line = valerie_response_get_line( nodes->response, index + 1 );
790 valerie_tokeniser tokeniser = valerie_tokeniser_init( );
791 valerie_tokeniser_parse_new( tokeniser, line, " " );
793 if ( valerie_tokeniser_count( tokeniser ) == 3 )
795 entry->node = atoi( valerie_tokeniser_get_string( tokeniser, 0 ) );
796 strncpy( entry->guid, valerie_tokeniser_get_string( tokeniser, 1 ), sizeof( entry->guid ) );
797 valerie_util_strip( valerie_tokeniser_get_string( tokeniser, 2 ), '\"' );
798 strncpy( entry->name, valerie_tokeniser_get_string( tokeniser, 2 ), sizeof( entry->name ) );
801 valerie_tokeniser_close( tokeniser );
806 /** Get the number of nodes
809 int valerie_nodes_count( valerie_nodes nodes )
811 if ( nodes != NULL && valerie_response_count( nodes->response ) >= 2 )
812 return valerie_response_count( nodes->response ) - 2;
817 /** Close the nodes structure.
820 void valerie_nodes_close( valerie_nodes nodes )
824 valerie_response_close( nodes->response );
829 /** List the currently defined units.
832 valerie_units valerie_units_init( valerie this )
834 valerie_units units = malloc( sizeof( valerie_units_t ) );
837 memset( units, 0, sizeof( valerie_units_t ) );
838 units->response = valerie_parser_executef( this->parser, "ULS" );
843 /** Return the error code associated to the nodes list.
846 valerie_error_code valerie_units_get_error_code( valerie_units units )
849 return valerie_get_error_code( NULL, units->response );
851 return valerie_malloc_failed;
854 /** Get a particular unit entry.
857 valerie_error_code valerie_units_get( valerie_units units, int index, valerie_unit_entry entry )
859 valerie_error_code error = valerie_ok;
860 memset( entry, 0, sizeof( valerie_unit_entry_t ) );
861 if ( index < valerie_units_count( units ) )
863 char *line = valerie_response_get_line( units->response, index + 1 );
864 valerie_tokeniser tokeniser = valerie_tokeniser_init( );
865 valerie_tokeniser_parse_new( tokeniser, line, " " );
867 if ( valerie_tokeniser_count( tokeniser ) == 4 )
869 entry->unit = atoi( valerie_tokeniser_get_string( tokeniser, 0 ) + 1 );
870 entry->node = atoi( valerie_tokeniser_get_string( tokeniser, 1 ) );
871 strncpy( entry->guid, valerie_tokeniser_get_string( tokeniser, 2 ), sizeof( entry->guid ) );
872 entry->online = atoi( valerie_tokeniser_get_string( tokeniser, 3 ) );
875 valerie_tokeniser_close( tokeniser );
880 /** Get the number of units
883 int valerie_units_count( valerie_units units )
885 if ( units != NULL && valerie_response_count( units->response ) >= 2 )
886 return valerie_response_count( units->response ) - 2;
891 /** Close the units structure.
894 void valerie_units_close( valerie_units units )
898 valerie_response_close( units->response );
903 /** Get the response of the last command executed.
906 valerie_response valerie_get_last_response( valerie this )
908 return this->last_response;
911 /** Obtain a printable message associated to the error code provided.
914 const char *valerie_error_description( valerie_error_code error )
916 const char *msg = "Unrecognised error";
922 case valerie_malloc_failed:
923 msg = "Memory allocation error";
925 case valerie_unknown_error:
926 msg = "Unknown error";
928 case valerie_no_response:
929 msg = "No response obtained";
931 case valerie_invalid_command:
932 msg = "Invalid command";
934 case valerie_server_timeout:
935 msg = "Communications with server timed out";
937 case valerie_missing_argument:
938 msg = "Missing argument";
940 case valerie_server_unavailable:
941 msg = "Unable to communicate with server";
943 case valerie_unit_creation_failed:
944 msg = "Unit creation failed";
946 case valerie_unit_unavailable:
947 msg = "Unit unavailable";
949 case valerie_invalid_file:
950 msg = "Invalid file";
952 case valerie_invalid_position:
953 msg = "Invalid position";
959 /** Close the valerie structure.
962 void valerie_close( valerie this )
966 valerie_set_last_response( this, NULL );