]> git.sesse.net Git - mlt/commitdiff
uset and doco
authorlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Sun, 11 Jan 2004 13:06:31 +0000 (13:06 +0000)
committerlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Sun, 11 Jan 2004 13:06:31 +0000 (13:06 +0000)
git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@55 d19143bc-622f-0410-bfdd-b5b2a6649095

12 files changed:
docs/dvcp.txt [new file with mode: 0644]
docs/valerie.txt [new file with mode: 0644]
mlt/docs/dvcp.txt [new file with mode: 0644]
mlt/docs/valerie.txt [new file with mode: 0644]
mlt/src/framework/mlt_playlist.c
mlt/src/miracle/miracle_unit.c
mlt/src/miracle/miracle_unit.h
mlt/src/miracle/miracle_unit_commands.c
src/framework/mlt_playlist.c
src/miracle/miracle_unit.c
src/miracle/miracle_unit.h
src/miracle/miracle_unit_commands.c

diff --git a/docs/dvcp.txt b/docs/dvcp.txt
new file mode 100644 (file)
index 0000000..6da16db
--- /dev/null
@@ -0,0 +1,336 @@
+
+dv1394d Control Protocol (DVCP) Reference Documentation
+
+Copyright (C) 2003 Ushodaya Enterprised Limited
+Author: Dan Dennedy <dan@dennedy.org>
+Last Revision: 2003-01-13
+
+General Format
+--------------
+       DVCP is an ASCII-based request/response TCP protocol much like FTP and
+       inspired by the SGI MVCP (Multiport Video Computer Protocol). Each
+       command is three to eight characters long followed by zero or more
+       arguments. Every item (command or argument) in the request is delimited
+       by a space and terminated with a new line. Arguments that contain spaces
+       must be surrounded by double quotation marks. The new line must contain
+       a line feed optionally preceeded by a carriage return. There are no
+       request header lines or body.
+
+
+Response Codes
+--------------
+       Responses consist of a numeric result code followed by a space folowed
+       by a brief textual description of the result. No quoting is applied to
+       descriptions regardless if it contains spaces. The result codes are
+       grouped by the hundreds into general categories of responses. Anything
+       in the 200-299 range is considered a success and anything 300 and above
+       is an error or exception. Most responses do not contain a body except
+       some of the success results that report information and sometimes the
+       500 Server Error returns specific information. 
+               A 200 result code contains no body.
+               A 201 result code contains one or more lines in the body, and a empty
+                       line terminates the response.
+               A 202 result code contains only a single response line in the body.
+
+       Errors in the 400 range indicate a normally handled error where the
+       command could not perform its action due to protocol syntax errors or
+       problems with validation of one or more of the arguments. This usually
+       indicates that the client is responsible for performing an illegal
+       request.
+       
+       Errors in the 500 range indicate a server error or exception.
+       
+       The following is a list of response codes and their descriptions:
+       200 OK
+       201 OK
+       202 OK
+       400 Unknown command
+       401 Operation timed out
+       402 Argument missing
+       403 Unit not found
+       404 Failed to locate or open clip
+       405 Argument value out of range
+       500 Server Error
+
+
+Establishing a Connection
+-------------------------
+       One can connect to the miracle server using telnet or a custom client,
+       preferrably one developed using the valerie client API. The default port
+       is 5250. Connections can be broken at will or use the BYE command to
+       request the server to terminate the connection.
+
+
+General Command Information
+---------------------------
+
+       All commands are case insensitive. Arguments may or may not be case
+       sensitive. There are two categories of commands: global and unit. Global
+       commands operate at the server level. Unit commands address a specific
+       unit. miracle is a multi-unit system. Units are named as U? where ?
+       is the unit number, for example, U0. As units are added to the server,
+       the unit number increases; the first unit is U0.
+       
+       The command HELP lists all commands known to the server with a brief
+       description of their purpose and arguments. Most commands take zero or
+       one argument outside of the unit name. Sometimes an argument is
+       optional, and an optional argument always follows required arguments.
+       All units command required a unit name argument.
+       
+       {} = required argument
+       [] = optional argument
+       () = one of a set of pre-defined values
+       
+
+Global Commands
+---------------
+
+HELP
+       List the commands and their brief description.
+
+BYE
+       Close the connection.
+       
+SHUTDOWN
+       Shutdown the server and all client connections.
+
+SET {key=value}
+       Set a global server configuration property.
+       Currently, the only planned key is "root" to set the base directory
+       path for the CLS and LOAD commands. The default root value is /.
+
+GET {key}
+       Get the current value of a configuration property.
+       The value is returned by itself in the body of the response.
+
+CLS {path}
+       List the clips and subdirectories at {path} on the server.
+       Only subdirectories, non-hidden regular files, symbolic links, and NFS
+       shares are supported.
+       The response body contains one line per item.
+       The name of the subdirectory/file is always surrounded by double
+       quotation marks in case it contains spaces.
+       Subdirectories are listed before files and have a trailing / in their
+       name.
+       File entries have a size value in bytes in the second column position.
+
+RUN {file}
+       Process the commands in a file located on the server.
+       Commands are executed one after the other with no delay until the end
+       of file is reached or a command returns a response code not in the 200
+       range.
+       The response body contains each command sent along with its arguments,
+       followed by each command's response status code and response body.
+
+
+STATUS
+       Responds with the output of USTA for each unit and accepts no further
+       input. Each time the state of the unit changes, a new row is returned by
+       the server containing the state of the unit. 
+
+Unit Management
+
+       The following global commands manage the DV units within the server.
+       Currently there is a maximum of four units, and units can not be
+       removed. Each unit may be in an online or offline state. Offline units
+       can not be used, and any unit commands issued against an offline unit
+       results in a 403 response. 
+       
+NLS
+       * NOT IMPLEMENTED IN MIRACLE YET *
+
+
+UADD mlt-consumer[:argument]
+       Add a unit based upon the mlt-consumer id and optional constructor
+       argument.
+       If the consumer is not found, then it still added but in an
+       offline manner. Later, by adding the device to the bus, the unit will
+       automatically become online.
+       The response body contains the name of the new unit: U0, U1, U2, or U3.
+       Channel is an optional setting. 
+
+ULS
+       List the units.
+       The response body contains a space-delimited row for each unit in the
+       server containing the following columns:
+       - unit name (one of U0, U1, U2, or U3)
+       - mlt-consumer[:argument] from uadd
+       - 1394 node GUID (defunt - always 0 with miracle for now)
+       - online flag (1 = online, 0 = offline)
+
+SHUTDOWN
+       Shutdown the server.
+
+
+Unit Commands
+-------------
+
+       The first argument of any unit command is the unit name (U0 - U3). A
+       unit must be loaded with a file before it can play anything. A "clip"
+       refers to the presence of a file loaded into the unit. A clip can
+       contain an in and out point to set the playback region. The default in
+       point is 0, and the default out point is the number of frames in the
+       file minus one. Therefore, all frame positions are zero-based.
+
+USET {unit} {key=value}
+       Set a unit's configuration property.
+       Key is one of the following: eof, points.
+       
+       Property "eof" determines what the playback engine does when it reaches
+       the end of a clip. The eof property takes one of the following values:
+       stop, loop, continue or pause. The default is pause.
+       
+       Property "points" determines whether the playback engine restricts the
+       playback region to the in and out points. It takes one of the following
+       values: use, ignore.
+       
+UGET {unit} {key}
+       Get a unit's configuration property.
+       Key is one of the following: eof, points.
+       The response body contains only the key's value. See USET for information 
+       about each property.
+
+LIST {unit}
+       List the clips associated to the unit.
+       The response body consists of two sections - the first section is a single row
+       containing the generation number of the playlist associated to the unit (an
+       integer starting from 0 which is incremented on each action which changes the
+       playlist). The second sections contais a space-delimited row for each clip in the
+       units playlistcontaining the following columns:
+       - clip index (starts from 0)
+       - file name
+       - in point
+       - out point
+       - real length of the files
+       - calculated length of file
+       When USET points=use is specified (default), the calculated size is (out-in)+1. 
+       When points are ignored, the real length of the file is returned.
+
+LOAD {unit} {filename} [in out]
+       Load a clip into the unit.
+       Optionally set the in and out points to the specified absolute frame numbers.
+       Sets the current position to the first frame in the clip.
+       Preface the filename with '!' to tell the disk reader thread to remove only
+       duplicate frames from the tail of its buffer queue (from a previously loaded
+       and playing clip). Otherwise, miracle flushes all of its buffers upon LOAD
+       to make the effect of LOAD instantaneous. The LOAD !, USET eof=pause, and
+       extended USTA information can be used for client-side playlists (see the 
+       demo programs).
+
+APND {unit} {filename} [in out]
+       Append a clip onto the unit's playlist.
+       Optionally set the in and out points to the specified absolute frame numbers.
+       
+INSERT {unit} {filename} [ [+|-]clip [ in out ] ]
+       Insert a clip into the units playlist at the specified clip index or relative
+       to the currently playing clip index.
+
+REMOVE {unit} [ [+|-]clip ]
+       Removes a clip from the specified clip index or position relative to the 
+       currently playing clip index.
+       
+CLEAN {unit}
+       Removes all by the playing clip.
+       
+MOVE {unit} [+|-]clip [ [+|-]clip ]
+       Move a clip in the playlist to position specified or position relative to the
+       currently playing clip.
+
+PLAY {unit} [speed]
+       Commence unit playback from the current position.
+       The default speed is 100% if not specified.
+       Speed is represented as a percentage value multiplied by 10. Therefore
+       the default playback speed is 1000 (1X or 100%), 2X is 2000.
+       Negative speed values play in reverse.
+
+STOP {unit}
+       Terminate the unit playback resulting in no video being sent.
+
+PAUSE {unit}
+       Pause the unit playback causing the current frame position to he held
+       indefinitely.
+
+REW {unit}
+       Rewind the unit.
+       If the unit it playing, then REW sets the playback speed to 2000
+       (200%).
+       If the unit is stopped, then the frame position is reset to the first
+       frame. First frame depends upon the "points" unit configuration property
+       and whether an in point has been established for the clip using the SIN
+       command.
+       Set the currently loaded clip's in point.
+       Frame is zero-based and absolute. It is not dependent upon the clip's
+       current in point.
+       A frame-number of -1, resets the in point to 0.
+
+FF {unit}
+       Fast forward the unit.
+       If the unit it playing, then FF sets the playback speed to -2000 (200%
+       in reverse).
+       If the unit is stopped, then the frame position is reset to the first
+       frame. First frame depends upon the "points" unit configuration property
+       and whether an in point has been established for the clip using the SIN
+       command.
+
+STEP {unit} {number-of-frames}
+       Adjust the current frame position by the number of frames specified.
+       Number-of-frames can accept positive or negative values.
+
+GOTO {unit} {frame-number} [ [+|-]clip ]
+       Set the current frame position to frame-number.
+       Frame-number is zero-based and absolute within the clip, which means it is 
+       relative to the file beginning and not the clip in point.
+       It does not alter the playback status of the unit. 
+
+SIN {unit} {frame-number} [ [+|-]clip ]
+       Set the currently loaded clip's in point.
+       The in point is the logical starting frame of the clip.
+       Frame is zero-based and absolute. It is not dependent upon the clip's
+       current in point.
+       A frame-number of -1, resets the in point to 0.
+
+SOUT {unit} {frame-number} [ [+|-]clip ]
+       Set the currently loaded clip's out point.
+       The out point is the logical last frame of the clip.
+       Frame is zero-based and absolute. It is not dependent upon the clip's
+       current out point.
+       A frame-number of -1, resets the out point to the number of frames in
+       the file minus 1.
+
+USTA {unit}
+       Get the unit status report.
+       The response body contains the following fields delimited by spaces:
+       - unit number: U0, U1, U2, or U3 without the "U" prefix
+       - mode: (offline|not_loaded|playing|stopped|paused|disconnected|unknown)
+         "unknown" means the unit has not been added
+         "disconnected" means the server has closed a connection to a client running
+               STATUS.
+       - current clip name: filename
+       - current position: in absolute frame number units
+       - speed: playback rate in (percent * 10)
+       - fps: frames-per-second of loaded clip
+       - current in-point: starting frame number
+       - current out-point: ending frame number
+       - length of the clip
+       - buffer tail clip name: filename
+       - buffer tail position: in absolute frame number units
+       - buffer tail in-point: starting frame number
+       - buffer tail out-point: ending frame number
+       - buffer tail length: length of clip in buffer tail
+       - seekable flag: indicates if the current clip is seekable (relates to head)
+       - playlist generation number
+       - current clip index (relates to head)
+        
+       The status contains information based not only on the current frame being
+       output (current above) but also based upon the most recent frame read by
+       the disk reader thread and added to the tail of the input buffer queue
+       (buffer tail above).
+
+XFER {unit} {target-unit}
+       Transfer the unit's clip to the target unit.
+       The clip inherently includes the in- and out-point information.
+       The target unit's "points" configuration property is set to "use."
+
+
+
+
diff --git a/docs/valerie.txt b/docs/valerie.txt
new file mode 100644 (file)
index 0000000..a5abcce
--- /dev/null
@@ -0,0 +1,861 @@
+VALERIE API Documentation 
+
+Copyright (C) 2003 Ushodaya Enterprised Limited 
+Author: Charles Yates <charles.yates@pandora.be> 
+Last Revision: 2004-01-11
+
+
+TABLE OF CONTENTS
+-----------------
+
+       0. Overview 
+       0.1. Intended Audience
+       0.2. Terminology
+       1. Definition of a Parser 
+       1.1. Construction of a Local Parser 
+       1.2. Construction of a Remote Parser
+       1.3. Using the Parser
+       1.4. Closing the Parser
+       2. The High Level Parser Wrapper
+       2.1. Connecting
+       2.2. valerie_error_code
+       2.3. Using the High Level Wrapper
+       2.4. Obtaining Directory Contents
+       2.5. Obtaining the Node List
+       2.6. Obtaining the Unit List
+       2.7. Unit Status Information
+       2.8. Server Side Queuing APIs
+       2.9. Accessing the Low Level Parser Directly
+       2.10. Cleaning up
+       2.11. Examples
+       3. The Low Level Parser API
+       3.1. Executing a Command
+       3.2. Interpreting valerie_response
+       3.3. Accessing Unit Status
+       APPENDIX A - COMPILATION AND LINKING
+       APPENDIX B - COMPLETE HIGH LEVEL PARSER WRAPPER API LISTING
+       APPENDIX C - COMPLETE LOW LEVEL PARSER API LISTING
+       APPENDIX D - REFERENCES
+       
+
+0. Overview 
+-----------
+
+       This document details how applications interface to DVCP functionality. 
+
+
+0.1. Intended Audience
+----------------------
+
+       This document draws heavily upon the DVCP design (1) and assumes a basic 
+       knowledge of the functionality provided by the DVCP core. 
+
+       It is aimed at developers who wish to use or maintain the API.
+
+
+0.2. Terminology
+----------------
+
+       The API is designed to allow client applications the ability to communicate
+       to a standalone miracle server or entirely embed the DVCP core in an 
+       instance of a client application. 
+
+       The distinction between the two is defined by the construction of the 
+       'parser'. 
+
+       This 'parser' can be used to issue DVCP commands and receive responses and 
+       a 'high level parser wrapper' is provided to simplify the usage and 
+       decouple the application from the DVCP command set.
+
+
+1. Definition of a Parser 
+------------------------- 
+
+       The parser provides a low level API which allows text DVCP commands to be 
+       executed with responses being returned to the caller. Commands and 
+       responses are ASCII formatted text. 
+
+       Two parsers are provided - local and remote. 
+
+       The local parser is the physical implementation which takes commands and 
+       executes them. 
+
+       The remote parser is a network abstraction that forwards commands to a 
+       miracle instance that hosts a local parser. 
+
+
+1.1. Construction of a Local Parser 
+----------------------------------- 
+
+       To construct a local parser you must have:
+
+           #include <miracle/miracle_local.h>
+
+       and code to initialise the parser is as follows:
+
+           valerie_parser parser = miracle_parser_init_local( );
+
+       See Appendix A for compilation and linking details.
+
+
+1.2. Construction of a Remote Parser
+------------------------------------
+
+       To construct a remote parser you must have:
+
+           #include <valerie/valerie_remote.h>
+
+       and code to initialise the parser is as follows:
+
+           valerie_parser parser = valerie_parser_init_remote( "server", port );
+
+       See Appendix A for compilation and linking details.
+
+
+1.3. Using the Parser
+---------------------
+
+       Although the parser can be used directly to send commands and receive 
+       responses, this low level usage puts the onus on the developer to parse the 
+       responses in a meaningful way. 
+
+       Although this usage is not strictly forbidden by applications, it is 
+       discouraged as construction of commands and meaningful parsing of responses 
+       leads to the clients being unnecessarily dependent on the servers input and 
+       output. 
+
+       As a result, a higher level Parser Wrapper API is provided - this API 
+       encapsulates the command construction and response parsing.
+
+       The following 2 sections provide details on these modes of access.
+
+
+1.4. Closing the Parser
+-----------------------
+
+       Regardless of use, it is the constructors responsibility to close the 
+       parser before it goes out of scope. This is done via:
+
+           valerie_parser_close( parser );
+
+
+2. The High Level Parser Wrapper
+--------------------------------
+
+       The recommended way to access the parser, is via the valerie API. To use 
+       this API, you must have:
+
+           #include <valerie/valerie.h>
+
+       and code to construct the wrapper is:
+
+           valerie dv = valerie_init( parser );
+
+       Note that either remote or local parsers can be used here and there is no 
+       difference in usage, though some error returns will not be applicable to 
+       both. 
+
+       It is recommended that applications honour and deal with the error returns 
+       of both as this allows applications to interchange parsers.
+
+       Also note that valerie is not threadsafe, so you should not use the same 
+       structure in multiple threads. The correct solution to this is to create a
+       valerie per thread - you may safely use the same parser for each thread ie:
+
+           /* valerie for the application */
+           valerie dv = valerie_init( parser );
+           /* valerie for the status handling thread. */
+           valerie dv_status = valerie_init( parser );
+
+       For the purposes of simplification, the remainder of this section assumes 
+       that a remote parser is in use. 
+
+
+2.1. Connecting
+---------------
+
+       Once constructed, the next thing to do is 'connect':
+
+           valerie_error_code error = valerie_connect( dv );
+
+       This function call initialises the parser (ie: if it's remote, it 
+       establishes a connection to the server, or if it's local, it initialises 
+       the state of the units and supporting objects).
+
+       Note that if you have multiple valerie instances on the same parser you 
+       should only connect one of the instances.
+
+
+2.2. valerie_error_code
+----------------------
+
+       All but a couple of the functions that make up the valerie API return a 
+       valerie_error_code.
+
+       These are defined as follows:
+
+           valerie_ok = 0,
+           valerie_malloc_failed,
+           valerie_unknown_error,
+           valerie_no_response,
+           valerie_invalid_command,
+           valerie_server_timeout,
+           valerie_missing_argument,
+           valerie_server_unavailable,
+           valerie_unit_creation_failed,
+           valerie_unit_unavailable,
+           valerie_invalid_file,
+           valerie_invalid_position
+
+       In most cases, it is sufficient to check on a return of valerie_ok.
+
+       To obtain a textual description of a particular error, you can use:
+
+           char *valerie_error_description( valerie_error_code );
+
+
+2.3. Using the High Level Wrapper
+---------------------------------
+
+       The following code snippet assumes that dv is an initialised and connected 
+       valerie structure:
+
+           valerie_error_code error = valerie_unit_play( dv, 0 );
+           if ( error == valerie_ok )
+            fprintf( stderr, "Unit 0 is now playing\n" );
+           else
+            fprintf( stderr, "Play on unit 0 failed: %s\n",
+                         valerie_error_description( error ) );
+
+       The complete interface to valerie is listed in Appendix B of this document.
+
+
+2.4. Obtaining Directory Contents
+--------------------------------
+
+       To obtain a list of files and subdirectories in a given directory relative 
+       to the ROOT property of the server, DVCP provides the CLS command. 
+
+       A valid execution of CLS would be something like:
+
+           CLS "/Stuff"
+
+       would provide a response formatted as follows:
+
+           201 OK
+           "More Stuff/"
+           "file0001.dv" 15552000
+           "file0002.dv" 15552000
+
+       with a trailing empty line.
+
+       The first line indicates the error value, the second line shows an example 
+       of a subdirectory and the 3rd and 4th line lists two files that happen to 
+       exist in the directory.
+
+       valerie provides a high level view on this which automatically parses the 
+       response from the server correctly via the valerie_dir structures and 
+       related functions. 
+
+       An example of use is as follows:
+       
+           valerie_dir dir = valerie_dir_init( dv, "/Stuff" );
+           valerie_error_code error = valerie_dir_get_error_code( dir );
+           if ( error == valerie_ok )
+           {
+               if ( valerie_dir_count( dir ) > 0 )
+               {
+                   valerie_dir_entry_t entry;
+                   int index = 0;
+                   for ( index = 0; index < valerie_dir_count( dir ); index ++ )
+                   {
+                       valerie_dir_get( dir, index, &entry );
+                       if ( entry.dir )
+                           printf( "<%s>\n", entry.name );
+                       else
+                           printf( "%30s %8d", entry.name, entry.size );
+                   }
+               }
+               else
+               {
+                   fprintf( stderr, "Directory is empty\n" );
+               }
+           }
+           else
+           {
+               fprintf( stderr, "Directory listing failed: %s\n",
+                                valerie_error_description( error ) );
+           }
+           valerie_dir_close( dir );
+
+       Note that entry.name provides the name of the file or directory without the 
+       directory prefix. As a convenience, entry.full provides the prefixed name, 
+       so you could subsequently use:
+
+           error = valerie_unit_load( dv, 0, entry.full );
+
+       to load unit 0 with an entry.
+
+
+2.5. Obtaining the Node List
+----------------------------
+
+       Currently not defined by miracle.
+
+2.6. Obtaining the Unit List
+----------------------------
+
+       To obtain a list of defined units, DVCP provides the ULS command.
+       
+       A valid execution of ULS would be:
+       
+           ULS
+       
+       and would provide a response formatted as follows:
+       
+           201 OK
+               U0 00 sdl:360x288 1
+       
+       with a trailing empty line.
+       
+       The fields of each record in the response dictate unit, node, mlt consumer and 
+       online status respectively.
+       
+       valerie provides a high level view on this which automatically parses the 
+       response from the server correctly via the valerie_units structures and 
+       related functions. 
+       
+       An example of use is as follows:
+       
+           valerie_units units = valerie_units_init( dv );
+           valerie_error_code error = valerie_units_get_error_code( units );
+           if ( error == valerie_ok )
+           {
+               if ( valerie_units_count( units ) > 0 )
+               {
+                   valerie_unit_entry_t entry;
+                   int index = 0;
+                   for ( index = 0; index < valerie_units_count( units ); index ++ )
+                   {
+                       valerie_units_get( units, index, &entry );
+                       printf( "U%d %02d %s %s\n", 
+                               entry.unit,
+                               entry.node,
+                               entry.guid,
+                               entry.online ? "online" : "offline" );
+                   }
+               }
+               else
+               {
+                   fprintf( stderr, "Unit list is empty\n" );
+               }
+           }
+           else
+           {
+               fprintf( stderr, "Unit listing failed: %s\n",
+                                valerie_error_description( error ) );
+           }
+           valerie_units_close( units );
+       
+
+2.7. Unit Status Information
+----------------------------
+
+       There are two methods for a client to obtain unit status information.
+       
+       The first is via the DVCP USTA command, which would normally be accessed 
+       via: 
+
+           USTA U0
+       
+       and would provide a response formated as follows:
+       
+           202 OK
+               0 playing "a.dv" 58 1000 25.00 0 6999 7000 "a.dv" 157 0 6999 7000 1 4 0
+               
+       with no trailing empty line.
+       
+       The entries in the record are:
+       
+       * Unit
+       * State (undefined, offline, not_loaded, stopped, playing, 
+                paused, disconnected [when server dies])
+       * Name of Clip
+       * Position in clip
+       * Speed * 1000
+       * Frames per second
+       * Start of clip (in point)
+       * End of clip (out point)
+       * Length of clip
+       * Read ahead clip
+       * Read ahead position 
+       * Read ahead clip in
+       * Read ahead clip out
+       * Read ahead clip length
+       * Seekable flag
+       * Playlist generation
+       * Clip index
+       
+       Again, valerie provides a high level means for obtaining this via the 
+       valerie_unit_status function and valerie_status structures:
+       
+           valerie_status_t status;
+           valerie_error_code error = valerie_unit_status( dv, 0, &status );
+           if ( error == valerie_ok )
+           {
+               switch( status.status )
+               {
+                   case unit_offline:
+                       printf( "offline   " );
+                       break;
+                   case unit_undefined:
+                       printf( "undefined " );
+                       break;
+                   case unit_not_loaded:
+                       printf( "unloaded  " );
+                       break;
+                   case unit_stopped:
+                       printf( "stopped   " );
+                       break;
+                   case unit_playing:
+                       printf( "playing   " );
+                       break;
+                   default:
+                       printf( "unknown   " );
+                       break;
+               }
+       
+               printf( "%06lld %06lld %06lld %s\n", status.in,
+                                                    status.position,
+                                                    status.out,
+                                                    status.clip );
+           }
+           else
+           {
+               fprintf( stderr, "Unit status failed: %s\n",
+                                valerie_error_description( error ) );
+           }
+       
+       The second approach for obtaining a units status is via automatic 
+       notification.
+       
+       This is done via the valerie_notifier API. To obtain the notifier from the 
+       high level API, you can use:
+       
+           valerie_notifier notifier = valerie_get_notifier( dv );
+       
+       To obtain the last status associated to a unit, you can use:
+       
+           int unit = 1;
+           valerie_status_t status;
+           valerie_notifier_get( notifier, &status, unit );
+       
+       To wait for the next status from any unit, you can use:
+       
+           valerie_notifier_wait( notifier, &status );
+       
+       If you wish to trigger the action associated to your applications wait 
+       handling of a particular unit, you can use:
+       
+           valerie_notifier_get( notifier, &status, unit );
+           valerie_notifier_put( notifier, &status );
+       
+       See Examples below for details on this.
+
+       The complete list of fields in the status structure are:
+
+           int unit;
+           unit_status status;
+           char clip[ 2048 ];
+           int64_t position;
+           int speed;
+           double fps;
+           int64_t in;
+           int64_t out;
+               int64_t length;
+           char tail_clip[ 2048 ];
+           int64_t tail_position;
+           int64_t tail_in;
+           int64_t tail_out;
+               int64_t tail_length;
+               int seekable;
+               int generation;
+               int clip_index;
+       
+       You will always receive a status record for every frame output.
+
+       The read ahead information is provided for client side queuing. Client side
+       queuing assumes that uset eof=pause is applied to the unit. A client can 
+       detect when the previously scheduled clip is played out by using the read 
+       ahead information and schedule the next clip. While this mode of operation
+       is still supported, it is recommended that new clients use the server side
+       queuing mechanism which is described in the following section.
+       
+
+2.8. Server Side Queueing APIs
+------------------------------
+
+       This section describes the APIs available to provide server side queueing. 
+       
+       The concept is that each unit maintains its own playlist, containing multiple
+       clips. Associated to the playlist is a generation number which is incremented 
+       on each modification to the playlist. The current playlist generation is
+       provided in the status record in order for a client to know when to refresh
+       its presentation of the list. The status record also indicates which clip is 
+       currently active.
+       
+       Actions that can be carried out on the playlist are summarised as:
+       
+       * list - list all the clips and associated in/out points and size
+       * loading a clip - a load will wipe the current list and replace it with the
+         specified clip
+       * appending a clip - append will always place the specified clip at the end 
+         of the playlist
+       * inserting a clip - insert will place a new clip at the specified position 
+         in the playlist
+       * moving a clip - move will allow clips can be moved in the playlist
+       * removing a clip - remove will remove the specified clip from the playlist
+       * clean - clean will remove all but the playing clip from the playlist
+       
+       Additionally, the following existing actions are clip aware:
+       
+       * goto allows you to move the current play position to a specific clip position
+       * set in/out points allows you to modify clip in and out points
+       
+       Backward compatability has been maintained by the addition of a clip-aware 
+       family of APIs which have the naming convention of valerie_unit_clip_*.
+       
+       These are listed in Appendix B.
+       
+       The following shows an example of obtaining the clips queued on unit 0:
+       
+               valerie_list list = valerie_list_init( dv, 0 );
+               valerie_list_entry_t entry;
+               int index;
+               
+               printf( "Generation = %d\n", list->generation );
+               for ( index = 0; index < valerie_list_count( list ); index ++ )
+               {
+                       valerie_list_get( list, index, &entry );
+                       printf( "%d %s %d %d %d %d\n", 
+                                       entry.clip, 
+                                       entry.full,
+                                       entry.in,
+                                       entry.out,
+                                       entry.max,
+                                       entry.size );
+               }
+               valerie_list_close( list );
+               
+       To load a clip on unit 0:
+       
+               valerie_unit_load( dv, 0, "/path/clip.dv" );
+               
+       To append a clip on unit 0:
+       
+               valerie_unit_append( dv, 0, "/path/clip.dv", -1, -1 );
+               
+       Note that the last two arguments specify the in and out points of the clip
+       with -1 denoting dfaults of the entirety of the file.
+       
+       To insert a clip at position 0 on unit 0, we can use the following:
+       
+               valerie_unit_clip_insert( dv, 0, clip_absolute, 0, "/path/clip.dv", -1, -1 );
+               
+       The 3rd and 4th arguments here are common to all the valerie_unit_clip functions.
+       They take the form of either [clip_absolute, n] to indicate an absolute clip
+       index, or [clip_relative, n] to indicate a clip index relative to the 
+       currently playing clip.
+       
+       So, to insert a clip immediately before the currently playing clip, we can
+       use:
+       
+               valerie_unit_clip_insert( dv, 0, clip_relative, -1, "/path/clip.dv", -1, -1 );
+               
+       To move the current clip to the next position in the list:
+       
+               valerie_unit_clip_move( dv, 0, clip_relative, 0, clip_relative, 1 );
+               
+       To remove a specific clip:
+       
+               valerie_unit_clip_remove( dv, 0, clip_absolute, index );
+               
+       To remove all but the currently playing clip:
+       
+               valerie_unit_clean( dv, 0 );
+               
+       To goto the first frame in the first clip, you can use:
+       
+               valerie_unit_clip_goto( dv, 0, clip_absolute, 0, 0 );
+               
+       To set the in and out points on the current clip:
+       
+               valerie_unit_clip_set_in( dv, 0, clip_relative, 0, 0 );
+               valerie_unit_clip_set_out( dv, 0, clip_relative, 0, 1000 );
+               
+       A more complete example of use of the server side can queuing can be found
+       at:
+       
+               http://users.pandora.be/acp/gdv1394
+               
+       The demo client provided with valerie is used for retaining backward 
+       compatability with the client side queuing API.
+
+       
+2.9. Accessing the Low Level Parser Directly
+--------------------------------------------
+
+       The low level parser and its associated structures can be accessed directly 
+       from the high level API, but is very occasionally actually needed.
+       
+       The methods are provided via a pair of high level methods:
+       
+           valerie_error_code error = valerie_execute( dv, 1024, "USTA U%d", unit );
+           valerie_response response = valerie_get_last_response( dv );
+           int index = 0;
+           for ( index = 0; index < valerie_response_count( response ); index ++ )
+               printf( "%d: %s\n", index, valerie_response_get_line( response,index ) );
+       
+       More details on the valerie_response structure can be found in section 3 of this
+       document.
+       
+
+2.10. Cleaning up
+-----------------
+
+       Before the valerie and parser go out of scope, you need to run:
+       
+           valerie_close( dv );
+           valerie_parser_close( parser );
+       
+       Note that you should close all valerie instances before closing the parser.
+       
+
+2.11. Examples
+--------------
+
+       Please refer to albino and humperdink source for examples provided with
+       the project. Additional examples can be found via google with gdv1394 and
+       poldo.
+
+
+3. The Low Level Parser API
+---------------------------
+
+       The low level parser API provides a very simple mechanism for constructing 
+       commands and receiving responses.
+       
+       As described in section 2, a parser is constructed as local or remote and 
+       this is sufficient for constructing the low level parser.
+       
+
+3.1. Executing a Command
+------------------------
+
+       All commands can be executed via the single variable argument function
+       valerie_parser_executef and this function returns a valerie_response, ie:
+       
+           valerie_response response = valerie_parser_executef( parser, "CLS \"%s\"", dir );
+       
+       Note that no carriage return/line feed is required (adding this is 
+       erroneous).
+       
+       It is the receiver of the response who is responsible for closing it.
+       
+           valerie_response_close( response );
+       
+
+3.2. Interpreting valerie_response
+-----------------------------
+
+       The response received can be NULL, but it is safe to call:
+       
+           int error = valerie_response_get_error_code( response );
+       
+       which will return:
+       
+       * -1 if response is NULL, 
+       * -2 if there is no content to the response, 
+       * 0 if the responses first line does not correspond to a valid DVCP response
+       * or the DVCP protocol error code returned on the first line of the response
+       
+       A simple use of a valerie_response structure is as follows:
+       
+           valerie_response response = valerie_parser_executef( parser, "CLS \"%s\"", dir );
+           int error = valerie_response_get_error_code( response );
+           if ( error >= 0 )
+           {
+               int index = 0;
+               for ( index = 0; index < valerie_response_count( response ); index ++ )
+                   printf( "%3d: %s\n", index, valerie_response_get_line( response, index ) );
+           }
+           else
+           {
+               /* interpret error */
+           }
+           valerie_response_close( response );
+       
+       Note that it is safe to call valerie_response_close regardless of the error 
+       condition indicated.
+       
+
+3.3. Accessing Unit Status
+--------------------------
+
+       As with the high level parser, there are two alternatives to obtain unit 
+       status information - either via the USTA DVCP command or via the 
+       valerie1394_notifier.
+       
+       The latter is the recommended way for any applications which wish to extract
+       meaningful information from the status while avoiding the requirement to 
+       duplicate the parsing process in a specific client.
+       
+       The notifier can be obtained by:
+       
+       valerie_notifier notifier = valerie_parser_get_notifier( parser );
+       
+       The use of the notifier with the low level parser is identical to that 
+       dictated in Section 2 - to obtain the last status associated to a unit, 
+       you can use: 
+
+           int unit = 1;
+           valerie_status_t status;
+           valerie_notifier_get( notifier, &status, unit );
+           
+       To wait for the next status from any unit, you can use:
+       
+           valerie_notifier_wait( notifier, &status );
+       
+
+APPENDIX A - COMPILATION AND LINKING
+------------------------------------
+
+       Compilation flags are:
+
+           -I <prefix>/include
+
+       where prefix defaults to /usr/local.
+
+       Linking flags for a client are:
+
+           -L <prefix>/lib/ -lvalerie
+
+       Or for a local parser:
+
+           -L <prefix>/lib/ -lmiracle
+
+       Note that you never need both libs.
+
+
+APPENDIX B - COMPLETE HIGH LEVEL PARSER WRAPPER API LISTING
+-----------------------------------------------------------
+
+       valerie valerie_init( valerie_parser );
+       
+       valerie_error_code valerie_connect( valerie );
+       
+       valerie_error_code valerie_set( valerie, char *, char * );
+       valerie_error_code valerie_get( valerie, char *, char *, int );
+       
+       valerie_error_code valerie_unit_add( valerie, char * );
+       valerie_error_code valerie_unit_load( valerie, int, char * );
+       valerie_error_code valerie_unit_load_clipped( valerie,int,char *,long,long );
+       valerie_error_code valerie_unit_load_back( valerie, int, char * );
+       valerie_error_code valerie_unit_load_back_clipped(valerie,int,char *,long,long)
+       valerie_error_code valerie_unit_play( valerie, int );
+       valerie_error_code valerie_unit_play_at_speed( valerie, int, int );
+       valerie_error_code valerie_unit_stop( valerie, int );
+       valerie_error_code valerie_unit_pause( valerie, int );
+       valerie_error_code valerie_unit_rewind( valerie, int );
+       valerie_error_code valerie_unit_fast_forward( valerie, int );
+       valerie_error_code valerie_unit_step( valerie, int, int );
+       valerie_error_code valerie_unit_goto( valerie, int, int );
+       valerie_error_code valerie_unit_set_in( valerie, int, int );
+       valerie_error_code valerie_unit_set_out( valerie, int, int );
+       valerie_error_code valerie_unit_clear_in( valerie, int );
+       valerie_error_code valerie_unit_clear_out( valerie, int );
+       valerie_error_code valerie_unit_clear_in_out( valerie, int );
+       valerie_error_code valerie_unit_set( valerie, int, char *, char * );
+       valerie_error_code valerie_unit_get( valerie, int, char * );
+       
+       valerie_error_code valerie_unit_status( valerie, int, valerie_status );
+       valerie_notifier valerie_get_notifier( valerie );
+       
+       valerie_dir valerie_dir_init( valerie, char * );
+       valerie_error_code valerie_dir_get( valerie_dir, int, valerie_dir_entry );
+       int valerie_dir_count( valerie_dir );
+       void valerie_dir_close( valerie_dir );
+       
+       valerie_nodes valerie_nodes_init( valerie );
+       valerie_error_code valerie_nodes_get(valerie_nodes,int,valerie_node_entry);
+       int valerie_nodes_count( valerie_nodes );
+       void valerie_nodes_close( valerie_nodes );
+       
+       valerie_units valerie_units_init( valerie );
+       valerie_error_code valerie_units_get(valerie_units,int,valerie_unit_entry);
+       int valerie_units_count( valerie_units );
+       void valerie_units_close( valerie_units );
+       
+       valerie_response valerie_get_last_response( valerie );
+       
+       valerie_error_code valerie_execute( valerie, size_t, char *, ... );
+       
+       void valerie_close( valerie );
+       
+       Notifier Functions
+       ------------------
+       
+       void valerie_notifier_get( valerie_notifier, valerie_status, int );
+       void valerie_notifier_put( valerie_notifier, valerie_status );
+       int valerie_notifier_wait( valerie_notifier, valerie_status );
+       void valerie_notifier_close( valerie_notifier );
+       
+       Server Side Queuing
+       -------------------
+
+       valerie_list valerie_list_init( valerie, int )
+       valerie_error_code valerie_list_get_error_code( valerie_list )
+       valerie_error_code valerie_list_get( valerie_list, int, valerie_list_entry )
+       int valerie_list_count( valerie_list )
+       void valerie_list_close( valerie_list )
+       
+       valerie_error_code valerie_unit_clean( valerie dv, int unit )
+       valerie_error_code valerie_unit_append( valerie dv, int unit, char *file, int in, int out )
+       valerie_error_code valerie_unit_remove_current_clip( valerie dv, int unit )
+       
+       valerie_error_code valerie_unit_clip_goto( valerie dv, int unit, valerie_clip_offset offset, int clip, int position )
+       valerie_error_code valerie_unit_clip_set_in( valerie dv, int unit, valerie_clip_offset offset, int clip, int in )
+       valerie_error_code valerie_unit_clip_set_out( valerie dv, int unit, valerie_clip_offset offset, int clip, int in )
+       valerie_error_code valerie_unit_clip_move( valerie dv, int unit, valerie_clip_offset offset, int src, valerie_clip_offset offset, int dest )
+       valerie_error_code valerie_unit_clip_remove( valerie dv, int unit, valerie_clip_offset offset, int clip )
+       valerie_error_code valerie_unit_clip_insert( valerie dv, int unit, valerie_clip_offset offset, int clip, char *file, int in, int out )
+
+       
+
+APPENDIX C - COMPLETE LOW LEVEL PARSER API LISTING
+--------------------------------------------------
+
+       valerie_response valerie_parser_connect( valerie_parser );
+       valerie_response valerie_parser_execute( valerie_parser, char * );
+       valerie_response valerie_parser_executef( valerie_parser, char *, ... );
+       valerie_response valerie_parser_run( valerie_parser, char * );
+       valerie_notifier valerie_parser_get_notifier( valerie_parser );
+       void valerie_parser_close( valerie_parser );
+       
+       valerie_response valerie_response_init( );
+       valerie_response valerie_response_clone( valerie_response );
+       int valerie_response_get_error_code( valerie_response );
+       char *valerie_response_get_error_string( valerie_response );
+       char *valerie_response_get_line( valerie_response, int );
+       int valerie_response_count( valerie_response );
+       void valerie_response_set_error( valerie_response, int, char * );
+       int valerie_response_printf( valerie_response, size_t, char *, ... );
+       int valerie_response_write( valerie_response, char *, int );
+       void valerie_response_close( valerie_response );
+       
+
+APPENDIX D - REFERENCES
+-----------------------
+
+       (1) doc/dvcp.txt - DVCP protocol
+       (2) doc/testing.txt - Test procedures
diff --git a/mlt/docs/dvcp.txt b/mlt/docs/dvcp.txt
new file mode 100644 (file)
index 0000000..6da16db
--- /dev/null
@@ -0,0 +1,336 @@
+
+dv1394d Control Protocol (DVCP) Reference Documentation
+
+Copyright (C) 2003 Ushodaya Enterprised Limited
+Author: Dan Dennedy <dan@dennedy.org>
+Last Revision: 2003-01-13
+
+General Format
+--------------
+       DVCP is an ASCII-based request/response TCP protocol much like FTP and
+       inspired by the SGI MVCP (Multiport Video Computer Protocol). Each
+       command is three to eight characters long followed by zero or more
+       arguments. Every item (command or argument) in the request is delimited
+       by a space and terminated with a new line. Arguments that contain spaces
+       must be surrounded by double quotation marks. The new line must contain
+       a line feed optionally preceeded by a carriage return. There are no
+       request header lines or body.
+
+
+Response Codes
+--------------
+       Responses consist of a numeric result code followed by a space folowed
+       by a brief textual description of the result. No quoting is applied to
+       descriptions regardless if it contains spaces. The result codes are
+       grouped by the hundreds into general categories of responses. Anything
+       in the 200-299 range is considered a success and anything 300 and above
+       is an error or exception. Most responses do not contain a body except
+       some of the success results that report information and sometimes the
+       500 Server Error returns specific information. 
+               A 200 result code contains no body.
+               A 201 result code contains one or more lines in the body, and a empty
+                       line terminates the response.
+               A 202 result code contains only a single response line in the body.
+
+       Errors in the 400 range indicate a normally handled error where the
+       command could not perform its action due to protocol syntax errors or
+       problems with validation of one or more of the arguments. This usually
+       indicates that the client is responsible for performing an illegal
+       request.
+       
+       Errors in the 500 range indicate a server error or exception.
+       
+       The following is a list of response codes and their descriptions:
+       200 OK
+       201 OK
+       202 OK
+       400 Unknown command
+       401 Operation timed out
+       402 Argument missing
+       403 Unit not found
+       404 Failed to locate or open clip
+       405 Argument value out of range
+       500 Server Error
+
+
+Establishing a Connection
+-------------------------
+       One can connect to the miracle server using telnet or a custom client,
+       preferrably one developed using the valerie client API. The default port
+       is 5250. Connections can be broken at will or use the BYE command to
+       request the server to terminate the connection.
+
+
+General Command Information
+---------------------------
+
+       All commands are case insensitive. Arguments may or may not be case
+       sensitive. There are two categories of commands: global and unit. Global
+       commands operate at the server level. Unit commands address a specific
+       unit. miracle is a multi-unit system. Units are named as U? where ?
+       is the unit number, for example, U0. As units are added to the server,
+       the unit number increases; the first unit is U0.
+       
+       The command HELP lists all commands known to the server with a brief
+       description of their purpose and arguments. Most commands take zero or
+       one argument outside of the unit name. Sometimes an argument is
+       optional, and an optional argument always follows required arguments.
+       All units command required a unit name argument.
+       
+       {} = required argument
+       [] = optional argument
+       () = one of a set of pre-defined values
+       
+
+Global Commands
+---------------
+
+HELP
+       List the commands and their brief description.
+
+BYE
+       Close the connection.
+       
+SHUTDOWN
+       Shutdown the server and all client connections.
+
+SET {key=value}
+       Set a global server configuration property.
+       Currently, the only planned key is "root" to set the base directory
+       path for the CLS and LOAD commands. The default root value is /.
+
+GET {key}
+       Get the current value of a configuration property.
+       The value is returned by itself in the body of the response.
+
+CLS {path}
+       List the clips and subdirectories at {path} on the server.
+       Only subdirectories, non-hidden regular files, symbolic links, and NFS
+       shares are supported.
+       The response body contains one line per item.
+       The name of the subdirectory/file is always surrounded by double
+       quotation marks in case it contains spaces.
+       Subdirectories are listed before files and have a trailing / in their
+       name.
+       File entries have a size value in bytes in the second column position.
+
+RUN {file}
+       Process the commands in a file located on the server.
+       Commands are executed one after the other with no delay until the end
+       of file is reached or a command returns a response code not in the 200
+       range.
+       The response body contains each command sent along with its arguments,
+       followed by each command's response status code and response body.
+
+
+STATUS
+       Responds with the output of USTA for each unit and accepts no further
+       input. Each time the state of the unit changes, a new row is returned by
+       the server containing the state of the unit. 
+
+Unit Management
+
+       The following global commands manage the DV units within the server.
+       Currently there is a maximum of four units, and units can not be
+       removed. Each unit may be in an online or offline state. Offline units
+       can not be used, and any unit commands issued against an offline unit
+       results in a 403 response. 
+       
+NLS
+       * NOT IMPLEMENTED IN MIRACLE YET *
+
+
+UADD mlt-consumer[:argument]
+       Add a unit based upon the mlt-consumer id and optional constructor
+       argument.
+       If the consumer is not found, then it still added but in an
+       offline manner. Later, by adding the device to the bus, the unit will
+       automatically become online.
+       The response body contains the name of the new unit: U0, U1, U2, or U3.
+       Channel is an optional setting. 
+
+ULS
+       List the units.
+       The response body contains a space-delimited row for each unit in the
+       server containing the following columns:
+       - unit name (one of U0, U1, U2, or U3)
+       - mlt-consumer[:argument] from uadd
+       - 1394 node GUID (defunt - always 0 with miracle for now)
+       - online flag (1 = online, 0 = offline)
+
+SHUTDOWN
+       Shutdown the server.
+
+
+Unit Commands
+-------------
+
+       The first argument of any unit command is the unit name (U0 - U3). A
+       unit must be loaded with a file before it can play anything. A "clip"
+       refers to the presence of a file loaded into the unit. A clip can
+       contain an in and out point to set the playback region. The default in
+       point is 0, and the default out point is the number of frames in the
+       file minus one. Therefore, all frame positions are zero-based.
+
+USET {unit} {key=value}
+       Set a unit's configuration property.
+       Key is one of the following: eof, points.
+       
+       Property "eof" determines what the playback engine does when it reaches
+       the end of a clip. The eof property takes one of the following values:
+       stop, loop, continue or pause. The default is pause.
+       
+       Property "points" determines whether the playback engine restricts the
+       playback region to the in and out points. It takes one of the following
+       values: use, ignore.
+       
+UGET {unit} {key}
+       Get a unit's configuration property.
+       Key is one of the following: eof, points.
+       The response body contains only the key's value. See USET for information 
+       about each property.
+
+LIST {unit}
+       List the clips associated to the unit.
+       The response body consists of two sections - the first section is a single row
+       containing the generation number of the playlist associated to the unit (an
+       integer starting from 0 which is incremented on each action which changes the
+       playlist). The second sections contais a space-delimited row for each clip in the
+       units playlistcontaining the following columns:
+       - clip index (starts from 0)
+       - file name
+       - in point
+       - out point
+       - real length of the files
+       - calculated length of file
+       When USET points=use is specified (default), the calculated size is (out-in)+1. 
+       When points are ignored, the real length of the file is returned.
+
+LOAD {unit} {filename} [in out]
+       Load a clip into the unit.
+       Optionally set the in and out points to the specified absolute frame numbers.
+       Sets the current position to the first frame in the clip.
+       Preface the filename with '!' to tell the disk reader thread to remove only
+       duplicate frames from the tail of its buffer queue (from a previously loaded
+       and playing clip). Otherwise, miracle flushes all of its buffers upon LOAD
+       to make the effect of LOAD instantaneous. The LOAD !, USET eof=pause, and
+       extended USTA information can be used for client-side playlists (see the 
+       demo programs).
+
+APND {unit} {filename} [in out]
+       Append a clip onto the unit's playlist.
+       Optionally set the in and out points to the specified absolute frame numbers.
+       
+INSERT {unit} {filename} [ [+|-]clip [ in out ] ]
+       Insert a clip into the units playlist at the specified clip index or relative
+       to the currently playing clip index.
+
+REMOVE {unit} [ [+|-]clip ]
+       Removes a clip from the specified clip index or position relative to the 
+       currently playing clip index.
+       
+CLEAN {unit}
+       Removes all by the playing clip.
+       
+MOVE {unit} [+|-]clip [ [+|-]clip ]
+       Move a clip in the playlist to position specified or position relative to the
+       currently playing clip.
+
+PLAY {unit} [speed]
+       Commence unit playback from the current position.
+       The default speed is 100% if not specified.
+       Speed is represented as a percentage value multiplied by 10. Therefore
+       the default playback speed is 1000 (1X or 100%), 2X is 2000.
+       Negative speed values play in reverse.
+
+STOP {unit}
+       Terminate the unit playback resulting in no video being sent.
+
+PAUSE {unit}
+       Pause the unit playback causing the current frame position to he held
+       indefinitely.
+
+REW {unit}
+       Rewind the unit.
+       If the unit it playing, then REW sets the playback speed to 2000
+       (200%).
+       If the unit is stopped, then the frame position is reset to the first
+       frame. First frame depends upon the "points" unit configuration property
+       and whether an in point has been established for the clip using the SIN
+       command.
+       Set the currently loaded clip's in point.
+       Frame is zero-based and absolute. It is not dependent upon the clip's
+       current in point.
+       A frame-number of -1, resets the in point to 0.
+
+FF {unit}
+       Fast forward the unit.
+       If the unit it playing, then FF sets the playback speed to -2000 (200%
+       in reverse).
+       If the unit is stopped, then the frame position is reset to the first
+       frame. First frame depends upon the "points" unit configuration property
+       and whether an in point has been established for the clip using the SIN
+       command.
+
+STEP {unit} {number-of-frames}
+       Adjust the current frame position by the number of frames specified.
+       Number-of-frames can accept positive or negative values.
+
+GOTO {unit} {frame-number} [ [+|-]clip ]
+       Set the current frame position to frame-number.
+       Frame-number is zero-based and absolute within the clip, which means it is 
+       relative to the file beginning and not the clip in point.
+       It does not alter the playback status of the unit. 
+
+SIN {unit} {frame-number} [ [+|-]clip ]
+       Set the currently loaded clip's in point.
+       The in point is the logical starting frame of the clip.
+       Frame is zero-based and absolute. It is not dependent upon the clip's
+       current in point.
+       A frame-number of -1, resets the in point to 0.
+
+SOUT {unit} {frame-number} [ [+|-]clip ]
+       Set the currently loaded clip's out point.
+       The out point is the logical last frame of the clip.
+       Frame is zero-based and absolute. It is not dependent upon the clip's
+       current out point.
+       A frame-number of -1, resets the out point to the number of frames in
+       the file minus 1.
+
+USTA {unit}
+       Get the unit status report.
+       The response body contains the following fields delimited by spaces:
+       - unit number: U0, U1, U2, or U3 without the "U" prefix
+       - mode: (offline|not_loaded|playing|stopped|paused|disconnected|unknown)
+         "unknown" means the unit has not been added
+         "disconnected" means the server has closed a connection to a client running
+               STATUS.
+       - current clip name: filename
+       - current position: in absolute frame number units
+       - speed: playback rate in (percent * 10)
+       - fps: frames-per-second of loaded clip
+       - current in-point: starting frame number
+       - current out-point: ending frame number
+       - length of the clip
+       - buffer tail clip name: filename
+       - buffer tail position: in absolute frame number units
+       - buffer tail in-point: starting frame number
+       - buffer tail out-point: ending frame number
+       - buffer tail length: length of clip in buffer tail
+       - seekable flag: indicates if the current clip is seekable (relates to head)
+       - playlist generation number
+       - current clip index (relates to head)
+        
+       The status contains information based not only on the current frame being
+       output (current above) but also based upon the most recent frame read by
+       the disk reader thread and added to the tail of the input buffer queue
+       (buffer tail above).
+
+XFER {unit} {target-unit}
+       Transfer the unit's clip to the target unit.
+       The clip inherently includes the in- and out-point information.
+       The target unit's "points" configuration property is set to "use."
+
+
+
+
diff --git a/mlt/docs/valerie.txt b/mlt/docs/valerie.txt
new file mode 100644 (file)
index 0000000..a5abcce
--- /dev/null
@@ -0,0 +1,861 @@
+VALERIE API Documentation 
+
+Copyright (C) 2003 Ushodaya Enterprised Limited 
+Author: Charles Yates <charles.yates@pandora.be> 
+Last Revision: 2004-01-11
+
+
+TABLE OF CONTENTS
+-----------------
+
+       0. Overview 
+       0.1. Intended Audience
+       0.2. Terminology
+       1. Definition of a Parser 
+       1.1. Construction of a Local Parser 
+       1.2. Construction of a Remote Parser
+       1.3. Using the Parser
+       1.4. Closing the Parser
+       2. The High Level Parser Wrapper
+       2.1. Connecting
+       2.2. valerie_error_code
+       2.3. Using the High Level Wrapper
+       2.4. Obtaining Directory Contents
+       2.5. Obtaining the Node List
+       2.6. Obtaining the Unit List
+       2.7. Unit Status Information
+       2.8. Server Side Queuing APIs
+       2.9. Accessing the Low Level Parser Directly
+       2.10. Cleaning up
+       2.11. Examples
+       3. The Low Level Parser API
+       3.1. Executing a Command
+       3.2. Interpreting valerie_response
+       3.3. Accessing Unit Status
+       APPENDIX A - COMPILATION AND LINKING
+       APPENDIX B - COMPLETE HIGH LEVEL PARSER WRAPPER API LISTING
+       APPENDIX C - COMPLETE LOW LEVEL PARSER API LISTING
+       APPENDIX D - REFERENCES
+       
+
+0. Overview 
+-----------
+
+       This document details how applications interface to DVCP functionality. 
+
+
+0.1. Intended Audience
+----------------------
+
+       This document draws heavily upon the DVCP design (1) and assumes a basic 
+       knowledge of the functionality provided by the DVCP core. 
+
+       It is aimed at developers who wish to use or maintain the API.
+
+
+0.2. Terminology
+----------------
+
+       The API is designed to allow client applications the ability to communicate
+       to a standalone miracle server or entirely embed the DVCP core in an 
+       instance of a client application. 
+
+       The distinction between the two is defined by the construction of the 
+       'parser'. 
+
+       This 'parser' can be used to issue DVCP commands and receive responses and 
+       a 'high level parser wrapper' is provided to simplify the usage and 
+       decouple the application from the DVCP command set.
+
+
+1. Definition of a Parser 
+------------------------- 
+
+       The parser provides a low level API which allows text DVCP commands to be 
+       executed with responses being returned to the caller. Commands and 
+       responses are ASCII formatted text. 
+
+       Two parsers are provided - local and remote. 
+
+       The local parser is the physical implementation which takes commands and 
+       executes them. 
+
+       The remote parser is a network abstraction that forwards commands to a 
+       miracle instance that hosts a local parser. 
+
+
+1.1. Construction of a Local Parser 
+----------------------------------- 
+
+       To construct a local parser you must have:
+
+           #include <miracle/miracle_local.h>
+
+       and code to initialise the parser is as follows:
+
+           valerie_parser parser = miracle_parser_init_local( );
+
+       See Appendix A for compilation and linking details.
+
+
+1.2. Construction of a Remote Parser
+------------------------------------
+
+       To construct a remote parser you must have:
+
+           #include <valerie/valerie_remote.h>
+
+       and code to initialise the parser is as follows:
+
+           valerie_parser parser = valerie_parser_init_remote( "server", port );
+
+       See Appendix A for compilation and linking details.
+
+
+1.3. Using the Parser
+---------------------
+
+       Although the parser can be used directly to send commands and receive 
+       responses, this low level usage puts the onus on the developer to parse the 
+       responses in a meaningful way. 
+
+       Although this usage is not strictly forbidden by applications, it is 
+       discouraged as construction of commands and meaningful parsing of responses 
+       leads to the clients being unnecessarily dependent on the servers input and 
+       output. 
+
+       As a result, a higher level Parser Wrapper API is provided - this API 
+       encapsulates the command construction and response parsing.
+
+       The following 2 sections provide details on these modes of access.
+
+
+1.4. Closing the Parser
+-----------------------
+
+       Regardless of use, it is the constructors responsibility to close the 
+       parser before it goes out of scope. This is done via:
+
+           valerie_parser_close( parser );
+
+
+2. The High Level Parser Wrapper
+--------------------------------
+
+       The recommended way to access the parser, is via the valerie API. To use 
+       this API, you must have:
+
+           #include <valerie/valerie.h>
+
+       and code to construct the wrapper is:
+
+           valerie dv = valerie_init( parser );
+
+       Note that either remote or local parsers can be used here and there is no 
+       difference in usage, though some error returns will not be applicable to 
+       both. 
+
+       It is recommended that applications honour and deal with the error returns 
+       of both as this allows applications to interchange parsers.
+
+       Also note that valerie is not threadsafe, so you should not use the same 
+       structure in multiple threads. The correct solution to this is to create a
+       valerie per thread - you may safely use the same parser for each thread ie:
+
+           /* valerie for the application */
+           valerie dv = valerie_init( parser );
+           /* valerie for the status handling thread. */
+           valerie dv_status = valerie_init( parser );
+
+       For the purposes of simplification, the remainder of this section assumes 
+       that a remote parser is in use. 
+
+
+2.1. Connecting
+---------------
+
+       Once constructed, the next thing to do is 'connect':
+
+           valerie_error_code error = valerie_connect( dv );
+
+       This function call initialises the parser (ie: if it's remote, it 
+       establishes a connection to the server, or if it's local, it initialises 
+       the state of the units and supporting objects).
+
+       Note that if you have multiple valerie instances on the same parser you 
+       should only connect one of the instances.
+
+
+2.2. valerie_error_code
+----------------------
+
+       All but a couple of the functions that make up the valerie API return a 
+       valerie_error_code.
+
+       These are defined as follows:
+
+           valerie_ok = 0,
+           valerie_malloc_failed,
+           valerie_unknown_error,
+           valerie_no_response,
+           valerie_invalid_command,
+           valerie_server_timeout,
+           valerie_missing_argument,
+           valerie_server_unavailable,
+           valerie_unit_creation_failed,
+           valerie_unit_unavailable,
+           valerie_invalid_file,
+           valerie_invalid_position
+
+       In most cases, it is sufficient to check on a return of valerie_ok.
+
+       To obtain a textual description of a particular error, you can use:
+
+           char *valerie_error_description( valerie_error_code );
+
+
+2.3. Using the High Level Wrapper
+---------------------------------
+
+       The following code snippet assumes that dv is an initialised and connected 
+       valerie structure:
+
+           valerie_error_code error = valerie_unit_play( dv, 0 );
+           if ( error == valerie_ok )
+            fprintf( stderr, "Unit 0 is now playing\n" );
+           else
+            fprintf( stderr, "Play on unit 0 failed: %s\n",
+                         valerie_error_description( error ) );
+
+       The complete interface to valerie is listed in Appendix B of this document.
+
+
+2.4. Obtaining Directory Contents
+--------------------------------
+
+       To obtain a list of files and subdirectories in a given directory relative 
+       to the ROOT property of the server, DVCP provides the CLS command. 
+
+       A valid execution of CLS would be something like:
+
+           CLS "/Stuff"
+
+       would provide a response formatted as follows:
+
+           201 OK
+           "More Stuff/"
+           "file0001.dv" 15552000
+           "file0002.dv" 15552000
+
+       with a trailing empty line.
+
+       The first line indicates the error value, the second line shows an example 
+       of a subdirectory and the 3rd and 4th line lists two files that happen to 
+       exist in the directory.
+
+       valerie provides a high level view on this which automatically parses the 
+       response from the server correctly via the valerie_dir structures and 
+       related functions. 
+
+       An example of use is as follows:
+       
+           valerie_dir dir = valerie_dir_init( dv, "/Stuff" );
+           valerie_error_code error = valerie_dir_get_error_code( dir );
+           if ( error == valerie_ok )
+           {
+               if ( valerie_dir_count( dir ) > 0 )
+               {
+                   valerie_dir_entry_t entry;
+                   int index = 0;
+                   for ( index = 0; index < valerie_dir_count( dir ); index ++ )
+                   {
+                       valerie_dir_get( dir, index, &entry );
+                       if ( entry.dir )
+                           printf( "<%s>\n", entry.name );
+                       else
+                           printf( "%30s %8d", entry.name, entry.size );
+                   }
+               }
+               else
+               {
+                   fprintf( stderr, "Directory is empty\n" );
+               }
+           }
+           else
+           {
+               fprintf( stderr, "Directory listing failed: %s\n",
+                                valerie_error_description( error ) );
+           }
+           valerie_dir_close( dir );
+
+       Note that entry.name provides the name of the file or directory without the 
+       directory prefix. As a convenience, entry.full provides the prefixed name, 
+       so you could subsequently use:
+
+           error = valerie_unit_load( dv, 0, entry.full );
+
+       to load unit 0 with an entry.
+
+
+2.5. Obtaining the Node List
+----------------------------
+
+       Currently not defined by miracle.
+
+2.6. Obtaining the Unit List
+----------------------------
+
+       To obtain a list of defined units, DVCP provides the ULS command.
+       
+       A valid execution of ULS would be:
+       
+           ULS
+       
+       and would provide a response formatted as follows:
+       
+           201 OK
+               U0 00 sdl:360x288 1
+       
+       with a trailing empty line.
+       
+       The fields of each record in the response dictate unit, node, mlt consumer and 
+       online status respectively.
+       
+       valerie provides a high level view on this which automatically parses the 
+       response from the server correctly via the valerie_units structures and 
+       related functions. 
+       
+       An example of use is as follows:
+       
+           valerie_units units = valerie_units_init( dv );
+           valerie_error_code error = valerie_units_get_error_code( units );
+           if ( error == valerie_ok )
+           {
+               if ( valerie_units_count( units ) > 0 )
+               {
+                   valerie_unit_entry_t entry;
+                   int index = 0;
+                   for ( index = 0; index < valerie_units_count( units ); index ++ )
+                   {
+                       valerie_units_get( units, index, &entry );
+                       printf( "U%d %02d %s %s\n", 
+                               entry.unit,
+                               entry.node,
+                               entry.guid,
+                               entry.online ? "online" : "offline" );
+                   }
+               }
+               else
+               {
+                   fprintf( stderr, "Unit list is empty\n" );
+               }
+           }
+           else
+           {
+               fprintf( stderr, "Unit listing failed: %s\n",
+                                valerie_error_description( error ) );
+           }
+           valerie_units_close( units );
+       
+
+2.7. Unit Status Information
+----------------------------
+
+       There are two methods for a client to obtain unit status information.
+       
+       The first is via the DVCP USTA command, which would normally be accessed 
+       via: 
+
+           USTA U0
+       
+       and would provide a response formated as follows:
+       
+           202 OK
+               0 playing "a.dv" 58 1000 25.00 0 6999 7000 "a.dv" 157 0 6999 7000 1 4 0
+               
+       with no trailing empty line.
+       
+       The entries in the record are:
+       
+       * Unit
+       * State (undefined, offline, not_loaded, stopped, playing, 
+                paused, disconnected [when server dies])
+       * Name of Clip
+       * Position in clip
+       * Speed * 1000
+       * Frames per second
+       * Start of clip (in point)
+       * End of clip (out point)
+       * Length of clip
+       * Read ahead clip
+       * Read ahead position 
+       * Read ahead clip in
+       * Read ahead clip out
+       * Read ahead clip length
+       * Seekable flag
+       * Playlist generation
+       * Clip index
+       
+       Again, valerie provides a high level means for obtaining this via the 
+       valerie_unit_status function and valerie_status structures:
+       
+           valerie_status_t status;
+           valerie_error_code error = valerie_unit_status( dv, 0, &status );
+           if ( error == valerie_ok )
+           {
+               switch( status.status )
+               {
+                   case unit_offline:
+                       printf( "offline   " );
+                       break;
+                   case unit_undefined:
+                       printf( "undefined " );
+                       break;
+                   case unit_not_loaded:
+                       printf( "unloaded  " );
+                       break;
+                   case unit_stopped:
+                       printf( "stopped   " );
+                       break;
+                   case unit_playing:
+                       printf( "playing   " );
+                       break;
+                   default:
+                       printf( "unknown   " );
+                       break;
+               }
+       
+               printf( "%06lld %06lld %06lld %s\n", status.in,
+                                                    status.position,
+                                                    status.out,
+                                                    status.clip );
+           }
+           else
+           {
+               fprintf( stderr, "Unit status failed: %s\n",
+                                valerie_error_description( error ) );
+           }
+       
+       The second approach for obtaining a units status is via automatic 
+       notification.
+       
+       This is done via the valerie_notifier API. To obtain the notifier from the 
+       high level API, you can use:
+       
+           valerie_notifier notifier = valerie_get_notifier( dv );
+       
+       To obtain the last status associated to a unit, you can use:
+       
+           int unit = 1;
+           valerie_status_t status;
+           valerie_notifier_get( notifier, &status, unit );
+       
+       To wait for the next status from any unit, you can use:
+       
+           valerie_notifier_wait( notifier, &status );
+       
+       If you wish to trigger the action associated to your applications wait 
+       handling of a particular unit, you can use:
+       
+           valerie_notifier_get( notifier, &status, unit );
+           valerie_notifier_put( notifier, &status );
+       
+       See Examples below for details on this.
+
+       The complete list of fields in the status structure are:
+
+           int unit;
+           unit_status status;
+           char clip[ 2048 ];
+           int64_t position;
+           int speed;
+           double fps;
+           int64_t in;
+           int64_t out;
+               int64_t length;
+           char tail_clip[ 2048 ];
+           int64_t tail_position;
+           int64_t tail_in;
+           int64_t tail_out;
+               int64_t tail_length;
+               int seekable;
+               int generation;
+               int clip_index;
+       
+       You will always receive a status record for every frame output.
+
+       The read ahead information is provided for client side queuing. Client side
+       queuing assumes that uset eof=pause is applied to the unit. A client can 
+       detect when the previously scheduled clip is played out by using the read 
+       ahead information and schedule the next clip. While this mode of operation
+       is still supported, it is recommended that new clients use the server side
+       queuing mechanism which is described in the following section.
+       
+
+2.8. Server Side Queueing APIs
+------------------------------
+
+       This section describes the APIs available to provide server side queueing. 
+       
+       The concept is that each unit maintains its own playlist, containing multiple
+       clips. Associated to the playlist is a generation number which is incremented 
+       on each modification to the playlist. The current playlist generation is
+       provided in the status record in order for a client to know when to refresh
+       its presentation of the list. The status record also indicates which clip is 
+       currently active.
+       
+       Actions that can be carried out on the playlist are summarised as:
+       
+       * list - list all the clips and associated in/out points and size
+       * loading a clip - a load will wipe the current list and replace it with the
+         specified clip
+       * appending a clip - append will always place the specified clip at the end 
+         of the playlist
+       * inserting a clip - insert will place a new clip at the specified position 
+         in the playlist
+       * moving a clip - move will allow clips can be moved in the playlist
+       * removing a clip - remove will remove the specified clip from the playlist
+       * clean - clean will remove all but the playing clip from the playlist
+       
+       Additionally, the following existing actions are clip aware:
+       
+       * goto allows you to move the current play position to a specific clip position
+       * set in/out points allows you to modify clip in and out points
+       
+       Backward compatability has been maintained by the addition of a clip-aware 
+       family of APIs which have the naming convention of valerie_unit_clip_*.
+       
+       These are listed in Appendix B.
+       
+       The following shows an example of obtaining the clips queued on unit 0:
+       
+               valerie_list list = valerie_list_init( dv, 0 );
+               valerie_list_entry_t entry;
+               int index;
+               
+               printf( "Generation = %d\n", list->generation );
+               for ( index = 0; index < valerie_list_count( list ); index ++ )
+               {
+                       valerie_list_get( list, index, &entry );
+                       printf( "%d %s %d %d %d %d\n", 
+                                       entry.clip, 
+                                       entry.full,
+                                       entry.in,
+                                       entry.out,
+                                       entry.max,
+                                       entry.size );
+               }
+               valerie_list_close( list );
+               
+       To load a clip on unit 0:
+       
+               valerie_unit_load( dv, 0, "/path/clip.dv" );
+               
+       To append a clip on unit 0:
+       
+               valerie_unit_append( dv, 0, "/path/clip.dv", -1, -1 );
+               
+       Note that the last two arguments specify the in and out points of the clip
+       with -1 denoting dfaults of the entirety of the file.
+       
+       To insert a clip at position 0 on unit 0, we can use the following:
+       
+               valerie_unit_clip_insert( dv, 0, clip_absolute, 0, "/path/clip.dv", -1, -1 );
+               
+       The 3rd and 4th arguments here are common to all the valerie_unit_clip functions.
+       They take the form of either [clip_absolute, n] to indicate an absolute clip
+       index, or [clip_relative, n] to indicate a clip index relative to the 
+       currently playing clip.
+       
+       So, to insert a clip immediately before the currently playing clip, we can
+       use:
+       
+               valerie_unit_clip_insert( dv, 0, clip_relative, -1, "/path/clip.dv", -1, -1 );
+               
+       To move the current clip to the next position in the list:
+       
+               valerie_unit_clip_move( dv, 0, clip_relative, 0, clip_relative, 1 );
+               
+       To remove a specific clip:
+       
+               valerie_unit_clip_remove( dv, 0, clip_absolute, index );
+               
+       To remove all but the currently playing clip:
+       
+               valerie_unit_clean( dv, 0 );
+               
+       To goto the first frame in the first clip, you can use:
+       
+               valerie_unit_clip_goto( dv, 0, clip_absolute, 0, 0 );
+               
+       To set the in and out points on the current clip:
+       
+               valerie_unit_clip_set_in( dv, 0, clip_relative, 0, 0 );
+               valerie_unit_clip_set_out( dv, 0, clip_relative, 0, 1000 );
+               
+       A more complete example of use of the server side can queuing can be found
+       at:
+       
+               http://users.pandora.be/acp/gdv1394
+               
+       The demo client provided with valerie is used for retaining backward 
+       compatability with the client side queuing API.
+
+       
+2.9. Accessing the Low Level Parser Directly
+--------------------------------------------
+
+       The low level parser and its associated structures can be accessed directly 
+       from the high level API, but is very occasionally actually needed.
+       
+       The methods are provided via a pair of high level methods:
+       
+           valerie_error_code error = valerie_execute( dv, 1024, "USTA U%d", unit );
+           valerie_response response = valerie_get_last_response( dv );
+           int index = 0;
+           for ( index = 0; index < valerie_response_count( response ); index ++ )
+               printf( "%d: %s\n", index, valerie_response_get_line( response,index ) );
+       
+       More details on the valerie_response structure can be found in section 3 of this
+       document.
+       
+
+2.10. Cleaning up
+-----------------
+
+       Before the valerie and parser go out of scope, you need to run:
+       
+           valerie_close( dv );
+           valerie_parser_close( parser );
+       
+       Note that you should close all valerie instances before closing the parser.
+       
+
+2.11. Examples
+--------------
+
+       Please refer to albino and humperdink source for examples provided with
+       the project. Additional examples can be found via google with gdv1394 and
+       poldo.
+
+
+3. The Low Level Parser API
+---------------------------
+
+       The low level parser API provides a very simple mechanism for constructing 
+       commands and receiving responses.
+       
+       As described in section 2, a parser is constructed as local or remote and 
+       this is sufficient for constructing the low level parser.
+       
+
+3.1. Executing a Command
+------------------------
+
+       All commands can be executed via the single variable argument function
+       valerie_parser_executef and this function returns a valerie_response, ie:
+       
+           valerie_response response = valerie_parser_executef( parser, "CLS \"%s\"", dir );
+       
+       Note that no carriage return/line feed is required (adding this is 
+       erroneous).
+       
+       It is the receiver of the response who is responsible for closing it.
+       
+           valerie_response_close( response );
+       
+
+3.2. Interpreting valerie_response
+-----------------------------
+
+       The response received can be NULL, but it is safe to call:
+       
+           int error = valerie_response_get_error_code( response );
+       
+       which will return:
+       
+       * -1 if response is NULL, 
+       * -2 if there is no content to the response, 
+       * 0 if the responses first line does not correspond to a valid DVCP response
+       * or the DVCP protocol error code returned on the first line of the response
+       
+       A simple use of a valerie_response structure is as follows:
+       
+           valerie_response response = valerie_parser_executef( parser, "CLS \"%s\"", dir );
+           int error = valerie_response_get_error_code( response );
+           if ( error >= 0 )
+           {
+               int index = 0;
+               for ( index = 0; index < valerie_response_count( response ); index ++ )
+                   printf( "%3d: %s\n", index, valerie_response_get_line( response, index ) );
+           }
+           else
+           {
+               /* interpret error */
+           }
+           valerie_response_close( response );
+       
+       Note that it is safe to call valerie_response_close regardless of the error 
+       condition indicated.
+       
+
+3.3. Accessing Unit Status
+--------------------------
+
+       As with the high level parser, there are two alternatives to obtain unit 
+       status information - either via the USTA DVCP command or via the 
+       valerie1394_notifier.
+       
+       The latter is the recommended way for any applications which wish to extract
+       meaningful information from the status while avoiding the requirement to 
+       duplicate the parsing process in a specific client.
+       
+       The notifier can be obtained by:
+       
+       valerie_notifier notifier = valerie_parser_get_notifier( parser );
+       
+       The use of the notifier with the low level parser is identical to that 
+       dictated in Section 2 - to obtain the last status associated to a unit, 
+       you can use: 
+
+           int unit = 1;
+           valerie_status_t status;
+           valerie_notifier_get( notifier, &status, unit );
+           
+       To wait for the next status from any unit, you can use:
+       
+           valerie_notifier_wait( notifier, &status );
+       
+
+APPENDIX A - COMPILATION AND LINKING
+------------------------------------
+
+       Compilation flags are:
+
+           -I <prefix>/include
+
+       where prefix defaults to /usr/local.
+
+       Linking flags for a client are:
+
+           -L <prefix>/lib/ -lvalerie
+
+       Or for a local parser:
+
+           -L <prefix>/lib/ -lmiracle
+
+       Note that you never need both libs.
+
+
+APPENDIX B - COMPLETE HIGH LEVEL PARSER WRAPPER API LISTING
+-----------------------------------------------------------
+
+       valerie valerie_init( valerie_parser );
+       
+       valerie_error_code valerie_connect( valerie );
+       
+       valerie_error_code valerie_set( valerie, char *, char * );
+       valerie_error_code valerie_get( valerie, char *, char *, int );
+       
+       valerie_error_code valerie_unit_add( valerie, char * );
+       valerie_error_code valerie_unit_load( valerie, int, char * );
+       valerie_error_code valerie_unit_load_clipped( valerie,int,char *,long,long );
+       valerie_error_code valerie_unit_load_back( valerie, int, char * );
+       valerie_error_code valerie_unit_load_back_clipped(valerie,int,char *,long,long)
+       valerie_error_code valerie_unit_play( valerie, int );
+       valerie_error_code valerie_unit_play_at_speed( valerie, int, int );
+       valerie_error_code valerie_unit_stop( valerie, int );
+       valerie_error_code valerie_unit_pause( valerie, int );
+       valerie_error_code valerie_unit_rewind( valerie, int );
+       valerie_error_code valerie_unit_fast_forward( valerie, int );
+       valerie_error_code valerie_unit_step( valerie, int, int );
+       valerie_error_code valerie_unit_goto( valerie, int, int );
+       valerie_error_code valerie_unit_set_in( valerie, int, int );
+       valerie_error_code valerie_unit_set_out( valerie, int, int );
+       valerie_error_code valerie_unit_clear_in( valerie, int );
+       valerie_error_code valerie_unit_clear_out( valerie, int );
+       valerie_error_code valerie_unit_clear_in_out( valerie, int );
+       valerie_error_code valerie_unit_set( valerie, int, char *, char * );
+       valerie_error_code valerie_unit_get( valerie, int, char * );
+       
+       valerie_error_code valerie_unit_status( valerie, int, valerie_status );
+       valerie_notifier valerie_get_notifier( valerie );
+       
+       valerie_dir valerie_dir_init( valerie, char * );
+       valerie_error_code valerie_dir_get( valerie_dir, int, valerie_dir_entry );
+       int valerie_dir_count( valerie_dir );
+       void valerie_dir_close( valerie_dir );
+       
+       valerie_nodes valerie_nodes_init( valerie );
+       valerie_error_code valerie_nodes_get(valerie_nodes,int,valerie_node_entry);
+       int valerie_nodes_count( valerie_nodes );
+       void valerie_nodes_close( valerie_nodes );
+       
+       valerie_units valerie_units_init( valerie );
+       valerie_error_code valerie_units_get(valerie_units,int,valerie_unit_entry);
+       int valerie_units_count( valerie_units );
+       void valerie_units_close( valerie_units );
+       
+       valerie_response valerie_get_last_response( valerie );
+       
+       valerie_error_code valerie_execute( valerie, size_t, char *, ... );
+       
+       void valerie_close( valerie );
+       
+       Notifier Functions
+       ------------------
+       
+       void valerie_notifier_get( valerie_notifier, valerie_status, int );
+       void valerie_notifier_put( valerie_notifier, valerie_status );
+       int valerie_notifier_wait( valerie_notifier, valerie_status );
+       void valerie_notifier_close( valerie_notifier );
+       
+       Server Side Queuing
+       -------------------
+
+       valerie_list valerie_list_init( valerie, int )
+       valerie_error_code valerie_list_get_error_code( valerie_list )
+       valerie_error_code valerie_list_get( valerie_list, int, valerie_list_entry )
+       int valerie_list_count( valerie_list )
+       void valerie_list_close( valerie_list )
+       
+       valerie_error_code valerie_unit_clean( valerie dv, int unit )
+       valerie_error_code valerie_unit_append( valerie dv, int unit, char *file, int in, int out )
+       valerie_error_code valerie_unit_remove_current_clip( valerie dv, int unit )
+       
+       valerie_error_code valerie_unit_clip_goto( valerie dv, int unit, valerie_clip_offset offset, int clip, int position )
+       valerie_error_code valerie_unit_clip_set_in( valerie dv, int unit, valerie_clip_offset offset, int clip, int in )
+       valerie_error_code valerie_unit_clip_set_out( valerie dv, int unit, valerie_clip_offset offset, int clip, int in )
+       valerie_error_code valerie_unit_clip_move( valerie dv, int unit, valerie_clip_offset offset, int src, valerie_clip_offset offset, int dest )
+       valerie_error_code valerie_unit_clip_remove( valerie dv, int unit, valerie_clip_offset offset, int clip )
+       valerie_error_code valerie_unit_clip_insert( valerie dv, int unit, valerie_clip_offset offset, int clip, char *file, int in, int out )
+
+       
+
+APPENDIX C - COMPLETE LOW LEVEL PARSER API LISTING
+--------------------------------------------------
+
+       valerie_response valerie_parser_connect( valerie_parser );
+       valerie_response valerie_parser_execute( valerie_parser, char * );
+       valerie_response valerie_parser_executef( valerie_parser, char *, ... );
+       valerie_response valerie_parser_run( valerie_parser, char * );
+       valerie_notifier valerie_parser_get_notifier( valerie_parser );
+       void valerie_parser_close( valerie_parser );
+       
+       valerie_response valerie_response_init( );
+       valerie_response valerie_response_clone( valerie_response );
+       int valerie_response_get_error_code( valerie_response );
+       char *valerie_response_get_error_string( valerie_response );
+       char *valerie_response_get_line( valerie_response, int );
+       int valerie_response_count( valerie_response );
+       void valerie_response_set_error( valerie_response, int, char * );
+       int valerie_response_printf( valerie_response, size_t, char *, ... );
+       int valerie_response_write( valerie_response, char *, int );
+       void valerie_response_close( valerie_response );
+       
+
+APPENDIX D - REFERENCES
+-----------------------
+
+       (1) doc/dvcp.txt - DVCP protocol
+       (2) doc/testing.txt - Test procedures
index 798c9ed4553856f1de4316c65e242642de2c603d..7daa7c9959d4109f1851f4f8921f79868c27f378 100644 (file)
@@ -238,6 +238,16 @@ static mlt_producer mlt_playlist_virtual_seek( mlt_playlist this )
                mlt_producer_seek_frame( producer, position + entry->frame_out );
                mlt_producer_set_speed( producer, 0 );
        }
+       else if ( !strcmp( eof, "loop" ) && total > 0 )
+       {
+               playlist_entry *entry = this->list[ 0 ];
+               mlt_producer this_producer = mlt_playlist_producer( this );
+               mlt_producer_seek_frame( this_producer, 0 );
+               producer = entry->producer;
+               position = entry->frame_in;
+               position += mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) );
+               mlt_producer_seek_frame( producer, position );
+       }
        else
        {
                mlt_producer_seek( mlt_playlist_producer( this ), 0 );
index ba8bf09839b6f94afa982450f48358815d879dee..aa81efc0703bcde7883a8c8725f8d4c226d2b392 100644 (file)
@@ -593,6 +593,20 @@ void miracle_unit_step( miracle_unit unit, int64_t offset )
        //return dv_player_get_eof_action( player );
 //}
 
+int miracle_unit_set( miracle_unit unit, char *name_value )
+{
+       mlt_playlist playlist = mlt_properties_get_data( unit->properties, "playlist", NULL );
+       mlt_properties properties = mlt_playlist_properties( playlist );
+       return mlt_properties_parse( properties, name_value );
+}
+
+char *miracle_unit_get( miracle_unit unit, char *name )
+{
+       mlt_playlist playlist = mlt_properties_get_data( unit->properties, "playlist", NULL );
+       mlt_properties properties = mlt_playlist_properties( playlist );
+       return mlt_properties_get( properties, name );
+}
+
 /** Release the unit
 
     \todo error handling
index 7670b457d8234812b7ae51abdb06ef9cf0f7d3bd..9cf26638a93c830c8056d2fc93cef7a9a655d0c4 100644 (file)
@@ -69,6 +69,8 @@ extern void                 miracle_unit_step( miracle_unit unit, int64_t offset
 extern void                 miracle_unit_close( miracle_unit unit );
 extern void                 miracle_unit_suspend( miracle_unit );
 extern void                 miracle_unit_restore( miracle_unit );
+extern int                                     miracle_unit_set( miracle_unit, char *name_value );
+extern char *                          miracle_unit_get( miracle_unit, char *name );
 extern int                                     miracle_unit_get_current_clip( miracle_unit );
 
 
index e0f60031ea2f010d3be2f8ab11681f2bdebc81e0..99de3f40e027f99fde595727e46a63f6fb594c52 100644 (file)
@@ -373,179 +373,24 @@ int miracle_get_unit_status( command_argument cmd_arg )
 
 int miracle_set_unit_property( command_argument cmd_arg )
 {
-       /*
-       dv_unit unit = miracle_get_unit(cmd_arg->unit);
-       
+       miracle_unit unit = miracle_get_unit(cmd_arg->unit);
+       char *name_value = (char*) cmd_arg->argument;
        if (unit == NULL)
                return RESPONSE_INVALID_UNIT;
        else
-       {
-               char *key = (char*) cmd_arg->argument;
-               char *value = NULL;
-
-               value = strchr( key, '=' );
-               if (value == NULL)
-                       return RESPONSE_OUT_OF_RANGE;
-               value[0] = 0;
-               value++;
-               miracle_log( LOG_DEBUG, "USET %s = %s", key, value );
-               if ( strncasecmp( key, "eof", 1024) == 0 )
-               {
-                       if ( strncasecmp( value, "pause", 1024) == 0)
-                               dv_unit_set_eof_action( unit, dv_player_pause );
-                       else if ( strncasecmp( value, "loop", 1024) == 0)
-                               dv_unit_set_eof_action( unit, dv_player_loop );
-                       else if ( strncasecmp( value, "stop", 1024) == 0)
-                               dv_unit_set_eof_action( unit, dv_player_terminate );
-                       else if ( strncasecmp( value, "clean", 1024) == 0)
-                               dv_unit_set_eof_action( unit, dv_player_clean_loop );
-                       else
-                               return RESPONSE_OUT_OF_RANGE;
-               }
-               else if ( strncasecmp( key, "points", 1024) == 0 )
-               {
-                       if ( strncasecmp( value, "use", 1024) == 0)
-                               dv_unit_set_mode( unit, dv_clip_mode_restricted );
-                       else if ( strncasecmp( value, "ignore", 1024) == 0)
-                               dv_unit_set_mode( unit, dv_clip_mode_unrestricted );
-                       else
-                               return RESPONSE_OUT_OF_RANGE;
-               }
-               else if ( strncasecmp( key, "syt_offset", 1024) == 0 )
-               {
-                       dv_unit_set_syt_offset( unit, atoi( value ) );
-               }
-               else if ( strncasecmp( key, "cip_n", 1024) == 0 )
-               {
-                       dv_unit_set_cip_n( unit, atoi( value ) );
-               }
-               else if ( strncasecmp( key, "cip_d", 1024) == 0 )
-               {
-                       dv_unit_set_cip_d( unit, atoi( value ) );
-               }
-               else if ( strncasecmp( key, "size", 1024) == 0 )
-               {
-                       dv_unit_set_buffer_size( unit, atoi( value ) );
-               }
-               else if ( strncasecmp( key, "n_frames", 1024) == 0 )
-               {
-                       dv_unit_set_n_frames( unit, atoi( value ) );
-               }               
-               else if ( strncasecmp( key, "n_fill", 1024) == 0 )
-               {
-                       dv_unit_set_n_fill( unit, atoi( value ) );
-               }               
-               else
-                       return RESPONSE_OUT_OF_RANGE;
-       }
-       */
+               miracle_unit_set( unit, name_value );
        return RESPONSE_SUCCESS;
 }
 
 int miracle_get_unit_property( command_argument cmd_arg )
 {
-       /*
-       dv_unit unit = miracle_get_unit(cmd_arg->unit);
-       
+       miracle_unit unit = miracle_get_unit(cmd_arg->unit);
+       char *name = (char*) cmd_arg->argument;
+       char *value = miracle_unit_get( unit, name );
        if (unit == NULL)
                return RESPONSE_INVALID_UNIT;
-       else
-       {
-               char *key = (char*) cmd_arg->argument;
-
-               if ( strncasecmp( key, "eof", 1024) == 0 )
-               {
-                       switch ( dv_unit_get_eof_action( unit ) )
-                       {
-                               case dv_player_pause:
-                                       dv_response_write( cmd_arg->response, "pause", strlen("pause") );
-                                       break;
-                               case dv_player_loop:
-                                       dv_response_write( cmd_arg->response, "loop", strlen("loop") );
-                                       break;
-                               case dv_player_terminate:
-                                       dv_response_write( cmd_arg->response, "stop", strlen("stop") );
-                                       break;
-                               case dv_player_clean_loop:
-                                       dv_response_write( cmd_arg->response, "clean", strlen("clean") );
-                                       break;
-                       }
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "points", 1024) == 0 )
-               {
-                       if ( dv_unit_get_mode( unit ) == dv_clip_mode_restricted )
-                               dv_response_write( cmd_arg->response, "use", strlen("use") );
-                       else
-                               dv_response_write( cmd_arg->response, "ignore", strlen("ignore") );
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "syt_offset", 1024) == 0 )
-               {
-                       dv_response_printf( cmd_arg->response, 1024, "%d\n",
-                               dv_unit_get_syt_offset( unit ) );
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "cip_n", 1024) == 0 )
-               {
-                       dv_response_printf( cmd_arg->response, 1024, "%d\n",
-                               dv_unit_get_cip_n( unit ) );
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "cip_d", 1024) == 0 )
-               {
-                       dv_response_printf( cmd_arg->response, 1024, "%d\n",
-                               dv_unit_get_cip_d( unit ) );
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "size", 1024) == 0 )
-               {
-                       dv_response_printf( cmd_arg->response, 1024, "%d\n",
-                               dv_unit_get_buffer_size( unit ) );
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "n_frames", 1024) == 0 )
-               {
-                       dv_response_printf( cmd_arg->response, 1024, "%d\n",
-                               dv_unit_get_n_frames( unit ) );
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "n_fill", 1024) == 0 )
-               {
-                       dv_response_printf( cmd_arg->response, 1024, "%d\n",
-                               dv_unit_get_n_fill( unit ) );
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "all", 1024 ) == 0 )
-               {
-                       switch ( dv_unit_get_eof_action( unit ) )
-                       {
-                               case dv_player_pause:
-                                       dv_response_write( cmd_arg->response, "eof=pause\n", strlen("pause") );
-                                       break;
-                               case dv_player_loop:
-                                       dv_response_write( cmd_arg->response, "eof=loop\n", strlen("loop") );
-                                       break;
-                               case dv_player_terminate:
-                                       dv_response_write( cmd_arg->response, "eof=stop\n", strlen("stop") );
-                                       break;
-                               case dv_player_clean_loop:
-                                       dv_response_write( cmd_arg->response, "eof=clean\n", strlen("clean") );
-                                       break;
-                       }
-                       if ( dv_unit_get_mode( unit ) == dv_clip_mode_restricted )
-                               dv_response_write( cmd_arg->response, "points=use\n", strlen("use") );
-                       else
-                               dv_response_write( cmd_arg->response, "points=ignore\n", strlen("ignore") );
-                       dv_response_printf( cmd_arg->response, 1024, "syt_offset=%d\n", dv_unit_get_syt_offset( unit ) );
-                       dv_response_printf( cmd_arg->response, 1024, "cip_n=%d\n", dv_unit_get_cip_n( unit ) );
-                       dv_response_printf( cmd_arg->response, 1024, "cip_d=%d\n", dv_unit_get_cip_d( unit ) );
-                       dv_response_printf( cmd_arg->response, 1024, "size=%d\n", dv_unit_get_buffer_size( unit ) );
-                       dv_response_printf( cmd_arg->response, 1024, "n_frames=%d\n", dv_unit_get_n_frames( unit ) );
-                       dv_response_printf( cmd_arg->response, 1024, "n_fill=%d\n", dv_unit_get_n_fill( unit ) );
-               }
-       }
-       */
+       else if ( value != NULL )
+               valerie_response_printf( cmd_arg->response, 1024, "%s\n", value );
        return RESPONSE_SUCCESS;
 }
 
index 798c9ed4553856f1de4316c65e242642de2c603d..7daa7c9959d4109f1851f4f8921f79868c27f378 100644 (file)
@@ -238,6 +238,16 @@ static mlt_producer mlt_playlist_virtual_seek( mlt_playlist this )
                mlt_producer_seek_frame( producer, position + entry->frame_out );
                mlt_producer_set_speed( producer, 0 );
        }
+       else if ( !strcmp( eof, "loop" ) && total > 0 )
+       {
+               playlist_entry *entry = this->list[ 0 ];
+               mlt_producer this_producer = mlt_playlist_producer( this );
+               mlt_producer_seek_frame( this_producer, 0 );
+               producer = entry->producer;
+               position = entry->frame_in;
+               position += mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) );
+               mlt_producer_seek_frame( producer, position );
+       }
        else
        {
                mlt_producer_seek( mlt_playlist_producer( this ), 0 );
index ba8bf09839b6f94afa982450f48358815d879dee..aa81efc0703bcde7883a8c8725f8d4c226d2b392 100644 (file)
@@ -593,6 +593,20 @@ void miracle_unit_step( miracle_unit unit, int64_t offset )
        //return dv_player_get_eof_action( player );
 //}
 
+int miracle_unit_set( miracle_unit unit, char *name_value )
+{
+       mlt_playlist playlist = mlt_properties_get_data( unit->properties, "playlist", NULL );
+       mlt_properties properties = mlt_playlist_properties( playlist );
+       return mlt_properties_parse( properties, name_value );
+}
+
+char *miracle_unit_get( miracle_unit unit, char *name )
+{
+       mlt_playlist playlist = mlt_properties_get_data( unit->properties, "playlist", NULL );
+       mlt_properties properties = mlt_playlist_properties( playlist );
+       return mlt_properties_get( properties, name );
+}
+
 /** Release the unit
 
     \todo error handling
index 7670b457d8234812b7ae51abdb06ef9cf0f7d3bd..9cf26638a93c830c8056d2fc93cef7a9a655d0c4 100644 (file)
@@ -69,6 +69,8 @@ extern void                 miracle_unit_step( miracle_unit unit, int64_t offset
 extern void                 miracle_unit_close( miracle_unit unit );
 extern void                 miracle_unit_suspend( miracle_unit );
 extern void                 miracle_unit_restore( miracle_unit );
+extern int                                     miracle_unit_set( miracle_unit, char *name_value );
+extern char *                          miracle_unit_get( miracle_unit, char *name );
 extern int                                     miracle_unit_get_current_clip( miracle_unit );
 
 
index e0f60031ea2f010d3be2f8ab11681f2bdebc81e0..99de3f40e027f99fde595727e46a63f6fb594c52 100644 (file)
@@ -373,179 +373,24 @@ int miracle_get_unit_status( command_argument cmd_arg )
 
 int miracle_set_unit_property( command_argument cmd_arg )
 {
-       /*
-       dv_unit unit = miracle_get_unit(cmd_arg->unit);
-       
+       miracle_unit unit = miracle_get_unit(cmd_arg->unit);
+       char *name_value = (char*) cmd_arg->argument;
        if (unit == NULL)
                return RESPONSE_INVALID_UNIT;
        else
-       {
-               char *key = (char*) cmd_arg->argument;
-               char *value = NULL;
-
-               value = strchr( key, '=' );
-               if (value == NULL)
-                       return RESPONSE_OUT_OF_RANGE;
-               value[0] = 0;
-               value++;
-               miracle_log( LOG_DEBUG, "USET %s = %s", key, value );
-               if ( strncasecmp( key, "eof", 1024) == 0 )
-               {
-                       if ( strncasecmp( value, "pause", 1024) == 0)
-                               dv_unit_set_eof_action( unit, dv_player_pause );
-                       else if ( strncasecmp( value, "loop", 1024) == 0)
-                               dv_unit_set_eof_action( unit, dv_player_loop );
-                       else if ( strncasecmp( value, "stop", 1024) == 0)
-                               dv_unit_set_eof_action( unit, dv_player_terminate );
-                       else if ( strncasecmp( value, "clean", 1024) == 0)
-                               dv_unit_set_eof_action( unit, dv_player_clean_loop );
-                       else
-                               return RESPONSE_OUT_OF_RANGE;
-               }
-               else if ( strncasecmp( key, "points", 1024) == 0 )
-               {
-                       if ( strncasecmp( value, "use", 1024) == 0)
-                               dv_unit_set_mode( unit, dv_clip_mode_restricted );
-                       else if ( strncasecmp( value, "ignore", 1024) == 0)
-                               dv_unit_set_mode( unit, dv_clip_mode_unrestricted );
-                       else
-                               return RESPONSE_OUT_OF_RANGE;
-               }
-               else if ( strncasecmp( key, "syt_offset", 1024) == 0 )
-               {
-                       dv_unit_set_syt_offset( unit, atoi( value ) );
-               }
-               else if ( strncasecmp( key, "cip_n", 1024) == 0 )
-               {
-                       dv_unit_set_cip_n( unit, atoi( value ) );
-               }
-               else if ( strncasecmp( key, "cip_d", 1024) == 0 )
-               {
-                       dv_unit_set_cip_d( unit, atoi( value ) );
-               }
-               else if ( strncasecmp( key, "size", 1024) == 0 )
-               {
-                       dv_unit_set_buffer_size( unit, atoi( value ) );
-               }
-               else if ( strncasecmp( key, "n_frames", 1024) == 0 )
-               {
-                       dv_unit_set_n_frames( unit, atoi( value ) );
-               }               
-               else if ( strncasecmp( key, "n_fill", 1024) == 0 )
-               {
-                       dv_unit_set_n_fill( unit, atoi( value ) );
-               }               
-               else
-                       return RESPONSE_OUT_OF_RANGE;
-       }
-       */
+               miracle_unit_set( unit, name_value );
        return RESPONSE_SUCCESS;
 }
 
 int miracle_get_unit_property( command_argument cmd_arg )
 {
-       /*
-       dv_unit unit = miracle_get_unit(cmd_arg->unit);
-       
+       miracle_unit unit = miracle_get_unit(cmd_arg->unit);
+       char *name = (char*) cmd_arg->argument;
+       char *value = miracle_unit_get( unit, name );
        if (unit == NULL)
                return RESPONSE_INVALID_UNIT;
-       else
-       {
-               char *key = (char*) cmd_arg->argument;
-
-               if ( strncasecmp( key, "eof", 1024) == 0 )
-               {
-                       switch ( dv_unit_get_eof_action( unit ) )
-                       {
-                               case dv_player_pause:
-                                       dv_response_write( cmd_arg->response, "pause", strlen("pause") );
-                                       break;
-                               case dv_player_loop:
-                                       dv_response_write( cmd_arg->response, "loop", strlen("loop") );
-                                       break;
-                               case dv_player_terminate:
-                                       dv_response_write( cmd_arg->response, "stop", strlen("stop") );
-                                       break;
-                               case dv_player_clean_loop:
-                                       dv_response_write( cmd_arg->response, "clean", strlen("clean") );
-                                       break;
-                       }
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "points", 1024) == 0 )
-               {
-                       if ( dv_unit_get_mode( unit ) == dv_clip_mode_restricted )
-                               dv_response_write( cmd_arg->response, "use", strlen("use") );
-                       else
-                               dv_response_write( cmd_arg->response, "ignore", strlen("ignore") );
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "syt_offset", 1024) == 0 )
-               {
-                       dv_response_printf( cmd_arg->response, 1024, "%d\n",
-                               dv_unit_get_syt_offset( unit ) );
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "cip_n", 1024) == 0 )
-               {
-                       dv_response_printf( cmd_arg->response, 1024, "%d\n",
-                               dv_unit_get_cip_n( unit ) );
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "cip_d", 1024) == 0 )
-               {
-                       dv_response_printf( cmd_arg->response, 1024, "%d\n",
-                               dv_unit_get_cip_d( unit ) );
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "size", 1024) == 0 )
-               {
-                       dv_response_printf( cmd_arg->response, 1024, "%d\n",
-                               dv_unit_get_buffer_size( unit ) );
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "n_frames", 1024) == 0 )
-               {
-                       dv_response_printf( cmd_arg->response, 1024, "%d\n",
-                               dv_unit_get_n_frames( unit ) );
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "n_fill", 1024) == 0 )
-               {
-                       dv_response_printf( cmd_arg->response, 1024, "%d\n",
-                               dv_unit_get_n_fill( unit ) );
-                       return RESPONSE_SUCCESS_1;
-               }
-               else if ( strncasecmp( key, "all", 1024 ) == 0 )
-               {
-                       switch ( dv_unit_get_eof_action( unit ) )
-                       {
-                               case dv_player_pause:
-                                       dv_response_write( cmd_arg->response, "eof=pause\n", strlen("pause") );
-                                       break;
-                               case dv_player_loop:
-                                       dv_response_write( cmd_arg->response, "eof=loop\n", strlen("loop") );
-                                       break;
-                               case dv_player_terminate:
-                                       dv_response_write( cmd_arg->response, "eof=stop\n", strlen("stop") );
-                                       break;
-                               case dv_player_clean_loop:
-                                       dv_response_write( cmd_arg->response, "eof=clean\n", strlen("clean") );
-                                       break;
-                       }
-                       if ( dv_unit_get_mode( unit ) == dv_clip_mode_restricted )
-                               dv_response_write( cmd_arg->response, "points=use\n", strlen("use") );
-                       else
-                               dv_response_write( cmd_arg->response, "points=ignore\n", strlen("ignore") );
-                       dv_response_printf( cmd_arg->response, 1024, "syt_offset=%d\n", dv_unit_get_syt_offset( unit ) );
-                       dv_response_printf( cmd_arg->response, 1024, "cip_n=%d\n", dv_unit_get_cip_n( unit ) );
-                       dv_response_printf( cmd_arg->response, 1024, "cip_d=%d\n", dv_unit_get_cip_d( unit ) );
-                       dv_response_printf( cmd_arg->response, 1024, "size=%d\n", dv_unit_get_buffer_size( unit ) );
-                       dv_response_printf( cmd_arg->response, 1024, "n_frames=%d\n", dv_unit_get_n_frames( unit ) );
-                       dv_response_printf( cmd_arg->response, 1024, "n_fill=%d\n", dv_unit_get_n_fill( unit ) );
-               }
-       }
-       */
+       else if ( value != NULL )
+               valerie_response_printf( cmd_arg->response, 1024, "%s\n", value );
        return RESPONSE_SUCCESS;
 }