annotate plugin/api/dssi.h @ 1390:1a572937ed8c

And say so
author Chris Cannam
date Mon, 27 Feb 2017 15:44:14 +0000
parents 39ae3dee27b9
children 48e9f538e6e9
rev   line source
Chris@49 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- */
Chris@0 2
Chris@0 3 /* dssi.h
Chris@0 4
Chris@0 5 DSSI version 0.10
Chris@0 6 Copyright (c) 2004,2005 Chris Cannam, Steve Harris and Sean Bolton
Chris@0 7
Chris@0 8 This library is free software; you can redistribute it and/or
Chris@0 9 modify it under the terms of the GNU Lesser General Public License
Chris@0 10 as published by the Free Software Foundation; either version 2.1 of
Chris@0 11 the License, or (at your option) any later version.
Chris@0 12
Chris@0 13 This library is distributed in the hope that it will be useful, but
Chris@0 14 WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@0 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Chris@0 16 Lesser General Public License for more details.
Chris@0 17
Chris@0 18 You should have received a copy of the GNU Lesser General Public
Chris@0 19 License along with this library; if not, write to the Free Software
Chris@0 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
Chris@0 21 USA.
Chris@0 22 */
Chris@0 23
Chris@0 24 #ifndef DSSI_INCLUDED
Chris@0 25 #define DSSI_INCLUDED
Chris@0 26
Chris@0 27 #include "ladspa.h"
Chris@0 28 #include "alsa/seq_event.h"
Chris@0 29
Chris@0 30 #define DSSI_VERSION "0.10"
Chris@0 31 #define DSSI_VERSION_MAJOR 0
Chris@0 32 #define DSSI_VERSION_MINOR 10
Chris@0 33
Chris@0 34 #ifdef __cplusplus
Chris@0 35 extern "C" {
Chris@0 36 #endif
Chris@0 37
Chris@0 38 /*
Chris@0 39 There is a need for an API that supports hosted MIDI soft synths
Chris@0 40 with GUIs in Linux audio applications. In time the GMPI initiative
Chris@0 41 should comprehensively address this need, but the requirement for
Chris@0 42 Linux applications to be able to support simple hosted synths is
Chris@0 43 here now, and GMPI is not. This proposal (the "DSSI Soft Synth
Chris@0 44 Interface" or DSSI, pronounced "dizzy") aims to provide a simple
Chris@0 45 solution in a way that we hope will prove complete and compelling
Chris@0 46 enough to support now, yet not so compelling as to supplant GMPI or
Chris@0 47 any other comprehensive future proposal.
Chris@0 48
Chris@0 49 For simplicity and familiarity, this API is based as far as
Chris@0 50 possible on existing work -- the LADSPA plugin API for control
Chris@0 51 values and audio processing, and the ALSA sequencer event types for
Chris@0 52 MIDI event communication. The GUI part of the proposal is quite
Chris@0 53 new, but may also be applicable retroactively to LADSPA plugins
Chris@0 54 that do not otherwise support this synth interface.
Chris@0 55 */
Chris@0 56
Chris@0 57 /*
Chris@0 58 A program wishing to use the DSSI v2 API should set the following
Chris@0 59 symbol to 2 before including this header.
Chris@0 60 */
Chris@0 61 #if (!defined DSSI_API_LEVEL)
Chris@0 62 #define DSSI_API_LEVEL 1
Chris@0 63 #endif
Chris@0 64
Chris@0 65 typedef struct _DSSI_Program_Descriptor {
Chris@0 66
Chris@0 67 /** Bank number for this program. Note that DSSI does not support
Chris@0 68 MIDI-style separation of bank LSB and MSB values. There is no
Chris@0 69 restriction on the set of available banks: the numbers do not
Chris@0 70 need to be contiguous, there does not need to be a bank 0, etc. */
Chris@0 71 unsigned long Bank;
Chris@0 72
Chris@0 73 /** Program number (unique within its bank) for this program.
Chris@0 74 There is no restriction on the set of available programs: the
Chris@0 75 numbers do not need to be contiguous, there does not need to
Chris@0 76 be a program 0, etc. */
Chris@0 77 unsigned long Program;
Chris@0 78
Chris@0 79 /** Name of the program. */
Chris@0 80 const char * Name;
Chris@0 81
Chris@0 82 } DSSI_Program_Descriptor;
Chris@0 83
Chris@0 84
Chris@0 85 #define DSSI_TRANSPORT_VALID_STATE 0x01
Chris@0 86 #define DSSI_TRANSPORT_VALID_BPM 0x02
Chris@0 87 #define DSSI_TRANSPORT_VALID_BBT 0x10
Chris@0 88 #define DSSI_TRANSPORT_VALID_TIME 0x20
Chris@0 89
Chris@0 90 #define DSSI_TRANSPORT_STATE_STOPPED 0
Chris@0 91 #define DSSI_TRANSPORT_STATE_RUNNING 1
Chris@0 92 #define DSSI_TRANSPORT_STATE_FREEWHEELING 2
Chris@0 93 #define DSSI_TRANSPORT_STATE_OTHER 3 /* waiting for sync, ? */
Chris@0 94
Chris@0 95 typedef struct _DSSI_Transport_Info {
Chris@0 96
Chris@0 97 /** The value of this field indicates which of the following
Chris@0 98 * transport information fields contain valid values. It is
Chris@0 99 * the logical OR of the DSSI_TRANSPORT_VALID_* bits defined
Chris@0 100 * above, and may be zero. */
Chris@0 101 int Valid;
Chris@0 102
Chris@0 103
Chris@0 104 /** This field is valid when (Valid & DSSI_TRANSPORT_VALID_STATE)
Chris@0 105 * is true:
Chris@0 106 *
Chris@0 107 * ---- The current transport state, one of the DSSI_TRANSPORT_STATE_*
Chris@0 108 * values defined above. */
Chris@0 109 int State;
Chris@0 110
Chris@0 111
Chris@0 112 /** This field is valid when (Valid & DSSI_TRANSPORT_VALID_BPM)
Chris@0 113 * is true:
Chris@0 114 *
Chris@0 115 * ---- The current tempo, in beats per minute. */
Chris@0 116 double Beats_Per_Minute;
Chris@0 117
Chris@0 118
Chris@0 119 /** These six fields are valid when (Valid & DSSI_TRANSPORT_VALID_BBT)
Chris@0 120 * is true:
Chris@0 121 *
Chris@0 122 * ---- The bar number at the beginning of the current process cycle. */
Chris@0 123 unsigned long Bar;
Chris@0 124
Chris@0 125 /** ---- The beat within that Bar. */
Chris@0 126 unsigned long Beat;
Chris@0 127
Chris@0 128 /** ---- The tick within that Beat. */
Chris@0 129 unsigned long Tick;
Chris@0 130
Chris@0 131 /** ---- The (possibly fractional) tick count since transport 'start'
Chris@0 132 * and the beginning of the current Bar. */
Chris@0 133 double Bar_Start_Tick;
Chris@0 134
Chris@0 135 /** ---- The number of beats per bar. */
Chris@0 136 float Beats_Per_Bar;
Chris@0 137
Chris@0 138 /** ---- The number of ticks for each beat. */
Chris@0 139 double Ticks_Per_Beat;
Chris@0 140
Chris@0 141 /* [Sean says: I left out the 'beat_type' (time signature "denominator")
Chris@0 142 * field of the jack_position_t structure, because I think it's useless
Chris@0 143 * except to a notation program. Does anybody else feel like we need it?]
Chris@0 144 */
Chris@0 145
Chris@0 146 /** These two fields are valid when (Valid & DSSI_TRANSPORT_VALID_TIME)
Chris@0 147 * is true:
Chris@0 148 *
Chris@0 149 * ---- The transport time at the beginning of the current process
Chris@0 150 * cycle, in seconds. */
Chris@0 151 double Current_Time;
Chris@0 152
Chris@0 153 /** ---- The transport time at the beginning of the next process
Chris@0 154 cycle, unless repositioning occurs. */
Chris@0 155 double Next_Time;
Chris@0 156
Chris@0 157 } DSSI_Transport_Info;
Chris@0 158
Chris@0 159 typedef struct _DSSI_Host_Descriptor DSSI_Host_Descriptor; /* below */
Chris@0 160
Chris@0 161 typedef struct _DSSI_Descriptor {
Chris@0 162
Chris@0 163 /**
Chris@0 164 * DSSI_API_Version
Chris@0 165 *
Chris@0 166 * This member indicates the DSSI API level used by this plugin.
Chris@0 167 * All plugins must set this to 1 or 2. The version 1 API contains
Chris@0 168 * all DSSI_Descriptor fields through run_multiple_synths_adding(),
Chris@0 169 * while the version 2 API adds the receive_host_descriptor().
Chris@0 170 */
Chris@0 171 int DSSI_API_Version;
Chris@0 172
Chris@0 173 /**
Chris@0 174 * LADSPA_Plugin
Chris@0 175 *
Chris@0 176 * A DSSI synth plugin consists of a LADSPA plugin plus an
Chris@0 177 * additional framework for controlling program settings and
Chris@0 178 * transmitting MIDI events. A plugin must fully implement the
Chris@0 179 * LADSPA descriptor fields as well as the required LADSPA
Chris@0 180 * functions including instantiate() and (de)activate(). It
Chris@0 181 * should also implement run(), with the same behaviour as if
Chris@0 182 * run_synth() (below) were called with no synth events.
Chris@0 183 *
Chris@0 184 * In order to instantiate a synth the host calls the LADSPA
Chris@0 185 * instantiate function, passing in this LADSPA_Descriptor
Chris@0 186 * pointer. The returned LADSPA_Handle is used as the argument
Chris@0 187 * for the DSSI functions below as well as for the LADSPA ones.
Chris@0 188 */
Chris@0 189 const LADSPA_Descriptor *LADSPA_Plugin;
Chris@0 190
Chris@0 191 /**
Chris@0 192 * configure()
Chris@0 193 *
Chris@0 194 * This member is a function pointer that sends a piece of
Chris@0 195 * configuration data to the plugin. The key argument specifies
Chris@0 196 * some aspect of the synth's configuration that is to be changed,
Chris@0 197 * and the value argument specifies a new value for it. A plugin
Chris@0 198 * that does not require this facility at all may set this member
Chris@0 199 * to NULL.
Chris@0 200 *
Chris@0 201 * This call is intended to set some session-scoped aspect of a
Chris@0 202 * plugin's behaviour, for example to tell the plugin to load
Chris@0 203 * sample data from a particular file. The plugin should act
Chris@0 204 * immediately on the request. The call should return NULL on
Chris@0 205 * success, or an error string that may be shown to the user. The
Chris@0 206 * host will free the returned value after use if it is non-NULL.
Chris@0 207 *
Chris@0 208 * Calls to configure() are not automated as timed events.
Chris@0 209 * Instead, a host should remember the last value associated with
Chris@0 210 * each key passed to configure() during a given session for a
Chris@0 211 * given plugin instance, and should call configure() with the
Chris@0 212 * correct value for each key the next time it instantiates the
Chris@0 213 * "same" plugin instance, for example on reloading a project in
Chris@0 214 * which the plugin was used before. Plugins should note that a
Chris@0 215 * host may typically instantiate a plugin multiple times with the
Chris@0 216 * same configuration values, and should share data between
Chris@0 217 * instances where practical.
Chris@0 218 *
Chris@0 219 * Calling configure() completely invalidates the program and bank
Chris@0 220 * information last obtained from the plugin.
Chris@0 221 *
Chris@0 222 * Reserved and special key prefixes
Chris@0 223 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Chris@0 224 * The DSSI: prefix
Chris@0 225 * ----------------
Chris@0 226 * Configure keys starting with DSSI: are reserved for particular
Chris@0 227 * purposes documented in the DSSI specification. At the moment,
Chris@0 228 * there is one such key: DSSI:PROJECT_DIRECTORY. A host may call
Chris@0 229 * configure() passing this key and a directory path value. This
Chris@0 230 * indicates to the plugin and its UI that a directory at that
Chris@0 231 * path exists and may be used for project-local data. Plugins
Chris@0 232 * may wish to use the project directory as a fallback location
Chris@0 233 * when looking for other file data, or as a base for relative
Chris@0 234 * paths in other configuration values.
Chris@0 235 *
Chris@0 236 * The GLOBAL: prefix
Chris@0 237 * ------------------
Chris@0 238 * Configure keys starting with GLOBAL: may be used by the plugin
Chris@0 239 * and its UI for any purpose, but are treated specially by the
Chris@0 240 * host. When one of these keys is used in a configure OSC call
Chris@0 241 * from the plugin UI, the host makes the corresponding configure
Chris@0 242 * call (preserving the GLOBAL: prefix) not only to the target
Chris@0 243 * plugin but also to all other plugins in the same instance
Chris@0 244 * group, as well as their UIs. Note that if any instance
Chris@0 245 * returns non-NULL from configure to indicate error, the host
Chris@0 246 * may stop there (and the set of plugins on which configure has
Chris@0 247 * been called will thus depend on the host implementation).
Chris@0 248 * See also the configure OSC call documentation in RFC.txt.
Chris@0 249 */
Chris@0 250 char *(*configure)(LADSPA_Handle Instance,
Chris@0 251 const char *Key,
Chris@0 252 const char *Value);
Chris@0 253
Chris@0 254 #define DSSI_RESERVED_CONFIGURE_PREFIX "DSSI:"
Chris@0 255 #define DSSI_GLOBAL_CONFIGURE_PREFIX "GLOBAL:"
Chris@0 256 #define DSSI_PROJECT_DIRECTORY_KEY \
Chris@0 257 DSSI_RESERVED_CONFIGURE_PREFIX "PROJECT_DIRECTORY"
Chris@0 258
Chris@0 259 /**
Chris@0 260 * get_program()
Chris@0 261 *
Chris@0 262 * This member is a function pointer that provides a description
Chris@0 263 * of a program (named preset sound) available on this synth. A
Chris@0 264 * plugin that does not support programs at all should set this
Chris@0 265 * member to NULL.
Chris@0 266 *
Chris@0 267 * The Index argument is an index into the plugin's list of
Chris@0 268 * programs, not a program number as represented by the Program
Chris@0 269 * field of the DSSI_Program_Descriptor. (This distinction is
Chris@0 270 * needed to support synths that use non-contiguous program or
Chris@0 271 * bank numbers.)
Chris@0 272 *
Chris@0 273 * This function returns a DSSI_Program_Descriptor pointer that is
Chris@0 274 * guaranteed to be valid only until the next call to get_program,
Chris@0 275 * deactivate, or configure, on the same plugin instance. This
Chris@0 276 * function must return NULL if passed an Index argument out of
Chris@0 277 * range, so that the host can use it to query the number of
Chris@0 278 * programs as well as their properties.
Chris@0 279 */
Chris@0 280 const DSSI_Program_Descriptor *(*get_program)(LADSPA_Handle Instance,
Chris@0 281 unsigned long Index);
Chris@0 282
Chris@0 283 /**
Chris@0 284 * select_program()
Chris@0 285 *
Chris@0 286 * This member is a function pointer that selects a new program
Chris@0 287 * for this synth. The program change should take effect
Chris@0 288 * immediately at the start of the next run_synth() call. (This
Chris@0 289 * means that a host providing the capability of changing programs
Chris@0 290 * between any two notes on a track must vary the block size so as
Chris@0 291 * to place the program change at the right place. A host that
Chris@0 292 * wanted to avoid this would probably just instantiate a plugin
Chris@0 293 * for each program.)
Chris@0 294 *
Chris@0 295 * A plugin that does not support programs at all should set this
Chris@0 296 * member NULL. Plugins should ignore a select_program() call
Chris@0 297 * with an invalid bank or program.
Chris@0 298 *
Chris@0 299 * A plugin is not required to select any particular default
Chris@0 300 * program on activate(): it's the host's duty to set a program
Chris@0 301 * explicitly. The current program is invalidated by any call to
Chris@0 302 * configure().
Chris@0 303 *
Chris@0 304 * A plugin is permitted to re-write the values of its input
Chris@0 305 * control ports when select_program is called. The host should
Chris@0 306 * re-read the input control port values and update its own
Chris@0 307 * records appropriately. (This is the only circumstance in
Chris@0 308 * which a DSSI plugin is allowed to modify its own input ports.)
Chris@0 309 */
Chris@0 310 void (*select_program)(LADSPA_Handle Instance,
Chris@0 311 unsigned long Bank,
Chris@0 312 unsigned long Program);
Chris@0 313
Chris@0 314 /**
Chris@0 315 * get_midi_controller_for_port()
Chris@0 316 *
Chris@0 317 * This member is a function pointer that returns the MIDI
Chris@0 318 * controller number or NRPN that should be mapped to the given
Chris@0 319 * input control port. If the given port should not have any MIDI
Chris@0 320 * controller mapped to it, the function should return DSSI_NONE.
Chris@0 321 * The behaviour of this function is undefined if the given port
Chris@0 322 * number does not correspond to an input control port. A plugin
Chris@0 323 * that does not want MIDI controllers mapped to ports at all may
Chris@0 324 * set this member NULL.
Chris@0 325 *
Chris@0 326 * Correct values can be got using the macros DSSI_CC(num) and
Chris@0 327 * DSSI_NRPN(num) as appropriate, and values can be combined using
Chris@0 328 * bitwise OR: e.g. DSSI_CC(23) | DSSI_NRPN(1069) means the port
Chris@0 329 * should respond to CC #23 and NRPN #1069.
Chris@0 330 *
Chris@0 331 * The host is responsible for doing proper scaling from MIDI
Chris@0 332 * controller and NRPN value ranges to port ranges according to
Chris@0 333 * the plugin's LADSPA port hints. Hosts should not deliver
Chris@0 334 * through run_synth any MIDI controller events that have already
Chris@0 335 * been mapped to control port values.
Chris@0 336 *
Chris@0 337 * A plugin should not attempt to request mappings from
Chris@0 338 * controllers 0 or 32 (MIDI Bank Select MSB and LSB).
Chris@0 339 */
Chris@0 340 int (*get_midi_controller_for_port)(LADSPA_Handle Instance,
Chris@0 341 unsigned long Port);
Chris@0 342
Chris@0 343 /**
Chris@0 344 * run_synth()
Chris@0 345 *
Chris@0 346 * This member is a function pointer that runs a synth for a
Chris@0 347 * block. This is identical in function to the LADSPA run()
Chris@0 348 * function, except that it also supplies events to the synth.
Chris@0 349 *
Chris@0 350 * A plugin may provide this function, run_multiple_synths() (see
Chris@0 351 * below), both, or neither (if it is not in fact a synth). A
Chris@0 352 * plugin that does not provide this function must set this member
Chris@0 353 * to NULL. Authors of synth plugins are encouraged to provide
Chris@0 354 * this function if at all possible.
Chris@0 355 *
Chris@0 356 * The Events pointer points to a block of EventCount ALSA
Chris@0 357 * sequencer events, which is used to communicate MIDI and related
Chris@0 358 * events to the synth. Each event is timestamped relative to the
Chris@0 359 * start of the block, (mis)using the ALSA "tick time" field as a
Chris@0 360 * frame count. The host is responsible for ensuring that events
Chris@0 361 * with differing timestamps are already ordered by time.
Chris@0 362 *
Chris@0 363 * See also the notes on activation, port connection etc in
Chris@0 364 * ladpsa.h, in the context of the LADSPA run() function.
Chris@0 365 *
Chris@0 366 * Note Events
Chris@0 367 * ~~~~~~~~~~~
Chris@0 368 * There are two minor requirements aimed at making the plugin
Chris@0 369 * writer's life as simple as possible:
Chris@0 370 *
Chris@0 371 * 1. A host must never send events of type SND_SEQ_EVENT_NOTE.
Chris@0 372 * Notes should always be sent as separate SND_SEQ_EVENT_NOTE_ON
Chris@0 373 * and NOTE_OFF events. A plugin should discard any one-point
Chris@0 374 * NOTE events it sees.
Chris@0 375 *
Chris@0 376 * 2. A host must not attempt to switch notes off by sending
Chris@0 377 * zero-velocity NOTE_ON events. It should always send true
Chris@0 378 * NOTE_OFFs. It is the host's responsibility to remap events in
Chris@0 379 * cases where an external MIDI source has sent it zero-velocity
Chris@0 380 * NOTE_ONs.
Chris@0 381 *
Chris@0 382 * Bank and Program Events
Chris@0 383 * ~~~~~~~~~~~~~~~~~~~~~~~
Chris@0 384 * Hosts must map MIDI Bank Select MSB and LSB (0 and 32)
Chris@0 385 * controllers and MIDI Program Change events onto the banks and
Chris@0 386 * programs specified by the plugin, using the DSSI select_program
Chris@0 387 * call. No host should ever deliver a program change or bank
Chris@0 388 * select controller to a plugin via run_synth.
Chris@0 389 */
Chris@0 390 void (*run_synth)(LADSPA_Handle Instance,
Chris@0 391 unsigned long SampleCount,
Chris@0 392 snd_seq_event_t *Events,
Chris@0 393 unsigned long EventCount);
Chris@0 394
Chris@0 395 /**
Chris@0 396 * run_synth_adding()
Chris@0 397 *
Chris@0 398 * This member is a function pointer that runs an instance of a
Chris@0 399 * synth for a block, adding its outputs to the values already
Chris@0 400 * present at the output ports. This is provided for symmetry
Chris@0 401 * with LADSPA run_adding(), and is equally optional. A plugin
Chris@0 402 * that does not provide it must set this member to NULL.
Chris@0 403 */
Chris@0 404 void (*run_synth_adding)(LADSPA_Handle Instance,
Chris@0 405 unsigned long SampleCount,
Chris@0 406 snd_seq_event_t *Events,
Chris@0 407 unsigned long EventCount);
Chris@0 408
Chris@0 409 /**
Chris@0 410 * run_multiple_synths()
Chris@0 411 *
Chris@0 412 * This member is a function pointer that runs multiple synth
Chris@0 413 * instances for a block. This is very similar to run_synth(),
Chris@0 414 * except that Instances, Events, and EventCounts each point to
Chris@0 415 * arrays that hold the LADSPA handles, event buffers, and
Chris@0 416 * event counts for each of InstanceCount instances. That is,
Chris@0 417 * Instances points to an array of InstanceCount pointers to
Chris@0 418 * DSSI plugin instantiations, Events points to an array of
Chris@0 419 * pointers to each instantiation's respective event list, and
Chris@0 420 * EventCounts points to an array containing each instantiation's
Chris@0 421 * respective event count.
Chris@0 422 *
Chris@0 423 * A host using this function must guarantee that ALL active
Chris@0 424 * instances of the plugin are represented in each call to the
Chris@0 425 * function -- that is, a host may not call run_multiple_synths()
Chris@0 426 * for some instances of a given plugin and then call run_synth()
Chris@0 427 * as well for others. 'All .. instances of the plugin' means
Chris@0 428 * every instance sharing the same LADSPA label and shared object
Chris@0 429 * (*.so) file (rather than every instance sharing the same *.so).
Chris@0 430 * 'Active' means any instance for which activate() has been called
Chris@0 431 * but deactivate() has not.
Chris@0 432 *
Chris@0 433 * A plugin may provide this function, run_synths() (see above),
Chris@0 434 * both, or neither (if it not in fact a synth). A plugin that
Chris@0 435 * does not provide this function must set this member to NULL.
Chris@0 436 * Plugin authors implementing run_multiple_synths are strongly
Chris@0 437 * encouraged to implement run_synth as well if at all possible,
Chris@0 438 * to aid simplistic hosts, even where it would be less efficient
Chris@0 439 * to use it.
Chris@0 440 */
Chris@0 441 void (*run_multiple_synths)(unsigned long InstanceCount,
Chris@0 442 LADSPA_Handle *Instances,
Chris@0 443 unsigned long SampleCount,
Chris@0 444 snd_seq_event_t **Events,
Chris@0 445 unsigned long *EventCounts);
Chris@0 446
Chris@0 447 /**
Chris@0 448 * run_multiple_synths_adding()
Chris@0 449 *
Chris@0 450 * This member is a function pointer that runs multiple synth
Chris@0 451 * instances for a block, adding each synth's outputs to the
Chris@0 452 * values already present at the output ports. This is provided
Chris@0 453 * for symmetry with both the DSSI run_multiple_synths() and LADSPA
Chris@0 454 * run_adding() functions, and is equally optional. A plugin
Chris@0 455 * that does not provide it must set this member to NULL.
Chris@0 456 */
Chris@0 457 void (*run_multiple_synths_adding)(unsigned long InstanceCount,
Chris@0 458 LADSPA_Handle *Instances,
Chris@0 459 unsigned long SampleCount,
Chris@0 460 snd_seq_event_t **Events,
Chris@0 461 unsigned long *EventCounts);
Chris@0 462
Chris@0 463 #if (DSSI_API_LEVEL > 1)
Chris@0 464
Chris@0 465 /**
Chris@0 466 * receive_host_descriptor()
Chris@0 467 *
Chris@0 468 * This member is a function pointer by which a host may provide
Chris@0 469 * a plugin with a pointer to its DSSI_Host_Descriptor. Hosts
Chris@0 470 * which provide host descriptor support must call this function
Chris@0 471 * once per plugin shared object file, before any calls to
Chris@0 472 * instantiate().
Chris@0 473 *
Chris@0 474 * NOTE: This field was added in version 2 of the DSSI API. Hosts
Chris@0 475 * supporting version 2 must not access this field in a plugin
Chris@0 476 * whose DSSI_API_Version is 1, and plugins supporting version 2
Chris@0 477 * should behave reasonably under hosts (of any version) which do
Chris@0 478 * not implement this function. A version 2 plugin that does not
Chris@0 479 * provide this function must set this member to NULL.
Chris@0 480 */
Chris@0 481 void (*receive_host_descriptor)(const DSSI_Host_Descriptor *Descriptor);
Chris@0 482
Chris@0 483 #endif
Chris@0 484
Chris@0 485 } DSSI_Descriptor;
Chris@0 486
Chris@0 487 struct _DSSI_Host_Descriptor {
Chris@0 488
Chris@0 489 /**
Chris@0 490 * DSSI_API_Version
Chris@0 491 *
Chris@0 492 * This member indicates the DSSI API level used by this host.
Chris@0 493 * All hosts must set this to 2. Hopefully, we'll get this right
Chris@0 494 * the first time, and this will never be needed.
Chris@0 495 */
Chris@0 496 int DSSI_API_Version;
Chris@0 497
Chris@0 498 /**
Chris@0 499 * request_transport_information()
Chris@0 500 *
Chris@0 501 * This member is a function pointer by which a plugin instance may
Chris@0 502 * request that a host begin providing transport information (if
Chris@0 503 * Request is non-zero), or notify the host that it no longer needs
Chris@0 504 * transport information (if Request is zero). Upon receiving a
Chris@0 505 * non-zero request, the host should return a pointer to a
Chris@0 506 * DSSI_Transport_Info structure if it is able to provide transport
Chris@0 507 * information, or NULL otherwise.
Chris@0 508 *
Chris@0 509 * Once a plugin instance has received a non-null transport
Chris@0 510 * information pointer, it may read from the structure at any time
Chris@0 511 * within the execution of an audio class function (see doc/RFC.txt).
Chris@0 512 * It should not consider the structure contents to be meaningful
Chris@0 513 * while within a instantiation or control class function. Also,
Chris@0 514 * since the validity of fields within the structure may change
Chris@0 515 * between each new invocation of an audio class function, a plugin
Chris@0 516 * instance must check the Valid field of the structure accordingly
Chris@0 517 * before using the structure's other contents.
Chris@0 518 *
Chris@0 519 * A host which does not support this function must set this member
Chris@0 520 * to NULL.
Chris@0 521 */
Chris@0 522 DSSI_Transport_Info *
Chris@0 523 (*request_transport_information)(LADSPA_Handle Instance,
Chris@0 524 int Request);
Chris@0 525
Chris@0 526 /**
Chris@0 527 * request_midi_send()
Chris@0 528 *
Chris@0 529 * This member is a function pointer that allows a plugin to
Chris@0 530 * request the ability to send MIDI events to the host.
Chris@0 531 *
Chris@0 532 * While the interpretation of plugin-generated MIDI events is
Chris@0 533 * host implementation specific, a mechanism exists by which a
Chris@0 534 * plugin may declare to the host the number of destination
Chris@0 535 * 'ports' and MIDI channels it can expect will be used in the
Chris@0 536 * plugin-generated events. Plugins which generate unchannelized
Chris@0 537 * MIDI should supply zero for both Ports and Channels, otherwise
Chris@0 538 * they should supply the maximum numbers for Ports and Channels
Chris@0 539 * they expect to use.
Chris@0 540 *
Chris@0 541 * A plugin instance must call this function during instantiate().
Chris@0 542 * [Sean says: this restriction seems reasonable to me, since
Chris@0 543 * the host may need to create output ports, etc., and instantiate()
Chris@0 544 * seems like a good place to do such things. I'm sure I haven't
Chris@0 545 * fully thought through all the details, though....]
Chris@0 546 *
Chris@0 547 * The host should return a non-zero value if it is able to
Chris@0 548 * provide MIDI send for the plugin instance, otherwise it should
Chris@0 549 * return zero, and the plugin instance may not subsequently call
Chris@0 550 * midi_send().
Chris@0 551 *
Chris@0 552 * A host which does not support the MIDI send function must set
Chris@0 553 * both this member and (*midi_send)() below to NULL.
Chris@0 554 */
Chris@0 555 int (*request_midi_send)(LADSPA_Handle Instance,
Chris@0 556 unsigned char Ports,
Chris@0 557 unsigned char Channels);
Chris@0 558
Chris@0 559 /**
Chris@0 560 * midi_send()
Chris@0 561 *
Chris@0 562 * This member is a function pointer by which a plugin actually
Chris@0 563 * sends MIDI events to the host (provided it has received a non-
Chris@0 564 * zero return from request_midi_send()). As in the run_synth()
Chris@0 565 * functions, the Event pointer points to a block of EventCount
Chris@0 566 * ALSA sequencer events. The dest.port and data.*.channel fields
Chris@0 567 * of each event are used to specify destination port and channel,
Chris@0 568 * respectively, when the plugin is supplying channelized events.
Chris@0 569 *
Chris@0 570 * A plugin may only call this function from within the execution
Chris@0 571 * of the audio class run_*() or select_program() functions. When
Chris@0 572 * called from a run_*() functions, the events are timestamped
Chris@0 573 * relative to the start of the block, (mis)using the ALSA "tick
Chris@0 574 * time" field as a frame count. The plugin is responsible for
Chris@0 575 * ensuring that events with differing timestamps are already
Chris@0 576 * ordered by time, and that timestamps across multiple calls to
Chris@0 577 * midi_send() from within the same run_*() invocation are
Chris@0 578 * monotonic. When midi_send() is called from within
Chris@0 579 * select_program(), the timestamps are ignored, and the events
Chris@0 580 * are considered to originate at the same frame time as the
Chris@0 581 * select_program() call, if such a timing can be considered
Chris@0 582 * meaningful.
Chris@0 583 *
Chris@0 584 * The memory pointed to by Event belongs to the plugin, and it is
Chris@0 585 * the host's responsibility to copy the events as needed before
Chris@0 586 * returning from the midi_send() call.
Chris@0 587 *
Chris@0 588 * A host which does not support the MIDI send function must set
Chris@0 589 * both this member and (*request_midi_send)() above to NULL.
Chris@0 590 */
Chris@0 591 void (*midi_send)(LADSPA_Handle Instance,
Chris@0 592 snd_seq_event_t *Event,
Chris@0 593 unsigned long EventCount);
Chris@0 594
Chris@0 595 /**
Chris@0 596 * . . . additional fields could follow here, possibly supporting:
Chris@0 597 *
Chris@0 598 * - a facility by which a plugin instance may request from a
Chris@0 599 * host a non-realtime thread in which to do off-line
Chris@0 600 * rendering, I/O, etc., thus (hopefully) avoiding the
Chris@0 601 * crashes that seem to occur when plugins create their own
Chris@0 602 * threads. I got this idea after noticing that ZynAddSubFX
Chris@0 603 * achieves its gorgeous textures while remaining very
Chris@0 604 * responsive by doing a lot of non-real-time rendering.
Chris@0 605 * Several other uses for it have been mentioned on the DSSI
Chris@0 606 * list; I forget what.
Chris@0 607 *
Chris@0 608 * - per-voice audio output
Chris@0 609 */
Chris@0 610
Chris@0 611 int (*request_non_rt_thread)(LADSPA_Handle Instance,
Chris@0 612 void (*RunFunction)(LADSPA_Handle Instance));
Chris@0 613 };
Chris@0 614
Chris@0 615 /**
Chris@0 616 * DSSI supports a plugin discovery method similar to that of LADSPA:
Chris@0 617 *
Chris@0 618 * - DSSI hosts may wish to locate DSSI plugin shared object files by
Chris@0 619 * searching the paths contained in the DSSI_PATH and LADSPA_PATH
Chris@0 620 * environment variables, if they are present. Both are expected
Chris@0 621 * to be colon-separated lists of directories to be searched (in
Chris@0 622 * order), and DSSI_PATH should be searched first if both variables
Chris@0 623 * are set.
Chris@0 624 *
Chris@0 625 * - Each shared object file containing DSSI plugins must include a
Chris@0 626 * function dssi_descriptor(), with the following function prototype
Chris@0 627 * and C-style linkage. Hosts may enumerate the plugin types
Chris@0 628 * available in the shared object file by repeatedly calling
Chris@0 629 * this function with successive Index values (beginning from 0),
Chris@0 630 * until a return value of NULL indicates no more plugin types are
Chris@0 631 * available. Each non-NULL return is the DSSI_Descriptor
Chris@0 632 * of a distinct plugin type.
Chris@0 633 */
Chris@0 634
Chris@0 635 const DSSI_Descriptor *dssi_descriptor(unsigned long Index);
Chris@0 636
Chris@0 637 typedef const DSSI_Descriptor *(*DSSI_Descriptor_Function)(unsigned long Index);
Chris@0 638
Chris@0 639 /*
Chris@0 640 * Macros to specify particular MIDI controllers in return values from
Chris@0 641 * get_midi_controller_for_port()
Chris@0 642 */
Chris@0 643
Chris@0 644 #define DSSI_CC_BITS 0x20000000
Chris@0 645 #define DSSI_NRPN_BITS 0x40000000
Chris@0 646
Chris@0 647 #define DSSI_NONE -1
Chris@0 648 #define DSSI_CONTROLLER_IS_SET(n) (DSSI_NONE != (n))
Chris@0 649
Chris@0 650 #define DSSI_CC(n) (DSSI_CC_BITS | (n))
Chris@0 651 #define DSSI_IS_CC(n) (DSSI_CC_BITS & (n))
Chris@0 652 #define DSSI_CC_NUMBER(n) ((n) & 0x7f)
Chris@0 653
Chris@0 654 #define DSSI_NRPN(n) (DSSI_NRPN_BITS | ((n) << 7))
Chris@0 655 #define DSSI_IS_NRPN(n) (DSSI_NRPN_BITS & (n))
Chris@0 656 #define DSSI_NRPN_NUMBER(n) (((n) >> 7) & 0x3fff)
Chris@0 657
Chris@0 658 #ifdef __cplusplus
Chris@0 659 }
Chris@0 660 #endif
Chris@0 661
Chris@0 662 #endif /* DSSI_INCLUDED */