Valerie API Documentation 

Copyright (C) 2004 Ushodaya Enterprised Limited 
Author: Charles Yates <charles.yates@pandora.be> 
Last Revision: 2004-03-20


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/rugen
	    
	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
