[gst-devel] LADMEA Prototype

Richard W.E. Furse richard at muse.demon.co.uk
Thu Aug 9 19:28:41 CEST 2001


Hi folks, as some of you will know I've been looking into a more flexible
way to construct an inter-application data streaming approach, primarily for
audio but with support for general multimedia. At last (apologies for the
delay) I have a prototype API in the flavour of LADSPA (see
http://www.ladspa.org) which I include here. Apologies for the large
posting. This prototype is somewhat rough and I'm expecting a lot of
modification.

In terms of compatibility (and as sources of ideas) I've been looking
particularly at LADSPA, Csound, MN, ATM, GStreamer, OSS, ALSA, LAAGA and
aRts. There is a deliberate separation and abstraction of both the 'client'
and 'exchange' sides of the API ('codecs' are supported too as specialised
clients). I should not be too hard to build exchange links using GStreamer,
LAAGA, ATM and aRts. It should be easy to write new clients or wrap existing
software such as Csound, Ardour, OSS and ALSA. A LADSPA client wrapper
should be trivial. The API (with suitable exchange design) should handle
real time and offline processing. All of this should be possible without
either the client or exchange knowing what they are connected to. Hopefully
it should be possible for the exchange to be in-process, in an external
process or on a remote machine and exchanges do not need to know what data
they are handling (although this can help).

Why should a good program with plugins (e.g. GStreamer) be interested in an
API like this? Hopefully the presence of a (relatively) simple API such as
this will allow two big steps forward: firstly, it should make it possible
for existing external applications such as GStreamer, Csound and Ardour to
work together. Secondly, it allows clients (or codecs) to be written once
and be used in/by many different applications in the same way that LADSPA
plugins are. The target license would allow commercial applications to use
the API too, but for the moment it will start under LGPL.

This API concerns itself with the interface between the exchange and client.
It does not assume a particular way in which the exchange will connect,
publish, merge or share channels. Synchronisation is kept simple and no
support for transport is provided (it is assumed that transport instructions
such as rewind be sent as data like any other). There are extensible calls
to request the streaming characteristics of channels and the latency
requirements of clients and data specifications are provided in an
extensible way that does not require any understanding on the part of the
exchange. Data types and descriptor conventions are given unique identifiers
to keep data types compatible.

I think the only point where the API strays from being strictly generic is
the insistence of use of a single timestamping scheme (managed by the
exchange) when sending data. I've had a lot of trouble persuading myself
that this is necessary but have come down in support of it. This doesn't
require the client or exchange to use this convention internally, just at
its interfaces, and it is hoped this won't be too hard to do.

I enclose the API itself and two files containing the obligatory streaming
characteristic descriptor convention and latency requirement descriptor
conventions that all clients and exchanges should understand.

The name of the API is reasonably flexible - there's been lots of debate
about potential names for this sort of technology for LAAGA (which is
great). At this stage I'll observe that ALBA is already in use and JACK is
susceptible to unfortunate jokes.

I hope this is all of use - I've spent rather more time on it than I'd hoped
and I've cut off development to give me something to release. Which is
probably very broken in some way!

Please let me know what you think - like LADSPA, this API will only be any
use if people are prepared to use it.

--Richard

/* ladmea.h

   Linux Audio Developer's Multimedia Exchange API Version 1.0[LGPL].
   Copyright (C) 2001 Richard W.E. Furse.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public License
   as published by the Free Software Foundation; either version 2.1 of
   the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
   USA. */

#ifndef LADMEA_INCLUDED
#define LADMEA_INCLUDED

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************
**/

/* Overview:

   The Linux Audio Developer's Multimedia Exchange API is a technology
   designed to make it simple for audio and multimedia applications to
   exchange data. This API does not provide a mechanism for this
   exchange to happen, but ensures the information is in place to
   allow exchange to happen using whatever is available.

   This API defines a contract for behaviour of `clients' such as MIDI
   players, audio cards, sequencers, video players, computer games
   etc. This contract is designed in a way to avoid restricting what
   the client can do. Clients read and write data from and to
   `channels'.

   This API defines a contract for behaviour of `exchanges'. Exchanges
   are mechanisms that allow the exchange of multimedia
   information. Exchanges have different flavours. For efficiency,
   some may be programs that load clients into their memory space and
   perform all processing within a single thread. Some may use IPC
   messaging, encryption, sockets, ATM and unknown technologies to
   exchange information. This API does not proscribe how data will be
   routed, combined or interpreted. Exchanges do not need to
   understand the data types that they route although they can take
   advantage of such understanding when it is present. Although the
   API does not require the exchange to understand data, `streaming
   characteristics' and `latency requirements' are available in case
   the exchange needs to establish quality of service conventions with
   its underlying technology. These may be represented using different
   conventions identified by `convention identifiers'
   (LADMEA_ConventionIDs) to make their use consistent between
   applications. At the very least, the default stream characteristic
   convention and latency requirement convention must be supported by
   all clients and exchanges.

   This API defines a contract for behaviour of `codecs' and `codec
   providers'. Codecs are special clients that are used to perform
   natural conversions from one type of data to another. A typical
   example of this is an MP3 encoder. `Codec providers' provide codec
   clients for specific tasks.

   Shared-library loading conventions are provided for clients,
   exchanges and codec providers. A program does not need to load any
   of these elements, either because it provides such entities itself
   (the program may contain exchanges or a client and/or a codec
   provider in its own right) or does not require them.

   The flexibility implicit in a framework like this is useful only if
   applications agree on the data types that are to be
   communicated. `Data types' (e.g. `PCM audio') are given centrally
   registered unique LADMEA data type identifiers (LADMEA_DataTypeIDs)
   to make their use consistent between applications. `Data
   specifications' provide more specific information (e.g. channel
   counts, sample rates, block sizes etc.).

   Routines are also provided that allow the exchange to translate
   data to and from `network ordering' for transmission to deal with
   big/little endian issues when data is communicated between machines
   using differing conventions.

   The API does not proscribe a particular way to perform general
   synchronisation, clocking and transport control. Such requirements
   can be handled implicitly or explicitly (e.g. SMPTE) through
   ordinary channels. This API does not prohibit a client from using
   more than one exchange simultaneously and does not prohibit a
   program from registering a single entity more than once within a
   single exchange as separate clients. However, such behaviour is not
   recommended.

   Although the API does not proscribe a general synchronisation
   approach, all data exchanged is timestamped and clients and
   exchanges guarantee to send data in timestamp order. All timestamps
   are considered `logical' and may provided by a real time clock,
   derived from a real time clock or relative to some abstract clock
   tick during non real time processing. The client is not informed of
   this, instead controlling it through latency requirements. Clients
   should output data timestamped consistently with its input data
   (for instance, a reverb unit should output a frame of audio data
   with the same timestamp as its input to indicate chronological
   correspondence). When there is no input to timestamp against,
   timestamps can be requested from the exchange although clients
   should be careful to make sure sequences of timestamps are
   meaningful.

   The API allows some negotiation between the exchange and the client
   or codec provider over what kind of data is to be exchanged. The
   negotiation process and final decision are arbitrated by the
   exchange, but obviously the client cannot be forced to perform a
   task that it is not capable of. */

/***************************************************************************
**/

/* Data types are specified by unique identifier. Programmers may
   reserve data type IDs from a central body to avoid clashes. IDs are
   below 0x1000000. */
typedef unsigned long LADMEA_DataTypeID;

/***************************************************************************
**/

/* Conventions (for streaming convention or latency requirement
   descriptors) are specified by unique identifier. Programmers may
   reserve convention IDs from a central body to avoid clashes. IDs
   are below 0x1000000. */
typedef unsigned long LADMEA_ConventionID;

/***************************************************************************
**/

/* Channels are identified by ID. The channel ID is unique and
   meaningful only for a particular combination of exchange and
   client. This is signed to allow error codes to be returned by
   functions that otherwise return channel IDs. */
typedef long LADMEA_ChannelID;

/***************************************************************************
**/

/* Timestamps are currently defined to use the timeval structure. On
   Linux this provides microsecond resolution which is probably
   adequate for most purposes. All timestamps are considered `logical'
   and may provided by a real time clock, derived from a real time
   clock or relative to some abstract clock tick during non real time
   processing. Because of this, timestamps should never be filled in
   from the real time clock. On the unusual occasions on which an
   absolute clock reference is required (e.g. startup of a software
   synth) the exchange function getCurrentTimestamp() should be
   called. */
typedef timeval LADMEA_Timestamp;

/***************************************************************************
**/

/* Results:

   A number of different result codes are returned by functions. The
   valid result codes are indicated with each function. Note that some
   of these result codes are sometimes returned by functions that
   otherwise return meaningful non-negative data. */

typedef long LADMEA_Result;

/* For many functions, this result code indicates a call succeeded. */
#define LADMEA_SUCCESS                  0

/* This result code indicates that data passed to a function was not
   formed correctly. */
#define LADMEA_ERROR_DATA               -1

/* This result code indicates that an object is not registered
   correctly or is already registered in error. */
#define LADMEA_ERROR_BAD_CLIENT         -2

/* This result code indicates that an object is not registered
   correctly or is already registered in error. */
#define LADMEA_ERROR_BAD_CODEC_PROVIDER -3

/* This result indicates that there were insufficient resources to
   satisfy a request. Typical examples are memory, file handles or
   spaces for clients in an exchange. */
#define LADMEA_ERROR_RESOURCES          -4

/* This result indicates that it wasn't possible to find a channel
   with adequate characteristics to carry the data. */
#define LADMEA_ERROR_SERVICE_QUALITY    -5

/* This result indicates that a client was not allowed to do
   something. This is an exchange-specific result. For instance, it
   might mean that a channel is read only or private. */
#define LADMEA_ERROR_PERMISSION         -6

/* This result indicates that an attempt was made to create an entity
   that already existed. */
#define LADMEA_ERROR_EXISTS             -7

/* This result indicates that an attempt was made to access an entity
   name that did not exist. */
#define LADMEA_ERROR_NOT_FOUND          -8

/* This result indicates that a client attempted to access a channel
   that was not valid. */
#define LADMEA_ERROR_BAD_CHANNEL        -9

/* This result indicates that a feature is not supported. See also the
   LADMEA_SupportLevel enumeration. */
#define LADMEA_ERROR_SUPPORT            -10

/* This indicates that the operation could not complete because the
   client was already active. */
#define LADMEA_ERROR_ALREADY_ACTIVE     -11

/* This indicates that the data was delivered to client or exchange
   too late for whatever processing was required. This may or may not
   be fatal. */
#define LADMEA_ERROR_TOO_LATE           -12

/***************************************************************************
**/

/* Support Levels:

   Various levels of support may be indicated for a particular data
   specification. These are identified by LADMEA_SupportLevel. This is
   a number constructed by ORing the following flags together. The
   default value (0) indicates full support. */

typedef long LADMEA_SupportLevel;

/* This indicates that support is available but may not function
   correctly as it is experimental and/or development. */
#define LADMEA_SUPPORT_EXPERIMENTAL     0x1

/* This indicates that a particular feature will cause some difficulty
   (for example, a client may be able to support MP3 encoded inputs
   but prefer not to due to an inefficient algorithm). In itself this
   flag does not indicate that support is unavailable. */
#define LADMEA_SUPPORT_COSTLY           0x2

/* This indicates that support is not at the requested quality of
   service level and streaming problems are possible in the future. */
#define LADMEA_SUPPORT_STREAM_RISK      0x4

/* This indicates that there was a problem with compatibility with
   other streams attached to the client. */
#define LADMEA_SUPPORT_BAD_COMBINATION  0x8

/* This indicates that no support is available. Other flags are now
   reinterpreted to indicate why (and some other flags disappear if
   they were not in themselves a source of failure). */
#define LADMEA_SUPPORT_FAIL             0x10

/***************************************************************************
**/

/* Data Specification:

   A data specification is a structure describing a data stream. An
   example is `5 channels of IEEE float PCM audio data sampled at
   96kHz transmitted in blocks of 1024 frames.' An `additional data'
   structure is used to contain data that is specific to the data
   type. In the example preceding, the actual data type would be
   LADMEA_DTID_PCM_FLOAT_AUDIO and the rest of the detail (channel
   count, sample rate and frame size) are provided separately.

   Note that an exchange is never required to understand the data it
   passes (although knowledge is unlikely to hurt). However, it may
   ask clients to provide information about its stream characteristics
   (see below).

   The functions provided here must be thread-safe and may not call
   the exchange or client. */

typedef struct t_LADMEA_DataSpecification {

  /* The size of the specification structure in bytes. */
  unsigned long StructureSize;

  /* Additional data required by the data type. This is NULL if and
     only if AdditionalDataSize is zero. */
  void * AdditionalData;

  /* The size of the additional information data pointed to by
     AdditionalData. */
  unsigned long AdditionalDataSize;

  /* Data types are specified by unique identifier. Programmers may
     reserve data type IDs from a central body to avoid clashes. IDs
     are below 0x1000000. */
  LADMEA_DataTypeID DataTypeID;

  /* Take the additional data of a data specification and convert it
     into network ordering. A NULL placed here instead of a function
     if the data specification does not require conversion. This
     function may return LADMEA_SUCCESS, LADMEA_ERROR_RESOURCES or
     LADMEA_ERROR_DATA if the specification was not valid. */
  LADMEA_Result (*convertDataSpecificationDataToNetworkOrdering)
  (const void                               * Data,
   const unsigned long                        Size);

  /* Take the additional data of a data specification and convert it
     from network ordering to local ordering. A NULL may be placed
     here instead of a function if the data specification does not
     require conversion. This function may return LADMEA_SUCCESS,
     LADMEA_ERROR_RESOURCES or LADMEA_ERROR_DATA if the specification
     was not valid. */
  LADMEA_Result (*convertDataSpecificationDataFromNetworkOrdering)
  (const void                               * Data,
   const unsigned long                        Size);

  /* Take a data packet and convert it into network ordering. This
     should change the data for communication to a remote computer or
     other program using a different word ordering. A NULL may be
     placed here instead of a function if the data type does not
     require conversion. This function may return LADMEA_SUCCESS,
     LADMEA_ERROR_RESOURCES or LADMEA_ERROR_DATA if the specification
     was not valid. */
  LADMEA_Result (*convertPacketDataToNetworkOrdering)
  (const void                               * Data,
   const unsigned long                        Size);

  /* Take a data specification and convert it from a network ordering
     to local ordering. This should change the data for communication
     to a remote computer or other program using a different word
     ordering. A NULL may be placed here instead of a function if the
     data type does not require conversion. This function may return
     LADMEA_SUCCESS, LADMEA_ERROR_RESOURCES or LADMEA_ERROR_DATA if
     the specification was not valid. */
  LADMEA_Result (*convertPacketDataFromNetworkOrdering)
  (const void                               * Data,
   const unsigned long                        Size);

} LADMEA_DataSpecification;

/***************************************************************************
**/

/* Catalogue Entry Types:

   When items are catalogued in channel directories, they can be
   listed as directories in their own right or as channels. */

typedef enum {

  /* The catalogue entry is a channel. */
  LADMEA_CATALOGUE_ENTRY_CHANNEL   = 1,

  /* The catalogue entry is a subdirectory. */
  LADMEA_CATALOGUE_ENTRY_DIRECTORY = 2

} LADMEA_CatalogueEntryType;

/***************************************************************************
**/

/* Direction:

   Indicates input or output. */

typedef enum {

  /* Into the client. */
  LADMEA_DIRECTION_INPUT  = 1,

  /* Out of the client. */
  LADMEA_DIRECTION_OUTPUT = 2

} LADMEA_Direction;

/***************************************************************************
**/

/* An Exchange:

   This structure is used to describe an exchange. It provides a
   number of functions to interact with it. The exchange communicates
   back using returned data and callbacks. The structure must remain
   static.

   Exchanges must support simultaneous calls as multiple or
   multithreaded clients or codec providers may wish to call functions
   simultaneously. Also, the sendToExchange() function must return
   before any data is passed on to other clients. This may present
   difficulties for some exchanges but is a practical way to avoid
   infinite looping and stack overflow.

   The exchange guarantees not to call the client back during any of
   the functions provided below except activateClient() (see the
   function). However, because both client and exchange may be
   multithreaded it is possible that both initiate overlapping
   calls. In this case it is the responsibility of the exchange to
   perform locking to guarantee that no code is run
   simultaneously. This should be done in a way that disrupts the
   client as little as possible. In other words, an exchange should
   block a call from the client while it is running its calls to the
   client and must block or stop its calls to the client when the
   client is already calling it. */

typedef struct t_LADMEA_Exchange {

  /* The full name of the exchange. This is a human-readable name for
     use in user interfaces etc. */
  const char * Name;

  /* A brief textual description of the mechanism used by the
     exchange. This is a non-unique human-readable name for use in
     user interfaces etc. This should suggest the underlying
     technology (e.g. IPC, sockets, direct link to a particular
     application). */
  const char * MechanismDescription;

  /* The name of the creator of the exchange. This is a non-unique
     human-readable name for use in user interfaces etc. */
  const char * Maker;

  /* This member points to the null-terminated string indicating any
     copyright applying to the exchange. If no Copyright applies the
     string "None" should be used. */
  const char * Copyright;

  /* Register a client with the exchange. The exchange is entitled to
     call methods on the client at any time until the
     unregisterClient() call returns. This method may not be called
     for a client that is currently registered. This function may
     return LADMEA_SUCCESS, LADMEA_ERROR_RESOURCES or
     LADMEA_ERROR_BAD_CLIENT if the client is already registered.  */
  LADMEA_Result (*registerClient)
  (struct t_LADMEA_Client                   * Client);

  /* Takes a client that was previously registered and removes it from
     the exchange's register. It is guaranteed that once this function
     returns that the client will not receive callbacks from the
     exchange. Note that the exchange may call the client back during
     this call. This function may return LADMEA_SUCCESS,
     LADMEA_ERROR_RESOURCES or LADMEA_ERROR_BAD_CLIENT. */
  LADMEA_Result (*unregisterClient)
  (struct t_LADMEA_Client                   * Client);

  /* Register a codec provider with the exchange. The exchange is
     entitled to call methods on the codec provider at any time until
     the unregisterCodecProvider() call returns. This method may not
     be called for a codec provider that is currently registered. This
     function may return LADMEA_SUCCESS, LADMEA_ERROR_RESOURCES or
     LADMEA_ERROR_BAD_CODEC_PROVIDER if the provider is already
     registered.  */
  LADMEA_Result (*registerCodecProvider)
  (struct t_LADMEA_CodecProvider            * CodecProvider);

  /* Takes a codec provider that was previously registered and removes
     it from the exchange's register. It is guaranteed that once this
     function returns the codec provider will not receive callbacks
     from the exchange. Note that the exchange may call the codec
     provider back during this call. This function may return
     LADMEA_SUCCESS, LADMEA_ERROR_RESOURCES or
     LADMEA_ERROR_BAD_CODEC_PROVIDER if the provider is not
     registered.  */
  LADMEA_Result (*unregisterCodecProvider)
  (struct t_LADMEA_CodecProvider            * CodecProvider);

  /* Attempt to create a channel with which we may interact. By
     default channels carry no data. Note that this channel handle
     returned is unique only for this exchange and client. For
     instance, an application providing more than one client may not
     interchange LADMEA_ChannelIDs. This function may return a channel
     ID (zero or above), LADMEA_ERROR_PERMISSION, LADMEA_ERROR_EXISTS
     or LADMEA_ERROR_RESOURCES. */
  LADMEA_ChannelID (*createChannel)
  (struct t_LADMEA_Client                   * Client,
   const char                               * ChannelLabel);

  /* Find a channel that already exists. Note that this channel handle
     returned is unique only for this exchange and client. For
     instance, an application providing more than one client may not
     interchange LADMEA_ChannelIDs. This function may return a channel
     ID, LADMEA_ERROR_PERMISSION, LADMEA_ERROR_RESOURCES or
     LADMEA_ERROR_NOT_FOUND. */
  LADMEA_ChannelID (*findChannel)
  (struct t_LADMEA_Client                   * Client,
   const char                               * ChannelLabel);

  /* Delete a channel. This function may return LADMEA_SUCCESS,
     LADMEA_ERROR_PERMISSION, LADMEA_ERROR_BAD_CHANNEL or
     LADMEA_ERROR_RESOURCES. */
  LADMEA_Result (*deleteChannel)
  (const LADMEA_ChannelID                     Channel);

  /* Get a catalogue of a `channel directory', a collection of
     channels and other directories. The notation used will depend on
     the exchange but it is anticipated that most exchanges will use a
     catalogue structure resembling a forward-slash-delimited file
     system. Note that it is not possible to assume that all root
     directories are available. For instance, a socket-based exchange
     might use a notation or form /<machine>/<port>/<conventional
     directory>. In this case, it may not be practical for the
     exchange to perform catalogue listings for either of the top two
     directories (in this case LADMEA_ERROR_SUPPORT would be
     returned). The ChannelDirectory identifies the directory to
     catalogue. The calling program must provide space into which this
     function will write null-terminated names (into Names) and entity
     types (LADMEA_CatalogueEntryType, directory or channel). The
     MaximumEntryNameSize indicates how much space is allocated to
     store each name (including the null-terminating space). Names and
     lists should be truncated when there is insufficient space. This
     method may return LADMEA_ERROR_SUCCESS, LADMEA_ERROR_SUPPORT,
     LADMEA_ERROR_RESOURCES, LADMEA_ERROR_PERMISSION,
     LADMEA_ERROR_NOT_FOUND. */
  LADMEA_Result (*getChannelCatalogue)
  (struct t_LADMEA_Client                   * Client,
   const char                               * ChannelDirectoryLabel,
   char                                    ** Names,
   LADMEA_CatalogueEntryType                * Types,
   const unsigned long                        MaximumEntryCount,
   const unsigned long                        MaximumEntryNameSize);

  /* Connect part of our application to a particular channel. This can
     only be done for an inactive client. The client uses the channel
     as an input or an output depending on the Direction. Once this
     function returns it is guaranteed that the client will be
     informed of any changes to the relevant channel specification. It
     is good practice to check the specification of the channel
     immediately after connecting to it to ensure the configuration is
     as expected. This function may return LADMEA_SUCCESS,
     LADMEA_ERROR_PERMISSION, LADMEA_ERROR_BAD_CLIENT,
     LADMEA_ERROR_BAD_CHANNEL, LADMEA_ERROR_RESOURCES or
     LADMEA_ERROR_ALREADY_ACTIVE. */
  LADMEA_Result (*connectChannel)
  (struct t_LADMEA_Client                   * Client,
   const LADMEA_ChannelID                     Channel,
   const LADMEA_Direction                     Direction);

  /* Disconnect part of our application from a particular channel that
     it is currently connected to. This can only be done for an
     inactive client. This function may return LADMEA_SUCCESS,
     LADMEA_ERROR_PERMISSION, LADMEA_ERROR_BAD_CLIENT,
     LADMEA_ERROR_BAD_CHANNEL, LADMEA_ERROR_RESOURCES or
     LADMEA_ERROR_ALREADY_ACTIVE. */
  LADMEA_Result (*disconnectChannel)
  (struct t_LADMEA_Client                   * Client,
   const LADMEA_ChannelID                     Channel);

  /* This call requests access to the current data specification of a
     channel. The result will remain statically (and unchanging) in
     memory until the function is called again for the same
     client. The data will not be refreshed even if the actual
     specification changes or if requests are made by other
     clients. Data is passed back by reference through
     DataSpecification. This function may return LADMEA_SUCCESS,
     LADMEA_ERROR_BAD_CLIENT, LADMEA_ERROR_BAD_CHANNEL or
     LADMEA_ERROR_RESOURCES. */
  LADMEA_Result (*getChannelDataSpecification)
  (const struct t_LADMEA_Client *             Client,
   const LADMEA_ChannelID                     Channel,
   t_LADMEA_DataSpecification              ** DataSpecification);

  /* Propose a data specification for a channel. This function can be
     called a number of times to provide a number of options to the
     exchange. The client must be connected to the channel
     concerned. The actual transition does not occur until the
     exchange signals it to the client with the
     notifyChannelDataSpecification() function, which may happen at
     any time but often happens during activateClient(). This can only
     be done for an active client which is connected to the
     channel. proposeChannelDataSpecification() may return
     LADMEA_SUCCESS (this only indicates that the request has been
     understood, not agreed), LADMEA_ERROR_PERMISSION,
     LADMEA_ERROR_BAD_CLIENT (if the client is unknown),
     LADMEA_ERROR_BAD_CHANNEL, LADMEA_ERROR_DATA (bad data
     specification), LADMEA_ERROR_RESOURCES or
     LADMEA_ERROR_ALREADY_ACTIVE. */
  LADMEA_Result (*proposeChannelDataSpecification)
  (const struct t_LADMEA_Client             * Client,
   const LADMEA_ChannelID                     Channel,
   const struct t_LADMEA_DataSpecification  * DataSpecification);

  /* Find the current logical time and write it to the Timestamp
     structure provided. This function may return LADMEA_SUCCESS or
     LADMEA_ERROR_RESOURCES. */
  LADMEA_Result (*getCurrentTimestamp)(LADMEA_Timestamp * Timestamp);

  /* This call requests that the exchange make the client active. The
     exchange may, and is likely to, make a number of calls back to
     the client and possibly to other clients to attempt to agree
     suitable data specifications for all channels involved. If this
     function returns LADMEA_SUCCESS the client is active and should
     behave accordingly, assuming that something is attached to each
     of its channels. The exchange may delay the return of this call
     for synchronisation purposes. The exchange guarantees that it
     will not return within delivery of the data for a particular
     timestamp (thus ensuring that the client receives all the data
     corresponding to the first timestamp it encounters). This
     function may return LADMEA_SUCCESS, LADMEA_ERROR_BAD_CLIENT,
     LADMEA_ERROR_SUPPORT or LADMEA_ERROR_RESOURCES. */
  LADMEA_Result (*activateClient)
  (const struct t_LADMEA_Client *             Client);

  /* This call requests that the exchange make the client
     inactive. The exchange may delay the return of this call for
     synchronisation purposes. Once this function returns it is
     guaranteed that no further data will be sent to the client. This
     function may return LADMEA_SUCCESS, LADMEA_ERROR_BAD_CLIENT or
     LADMEA_ERROR_RESOURCES. */
  LADMEA_Result (*deactivateClient)
  (const struct t_LADMEA_Client *             Client);

  /* Write a packet to an output. This function may block. Packets
     must be sent in timestamp order. This function may return
     LADMEA_SUCCESS, LADMEA_ERROR_TOO_LATE, LADMEA_ERROR_BAD_CLIENT
     (if the client is unknown), LADMEA_ERROR_BAD_CHANNEL (indicating
     only that the client is not connected), LADMEA_ERROR_DATA (bad
     data) or LADMEA_ERROR_RESOURCES. */
  LADMEA_Result (*sendToExchange)
  (const struct t_LADMEA_Client             * Client,
   const LADMEA_ChannelID                     Output,
   const LADMEA_Timestamp                     Timestamp,
   const void                               * Data,
   const unsigned long                        Size);

} LADMEA_Exchange;

/***************************************************************************
**/

/* Client Properties:

   Some properties of the client are identified by
   LADMEA_ClientProperties. This is a number constructed by ORing the
   following flags together. The default value (0) indicates full
   support. */

typedef unsigned long LADMEA_ClientProperties;

/* This indicates that the client runs in real time. Because of this the
   exchange must wait for real time to move forward before assuming
   the client does not wish to produce output. */
#define LADMEA_SUPPORT_REAL_TIME 0x1

/***************************************************************************
**/

/* A Client:

   Any client application that wishes to use a LADMEA exchange must
   provide one of these structures which can be used by the exchange
   to communicate back. The structure must remain static between the
   registerClient() and unregisterClient() calls. Note that the
   exchange activateClient() call is likely to result in these
   functions being called. Because of this, functions here should be
   very careful in their assumptions about what code is running, locks
   active etc.

   The client is guaranteed that an exchange will only call one
   function at a time. This makes it possible for a client to be
   written without explicit thread handling, although such a
   single-threaded client must hand control over its flow to the
   functions below. In exchange, the client guarantees not to call the
   exchange during any of these calls except for sendToClient(), in
   which sendToExchange() may be used. */
typedef struct t_LADMEA_Client {

  /* The full name of the client. This is a human-readable name for
     use in user interfaces etc. */
  const char * Name;

  /* The name of the creator of the exchange. This is a non-unique
     human-readable name for use in user interfaces etc. */
  const char * Maker;

  /* This member points to the null-terminated string indicating any
     copyright applying to the exchange. If no Copyright applies the
     string "None" should be used. */
  const char * Copyright;

  /* This member indicates special properties of the client. */
  LADMEA_ClientProperties Properties;

  /* Find out if the client could support a change in the
     specification of an existing channel. The client may not call the
     exchange during this so the client may wish to store data sent
     previously by notifyChannelDataSpecification() for use in this
     function. The exchange may call this function for any channel the
     client is connected to and for any data specification
     whatsoever. This client does not have to support the
     specification even if it proposed it and may take into account
     the data specification of other channels (for which notification
     has been sent and the data type ID was not
     LADMEA_DTID_UNDEFINED). This function returns a support level,
     LADMEA_ERROR_DATA (bad data specification),
     LADMEA_ERROR_BAD_CLIENT, LADMEA_ERROR_BAD_CHANNEL or
     LADMEA_ERROR_RESOURCES. */
  LADMEA_SupportLevel (*queryChannelDataSpecification)
  (const struct t_LADMEA_Client             * Client,
   const LADMEA_ChannelID                     Channel,
   const struct t_LADMEA_DataSpecification  * DataSpecification,
   const struct t_LADMEA_Exchange           * Exchange);

  /* This call allows the exchange to request the streaming
     characteristics of a channel to which a client is connected if a
     particular data specification were used. A number of different
     representations of streaming characteristic descriptor types are
     supported and are identified by LADMEA convention identifiers
     (LADMEA_ConventionIDs). Streaming characteristic descriptor
     conventions can vary from simple expressions of average flows to
     covariance expressions, moments, bandwidth limits, jitter
     expectations etc. If a client does not know how to represent
     streaming characteristics using a particular convention then it
     simply returns LADMEA_ERROR_SUPPORT. For compatibility, it is
     strongly recommended that all exchanges and clients at the very
     least support LADMEA_SCID_BASIC (with a structure defined in the
     ladmeasc_basic.h file). This function may return LADMEA_SUCCESS,
     LADMEA_BAD_CLIENT, LADMEA_BAD_CHANNEL, LADMEA_ERROR_DATA (if the
     Size is not valid), LADMEA_ERROR_SUPPORT or
     LADMEA_ERROR_RESOURCES. */
  LADMEA_Result (*getStreamingCharacteristics)
  (const struct t_LADMEA_Client             * Client,
   const LADMEA_ChannelID                     Channel,
   const struct t_LADMEA_DataSpecification  * DataSpecification,
   const LADMEA_ConventionID                  ConventionID,
   void                                     * Data,
   unsigned long                              Size);

  /* This call allows the exchange to request the latency requirement
     of an input channel to which a client is connected if a
     particular data specification were used. It assumed for the
     purposes of this call that the client is running real time,
     whether or not the client needs to. A number of different
     representations of latency requirement descriptor types are
     supported and are identified by LADMEA convention identifiers
     (LADMEA_ConventionIDs). Latency requirement descriptor
     conventions can vary from simple constraints on latency and
     jitter to complex rule-based approaches. If a client does not
     know how to represent its latency requirement for a channel using
     a particular convention then it simply returns
     LADMEA_ERROR_SUPPORT. For compatibility, it is strongly
     recommended that all exchanges and clients at the very least
     support LADMEA_LRID_BASIC (with a structure defined in the
     ladmealr_basic.h file). This function may return LADMEA_SUCCESS,
     LADMEA_BAD_CLIENT, LADMEA_BAD_CHANNEL, LADMEA_ERROR_DATA (if the
     Size is not valid), LADMEA_ERROR_SUPPORT or
     LADMEA_ERROR_RESOURCES. */
  LADMEA_Result (*getInputLatencyRequirement)
  (const struct t_LADMEA_Client             * Client,
   const LADMEA_ChannelID                     Channel,
   const struct t_LADMEA_DataSpecification  * DataSpecification,
   const LADMEA_ConventionID                  ConventionID,
   void                                     * Data,
   unsigned long                              Size);

  /* Tell the client of a change in the data specification of a
     channel. This call is only valid for an inactive client. The
     client has no right to negotiate this call but may indicate
     support failure using LADMEA_ERROR_SUPPORT. Valid results are
     LADMEA_ERROR_DATA (bad data specification),
     LADMEA_ERROR_BAD_CLIENT, LADMEA_ERROR_BAD_CHANNEL,
     LADMEA_ERROR_SUPPORT or LADMEA_ERROR_RESOURCES.*/
  LADMEA_Result (*notifyChannelDataSpecification)
  (const struct t_LADMEA_Client             * Client,
   const LADMEA_ChannelID                     Channel,
   const struct t_LADMEA_DataSpecification  * DataSpecification,
   const struct t_LADMEA_Exchange           * Exchange);

  /* This call requests that the client deactivate as soon as
     possible. This is only valid for an active client. Valid results
     are LADMEA_ERROR_BAD_CLIENT or LADMEA_ERROR_RESOURCES.*/
  LADMEA_Result (*requestDeactivation)
  (const struct t_LADMEA_Client             * Client);

  /* Write a packet to an input. Unlike other calls, the client may
     call the exchange back during this call, but only through the
     sendToExchange() function. Packets must be sent in timestamp
     order. This function may return LADMEA_SUCCESS,
     LADMEA_ERROR_TOO_LATE, LADMEA_ERROR_BAD_CLIENT,
     LADMEA_ERROR_BAD_CHANNEL, LADMEA_ERROR_DATA (bad data),
     LADMEA_ERROR_RESOURCES. */
  LADMEA_Result (*sendToClient)
  (const struct t_LADMEA_Client             * Client,
   const struct t_LADMEA_Exchange           * Exchange,
   const LADMEA_ChannelID                     Input,
   const LADMEA_Timestamp                     Timestamp,
   const void                               * Data,
   const unsigned long                        Size);

} LADMEA_Client;

/***************************************************************************
**/

/* A Codec Specification:

   This structure provides a description of a codec's task
   (e.g. converting 16bit audio to MP3). */
typedef struct t_LADMEA_CodecSpecification {

  /* Description of the kind of data that will go into the Codec. */
  struct t_LADMEA_DataSpecification * Input;

  /* Description of the kind of data that will come out of the Codec. */
  struct t_LADMEA_DataSpecification * Output;

} LADMEA_CodecSpecification;

/***************************************************************************
**/

/* A Codec Provider:

   Some software provides conversions between data types.

   Codec providers should be written to be threadsafe. This does not
   require explicit use of multithreading calls. */
typedef struct t_LADMEA_CodecProvider {

  /* This call can be used to pick through a list of recommended
     Codecs. This does not need to be a complete list, but the codecs
     listed should be supported well. Indexes start at 0 and continue
     upwards until no more recommended codecs are found. NULL is
     returned to indicate this. The codec specification structures
     returned are expected to be valid until the codec provider is
     unregistered. This function returns a specification or NULL. */
  struct t_LADMEA_CodecSpecification * (*getCodec)
  (const struct t_LADMEA_CodecProvider      * CodecProvider,
   const unsigned long                        Index);

  /* Find out if the codec provider can provide a particular codec
     (this may or may not be on the list of codecs returned by
     getCodec()). This function returns a support level,
     LADMEA_ERROR_DATA (bad codec specification) or
     LADMEA_ERROR_RESOURCES. */
  LADMEA_SupportLevel (*queryCodecSupportLevel)
  (const struct t_LADMEA_CodecProvider      * CodecProvider,
   const struct t_LADMEA_CodecSpecification * CodecSpecification);

  /* Tell the codec provider to create a codec client, connect it to
     the provided channels on the relevant exchange, activate itself
     and run. Before making this call, the exchange will construct the
     channels and set them to the relevant data specifications. The
     codec may attempt to negotiate these but is unlikely to
     succeed. The codec should be deleted when this function returns,
     which happens when it is deactivated by the exchange. This
     function returns LADMEA_SUCCESS, LADMEA_ERROR_PERMISSION,
     LADMEA_ERROR_BAD_CLIENT, LADMEA_ERROR_BAD_CHANNEL,
     LADMEA_ERROR_SUPPORT or LADMEA_ERROR_RESOURCES. Note that some of
     these return codes originate at the exchange and indicate an
     internal failure there. */
  LADMEA_Result (*runCodecClient)
  (const struct t_LADMEA_CodecProvider      * CodecProvider,
   const struct t_LADMEA_CodecSpecification * CodecSpecification,
   const struct t_LADMEA_Exchange           * Exchange,
   const LADMEA_ChannelID                     Input,
   const LADMEA_ChannelID                     Output,
   const struct t_LADMEA_Client            ** Client);

} LADMEA_CodecProvider;

/***************************************************************************
**/

/* Accessing an Exchange Library: */

/* Programs may load exchanges as shared object files (these will
   often require external server processes). To allow multiple clients
   to share exchanges, clients may wish to check for environment
   variable LADMEA_EXCHANGE_PATH. If present, this should contain a
   colon-separated path indicating directories that should be searched
   (in order) when loading exchanges.

   A plugin programmer must include a function called
   "get_ladmea_exchange" with the following function prototype within
   the shared object file. This function will have C-style linkage (if
   you are using C++ this is taken care of by the `extern "C"' clause
   at the top of the file).

   A client will find the exchange object file by one means or
   another, find the get_ladmea_exchange() function, call it, and
   proceed from there. This function returns a pointer to an exchange
   that will persist until the library is unloaded (at which point it
   will be deleted). The function returns NULL on internal error. */

const LADMEA_Exchange * get_ladmea_exchange();

/* Datatype corresponding to the get_ladmea_exchange() function. */
typedef const LADMEA_Exchange * (*LADMEA_ExchangeFunction)();

/***************************************************************************
**/

/* Accessing a Client Library: */

/* Programs may load clients as shared object files. To allow multiple
   exchanges to share clients, programs may wish to check for
   environment variable LADMEA_CLIENT_PATH. If present, this should
   contain a colon-separated path indicating directories that should
   be searched (in order) when loading clients.

   A plugin programmer must include a function called
   "run_ladmea_client" with the following function prototype within
   the shared object file. This functions will have C-style linkage
   (if you are using C++ this is taken care of by the `extern "C"'
   clause at the top of the file).

   An exchange will find the client shared object file by one means or
   another, find the run_ladmea_client() function and call it. */

  /* Data passed as arguments need be valid only for the duration of
     the call. Note that the real arguments passed are numbered from 0
     excluding the program name, unlike the arguments to main()
     functions. This function returns any of the normal LADMEA error
     results depending on the error that stops
     operation. LADMEA_SUCCESS is returned on success. */
LADMEA_Result run_ladmea_client
(const struct t_LADMEA_Exchange  * Exchange,
 const int                         ArgumentCount,
 const char                     ** Arguments);

/* Datatype corresponding to the run_ladmea_client() function. */
typedef LADMEA_Result
(*LADMEA_ClientRunFunction)(const struct t_LADMEA_Exchange  * Exchange,
			    const int                         ArgumentCount,
			    const char                     ** Arguments);

/***************************************************************************
**/

/* Accessing a Codec Library: */

/* Programs may load codec providers as shared object files. To allow
   programs to share codec providers, programs may wish to check for
   environment variable LADMEA_CODEC_PATH. If present, this should
   contain a colon-separated path indicating directories that should
   be searched (in order) when loading exchanges.

   A plugin programmer must include a function called
   "get_ladmea_codec_provider" with the following function prototype
   within the shared object file. This function will have C-style
   linkage (if you are using C++ this is taken care of by the `extern
   "C"' clause at the top of the file).

   A client will find the exchange object file by one means or
   another, find the get_ladmea_codec_provider() function, call it,
   and proceed from there. This function returns a pointer to a codec
   provider that will persist until the library is unloaded (at which
   point it will be deleted). The function returns NULL on internal
   error. */

const LADMEA_CodecProvider * get_ladmea_codec_provider();

/* Data type corresponding to the get_ladmea_codec_provider()
   function. */
typedef const LADMEA_CodecProvider * (*LADMEA_CodecDescriptorFunction)();

/***************************************************************************
**/

#ifdef __cplusplus
}
#endif

#endif /* LADMEA_INCLUDED */

/* EOF */



/* ladmeasc_basic.h

   Linux Audio Developer's Multimedia Exchange API Version 1.0[LGPL].
   Copyright (C) 2001 Richard W.E. Furse.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public License
   as published by the Free Software Foundation; either version 2.1 of
   the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
   USA. */

#ifndef LADMEASC_BASIC_INCLUDED
#define LADMEASC_BASIC_INCLUDED

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************
**/

#include "data_types.h"
#include "ladmea.h"

/***************************************************************************
**/

/* Stream Properties:

   In this convention, streams may have the following properties. By
   default a stream is assumed to carry irregular packets of variable
   size. */

typedef UNSIGNED_32BIT_INTEGER LADMEA_SC_Basic_Properties;

/* This flag indicates that the stream sends packets at regular time
   intervals. */
#define LADMEA_SC_BASIC_TYPE_REGULAR           0x1

/* This indicates that the stream will always send packets of the same
   size. */
#define LADMEA_SC_BASIC_TYPE_FIXED_SIZE        0x2

/***************************************************************************
**/

/* Basic Stream Characteristic Descriptor Convention:

   This streaming characteristic descriptor convention describes the
   statistical behaviour of data using a simple approach.

   This stream characteristic descriptor convention is unique in
   LADMEA in that all clients and exchanges are required to understand
   it. It is identified by its LADMEA_ConventionID which is 1. */

#define LADMEA_SCID_BASIC 1

typedef struct t_LADMEA_SC_Basic {

  /* This indicates the properties of the stream ORed together. */
  LADMEA_SC_Basic_Properties Properties;

  /* This indicates the (mean) average number of bytes sent per second
     over the stream. This data should always be present. */
  IEEE_DOUBLE               AverageBytesPerSecond;

  /* This indicates the (mean) average number of packets per
     second. For a regular fixed-size stream this will be a precise
     value that can be used to calculate the bytes in a packet. */
  IEEE_DOUBLE               AveragePacketFrequency;

} LADMEA_SC_Basic;

/***************************************************************************
**/

#ifdef __cplusplus
}
#endif

#endif /* LADMEASC_BASIC_INCLUDED */

/* EOF */



/* ladmealr_basic.h

   Linux Audio Developer's Multimedia Exchange API Version 1.0[LGPL].
   Copyright (C) 2001 Richard W.E. Furse.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public License
   as published by the Free Software Foundation; either version 2.1 of
   the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
   USA. */

#ifndef LADMEALR_BASIC_INCLUDED
#define LADMEALR_BASIC_INCLUDED

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************
**/

#include "data_types.h"
#include "ladmea.h"

/***************************************************************************
**/

/* Basic Latency Requirement Descriptor Convention:

   This streaming characteristic convention describes the statistical
   behaviour of data in a stream as a single latency value.

   This latency requirement descriptor convention is unique in LADMEA
   in that all clients and exchanges are required to understand it. It
   is identified by its LADMEA_ConventionID which is 2. */

#define LADMEA_LRID_BASIC 2

typedef struct t_LADMEA_LR_Basic {

  /* This indicates how long the maximum distance between the real
     time clock and logical timestamps (derived or on input packets)
     tolerated by the client. Measured in second. */
  IEEE_DOUBLE  LatencyTolerance;

} LADMEA_LR_Basic;

/***************************************************************************
**/

#ifdef __cplusplus
}
#endif

#endif /* LADMEALR_BASIC_INCLUDED */

/* EOF */





More information about the gstreamer-devel mailing list