1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License
7  * as published by the Free Software Foundation; either version 2.1 of
8  * the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA
19  */
20 
21 
22 /* fluid_jack.c
23  *
24  * Driver for the JACK
25  *
26  * This code is derived from the simple_client example in the JACK
27  * source distribution. Many thanks to Paul Davis.
28  *
29  */
30 
31 #include "fluid_synth.h"
32 #include "fluid_adriver.h"
33 #include "fluid_mdriver.h"
34 #include "fluid_settings.h"
35 
36 #if JACK_SUPPORT
37 
38 #include <jack/jack.h>
39 #include <jack/midiport.h>
40 
41 #include "fluid_lash.h"
42 
43 
44 typedef struct _fluid_jack_audio_driver_t fluid_jack_audio_driver_t;
45 typedef struct _fluid_jack_midi_driver_t fluid_jack_midi_driver_t;
46 
47 
48 /* Clients are shared for drivers using the same server. */
49 typedef struct
50 {
51     jack_client_t *client;
52     char *server;                 /* Jack server name used */
53     fluid_jack_audio_driver_t *audio_driver;
54     fluid_jack_midi_driver_t *midi_driver;
55 } fluid_jack_client_t;
56 
57 /* Jack audio driver instance */
58 struct _fluid_jack_audio_driver_t
59 {
60     fluid_audio_driver_t driver;
61     fluid_jack_client_t *client_ref;
62 
63     jack_port_t **output_ports;
64     int num_output_ports;
65     float **output_bufs;
66 
67     jack_port_t **fx_ports;
68     int num_fx_ports;
69     float **fx_bufs;
70 
71     fluid_audio_func_t callback;
72     void *data;
73 };
74 
75 /* Jack MIDI driver instance */
76 struct _fluid_jack_midi_driver_t
77 {
78     fluid_midi_driver_t driver;
79     fluid_jack_client_t *client_ref;
80     int midi_port_count;
81     jack_port_t **midi_port; // array of midi port handles
82     fluid_midi_parser_t *parser;
83     int autoconnect_inputs;
84     fluid_atomic_int_t autoconnect_is_outdated;
85 };
86 
87 static fluid_jack_client_t *new_fluid_jack_client(fluid_settings_t *settings,
88         int isaudio, void *driver);
89 static int fluid_jack_client_register_ports(void *driver, int isaudio,
90         jack_client_t *client,
91         fluid_settings_t *settings);
92 
93 void fluid_jack_driver_shutdown(void *arg);
94 int fluid_jack_driver_srate(jack_nframes_t nframes, void *arg);
95 int fluid_jack_driver_bufsize(jack_nframes_t nframes, void *arg);
96 int fluid_jack_driver_process(jack_nframes_t nframes, void *arg);
97 void fluid_jack_port_registration(jack_port_id_t port, int is_registering, void *arg);
98 
99 static fluid_mutex_t last_client_mutex = FLUID_MUTEX_INIT;     /* Probably not necessary, but just in case drivers are created by multiple threads */
100 static fluid_jack_client_t *last_client = NULL;       /* Last unpaired client. For audio/MIDI driver pairing. */
101 
102 
103 void
fluid_jack_audio_driver_settings(fluid_settings_t * settings)104 fluid_jack_audio_driver_settings(fluid_settings_t *settings)
105 {
106     fluid_settings_register_str(settings, "audio.jack.id", "fluidsynth", 0);
107     fluid_settings_register_int(settings, "audio.jack.multi", 0, 0, 1, FLUID_HINT_TOGGLED);
108     fluid_settings_register_int(settings, "audio.jack.autoconnect", 0, 0, 1, FLUID_HINT_TOGGLED);
109     fluid_settings_register_str(settings, "audio.jack.server", "", 0);
110 }
111 
112 /*
113  * Connect all midi input ports to all terminal midi output ports
114  */
115 void
fluid_jack_midi_autoconnect(jack_client_t * client,fluid_jack_midi_driver_t * midi_driver)116 fluid_jack_midi_autoconnect(jack_client_t *client, fluid_jack_midi_driver_t *midi_driver)
117 {
118     int i, j;
119     const char **midi_source_ports;
120 
121     midi_source_ports = jack_get_ports(client, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal);
122 
123     if(midi_source_ports != NULL)
124     {
125         for(j = 0; midi_source_ports[j] != NULL; j++)
126         {
127             for(i = 0; i < midi_driver->midi_port_count; i++)
128             {
129                 FLUID_LOG(FLUID_INFO, "jack midi autoconnect \"%s\" to \"%s\"", midi_source_ports[j], jack_port_name(midi_driver->midi_port[i]));
130                 jack_connect(client, midi_source_ports[j], jack_port_name(midi_driver->midi_port[i]));
131             }
132         }
133 
134         jack_free(midi_source_ports);
135     }
136 
137     fluid_atomic_int_set(&midi_driver->autoconnect_is_outdated, FALSE);
138 }
139 
140 /*
141  * Create Jack client as necessary, share clients of the same server.
142  * @param settings Settings object
143  * @param isaudio TRUE if audio driver, FALSE if MIDI
144  * @param driver fluid_jack_audio_driver_t or fluid_jack_midi_driver_t
145  * @param data The user data instance associated with the driver (fluid_synth_t for example)
146  * @return New or paired Audio/MIDI Jack client
147  */
148 static fluid_jack_client_t *
new_fluid_jack_client(fluid_settings_t * settings,int isaudio,void * driver)149 new_fluid_jack_client(fluid_settings_t *settings, int isaudio, void *driver)
150 {
151     fluid_jack_client_t *client_ref = NULL;
152     char *server = NULL;
153     char *client_name;
154     char name[64];
155 
156     if(fluid_settings_dupstr(settings, isaudio ? "audio.jack.server"          /* ++ alloc server name */
157                              : "midi.jack.server", &server) != FLUID_OK)
158     {
159         return NULL;
160     }
161 
162     fluid_mutex_lock(last_client_mutex);      /* ++ lock last_client */
163 
164     /* If the last client uses the same server and is not the same type (audio or MIDI),
165      * then re-use the client. */
166     if(last_client &&
167             (last_client->server != NULL && server != NULL && FLUID_STRCMP(last_client->server, server) == 0) &&
168             ((!isaudio && last_client->midi_driver == NULL) || (isaudio && last_client->audio_driver == NULL)))
169     {
170         client_ref = last_client;
171 
172         /* Register ports */
173         if(fluid_jack_client_register_ports(driver, isaudio, client_ref->client, settings) == FLUID_OK)
174         {
175             last_client = NULL; /* No more pairing for this client */
176 
177             if(isaudio)
178             {
179                 fluid_atomic_pointer_set(&client_ref->audio_driver, driver);
180             }
181             else
182             {
183                 fluid_atomic_pointer_set(&client_ref->midi_driver, driver);
184             }
185         }
186         else
187         {
188             // do not free client_ref and do not goto error_recovery
189             // client_ref is being used by another audio or midi driver. Freeing it here will lead to a double free.
190             client_ref = NULL;
191         }
192 
193         fluid_mutex_unlock(last_client_mutex);        /* -- unlock last_client */
194 
195         if(server)
196         {
197             FLUID_FREE(server);
198         }
199 
200         return client_ref;
201     }
202 
203     /* No existing client for this Jack server */
204     client_ref = FLUID_NEW(fluid_jack_client_t);
205 
206     if(!client_ref)
207     {
208         FLUID_LOG(FLUID_PANIC, "Out of memory");
209         goto error_recovery;
210     }
211 
212     FLUID_MEMSET(client_ref, 0, sizeof(fluid_jack_client_t));
213 
214     fluid_settings_dupstr(settings, isaudio ? "audio.jack.id"    /* ++ alloc client name */
215                           : "midi.jack.id", &client_name);
216 
217     if(client_name != NULL && client_name[0] != 0)
218     {
219         FLUID_SNPRINTF(name, sizeof(name), "%s", client_name);
220     }
221     else
222     {
223         FLUID_STRNCPY(name, "fluidsynth", sizeof(name));
224     }
225 
226     name[63] = '\0';
227 
228     if(client_name)
229     {
230         FLUID_FREE(client_name);    /* -- free client name */
231     }
232 
233     /* Open a connection to the Jack server and use the server name if specified */
234     if(server && server[0] != '\0')
235     {
236         client_ref->client = jack_client_open(name, JackServerName, NULL, server);
237     }
238     else
239     {
240         client_ref->client = jack_client_open(name, JackNullOption, NULL);
241     }
242 
243     if(!client_ref->client)
244     {
245         FLUID_LOG(FLUID_ERR, "Failed to connect to Jack server.");
246         goto error_recovery;
247     }
248 
249     jack_set_port_registration_callback(client_ref->client, fluid_jack_port_registration, client_ref);
250     jack_set_process_callback(client_ref->client, fluid_jack_driver_process, client_ref);
251     jack_set_buffer_size_callback(client_ref->client, fluid_jack_driver_bufsize, client_ref);
252     jack_set_sample_rate_callback(client_ref->client, fluid_jack_driver_srate, client_ref);
253     jack_on_shutdown(client_ref->client, fluid_jack_driver_shutdown, client_ref);
254 
255     /* Register ports */
256     if(fluid_jack_client_register_ports(driver, isaudio, client_ref->client, settings) != FLUID_OK)
257     {
258         goto error_recovery;
259     }
260 
261     /* tell the JACK server that we are ready to roll */
262     if(jack_activate(client_ref->client))
263     {
264         FLUID_LOG(FLUID_ERR, "Failed to activate Jack client");
265         goto error_recovery;
266     }
267 
268     /* tell the lash server our client name */
269 #ifdef HAVE_LASH
270     {
271         int enable_lash = 0;
272         fluid_settings_getint(settings, "lash.enable", &enable_lash);
273 
274         if(enable_lash)
275         {
276             fluid_lash_jack_client_name(fluid_lash_client, name);
277         }
278     }
279 #endif /* HAVE_LASH */
280 
281     client_ref->server = server;        /* !! takes over allocation */
282     server = NULL;      /* Set to NULL so it doesn't get freed below */
283 
284     last_client = client_ref;
285 
286     if(isaudio)
287     {
288         fluid_atomic_pointer_set(&client_ref->audio_driver, driver);
289     }
290     else
291     {
292         fluid_atomic_pointer_set(&client_ref->midi_driver, driver);
293     }
294 
295     fluid_mutex_unlock(last_client_mutex);        /* -- unlock last_client */
296 
297     if(server)
298     {
299         FLUID_FREE(server);
300     }
301 
302     return client_ref;
303 
304 error_recovery:
305 
306     fluid_mutex_unlock(last_client_mutex);        /* -- unlock clients list */
307 
308     if(server)
309     {
310         FLUID_FREE(server);    /* -- free server name */
311     }
312 
313     if(client_ref)
314     {
315         if(client_ref->client)
316         {
317             jack_client_close(client_ref->client);
318         }
319 
320         FLUID_FREE(client_ref);
321     }
322 
323     return NULL;
324 }
325 
326 static int
fluid_jack_client_register_ports(void * driver,int isaudio,jack_client_t * client,fluid_settings_t * settings)327 fluid_jack_client_register_ports(void *driver, int isaudio, jack_client_t *client,
328                                  fluid_settings_t *settings)
329 {
330     fluid_jack_audio_driver_t *dev;
331     char name[64];
332     int multi;
333     int i;
334     unsigned long jack_srate;
335     double sample_rate;
336 
337     if(!isaudio)
338     {
339         fluid_jack_midi_driver_t *dev = driver;
340         int midi_channels, ports;
341 
342         fluid_settings_getint(settings, "synth.midi-channels", &midi_channels);
343         ports = midi_channels / 16;
344 
345         if((dev->midi_port = FLUID_ARRAY(jack_port_t *, ports)) == NULL)
346         {
347             FLUID_LOG(FLUID_PANIC, "Out of memory");
348             return FLUID_FAILED;
349         }
350 
351         for(i = 0; i < ports; i++)
352         {
353             FLUID_SNPRINTF(name, sizeof(name), "midi_%02d", i);
354             dev->midi_port[i] = jack_port_register(client, name, JACK_DEFAULT_MIDI_TYPE,
355                                                    JackPortIsInput | JackPortIsTerminal, 0);
356 
357             if(dev->midi_port[i] == NULL)
358             {
359                 FLUID_LOG(FLUID_ERR, "Failed to create Jack MIDI port '%s'", name);
360                 FLUID_FREE(dev->midi_port);
361                 dev->midi_port = NULL;
362                 return FLUID_FAILED;
363             }
364         }
365 
366         dev->midi_port_count = ports;
367         return FLUID_OK;
368     }
369 
370     dev = driver;
371 
372     fluid_settings_getint(settings, "audio.jack.multi", &multi);
373 
374     if(!multi)
375     {
376         /* create the two audio output ports */
377         dev->num_output_ports = 1;
378         dev->num_fx_ports = 0;
379 
380         dev->output_ports = FLUID_ARRAY(jack_port_t *, 2 * dev->num_output_ports);
381 
382         if(dev->output_ports == NULL)
383         {
384             FLUID_LOG(FLUID_PANIC, "Out of memory");
385             return FLUID_FAILED;
386         }
387 
388         dev->output_bufs = FLUID_ARRAY(float *, 2 * dev->num_output_ports);
389         FLUID_MEMSET(dev->output_ports, 0, 2 * dev->num_output_ports * sizeof(jack_port_t *));
390 
391         dev->output_ports[0]
392             = jack_port_register(client, "left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
393 
394         dev->output_ports[1]
395             = jack_port_register(client, "right", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
396 
397         if(dev->output_ports[0] == NULL || dev->output_ports[1] == NULL)
398         {
399             FLUID_LOG(FLUID_ERR, "Failed to create Jack audio port '%s'",
400                       (dev->output_ports[0] == NULL ? (dev->output_ports[1] == NULL ? "left & right" : "left") : "right"));
401             goto error_recovery;
402         }
403     }
404     else
405     {
406         fluid_settings_getint(settings, "synth.audio-channels", &dev->num_output_ports);
407 
408         dev->output_ports = FLUID_ARRAY(jack_port_t *, 2 * dev->num_output_ports);
409 
410         if(dev->output_ports == NULL)
411         {
412             FLUID_LOG(FLUID_PANIC, "Out of memory");
413             return FLUID_FAILED;
414         }
415 
416         dev->output_bufs = FLUID_ARRAY(float *, 2 * dev->num_output_ports);
417 
418         if(dev->output_bufs == NULL)
419         {
420             FLUID_LOG(FLUID_PANIC, "Out of memory");
421             goto error_recovery;
422         }
423 
424         FLUID_MEMSET(dev->output_ports, 0, 2 * dev->num_output_ports * sizeof(jack_port_t *));
425 
426         for(i = 0; i < dev->num_output_ports; i++)
427         {
428             sprintf(name, "l_%02d", i);
429 
430             if((dev->output_ports[2 * i]
431                     = jack_port_register(client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) == NULL)
432             {
433                 FLUID_LOG(FLUID_ERR, "Failed to create Jack audio port '%s'", name);
434                 goto error_recovery;
435             }
436 
437             sprintf(name, "r_%02d", i);
438 
439             if((dev->output_ports[2 * i + 1]
440                     = jack_port_register(client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) == NULL)
441             {
442                 FLUID_LOG(FLUID_ERR, "Failed to create Jack audio port '%s'", name);
443                 goto error_recovery;
444             }
445         }
446 
447         fluid_settings_getint(settings, "synth.effects-channels", &dev->num_fx_ports);
448         fluid_settings_getint(settings, "synth.effects-groups", &i);
449 
450         dev->num_fx_ports *= i;
451         dev->fx_ports = FLUID_ARRAY(jack_port_t *, 2 * dev->num_fx_ports);
452 
453         if(dev->fx_ports == NULL)
454         {
455             FLUID_LOG(FLUID_PANIC, "Out of memory");
456             goto error_recovery;
457         }
458 
459         dev->fx_bufs = FLUID_ARRAY(float *, 2 * dev->num_fx_ports);
460 
461         if(dev->fx_bufs == NULL)
462         {
463             FLUID_LOG(FLUID_PANIC, "Out of memory");
464             goto error_recovery;
465         }
466 
467         FLUID_MEMSET(dev->fx_ports, 0, 2 * dev->num_fx_ports * sizeof(jack_port_t *));
468 
469         for(i = 0; i < dev->num_fx_ports; i++)
470         {
471             sprintf(name, "fx_l_%02d", i);
472 
473             if((dev->fx_ports[2 * i]
474                     = jack_port_register(client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) == NULL)
475             {
476                 FLUID_LOG(FLUID_ERR, "Failed to create Jack fx audio port '%s'", name);
477                 goto error_recovery;
478             }
479 
480             sprintf(name, "fx_r_%02d", i);
481 
482             if((dev->fx_ports[2 * i + 1]
483                     = jack_port_register(client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) == NULL)
484             {
485                 FLUID_LOG(FLUID_ERR, "Failed to create Jack fx audio port '%s'", name);
486                 goto error_recovery;
487             }
488         }
489     }
490 
491     /* Adjust sample rate to match JACK's */
492     jack_srate = jack_get_sample_rate(client);
493     FLUID_LOG(FLUID_DBG, "Jack engine sample rate: %lu", jack_srate);
494 
495     fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
496 
497     if((unsigned long)sample_rate != jack_srate)
498     {
499         fluid_synth_t* synth;
500         if(fluid_jack_obtain_synth(settings, &synth) == FLUID_OK)
501         {
502             FLUID_LOG(FLUID_INFO, "Jack sample rate mismatch, adjusting."
503                   " (synth.sample-rate=%lu, jackd=%lu)", (unsigned long)sample_rate, jack_srate);
504             fluid_synth_set_sample_rate_immediately(synth, jack_srate);
505         }
506         else
507         {
508             FLUID_LOG(FLUID_WARN, "Jack sample rate mismatch (synth.sample-rate=%lu, jackd=%lu)"
509             " impossible to adjust, because the settings object provided to new_fluid_audio_driver2() was not used to create a synth."
510             , (unsigned long)sample_rate, jack_srate);
511         }
512     }
513 
514     return FLUID_OK;
515 
516 error_recovery:
517 
518     FLUID_FREE(dev->output_ports);
519     dev->output_ports = NULL;
520     FLUID_FREE(dev->fx_ports);
521     dev->fx_ports = NULL;
522     FLUID_FREE(dev->output_bufs);
523     dev->output_bufs = NULL;
524     FLUID_FREE(dev->fx_bufs);
525     dev->fx_bufs = NULL;
526     return FLUID_FAILED;
527 }
528 
529 static void
fluid_jack_client_close(fluid_jack_client_t * client_ref,void * driver)530 fluid_jack_client_close(fluid_jack_client_t *client_ref, void *driver)
531 {
532     if(client_ref->audio_driver == driver)
533     {
534         fluid_atomic_pointer_set(&client_ref->audio_driver, NULL);
535     }
536     else if(client_ref->midi_driver == driver)
537     {
538         fluid_atomic_pointer_set(&client_ref->midi_driver, NULL);
539     }
540 
541     if(client_ref->audio_driver || client_ref->midi_driver)
542     {
543         fluid_msleep(100);  /* FIXME - Hack to make sure that resources don't get freed while Jack callback is active */
544         return;
545     }
546 
547     fluid_mutex_lock(last_client_mutex);
548 
549     if(client_ref == last_client)
550     {
551         last_client = NULL;
552     }
553 
554     fluid_mutex_unlock(last_client_mutex);
555 
556     if(client_ref->client)
557     {
558         jack_client_close(client_ref->client);
559     }
560 
561     if(client_ref->server)
562     {
563         FLUID_FREE(client_ref->server);
564     }
565 
566     FLUID_FREE(client_ref);
567 }
568 
569 
570 fluid_audio_driver_t *
new_fluid_jack_audio_driver(fluid_settings_t * settings,fluid_synth_t * synth)571 new_fluid_jack_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
572 {
573     return new_fluid_jack_audio_driver2(settings, NULL, synth);
574 }
575 
576 fluid_audio_driver_t *
new_fluid_jack_audio_driver2(fluid_settings_t * settings,fluid_audio_func_t func,void * data)577 new_fluid_jack_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data)
578 {
579     fluid_jack_audio_driver_t *dev = NULL;
580     jack_client_t *client;
581     const char **jack_ports;      /* for looking up ports */
582     int autoconnect = 0;
583     int i;
584 
585     dev = FLUID_NEW(fluid_jack_audio_driver_t);
586 
587     if(dev == NULL)
588     {
589         FLUID_LOG(FLUID_PANIC, "Out of memory");
590         return NULL;
591     }
592 
593     FLUID_MEMSET(dev, 0, sizeof(fluid_jack_audio_driver_t));
594 
595     dev->callback = func;
596     dev->data = data;
597 
598     dev->client_ref = new_fluid_jack_client(settings, TRUE, dev);
599 
600     if(!dev->client_ref)
601     {
602         FLUID_FREE(dev);
603         return NULL;
604     }
605 
606     client = dev->client_ref->client;
607 
608     /* connect the ports. */
609 
610     /* find some physical ports and connect to them */
611     fluid_settings_getint(settings, "audio.jack.autoconnect", &autoconnect);
612 
613     if(autoconnect)
614     {
615         jack_ports = jack_get_ports(client, NULL, NULL, JackPortIsInput | JackPortIsPhysical);
616 
617         if(jack_ports && jack_ports[0])
618         {
619             int err, o = 0;
620             int connected = 0;
621 
622             for(i = 0; i < 2 * dev->num_output_ports; ++i)
623             {
624                 err = jack_connect(client, jack_port_name(dev->output_ports[i]), jack_ports[o++]);
625 
626                 if(err)
627                 {
628                     FLUID_LOG(FLUID_ERR, "Error connecting jack port");
629                 }
630                 else
631                 {
632                     connected++;
633                 }
634 
635                 if(!jack_ports[o])
636                 {
637                     o = 0;
638                 }
639             }
640 
641             o = 0;
642             for(i = 0; i < 2 * dev->num_fx_ports; ++i)
643             {
644                 err = jack_connect(client, jack_port_name(dev->fx_ports[i]), jack_ports[o++]);
645 
646                 if(err)
647                 {
648                     FLUID_LOG(FLUID_ERR, "Error connecting jack port");
649                 }
650                 else
651                 {
652                     connected++;
653                 }
654 
655                 if(!jack_ports[o])
656                 {
657                     o = 0;
658                 }
659             }
660 
661             jack_free(jack_ports);   /* free jack ports array (not the port values!) */
662         }
663         else
664         {
665             FLUID_LOG(FLUID_WARN, "Could not connect to any physical jack ports; fluidsynth is unconnected");
666         }
667     }
668 
669     return (fluid_audio_driver_t *) dev;
670 }
671 
672 /*
673  * delete_fluid_jack_audio_driver
674  */
675 void
delete_fluid_jack_audio_driver(fluid_audio_driver_t * p)676 delete_fluid_jack_audio_driver(fluid_audio_driver_t *p)
677 {
678     fluid_jack_audio_driver_t *dev = (fluid_jack_audio_driver_t *) p;
679     fluid_return_if_fail(dev != NULL);
680 
681     if(dev->client_ref != NULL)
682     {
683         fluid_jack_client_close(dev->client_ref, dev);
684     }
685 
686     FLUID_FREE(dev->output_bufs);
687     FLUID_FREE(dev->output_ports);
688     FLUID_FREE(dev->fx_bufs);
689     FLUID_FREE(dev->fx_ports);
690     FLUID_FREE(dev);
691 }
692 
693 /* Process function for audio and MIDI Jack drivers */
694 int
fluid_jack_driver_process(jack_nframes_t nframes,void * arg)695 fluid_jack_driver_process(jack_nframes_t nframes, void *arg)
696 {
697     fluid_jack_client_t *client = (fluid_jack_client_t *)arg;
698     fluid_jack_audio_driver_t *audio_driver;
699     fluid_jack_midi_driver_t *midi_driver;
700     float *left, *right;
701     int i;
702 
703     jack_midi_event_t midi_event;
704     fluid_midi_event_t *evt;
705     void *midi_buffer;
706     jack_nframes_t event_count;
707     jack_nframes_t event_index;
708     unsigned int u;
709 
710     /* Process MIDI events first, so that they take effect before audio synthesis */
711     midi_driver = fluid_atomic_pointer_get(&client->midi_driver);
712 
713     if(midi_driver)
714     {
715         if(fluid_atomic_int_get(&midi_driver->autoconnect_is_outdated))
716         {
717             fluid_jack_midi_autoconnect(client->client, midi_driver);
718         }
719 
720         for(i = 0; i < midi_driver->midi_port_count; i++)
721         {
722             midi_buffer = jack_port_get_buffer(midi_driver->midi_port[i], 0);
723             event_count = jack_midi_get_event_count(midi_buffer);
724 
725             for(event_index = 0; event_index < event_count; event_index++)
726             {
727                 jack_midi_event_get(&midi_event, midi_buffer, event_index);
728 
729                 /* let the parser convert the data into events */
730                 for(u = 0; u < midi_event.size; u++)
731                 {
732                     evt = fluid_midi_parser_parse(midi_driver->parser, midi_event.buffer[u]);
733 
734                     /* send the event to the next link in the chain */
735                     if(evt != NULL)
736                     {
737                         fluid_midi_event_set_channel(evt, fluid_midi_event_get_channel(evt) + i * 16);
738                         midi_driver->driver.handler(midi_driver->driver.data, evt);
739                     }
740                 }
741             }
742         }
743     }
744 
745     audio_driver = fluid_atomic_pointer_get(&client->audio_driver);
746 
747     if(audio_driver == NULL)
748     {
749         // shutting down
750         return FLUID_OK;
751     }
752 
753     if(audio_driver->callback == NULL && audio_driver->num_output_ports == 1 && audio_driver->num_fx_ports == 0)  /* i.e. audio.jack.multi=no */
754     {
755         left = (float *) jack_port_get_buffer(audio_driver->output_ports[0], nframes);
756         right = (float *) jack_port_get_buffer(audio_driver->output_ports[1], nframes);
757 
758         return fluid_synth_write_float(audio_driver->data, nframes, left, 0, 1, right, 0, 1);
759     }
760     else
761     {
762         int res;
763         fluid_audio_func_t callback = (audio_driver->callback != NULL) ? audio_driver->callback : (fluid_audio_func_t) fluid_synth_process;
764 
765         for(i = 0; i < audio_driver->num_output_ports; i++)
766         {
767             int k = i * 2;
768 
769             audio_driver->output_bufs[k] = (float *)jack_port_get_buffer(audio_driver->output_ports[k], nframes);
770             FLUID_MEMSET(audio_driver->output_bufs[k], 0, nframes * sizeof(float));
771 
772             k = 2 * i + 1;
773             audio_driver->output_bufs[k] = (float *)jack_port_get_buffer(audio_driver->output_ports[k], nframes);
774             FLUID_MEMSET(audio_driver->output_bufs[k], 0, nframes * sizeof(float));
775         }
776 
777         for(i = 0; i < audio_driver->num_fx_ports; i++)
778         {
779             int k = i * 2;
780 
781             audio_driver->fx_bufs[k] = (float *) jack_port_get_buffer(audio_driver->fx_ports[k], nframes);
782             FLUID_MEMSET(audio_driver->fx_bufs[k], 0, nframes * sizeof(float));
783 
784             k = 2 * i + 1;
785             audio_driver->fx_bufs[k] = (float *) jack_port_get_buffer(audio_driver->fx_ports[k], nframes);
786             FLUID_MEMSET(audio_driver->fx_bufs[k], 0, nframes * sizeof(float));
787         }
788 
789         res = callback(audio_driver->data,
790                         nframes,
791                         audio_driver->num_fx_ports * 2,
792                         audio_driver->fx_bufs,
793                         audio_driver->num_output_ports * 2,
794                         audio_driver->output_bufs);
795         if(res != FLUID_OK)
796         {
797             const char *cb_func_name = (audio_driver->callback != NULL) ? "Custom audio callback function" : "fluid_synth_process()";
798             FLUID_LOG(FLUID_PANIC, "%s returned an error. As a consequence, fluidsynth will now be removed from Jack's processing loop.", cb_func_name);
799         }
800         return res;
801     }
802 }
803 
804 int
fluid_jack_driver_bufsize(jack_nframes_t nframes,void * arg)805 fluid_jack_driver_bufsize(jack_nframes_t nframes, void *arg)
806 {
807     /*   printf("the maximum buffer size is now %lu\n", nframes); */
808     return 0;
809 }
810 
811 int
fluid_jack_driver_srate(jack_nframes_t nframes,void * arg)812 fluid_jack_driver_srate(jack_nframes_t nframes, void *arg)
813 {
814     /*   printf("the sample rate is now %lu/sec\n", nframes); */
815     /* FIXME: change the sample rate of the synthesizer! */
816     return 0;
817 }
818 
819 void
fluid_jack_driver_shutdown(void * arg)820 fluid_jack_driver_shutdown(void *arg)
821 {
822 //  fluid_jack_audio_driver_t* dev = (fluid_jack_audio_driver_t*) arg;
823     FLUID_LOG(FLUID_ERR, "Help! Lost the connection to the JACK server");
824     /*   exit (1); */
825 }
826 
827 void
fluid_jack_port_registration(jack_port_id_t port,int is_registering,void * arg)828 fluid_jack_port_registration(jack_port_id_t port, int is_registering, void *arg)
829 {
830     fluid_jack_client_t *client_ref = (fluid_jack_client_t *)arg;
831 
832     if(client_ref->midi_driver != NULL)
833     {
834         fluid_atomic_int_set(&client_ref->midi_driver->autoconnect_is_outdated, client_ref->midi_driver->autoconnect_inputs && is_registering != 0);
835     }
836 }
837 
fluid_jack_midi_driver_settings(fluid_settings_t * settings)838 void fluid_jack_midi_driver_settings(fluid_settings_t *settings)
839 {
840     fluid_settings_register_str(settings, "midi.jack.id", "fluidsynth-midi", 0);
841     fluid_settings_register_str(settings, "midi.jack.server", "", 0);
842 }
843 
844 /*
845  * new_fluid_jack_midi_driver
846  */
847 fluid_midi_driver_t *
new_fluid_jack_midi_driver(fluid_settings_t * settings,handle_midi_event_func_t handler,void * data)848 new_fluid_jack_midi_driver(fluid_settings_t *settings,
849                            handle_midi_event_func_t handler, void *data)
850 {
851     fluid_jack_midi_driver_t *dev;
852 
853     fluid_return_val_if_fail(handler != NULL, NULL);
854 
855     /* allocate the device */
856     dev = FLUID_NEW(fluid_jack_midi_driver_t);
857 
858     if(dev == NULL)
859     {
860         FLUID_LOG(FLUID_PANIC, "Out of memory");
861         return NULL;
862     }
863 
864     FLUID_MEMSET(dev, 0, sizeof(fluid_jack_midi_driver_t));
865 
866     dev->driver.handler = handler;
867     dev->driver.data = data;
868 
869     /* allocate one event to store the input data */
870     dev->parser = new_fluid_midi_parser();
871 
872     if(dev->parser == NULL)
873     {
874         FLUID_LOG(FLUID_PANIC, "Out of memory");
875         goto error_recovery;
876     }
877 
878     fluid_settings_getint(settings, "midi.autoconnect", &dev->autoconnect_inputs);
879     fluid_atomic_int_set(&dev->autoconnect_is_outdated, dev->autoconnect_inputs);
880 
881     dev->client_ref = new_fluid_jack_client(settings, FALSE, dev);
882 
883     if(!dev->client_ref)
884     {
885         goto error_recovery;
886     }
887 
888     return (fluid_midi_driver_t *)dev;
889 
890 error_recovery:
891     delete_fluid_jack_midi_driver((fluid_midi_driver_t *)dev);
892     return NULL;
893 }
894 
895 void
delete_fluid_jack_midi_driver(fluid_midi_driver_t * p)896 delete_fluid_jack_midi_driver(fluid_midi_driver_t *p)
897 {
898     fluid_jack_midi_driver_t *dev = (fluid_jack_midi_driver_t *)p;
899     fluid_return_if_fail(dev != NULL);
900 
901     if(dev->client_ref != NULL)
902     {
903         fluid_jack_client_close(dev->client_ref, dev);
904     }
905 
906     delete_fluid_midi_parser(dev->parser);
907     FLUID_FREE(dev->midi_port);
908     FLUID_FREE(dev);
909 }
910 
fluid_jack_obtain_synth(fluid_settings_t * settings,fluid_synth_t ** synth)911 int fluid_jack_obtain_synth(fluid_settings_t *settings, fluid_synth_t **synth)
912 {
913     void *data;
914 
915     if(!fluid_settings_is_realtime(settings, "synth.gain") ||
916        (data = fluid_settings_get_user_data(settings, "synth.gain")) == NULL)
917     {
918         return FLUID_FAILED;
919     }
920 
921     *synth = data;
922     return FLUID_OK;
923 }
924 
925 #endif /* JACK_SUPPORT */
926