~ubuntu-branches/debian/sid/x42-plugins/sid

« back to all changes in this revision

Viewing changes to .pc/01-spelling.patch/robtk/jackwrap.c

  • Committer: Package Import Robot
  • Author(s): Jaromír Mikeš
  • Date: 2015-06-09 03:12:15 UTC
  • mfrom: (1.1.8)
  • Revision ID: package-import@ubuntu.com-20150609031215-2582mlqmpovk2g7m
Tags: 20150608-1
* Remove spelling patch - applied upstream.
* Remove GTK build-deps - not needed now.
* Improved description.
* Exclude mipsel from build.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* x42 jack wrapper / minimal LV2 host
2
 
 *
3
 
 * Copyright (C) 2012-2014 Robin Gareus
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License as published by
7
 
 * the Free Software Foundation; either version 2 of the License, or
8
 
 * (at your option) any later version.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 
 */
18
 
 
19
 
 
20
 
#ifndef UPDATE_FREQ_RATIO
21
 
#define UPDATE_FREQ_RATIO 60 // MAX # of audio-cycles per GUI-refresh
22
 
#endif
23
 
 
24
 
#ifndef JACK_AUTOCONNECT
25
 
#define JACK_AUTOCONNECT 0
26
 
#endif
27
 
 
28
 
#ifndef UI_UPDATE_FPS
29
 
#define UI_UPDATE_FPS 25
30
 
#endif
31
 
 
32
 
#ifndef MAXDELAY
33
 
#define MAXDELAY 192001 // delayline max possible delay
34
 
#endif
35
 
 
36
 
#ifndef MAXPERIOD
37
 
#define MAXPERIOD 8192 // delayline - max period size (jack-period)
38
 
#endif
39
 
 
40
 
///////////////////////////////////////////////////////////////////////////////
41
 
 
42
 
#ifndef _GNU_SOURCE
43
 
#define _GNU_SOURCE
44
 
#endif
45
 
 
46
 
#ifdef WIN32
47
 
#include <windows.h>
48
 
#include <pthread.h>
49
 
#define pthread_t //< override jack.h def
50
 
#endif
51
 
 
52
 
#ifdef __APPLE__
53
 
#include <CoreFoundation/CoreFoundation.h>
54
 
extern void rtk_osx_api_init(void);
55
 
extern void rtk_osx_api_terminate(void);
56
 
extern void rtk_osx_api_run(void);
57
 
extern void rtk_osx_api_err(const char *msg);
58
 
#endif
59
 
 
60
 
#include <stdio.h>
61
 
#include <errno.h>
62
 
#include <unistd.h>
63
 
#include <stdlib.h>
64
 
#include <string.h>
65
 
#include <math.h>
66
 
#include <time.h>
67
 
#include <assert.h>
68
 
 
69
 
#if (defined _WIN32 && defined RTK_STATIC_INIT)
70
 
#include <glib-object.h>
71
 
#endif
72
 
 
73
 
#ifndef _WIN32
74
 
#include <sys/mman.h>
75
 
#else
76
 
#include <sys/timeb.h>
77
 
#endif
78
 
 
79
 
#ifdef USE_WEAK_JACK
80
 
#include "weakjack/weak_libjack.h"
81
 
#else
82
 
#include <jack/jack.h>
83
 
#include <jack/ringbuffer.h>
84
 
#include <jack/midiport.h>
85
 
#endif
86
 
#undef pthread_t
87
 
 
88
 
#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
89
 
#include "lv2/lv2plug.in/ns/extensions/ui/ui.h"
90
 
#include "lv2/lv2plug.in/ns/ext/uri-map/uri-map.h"
91
 
#include "lv2/lv2plug.in/ns/ext/urid/urid.h"
92
 
#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
93
 
#include "lv2/lv2plug.in/ns/ext/atom/forge.h"
94
 
#include "lv2/lv2plug.in/ns/ext/midi/midi.h"
95
 
#include "lv2/lv2plug.in/ns/ext/time/time.h"
96
 
#include "lv2/lv2plug.in/ns/ext/worker/worker.h"
97
 
 
98
 
#include "./gl/xternalui.h"
99
 
 
100
 
#ifndef WIN32
101
 
#include <signal.h>
102
 
#include <pthread.h>
103
 
#endif
104
 
 
105
 
#define LV2_EXTERNAL_UI_RUN(ptr) (ptr)->run(ptr)
106
 
#define LV2_EXTERNAL_UI_SHOW(ptr) (ptr)->show(ptr)
107
 
#define LV2_EXTERNAL_UI_HIDE(ptr) (ptr)->hide(ptr)
108
 
 
109
 
#define nan NAN
110
 
 
111
 
static const LV2_Descriptor* plugin_dsp;
112
 
static const LV2UI_Descriptor *plugin_gui;
113
 
 
114
 
static LV2_Handle plugin_instance = NULL;
115
 
static LV2UI_Handle gui_instance = NULL;
116
 
 
117
 
static float  *plugin_ports_pre  = NULL;
118
 
static float  *plugin_ports_post = NULL;
119
 
 
120
 
static LV2_Atom_Sequence *atom_in = NULL;
121
 
static LV2_Atom_Sequence *atom_out = NULL;
122
 
 
123
 
static jack_port_t **input_port = NULL;
124
 
static jack_port_t **output_port = NULL;
125
 
 
126
 
static jack_port_t *midi_in = NULL;
127
 
static jack_port_t *midi_out = NULL;
128
 
 
129
 
static jack_client_t *j_client = NULL;
130
 
static uint32_t j_samplerate = 48000;
131
 
 
132
 
static int _freewheeling = 0;
133
 
 
134
 
struct transport_position {
135
 
        jack_nframes_t position;
136
 
        float          bpm;
137
 
        bool           rolling;
138
 
} j_transport = {0, 0, false};
139
 
 
140
 
static jack_ringbuffer_t *rb_ctrl_to_ui = NULL;
141
 
static jack_ringbuffer_t *rb_ctrl_from_ui = NULL;
142
 
static jack_ringbuffer_t *rb_atom_to_ui = NULL;
143
 
static jack_ringbuffer_t *rb_atom_from_ui = NULL;
144
 
 
145
 
static pthread_mutex_t gui_thread_lock = PTHREAD_MUTEX_INITIALIZER;
146
 
static pthread_cond_t  data_ready = PTHREAD_COND_INITIALIZER;
147
 
 
148
 
static uint32_t uri_midi_MidiEvent = 0;
149
 
static uint32_t uri_atom_Sequence = 0;
150
 
static uint32_t uri_atom_EventTransfer = 0;
151
 
 
152
 
static uint32_t uri_time_Position = 0;
153
 
static uint32_t uri_time_frame    = 0;
154
 
static uint32_t uri_time_speed    = 0;
155
 
static uint32_t uri_time_bar     = 0;
156
 
static uint32_t uri_time_barBeat = 0;
157
 
static uint32_t uri_time_beatUnit = 0;
158
 
static uint32_t uri_time_beatsPerBar = 0;
159
 
static uint32_t uri_time_beatsPerMinute = 0;
160
 
 
161
 
static char **urimap = NULL;
162
 
static uint32_t urimap_len = 0;
163
 
 
164
 
enum PortType {
165
 
        CONTROL_IN = 0,
166
 
        CONTROL_OUT,
167
 
        AUDIO_IN,
168
 
        AUDIO_OUT,
169
 
        MIDI_IN,
170
 
        MIDI_OUT,
171
 
        ATOM_IN,
172
 
        ATOM_OUT
173
 
};
174
 
 
175
 
struct DelayBuffer {
176
 
        jack_latency_range_t port_latency;
177
 
        int wanted_delay;
178
 
        int c_dly; // current delay
179
 
        int w_ptr;
180
 
        int r_ptr;
181
 
        float out_buffer[MAXPERIOD]; // TODO dynamically allocate, use jack-period
182
 
        float delay_buffer[MAXDELAY];
183
 
};
184
 
 
185
 
struct LV2Port {
186
 
        const char *name;
187
 
        enum PortType porttype;
188
 
        float val_default;
189
 
};
190
 
 
191
 
typedef struct _RtkLv2Description {
192
 
        const LV2_Descriptor* (*lv2_descriptor)(uint32_t index);
193
 
        const LV2UI_Descriptor* (*lv2ui_descriptor)(uint32_t index);
194
 
 
195
 
        const uint32_t dsp_descriptor_id;
196
 
        const uint32_t gui_descriptor_id;
197
 
        const char *plugin_human_id;
198
 
 
199
 
        const struct LV2Port *ports;
200
 
 
201
 
        const uint32_t nports_total;
202
 
        const uint32_t nports_audio_in;
203
 
        const uint32_t nports_audio_out;
204
 
        const uint32_t nports_midi_in;
205
 
        const uint32_t nports_midi_out;
206
 
        const uint32_t nports_atom_in;
207
 
        const uint32_t nports_atom_out;
208
 
        const uint32_t nports_ctrl;
209
 
        const uint32_t nports_ctrl_in;
210
 
        const uint32_t nports_ctrl_out;
211
 
        const uint32_t min_atom_bufsiz;
212
 
        const bool     send_time_info;
213
 
} RtkLv2Description;
214
 
 
215
 
static RtkLv2Description const *inst;
216
 
 
217
 
/* a simple state machine for this client */
218
 
static volatile enum {
219
 
        Run,
220
 
        Exit
221
 
} client_state = Run;
222
 
 
223
 
static struct lv2_external_ui_host extui_host;
224
 
static struct lv2_external_ui *extui = NULL;
225
 
 
226
 
static LV2UI_Controller controller = NULL;
227
 
 
228
 
static LV2_Atom_Forge lv2_forge;
229
 
static uint32_t *portmap_a_in;
230
 
static uint32_t *portmap_a_out;
231
 
static uint32_t *portmap_rctl;
232
 
static int      *portmap_ctrl;
233
 
static uint32_t  portmap_atom_to_ui = -1;
234
 
static uint32_t  portmap_atom_from_ui = -1;
235
 
 
236
 
static uint32_t uri_to_id(LV2_URI_Map_Callback_Data callback_data, const char* uri);
237
 
 
238
 
 
239
 
static jack_ringbuffer_t*    worker_requests = NULL;
240
 
static jack_ringbuffer_t*    worker_responses = NULL;
241
 
static pthread_t             worker_thread;
242
 
static pthread_mutex_t       worker_lock = PTHREAD_MUTEX_INITIALIZER;
243
 
static pthread_cond_t        worker_ready = PTHREAD_COND_INITIALIZER;
244
 
static LV2_Worker_Interface* worker_iface = NULL;
245
 
 
246
 
static struct DelayBuffer **delayline = NULL;
247
 
static uint32_t worst_capture_latency = 0;
248
 
static uint32_t plugin_latency = 0;
249
 
 
250
 
/******************************************************************************
251
 
 * Delayline for latency compensation
252
 
 */
253
 
#define FADE_LEN (16)
254
 
 
255
 
#define INCREMENT_PTRS \
256
 
                dly->r_ptr = (dly->r_ptr + 1) % MAXDELAY; \
257
 
                dly->w_ptr = (dly->w_ptr + 1) % MAXDELAY;
258
 
 
259
 
static float *
260
 
delay_port (struct DelayBuffer *dly, uint32_t n_samples, float *in)
261
 
{
262
 
        uint32_t pos = 0;
263
 
        const int delay = dly->wanted_delay;
264
 
        const float * const input = in;
265
 
        float* const output  = dly->out_buffer;
266
 
 
267
 
        if (dly->c_dly == delay && delay == 0) {
268
 
                // only copy data into buffer in case delay time changes
269
 
                for (; pos < n_samples; pos++) {
270
 
                        dly->delay_buffer[ dly->w_ptr ] = input[pos];
271
 
                        INCREMENT_PTRS;
272
 
                }
273
 
                return in;
274
 
        }
275
 
 
276
 
        // fade if delaytime changes
277
 
        if (dly->c_dly != delay) {
278
 
                const uint32_t fade_len = (n_samples >= FADE_LEN) ? FADE_LEN : n_samples / 2;
279
 
 
280
 
                // fade out
281
 
                for (; pos < fade_len; pos++) {
282
 
                        const float gain = (float)(fade_len - pos) / (float)fade_len;
283
 
                        dly->delay_buffer[ dly->w_ptr ] = input[pos];
284
 
                        output[pos] = dly->delay_buffer[ dly->r_ptr ] * gain;
285
 
                        INCREMENT_PTRS;
286
 
                }
287
 
 
288
 
                // update read pointer
289
 
                dly->r_ptr += dly->c_dly - delay;
290
 
                if (dly->r_ptr < 0) {
291
 
                        dly->r_ptr -= MAXDELAY * floor(dly->r_ptr / (float)MAXDELAY);
292
 
                }
293
 
 
294
 
                //printf("Delay changed %d -> %d\n", dly->c_dly, delay); // DEBUG
295
 
                dly->r_ptr = dly->r_ptr % MAXDELAY;
296
 
                dly->c_dly = delay;
297
 
 
298
 
                // fade in
299
 
                for (; pos < 2 * fade_len; pos++) {
300
 
                        const float gain = (float)(pos - fade_len) / (float)fade_len;
301
 
                        dly->delay_buffer[ dly->w_ptr ] = input[pos];
302
 
                        output[pos] = dly->delay_buffer[ dly->r_ptr ] * gain;
303
 
                        INCREMENT_PTRS;
304
 
                }
305
 
        }
306
 
 
307
 
        for (; pos < n_samples; pos++) {
308
 
                dly->delay_buffer[ dly->w_ptr ] = input[pos];
309
 
                output[pos] = dly->delay_buffer[ dly->r_ptr ];
310
 
                INCREMENT_PTRS;
311
 
        }
312
 
 
313
 
        return dly->out_buffer;
314
 
}
315
 
 
316
 
 
317
 
///////////////////////////
318
 
// GET INFO FROM LV2 TTL //
319
 
//     see lv2ttl2c      //
320
 
//    define _plugin     //
321
 
///////////////////////////
322
 
#include JACK_DESCRIPT ////
323
 
///////////////////////////
324
 
 
325
 
 
326
 
/******************************************************************************
327
 
 * JACK
328
 
 */
329
 
 
330
 
static int process (jack_nframes_t nframes, void *arg) {
331
 
        while (jack_ringbuffer_read_space(rb_ctrl_from_ui) >= sizeof(uint32_t) + sizeof(float)) {
332
 
                uint32_t idx;
333
 
                jack_ringbuffer_read(rb_ctrl_from_ui, (char*) &idx, sizeof(uint32_t));
334
 
                jack_ringbuffer_read(rb_ctrl_from_ui, (char*) &(plugin_ports_pre[idx]), sizeof(float));
335
 
        }
336
 
 
337
 
        /* Get Jack transport position */
338
 
        jack_position_t pos;
339
 
        const bool rolling = (jack_transport_query(j_client, &pos) == JackTransportRolling);
340
 
        const bool transport_changed = (rolling != j_transport.rolling
341
 
                        || pos.frame != j_transport.position
342
 
                        || ((pos.valid & JackPositionBBT) && (pos.beats_per_minute != j_transport.bpm)));
343
 
 
344
 
        /* atom buffers */
345
 
        if (inst->nports_atom_in > 0 || inst->nports_midi_in > 0) {
346
 
                /* start Atom sequence */
347
 
                atom_in->atom.type = uri_atom_Sequence;
348
 
                atom_in->atom.size = 8;
349
 
                LV2_Atom_Sequence_Body *body = &atom_in->body;
350
 
                body->unit = 0; // URID of unit of event time stamp LV2_ATOM__timeUnit ??
351
 
                body->pad  = 0; // unused
352
 
                uint8_t * seq = (uint8_t*) (body + 1);
353
 
 
354
 
                if (transport_changed && inst->send_time_info) {
355
 
                        uint8_t   pos_buf[256];
356
 
                        LV2_Atom* lv2_pos = (LV2_Atom*)pos_buf;
357
 
 
358
 
                        lv2_atom_forge_set_buffer(&lv2_forge, pos_buf, sizeof(pos_buf));
359
 
                        LV2_Atom_Forge* forge = &lv2_forge;
360
 
                        LV2_Atom_Forge_Frame frame;
361
 
#ifdef HAVE_LV2_1_8
362
 
                        lv2_atom_forge_object(&lv2_forge, &frame, 1, uri_time_Position);
363
 
#else
364
 
                        lv2_atom_forge_blank(&lv2_forge, &frame, 1, uri_time_Position);
365
 
#endif
366
 
                        lv2_atom_forge_property_head(forge, uri_time_frame, 0);
367
 
                        lv2_atom_forge_long(forge, pos.frame);
368
 
                        lv2_atom_forge_property_head(forge, uri_time_speed, 0);
369
 
                        lv2_atom_forge_float(forge, rolling ? 1.0 : 0.0);
370
 
                        if (pos.valid & JackPositionBBT) {
371
 
                                lv2_atom_forge_property_head(forge, uri_time_barBeat, 0);
372
 
                                lv2_atom_forge_float(
373
 
                                                forge, pos.beat - 1 + (pos.tick / pos.ticks_per_beat));
374
 
                                lv2_atom_forge_property_head(forge, uri_time_bar, 0);
375
 
                                lv2_atom_forge_long(forge, pos.bar - 1);
376
 
                                lv2_atom_forge_property_head(forge, uri_time_beatUnit, 0);
377
 
                                lv2_atom_forge_int(forge, pos.beat_type);
378
 
                                lv2_atom_forge_property_head(forge, uri_time_beatsPerBar, 0);
379
 
                                lv2_atom_forge_float(forge, pos.beats_per_bar);
380
 
                                lv2_atom_forge_property_head(forge, uri_time_beatsPerMinute, 0);
381
 
                                lv2_atom_forge_float(forge, pos.beats_per_minute);
382
 
                        }
383
 
 
384
 
                        uint32_t size = lv2_pos->size;
385
 
                        uint32_t padded_size = ((sizeof(LV2_Atom_Event) + size) +  7) & (~7);
386
 
 
387
 
                        if (inst->min_atom_bufsiz > padded_size) {
388
 
                                printf("send time..\n");
389
 
                                LV2_Atom_Event *aev = (LV2_Atom_Event *)seq;
390
 
                                aev->time.frames = 0;
391
 
                                aev->body.size   = size;
392
 
                                aev->body.type   = lv2_pos->type;
393
 
                                memcpy(LV2_ATOM_BODY(&aev->body), LV2_ATOM_BODY(lv2_pos), size);
394
 
                                atom_in->atom.size += padded_size;
395
 
                                seq +=  padded_size;
396
 
                        }
397
 
                }
398
 
                // TODO only if UI..?
399
 
                while (jack_ringbuffer_read_space(rb_atom_from_ui) > sizeof(LV2_Atom)) {
400
 
                        LV2_Atom a;
401
 
                        jack_ringbuffer_read(rb_atom_from_ui, (char *) &a, sizeof(LV2_Atom));
402
 
                        uint32_t padded_size = atom_in->atom.size + a.size + sizeof(int64_t);
403
 
                        if (inst->min_atom_bufsiz > padded_size) {
404
 
                                memset(seq, 0, sizeof(int64_t)); // LV2_Atom_Event->time
405
 
                                seq += sizeof(int64_t);
406
 
                                jack_ringbuffer_read(rb_atom_from_ui, (char *) seq, a.size);
407
 
                                seq += a.size;
408
 
                                atom_in->atom.size += a.size + sizeof(int64_t);
409
 
                        }
410
 
                }
411
 
                if (inst->nports_midi_in > 0) {
412
 
                        /* inject midi events */
413
 
                        void* buf = jack_port_get_buffer(midi_in, nframes);
414
 
                        for (uint32_t i = 0; i < jack_midi_get_event_count(buf); ++i) {
415
 
                                jack_midi_event_t ev;
416
 
                                jack_midi_event_get(&ev, buf, i);
417
 
 
418
 
                                uint32_t size = ev.size;
419
 
                                uint32_t padded_size = ((sizeof(LV2_Atom_Event) + size) +  7) & (~7);
420
 
 
421
 
                                if (inst->min_atom_bufsiz > padded_size) {
422
 
                                        LV2_Atom_Event *aev = (LV2_Atom_Event *)seq;
423
 
                                        aev->time.frames = ev.time;
424
 
                                        aev->body.size  = size;
425
 
                                        aev->body.type  = uri_midi_MidiEvent;
426
 
                                        memcpy(LV2_ATOM_BODY(&aev->body), ev.buffer, size);
427
 
                                        atom_in->atom.size += padded_size;
428
 
                                        seq += padded_size;
429
 
                                }
430
 
                        }
431
 
                }
432
 
        }
433
 
 
434
 
        if (inst->nports_atom_out > 0 || inst->nports_midi_out > 0) {
435
 
                atom_out->atom.type = 0;
436
 
                atom_out->atom.size = inst->min_atom_bufsiz;
437
 
        }
438
 
 
439
 
        /* make a backup copy, to see what was changed */
440
 
        memcpy(plugin_ports_post, plugin_ports_pre, inst->nports_ctrl * sizeof(float));
441
 
 
442
 
        /* expected transport state in next cycle */
443
 
        j_transport.position = rolling ? pos.frame + nframes : pos.frame;
444
 
        j_transport.bpm      = pos.beats_per_minute;
445
 
        j_transport.rolling  = rolling;
446
 
 
447
 
        /* [re] connect jack audio buffers */
448
 
        for (uint32_t i=0 ; i < inst->nports_audio_out; i++) {
449
 
                plugin_dsp->connect_port(plugin_instance, portmap_a_out[i], jack_port_get_buffer (output_port[i], nframes));
450
 
        }
451
 
 
452
 
        for (uint32_t i=0; i < inst->nports_audio_in; i++) {
453
 
                delayline[i]->wanted_delay = worst_capture_latency - delayline[i]->port_latency.max;
454
 
                plugin_dsp->connect_port(
455
 
                                plugin_instance, portmap_a_in[i],
456
 
                                delay_port(delayline[i], nframes, (float*) jack_port_get_buffer (input_port[i], nframes))
457
 
                                );
458
 
        }
459
 
 
460
 
        /* run the plugin */
461
 
        plugin_dsp->run(plugin_instance, nframes);
462
 
 
463
 
        /* handle worker emit response  - may amend Atom seq... */
464
 
        if (worker_responses) {
465
 
                uint32_t read_space = jack_ringbuffer_read_space(worker_responses);
466
 
                while (read_space) {
467
 
                        uint32_t size = 0;
468
 
                        char worker_response[4096];
469
 
                        jack_ringbuffer_read(worker_responses, (char*)&size, sizeof(size));
470
 
                        jack_ringbuffer_read(worker_responses, worker_response, size);
471
 
                        worker_iface->work_response(plugin_instance, size, worker_response);
472
 
                        read_space -= sizeof(size) + size;
473
 
                }
474
 
        }
475
 
 
476
 
        /* create port-events for change values */
477
 
        // TODO only if UI..?
478
 
        for (uint32_t p = 0; p < inst->nports_ctrl; p++) {
479
 
                if (inst->ports[portmap_rctl[p]].porttype != CONTROL_OUT) continue;
480
 
 
481
 
                if (plugin_ports_pre[p] != plugin_ports_post[p]) {
482
 
#if 0
483
 
                        if (TODO this port reportsLatency) {
484
 
                                plugin_latency = rintf(plugin_ports_pre[p]);
485
 
                                jack_recompute_total_latencies(j_client);
486
 
                        }
487
 
#endif
488
 
                        if (jack_ringbuffer_write_space(rb_ctrl_to_ui) >= sizeof(uint32_t) + sizeof(float)) {
489
 
                                jack_ringbuffer_write(rb_ctrl_to_ui, (char *) &portmap_rctl[p], sizeof(uint32_t));
490
 
                                jack_ringbuffer_write(rb_ctrl_to_ui, (char *) &plugin_ports_pre[p], sizeof(float));
491
 
                        }
492
 
                }
493
 
        }
494
 
 
495
 
        if (inst->nports_midi_out > 0) {
496
 
                void* buf = jack_port_get_buffer(midi_out, nframes);
497
 
                jack_midi_clear_buffer(buf);
498
 
        }
499
 
 
500
 
        /* Atom sequence port-events */
501
 
        if (inst->nports_atom_out + inst->nports_midi_out > 0 && atom_out->atom.size > sizeof(LV2_Atom)) {
502
 
                // TODO only if UI..?
503
 
                if (jack_ringbuffer_write_space(rb_atom_to_ui) >= atom_out->atom.size + 2 * sizeof(LV2_Atom)) {
504
 
                        LV2_Atom a = {atom_out->atom.size + (uint32_t) sizeof(LV2_Atom), 0};
505
 
                        jack_ringbuffer_write(rb_atom_to_ui, (char *) &a, sizeof(LV2_Atom));
506
 
                        jack_ringbuffer_write(rb_atom_to_ui, (char *) atom_out, a.size);
507
 
                }
508
 
 
509
 
                if (inst->nports_midi_out) {
510
 
                        void* buf = jack_port_get_buffer(midi_out, nframes);
511
 
                        LV2_Atom_Event const* ev = (LV2_Atom_Event const*)((&(atom_out)->body) + 1); // lv2_atom_sequence_begin
512
 
                        while((const uint8_t*)ev < ((const uint8_t*) &(atom_out)->body + (atom_out)->atom.size)) {
513
 
                                if (ev->body.type == uri_midi_MidiEvent) {
514
 
                                        jack_midi_event_write(buf, ev->time.frames, (const uint8_t*)(ev+1), ev->body.size);
515
 
                                }
516
 
                                ev = (LV2_Atom_Event const*) /* lv2_atom_sequence_next() */
517
 
                                        ((const uint8_t*)ev + sizeof(LV2_Atom_Event) + ((ev->body.size + 7) & ~7));
518
 
                        }
519
 
                }
520
 
        }
521
 
 
522
 
        /* signal worker end of process run */
523
 
        if (worker_iface && worker_iface->end_run) {
524
 
                worker_iface->end_run(plugin_instance);
525
 
        }
526
 
 
527
 
        /* wake up UI */
528
 
        if (jack_ringbuffer_read_space(rb_ctrl_to_ui) > sizeof(uint32_t) + sizeof(float)
529
 
                        || jack_ringbuffer_read_space(rb_atom_to_ui) > sizeof(LV2_Atom)
530
 
                        ) {
531
 
                if (pthread_mutex_trylock (&gui_thread_lock) == 0) {
532
 
                        pthread_cond_signal (&data_ready);
533
 
                        pthread_mutex_unlock (&gui_thread_lock);
534
 
                }
535
 
        }
536
 
        return 0;
537
 
}
538
 
 
539
 
 
540
 
static void jack_shutdown (void *arg) {
541
 
        fprintf(stderr,"recv. shutdown request from jackd.\n");
542
 
        client_state=Exit;
543
 
        pthread_cond_signal (&data_ready);
544
 
}
545
 
 
546
 
static int jack_graph_order_cb (void *arg) {
547
 
        worst_capture_latency = 0;
548
 
        for (uint32_t i = 0; i < inst->nports_audio_in; i++) {
549
 
                jack_port_get_latency_range(input_port[i], JackCaptureLatency, &(delayline[i]->port_latency));
550
 
                if (delayline[i]->port_latency.max > worst_capture_latency) {
551
 
                        worst_capture_latency = delayline[i]->port_latency.max;
552
 
                }
553
 
        }
554
 
        return 0;
555
 
}
556
 
 
557
 
static void jack_latency_cb (jack_latency_callback_mode_t mode, void *arg) {
558
 
        // assume 1 -> 1 map
559
 
        // TODO add systemic latency of plugin (currently no robtk plugins add latency)
560
 
        jack_graph_order_cb(NULL); // update worst-case latency, delayline alignment
561
 
        if (mode == JackCaptureLatency) {
562
 
                for (uint32_t i = 0; i < inst->nports_audio_out; i++) {
563
 
                        jack_latency_range_t r;
564
 
                        if (i < inst->nports_audio_in) {
565
 
                                const uint32_t port_delay = worst_capture_latency - delayline[i]->port_latency.max;
566
 
                                jack_port_get_latency_range(input_port[i], JackCaptureLatency, &r);
567
 
                                r.min += port_delay;
568
 
                                r.max += port_delay;
569
 
                        } else {
570
 
                                r.min = r.max = 0;
571
 
                        }
572
 
                        r.min += plugin_latency;
573
 
                        r.max += plugin_latency;
574
 
                        jack_port_set_latency_range(output_port[i], JackCaptureLatency, &r);
575
 
                }
576
 
        } else { // JackPlaybackLatency
577
 
                for (uint32_t i = 0; i < inst->nports_audio_in; i++) {
578
 
                        const uint32_t port_delay = worst_capture_latency - delayline[i]->port_latency.max;
579
 
                        jack_latency_range_t r;
580
 
                        if (i < inst->nports_audio_out) {
581
 
                                jack_port_get_latency_range(output_port[i], JackPlaybackLatency, &r);
582
 
                        } else {
583
 
                                r.min = r.max = 0;
584
 
                        }
585
 
                        r.min += port_delay + plugin_latency;
586
 
                        r.max += port_delay + plugin_latency;
587
 
                        jack_port_set_latency_range(input_port[i], JackPlaybackLatency, &r);
588
 
                }
589
 
        }
590
 
}
591
 
 
592
 
static void jack_freewheel_cb (int onoff, void *arg) {
593
 
        _freewheeling = onoff;
594
 
}
595
 
 
596
 
static int init_jack(const char *client_name) {
597
 
        jack_status_t status;
598
 
        j_client = jack_client_open (client_name, JackNoStartServer, &status);
599
 
        if (j_client == NULL) {
600
 
                fprintf (stderr, "jack_client_open() failed, status = 0x%2.0x\n", status);
601
 
                if (status & JackServerFailed) {
602
 
                        fprintf (stderr, "Unable to connect to JACK server\n");
603
 
                }
604
 
                return (-1);
605
 
        }
606
 
        if (status & JackServerStarted) {
607
 
                fprintf (stderr, "JACK server started\n");
608
 
        }
609
 
        if (status & JackNameNotUnique) {
610
 
                client_name = jack_get_client_name(j_client);
611
 
                fprintf (stderr, "jack-client name: `%s'\n", client_name);
612
 
        }
613
 
 
614
 
        jack_set_process_callback (j_client, process, 0);
615
 
        jack_set_graph_order_callback (j_client, jack_graph_order_cb, 0);
616
 
        jack_set_latency_callback(j_client, jack_latency_cb, 0);
617
 
        jack_set_freewheel_callback(j_client, jack_freewheel_cb, 0);
618
 
 
619
 
#ifndef WIN32
620
 
        jack_on_shutdown (j_client, jack_shutdown, NULL);
621
 
#endif
622
 
        j_samplerate=jack_get_sample_rate (j_client);
623
 
        return (0);
624
 
}
625
 
 
626
 
static int jack_portsetup(void) {
627
 
        /* Allocate data structures that depend on the number of ports. */
628
 
        input_port = (jack_port_t **) malloc (sizeof (jack_port_t *) * inst->nports_audio_in);
629
 
        delayline = (struct DelayBuffer **) calloc (inst->nports_audio_in, sizeof (struct DelayBuffer *));
630
 
 
631
 
        for (uint32_t i = 0; i < inst->nports_audio_in; i++) {
632
 
                if ((input_port[i] = jack_port_register (j_client,
633
 
                                                inst->ports[portmap_a_in[i]].name,
634
 
                                                JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)) == 0) {
635
 
                        fprintf (stderr, "cannot register input port \"%s\"!\n", inst->ports[portmap_a_in[i]].name);
636
 
                        return (-1);
637
 
                }
638
 
                delayline[i] = (struct DelayBuffer *) calloc (1, sizeof (struct DelayBuffer));
639
 
        }
640
 
 
641
 
        output_port = (jack_port_t **) malloc (sizeof (jack_port_t *) * inst->nports_audio_out);
642
 
 
643
 
        for (uint32_t i = 0; i < inst->nports_audio_out; i++) {
644
 
                if ((output_port[i] = jack_port_register (j_client,
645
 
                                                inst->ports[portmap_a_out[i]].name,
646
 
                                                JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) == 0) {
647
 
                        fprintf (stderr, "cannot register output port \"%s\"!\n", inst->ports[portmap_a_out[i]].name);
648
 
                        return (-1);
649
 
                }
650
 
        }
651
 
 
652
 
        if (inst->nports_midi_in){
653
 
                if ((midi_in = jack_port_register (j_client,
654
 
                                                inst->ports[portmap_atom_from_ui].name,
655
 
                                                JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0)) == 0) {
656
 
                        fprintf (stderr, "cannot register midi input port \"%s\"!\n", inst->ports[portmap_atom_from_ui].name);
657
 
                        return (-1);
658
 
                }
659
 
        }
660
 
 
661
 
        if (inst->nports_midi_out){
662
 
                if ((midi_out = jack_port_register (j_client,
663
 
                                                inst->ports[portmap_atom_to_ui].name,
664
 
                                                JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0)) == 0) {
665
 
                        fprintf (stderr, "cannot register midi ouput port \"%s\"!\n", inst->ports[portmap_atom_to_ui].name);
666
 
                        return (-1);
667
 
                }
668
 
        }
669
 
        jack_graph_order_cb (NULL); // query port latencies
670
 
        jack_recompute_total_latencies(j_client);
671
 
        return (0);
672
 
}
673
 
 
674
 
static void jack_portconnect(int which) {
675
 
 
676
 
        if (which & 1) { // connect audio input(s)
677
 
                const char **ports = jack_get_ports(j_client, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput|JackPortIsPhysical);
678
 
                for (uint32_t i = 0; i < inst->nports_audio_in && ports && ports[i]; i++) {
679
 
                        if (jack_connect (j_client, jack_port_name (input_port[i]), ports[i]))
680
 
                                break;
681
 
                }
682
 
                if (ports) { jack_free(ports); }
683
 
        }
684
 
 
685
 
        if (which & 2) { // connect audio outputs(s)
686
 
                const char **ports = jack_get_ports(j_client, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput|JackPortIsPhysical);
687
 
                for (uint32_t i = 0; i < inst->nports_audio_out && ports && ports[i]; i++) {
688
 
                        if (jack_connect (j_client, jack_port_name (output_port[i]), ports[i]))
689
 
                                break;
690
 
                }
691
 
                if (ports) { jack_free(ports); }
692
 
        }
693
 
 
694
 
        if ((which & 4) && midi_in) { // midi in
695
 
                const char **ports = jack_get_ports(j_client, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput|JackPortIsPhysical);
696
 
                if (ports && ports[0]) {
697
 
                        jack_connect (j_client, jack_port_name (midi_in), ports[0]);
698
 
                }
699
 
                if (ports) { jack_free(ports); }
700
 
        }
701
 
 
702
 
        if ((which & 8) && midi_out) { // midi out
703
 
                const char **ports = jack_get_ports(j_client, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput|JackPortIsPhysical);
704
 
                if (ports && ports[0]) {
705
 
                        jack_connect (j_client, jack_port_name (midi_out), ports[0]);
706
 
                }
707
 
                if (ports) { jack_free(ports); }
708
 
        }
709
 
 
710
 
}
711
 
 
712
 
/******************************************************************************
713
 
 * LV2
714
 
 */
715
 
 
716
 
static uint32_t uri_to_id(LV2_URI_Map_Callback_Data callback_data, const char* uri) {
717
 
        for (uint32_t i=0; i < urimap_len; ++i) {
718
 
                if (!strcmp(urimap[i], uri)) {
719
 
                        //printf("Found mapped URI '%s' -> %d\n", uri, i);
720
 
                        return i;
721
 
                }
722
 
        }
723
 
        //printf("map URI '%s' -> %d\n", uri, urimap_len);
724
 
        urimap = (char**) realloc(urimap, (urimap_len + 1) * sizeof(char*));
725
 
        urimap[urimap_len] = strdup(uri);
726
 
        return urimap_len++;
727
 
}
728
 
 
729
 
static void free_uri_map() {
730
 
        for (uint32_t i=0; i < urimap_len; ++i) {
731
 
                free(urimap[i]);
732
 
        }
733
 
        free(urimap);
734
 
}
735
 
 
736
 
static void write_function(
737
 
                LV2UI_Controller controller,
738
 
                uint32_t         port_index,
739
 
                uint32_t         buffer_size,
740
 
                uint32_t         port_protocol,
741
 
                const void*      buffer) {
742
 
 
743
 
        if (buffer_size == 0) return;
744
 
 
745
 
        if (port_protocol != 0) {
746
 
                if (jack_ringbuffer_write_space(rb_atom_from_ui) >= buffer_size + sizeof(LV2_Atom)) {
747
 
                        LV2_Atom a = {buffer_size, 0};
748
 
                        jack_ringbuffer_write(rb_atom_from_ui, (char *) &a, sizeof(LV2_Atom));
749
 
                        jack_ringbuffer_write(rb_atom_from_ui, (char *) buffer, buffer_size);
750
 
                }
751
 
                return;
752
 
        }
753
 
        if (buffer_size != sizeof(float)) {
754
 
                fprintf(stderr, "LV2Host: write_function() unsupported buffer\n");
755
 
                return;
756
 
        }
757
 
        if (port_index < inst->nports_total && portmap_ctrl[port_index] < 0) {
758
 
                fprintf(stderr, "LV2Host: write_function() unmapped port\n");
759
 
                return;
760
 
        }
761
 
        if (jack_ringbuffer_write_space(rb_ctrl_from_ui) >= sizeof(uint32_t) + sizeof(float)) {
762
 
                jack_ringbuffer_write(rb_ctrl_from_ui, (char *) &portmap_ctrl[port_index], sizeof(uint32_t));
763
 
                jack_ringbuffer_write(rb_ctrl_from_ui, (char *) buffer, sizeof(float));
764
 
        }
765
 
}
766
 
 
767
 
// LV2 Worker
768
 
 
769
 
static LV2_Worker_Status
770
 
lv2_worker_respond(LV2_Worker_Respond_Handle unused,
771
 
                   uint32_t                  size,
772
 
                   const void*               data)
773
 
{
774
 
        jack_ringbuffer_write(worker_responses, (const char*)&size, sizeof(size));
775
 
        jack_ringbuffer_write(worker_responses, (const char*)data, size);
776
 
        return LV2_WORKER_SUCCESS;
777
 
}
778
 
 
779
 
 
780
 
static void* worker_func(void* data) {
781
 
        pthread_mutex_lock (&worker_lock);
782
 
        while (1) {
783
 
                char buf[4096];
784
 
                uint32_t size = 0;
785
 
 
786
 
                if (jack_ringbuffer_read_space(worker_requests) <= sizeof(size)) {
787
 
                        pthread_cond_wait(&worker_ready, &worker_lock);
788
 
                }
789
 
 
790
 
                if (client_state == Exit) break;
791
 
 
792
 
                jack_ringbuffer_read(worker_requests, (char*)&size, sizeof(size));
793
 
 
794
 
                if (size > 4096) {
795
 
                        fprintf(stderr, "Worker information is too large. Abort.\n");
796
 
                        break;
797
 
                }
798
 
 
799
 
                jack_ringbuffer_read(worker_requests, buf, size);
800
 
                worker_iface->work(plugin_instance, lv2_worker_respond, NULL, size, buf);
801
 
        }
802
 
        pthread_mutex_unlock (&worker_lock);
803
 
        return NULL;
804
 
}
805
 
 
806
 
static void worker_init() {
807
 
        worker_requests  = jack_ringbuffer_create(4096);
808
 
        worker_responses = jack_ringbuffer_create(4096);
809
 
        jack_ringbuffer_mlock(worker_requests);
810
 
        jack_ringbuffer_mlock(worker_responses);
811
 
        pthread_create(&worker_thread, NULL, worker_func, NULL);
812
 
}
813
 
 
814
 
static LV2_Worker_Status
815
 
lv2_worker_schedule(LV2_Worker_Schedule_Handle unused,
816
 
                    uint32_t                   size,
817
 
                    const void*                data)
818
 
{
819
 
        if (_freewheeling) {
820
 
                worker_iface->work(plugin_instance, lv2_worker_respond, NULL, size, data);
821
 
                return LV2_WORKER_SUCCESS;
822
 
        }
823
 
        assert(worker_requests);
824
 
        jack_ringbuffer_write(worker_requests, (const char*)&size, sizeof(size));
825
 
        jack_ringbuffer_write(worker_requests, (const char*)data, size);
826
 
        if (pthread_mutex_trylock (&worker_lock) == 0) {
827
 
                pthread_cond_signal (&worker_ready);
828
 
                pthread_mutex_unlock (&worker_lock);
829
 
        }
830
 
        return LV2_WORKER_SUCCESS;
831
 
}
832
 
 
833
 
/******************************************************************************
834
 
 * MAIN
835
 
 */
836
 
 
837
 
static void cleanup(int sig) {
838
 
        if (j_client) {
839
 
                jack_client_close (j_client);
840
 
                j_client=NULL;
841
 
        }
842
 
 
843
 
        if (worker_requests) {
844
 
                pthread_mutex_lock (&worker_lock);
845
 
                pthread_cond_signal (&worker_ready);
846
 
                pthread_mutex_unlock (&worker_lock);
847
 
 
848
 
                pthread_join(worker_thread, NULL);
849
 
 
850
 
                jack_ringbuffer_free(worker_requests);
851
 
                jack_ringbuffer_free(worker_responses);
852
 
        }
853
 
 
854
 
        if (plugin_dsp && plugin_instance && plugin_dsp->deactivate) {
855
 
                plugin_dsp->deactivate(plugin_instance);
856
 
        }
857
 
        if (plugin_gui && gui_instance && plugin_gui->cleanup) {
858
 
                plugin_gui->cleanup(gui_instance);
859
 
        }
860
 
        if (plugin_dsp && plugin_instance && plugin_dsp->cleanup) {
861
 
                plugin_dsp->cleanup(plugin_instance);
862
 
        }
863
 
 
864
 
        jack_ringbuffer_free(rb_ctrl_to_ui);
865
 
        jack_ringbuffer_free(rb_ctrl_from_ui);
866
 
 
867
 
        jack_ringbuffer_free(rb_atom_to_ui);
868
 
        jack_ringbuffer_free(rb_atom_from_ui);
869
 
 
870
 
        free(input_port);
871
 
        free(output_port);
872
 
 
873
 
        if (delayline) {
874
 
                for (uint32_t i = 0; i < inst->nports_audio_in; i++) {
875
 
                        free(delayline[i]);
876
 
                }
877
 
        }
878
 
        free(delayline);
879
 
 
880
 
        free(plugin_ports_pre);
881
 
        free(plugin_ports_post);
882
 
        free(portmap_a_in);
883
 
        free(portmap_a_out);
884
 
        free(portmap_ctrl);
885
 
        free(portmap_rctl);
886
 
        free_uri_map();
887
 
        fprintf(stderr, "bye.\n");
888
 
}
889
 
 
890
 
static void run_one(LV2_Atom_Sequence *data) {
891
 
 
892
 
        while (jack_ringbuffer_read_space(rb_ctrl_to_ui) >= sizeof(uint32_t) + sizeof(float)) {
893
 
                uint32_t idx;
894
 
                float val;
895
 
                jack_ringbuffer_read(rb_ctrl_to_ui, (char*) &idx, sizeof(uint32_t));
896
 
                jack_ringbuffer_read(rb_ctrl_to_ui, (char*) &val, sizeof(float));
897
 
                plugin_gui->port_event(gui_instance, idx, sizeof(float), 0, &val);
898
 
        }
899
 
 
900
 
        while (jack_ringbuffer_read_space(rb_atom_to_ui) > sizeof(LV2_Atom)) {
901
 
                LV2_Atom a;
902
 
                jack_ringbuffer_read(rb_atom_to_ui, (char *) &a, sizeof(LV2_Atom));
903
 
                assert(a.size < inst->min_atom_bufsiz);
904
 
                jack_ringbuffer_read(rb_atom_to_ui, (char *) data, a.size);
905
 
                LV2_Atom_Event const* ev = (LV2_Atom_Event const*)((&(data)->body) + 1); // lv2_atom_sequence_begin
906
 
                while((const uint8_t*)ev < ((const uint8_t*) &(data)->body + (data)->atom.size)) {
907
 
                        plugin_gui->port_event(gui_instance, portmap_atom_to_ui,
908
 
                                        ev->body.size, uri_atom_EventTransfer, &ev->body);
909
 
                        ev = (LV2_Atom_Event const*) /* lv2_atom_sequence_next() */
910
 
                                ((const uint8_t*)ev + sizeof(LV2_Atom_Event) + ((ev->body.size + 7) & ~7));
911
 
                }
912
 
        }
913
 
 
914
 
        LV2_EXTERNAL_UI_RUN(extui);
915
 
}
916
 
 
917
 
#ifdef __APPLE__
918
 
 
919
 
static void osx_loop (CFRunLoopTimerRef timer, void *info) {
920
 
        if (client_state == Run) {
921
 
                run_one((LV2_Atom_Sequence*)info);
922
 
        }
923
 
        if (client_state == Exit) {
924
 
                rtk_osx_api_terminate();
925
 
        }
926
 
}
927
 
 
928
 
#else
929
 
 
930
 
 
931
 
static void main_loop(void) {
932
 
        struct timespec timeout;
933
 
        LV2_Atom_Sequence *data = (LV2_Atom_Sequence*) malloc(inst->min_atom_bufsiz * sizeof(uint8_t));
934
 
 
935
 
        pthread_mutex_lock (&gui_thread_lock);
936
 
        while (client_state != Exit) {
937
 
                run_one(data);
938
 
 
939
 
                if (client_state == Exit) break;
940
 
 
941
 
#ifdef _WIN32
942
 
                //Sleep(1000/UI_UPDATE_FPS);
943
 
#if (defined(__MINGW64__) || defined(__MINGW32__)) && __MSVCRT_VERSION__ >= 0x0601
944
 
                struct __timeb64 timebuffer;
945
 
                _ftime64(&timebuffer);
946
 
#else
947
 
                struct __timeb32 timebuffer;
948
 
                _ftime(&timebuffer);
949
 
#endif
950
 
                timeout.tv_nsec = timebuffer.millitm * 1000000;
951
 
                timeout.tv_sec = timebuffer.time;
952
 
#else // POSIX
953
 
                clock_gettime(CLOCK_REALTIME, &timeout);
954
 
#endif
955
 
                timeout.tv_nsec += 1000000000 / (UI_UPDATE_FPS);
956
 
                if (timeout.tv_nsec >= 1000000000) {timeout.tv_nsec -= 1000000000; timeout.tv_sec+=1;}
957
 
                pthread_cond_timedwait (&data_ready, &gui_thread_lock, &timeout);
958
 
 
959
 
        } /* while running */
960
 
        free(data);
961
 
        pthread_mutex_unlock (&gui_thread_lock);
962
 
}
963
 
#endif // APPLE RUNLOOP
964
 
 
965
 
static void catchsig (int sig) {
966
 
        fprintf(stderr,"caught signal - shutting down.\n");
967
 
        client_state=Exit;
968
 
        pthread_cond_signal (&data_ready);
969
 
}
970
 
 
971
 
static void on_external_ui_closed(void* controller) {
972
 
        catchsig(0);
973
 
}
974
 
 
975
 
#ifdef X42_MULTIPLUGIN
976
 
static void list_plugins (void) {
977
 
        unsigned int i;
978
 
        for (i = 0; i < sizeof(_plugins) / sizeof(RtkLv2Description); ++i) {
979
 
                const LV2_Descriptor* d = _plugins[i].lv2_descriptor(_plugins[i].dsp_descriptor_id);
980
 
                printf(" %2d   \"%s\" %s\n", i, _plugins[i].plugin_human_id, d->URI);
981
 
        }
982
 
}
983
 
#endif
984
 
 
985
 
static void print_usage (void) {
986
 
#ifdef X42_MULTIPLUGIN
987
 
        printf ("x42-%s - JACK %s\n\n", APPNAME, X42_MULTIPLUGIN_NAME);
988
 
        printf ("Usage: x42-%s [ Plugin-ID or URI ]\n\n", APPNAME);
989
 
        printf ("This is a standalone JACK application of a collection of LV2 plugins.\n"
990
 
                "Use ID -1, -l or --list for a dedicated list of included plugins.\n"
991
 
                "By default the first listed plugin (ID 0) is used.\n\n");
992
 
        printf ("List if available plugins: (ID \"Name\" URI)\n");
993
 
        list_plugins();
994
 
        printf ("\nSee also: <%s>\n", X42_MULTIPLUGIN_URI);
995
 
#else
996
 
 
997
 
#if defined X42_PLUGIN_STRUCT
998
 
        inst = & X42_PLUGIN_STRUCT;
999
 
#else
1000
 
        inst = &_plugin;
1001
 
#endif
1002
 
        const LV2_Descriptor* d = inst->lv2_descriptor(inst->dsp_descriptor_id);
1003
 
 
1004
 
        printf ("x42-%s - JACK %s\n\n", APPNAME, inst->plugin_human_id);
1005
 
        printf ("Usage: x42-%s\n\n", APPNAME);
1006
 
        printf ("This is a standalone JACK application of the LV2 plugin:\n"
1007
 
                "\"%s\".\n", inst->plugin_human_id);
1008
 
 
1009
 
        printf ("\nSee also: <%s>\n", d->URI);
1010
 
#endif
1011
 
        printf ("Website: <http://x42-plugins.com/>\n");
1012
 
}
1013
 
 
1014
 
static void print_version (void) {
1015
 
        printf ("x42-%s version %s\n\n", APPNAME, VERSION);
1016
 
        printf ("\n"
1017
 
                "Copyright (C) GPL 2013-2015 Robin Gareus <robin@gareus.org>\n"
1018
 
                "This is free software; see the source for copying conditions.  There is NO\n"
1019
 
                "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
1020
 
}
1021
 
 
1022
 
int main (int argc, char **argv) {
1023
 
        int rv = 0;
1024
 
        uint32_t c_ain  = 0;
1025
 
        uint32_t c_aout = 0;
1026
 
        uint32_t c_ctrl = 0;
1027
 
 
1028
 
        if (argc > 2) {
1029
 
                print_usage();
1030
 
                return -1;
1031
 
        }
1032
 
        if (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) {
1033
 
                print_usage();
1034
 
                return 0;
1035
 
        }
1036
 
        if (argc > 1 && (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) {
1037
 
                print_version();
1038
 
                return 0;
1039
 
        }
1040
 
 
1041
 
        // TODO autoconnect option.
1042
 
 
1043
 
#ifdef X42_MULTIPLUGIN
1044
 
        if (argc > 1 && (atoi(argv[1]) < 0 || !strcmp(argv[1], "-l") || !strcmp(argv[1], "--list"))) {
1045
 
                list_plugins();
1046
 
                return 0;
1047
 
        }
1048
 
 
1049
 
        inst = NULL;
1050
 
        if (argc > 1 && strlen(argv[1]) > 2 && atoi(argv[1]) == 0) {
1051
 
                unsigned int i;
1052
 
                for (i = 0; i < sizeof(_plugins) / sizeof(RtkLv2Description); ++i) {
1053
 
                        const LV2_Descriptor* d = _plugins[i].lv2_descriptor(_plugins[i].dsp_descriptor_id);
1054
 
                        if (strstr(d->URI, argv[1]) || strstr(_plugins[i].plugin_human_id, argv[1])) {
1055
 
                                inst = &_plugins[i];
1056
 
                                break;
1057
 
                        }
1058
 
                }
1059
 
        }
1060
 
        if (argc > 1 && !inst && atoi(argv[1]) >= 0) {
1061
 
                unsigned int plugid = atoi(argv[1]);
1062
 
                if (plugid < (sizeof(_plugins) / sizeof(RtkLv2Description))) {
1063
 
                        inst = &_plugins[plugid];
1064
 
                }
1065
 
        }
1066
 
        if (!inst) {
1067
 
                inst = &_plugins[0];
1068
 
        }
1069
 
#elif defined X42_PLUGIN_STRUCT
1070
 
        inst = & X42_PLUGIN_STRUCT;
1071
 
#else
1072
 
        inst = &_plugin;
1073
 
#endif
1074
 
 
1075
 
#ifdef __APPLE__
1076
 
        rtk_osx_api_init();
1077
 
#endif
1078
 
 
1079
 
#ifdef USE_WEAK_JACK
1080
 
        if (have_libjack()) {
1081
 
                fprintf(stderr, "JACK is not available. http://jackaudio.org/\n");
1082
 
#ifdef _WIN32
1083
 
                MessageBox(NULL, TEXT(
1084
 
                                        "JACK is not available.\n"
1085
 
                                        "You must have the JACK Audio Connection Kit installed to use the tools. "
1086
 
                                        "Please see http://jackaudio.org/ and http://jackaudio.org/faq/jack_on_windows.html"
1087
 
                                        ), TEXT("Error"), MB_ICONERROR | MB_OK);
1088
 
#elif __APPLE__
1089
 
                rtk_osx_api_err (
1090
 
                                        "JACK is not available.\n"
1091
 
                                        "You must have the JACK Audio Connection Kit installed to use the tools. "
1092
 
                                        "Please see http://jackaudio.org/ and http://jackosx.com/"
1093
 
                                );
1094
 
#endif
1095
 
                return 1;
1096
 
        }
1097
 
#endif
1098
 
 
1099
 
#ifdef _WIN32
1100
 
        pthread_win32_process_attach_np();
1101
 
#endif
1102
 
#if (defined _WIN32 && defined RTK_STATIC_INIT)
1103
 
        glib_init_static();
1104
 
        gobject_init_ctor();
1105
 
#endif
1106
 
 
1107
 
 
1108
 
        LV2_URID_Map uri_map            = { NULL, &uri_to_id };
1109
 
        const LV2_Feature map_feature   = { LV2_URID__map, &uri_map};
1110
 
        const LV2_Feature unmap_feature = { LV2_URID__unmap, NULL };
1111
 
 
1112
 
        LV2_Worker_Schedule schedule = { NULL, lv2_worker_schedule };
1113
 
        LV2_Feature schedule_feature  = { LV2_WORKER__schedule, &schedule };
1114
 
 
1115
 
        const LV2_Feature* features[] = {
1116
 
                &map_feature, &unmap_feature, &schedule_feature, NULL
1117
 
        };
1118
 
 
1119
 
        const LV2_Feature external_lv_feature = { LV2_EXTERNAL_UI_URI, &extui_host};
1120
 
        const LV2_Feature external_kx_feature = { LV2_EXTERNAL_UI_URI__KX__Host, &extui_host};
1121
 
        LV2_Feature instance_feature          = { "http://lv2plug.in/ns/ext/instance-access", NULL };
1122
 
 
1123
 
        const LV2_Feature* ui_features[] = {
1124
 
                &map_feature, &unmap_feature,
1125
 
                &instance_feature,
1126
 
                &external_lv_feature,
1127
 
                &external_kx_feature,
1128
 
                NULL
1129
 
        };
1130
 
 
1131
 
        /* check sourced settings */
1132
 
        assert ((inst->nports_midi_in + inst->nports_atom_in) <= 1);
1133
 
        assert ((inst->nports_midi_out + inst->nports_atom_out) <= 1);
1134
 
        assert (inst->plugin_human_id);
1135
 
        assert (inst->nports_total > 0);
1136
 
 
1137
 
        extui_host.plugin_human_id = inst->plugin_human_id;
1138
 
 
1139
 
        // TODO check if allocs succeeded - OOM -> exit
1140
 
        /* allocate data structure */
1141
 
        portmap_a_in  = (uint32_t*) malloc(inst->nports_audio_in * sizeof(uint32_t));
1142
 
        portmap_a_out = (uint32_t*) malloc(inst->nports_audio_out * sizeof(uint32_t));
1143
 
        portmap_rctl  = (uint32_t*) malloc(inst->nports_ctrl  * sizeof(uint32_t));
1144
 
        portmap_ctrl  = (int*)      malloc(inst->nports_total * sizeof(int));
1145
 
 
1146
 
        plugin_ports_pre  = (float*) calloc(inst->nports_ctrl, sizeof(float));
1147
 
        plugin_ports_post = (float*) calloc(inst->nports_ctrl, sizeof(float));
1148
 
 
1149
 
        atom_in = (LV2_Atom_Sequence*) malloc(inst->min_atom_bufsiz + sizeof(uint8_t));
1150
 
        atom_out = (LV2_Atom_Sequence*) malloc(inst->min_atom_bufsiz + sizeof(uint8_t));
1151
 
 
1152
 
        rb_ctrl_to_ui = jack_ringbuffer_create((UPDATE_FREQ_RATIO) * inst->nports_ctrl * 2 * sizeof(float));
1153
 
        rb_ctrl_from_ui = jack_ringbuffer_create((UPDATE_FREQ_RATIO) * inst->nports_ctrl * 2 * sizeof(float));
1154
 
 
1155
 
        rb_atom_to_ui = jack_ringbuffer_create((UPDATE_FREQ_RATIO) * inst->min_atom_bufsiz);
1156
 
        rb_atom_from_ui = jack_ringbuffer_create((UPDATE_FREQ_RATIO) * inst->min_atom_bufsiz);
1157
 
 
1158
 
        /* reolve descriptors */
1159
 
        plugin_dsp = inst->lv2_descriptor(inst->dsp_descriptor_id);
1160
 
        plugin_gui = inst->lv2ui_descriptor(inst->gui_descriptor_id);
1161
 
 
1162
 
        if (!plugin_dsp) {
1163
 
                fprintf(stderr, "cannot resolve LV2 descriptor\n");
1164
 
                rv |= 2;
1165
 
                goto out;
1166
 
        }
1167
 
        /* jack-open -> samlerate */
1168
 
        if (init_jack(extui_host.plugin_human_id)) {
1169
 
                fprintf(stderr, "cannot connect to JACK.\n");
1170
 
#ifdef _WIN32
1171
 
                MessageBox (NULL, TEXT(
1172
 
                                        "Cannot connect to JACK.\n"
1173
 
                                        "Please start the JACK Server first."
1174
 
                                        ), TEXT("Error"), MB_ICONERROR | MB_OK);
1175
 
#elif __APPLE__
1176
 
                rtk_osx_api_err (
1177
 
                                        "Cannot connect to JACK.\n"
1178
 
                                        "Please start the JACK Server first."
1179
 
                                );
1180
 
#endif
1181
 
                rv |= 4;
1182
 
                goto out;
1183
 
        }
1184
 
 
1185
 
        /* init plugin */
1186
 
        plugin_instance = plugin_dsp->instantiate(plugin_dsp, j_samplerate, NULL, features);
1187
 
        if (!plugin_instance) {
1188
 
                fprintf(stderr, "instantiation failed\n");
1189
 
                rv |= 2;
1190
 
                goto out;
1191
 
        }
1192
 
 
1193
 
        /* connect ports */
1194
 
        for (uint32_t p=0; p < inst->nports_total; ++p) {
1195
 
                portmap_ctrl[p] = -1;
1196
 
                switch (inst->ports[p].porttype) {
1197
 
                        case CONTROL_IN:
1198
 
                                plugin_ports_pre[c_ctrl] = inst->ports[p].val_default;
1199
 
                        case CONTROL_OUT:
1200
 
                                portmap_ctrl[p] = c_ctrl;
1201
 
                                portmap_rctl[c_ctrl] = p;
1202
 
                                plugin_dsp->connect_port(plugin_instance, p , &plugin_ports_pre[c_ctrl++]);
1203
 
                                break;
1204
 
                        case AUDIO_IN:
1205
 
                                portmap_a_in[c_ain++] = p;
1206
 
                                break;
1207
 
                        case AUDIO_OUT:
1208
 
                                portmap_a_out[c_aout++] = p;
1209
 
                                break;
1210
 
                        case MIDI_IN:
1211
 
                        case ATOM_IN:
1212
 
                                portmap_atom_from_ui = p;
1213
 
                                plugin_dsp->connect_port(plugin_instance, p , atom_in);
1214
 
                                break;
1215
 
                        case MIDI_OUT:
1216
 
                        case ATOM_OUT:
1217
 
                                portmap_atom_to_ui = p;
1218
 
                                plugin_dsp->connect_port(plugin_instance, p , atom_out);
1219
 
                                break;
1220
 
                        default:
1221
 
                                fprintf(stderr, "yet unsupported port..\n");
1222
 
                                break;
1223
 
                }
1224
 
        }
1225
 
 
1226
 
        assert(c_ain == inst->nports_audio_in);
1227
 
        assert(c_aout == inst->nports_audio_out);
1228
 
        assert(c_ctrl == inst->nports_ctrl);
1229
 
 
1230
 
        if (inst->nports_atom_out > 0 || inst->nports_atom_in > 0 || inst->nports_midi_in > 0 || inst->nports_midi_out > 0) {
1231
 
                uri_atom_Sequence       = uri_to_id(NULL, LV2_ATOM__Sequence);
1232
 
                uri_atom_EventTransfer  = uri_to_id(NULL, LV2_ATOM__eventTransfer);
1233
 
                uri_midi_MidiEvent      = uri_to_id(NULL, LV2_MIDI__MidiEvent);
1234
 
                uri_time_Position       = uri_to_id(NULL, LV2_TIME__Position);
1235
 
                uri_time_frame          = uri_to_id(NULL, LV2_TIME__frame);
1236
 
                uri_time_speed          = uri_to_id(NULL, LV2_TIME__speed);
1237
 
                uri_time_bar            = uri_to_id(NULL, LV2_TIME__bar);
1238
 
                uri_time_barBeat        = uri_to_id(NULL, LV2_TIME__barBeat);
1239
 
                uri_time_beatUnit       = uri_to_id(NULL, LV2_TIME__beatUnit);
1240
 
                uri_time_beatsPerBar    = uri_to_id(NULL, LV2_TIME__beatsPerBar);
1241
 
                uri_time_beatsPerMinute = uri_to_id(NULL, LV2_TIME__beatsPerMinute);
1242
 
                lv2_atom_forge_init(&lv2_forge, &uri_map);
1243
 
        }
1244
 
 
1245
 
        if (jack_portsetup()) {
1246
 
                rv |= 12;
1247
 
                goto out;
1248
 
        }
1249
 
 
1250
 
        if (plugin_gui) {
1251
 
        /* init plugin GUI */
1252
 
        extui_host.ui_closed = on_external_ui_closed;
1253
 
        instance_feature.data = plugin_instance;
1254
 
        gui_instance = plugin_gui->instantiate(plugin_gui,
1255
 
                        plugin_dsp->URI, NULL,
1256
 
                        &write_function, controller,
1257
 
                        (void **)&extui, ui_features);
1258
 
 
1259
 
        }
1260
 
 
1261
 
        if (!gui_instance || !extui) {
1262
 
#ifdef REQUIRE_UI
1263
 
                fprintf(stderr, "Error: GUI initialization failed.\n");
1264
 
                rv |= 2;
1265
 
                goto out;
1266
 
#else
1267
 
                fprintf(stderr, "Warning: GUI initialization failed.\n");
1268
 
#endif
1269
 
        }
1270
 
 
1271
 
#ifndef _WIN32
1272
 
        if (mlockall (MCL_CURRENT | MCL_FUTURE)) {
1273
 
                fprintf(stderr, "Warning: Can not lock memory.\n");
1274
 
        }
1275
 
#endif
1276
 
 
1277
 
        if (gui_instance) {
1278
 
                for (uint32_t p = 0; p < inst->nports_ctrl; p++) {
1279
 
                        if (jack_ringbuffer_write_space(rb_ctrl_to_ui) >= sizeof(uint32_t) + sizeof(float)) {
1280
 
                                jack_ringbuffer_write(rb_ctrl_to_ui, (char *) &portmap_rctl[p], sizeof(uint32_t));
1281
 
                                jack_ringbuffer_write(rb_ctrl_to_ui, (char *) &plugin_ports_pre[p], sizeof(float));
1282
 
                        }
1283
 
                }
1284
 
        }
1285
 
 
1286
 
        if (plugin_dsp->extension_data) {
1287
 
                worker_iface = (LV2_Worker_Interface*) plugin_dsp->extension_data (LV2_WORKER__interface);
1288
 
        }
1289
 
        if (worker_iface) {
1290
 
                worker_init();
1291
 
        }
1292
 
 
1293
 
        if (plugin_dsp->activate) {
1294
 
                plugin_dsp->activate(plugin_instance);
1295
 
        }
1296
 
 
1297
 
        if (jack_activate (j_client)) {
1298
 
                fprintf (stderr, "cannot activate client.\n");
1299
 
                rv |= 20;
1300
 
                goto out;
1301
 
        }
1302
 
 
1303
 
        jack_portconnect(JACK_AUTOCONNECT);
1304
 
 
1305
 
#ifndef _WIN32
1306
 
        signal (SIGHUP, catchsig);
1307
 
        signal (SIGINT, catchsig);
1308
 
#endif
1309
 
 
1310
 
        if (!gui_instance || !extui) {
1311
 
                /* no GUI */
1312
 
                while (client_state != Exit) {
1313
 
                        sleep (1);
1314
 
                }
1315
 
        } else {
1316
 
 
1317
 
                LV2_EXTERNAL_UI_SHOW(extui);
1318
 
 
1319
 
#ifdef __APPLE__
1320
 
                LV2_Atom_Sequence *data = (LV2_Atom_Sequence*) malloc(inst->min_atom_bufsiz * sizeof(uint8_t));
1321
 
                CFRunLoopRef runLoop = CFRunLoopGetCurrent();
1322
 
                CFRunLoopTimerContext context = {0, data, NULL, NULL, NULL};
1323
 
                CFRunLoopTimerRef timer = CFRunLoopTimerCreate(kCFAllocatorDefault, 0, 1.0/UI_UPDATE_FPS, 0, 0, &osx_loop, &context);
1324
 
                CFRunLoopAddTimer(runLoop, timer, kCFRunLoopCommonModes);
1325
 
                rtk_osx_api_run();
1326
 
                free(data);
1327
 
#else
1328
 
 
1329
 
                main_loop();
1330
 
#endif
1331
 
 
1332
 
                LV2_EXTERNAL_UI_HIDE(extui);
1333
 
        }
1334
 
 
1335
 
out:
1336
 
        cleanup(0);
1337
 
#ifdef _WIN32
1338
 
        pthread_win32_process_detach_np();
1339
 
#endif
1340
 
#if (defined _WIN32 && defined RTK_STATIC_INIT)
1341
 
        glib_cleanup_static();
1342
 
#endif
1343
 
        return(rv);
1344
 
}
1345
 
/* vi:set ts=2 sts=2 sw=2: */