1 /* -*- c-basic-offset: 4 -*-  vi:set ts=8 sts=4 sw=4: */
2 
3 /* jack-dssi-host.c
4  *
5  * DSSI Soft Synth Interface
6  *
7  * This is a host for DSSI plugins.  It listens for MIDI events on an
8  * ALSA sequencer port, delivers them to DSSI synths and outputs the
9  * result via JACK.
10  *
11  * This program expects the names of up to 16 DSSI synth plugins, in
12  * the form '<dll-name>:<label>',* to be provided on the command line.
13  * If just '<dll-name>' is provided, the first plugin in the DLL is
14  * is used.  MIDI channels are assigned to each plugin instance, in
15  * order, beginning with channel 0 (zero-based).  A plugin may be
16  * easily instantiated multiple times by preceding its name and label
17  * with a dash followed immediately by the desired number of instances,
18  * e.g. '-3 my_plugins.so:zoomy' would create three instances of the
19  * 'zoomy' plugin.
20  */
21 
22 /*
23  * Copyright 2004, 2009 Chris Cannam, Steve Harris and Sean Bolton.
24  *
25  * Permission to use, copy, modify, distribute, and sell this software
26  * for any purpose is hereby granted without fee, provided that the
27  * above copyright notice and this permission notice are included in
28  * all copies or substantial portions of the software.
29  */
30 
31 #define _BSD_SOURCE    1
32 #define _SVID_SOURCE   1
33 #define _ISOC99_SOURCE 1
34 
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38 
39 #include <ladspa.h>
40 #include "dssi.h"
41 #include <alsa/asoundlib.h>
42 #include <alsa/seq.h>
43 #include <jack/jack.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <assert.h>
48 #include <dlfcn.h>
49 #include <unistd.h>
50 #include <math.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
53 #include <sys/time.h>
54 #include <sys/wait.h>
55 #include <signal.h>
56 #include <dirent.h>
57 #include <time.h>
58 #include <libgen.h>
59 
60 #include <lo/lo.h>
61 
62 #include "jack-dssi-host.h"
63 
64 #include "../message_buffer/message_buffer.h"
65 
66 #ifdef MIDI_ALSA
67 static snd_seq_t *alsaClient;
68 #endif
69 
70 static jack_client_t *jackClient;
71 static jack_port_t **inputPorts, **outputPorts;
72 
73 static d3h_dll_t     *dlls;
74 
75 static d3h_plugin_t  *plugins;
76 static int            plugin_count = 0;
77 
78 static float sample_rate;
79 
80 static d3h_instance_t instances[D3H_MAX_INSTANCES];
81 static int            instance_count = 0;
82 
83 static LADSPA_Handle    *instanceHandles;
84 static snd_seq_event_t **instanceEventBuffers;
85 static unsigned long    *instanceEventCounts;
86 
87 static int insTotal, outsTotal;
88 static float **pluginInputBuffers, **pluginOutputBuffers;
89 
90 static int controlInsTotal, controlOutsTotal;
91 static float *pluginControlIns, *pluginControlOuts;
92 static d3h_instance_t *channel2instance[D3H_MAX_CHANNELS]; /* maps MIDI channel to instance */
93 static d3h_instance_t **pluginControlInInstances;          /* maps global control in # to instance */
94 static unsigned long *pluginControlInPortNumbers;          /* maps global control in # to instance LADSPA port # */
95 static int *pluginPortUpdated;                             /* indexed by global control in # */
96 
97 static char osc_path_tmp[1024];
98 
99 static char *projectDirectory;
100 
101 lo_server_thread serverThread;
102 
103 static sigset_t _signals;
104 
105 int exiting = 0;
106 static int verbose = 0;
107 static int autoconnect = 1;
108 static int load_guis = 1;
109 const char *myName = NULL;
110 
111 #define EVENT_BUFFER_SIZE 1024
112 static snd_seq_event_t midiEventBuffer[EVENT_BUFFER_SIZE]; /* ring buffer */
113 static int midiEventReadIndex = 0, midiEventWriteIndex = 0;
114 
115 static pthread_mutex_t midiEventBufferMutex = PTHREAD_MUTEX_INITIALIZER;
116 
117 LADSPA_Data get_port_default(const LADSPA_Descriptor *plugin, int port);
118 
119 void osc_error(int num, const char *m, const char *path);
120 
121 int osc_message_handler(const char *path, const char *types, lo_arg **argv, int
122 		      argc, void *data, void *user_data) ;
123 int osc_debug_handler(const char *path, const char *types, lo_arg **argv, int
124 		      argc, void *data, void *user_data) ;
125 
126 void
signalHandler(int sig)127 signalHandler(int sig)
128 {
129     fprintf(stderr, "%s: signal %d caught, trying to clean up and exit\n",
130 	    myName, sig);
131     exiting = 1;
132 }
133 
134 void
midi_callback()135 midi_callback()
136 {
137     snd_seq_event_t *ev = 0;
138     struct timeval tv;
139 
140     pthread_mutex_lock(&midiEventBufferMutex);
141 
142 #ifdef MIDI_ALSA
143     do {
144 	if (snd_seq_event_input(alsaClient, &ev) > 0) {
145 
146 	    if (midiEventReadIndex == midiEventWriteIndex + 1) {
147 		fprintf(stderr, "%s: Warning: MIDI event buffer overflow! ignoring incoming event\n", myName);
148 		continue;
149 	    }
150 
151 	    midiEventBuffer[midiEventWriteIndex] = *ev;
152 
153 	    ev = &midiEventBuffer[midiEventWriteIndex];
154 
155 	    /* At this point we change the event timestamp so that its
156 	       real-time field contains the actual time at which it was
157 	       received and processed (i.e. now).  Then in the audio
158 	       callback we use that to calculate frame offset. */
159 
160 	    gettimeofday(&tv, NULL);
161 	    ev->time.time.tv_sec = tv.tv_sec;
162 	    ev->time.time.tv_nsec = tv.tv_usec * 1000L;
163 
164 	    if (ev->type == SND_SEQ_EVENT_NOTEON && ev->data.note.velocity == 0) {
165 		ev->type =  SND_SEQ_EVENT_NOTEOFF;
166 	    }
167 
168 	    /* We don't need to handle EVENT_NOTE here, because ALSA
169 	       won't ever deliver them on the sequencer queue -- it
170 	       unbundles them into NOTE_ON and NOTE_OFF when they're
171 	       dispatched.  We would only need worry about them when
172 	       retrieving MIDI events from some other source. */
173 
174 	    midiEventWriteIndex = (midiEventWriteIndex + 1) % EVENT_BUFFER_SIZE;
175 	}
176 
177     } while (snd_seq_event_input_pending(alsaClient, 0) > 0);
178 #endif
179 
180     pthread_mutex_unlock(&midiEventBufferMutex);
181 }
182 
183 void
setControl(d3h_instance_t * instance,long controlIn,snd_seq_event_t * event)184 setControl(d3h_instance_t *instance, long controlIn, snd_seq_event_t *event)
185 {
186     long port = pluginControlInPortNumbers[controlIn];
187 
188     const LADSPA_Descriptor *p = instance->plugin->descriptor->LADSPA_Plugin;
189 
190     LADSPA_PortRangeHintDescriptor d = p->PortRangeHints[port].HintDescriptor;
191 
192     LADSPA_Data lb = p->PortRangeHints[port].LowerBound *
193 	(LADSPA_IS_HINT_SAMPLE_RATE(p->PortRangeHints[port].HintDescriptor) ?
194 	 sample_rate : 1.0f);
195 
196     LADSPA_Data ub = p->PortRangeHints[port].UpperBound *
197 	(LADSPA_IS_HINT_SAMPLE_RATE(p->PortRangeHints[port].HintDescriptor) ?
198 	 sample_rate : 1.0f);
199 
200     float value = (float)event->data.control.value;
201 
202     if (!LADSPA_IS_HINT_BOUNDED_BELOW(d)) {
203 	if (!LADSPA_IS_HINT_BOUNDED_ABOVE(d)) {
204 	    /* unbounded: might as well leave the value alone. */
205             return;
206 	} else {
207 	    /* bounded above only. just shift the range. */
208 	    value = ub - 127.0f + value;
209 	}
210     } else {
211 	if (!LADSPA_IS_HINT_BOUNDED_ABOVE(d)) {
212 	    /* bounded below only. just shift the range. */
213 	    value = lb + value;
214 	} else {
215 	    /* bounded both ends.  more interesting. */
216             if (LADSPA_IS_HINT_LOGARITHMIC(d) && lb > 0.0f && ub > 0.0f) {
217 		const float llb = logf(lb);
218 		const float lub = logf(ub);
219 
220 		value = expf(llb + ((lub - llb) * value / 127.0f));
221 	    } else {
222 		value = lb + ((ub - lb) * value / 127.0f);
223 	    }
224 	}
225     }
226     if (LADSPA_IS_HINT_INTEGER(d)) {
227         value = lrintf(value);
228     }
229 
230     if (verbose) {
231 	printf("%s: %s MIDI controller %d=%d -> control in %ld=%f\n", myName,
232 	       instance->friendly_name, event->data.control.param,
233 	       event->data.control.value, controlIn, value);
234     }
235 
236     pluginControlIns[controlIn] = value;
237     pluginPortUpdated[controlIn] = 1;
238 }
239 
240 int
audio_callback(jack_nframes_t nframes,void * arg)241 audio_callback(jack_nframes_t nframes, void *arg)
242 {
243     int i;
244     int outCount, inCount;
245     d3h_instance_t *instance;
246     struct timeval tv, evtv, diff;
247     long framediff;
248 
249     gettimeofday(&tv, NULL);
250 
251     /* Not especially pretty or efficient */
252 
253     for (i = 0; i < instance_count; i++) {
254         instanceEventCounts[i] = 0;
255     }
256 
257     for ( ; midiEventReadIndex != midiEventWriteIndex;
258          midiEventReadIndex = (midiEventReadIndex + 1) % EVENT_BUFFER_SIZE) {
259 
260 	snd_seq_event_t *ev = &midiEventBuffer[midiEventReadIndex];
261 
262         if (!snd_seq_ev_is_channel_type(ev)) {
263             /* discard non-channel oriented messages */
264             continue;
265         }
266 
267         instance = channel2instance[ev->data.note.channel];
268         if (!instance
269 	    /* || instance->inactive */) /* no -- see comment in osc_exiting_handler */
270 	{
271             /* discard messages intended for channels we aren't using or
272 	       absent or exited plugins */
273             continue;
274         }
275         i = instance->number;
276 
277         /* Stop processing incoming MIDI if an instance's event buffer is
278          * full. */
279 	if (instanceEventCounts[i] == EVENT_BUFFER_SIZE)
280             break;
281 
282 	/* Each event has a real-time timestamp indicating when it was
283 	 * received (set by midi_callback).  We need to calculate the
284 	 * difference between then and the start of the audio callback
285 	 * (held in tv), and use that to assign a frame offset, to
286 	 * avoid jitter.  We should stop processing when we reach any
287 	 * event received after the start of the audio callback. */
288 
289 	evtv.tv_sec = ev->time.time.tv_sec;
290 	evtv.tv_usec = ev->time.time.tv_nsec / 1000;
291 
292 	if (evtv.tv_sec > tv.tv_sec ||
293 	    (evtv.tv_sec == tv.tv_sec &&
294 	     evtv.tv_usec > tv.tv_usec)) {
295 	    break;
296 	}
297 
298 	diff.tv_sec = tv.tv_sec - evtv.tv_sec;
299 	if (tv.tv_usec < evtv.tv_usec) {
300 	    --diff.tv_sec;
301 	    diff.tv_usec = tv.tv_usec + 1000000 - evtv.tv_usec;
302 	} else {
303 	    diff.tv_usec = tv.tv_usec - evtv.tv_usec;
304 	}
305 
306 	framediff =
307 	    diff.tv_sec * sample_rate +
308 	    ((diff.tv_usec / 1000) * sample_rate) / 1000 +
309 	    ((diff.tv_usec - 1000 * (diff.tv_usec / 1000)) * sample_rate) / 1000000;
310 
311 	if (framediff >= nframes) framediff = nframes - 1;
312 	else if (framediff < 0) framediff = 0;
313 
314 	ev->time.tick = nframes - framediff - 1;
315 
316 	if (ev->type == SND_SEQ_EVENT_CONTROLLER) {
317 
318 	    int controller = ev->data.control.param;
319 #ifdef DEBUG
320 	    MB_MESSAGE("%s CC %d(0x%02x) = %d\n", instance->friendly_name,
321                        controller, controller, ev->data.control.value);
322 #endif
323 
324 	    if (controller == 0) { // bank select MSB
325 
326 		instance->pendingBankMSB = ev->data.control.value;
327 
328 	    } else if (controller == 32) { // bank select LSB
329 
330 		instance->pendingBankLSB = ev->data.control.value;
331 
332 	    } else if (controller > 0 && controller < MIDI_CONTROLLER_COUNT) {
333 
334 		long controlIn = instance->controllerMap[controller];
335 		if (controlIn >= 0) {
336 
337                     /* controller is mapped to LADSPA port, update the port */
338 		    setControl(instance, controlIn, ev);
339 
340 		} else {
341 
342                     /* controller is not mapped, so pass the event through to plugin */
343                     instanceEventBuffers[i][instanceEventCounts[i]] = *ev;
344                     instanceEventCounts[i]++;
345                 }
346 	    }
347 
348 	} else if (ev->type == SND_SEQ_EVENT_PGMCHANGE) {
349 
350 	    instance->pendingProgramChange = ev->data.control.value;
351 	    instance->uiNeedsProgramUpdate = 1;
352 
353 	} else {
354 
355             instanceEventBuffers[i][instanceEventCounts[i]] = *ev;
356             instanceEventCounts[i]++;
357 	}
358     }
359 
360     /* process pending program changes */
361     for (i = 0; i < instance_count; i++) {
362         instance = &instances[i];
363 
364 	/* no -- see comment in osc_exiting_handler */
365 	/* if (instance->inactive) continue; */
366 
367         if (instance->pendingProgramChange >= 0) {
368 
369             int pc = instance->pendingProgramChange;
370             int msb = instance->pendingBankMSB;
371             int lsb = instance->pendingBankLSB;
372 
373             //!!! gosh, I don't know this -- need to check with the specs:
374             // if you only send one of MSB/LSB controllers, should the
375             // other go to zero or remain as it was?  Assume it remains as
376             // it was, for now.
377 
378             if (lsb >= 0) {
379                 if (msb >= 0) {
380                     instance->currentBank = lsb + 128 * msb;
381                 } else {
382                     instance->currentBank = lsb + 128 * (instance->currentBank / 128);
383                 }
384             } else if (msb >= 0) {
385                 instance->currentBank = (instance->currentBank % 128) + 128 * msb;
386             }
387 
388             instance->currentProgram = pc;
389 
390             instance->pendingProgramChange = -1;
391             instance->pendingBankMSB = -1;
392             instance->pendingBankLSB = -1;
393 
394             if (instance->plugin->descriptor->select_program) {
395                 instance->plugin->descriptor->
396                     select_program(instanceHandles[instance->number],
397                                    instance->currentBank,
398                                    instance->currentProgram);
399             }
400         }
401     }
402 
403     for (inCount = 0; inCount < insTotal; ++inCount) {
404 
405 	jack_default_audio_sample_t *buffer =
406 	    jack_port_get_buffer(inputPorts[inCount], nframes);
407 
408 	memcpy(pluginInputBuffers[inCount], buffer, nframes * sizeof(LADSPA_Data));
409     }
410 
411     /* call run_synth() or run_multiple_synths() for all instances */
412 
413     i = 0;
414     outCount = 0;
415 
416     while (i < instance_count) {
417 
418 	/* no -- see comment in osc_exiting_handler */
419 /*
420 	if (instances[i].inactive) {
421 	    int j;
422 	    for (j = 0; j < instances[i].plugin->outs; ++j) {
423 		memset(pluginOutputBuffers[outCount + j], 0, nframes * sizeof(LADSPA_Data));
424 	    }
425 	    outCount += j;
426 	    ++i;
427 	    continue;
428 	}
429 */
430 	outCount += instances[i].plugin->outs;
431 
432         if (instances[i].plugin->descriptor->run_multiple_synths) {
433             instances[i].plugin->descriptor->run_multiple_synths
434                 (instances[i].plugin->instances,
435                  instanceHandles + i,
436                  nframes,
437                  instanceEventBuffers + i,
438                  instanceEventCounts + i);
439             i += instances[i].plugin->instances;
440         } else if (instances[i].plugin->descriptor->run_synth) {
441             instances[i].plugin->descriptor->run_synth(instanceHandles[i],
442                                                        nframes,
443                                                        instanceEventBuffers[i],
444                                                        instanceEventCounts[i]);
445             i++;
446         } else if (instances[i].plugin->descriptor->LADSPA_Plugin->run) {
447 	    instances[i].plugin->descriptor->LADSPA_Plugin->run(instanceHandles[i],
448 								nframes);
449 	    i++;
450 	} else {
451 	    fprintf(stderr, "DSSI plugin %d has no run_multiple_synths, run_synth or run method!\n", i);
452 	    i++;
453 	}
454     }
455 
456     assert(sizeof(LADSPA_Data) == sizeof(jack_default_audio_sample_t));
457 
458     for (outCount = 0; outCount < outsTotal; ++outCount) {
459 
460 	jack_default_audio_sample_t *buffer =
461 	    jack_port_get_buffer(outputPorts[outCount], nframes);
462 
463 	memcpy(buffer, pluginOutputBuffers[outCount], nframes * sizeof(LADSPA_Data));
464     }
465 
466     return 0;
467 }
468 
469 #ifndef RTLD_LOCAL
470 #define RTLD_LOCAL  (0)
471 #endif
472 
473 char *
load(const char * dllName,void ** dll,int quiet)474 load(const char *dllName, void **dll, int quiet) /* returns directory where dll found */
475 {
476     static char *defaultDssiPath = 0;
477     const char *dssiPath = getenv("DSSI_PATH");
478     char *path, *origPath, *element, *message;
479     void *handle = 0;
480 
481     /* If the dllName is an absolute path */
482     if (*dllName == '/') {
483 	if ((handle = dlopen(dllName, RTLD_NOW |       /* real-time programs should not use RTLD_LAZY */
484                                       RTLD_LOCAL))) {  /* do not share symbols across plugins
485                                                         * (some systems (e.g. Mac OS X) default
486                                                         * to RTLD_GLOBAL!) */
487 	    *dll = handle;
488             path = strdup(dllName);
489 	    return dirname(path);
490 	} else {
491 	    if (!quiet) {
492 		fprintf(stderr, "Cannot find DSSI or LADSPA plugin at '%s'\n", dllName);
493 	    }
494 	    return NULL;
495 	}
496     }
497 
498     if (!dssiPath) {
499 	if (!defaultDssiPath) {
500 	    const char *home = getenv("HOME");
501 	    if (home) {
502 		defaultDssiPath = malloc(strlen(home) + 60);
503 		sprintf(defaultDssiPath, "/usr/local/lib/dssi:/usr/lib/dssi:%s/.dssi", home);
504 	    } else {
505 		defaultDssiPath = strdup("/usr/local/lib/dssi:/usr/lib/dssi");
506 	    }
507 	}
508 	dssiPath = defaultDssiPath;
509 	if (!quiet) {
510 	    fprintf(stderr, "\n%s: Warning: DSSI path not set\n%s: Defaulting to \"%s\"\n\n", myName, myName, dssiPath);
511 	}
512     }
513 
514     path = strdup(dssiPath);
515     origPath = path;
516     *dll = 0;
517 
518     while ((element = strtok(path, ":")) != 0) {
519 
520 	char *filePath;
521 
522 	path = 0;
523 
524 	if (element[0] != '/') {
525 	    if (!quiet) {
526 		fprintf(stderr, "%s: Ignoring relative element \"%s\" in path\n", myName, element);
527 	    }
528 	    continue;
529 	}
530 
531 	if (!quiet && verbose) {
532 	    fprintf(stderr, "%s: Looking for library \"%s\" in %s... ", myName, dllName, element);
533 	}
534 
535 	filePath = (char *)malloc(strlen(element) + strlen(dllName) + 2);
536 	sprintf(filePath, "%s/%s", element, dllName);
537 
538 	if ((handle = dlopen(filePath, RTLD_NOW |       /* real-time programs should not use RTLD_LAZY */
539                                        RTLD_LOCAL))) {  /* do not share symbols across plugins */
540 	    if (!quiet && verbose) {
541 		fprintf(stderr, "found\n");
542 	    }
543 	    *dll = handle;
544             free(filePath);
545             path = strdup(element);
546             free(origPath);
547 	    return path;
548 	}
549 
550 	if (!quiet && verbose) {
551 	    message = dlerror();
552 	    if (message) {
553 		fprintf(stderr, "not found: %s\n", message);
554 	    } else {
555 		fprintf(stderr, "not found\n");
556 	    }
557 	}
558 
559         free(filePath);
560     }
561 
562     free(origPath);
563     return 0;
564 }
565 
566 static int
instance_sort_cmp(const void * a,const void * b)567 instance_sort_cmp(const void *a, const void *b)
568 {
569     d3h_instance_t *ia = (d3h_instance_t *)a;
570     d3h_instance_t *ib = (d3h_instance_t *)b;
571 
572     if (ia->plugin->number != ib->plugin->number) {
573         return ia->plugin->number - ib->plugin->number;
574     } else {
575         return ia->channel - ib->channel;
576     }
577 }
578 
579 void
startGUI(const char * directory,const char * dllName,const char * label,const char * oscUrl,const char * instanceTag)580 startGUI(const char *directory, const char *dllName, const char *label,
581 	 const char *oscUrl, const char *instanceTag)
582 {
583     struct dirent *entry;
584     char *dllBase = strdup(dllName);
585     char *subpath;
586     DIR *subdir;
587     char *filename;
588     struct stat buf;
589     int fuzzy;
590 
591     if (strlen(dllBase) > 3 &&
592         !strcasecmp(dllBase + strlen(dllBase) - 3, ".so")) {
593 	dllBase[strlen(dllBase) - 3] = '\0';
594     }
595 
596     if (*dllBase == '/') {
597         subpath = dllBase;
598         dllBase = strdup(strrchr(subpath, '/') + 1);
599     } else {
600 	subpath = (char *)malloc(strlen(directory) + strlen(dllBase) + 2);
601 	sprintf(subpath, "%s/%s", directory, dllBase);
602     }
603 
604     for (fuzzy = 0; fuzzy <= 1; ++fuzzy) {
605 
606 	if (!(subdir = opendir(subpath))) {
607 	    if (verbose) {
608 		fprintf(stderr, "%s: can't open plugin GUI directory \"%s\"\n", myName, subpath);
609 	    }
610 	    free(subpath);
611 	    free(dllBase);
612 	    return;
613 	}
614 
615 	while ((entry = readdir(subdir))) {
616 
617 	    if (entry->d_name[0] == '.') continue;
618 	    if (!strchr(entry->d_name, '_')) continue;
619 
620 	    if (fuzzy) {
621 		if (verbose) {
622 		    fprintf(stderr, "checking %s against %s\n", entry->d_name, dllBase);
623 		}
624                 if (strlen(entry->d_name) <= strlen(dllBase) ||
625                     strncmp(entry->d_name, dllBase, strlen(dllBase)) ||
626                     entry->d_name[strlen(dllBase)] != '_')
627                     continue;
628 	    } else {
629 		if (verbose) {
630 		    fprintf(stderr, "checking %s against %s\n", entry->d_name, label);
631 		}
632                 if (strlen(entry->d_name) <= strlen(label) ||
633                     strncmp(entry->d_name, label, strlen(label)) ||
634                     entry->d_name[strlen(label)] != '_')
635                     continue;
636 	    }
637 
638 	    filename = (char *)malloc(strlen(subpath) + strlen(entry->d_name) + 2);
639 	    sprintf(filename, "%s/%s", subpath, entry->d_name);
640 
641 	    if (stat(filename, &buf)) {
642 		perror("stat failed");
643 		free(filename);
644 		continue;
645 	    }
646 
647 	    if ((S_ISREG(buf.st_mode) || S_ISLNK(buf.st_mode)) &&
648 		(buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
649 
650 		if (verbose) {
651 		    fprintf(stderr, "%s: trying to execute GUI at \"%s\"\n",
652 			    myName, filename);
653 		}
654 
655 		if (fork() == 0) {
656 		    execlp(filename, filename, oscUrl, dllName, label, instanceTag, NULL);
657 		    perror("exec failed");
658 		    exit(1);
659 		}
660 
661 		free(filename);
662 		free(subpath);
663 		free(dllBase);
664 		return;
665 	    }
666 
667 	    free(filename);
668 	}
669     }
670 
671     if (verbose) {
672 	fprintf(stderr, "%s: no GUI found for plugin \"%s\" in \"%s/\"\n",
673 		myName, label, subpath);
674     }
675     free(subpath);
676     free(dllBase);
677 }
678 
679 void
query_programs(d3h_instance_t * instance)680 query_programs(d3h_instance_t *instance)
681 {
682     int i;
683 
684     /* free old lot */
685     if (instance->pluginPrograms) {
686         for (i = 0; i < instance->pluginProgramCount; i++)
687             free((void *)instance->pluginPrograms[i].Name);
688 	free((char *)instance->pluginPrograms);
689 	instance->pluginPrograms = NULL;
690 	instance->pluginProgramCount = 0;
691     }
692 
693     instance->pendingBankLSB = -1;
694     instance->pendingBankMSB = -1;
695     instance->pendingProgramChange = -1;
696 
697     if (instance->plugin->descriptor->get_program &&
698         instance->plugin->descriptor->select_program) {
699 
700 	/* Count the plugins first */
701 	for (i = 0; instance->plugin->descriptor->
702                         get_program(instanceHandles[instance->number], i); ++i);
703 
704 	if (i > 0) {
705 	    instance->pluginProgramCount = i;
706 	    instance->pluginPrograms = (DSSI_Program_Descriptor *)
707 		malloc(i * sizeof(DSSI_Program_Descriptor));
708 	    while (i > 0) {
709 		const DSSI_Program_Descriptor *descriptor;
710 		--i;
711 		descriptor = instance->plugin->descriptor->
712 		    get_program(instanceHandles[instance->number], i);
713 		instance->pluginPrograms[i].Bank = descriptor->Bank;
714 		instance->pluginPrograms[i].Program = descriptor->Program;
715 		instance->pluginPrograms[i].Name = strdup(descriptor->Name);
716 		if (verbose) {
717 		    printf("%s: %s program %d is MIDI bank %lu program %lu, named '%s'\n",
718 			   myName, instance->friendly_name, i,
719 			   instance->pluginPrograms[i].Bank,
720 			   instance->pluginPrograms[i].Program,
721 			   instance->pluginPrograms[i].Name);
722 		}
723 	    }
724 	}
725     }
726 }
727 
728 int
main(int argc,char ** argv)729 main(int argc, char **argv)
730 {
731     int portid;
732     int npfd;
733     struct pollfd *pfd;
734 
735     d3h_dll_t *dll;
736     d3h_plugin_t *plugin;
737     d3h_instance_t *instance;
738     void *pluginObject;
739     char *dllName;
740     char *label;
741     const char **ports;
742     char *tmp;
743     char *url;
744     int i, reps, j;
745     int in, out, controlIn, controlOut;
746     char clientName[33];
747     int haveClientName = 0;
748     const int clientLen = 32;
749     jack_status_t status;
750 
751     setsid();
752     sigemptyset (&_signals);
753     sigaddset(&_signals, SIGHUP);
754     sigaddset(&_signals, SIGINT);
755     sigaddset(&_signals, SIGQUIT);
756     sigaddset(&_signals, SIGPIPE);
757     sigaddset(&_signals, SIGTERM);
758     sigaddset(&_signals, SIGUSR1);
759     sigaddset(&_signals, SIGUSR2);
760     pthread_sigmask(SIG_BLOCK, &_signals, 0);
761 
762     insTotal = outsTotal = controlInsTotal = controlOutsTotal = 0;
763 
764     /* Handle run-plugin-from-executable-name special case */
765 
766     if (argc == 1) {
767 
768 	const char *basename = strrchr(argv[0], '/');
769 	if (!basename) basename = argv[0];
770 	else ++basename;
771 
772 	if (basename[0] && strcmp(basename, "jack-dssi-host")) {
773 	    /* look for basename + .so as plugin */
774 	    dllName = malloc(strlen(basename) + 4);
775 	    sprintf(dllName, "%s.so", basename);
776 	    if (load(dllName, &pluginObject, 1)) {
777 		dlclose(pluginObject);
778 		argc = 2;
779 		myName = strdup(argv[0]);
780 		argv = (char **)malloc(2 * sizeof(char *));
781 		argv[0] = "jack-dssi-host";
782 		argv[1] = dllName;
783 	    }
784 	}
785     }
786 
787     if (!myName) myName = strdup(argv[0]);
788 
789     /* Parse args and report usage */
790 
791     if (argc < 2) {
792 	fprintf(stderr, "\nUsage: %s [-v] [-a] [-n] [-p <projdir>] [-c <cname>] [-<i>] <libname>[%c<label>] [...]\n", argv[0], LABEL_SEP);
793 	fprintf(stderr, "\n  -v        Verbose mode\n");
794 	fprintf(stderr, "  -a        Don't autoconnect outputs to JACK physical outputs\n");
795 	fprintf(stderr, "  -n        Don't automatically start plugin GUIs\n");
796 	fprintf(stderr, "  <projdir> Project directory to pass to plugin and UI\n");
797 	fprintf(stderr, "  <cname>   Client name to use for ALSA and JACK\n");
798 	fprintf(stderr, "  <i>       Number of instances of each plugin to run (max %d total, default 1)\n", D3H_MAX_INSTANCES);
799 	fprintf(stderr, "  <libname> DSSI plugin library .so to load (searched for in $DSSI_PATH)\n");
800 	fprintf(stderr, "  <label>   Label of plugin to load from library\n");
801 	fprintf(stderr, "  [...]     Optionally more instance counts, plugins and labels\n");
802 	fprintf(stderr, "\nExample: %s -2 lib1.so -1 lib2.so%cfuzzy\n", argv[0], LABEL_SEP);
803 	fprintf(stderr, "  run two instances of the first plugin found in lib1.so, assigned to MIDI\n  channels 0 and 1 and connected to the first available JACK outputs, and one\n  instance of the \"fuzzy\" plugin in lib2.so with MIDI channels 2 and 3 and\n  connected to the next available JACK outputs.\n");
804 	fprintf(stderr,"\nAs a special case, if this program is started with a name other than\njack-dssi-host, and if that name (plus .so suffix) can be found in the DSSI path\nas a valid plugin library, and if no further command line arguments are given,\nthen the first plugin in that library will be loaded automatically.\n\n");
805 	return 2;
806     }
807 
808     if (verbose) {
809 	fprintf(stderr, "%s: Starting...\n", myName);
810     }
811 
812     projectDirectory = NULL;
813 
814     reps = 1;
815     for (i = 1; i < argc; i++) {
816 
817 	if (!strcmp(argv[i], "-v")) {
818 	    verbose = 1;
819 	    continue;
820 	}
821 	if (!strcmp(argv[i], "-a")) {
822 	    autoconnect = 0;
823 	    continue;
824 	}
825 	if (!strcmp(argv[i], "-n")) {
826 	    load_guis = 0;
827 	    continue;
828 	}
829 
830 	if (!strcmp(argv[i], "-p")) {
831 	    if (i < argc - 1) {
832 		projectDirectory = argv[++i];
833 	    } else {
834 		fprintf(stderr, "%s: project directory expected after -p\n", myName);
835 		return 2;
836 	    }
837 	    continue;
838 	}
839 
840 	if (!strcmp(argv[i], "-c")) {
841 	    if (i < argc - 1) {
842 		strncpy(clientName, argv[++i], clientLen);
843 		clientName[clientLen] = '\0';
844 		haveClientName = 1;
845 	    } else {
846 		fprintf(stderr, "%s: client name expected after -c\n", myName);
847 		return 2;
848 	    }
849 	    continue;
850 	}
851 
852         if (instance_count >= D3H_MAX_INSTANCES) {
853             fprintf(stderr, "%s: too many plugin instances specified (max is %d)\n", myName, D3H_MAX_INSTANCES);
854             return 2;
855         }
856 
857         /* parse repetition count */
858         if (argv[i][0] == '-') {
859             reps = atoi(&argv[i][1]);
860             if (reps > 0) {
861                 continue;
862             } else {
863                 reps = 1;
864             }
865         }
866 
867         /* parse dll name, plus a label if supplied */
868         tmp = strchr(argv[i], LABEL_SEP);
869         if (tmp) {
870             dllName = calloc(1, tmp - argv[i] + 1);
871             strncpy(dllName, argv[i], tmp - argv[i]);
872             label = strdup(tmp + 1);
873         } else {
874             dllName = strdup(argv[i]);
875             label = NULL;
876         }
877 
878         /* check if we've seen this plugin before */
879         for (plugin = plugins; plugin; plugin = plugin->next) {
880             if (label) {
881                 if (!strcmp(dllName, plugin->dll->name) &&
882                     !strcmp(label,   plugin->label))
883                     break;
884             } else {
885                if (!strcmp(dllName, plugin->dll->name) &&
886                    plugin->is_first_in_dll)
887                    break;
888             }
889         }
890 
891         if (plugin) {
892             /* have already seen this plugin */
893 
894             free(dllName);
895             free(label);
896 
897         } else {
898             /* this is a new plugin */
899 
900             plugin = (d3h_plugin_t *)calloc(1, sizeof(d3h_plugin_t));
901             plugin->number = plugin_count;
902             plugin->label = label;
903 
904             /* check if we've seen this dll before */
905             for (dll = dlls; dll; dll = dll->next) {
906                 if (!strcmp(dllName, dll->name))
907                     break;
908             }
909             if (!dll) {
910                 /* this is a new dll */
911                 dll = (d3h_dll_t *)calloc(1, sizeof(d3h_dll_t));
912                 dll->name = dllName;
913 
914                 dll->directory = load(dllName, &pluginObject, 0);
915                 if (!dll->directory || !pluginObject) {
916                     fprintf(stderr, "\n%s: Error: Failed to load plugin library \"%s\"\n", myName, dllName);
917                     return 1;
918                 }
919 
920                 dll->descfn = (DSSI_Descriptor_Function)dlsym(pluginObject,
921                                                               "dssi_descriptor");
922                 if (dll->descfn) {
923                     dll->is_DSSI_dll = 1;
924                 } else {
925                     dll->descfn = (DSSI_Descriptor_Function)dlsym(pluginObject,
926                                                                   "ladspa_descriptor");
927                     if (!dll->descfn) {
928                         fprintf(stderr, "\n%s: Error: \"%s\" is not a DSSI or LADSPA plugin library\n", myName, dllName);
929                         return 1;
930                     }
931                     dll->is_DSSI_dll = 0;
932                 }
933 
934                 dll->next = dlls;
935                 dlls = dll;
936             }
937             plugin->dll = dll;
938 
939             /* get the plugin descriptor */
940             j = 0;
941             if (dll->is_DSSI_dll) {
942                 const DSSI_Descriptor *desc;
943 
944                 while ((desc = dll->descfn(j++))) {
945                     if (!plugin->label ||
946                         !strcmp(desc->LADSPA_Plugin->Label, plugin->label)) {
947                         plugin->descriptor = desc;
948                         break;
949                     }
950                 }
951             } else { /* LADSPA plugin; create and use a dummy DSSI descriptor */
952                 LADSPA_Descriptor *desc;
953 
954                 plugin->descriptor = (const DSSI_Descriptor *)calloc(1, sizeof(DSSI_Descriptor));
955                 ((DSSI_Descriptor *)plugin->descriptor)->DSSI_API_Version = 1;
956 
957                 while ((desc = (LADSPA_Descriptor *)dll->descfn(j++))) {
958                     if (!plugin->label ||
959                         !strcmp(desc->Label, plugin->label)) {
960                         ((DSSI_Descriptor *)plugin->descriptor)->LADSPA_Plugin = desc;
961                         break;
962                     }
963                 }
964                 if (!plugin->descriptor->LADSPA_Plugin) {
965                     free((void *)plugin->descriptor);
966                     plugin->descriptor = NULL;
967                 }
968             }
969             if (!plugin->descriptor) {
970                 fprintf(stderr, "\n%s: Error: Plugin label \"%s\" not found in library \"%s\"\n",
971                         myName, plugin->label ? plugin->label : "(none)", dllName);
972                 return 1;
973             }
974             plugin->is_first_in_dll = (j = 1);
975             if (!plugin->label) {
976                 plugin->label = strdup(plugin->descriptor->LADSPA_Plugin->Label);
977             }
978 
979             /* Count number of i/o buffers and ports required */
980             plugin->ins = 0;
981             plugin->outs = 0;
982             plugin->controlIns = 0;
983             plugin->controlOuts = 0;
984 
985             for (j = 0; j < plugin->descriptor->LADSPA_Plugin->PortCount; j++) {
986 
987                 LADSPA_PortDescriptor pod =
988                     plugin->descriptor->LADSPA_Plugin->PortDescriptors[j];
989 
990                 if (LADSPA_IS_PORT_AUDIO(pod)) {
991 
992                     if (LADSPA_IS_PORT_INPUT(pod)) ++plugin->ins;
993                     else if (LADSPA_IS_PORT_OUTPUT(pod)) ++plugin->outs;
994 
995                 } else if (LADSPA_IS_PORT_CONTROL(pod)) {
996 
997                     if (LADSPA_IS_PORT_INPUT(pod)) ++plugin->controlIns;
998                     else if (LADSPA_IS_PORT_OUTPUT(pod)) ++plugin->controlOuts;
999                 }
1000             }
1001 
1002             /* finish up new plugin */
1003             plugin->instances = 0;
1004             plugin->next = plugins;
1005             plugins = plugin;
1006             plugin_count++;
1007         }
1008 
1009         /* set up instances */
1010         for (j = 0; j < reps; j++) {
1011             if (instance_count < D3H_MAX_INSTANCES) {
1012                 instance = &instances[instance_count];
1013 
1014                 instance->plugin = plugin;
1015                 instance->channel = instance_count;
1016 		instance->inactive = 1;
1017                 tmp = (char *)malloc(strlen(plugin->dll->name) +
1018                                      strlen(plugin->label) + 9);
1019                 instance->friendly_name = tmp;
1020                 strcpy(tmp, plugin->dll->name);
1021                 if (strlen(tmp) > 3 &&
1022                     !strcasecmp(tmp + strlen(tmp) - 3, ".so")) {
1023                     tmp = tmp + strlen(tmp) - 3;
1024                 } else {
1025                     tmp = tmp + strlen(tmp);
1026                 }
1027                 sprintf(tmp, "/%s/chan%02d", plugin->label, instance->channel);
1028                 instance->pluginProgramCount = 0;
1029                 instance->pluginPrograms = NULL;
1030                 instance->currentBank = 0;
1031                 instance->currentProgram = 0;
1032                 instance->pendingBankLSB = -1;
1033                 instance->pendingBankMSB = -1;
1034                 instance->pendingProgramChange = -1;
1035                 instance->uiTarget = NULL;
1036 		instance->uiSource = NULL;
1037                 instance->ui_initial_show_sent = 0;
1038                 instance->uiNeedsProgramUpdate = 0;
1039                 instance->ui_osc_control_path = NULL;
1040                 instance->ui_osc_program_path = NULL;
1041                 instance->ui_osc_quit_path = NULL;
1042                 instance->ui_osc_rate_path = NULL;
1043                 instance->ui_osc_show_path = NULL;
1044 
1045                 insTotal += plugin->ins;
1046                 outsTotal += plugin->outs;
1047                 controlInsTotal += plugin->controlIns;
1048                 controlOutsTotal += plugin->controlOuts;
1049 
1050                 plugin->instances++;
1051                 instance_count++;
1052             } else {
1053                 fprintf(stderr, "%s: too many plugin instances specified\n", myName);
1054                 return 2;
1055             }
1056         }
1057         reps = 1;
1058     }
1059 
1060     if (instance_count == 0) {
1061 	fprintf(stderr, "%s: No plugin specified\n", myName);
1062 	return 2;
1063     }
1064 
1065     /* sort array of instances to group them by plugin */
1066     if (instance_count > 1) {
1067         qsort(instances, instance_count, sizeof(d3h_instance_t), instance_sort_cmp);
1068     }
1069 
1070     /* build channel2instance[] while showing what our instances are */
1071     for (i = 0; i < D3H_MAX_CHANNELS; i++)
1072         channel2instance[i] = NULL;
1073     for (i = 0; i < instance_count; i++) {
1074         instance = &instances[i];
1075         instance->number = i;
1076         channel2instance[instance->channel] = instance;
1077 	if (verbose) {
1078 	    fprintf(stderr, "%s: instance %2d on channel %2d, plugin %2d is \"%s\"\n",
1079 		    myName, i, instance->channel, instance->plugin->number,
1080 		    instance->friendly_name);
1081 	}
1082     }
1083 
1084     /* Create buffers and JACK client and ports */
1085 
1086     if (!haveClientName) {
1087 	if (instance_count > 1) strcpy(clientName, "jack-dssi-host");
1088 	else {
1089 	    strncpy(clientName, instances[0].plugin->descriptor->LADSPA_Plugin->Name, clientLen);
1090 	    clientName[clientLen] = '\0';
1091 	}
1092     }
1093 
1094     if ((jackClient = jack_client_open(clientName, 0, &status)) == 0) {
1095         fprintf(stderr, "\n%s: Error: Failed to connect to JACK server\n",
1096             myName);
1097         return 1;
1098     }
1099     if (status & JackNameNotUnique) {
1100         strncpy(clientName, jack_get_client_name(jackClient), clientLen);
1101 	clientName[clientLen] = '\0';
1102     }
1103 
1104     sample_rate = jack_get_sample_rate(jackClient);
1105 
1106     inputPorts = (jack_port_t **)malloc(insTotal * sizeof(jack_port_t *));
1107     pluginInputBuffers = (float **)malloc(insTotal * sizeof(float *));
1108     pluginControlIns = (float *)calloc(controlInsTotal, sizeof(float));
1109     pluginControlInInstances =
1110         (d3h_instance_t **)malloc(controlInsTotal * sizeof(d3h_instance_t *));
1111     pluginControlInPortNumbers =
1112         (unsigned long *)malloc(controlInsTotal * sizeof(unsigned long));
1113     pluginPortUpdated = (int *)malloc(controlInsTotal * sizeof(int));
1114 
1115     outputPorts = (jack_port_t **)malloc(outsTotal * sizeof(jack_port_t *));
1116     pluginOutputBuffers = (float **)malloc(outsTotal * sizeof(float *));
1117     pluginControlOuts = (float *)calloc(controlOutsTotal, sizeof(float));
1118 
1119     instanceHandles = (LADSPA_Handle *)malloc(instance_count *
1120                                               sizeof(LADSPA_Handle));
1121     instanceEventBuffers = (snd_seq_event_t **)malloc(instance_count *
1122                                                       sizeof(snd_seq_event_t *));
1123     instanceEventCounts = (unsigned long *)malloc(instance_count *
1124                                                   sizeof(unsigned long));
1125 
1126     for (i = 0; i < instance_count; i++) {
1127         instanceEventBuffers[i] = (snd_seq_event_t *)malloc(EVENT_BUFFER_SIZE *
1128                                                             sizeof(snd_seq_event_t));
1129         instances[i].pluginPortControlInNumbers =
1130             (int *)malloc(instances[i].plugin->descriptor->LADSPA_Plugin->PortCount *
1131                           sizeof(int));
1132     }
1133 
1134     in = 0;
1135     out = 0;
1136     reps = 0;
1137     for (i = 0; i < instance_count; i++) {
1138 	if (i > 0 &&
1139 	    !strcmp(instances[i  ].plugin->descriptor->LADSPA_Plugin->Name,
1140 		    instances[i-1].plugin->descriptor->LADSPA_Plugin->Name)) {
1141 	    ++reps;
1142 	} else if (i < instance_count - 1 &&
1143 		   !strcmp(instances[i  ].plugin->descriptor->LADSPA_Plugin->Name,
1144 			   instances[i+1].plugin->descriptor->LADSPA_Plugin->Name)) {
1145 	    reps = 1;
1146 	} else {
1147 	    reps = 0;
1148 	}
1149 	for (j = 0; j < instances[i].plugin->ins; ++j) {
1150 	    char portName[40];
1151 	    if (haveClientName) {
1152 		/* if we're given a specific client name for the whole
1153 		   application, just name our individual ports by
1154 		   number rather than by instance
1155 		*/
1156 		sprintf(portName, "in_%d", in);
1157 	    } else {
1158 		strncpy(portName, instances[i].plugin->descriptor->LADSPA_Plugin->Name, 30);
1159 		if (reps > 0) {
1160 		    portName[25] = '\0';
1161 		    sprintf(portName + strlen(portName), " %d in_%d", reps, j + 1);
1162 		} else {
1163 		    portName[30] = '\0';
1164 		    sprintf(portName + strlen(portName), " in_%d", j + 1);
1165 		}
1166 	    }
1167 	    inputPorts[in] = jack_port_register(jackClient, portName,
1168 						JACK_DEFAULT_AUDIO_TYPE,
1169 						JackPortIsInput, 0);
1170 	    pluginInputBuffers[in] =
1171 		(float *)calloc(jack_get_buffer_size(jackClient), sizeof(float));
1172 	    ++in;
1173 	}
1174 	for (j = 0; j < instances[i].plugin->outs; ++j) {
1175 	    char portName[40];
1176 	    if (haveClientName) {
1177 		/* if we're given a specific client name for the whole
1178 		   application, just name our individual ports by
1179 		   number rather than by instance
1180 		*/
1181 		sprintf(portName, "out_%d", out);
1182 	    } else {
1183 		strncpy(portName, instances[i].plugin->descriptor->LADSPA_Plugin->Name, 30);
1184 		if (reps > 0) {
1185 		    portName[25] = '\0';
1186 		    sprintf(portName + strlen(portName), " %d out_%d", reps, j + 1);
1187 		} else {
1188 		    portName[30] = '\0';
1189 		    sprintf(portName + strlen(portName), " out_%d", j + 1);
1190 		}
1191 	    }
1192 	    outputPorts[out] = jack_port_register(jackClient, portName,
1193 						  JACK_DEFAULT_AUDIO_TYPE,
1194 						  JackPortIsOutput, 0);
1195 	    pluginOutputBuffers[out] =
1196 		(float *)calloc(jack_get_buffer_size(jackClient), sizeof(float));
1197 	    ++out;
1198 	}
1199     }
1200 
1201     jack_set_process_callback(jackClient, audio_callback, 0);
1202 
1203     /* Instantiate plugins */
1204 
1205     for (i = 0; i < instance_count; i++) {
1206         plugin = instances[i].plugin;
1207         instanceHandles[i] = plugin->descriptor->LADSPA_Plugin->instantiate
1208             (plugin->descriptor->LADSPA_Plugin, sample_rate);
1209         if (!instanceHandles[i]) {
1210             fprintf(stderr, "\n%s: Error: Failed to instantiate instance %d!, plugin \"%s\"\n",
1211                     myName, i, plugin->label);
1212             return 1;
1213         }
1214 	if (projectDirectory && plugin->descriptor->configure) {
1215 	    char *rv =plugin->descriptor->configure(instanceHandles[i],
1216 						    DSSI_PROJECT_DIRECTORY_KEY,
1217 						    projectDirectory);
1218 	    if (rv) {
1219 		fprintf(stderr, "%s: Warning: plugin doesn't like project directory: \"%s\"\n", myName, rv);
1220 	    }
1221 	}
1222     }
1223 
1224     /* Create OSC thread */
1225 
1226     serverThread = lo_server_thread_new(NULL, osc_error);
1227     snprintf((char *)osc_path_tmp, 31, "/dssi");
1228     tmp = lo_server_thread_get_url(serverThread);
1229     url = (char *)malloc(strlen(tmp) + strlen(osc_path_tmp));
1230     sprintf(url, "%s%s", tmp, osc_path_tmp + 1);
1231     if (verbose) {
1232 	printf("%s: registering %s\n", myName, url);
1233     }
1234     free(tmp);
1235 
1236     lo_server_thread_add_method(serverThread, NULL, NULL, osc_message_handler,
1237 				NULL);
1238     lo_server_thread_start(serverThread);
1239 
1240     /* Connect and activate plugins */
1241 
1242     for (in = 0; in < controlInsTotal; in++) {
1243         pluginPortUpdated[in] = 0;
1244     }
1245 
1246     in = out = controlIn = controlOut = 0;
1247 
1248     for (i = 0; i < instance_count; i++) {   /* i is instance number */
1249         instance = &instances[i];
1250 
1251         instance->firstControlIn = controlIn;
1252         for (j = 0; j < MIDI_CONTROLLER_COUNT; j++) {
1253             instance->controllerMap[j] = -1;
1254         }
1255 
1256         plugin = instance->plugin;
1257         for (j = 0; j < plugin->descriptor->LADSPA_Plugin->PortCount; j++) {  /* j is LADSPA port number */
1258 
1259             LADSPA_PortDescriptor pod =
1260                 plugin->descriptor->LADSPA_Plugin->PortDescriptors[j];
1261 
1262             instance->pluginPortControlInNumbers[j] = -1;
1263 
1264             if (LADSPA_IS_PORT_AUDIO(pod)) {
1265 
1266                 if (LADSPA_IS_PORT_INPUT(pod)) {
1267                     plugin->descriptor->LADSPA_Plugin->connect_port
1268                         (instanceHandles[i], j, pluginInputBuffers[in++]);
1269 
1270                 } else if (LADSPA_IS_PORT_OUTPUT(pod)) {
1271                     plugin->descriptor->LADSPA_Plugin->connect_port
1272                         (instanceHandles[i], j, pluginOutputBuffers[out++]);
1273                 }
1274 
1275             } else if (LADSPA_IS_PORT_CONTROL(pod)) {
1276 
1277                 if (LADSPA_IS_PORT_INPUT(pod)) {
1278 
1279                     if (plugin->descriptor->get_midi_controller_for_port) {
1280 
1281                         int controller = plugin->descriptor->
1282                             get_midi_controller_for_port(instanceHandles[i], j);
1283 
1284                         if (controller == 0) {
1285                             MB_MESSAGE
1286                                 ("Buggy plugin: wants mapping for bank MSB\n");
1287                         } else if (controller == 32) {
1288                             MB_MESSAGE
1289                                 ("Buggy plugin: wants mapping for bank LSB\n");
1290                         } else if (DSSI_IS_CC(controller)) {
1291                             instance->controllerMap[DSSI_CC_NUMBER(controller)]
1292                                 = controlIn;
1293                         }
1294                     }
1295 
1296                     pluginControlInInstances[controlIn] = instance;
1297                     pluginControlInPortNumbers[controlIn] = j;
1298                     instance->pluginPortControlInNumbers[j] = controlIn;
1299 
1300                     pluginControlIns[controlIn] = get_port_default
1301                         (plugin->descriptor->LADSPA_Plugin, j);
1302 
1303                     plugin->descriptor->LADSPA_Plugin->connect_port
1304                         (instanceHandles[i], j, &pluginControlIns[controlIn++]);
1305 
1306                 } else if (LADSPA_IS_PORT_OUTPUT(pod)) {
1307                     plugin->descriptor->LADSPA_Plugin->connect_port
1308                         (instanceHandles[i], j, &pluginControlOuts[controlOut++]);
1309                 }
1310             }
1311         }  /* 'for (j...'  LADSPA port number */
1312 
1313         if (plugin->descriptor->LADSPA_Plugin->activate) {
1314             plugin->descriptor->LADSPA_Plugin->activate(instanceHandles[i]);
1315         }
1316 	instance->inactive = 0;
1317     } /* 'for (i...' instance number */
1318 
1319     assert(in == insTotal);
1320     assert(out == outsTotal);
1321     assert(controlIn == controlInsTotal);
1322     assert(controlOut == controlOutsTotal);
1323 
1324     /* Look up synth programs */
1325 
1326     for (i = 0; i < instance_count; i++) {
1327         instance = &instances[i];
1328 
1329         query_programs(instance);
1330 
1331         if (instance->plugin->descriptor->select_program &&
1332             instance->pluginProgramCount > 0) {
1333 
1334 	    /* select program at index 0 */
1335             unsigned long bank = instance->pluginPrograms[0].Bank;
1336             instance->pendingBankMSB = bank / 128;
1337             instance->pendingBankLSB = bank % 128;
1338             instance->pendingProgramChange = instance->pluginPrograms[0].Program;
1339 	    instance->uiNeedsProgramUpdate = 1;
1340         }
1341     }
1342 
1343     /* Create ALSA MIDI port */
1344 
1345 #ifdef MIDI_ALSA
1346     if (snd_seq_open(&alsaClient, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) {
1347 	fprintf(stderr, "\n%s: Error: Failed to open ALSA sequencer interface\n",
1348 		myName);
1349 	return 1;
1350     }
1351 
1352     snd_seq_set_client_name(alsaClient, clientName);
1353 
1354     if ((portid = snd_seq_create_simple_port
1355 	 (alsaClient, clientName,
1356 	  SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION)) < 0) {
1357 	fprintf(stderr, "\n%s: Error: Failed to create ALSA sequencer port\n",
1358 		myName);
1359 	return 1;
1360     }
1361 
1362     npfd = snd_seq_poll_descriptors_count(alsaClient, POLLIN);
1363     pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
1364     snd_seq_poll_descriptors(alsaClient, pfd, npfd, POLLIN);
1365 #endif /* MIDI_ALSA */
1366 
1367     mb_init("host: ");
1368 
1369     /* activate JACK and connect ports */
1370     if (jack_activate(jackClient)) {
1371         fprintf (stderr, "cannot activate jack client");
1372         exit(1);
1373     }
1374 
1375     if (autoconnect) {
1376         /* !FIX! this to more intelligently connect ports: */
1377         ports = jack_get_ports(jackClient, NULL,
1378                                "^" JACK_DEFAULT_AUDIO_TYPE "$",
1379                                JackPortIsPhysical|JackPortIsInput);
1380         if (ports && ports[0]) {
1381             for (i = 0, j = 0; i < outsTotal; ++i) {
1382                 if (jack_connect(jackClient, jack_port_name(outputPorts[i]),
1383                                  ports[j])) {
1384                     fprintf (stderr, "cannot connect output port %d\n", i);
1385                 }
1386                 if (!ports[++j]) j = 0;
1387             }
1388             free(ports);
1389         }
1390     }
1391 
1392     signal(SIGINT, signalHandler);
1393     signal(SIGTERM, signalHandler);
1394     signal(SIGHUP, signalHandler);
1395     signal(SIGQUIT, signalHandler);
1396     pthread_sigmask(SIG_UNBLOCK, &_signals, 0);
1397 
1398     /* Attempt to locate and start up a GUI for the plugin -- but
1399      * continue even if we can't */
1400     /* -FIX- Ack! So many windows all at once! */
1401     if (load_guis) {
1402         for (i = 0; i < instance_count; i++) {
1403             char tag[12];
1404             plugin = instances[i].plugin;
1405             snprintf(osc_path_tmp, 1024, "%s/%s", url, instances[i].friendly_name);
1406             snprintf(tag, 12, "channel %d", instances[i].channel);
1407             printf("\n%s: OSC URL is:\n%s\n\n", myName, osc_path_tmp);
1408 	    fflush(stdout);
1409             startGUI(plugin->dll->directory, plugin->dll->name,
1410                     plugin->descriptor->LADSPA_Plugin->Label, osc_path_tmp, tag);
1411         }
1412     }
1413 
1414     MB_MESSAGE("Ready\n");
1415 
1416     exiting = 0;
1417 
1418     while (!exiting) {
1419 
1420 #ifdef MIDI_ALSA
1421 	if (poll(pfd, npfd, 100) > 0) {
1422 	    midi_callback();
1423 	}
1424 #endif /* MIDI_ALSA */
1425 
1426 	/* Race conditions here, because the programs and ports are
1427 	   updated from the audio thread.  We at least try to minimise
1428 	   trouble by copying out before the expensive OSC call */
1429 
1430         for (i = 0; i < instance_count; i++) {
1431             instance = &instances[i];
1432             if (instance->uiNeedsProgramUpdate && instance->pendingProgramChange < 0) {
1433                 int bank = instance->currentBank;
1434                 int program = instance->currentProgram;
1435                 instance->uiNeedsProgramUpdate = 0;
1436                 if (instance->uiTarget) {
1437                     lo_send(instance->uiTarget, instance->ui_osc_program_path, "ii", bank, program);
1438                 }
1439             }
1440         }
1441 
1442 	for (i = 0; i < controlInsTotal; ++i) {
1443 	    if (pluginPortUpdated[i]) {
1444 		int port = pluginControlInPortNumbers[i];
1445 		float value = pluginControlIns[i];
1446                 instance = pluginControlInInstances[i];
1447 		pluginPortUpdated[i] = 0;
1448 		if (instance->uiTarget) {
1449 		    lo_send(instance->uiTarget, instance->ui_osc_control_path, "if", port, value);
1450 		}
1451 	    }
1452 	}
1453     }
1454 
1455     jack_client_close(jackClient);
1456 
1457     /* cleanup plugins */
1458     for (i = 0; i < instance_count; i++) {
1459         instance = &instances[i];
1460 
1461         if (instance->uiTarget) {
1462             lo_send(instance->uiTarget, instance->ui_osc_quit_path, "");
1463             lo_address_free(instance->uiTarget);
1464             instance->uiTarget = NULL;
1465         }
1466 
1467         if (instance->uiSource) {
1468             lo_address_free(instance->uiSource);
1469             instance->uiSource = NULL;
1470         }
1471 
1472         if (instance->plugin->descriptor->LADSPA_Plugin->deactivate) {
1473             instance->plugin->descriptor->LADSPA_Plugin->deactivate
1474 		(instanceHandles[i]);
1475 	}
1476 
1477         if (instance->plugin->descriptor->LADSPA_Plugin->cleanup) {
1478             instance->plugin->descriptor->LADSPA_Plugin->cleanup
1479 		(instanceHandles[i]);
1480 	}
1481     }
1482 
1483     sleep(1);
1484     sigemptyset (&_signals);
1485     sigaddset(&_signals, SIGHUP);
1486     pthread_sigmask(SIG_BLOCK, &_signals, 0);
1487     kill(0, SIGHUP);
1488 
1489     return 0;
1490 }
1491 
get_port_default(const LADSPA_Descriptor * plugin,int port)1492 LADSPA_Data get_port_default(const LADSPA_Descriptor *plugin, int port)
1493 {
1494     LADSPA_PortRangeHint hint = plugin->PortRangeHints[port];
1495     float lower = hint.LowerBound *
1496 	(LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor) ? sample_rate : 1.0f);
1497     float upper = hint.UpperBound *
1498 	(LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor) ? sample_rate : 1.0f);
1499 
1500     if (!LADSPA_IS_HINT_HAS_DEFAULT(hint.HintDescriptor)) {
1501 	if (!LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) ||
1502 	    !LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor)) {
1503 	    /* No hint, its not bounded, wild guess */
1504 	    return 0.0f;
1505 	}
1506 
1507 	if (lower <= 0.0f && upper >= 0.0f) {
1508 	    /* It spans 0.0, 0.0 is often a good guess */
1509 	    return 0.0f;
1510 	}
1511 
1512 	/* No clues, return minimum */
1513 	return lower;
1514     }
1515 
1516     /* Try all the easy ones */
1517 
1518     if (LADSPA_IS_HINT_DEFAULT_0(hint.HintDescriptor)) {
1519 	return 0.0f;
1520     } else if (LADSPA_IS_HINT_DEFAULT_1(hint.HintDescriptor)) {
1521 	return 1.0f;
1522     } else if (LADSPA_IS_HINT_DEFAULT_100(hint.HintDescriptor)) {
1523 	return 100.0f;
1524     } else if (LADSPA_IS_HINT_DEFAULT_440(hint.HintDescriptor)) {
1525 	return 440.0f;
1526     }
1527 
1528     /* All the others require some bounds */
1529 
1530     if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor)) {
1531 	if (LADSPA_IS_HINT_DEFAULT_MINIMUM(hint.HintDescriptor)) {
1532 	    return lower;
1533 	}
1534     }
1535     if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor)) {
1536 	if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint.HintDescriptor)) {
1537 	    return upper;
1538 	}
1539 	if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor)) {
1540             if (LADSPA_IS_HINT_LOGARITHMIC(hint.HintDescriptor) &&
1541                 lower > 0.0f && upper > 0.0f) {
1542                 if (LADSPA_IS_HINT_DEFAULT_LOW(hint.HintDescriptor)) {
1543                     return expf(logf(lower) * 0.75f + logf(upper) * 0.25f);
1544                 } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hint.HintDescriptor)) {
1545                     return expf(logf(lower) * 0.5f + logf(upper) * 0.5f);
1546                 } else if (LADSPA_IS_HINT_DEFAULT_HIGH(hint.HintDescriptor)) {
1547                     return expf(logf(lower) * 0.25f + logf(upper) * 0.75f);
1548                 }
1549             } else {
1550                 if (LADSPA_IS_HINT_DEFAULT_LOW(hint.HintDescriptor)) {
1551                     return lower * 0.75f + upper * 0.25f;
1552                 } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hint.HintDescriptor)) {
1553                     return lower * 0.5f + upper * 0.5f;
1554                 } else if (LADSPA_IS_HINT_DEFAULT_HIGH(hint.HintDescriptor)) {
1555                     return lower * 0.25f + upper * 0.75f;
1556                 }
1557 	    }
1558 	}
1559     }
1560 
1561     /* fallback */
1562     return 0.0f;
1563 }
1564 
osc_error(int num,const char * msg,const char * path)1565 void osc_error(int num, const char *msg, const char *path)
1566 {
1567     fprintf(stderr, "%s: liblo server error %d in path %s: %s\n",
1568 	    myName, num, path, msg);
1569 }
1570 
1571 int
osc_midi_handler(d3h_instance_t * instance,lo_arg ** argv)1572 osc_midi_handler(d3h_instance_t *instance, lo_arg **argv)
1573 {
1574     static snd_midi_event_t *alsaCoder = NULL;
1575     static snd_seq_event_t alsaEncodeBuffer[10];
1576     long count;
1577     snd_seq_event_t *ev = &alsaEncodeBuffer[0];
1578 
1579     if (verbose) {
1580 	printf("%s: OSC: got midi request for %s "
1581 	       "(%02x %02x %02x %02x)\n", myName, instance->friendly_name,
1582 	       argv[0]->m[0], argv[0]->m[1], argv[0]->m[2], argv[0]->m[3]);
1583     }
1584 
1585     if (!alsaCoder) {
1586         if (snd_midi_event_new(10, &alsaCoder)) {
1587             fprintf(stderr, "%s: Failed to initialise ALSA MIDI coder!\n",
1588 		    myName);
1589             return 0;
1590         }
1591     }
1592 
1593     snd_midi_event_reset_encode(alsaCoder);
1594 
1595     count = snd_midi_event_encode
1596 	(alsaCoder, (argv[0]->m) + 1, 3, alsaEncodeBuffer); /* ignore OSC "port id" in argv[0]->m[0] */
1597 
1598     if (!count || !snd_seq_ev_is_channel_type(ev)) {
1599         return 0;
1600     }
1601 
1602     /* substitute correct MIDI channel */
1603     ev->data.note.channel = instance->channel;
1604 
1605     if (ev->type == SND_SEQ_EVENT_NOTEON && ev->data.note.velocity == 0) {
1606         ev->type =  SND_SEQ_EVENT_NOTEOFF;
1607     }
1608 
1609     pthread_mutex_lock(&midiEventBufferMutex);
1610 
1611     if (midiEventReadIndex == midiEventWriteIndex + 1) {
1612 
1613         fprintf(stderr, "%s: Warning: MIDI event buffer overflow!\n", myName);
1614 
1615     } else if (ev->type == SND_SEQ_EVENT_CONTROLLER &&
1616                (ev->data.control.param == 0 || ev->data.control.param == 32)) {
1617 
1618         fprintf(stderr, "%s: Warning: %s UI sent bank select controller (should use /program OSC call), ignoring\n", myName, instance->friendly_name);
1619 
1620     } else if (ev->type == SND_SEQ_EVENT_PGMCHANGE) {
1621 
1622         fprintf(stderr, "%s: Warning: %s UI sent program change (should use /program OSC call), ignoring\n", myName, instance->friendly_name);
1623 
1624     } else {
1625 
1626         midiEventBuffer[midiEventWriteIndex] = *ev;
1627         midiEventWriteIndex = (midiEventWriteIndex + 1) % EVENT_BUFFER_SIZE;
1628 
1629     }
1630 
1631     pthread_mutex_unlock(&midiEventBufferMutex);
1632 
1633     return 0;
1634 }
1635 
1636 int
osc_control_handler(d3h_instance_t * instance,lo_arg ** argv)1637 osc_control_handler(d3h_instance_t *instance, lo_arg **argv)
1638 {
1639     int port = argv[0]->i;
1640     LADSPA_Data value = argv[1]->f;
1641 
1642     if (port < 0 || port > instance->plugin->descriptor->LADSPA_Plugin->PortCount) {
1643 	fprintf(stderr, "%s: OSC: %s port number (%d) is out of range\n",
1644                 myName, instance->friendly_name, port);
1645 	return 0;
1646     }
1647     if (instance->pluginPortControlInNumbers[port] == -1) {
1648 	fprintf(stderr, "%s: OSC: %s port %d is not a control in\n",
1649                 myName, instance->friendly_name, port);
1650 	return 0;
1651     }
1652     pluginControlIns[instance->pluginPortControlInNumbers[port]] = value;
1653     if (verbose) {
1654 	printf("%s: OSC: %s port %d = %f\n",
1655 	       myName, instance->friendly_name, port, value);
1656     }
1657 
1658     return 0;
1659 }
1660 
1661 int
osc_program_handler(d3h_instance_t * instance,lo_arg ** argv)1662 osc_program_handler(d3h_instance_t *instance, lo_arg **argv)
1663 {
1664     int bank = argv[0]->i;
1665     int program = argv[1]->i;
1666     int i;
1667     int found = 0;
1668 
1669     for (i = 0; i < instance->pluginProgramCount; ++i) {
1670 	if (instance->pluginPrograms[i].Bank == bank &&
1671 	    instance->pluginPrograms[i].Program == program) {
1672 	    if (verbose) {
1673 		printf("%s: OSC: %s setting bank %d, program %d, name %s\n",
1674 		       myName,
1675 		       instance->friendly_name, bank, program,
1676 		       instance->pluginPrograms[i].Name);
1677 	    }
1678 	    found = 1;
1679 	    break;
1680 	}
1681     }
1682 
1683     if (!found) {
1684 	printf("%s: OSC: %s UI requested unknown program: bank %d, program %d: sending to plugin anyway (plugin should ignore it)\n",
1685 	       myName, instance->friendly_name, bank, program);
1686     }
1687 
1688     instance->pendingBankMSB = bank / 128;
1689     instance->pendingBankLSB = bank % 128;
1690     instance->pendingProgramChange = program;
1691 
1692     return 0;
1693 }
1694 
1695 int
osc_configure_handler(d3h_instance_t * instance,lo_arg ** argv)1696 osc_configure_handler(d3h_instance_t *instance, lo_arg **argv)
1697 {
1698     const char *key = (const char *)&argv[0]->s;
1699     const char *value = (const char *)&argv[1]->s;
1700     char *message;
1701 
1702     /* This is pretty much the simplest legal implementation of
1703      * configure in a DSSI host. */
1704 
1705     /* The host has the option to remember the set of (key,value)
1706      * pairs associated with a particular instance, so that if it
1707      * wants to restore the "same" instance on another occasion it can
1708      * just call configure() on it for each of those pairs and so
1709      * restore state without any input from a GUI.  Any real-world GUI
1710      * host will probably want to do that.  This host doesn't have any
1711      * concept of restoring an instance from one run to the next, so
1712      * we don't bother remembering these at all. */
1713 
1714     if (instance->plugin->descriptor->configure) {
1715 
1716 	int n = instance->number;
1717 	int m = n;
1718 
1719 	if (!strncmp(key, DSSI_RESERVED_CONFIGURE_PREFIX,
1720 		     strlen(DSSI_RESERVED_CONFIGURE_PREFIX))) {
1721 	    fprintf(stderr, "%s: OSC: UI for plugin '%s' attempted to use reserved configure key \"%s\", ignoring\n", myName, instance->friendly_name, key);
1722 	    return 0;
1723 	}
1724 
1725 	if (instance->plugin->instances > 1 &&
1726 	    !strncmp(key, DSSI_GLOBAL_CONFIGURE_PREFIX,
1727 		     strlen(DSSI_GLOBAL_CONFIGURE_PREFIX))) {
1728 	    while (n > 0 && instances[n-1].plugin == instances[m].plugin) --n;
1729 	    m = n + instances[n].plugin->instances - 1;
1730 	}
1731 
1732 	while (n <= m) {
1733 
1734 	    message = instances[n].plugin->descriptor->configure
1735 		(instanceHandles[n], key, value);
1736 	    if (message) {
1737 		printf("%s: on configure '%s' '%s', plugin '%s' returned error '%s'\n",
1738 		       myName, key, value, instance->friendly_name, message);
1739 		free(message);
1740 	    }
1741 
1742 	    // also call back on UIs for plugins other than the one
1743 	    // that requested this:
1744 	    if (n != instance->number && instances[n].uiTarget) {
1745 		lo_send(instances[n].uiTarget,
1746 			instances[n].ui_osc_configure_path, "ss", key, value);
1747 	    }
1748 
1749 	    /* configure invalidates bank and program information, so
1750 	       we should do this again now: */
1751 	    query_programs(&instances[n]);
1752 
1753 	    ++n;
1754 	}
1755     }
1756 
1757     return 0;
1758 }
1759 
1760 int
osc_update_handler(d3h_instance_t * instance,lo_arg ** argv,lo_address source)1761 osc_update_handler(d3h_instance_t *instance, lo_arg **argv, lo_address source)
1762 {
1763     const char *url = (char *)&argv[0]->s;
1764     const char *path;
1765     unsigned int i;
1766     char *host, *port;
1767     const char *chost, *cport;
1768 
1769     if (verbose) {
1770 	printf("%s: OSC: got update request from <%s>\n", myName, url);
1771     }
1772 
1773     if (instance->uiTarget) lo_address_free(instance->uiTarget);
1774     host = lo_url_get_hostname(url);
1775     port = lo_url_get_port(url);
1776     instance->uiTarget = lo_address_new(host, port);
1777     free(host);
1778     free(port);
1779 
1780     if (instance->uiSource) lo_address_free(instance->uiSource);
1781     chost = lo_address_get_hostname(source);
1782     cport = lo_address_get_port(source);
1783     instance->uiSource = lo_address_new(chost, cport);
1784 
1785     path = lo_url_get_path(url);
1786 
1787     if (instance->ui_osc_control_path) free(instance->ui_osc_control_path);
1788     instance->ui_osc_control_path = (char *)malloc(strlen(path) + 10);
1789     sprintf(instance->ui_osc_control_path, "%s/control", path);
1790 
1791     if (instance->ui_osc_configure_path) free(instance->ui_osc_configure_path);
1792     instance->ui_osc_configure_path = (char *)malloc(strlen(path) + 12);
1793     sprintf(instance->ui_osc_configure_path, "%s/configure", path);
1794 
1795     if (instance->ui_osc_program_path) free(instance->ui_osc_program_path);
1796     instance->ui_osc_program_path = (char *)malloc(strlen(path) + 10);
1797     sprintf(instance->ui_osc_program_path, "%s/program", path);
1798 
1799     if (instance->ui_osc_quit_path) free(instance->ui_osc_quit_path);
1800     instance->ui_osc_quit_path = (char *)malloc(strlen(path) + 10);
1801     sprintf(instance->ui_osc_quit_path, "%s/quit", path);
1802 
1803     if (instance->ui_osc_rate_path) free(instance->ui_osc_rate_path);
1804     instance->ui_osc_rate_path = (char *)malloc(strlen(path) + 13);
1805     sprintf(instance->ui_osc_rate_path, "%s/sample-rate", path);
1806 
1807     if (instance->ui_osc_show_path) free(instance->ui_osc_show_path);
1808     instance->ui_osc_show_path = (char *)malloc(strlen(path) + 10);
1809     sprintf(instance->ui_osc_show_path, "%s/show", path);
1810 
1811     free((char *)path);
1812 
1813     /* Send sample rate */
1814     lo_send(instance->uiTarget, instance->ui_osc_rate_path, "i", lrintf(sample_rate));
1815 
1816     /* At this point a more substantial host might also call
1817      * configure() on the UI to set any state that it had remembered
1818      * for the plugin instance.  But we don't remember state for
1819      * plugin instances (see our own configure() implementation in
1820      * osc_configure_handler), and so we have nothing to send except
1821      * the optional project directory. */
1822 
1823     if (projectDirectory) {
1824 	lo_send(instance->uiTarget, instance->ui_osc_configure_path, "ss",
1825 		DSSI_PROJECT_DIRECTORY_KEY, projectDirectory);
1826     }
1827 
1828     /* Send current bank/program  (-FIX- another race...) */
1829     if (instance->pendingProgramChange < 0) {
1830         unsigned long bank = instance->currentBank;
1831         unsigned long program = instance->currentProgram;
1832         instance->uiNeedsProgramUpdate = 0;
1833         if (instance->uiTarget) {
1834             lo_send(instance->uiTarget, instance->ui_osc_program_path, "ii", bank, program);
1835         }
1836     }
1837 
1838     /* Send control ports */
1839     for (i = 0; i < instance->plugin->controlIns; i++) {
1840         int in = i + instance->firstControlIn;
1841 	int port = pluginControlInPortNumbers[in];
1842 	lo_send(instance->uiTarget, instance->ui_osc_control_path, "if", port,
1843                 pluginControlIns[in]);
1844 	/* Avoid overloading the GUI if there are lots and lots of ports */
1845 	if ((i+1) % 50 == 0) usleep(300000);
1846     }
1847 
1848     /* Send 'show' */
1849     if (!instance->ui_initial_show_sent) {
1850 	lo_send(instance->uiTarget, instance->ui_osc_show_path, "");
1851 	instance->ui_initial_show_sent = 1;
1852     }
1853 
1854     return 0;
1855 }
1856 
1857 int
osc_exiting_handler(d3h_instance_t * instance,lo_arg ** argv)1858 osc_exiting_handler(d3h_instance_t *instance, lo_arg **argv)
1859 {
1860     int i;
1861 
1862     if (verbose) {
1863 	printf("%s: OSC: got exiting notification for instance %d\n", myName,
1864 	       instance->number);
1865     }
1866 
1867     if (instance->uiTarget) {
1868         lo_address_free(instance->uiTarget);
1869         instance->uiTarget = NULL;
1870     }
1871 
1872     if (instance->uiSource) {
1873         lo_address_free(instance->uiSource);
1874         instance->uiSource = NULL;
1875     }
1876 
1877     if (instance->plugin) {
1878 
1879 	/*!!! No, this isn't safe -- plugins deactivated in this way
1880 	  would still be included in a run_multiple_synths call unless
1881 	  we re-jigged the instance array at the same time -- leave it
1882 	  for now
1883 	if (instance->plugin->descriptor->LADSPA_Plugin->deactivate) {
1884             instance->plugin->descriptor->LADSPA_Plugin->deactivate
1885 		(instanceHandles[instance->number]);
1886 	}
1887 	*/
1888 	/* Leave this flag though, as we need it to determine when to exit */
1889 	instance->inactive = 1;
1890     }
1891 
1892     /* Do we have any plugins left running? */
1893 
1894     for (i = 0; i < instance_count; ++i) {
1895 	if (!instances[i].inactive) return 0;
1896     }
1897 
1898     if (verbose) {
1899 	printf("%s: That was the last remaining plugin, exiting...\n", myName);
1900     }
1901     exiting = 1;
1902     return 0;
1903 }
1904 
osc_debug_handler(const char * path,const char * types,lo_arg ** argv,int argc,void * data,void * user_data)1905 int osc_debug_handler(const char *path, const char *types, lo_arg **argv,
1906                       int argc, void *data, void *user_data)
1907 {
1908     int i;
1909 
1910     printf("%s: got unhandled OSC message:\npath: <%s>\n", myName, path);
1911     for (i=0; i<argc; i++) {
1912         printf("%s: arg %d '%c' ", myName, i, types[i]);
1913         lo_arg_pp(types[i], argv[i]);
1914         printf("\n");
1915     }
1916     printf("%s:\n", myName);
1917 
1918     return 1;
1919 }
1920 
osc_message_handler(const char * path,const char * types,lo_arg ** argv,int argc,void * data,void * user_data)1921 int osc_message_handler(const char *path, const char *types, lo_arg **argv,
1922                         int argc, void *data, void *user_data)
1923 {
1924     int i;
1925     d3h_instance_t *instance = NULL;
1926     const char *method;
1927     unsigned int flen = 0;
1928     lo_message message;
1929     lo_address source;
1930     int send_to_ui = 0;
1931 
1932     if (strncmp(path, "/dssi/", 6))
1933         return osc_debug_handler(path, types, argv, argc, data, user_data);
1934 
1935     for (i = 0; i < instance_count; i++) {
1936 	flen = strlen(instances[i].friendly_name);
1937         if (!strncmp(path + 6, instances[i].friendly_name, flen) &&
1938 	    *(path + 6 + flen) == '/') { /* avoid matching prefix only */
1939             instance = &instances[i];
1940             break;
1941         }
1942     }
1943     if (!instance)
1944         return osc_debug_handler(path, types, argv, argc, data, user_data);
1945 
1946     /* no -- see comment in osc_exiting_handler */
1947     /*
1948     if (instance->inactive)
1949 	return 0;
1950     */
1951     method = path + 6 + flen;
1952     if (*method != '/' || *(method + 1) == 0)
1953         return osc_debug_handler(path, types, argv, argc, data, user_data);
1954     method++;
1955 
1956     message = (lo_message)data;
1957     source = lo_message_get_source(message);
1958 
1959     if (instance->uiSource && instance->uiTarget) {
1960 	if (strcmp(lo_address_get_hostname(source),
1961 		   lo_address_get_hostname(instance->uiSource)) ||
1962 	    strcmp(lo_address_get_port(source),
1963 		   lo_address_get_port(instance->uiSource))) {
1964 	    /* This didn't come from our known UI for this plugin,
1965 	       so send an update to that as well */
1966 	    send_to_ui = 1;
1967 	}
1968     }
1969 
1970     if (!strcmp(method, "configure") && argc == 2 && !strcmp(types, "ss")) {
1971 
1972 	if (send_to_ui) {
1973 	    lo_send(instance->uiTarget, instance->ui_osc_configure_path, "ss",
1974 		    &argv[0]->s, &argv[1]->s);
1975 	}
1976 
1977         return osc_configure_handler(instance, argv);
1978 
1979     } else if (!strcmp(method, "control") && argc == 2 && !strcmp(types, "if")) {
1980 
1981 	if (send_to_ui) {
1982 	    lo_send(instance->uiTarget, instance->ui_osc_control_path, "if",
1983 		    argv[0]->i, argv[1]->f);
1984 	}
1985 
1986         return osc_control_handler(instance, argv);
1987 
1988     } else if (!strcmp(method, "midi") && argc == 1 && !strcmp(types, "m")) {
1989 
1990         return osc_midi_handler(instance, argv);
1991 
1992     } else if (!strcmp(method, "program") && argc == 2 && !strcmp(types, "ii")) {
1993 
1994 	if (send_to_ui) {
1995 	    lo_send(instance->uiTarget, instance->ui_osc_program_path, "ii",
1996 		    argv[0]->i, argv[1]->i);
1997 	}
1998 
1999         return osc_program_handler(instance, argv);
2000 
2001     } else if (!strcmp(method, "update") && argc == 1 && !strcmp(types, "s")) {
2002 
2003         return osc_update_handler(instance, argv, source);
2004 
2005     } else if (!strcmp(method, "exiting") && argc == 0) {
2006 
2007         return osc_exiting_handler(instance, argv);
2008     }
2009 
2010     return osc_debug_handler(path, types, argv, argc, data, user_data);
2011 }
2012 
2013