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