| 
							- /* -*- c-basic-offset: 4 -*- */
 - 
 - /* dssi.h
 - 
 -    DSSI version 1.0
 -    Copyright (c) 2004, 2009 Chris Cannam, Steve Harris and Sean Bolton
 -    
 -    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., 51 Franklin Street, Fifth Floor, Boston,
 -    MA  02110-1301  USA
 - */
 - 
 - #ifndef DSSI_INCLUDED
 - #define DSSI_INCLUDED
 - 
 - #include "../ladspa/ladspa.h"
 - #include "seq_event-compat.h"
 - 
 - #define DSSI_VERSION "1.0"
 - #define DSSI_VERSION_MAJOR 1
 - #define DSSI_VERSION_MINOR 0
 - 
 - #ifdef __cplusplus
 - extern "C" {
 - #endif
 - 
 - /* 
 -    There is a need for an API that supports hosted MIDI soft synths
 -    with GUIs in Linux audio applications.  In time the GMPI initiative
 -    should comprehensively address this need, but the requirement for
 -    Linux applications to be able to support simple hosted synths is
 -    here now, and GMPI is not.  This proposal (the "DSSI Soft Synth
 -    Interface" or DSSI, pronounced "dizzy") aims to provide a simple
 -    solution in a way that we hope will prove complete and compelling
 -    enough to support now, yet not so compelling as to supplant GMPI or
 -    any other comprehensive future proposal.
 - 
 -    For simplicity and familiarity, this API is based as far as
 -    possible on existing work -- the LADSPA plugin API for control
 -    values and audio processing, and the ALSA sequencer event types for
 -    MIDI event communication.  The GUI part of the proposal is quite
 -    new, but may also be applicable retroactively to LADSPA plugins
 -    that do not otherwise support this synth interface.
 - */
 - 
 - typedef struct _DSSI_Program_Descriptor {
 - 
 -     /** Bank number for this program.  Note that DSSI does not support
 -         MIDI-style separation of bank LSB and MSB values.  There is no
 -         restriction on the set of available banks: the numbers do not
 -         need to be contiguous, there does not need to be a bank 0, etc. */
 -     unsigned long Bank;
 - 
 -     /** Program number (unique within its bank) for this program.
 - 	There is no restriction on the set of available programs: the
 - 	numbers do not need to be contiguous, there does not need to
 - 	be a program 0, etc. */
 -     unsigned long Program;
 - 
 -     /** Name of the program. */
 -     const char * Name;
 - 
 - } DSSI_Program_Descriptor;
 - 
 - 
 - typedef struct _DSSI_Descriptor {
 - 
 -     /**
 -      * DSSI_API_Version
 -      *
 -      * This member indicates the DSSI API level used by this plugin.
 -      * If we're lucky, this will never be needed.  For now all plugins
 -      * must set it to 1.
 -      */
 -     int DSSI_API_Version;
 - 
 -     /**
 -      * LADSPA_Plugin
 -      *
 -      * A DSSI synth plugin consists of a LADSPA plugin plus an
 -      * additional framework for controlling program settings and
 -      * transmitting MIDI events.  A plugin must fully implement the
 -      * LADSPA descriptor fields as well as the required LADSPA
 -      * functions including instantiate() and (de)activate().  It
 -      * should also implement run(), with the same behaviour as if
 -      * run_synth() (below) were called with no synth events.
 -      *
 -      * In order to instantiate a synth the host calls the LADSPA
 -      * instantiate function, passing in this LADSPA_Descriptor
 -      * pointer.  The returned LADSPA_Handle is used as the argument
 -      * for the DSSI functions below as well as for the LADSPA ones.
 -      */
 -     const LADSPA_Descriptor *LADSPA_Plugin;
 - 
 -     /**
 -      * configure()
 -      *
 -      * This member is a function pointer that sends a piece of
 -      * configuration data to the plugin.  The key argument specifies
 -      * some aspect of the synth's configuration that is to be changed,
 -      * and the value argument specifies a new value for it.  A plugin
 -      * that does not require this facility at all may set this member
 -      * to NULL.
 -      *
 -      * This call is intended to set some session-scoped aspect of a
 -      * plugin's behaviour, for example to tell the plugin to load
 -      * sample data from a particular file.  The plugin should act
 -      * immediately on the request.  The call should return NULL on
 -      * success, or an error string that may be shown to the user.  The
 -      * host will free the returned value after use if it is non-NULL.
 -      *
 -      * Calls to configure() are not automated as timed events.
 -      * Instead, a host should remember the last value associated with
 -      * each key passed to configure() during a given session for a
 -      * given plugin instance, and should call configure() with the
 -      * correct value for each key the next time it instantiates the
 -      * "same" plugin instance, for example on reloading a project in
 -      * which the plugin was used before.  Plugins should note that a
 -      * host may typically instantiate a plugin multiple times with the
 -      * same configuration values, and should share data between
 -      * instances where practical.
 -      *
 -      * Calling configure() completely invalidates the program and bank
 -      * information last obtained from the plugin.
 -      *
 -      * Reserved and special key prefixes
 -      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 -      * The DSSI: prefix
 -      * ----------------
 -      * Configure keys starting with DSSI: are reserved for particular
 -      * purposes documented in the DSSI specification.  At the moment,
 -      * there is one such key: DSSI:PROJECT_DIRECTORY.  A host may call
 -      * configure() passing this key and a directory path value.  This
 -      * indicates to the plugin and its UI that a directory at that
 -      * path exists and may be used for project-local data.  Plugins
 -      * may wish to use the project directory as a fallback location
 -      * when looking for other file data, or as a base for relative
 -      * paths in other configuration values.
 -      *
 -      * The GLOBAL: prefix
 -      * ------------------
 -      * Configure keys starting with GLOBAL: may be used by the plugin
 -      * and its UI for any purpose, but are treated specially by the
 -      * host.  When one of these keys is used in a configure OSC call
 -      * from the plugin UI, the host makes the corresponding configure
 -      * call (preserving the GLOBAL: prefix) not only to the target
 -      * plugin but also to all other plugins in the same instance
 -      * group, as well as their UIs.  Note that if any instance
 -      * returns non-NULL from configure to indicate error, the host
 -      * may stop there (and the set of plugins on which configure has
 -      * been called will thus depend on the host implementation).
 -      * See also the configure OSC call documentation in RFC.txt.
 -      */
 -     char *(*configure)(LADSPA_Handle Instance,
 - 		       const char *Key,
 - 		       const char *Value);
 - 
 -     #define DSSI_RESERVED_CONFIGURE_PREFIX "DSSI:"
 -     #define DSSI_GLOBAL_CONFIGURE_PREFIX "GLOBAL:"
 -     #define DSSI_PROJECT_DIRECTORY_KEY \
 - 	DSSI_RESERVED_CONFIGURE_PREFIX "PROJECT_DIRECTORY"
 -     #define DSSI_CUSTOMDATA_EXTENSION_KEY \
 - 	DSSI_RESERVED_CONFIGURE_PREFIX "SUPPORTS_CUSTOMDATA"
 - 
 -     /**
 -      * get_program()
 -      *
 -      * This member is a function pointer that provides a description
 -      * of a program (named preset sound) available on this synth.  A
 -      * plugin that does not support programs at all should set this
 -      * member to NULL.
 -      *
 -      * The Index argument is an index into the plugin's list of
 -      * programs, not a program number as represented by the Program
 -      * field of the DSSI_Program_Descriptor.  (This distinction is
 -      * needed to support synths that use non-contiguous program or
 -      * bank numbers.)
 -      *
 -      * This function returns a DSSI_Program_Descriptor pointer that is
 -      * guaranteed to be valid only until the next call to get_program,
 -      * deactivate, or configure, on the same plugin instance.  This
 -      * function must return NULL if passed an Index argument out of
 -      * range, so that the host can use it to query the number of
 -      * programs as well as their properties.
 -      */
 -     const DSSI_Program_Descriptor *(*get_program)(LADSPA_Handle Instance,
 - 						  unsigned long Index);
 -     
 -     /**
 -      * select_program()
 -      *
 -      * This member is a function pointer that selects a new program
 -      * for this synth.  The program change should take effect
 -      * immediately at the start of the next run_synth() call.  (This
 -      * means that a host providing the capability of changing programs
 -      * between any two notes on a track must vary the block size so as
 -      * to place the program change at the right place.  A host that
 -      * wanted to avoid this would probably just instantiate a plugin
 -      * for each program.)
 -      * 
 -      * A plugin that does not support programs at all should set this
 -      * member NULL.  Plugins should ignore a select_program() call
 -      * with an invalid bank or program.
 -      *
 -      * A plugin is not required to select any particular default
 -      * program on activate(): it's the host's duty to set a program
 -      * explicitly.  The current program is invalidated by any call to
 -      * configure().
 -      *
 -      * A plugin is permitted to re-write the values of its input
 -      * control ports when select_program is called.  The host should
 -      * re-read the input control port values and update its own
 -      * records appropriately.  (This is the only circumstance in
 -      * which a DSSI plugin is allowed to modify its own input ports.)
 -      */
 -     void (*select_program)(LADSPA_Handle Instance,
 - 			   unsigned long Bank,
 - 			   unsigned long Program);
 - 
 -     /**
 -      * get_midi_controller_for_port()
 -      *
 -      * This member is a function pointer that returns the MIDI
 -      * controller number or NRPN that should be mapped to the given
 -      * input control port.  If the given port should not have any MIDI
 -      * controller mapped to it, the function should return DSSI_NONE.
 -      * The behaviour of this function is undefined if the given port
 -      * number does not correspond to an input control port.  A plugin
 -      * that does not want MIDI controllers mapped to ports at all may
 -      * set this member NULL.
 -      *
 -      * Correct values can be got using the macros DSSI_CC(num) and
 -      * DSSI_NRPN(num) as appropriate, and values can be combined using
 -      * bitwise OR: e.g. DSSI_CC(23) | DSSI_NRPN(1069) means the port
 -      * should respond to CC #23 and NRPN #1069.
 -      *
 -      * The host is responsible for doing proper scaling from MIDI
 -      * controller and NRPN value ranges to port ranges according to
 -      * the plugin's LADSPA port hints.  Hosts should not deliver
 -      * through run_synth any MIDI controller events that have already
 -      * been mapped to control port values.
 -      *
 -      * A plugin should not attempt to request mappings from
 -      * controllers 0 or 32 (MIDI Bank Select MSB and LSB).
 -      */
 -     int (*get_midi_controller_for_port)(LADSPA_Handle Instance,
 - 					unsigned long Port);
 - 
 -     /**
 -      * run_synth()
 -      *
 -      * This member is a function pointer that runs a synth for a
 -      * block.  This is identical in function to the LADSPA run()
 -      * function, except that it also supplies events to the synth.
 -      *
 -      * A plugin may provide this function, run_multiple_synths() (see
 -      * below), both, or neither (if it is not in fact a synth).  A
 -      * plugin that does not provide this function must set this member
 -      * to NULL.  Authors of synth plugins are encouraged to provide
 -      * this function if at all possible.
 -      *
 -      * The Events pointer points to a block of EventCount ALSA
 -      * sequencer events, which is used to communicate MIDI and related
 -      * events to the synth.  Each event is timestamped relative to the
 -      * start of the block, (mis)using the ALSA "tick time" field as a
 -      * frame count. The host is responsible for ensuring that events
 -      * with differing timestamps are already ordered by time.
 -      *
 -      * See also the notes on activation, port connection etc in
 -      * ladpsa.h, in the context of the LADSPA run() function.
 -      *
 -      * Note Events
 -      * ~~~~~~~~~~~
 -      * There are two minor requirements aimed at making the plugin
 -      * writer's life as simple as possible:
 -      * 
 -      * 1. A host must never send events of type SND_SEQ_EVENT_NOTE.
 -      * Notes should always be sent as separate SND_SEQ_EVENT_NOTE_ON
 -      * and NOTE_OFF events.  A plugin should discard any one-point
 -      * NOTE events it sees.
 -      * 
 -      * 2. A host must not attempt to switch notes off by sending
 -      * zero-velocity NOTE_ON events.  It should always send true
 -      * NOTE_OFFs.  It is the host's responsibility to remap events in
 -      * cases where an external MIDI source has sent it zero-velocity
 -      * NOTE_ONs.
 -      *
 -      * Bank and Program Events
 -      * ~~~~~~~~~~~~~~~~~~~~~~~
 -      * Hosts must map MIDI Bank Select MSB and LSB (0 and 32)
 -      * controllers and MIDI Program Change events onto the banks and
 -      * programs specified by the plugin, using the DSSI select_program
 -      * call.  No host should ever deliver a program change or bank
 -      * select controller to a plugin via run_synth.
 -      */
 -     void (*run_synth)(LADSPA_Handle    Instance,
 - 		      unsigned long    SampleCount,
 - 		      snd_seq_event_t *Events,
 - 		      unsigned long    EventCount);
 - 
 -     /**
 -      * run_synth_adding()
 -      *
 -      * This member is a function pointer that runs an instance of a
 -      * synth for a block, adding its outputs to the values already
 -      * present at the output ports.  This is provided for symmetry
 -      * with LADSPA run_adding(), and is equally optional.  A plugin
 -      * that does not provide it must set this member to NULL.
 -      */
 -     void (*run_synth_adding)(LADSPA_Handle    Instance,
 - 			     unsigned long    SampleCount,
 - 			     snd_seq_event_t *Events,
 - 			     unsigned long    EventCount);
 - 
 -     /**
 -      * run_multiple_synths()
 -      *
 -      * This member is a function pointer that runs multiple synth
 -      * instances for a block.  This is very similar to run_synth(),
 -      * except that Instances, Events, and EventCounts each point to
 -      * arrays that hold the LADSPA handles, event buffers, and
 -      * event counts for each of InstanceCount instances.  That is,
 -      * Instances points to an array of InstanceCount pointers to
 -      * DSSI plugin instantiations, Events points to an array of
 -      * pointers to each instantiation's respective event list, and
 -      * EventCounts points to an array containing each instantiation's
 -      * respective event count.
 -      *
 -      * A host using this function must guarantee that ALL active
 -      * instances of the plugin are represented in each call to the
 -      * function -- that is, a host may not call run_multiple_synths()
 -      * for some instances of a given plugin and then call run_synth()
 -      * as well for others.  'All .. instances of the plugin' means
 -      * every instance sharing the same LADSPA label and shared object
 -      * (*.so) file (rather than every instance sharing the same *.so).
 -      * 'Active' means any instance for which activate() has been called
 -      * but deactivate() has not.
 -      *
 -      * A plugin may provide this function, run_synths() (see above),
 -      * both, or neither (if it not in fact a synth).  A plugin that
 -      * does not provide this function must set this member to NULL.
 -      * Plugin authors implementing run_multiple_synths are strongly
 -      * encouraged to implement run_synth as well if at all possible,
 -      * to aid simplistic hosts, even where it would be less efficient
 -      * to use it.
 -      */
 -     void (*run_multiple_synths)(unsigned long     InstanceCount,
 -                                 LADSPA_Handle    *Instances,
 -                                 unsigned long     SampleCount,
 -                                 snd_seq_event_t **Events,
 -                                 unsigned long    *EventCounts);
 - 
 -     /**
 -      * run_multiple_synths_adding()
 -      *
 -      * This member is a function pointer that runs multiple synth
 -      * instances for a block, adding each synth's outputs to the
 -      * values already present at the output ports.  This is provided
 -      * for symmetry with both the DSSI run_multiple_synths() and LADSPA
 -      * run_adding() functions, and is equally optional.  A plugin
 -      * that does not provide it must set this member to NULL.
 -      */
 -     void (*run_multiple_synths_adding)(unsigned long     InstanceCount,
 -                                        LADSPA_Handle    *Instances,
 -                                        unsigned long     SampleCount,
 -                                        snd_seq_event_t **Events,
 -                                        unsigned long    *EventCounts);
 - 
 -     /**
 -      * set_custom_data()
 -      */
 -     int (*set_custom_data)(LADSPA_Handle Instance,
 -                            void         *Data,
 -                            unsigned long DataLength);
 - 
 -     /**
 -      * get_custom_data()
 -      */
 -     int (*get_custom_data)(LADSPA_Handle  Instance,
 -                            void         **Data,
 -                            unsigned long *DataLength);
 - 
 - } DSSI_Descriptor;
 - 
 - /**
 -  * DSSI supports a plugin discovery method similar to that of LADSPA:
 -  *
 -  * - DSSI hosts may wish to locate DSSI plugin shared object files by
 -  *    searching the paths contained in the DSSI_PATH and LADSPA_PATH
 -  *    environment variables, if they are present.  Both are expected
 -  *    to be colon-separated lists of directories to be searched (in
 -  *    order), and DSSI_PATH should be searched first if both variables
 -  *    are set.
 -  *
 -  * - Each shared object file containing DSSI plugins must include a
 -  *   function dssi_descriptor(), with the following function prototype
 -  *   and C-style linkage.  Hosts may enumerate the plugin types
 -  *   available in the shared object file by repeatedly calling
 -  *   this function with successive Index values (beginning from 0),
 -  *   until a return value of NULL indicates no more plugin types are
 -  *   available.  Each non-NULL return is the DSSI_Descriptor
 -  *   of a distinct plugin type.
 -  */
 - 
 - const DSSI_Descriptor *dssi_descriptor(unsigned long Index);
 -   
 - typedef const DSSI_Descriptor *(*DSSI_Descriptor_Function)(unsigned long Index);
 - 
 - /*
 -  * Macros to specify particular MIDI controllers in return values from
 -  * get_midi_controller_for_port()
 -  */
 - 
 - #define DSSI_CC_BITS			0x20000000
 - #define DSSI_NRPN_BITS			0x40000000
 - 
 - #define DSSI_NONE			-1
 - #define DSSI_CONTROLLER_IS_SET(n)	(DSSI_NONE != (n))
 - 
 - #define DSSI_CC(n)			(DSSI_CC_BITS | (n))
 - #define DSSI_IS_CC(n)			(DSSI_CC_BITS & (n))
 - #define DSSI_CC_NUMBER(n)		((n) & 0x7f)
 - 
 - #define DSSI_NRPN(n)			(DSSI_NRPN_BITS | ((n) << 7))
 - #define DSSI_IS_NRPN(n)			(DSSI_NRPN_BITS & (n))
 - #define DSSI_NRPN_NUMBER(n)		(((n) >> 7) & 0x3fff)
 - 
 - #ifdef __cplusplus
 - }
 - #endif
 - 
 - #endif /* DSSI_INCLUDED */
 
 
  |