-
Notifications
You must be signed in to change notification settings - Fork 281
/
z_libpd.h
579 lines (466 loc) · 23.9 KB
/
z_libpd.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
/*
* Copyright (c) 2010 Peter Brinkmann (peter.brinkmann@gmail.com)
* Copyright (c) 2012-2021 libpd team
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
* See https://github.com/libpd/libpd/wiki for documentation
*
*/
#ifndef __Z_LIBPD_H__
#define __Z_LIBPD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "m_pd.h"
/* initializing pd */
/// initialize libpd; it is safe to call this more than once
/// returns 0 on success or -1 if libpd was already initialized
/// note: sets SIGFPE handler to keep bad pd patches from crashing due to divide
/// by 0, set any custom handling after calling this function
EXTERN int libpd_init(void);
/// clear the libpd search path for abstractions and externals
/// note: this is called by libpd_init()
EXTERN void libpd_clear_search_path(void);
/// add a path to the libpd search paths
/// relative paths are relative to the current working directory
/// unlike desktop pd, *no* search paths are set by default (ie. extra)
EXTERN void libpd_add_to_search_path(const char *path);
/* opening patches */
/// open a patch by filename and parent dir path
/// returns an opaque patch handle pointer or NULL on failure
EXTERN void *libpd_openfile(const char *name, const char *dir);
/// close a patch by patch handle pointer
EXTERN void libpd_closefile(void *p);
/// get the $0 id of the patch handle pointer
/// returns $0 value or 0 if the patch is non-existent
EXTERN int libpd_getdollarzero(void *p);
/* audio processing */
/// return pd's fixed block size: the number of sample frames per 1 pd tick
EXTERN int libpd_blocksize(void);
/// initialize audio rendering
/// returns 0 on success
EXTERN int libpd_init_audio(int inChannels, int outChannels, int sampleRate);
/// process interleaved float samples from inBuffer -> libpd -> outBuffer
/// buffer sizes are based on # of ticks and channels where:
/// size = ticks * libpd_blocksize() * (in/out)channels
/// returns 0 on success
EXTERN int libpd_process_float(const int ticks,
const float *inBuffer, float *outBuffer);
/// process interleaved short samples from inBuffer -> libpd -> outBuffer
/// buffer sizes are based on # of ticks and channels where:
/// size = ticks * libpd_blocksize() * (in/out)channels
/// float samples are converted to short by multiplying by 32767 and casting,
/// so any values received from pd patches beyond -1 to 1 will result in garbage
/// note: for efficiency, does *not* clip input
/// returns 0 on success
EXTERN int libpd_process_short(const int ticks,
const short *inBuffer, short *outBuffer);
/// process interleaved double samples from inBuffer -> libpd -> outBuffer
/// buffer sizes are based on # of ticks and channels where:
/// size = ticks * libpd_blocksize() * (in/out)channels
/// note: only full-precision when compiled with PD_FLOATSIZE=64
/// returns 0 on success
EXTERN int libpd_process_double(const int ticks,
const double *inBuffer, double *outBuffer);
/// process non-interleaved float samples from inBuffer -> libpd -> outBuffer
/// copies buffer contents to/from libpd without striping
/// buffer sizes are based on a single tick and # of channels where:
/// size = libpd_blocksize() * (in/out)channels
/// returns 0 on success
EXTERN int libpd_process_raw(const float *inBuffer, float *outBuffer);
/// process non-interleaved short samples from inBuffer -> libpd -> outBuffer
/// copies buffer contents to/from libpd without striping
/// buffer sizes are based on a single tick and # of channels where:
/// size = libpd_blocksize() * (in/out)channels
/// float samples are converted to short by multiplying by 32767 and casting,
/// so any values received from pd patches beyond -1 to 1 will result in garbage
/// note: for efficiency, does *not* clip input
/// returns 0 on success
EXTERN int libpd_process_raw_short(const short *inBuffer, short *outBuffer);
/// process non-interleaved double samples from inBuffer -> libpd -> outBuffer
/// copies buffer contents to/from libpd without striping
/// buffer sizes are based on a single tick and # of channels where:
/// size = libpd_blocksize() * (in/out)channels
/// note: only full-precision when compiled with PD_FLOATSIZE=64
/// returns 0 on success
EXTERN int libpd_process_raw_double(const double *inBuffer, double *outBuffer);
/* array access */
/// get the size of an array by name
/// returns size or negative error code if non-existent
EXTERN int libpd_arraysize(const char *name);
/// (re)size an array by name; sizes <= 0 are clipped to 1
/// returns 0 on success or negative error code if non-existent
EXTERN int libpd_resize_array(const char *name, long size);
/// read n values from named src array and write into dest starting at an offset
/// note: performs no bounds checking on dest
/// returns 0 on success or a negative error code if the array is non-existent
/// or offset + n exceeds range of array
EXTERN int libpd_read_array(float *dest, const char *name, int offset, int n);
/// read n values from src and write into named dest array starting at an offset
/// note: performs no bounds checking on src
/// returns 0 on success or a negative error code if the array is non-existent
/// or offset + n exceeds range of array
EXTERN int libpd_write_array(const char *name, int offset,
const float *src, int n);
/// read n values from named src array and write into dest starting at an offset
/// note: performs no bounds checking on dest
/// note: only full-precision when compiled with PD_FLOATSIZE=64
/// returns 0 on success or a negative error code if the array is non-existent
/// or offset + n exceeds range of array
/// double-precision variant of libpd_read_array()
EXTERN int libpd_read_array_double(double *dest, const char *src,
int offset, int n);
/// read n values from src and write into named dest array starting at an offset
/// note: performs no bounds checking on src
/// note: only full-precision when compiled with PD_FLOATSIZE=64
/// returns 0 on success or a negative error code if the array is non-existent
/// or offset + n exceeds range of array
/// double-precision variant of libpd_write_array()
EXTERN int libpd_write_array_double(const char *dest, int offset,
const double *src, int n);
/* sending messages to pd */
/// send a bang to a destination receiver
/// ex: libpd_bang("foo") will send a bang to [s foo] on the next tick
/// returns 0 on success or -1 if receiver name is non-existent
EXTERN int libpd_bang(const char *recv);
/// send a float to a destination receiver
/// ex: libpd_float("foo", 1) will send a 1.0 to [s foo] on the next tick
/// returns 0 on success or -1 if receiver name is non-existent
EXTERN int libpd_float(const char *recv, float x);
/// send a double to a destination receiver
/// ex: libpd_double("foo", 1.1) will send a 1.1 to [s foo] on the next tick
/// note: only full-precision when compiled with PD_FLOATSIZE=64
/// returns 0 on success or -1 if receiver name is non-existent
EXTERN int libpd_double(const char *recv, double x);
/// send a symbol to a destination receiver
/// ex: libpd_symbol("foo", "bar") will send "bar" to [s foo] on the next tick
/// returns 0 on success or -1 if receiver name is non-existent
EXTERN int libpd_symbol(const char *recv, const char *symbol);
/* sending compound messages: sequenced function calls */
/// start composition of a new list or typed message of up to max element length
/// messages can be of a smaller length as max length is only an upper bound
/// note: no cleanup is required for unfinished messages
/// returns 0 on success or nonzero if the length is too large
EXTERN int libpd_start_message(int maxlen);
/// add a float to the current message in progress
EXTERN void libpd_add_float(float x);
/// add a double to the current message in progress
/// note: only full-precision when compiled with PD_FLOATSIZE=64
EXTERN void libpd_add_double(double x);
/// add a symbol to the current message in progress
EXTERN void libpd_add_symbol(const char *symbol);
/// finish current message and send as a list to a destination receiver
/// returns 0 on success or -1 if receiver name is non-existent
/// ex: send [list 1 2 bar( to [s foo] on the next tick with:
/// libpd_start_message(3);
/// libpd_add_float(1);
/// libpd_add_float(2);
/// libpd_add_symbol("bar");
/// libpd_finish_list("foo");
EXTERN int libpd_finish_list(const char *recv);
/// finish current message and send as a typed message to a destination receiver
/// note: typed message handling currently only supports up to 4 elements
/// internally, additional elements may be ignored
/// returns 0 on success or -1 if receiver name is non-existent
/// ex: send [; pd dsp 1( on the next tick with:
/// libpd_start_message(1);
/// libpd_add_float(1);
/// libpd_finish_message("pd", "dsp");
EXTERN int libpd_finish_message(const char *recv, const char *msg);
/* sending compound messages: atom array */
/// write a float value to the given atom
EXTERN void libpd_set_float(t_atom *a, float x);
/// write a double value to the given atom
/// note: only full-precision when compiled with PD_FLOATSIZE=64
EXTERN void libpd_set_double(t_atom *v, double x);
/// write a symbol value to the given atom
EXTERN void libpd_set_symbol(t_atom *a, const char *symbol);
/// send an atom array of a given length as a list to a destination receiver
/// returns 0 on success or -1 if receiver name is non-existent
/// ex: send [list 1 2 bar( to [r foo] on the next tick with:
/// t_atom v[3];
/// libpd_set_float(v, 1);
/// libpd_set_float(v + 1, 2);
/// libpd_set_symbol(v + 2, "bar");
/// libpd_list("foo", 3, v);
EXTERN int libpd_list(const char *recv, int argc, t_atom *argv);
/// send a atom array of a given length as a typed message to a destination
/// receiver, returns 0 on success or -1 if receiver name is non-existent
/// ex: send [; pd dsp 1( on the next tick with:
/// t_atom v[1];
/// libpd_set_float(v, 1);
/// libpd_message("pd", "dsp", 1, v);
EXTERN int libpd_message(const char *recv, const char *msg,
int argc, t_atom *argv);
/* receiving messages from pd */
/// subscribe to messages sent to a source receiver
/// ex: libpd_bind("foo") adds a "virtual" [r foo] which forwards messages to
/// the libpd message hooks
/// returns an opaque receiver pointer or NULL on failure
EXTERN void *libpd_bind(const char *recv);
/// unsubscribe and free a source receiver object created by libpd_bind()
EXTERN void libpd_unbind(void *p);
/// check if a source receiver object exists with a given name
/// returns 1 if the receiver exists, otherwise 0
EXTERN int libpd_exists(const char *recv);
/// print receive hook signature, s is the string to be printed
/// note: default behavior returns individual words and spaces:
/// line "hello 123" is received in 4 parts -> "hello", " ", "123\n"
typedef void (*t_libpd_printhook)(const char *s);
/// bang receive hook signature, recv is the source receiver name
typedef void (*t_libpd_banghook)(const char *recv);
/// float receive hook signature, recv is the source receiver name
typedef void (*t_libpd_floathook)(const char *recv, float x);
/// double receive hook signature, recv is the source receiver name
/// note: only full-precision when compiled with PD_FLOATSIZE=64
typedef void (*t_libpd_doublehook)(const char *recv, double x);
/// symbol receive hook signature, recv is the source receiver name
typedef void (*t_libpd_symbolhook)(const char *recv, const char *symbol);
/// list receive hook signature, recv is the source receiver name
/// argc is the list length and vector argv contains the list elements
/// which can be accessed using the atom accessor functions, ex:
/// int i;
/// for (i = 0; i < argc; i++) {
/// t_atom *a = &argv[n];
/// if (libpd_is_float(a)) {
/// float x = libpd_get_float(a);
/// // do something with float x
/// } else if (libpd_is_symbol(a)) {
/// char *s = libpd_get_symbol(a);
/// // do something with c string s
/// }
/// }
/// note: check for both float and symbol types as atom may also be a pointer
typedef void (*t_libpd_listhook)(const char *recv, int argc, t_atom *argv);
/// typed message hook signature, recv is the source receiver name and msg is
/// the typed message name: a message like [; foo bar 1 2 a b( will trigger a
/// function call like libpd_messagehook("foo", "bar", 4, argv)
/// argc is the list length and vector argv contains the
/// list elements which can be accessed using the atom accessor functions, ex:
/// int i;
/// for (i = 0; i < argc; i++) {
/// t_atom *a = &argv[n];
/// if (libpd_is_float(a)) {
/// float x = libpd_get_float(a);
/// // do something with float x
/// } else if (libpd_is_symbol(a)) {
/// char *s = libpd_get_symbol(a);
/// // do something with c string s
/// }
/// }
/// note: check for both float and symbol types as atom may also be a pointer
typedef void (*t_libpd_messagehook)(const char *recv, const char *msg,
int argc, t_atom *argv);
/// set the print receiver hook, prints to stdout by default
/// note: do not call this while DSP is running
EXTERN void libpd_set_printhook(const t_libpd_printhook hook);
/// set the bang receiver hook, NULL by default
/// note: do not call this while DSP is running
EXTERN void libpd_set_banghook(const t_libpd_banghook hook);
/// set the float receiver hook, NULL by default
/// note: avoid calling this while DSP is running
/// note: you can either have a float receiver hook, or a double receiver
/// hook (see below), but not both.
/// calling this, will automatically unset the double receiver hook
/// note: only full-precision when compiled with PD_FLOATSIZE=64
EXTERN void libpd_set_floathook(const t_libpd_floathook hook);
/// set the double receiver hook, NULL by default
/// note: avoid calling this while DSP is running
/// note: you can either have a double receiver hook, or a float receiver
/// hook (see above), but not both.
/// calling this, will automatically unset the float receiver hook
/// note: only full-precision when compiled with PD_FLOATSIZE=64
EXTERN void libpd_set_doublehook(const t_libpd_doublehook hook);
/// set the symbol receiver hook, NULL by default
/// note: do not call this while DSP is running
EXTERN void libpd_set_symbolhook(const t_libpd_symbolhook hook);
/// set the list receiver hook, NULL by default
/// note: do not call this while DSP is running
EXTERN void libpd_set_listhook(const t_libpd_listhook hook);
/// set the message receiver hook, NULL by default
/// note: do not call this while DSP is running
EXTERN void libpd_set_messagehook(const t_libpd_messagehook hook);
/// check if an atom is a float type: 0 or 1
/// note: no NULL check is performed
EXTERN int libpd_is_float(t_atom *a);
/// check if an atom is a symbol type: 0 or 1
/// note: no NULL check is performed
EXTERN int libpd_is_symbol(t_atom *a);
/// get the float value of an atom
/// note: no NULL or type checks are performed
EXTERN float libpd_get_float(t_atom *a);
/// returns the double value of an atom
/// note: no NULL or type checks are performed
/// note: only full-precision when compiled with PD_FLOATSIZE=64
EXTERN double libpd_get_double(t_atom *a);
/// returns the symbol value of an atom
/// note: no NULL or type checks are performed
EXTERN const char *libpd_get_symbol(t_atom *a);
/// increment to the next atom in an atom vector
/// returns next atom or NULL, assuming the atom vector is NULL-terminated
EXTERN t_atom *libpd_next_atom(t_atom *a);
/* sending MIDI messages to pd */
/// send a MIDI note on message to [notein] objects
/// channel is 0-indexed, pitch is 0-127, and velocity is 0-127
/// channels encode MIDI ports via: libpd_channel = pd_channel + 16 * pd_port
/// note: there is no note off message, send a note on with velocity = 0 instead
/// returns 0 on success or -1 if an argument is out of range
EXTERN int libpd_noteon(int channel, int pitch, int velocity);
/// send a MIDI control change message to [ctlin] objects
/// channel is 0-indexed, controller is 0-127, and value is 0-127
/// channels encode MIDI ports via: libpd_channel = pd_channel + 16 * pd_port
/// returns 0 on success or -1 if an argument is out of range
EXTERN int libpd_controlchange(int channel, int controller, int value);
/// send a MIDI program change message to [pgmin] objects
/// channel is 0-indexed and value is 0-127
/// channels encode MIDI ports via: libpd_channel = pd_channel + 16 * pd_port
/// returns 0 on success or -1 if an argument is out of range
EXTERN int libpd_programchange(int channel, int value);
/// send a MIDI pitch bend message to [bendin] objects
/// channel is 0-indexed and value is -8192-8192
/// channels encode MIDI ports via: libpd_channel = pd_channel + 16 * pd_port
/// note: [bendin] outputs 0-16383 while [bendout] accepts -8192-8192
/// returns 0 on success or -1 if an argument is out of range
EXTERN int libpd_pitchbend(int channel, int value);
/// send a MIDI after touch message to [touchin] objects
/// channel is 0-indexed and value is 0-127
/// channels encode MIDI ports via: libpd_channel = pd_channel + 16 * pd_port
/// returns 0 on success or -1 if an argument is out of range
EXTERN int libpd_aftertouch(int channel, int value);
/// send a MIDI poly after touch message to [polytouchin] objects
/// channel is 0-indexed, pitch is 0-127, and value is 0-127
/// channels encode MIDI ports via: libpd_channel = pd_channel + 16 * pd_port
/// returns 0 on success or -1 if an argument is out of range
EXTERN int libpd_polyaftertouch(int channel, int pitch, int value);
/// send a raw MIDI byte to [midiin] objects
/// port is 0-indexed and byte is 0-256
/// returns 0 on success or -1 if an argument is out of range
EXTERN int libpd_midibyte(int port, int byte);
/// send a raw MIDI byte to [sysexin] objects
/// port is 0-indexed and byte is 0-256
/// returns 0 on success or -1 if an argument is out of range
EXTERN int libpd_sysex(int port, int byte);
/// send a raw MIDI byte to [realtimein] objects
/// port is 0-indexed and byte is 0-256
/// returns 0 on success or -1 if an argument is out of range
EXTERN int libpd_sysrealtime(int port, int byte);
/* receiving MIDI messages from pd */
/// MIDI note on receive hook signature
/// channel is 0-indexed, pitch is 0-127, and value is 0-127
/// channels encode MIDI ports via: libpd_channel = pd_channel + 16 * pd_port
/// note: there is no note off message, note on w/ velocity = 0 is used instead
/// note: out of range values from pd are clamped
typedef void (*t_libpd_noteonhook)(int channel, int pitch, int velocity);
/// MIDI control change receive hook signature
/// channel is 0-indexed, controller is 0-127, and value is 0-127
/// channels encode MIDI ports via: libpd_channel = pd_channel + 16 * pd_port
/// note: out of range values from pd are clamped
typedef void (*t_libpd_controlchangehook)(int channel,
int controller, int value);
/// MIDI program change receive hook signature
/// channel is 0-indexed and value is 0-127
/// channels encode MIDI ports via: libpd_channel = pd_channel + 16 * pd_port
/// note: out of range values from pd are clamped
typedef void (*t_libpd_programchangehook)(int channel, int value);
/// MIDI pitch bend receive hook signature
/// channel is 0-indexed and value is -8192-8192
/// channels encode MIDI ports via: libpd_channel = pd_channel + 16 * pd_port
/// note: [bendin] outputs 0-16383 while [bendout] accepts -8192-8192
/// note: out of range values from pd are clamped
typedef void (*t_libpd_pitchbendhook)(int channel, int value);
/// MIDI after touch receive hook signature
/// channel is 0-indexed and value is 0-127
/// channels encode MIDI ports via: libpd_channel = pd_channel + 16 * pd_port
/// note: out of range values from pd are clamped
typedef void (*t_libpd_aftertouchhook)(int channel, int value);
/// MIDI poly after touch receive hook signature
/// channel is 0-indexed, pitch is 0-127, and value is 0-127
/// channels encode MIDI ports via: libpd_channel = pd_channel + 16 * pd_port
/// note: out of range values from pd are clamped
typedef void (*t_libpd_polyaftertouchhook)(int channel, int pitch, int value);
/// raw MIDI byte receive hook signature
/// port is 0-indexed and byte is 0-256
/// note: out of range values from pd are clamped
typedef void (*t_libpd_midibytehook)(int port, int byte);
/// set the MIDI note on hook to receive from [noteout] objects, NULL by default
/// note: do not call this while DSP is running
EXTERN void libpd_set_noteonhook(const t_libpd_noteonhook hook);
/// set the MIDI control change hook to receive from [ctlout] objects,
/// NULL by default
/// note: do not call this while DSP is running
EXTERN void libpd_set_controlchangehook(const t_libpd_controlchangehook hook);
/// set the MIDI program change hook to receive from [pgmout] objects,
/// NULL by default
/// note: do not call this while DSP is running
EXTERN void libpd_set_programchangehook(const t_libpd_programchangehook hook);
/// set the MIDI pitch bend hook to receive from [bendout] objects,
/// NULL by default
/// note: do not call this while DSP is running
EXTERN void libpd_set_pitchbendhook(const t_libpd_pitchbendhook hook);
/// set the MIDI after touch hook to receive from [touchout] objects,
/// NULL by default
/// note: do not call this while DSP is running
EXTERN void libpd_set_aftertouchhook(const t_libpd_aftertouchhook hook);
/// set the MIDI poly after touch hook to receive from [polytouchout] objects,
/// NULL by default
/// note: do not call this while DSP is running
EXTERN void libpd_set_polyaftertouchhook(const t_libpd_polyaftertouchhook hook);
/// set the raw MIDI byte hook to receive from [midiout] objects,
/// NULL by default
/// note: do not call this while DSP is running
EXTERN void libpd_set_midibytehook(const t_libpd_midibytehook hook);
/* GUI */
/// open the current patches within a pd vanilla GUI
/// requires the path to pd's main folder that contains bin/, tcl/, etc
/// for a macOS .app bundle: /path/to/Pd-#.#-#.app/Contents/Resources
/// returns 0 on success
EXTERN int libpd_start_gui(const char *path);
/// stop the pd vanilla GUI
EXTERN void libpd_stop_gui(void);
/// manually update and handle any GUI messages
/// this is called automatically when using a libpd_process function,
/// note: this also facilitates network message processing, etc so it can be
/// useful to call repeatedly when idle for more throughput
/// returns 1 if the poll found something, in which case it might be desirable
/// to poll again, up to some reasonable limit
EXTERN int libpd_poll_gui(void);
/* multiple instances */
/// create a new pd instance and set as current
/// note: use this in place of pdinstance_new()
/// returns new instance or NULL when libpd is not compiled with PDINSTANCE
EXTERN t_pdinstance *libpd_new_instance(void);
/// set the current pd instance
/// subsequent libpd calls will affect this instance only
/// note: use this in place of pd_setinstance()
/// does nothing when libpd is not compiled with PDINSTANCE
EXTERN void libpd_set_instance(t_pdinstance *pd);
/// free a pd instance and set main instance as current
/// note: use this in place of pdinstance_free()
/// does nothing when libpd is not compiled with PDINSTANCE
EXTERN void libpd_free_instance(t_pdinstance *pd);
/// get the current pd instance
EXTERN t_pdinstance *libpd_this_instance(void);
/// get the main pd instance, always valid
EXTERN t_pdinstance *libpd_main_instance(void);
/// get the number of pd instances, including the main instance
/// returns number or 1 when libpd is not compiled with PDINSTANCE
EXTERN int libpd_num_instances(void);
/// per-instance data free hook signature
typedef void (*t_libpd_freehook)(void *data);
/// set per-instance user data and optional free hook
/// note: if non-NULL, freehook is called by libpd_free_instance()
EXTERN void libpd_set_instancedata(void *data, t_libpd_freehook freehook);
/// get per-instance user data
EXTERN void* libpd_get_instancedata(void);
/* log level */
/// set verbose print state: 0 or 1
EXTERN void libpd_set_verbose(int verbose);
/// get the verbose print state: 0 or 1
EXTERN int libpd_get_verbose(void);
#ifdef __cplusplus
}
#endif
#endif