1 VALERIE API Documentation
3 Copyright (C) 2003 Ushodaya Enterprised Limited
4 Author: Charles Yates <charles.yates@pandora.be>
5 Last Revision: 2004-01-11
12 0.1. Intended Audience
14 1. Definition of a Parser
15 1.1. Construction of a Local Parser
16 1.2. Construction of a Remote Parser
18 1.4. Closing the Parser
19 2. The High Level Parser Wrapper
21 2.2. valerie_error_code
22 2.3. Using the High Level Wrapper
23 2.4. Obtaining Directory Contents
24 2.5. Obtaining the Node List
25 2.6. Obtaining the Unit List
26 2.7. Unit Status Information
27 2.8. Server Side Queuing APIs
28 2.9. Accessing the Low Level Parser Directly
31 3. The Low Level Parser API
32 3.1. Executing a Command
33 3.2. Interpreting valerie_response
34 3.3. Accessing Unit Status
35 APPENDIX A - COMPILATION AND LINKING
36 APPENDIX B - COMPLETE HIGH LEVEL PARSER WRAPPER API LISTING
37 APPENDIX C - COMPLETE LOW LEVEL PARSER API LISTING
38 APPENDIX D - REFERENCES
44 This document details how applications interface to DVCP functionality.
47 0.1. Intended Audience
48 ----------------------
50 This document draws heavily upon the DVCP design (1) and assumes a basic
51 knowledge of the functionality provided by the DVCP core.
53 It is aimed at developers who wish to use or maintain the API.
59 The API is designed to allow client applications the ability to communicate
60 to a standalone miracle server or entirely embed the DVCP core in an
61 instance of a client application.
63 The distinction between the two is defined by the construction of the
66 This 'parser' can be used to issue DVCP commands and receive responses and
67 a 'high level parser wrapper' is provided to simplify the usage and
68 decouple the application from the DVCP command set.
71 1. Definition of a Parser
72 -------------------------
74 The parser provides a low level API which allows text DVCP commands to be
75 executed with responses being returned to the caller. Commands and
76 responses are ASCII formatted text.
78 Two parsers are provided - local and remote.
80 The local parser is the physical implementation which takes commands and
83 The remote parser is a network abstraction that forwards commands to a
84 miracle instance that hosts a local parser.
87 1.1. Construction of a Local Parser
88 -----------------------------------
90 To construct a local parser you must have:
92 #include <miracle/miracle_local.h>
94 and code to initialise the parser is as follows:
96 valerie_parser parser = miracle_parser_init_local( );
98 See Appendix A for compilation and linking details.
101 1.2. Construction of a Remote Parser
102 ------------------------------------
104 To construct a remote parser you must have:
106 #include <valerie/valerie_remote.h>
108 and code to initialise the parser is as follows:
110 valerie_parser parser = valerie_parser_init_remote( "server", port );
112 See Appendix A for compilation and linking details.
115 1.3. Using the Parser
116 ---------------------
118 Although the parser can be used directly to send commands and receive
119 responses, this low level usage puts the onus on the developer to parse the
120 responses in a meaningful way.
122 Although this usage is not strictly forbidden by applications, it is
123 discouraged as construction of commands and meaningful parsing of responses
124 leads to the clients being unnecessarily dependent on the servers input and
127 As a result, a higher level Parser Wrapper API is provided - this API
128 encapsulates the command construction and response parsing.
130 The following 2 sections provide details on these modes of access.
133 1.4. Closing the Parser
134 -----------------------
136 Regardless of use, it is the constructors responsibility to close the
137 parser before it goes out of scope. This is done via:
139 valerie_parser_close( parser );
142 2. The High Level Parser Wrapper
143 --------------------------------
145 The recommended way to access the parser, is via the valerie API. To use
146 this API, you must have:
148 #include <valerie/valerie.h>
150 and code to construct the wrapper is:
152 valerie dv = valerie_init( parser );
154 Note that either remote or local parsers can be used here and there is no
155 difference in usage, though some error returns will not be applicable to
158 It is recommended that applications honour and deal with the error returns
159 of both as this allows applications to interchange parsers.
161 Also note that valerie is not threadsafe, so you should not use the same
162 structure in multiple threads. The correct solution to this is to create a
163 valerie per thread - you may safely use the same parser for each thread ie:
165 /* valerie for the application */
166 valerie dv = valerie_init( parser );
167 /* valerie for the status handling thread. */
168 valerie dv_status = valerie_init( parser );
170 For the purposes of simplification, the remainder of this section assumes
171 that a remote parser is in use.
177 Once constructed, the next thing to do is 'connect':
179 valerie_error_code error = valerie_connect( dv );
181 This function call initialises the parser (ie: if it's remote, it
182 establishes a connection to the server, or if it's local, it initialises
183 the state of the units and supporting objects).
185 Note that if you have multiple valerie instances on the same parser you
186 should only connect one of the instances.
189 2.2. valerie_error_code
190 ----------------------
192 All but a couple of the functions that make up the valerie API return a
195 These are defined as follows:
198 valerie_malloc_failed,
199 valerie_unknown_error,
201 valerie_invalid_command,
202 valerie_server_timeout,
203 valerie_missing_argument,
204 valerie_server_unavailable,
205 valerie_unit_creation_failed,
206 valerie_unit_unavailable,
207 valerie_invalid_file,
208 valerie_invalid_position
210 In most cases, it is sufficient to check on a return of valerie_ok.
212 To obtain a textual description of a particular error, you can use:
214 char *valerie_error_description( valerie_error_code );
217 2.3. Using the High Level Wrapper
218 ---------------------------------
220 The following code snippet assumes that dv is an initialised and connected
223 valerie_error_code error = valerie_unit_play( dv, 0 );
224 if ( error == valerie_ok )
225 fprintf( stderr, "Unit 0 is now playing\n" );
227 fprintf( stderr, "Play on unit 0 failed: %s\n",
228 valerie_error_description( error ) );
230 The complete interface to valerie is listed in Appendix B of this document.
233 2.4. Obtaining Directory Contents
234 --------------------------------
236 To obtain a list of files and subdirectories in a given directory relative
237 to the ROOT property of the server, DVCP provides the CLS command.
239 A valid execution of CLS would be something like:
243 would provide a response formatted as follows:
247 "file0001.dv" 15552000
248 "file0002.dv" 15552000
250 with a trailing empty line.
252 The first line indicates the error value, the second line shows an example
253 of a subdirectory and the 3rd and 4th line lists two files that happen to
254 exist in the directory.
256 valerie provides a high level view on this which automatically parses the
257 response from the server correctly via the valerie_dir structures and
260 An example of use is as follows:
262 valerie_dir dir = valerie_dir_init( dv, "/Stuff" );
263 valerie_error_code error = valerie_dir_get_error_code( dir );
264 if ( error == valerie_ok )
266 if ( valerie_dir_count( dir ) > 0 )
268 valerie_dir_entry_t entry;
270 for ( index = 0; index < valerie_dir_count( dir ); index ++ )
272 valerie_dir_get( dir, index, &entry );
274 printf( "<%s>\n", entry.name );
276 printf( "%30s %8d", entry.name, entry.size );
281 fprintf( stderr, "Directory is empty\n" );
286 fprintf( stderr, "Directory listing failed: %s\n",
287 valerie_error_description( error ) );
289 valerie_dir_close( dir );
291 Note that entry.name provides the name of the file or directory without the
292 directory prefix. As a convenience, entry.full provides the prefixed name,
293 so you could subsequently use:
295 error = valerie_unit_load( dv, 0, entry.full );
297 to load unit 0 with an entry.
300 2.5. Obtaining the Node List
301 ----------------------------
303 Currently not defined by miracle.
305 2.6. Obtaining the Unit List
306 ----------------------------
308 To obtain a list of defined units, DVCP provides the ULS command.
310 A valid execution of ULS would be:
314 and would provide a response formatted as follows:
319 with a trailing empty line.
321 The fields of each record in the response dictate unit, node, mlt consumer and
322 online status respectively.
324 valerie provides a high level view on this which automatically parses the
325 response from the server correctly via the valerie_units structures and
328 An example of use is as follows:
330 valerie_units units = valerie_units_init( dv );
331 valerie_error_code error = valerie_units_get_error_code( units );
332 if ( error == valerie_ok )
334 if ( valerie_units_count( units ) > 0 )
336 valerie_unit_entry_t entry;
338 for ( index = 0; index < valerie_units_count( units ); index ++ )
340 valerie_units_get( units, index, &entry );
341 printf( "U%d %02d %s %s\n",
345 entry.online ? "online" : "offline" );
350 fprintf( stderr, "Unit list is empty\n" );
355 fprintf( stderr, "Unit listing failed: %s\n",
356 valerie_error_description( error ) );
358 valerie_units_close( units );
361 2.7. Unit Status Information
362 ----------------------------
364 There are two methods for a client to obtain unit status information.
366 The first is via the DVCP USTA command, which would normally be accessed
371 and would provide a response formated as follows:
374 0 playing "a.dv" 58 1000 25.00 0 6999 7000 "a.dv" 157 0 6999 7000 1 4 0
376 with no trailing empty line.
378 The entries in the record are:
381 * State (undefined, offline, not_loaded, stopped, playing,
382 paused, disconnected [when server dies])
387 * Start of clip (in point)
388 * End of clip (out point)
391 * Read ahead position
393 * Read ahead clip out
394 * Read ahead clip length
396 * Playlist generation
399 Again, valerie provides a high level means for obtaining this via the
400 valerie_unit_status function and valerie_status structures:
402 valerie_status_t status;
403 valerie_error_code error = valerie_unit_status( dv, 0, &status );
404 if ( error == valerie_ok )
406 switch( status.status )
409 printf( "offline " );
412 printf( "undefined " );
414 case unit_not_loaded:
415 printf( "unloaded " );
418 printf( "stopped " );
421 printf( "playing " );
424 printf( "unknown " );
428 printf( "%06lld %06lld %06lld %s\n", status.in,
435 fprintf( stderr, "Unit status failed: %s\n",
436 valerie_error_description( error ) );
439 The second approach for obtaining a units status is via automatic
442 This is done via the valerie_notifier API. To obtain the notifier from the
443 high level API, you can use:
445 valerie_notifier notifier = valerie_get_notifier( dv );
447 To obtain the last status associated to a unit, you can use:
450 valerie_status_t status;
451 valerie_notifier_get( notifier, &status, unit );
453 To wait for the next status from any unit, you can use:
455 valerie_notifier_wait( notifier, &status );
457 If you wish to trigger the action associated to your applications wait
458 handling of a particular unit, you can use:
460 valerie_notifier_get( notifier, &status, unit );
461 valerie_notifier_put( notifier, &status );
463 See Examples below for details on this.
465 The complete list of fields in the status structure are:
476 char tail_clip[ 2048 ];
477 int64_t tail_position;
485 You will always receive a status record for every frame output.
487 The read ahead information is provided for client side queuing. Client side
488 queuing assumes that uset eof=pause is applied to the unit. A client can
489 detect when the previously scheduled clip is played out by using the read
490 ahead information and schedule the next clip. While this mode of operation
491 is still supported, it is recommended that new clients use the server side
492 queuing mechanism which is described in the following section.
495 2.8. Server Side Queueing APIs
496 ------------------------------
498 This section describes the APIs available to provide server side queueing.
500 The concept is that each unit maintains its own playlist, containing multiple
501 clips. Associated to the playlist is a generation number which is incremented
502 on each modification to the playlist. The current playlist generation is
503 provided in the status record in order for a client to know when to refresh
504 its presentation of the list. The status record also indicates which clip is
507 Actions that can be carried out on the playlist are summarised as:
509 * list - list all the clips and associated in/out points and size
510 * loading a clip - a load will wipe the current list and replace it with the
512 * appending a clip - append will always place the specified clip at the end
514 * inserting a clip - insert will place a new clip at the specified position
516 * moving a clip - move will allow clips can be moved in the playlist
517 * removing a clip - remove will remove the specified clip from the playlist
518 * clean - clean will remove all but the playing clip from the playlist
520 Additionally, the following existing actions are clip aware:
522 * goto allows you to move the current play position to a specific clip position
523 * set in/out points allows you to modify clip in and out points
525 Backward compatability has been maintained by the addition of a clip-aware
526 family of APIs which have the naming convention of valerie_unit_clip_*.
528 These are listed in Appendix B.
530 The following shows an example of obtaining the clips queued on unit 0:
532 valerie_list list = valerie_list_init( dv, 0 );
533 valerie_list_entry_t entry;
536 printf( "Generation = %d\n", list->generation );
537 for ( index = 0; index < valerie_list_count( list ); index ++ )
539 valerie_list_get( list, index, &entry );
540 printf( "%d %s %d %d %d %d\n",
548 valerie_list_close( list );
550 To load a clip on unit 0:
552 valerie_unit_load( dv, 0, "/path/clip.dv" );
554 To append a clip on unit 0:
556 valerie_unit_append( dv, 0, "/path/clip.dv", -1, -1 );
558 Note that the last two arguments specify the in and out points of the clip
559 with -1 denoting dfaults of the entirety of the file.
561 To insert a clip at position 0 on unit 0, we can use the following:
563 valerie_unit_clip_insert( dv, 0, clip_absolute, 0, "/path/clip.dv", -1, -1 );
565 The 3rd and 4th arguments here are common to all the valerie_unit_clip functions.
566 They take the form of either [clip_absolute, n] to indicate an absolute clip
567 index, or [clip_relative, n] to indicate a clip index relative to the
568 currently playing clip.
570 So, to insert a clip immediately before the currently playing clip, we can
573 valerie_unit_clip_insert( dv, 0, clip_relative, -1, "/path/clip.dv", -1, -1 );
575 To move the current clip to the next position in the list:
577 valerie_unit_clip_move( dv, 0, clip_relative, 0, clip_relative, 1 );
579 To remove a specific clip:
581 valerie_unit_clip_remove( dv, 0, clip_absolute, index );
583 To remove all but the currently playing clip:
585 valerie_unit_clean( dv, 0 );
587 To goto the first frame in the first clip, you can use:
589 valerie_unit_clip_goto( dv, 0, clip_absolute, 0, 0 );
591 To set the in and out points on the current clip:
593 valerie_unit_clip_set_in( dv, 0, clip_relative, 0, 0 );
594 valerie_unit_clip_set_out( dv, 0, clip_relative, 0, 1000 );
596 A more complete example of use of the server side can queuing can be found
599 http://users.pandora.be/acp/gdv1394
601 The demo client provided with valerie is used for retaining backward
602 compatability with the client side queuing API.
605 2.9. Accessing the Low Level Parser Directly
606 --------------------------------------------
608 The low level parser and its associated structures can be accessed directly
609 from the high level API, but is very occasionally actually needed.
611 The methods are provided via a pair of high level methods:
613 valerie_error_code error = valerie_execute( dv, 1024, "USTA U%d", unit );
614 valerie_response response = valerie_get_last_response( dv );
616 for ( index = 0; index < valerie_response_count( response ); index ++ )
617 printf( "%d: %s\n", index, valerie_response_get_line( response,index ) );
619 More details on the valerie_response structure can be found in section 3 of this
626 Before the valerie and parser go out of scope, you need to run:
629 valerie_parser_close( parser );
631 Note that you should close all valerie instances before closing the parser.
637 Please refer to albino and humperdink source for examples provided with
638 the project. Additional examples can be found via google with gdv1394 and
642 3. The Low Level Parser API
643 ---------------------------
645 The low level parser API provides a very simple mechanism for constructing
646 commands and receiving responses.
648 As described in section 2, a parser is constructed as local or remote and
649 this is sufficient for constructing the low level parser.
652 3.1. Executing a Command
653 ------------------------
655 All commands can be executed via the single variable argument function
656 valerie_parser_executef and this function returns a valerie_response, ie:
658 valerie_response response = valerie_parser_executef( parser, "CLS \"%s\"", dir );
660 Note that no carriage return/line feed is required (adding this is
663 It is the receiver of the response who is responsible for closing it.
665 valerie_response_close( response );
668 3.2. Interpreting valerie_response
669 -----------------------------
671 The response received can be NULL, but it is safe to call:
673 int error = valerie_response_get_error_code( response );
677 * -1 if response is NULL,
678 * -2 if there is no content to the response,
679 * 0 if the responses first line does not correspond to a valid DVCP response
680 * or the DVCP protocol error code returned on the first line of the response
682 A simple use of a valerie_response structure is as follows:
684 valerie_response response = valerie_parser_executef( parser, "CLS \"%s\"", dir );
685 int error = valerie_response_get_error_code( response );
689 for ( index = 0; index < valerie_response_count( response ); index ++ )
690 printf( "%3d: %s\n", index, valerie_response_get_line( response, index ) );
694 /* interpret error */
696 valerie_response_close( response );
698 Note that it is safe to call valerie_response_close regardless of the error
702 3.3. Accessing Unit Status
703 --------------------------
705 As with the high level parser, there are two alternatives to obtain unit
706 status information - either via the USTA DVCP command or via the
707 valerie1394_notifier.
709 The latter is the recommended way for any applications which wish to extract
710 meaningful information from the status while avoiding the requirement to
711 duplicate the parsing process in a specific client.
713 The notifier can be obtained by:
715 valerie_notifier notifier = valerie_parser_get_notifier( parser );
717 The use of the notifier with the low level parser is identical to that
718 dictated in Section 2 - to obtain the last status associated to a unit,
722 valerie_status_t status;
723 valerie_notifier_get( notifier, &status, unit );
725 To wait for the next status from any unit, you can use:
727 valerie_notifier_wait( notifier, &status );
730 APPENDIX A - COMPILATION AND LINKING
731 ------------------------------------
733 Compilation flags are:
737 where prefix defaults to /usr/local.
739 Linking flags for a client are:
741 -L <prefix>/lib/ -lvalerie
743 Or for a local parser:
745 -L <prefix>/lib/ -lmiracle
747 Note that you never need both libs.
750 APPENDIX B - COMPLETE HIGH LEVEL PARSER WRAPPER API LISTING
751 -----------------------------------------------------------
753 valerie valerie_init( valerie_parser );
755 valerie_error_code valerie_connect( valerie );
757 valerie_error_code valerie_set( valerie, char *, char * );
758 valerie_error_code valerie_get( valerie, char *, char *, int );
760 valerie_error_code valerie_unit_add( valerie, char * );
761 valerie_error_code valerie_unit_load( valerie, int, char * );
762 valerie_error_code valerie_unit_load_clipped( valerie,int,char *,long,long );
763 valerie_error_code valerie_unit_load_back( valerie, int, char * );
764 valerie_error_code valerie_unit_load_back_clipped(valerie,int,char *,long,long)
765 valerie_error_code valerie_unit_play( valerie, int );
766 valerie_error_code valerie_unit_play_at_speed( valerie, int, int );
767 valerie_error_code valerie_unit_stop( valerie, int );
768 valerie_error_code valerie_unit_pause( valerie, int );
769 valerie_error_code valerie_unit_rewind( valerie, int );
770 valerie_error_code valerie_unit_fast_forward( valerie, int );
771 valerie_error_code valerie_unit_step( valerie, int, int );
772 valerie_error_code valerie_unit_goto( valerie, int, int );
773 valerie_error_code valerie_unit_set_in( valerie, int, int );
774 valerie_error_code valerie_unit_set_out( valerie, int, int );
775 valerie_error_code valerie_unit_clear_in( valerie, int );
776 valerie_error_code valerie_unit_clear_out( valerie, int );
777 valerie_error_code valerie_unit_clear_in_out( valerie, int );
778 valerie_error_code valerie_unit_set( valerie, int, char *, char * );
779 valerie_error_code valerie_unit_get( valerie, int, char * );
781 valerie_error_code valerie_unit_status( valerie, int, valerie_status );
782 valerie_notifier valerie_get_notifier( valerie );
784 valerie_dir valerie_dir_init( valerie, char * );
785 valerie_error_code valerie_dir_get( valerie_dir, int, valerie_dir_entry );
786 int valerie_dir_count( valerie_dir );
787 void valerie_dir_close( valerie_dir );
789 valerie_nodes valerie_nodes_init( valerie );
790 valerie_error_code valerie_nodes_get(valerie_nodes,int,valerie_node_entry);
791 int valerie_nodes_count( valerie_nodes );
792 void valerie_nodes_close( valerie_nodes );
794 valerie_units valerie_units_init( valerie );
795 valerie_error_code valerie_units_get(valerie_units,int,valerie_unit_entry);
796 int valerie_units_count( valerie_units );
797 void valerie_units_close( valerie_units );
799 valerie_response valerie_get_last_response( valerie );
801 valerie_error_code valerie_execute( valerie, size_t, char *, ... );
803 void valerie_close( valerie );
808 void valerie_notifier_get( valerie_notifier, valerie_status, int );
809 void valerie_notifier_put( valerie_notifier, valerie_status );
810 int valerie_notifier_wait( valerie_notifier, valerie_status );
811 void valerie_notifier_close( valerie_notifier );
816 valerie_list valerie_list_init( valerie, int )
817 valerie_error_code valerie_list_get_error_code( valerie_list )
818 valerie_error_code valerie_list_get( valerie_list, int, valerie_list_entry )
819 int valerie_list_count( valerie_list )
820 void valerie_list_close( valerie_list )
822 valerie_error_code valerie_unit_clean( valerie dv, int unit )
823 valerie_error_code valerie_unit_append( valerie dv, int unit, char *file, int in, int out )
824 valerie_error_code valerie_unit_remove_current_clip( valerie dv, int unit )
826 valerie_error_code valerie_unit_clip_goto( valerie dv, int unit, valerie_clip_offset offset, int clip, int position )
827 valerie_error_code valerie_unit_clip_set_in( valerie dv, int unit, valerie_clip_offset offset, int clip, int in )
828 valerie_error_code valerie_unit_clip_set_out( valerie dv, int unit, valerie_clip_offset offset, int clip, int in )
829 valerie_error_code valerie_unit_clip_move( valerie dv, int unit, valerie_clip_offset offset, int src, valerie_clip_offset offset, int dest )
830 valerie_error_code valerie_unit_clip_remove( valerie dv, int unit, valerie_clip_offset offset, int clip )
831 valerie_error_code valerie_unit_clip_insert( valerie dv, int unit, valerie_clip_offset offset, int clip, char *file, int in, int out )
835 APPENDIX C - COMPLETE LOW LEVEL PARSER API LISTING
836 --------------------------------------------------
838 valerie_response valerie_parser_connect( valerie_parser );
839 valerie_response valerie_parser_execute( valerie_parser, char * );
840 valerie_response valerie_parser_executef( valerie_parser, char *, ... );
841 valerie_response valerie_parser_run( valerie_parser, char * );
842 valerie_notifier valerie_parser_get_notifier( valerie_parser );
843 void valerie_parser_close( valerie_parser );
845 valerie_response valerie_response_init( );
846 valerie_response valerie_response_clone( valerie_response );
847 int valerie_response_get_error_code( valerie_response );
848 char *valerie_response_get_error_string( valerie_response );
849 char *valerie_response_get_line( valerie_response, int );
850 int valerie_response_count( valerie_response );
851 void valerie_response_set_error( valerie_response, int, char * );
852 int valerie_response_printf( valerie_response, size_t, char *, ... );
853 int valerie_response_write( valerie_response, char *, int );
854 void valerie_response_close( valerie_response );
857 APPENDIX D - REFERENCES
858 -----------------------
860 (1) doc/dvcp.txt - DVCP protocol
861 (2) doc/testing.txt - Test procedures