a-fluidsynth
[ardour.git] / libs / plugins / a-fluidsynth.lv2 / a-fluidsynth.c
1 /* a-fluidsynth -- simple & robust x-platform fluidsynth LV2
2  *
3  * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #ifndef _GNU_SOURCE
20 #define _GNU_SOURCE
21 #endif
22
23 #include <stdbool.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #define AFS_URN "urn:ardour:a-fluidsynth"
28
29 #ifdef HAVE_LV2_1_10_0
30 #define x_forge_object lv2_atom_forge_object
31 #else
32 #define x_forge_object lv2_atom_forge_blank
33 #endif
34
35 #include "fluidsynth.h"
36
37 #include <lv2/lv2plug.in/ns/lv2core/lv2.h>
38 #include <lv2/lv2plug.in/ns/ext/atom/atom.h>
39 #include <lv2/lv2plug.in/ns/ext/atom/forge.h>
40 #include <lv2/lv2plug.in/ns/ext/atom/util.h>
41 #include <lv2/lv2plug.in/ns/ext/log/logger.h>
42 #include <lv2/lv2plug.in/ns/ext/midi/midi.h>
43 #include <lv2/lv2plug.in/ns/ext/patch/patch.h>
44 #include <lv2/lv2plug.in/ns/ext/state/state.h>
45 #include <lv2/lv2plug.in/ns/ext/urid/urid.h>
46 #include <lv2/lv2plug.in/ns/ext/worker/worker.h>
47
48 enum {
49         FS_PORT_CONTROL = 0,
50         FS_PORT_NOTIFY,
51         FS_PORT_OUT_L,
52         FS_PORT_OUT_R
53 };
54
55 enum {
56   CMD_APPLY    = 0,
57   CMD_FREE     = 1,
58 };
59
60 typedef struct {
61         /* ports */
62         const LV2_Atom_Sequence* control;
63   LV2_Atom_Sequence*       notify;
64         float*                   output[2];
65
66         /* fluid synth */
67         fluid_settings_t* settings;
68         fluid_synth_t*    synth;
69         int               synthId;
70
71         /* lv2 URIDs */
72         LV2_URID atom_Blank;
73         LV2_URID atom_Object;
74         LV2_URID atom_URID;
75         LV2_URID atom_Path;
76         LV2_URID midi_MidiEvent;
77         LV2_URID patch_Get;
78         LV2_URID patch_Set;
79         LV2_URID patch_property;
80         LV2_URID patch_value;
81         LV2_URID afs_sf2file;
82
83         /* lv2 extensions */
84         LV2_Log_Log*         log;
85         LV2_Log_Logger       logger;
86   LV2_Worker_Schedule* schedule;
87         LV2_Atom_Forge       forge;
88         LV2_Atom_Forge_Frame frame;
89
90         /* state */
91         bool panic;
92         bool initialized;
93         bool inform_ui;
94
95         char current_sf2_file_path[1024];
96         char queue_sf2_file_path[1024];
97         bool reinit_in_progress; // set in run, cleared in work_response
98         bool queue_reinit; // set in restore, cleared in work_response
99
100         fluid_midi_event_t* fmidi_event;
101
102 } AFluidSynth;
103
104 /* *****************************************************************************
105  * helpers
106  */
107 static bool
108 load_sf2 (AFluidSynth* self, const char* fn)
109 {
110         const int synth_id = fluid_synth_sfload (self->synth, fn, 1);
111
112         if (synth_id == FLUID_FAILED) {
113                 return false;
114         }
115
116         fluid_sfont_t* const sfont = fluid_synth_get_sfont_by_id (self->synth, synth_id);
117         if (!sfont) {
118                 return false;
119         }
120
121         int chn;
122         fluid_preset_t preset;
123         sfont->iteration_start (sfont);
124         for (chn = 0; sfont->iteration_next (sfont, &preset) && chn < 15; ++chn) {
125                 fluid_synth_program_select (self->synth, chn, synth_id,
126                                 preset.get_banknum (&preset), preset.get_num (&preset));
127         }
128
129         if (chn == 0) {
130                 return false;
131         }
132
133         return true;
134 }
135
136 static const LV2_Atom*
137 parse_patch_msg (AFluidSynth* self, const LV2_Atom_Object* obj)
138 {
139         const LV2_Atom* property = NULL;
140         const LV2_Atom* file_path = NULL;
141
142         if (obj->body.otype != self->patch_Set) {
143                 return NULL;
144         }
145
146         lv2_atom_object_get (obj, self->patch_property, &property, 0);
147         if (!property || property->type != self->atom_URID) {
148                 return NULL;
149         } else if (((const LV2_Atom_URID*)property)->body != self->afs_sf2file) {
150                 return NULL;
151         }
152
153         lv2_atom_object_get(obj, self->patch_value, &file_path, 0);
154         if (!file_path || file_path->type != self->atom_Path) {
155                 return NULL;
156         }
157
158         return file_path;
159 }
160
161
162 static void
163 inform_ui (AFluidSynth* self)
164 {
165         if (strlen (self->current_sf2_file_path) == 0) {
166                 return;
167         }
168
169         LV2_Atom_Forge_Frame frame;
170         lv2_atom_forge_frame_time (&self->forge, 0);
171         x_forge_object(&self->forge, &frame, 1, self->patch_Set);
172         lv2_atom_forge_property_head (&self->forge, self->patch_property, 0);
173         lv2_atom_forge_urid (&self->forge, self->afs_sf2file);
174         lv2_atom_forge_property_head (&self->forge, self->patch_value, 0);
175         lv2_atom_forge_path( &self->forge, self->current_sf2_file_path, strlen(self->current_sf2_file_path));
176
177         lv2_atom_forge_pop (&self->forge, &frame);
178 }
179
180 /* *****************************************************************************
181  * LV2 Plugin
182  */
183
184 static LV2_Handle
185 instantiate (const LV2_Descriptor*     descriptor,
186              double                    rate,
187              const char*               bundle_path,
188              const LV2_Feature* const* features)
189 {
190         AFluidSynth* self = (AFluidSynth*)calloc (1, sizeof (AFluidSynth));
191
192         if (!self) {
193                 return NULL;
194         }
195
196         LV2_URID_Map* map = NULL;
197
198         for (int i=0; features[i] != NULL; ++i) {
199                 if (!strcmp (features[i]->URI, LV2_URID__map)) {
200                         map = (LV2_URID_Map*)features[i]->data;
201                 } else if (!strcmp (features[i]->URI, LV2_LOG__log)) {
202                         self->log = (LV2_Log_Log*)features[i]->data;
203                 } else if (!strcmp (features[i]->URI, LV2_WORKER__schedule)) {
204                         self->schedule = (LV2_Worker_Schedule*)features[i]->data;
205                 }
206         }
207
208         lv2_log_logger_init (&self->logger, map, self->log);
209
210         if (!map) {
211                 lv2_log_error (&self->logger, "a-fluidsynth.lv2: Host does not support urid:map\n");
212                 free (self);
213                 return NULL;
214         }
215
216         if (!self->schedule) {
217                 lv2_log_error (&self->logger, "a-fluidsynth.lv2: Host does not support worker:schedule\n");
218                 free (self);
219                 return NULL;
220         }
221
222         /* initialize fluid synth */
223         self->settings = new_fluid_settings ();
224
225         if (!self->settings) {
226                 lv2_log_error (&self->logger, "a-fluidsynth.lv2: cannot allocate Fluid Settings\n");
227                 free (self);
228                 return NULL;
229         }
230
231         fluid_settings_setnum (self->settings, "synth.sample-rate", rate);
232         fluid_settings_setint (self->settings, "synth.parallel-render", 1);
233         fluid_settings_setint (self->settings, "synth.threadsafe-api", 0);
234
235         self->synth = new_fluid_synth (self->settings);
236
237         if (!self->synth) {
238                 lv2_log_error (&self->logger, "a-fluidsynth.lv2: cannot allocate Fluid Synth\n");
239     delete_fluid_settings (self->settings);
240                 free (self);
241                 return NULL;
242         }
243
244         fluid_synth_set_gain (self->synth, 1.0f);
245         fluid_synth_set_polyphony (self->synth, 32);
246         fluid_synth_set_sample_rate (self->synth, (float)rate);
247
248         self->fmidi_event = new_fluid_midi_event ();
249
250         if (!self->fmidi_event) {
251                 lv2_log_error (&self->logger, "a-fluidsynth.lv2: cannot allocate Fluid Event\n");
252                 delete_fluid_synth (self->synth);
253     delete_fluid_settings (self->settings);
254                 free (self);
255                 return NULL;
256         }
257
258         /* initialize plugin state */
259
260         self->panic = true;
261         self->inform_ui = false;
262         self->initialized = false;
263         self->reinit_in_progress = false;
264         self->queue_reinit = false;
265
266         lv2_atom_forge_init (&self->forge, map);
267
268         /* map URIDs */
269         self->atom_Blank         = map->map (map->handle, LV2_ATOM__Blank);
270         self->atom_Object        = map->map (map->handle, LV2_ATOM__Object);
271         self->atom_Path          = map->map (map->handle, LV2_ATOM__Path);
272         self->atom_URID          = map->map (map->handle, LV2_ATOM__URID);
273         self->midi_MidiEvent     = map->map (map->handle, LV2_MIDI__MidiEvent);
274         self->patch_Get          = map->map (map->handle, LV2_PATCH__Get);
275         self->patch_Set          = map->map (map->handle, LV2_PATCH__Set);
276         self->patch_property     = map->map (map->handle, LV2_PATCH__property);
277         self->patch_value        = map->map (map->handle, LV2_PATCH__value);
278         self->afs_sf2file        = map->map (map->handle, AFS_URN ":sf2file");
279
280         return (LV2_Handle)self;
281 }
282
283 static void
284 connect_port (LV2_Handle instance,
285               uint32_t   port,
286               void*      data)
287 {
288         AFluidSynth* self = (AFluidSynth*)instance;
289
290         switch (port) {
291                 case FS_PORT_CONTROL:
292                         self->control = (const LV2_Atom_Sequence*)data;
293                         break;
294                 case FS_PORT_NOTIFY:
295                         self->notify = (LV2_Atom_Sequence*)data;
296                         break;
297                 case FS_PORT_OUT_L:
298                         self->output[0] = (float*)data;
299                         break;
300                 case FS_PORT_OUT_R:
301                         self->output[1] = (float*)data;
302                         break;
303         }
304 }
305
306 static void
307 activate (LV2_Handle instance)
308 {
309         AFluidSynth* self = (AFluidSynth*)instance;
310         self->panic = true;
311 }
312
313 static void
314 run (LV2_Handle instance, uint32_t n_samples)
315 {
316         AFluidSynth* self = (AFluidSynth*)instance;
317
318         if (!self->control || !self->notify) {
319                 return;
320         }
321
322         const uint32_t capacity = self->notify->atom.size;
323         lv2_atom_forge_set_buffer (&self->forge, (uint8_t*)self->notify, capacity);
324         lv2_atom_forge_sequence_head (&self->forge, &self->frame, 0);
325
326         if (!self->initialized || self->reinit_in_progress) {
327                 memset (self->output[0], 0, n_samples * sizeof (float));
328                 memset (self->output[1], 0, n_samples * sizeof (float));
329         } else if (self->panic) {
330                 fluid_synth_all_notes_off (self->synth, -1);
331                 fluid_synth_all_sounds_off (self->synth, -1);
332                 self->panic = false;
333         }
334
335         uint32_t offset = 0;
336
337         LV2_ATOM_SEQUENCE_FOREACH (self->control, ev) {
338                 const LV2_Atom_Object* obj = (LV2_Atom_Object*)&ev->body;
339                 if (ev->body.type == self->atom_Blank || ev->body.type == self->atom_Object) {
340                         if (obj->body.otype == self->patch_Get) {
341                                 self->inform_ui = false;
342                                 inform_ui (self);
343                         }
344                         else if (obj->body.otype == self->patch_Set) {
345                                 const LV2_Atom* file_path = parse_patch_msg (self, obj);
346                                 if (file_path && !self->reinit_in_progress && !self->queue_reinit) {
347                                         const char *fn = (const char*)(file_path+1);
348                                         strncpy (self->queue_sf2_file_path, fn, 1023);
349                                         self->queue_sf2_file_path[1023] = '\0';
350                                         self->reinit_in_progress = true;
351                                         int magic = 0x4711;
352                                         self->schedule->schedule_work (self->schedule->handle, sizeof(int), &magic);
353                                 }
354                         }
355                 }
356                 else if (ev->body.type == self->midi_MidiEvent && self->initialized && !self->reinit_in_progress) {
357                         if (ev->body.size > 3 || ev->time.frames >= n_samples) {
358                                 continue;
359                         }
360
361                         if (ev->time.frames > offset) {
362                                 fluid_synth_write_float (
363                                                 self->synth,
364                                                 ev->time.frames - offset,
365                                                 &self->output[0][offset], 0, 1,
366                                                 &self->output[1][offset], 0, 1);
367                         }
368
369                         offset = ev->time.frames;
370
371                         const uint8_t* const data = (const uint8_t*)(ev + 1);
372                         fluid_midi_event_set_type (self->fmidi_event, data[0] & 0xf0);
373                         fluid_midi_event_set_channel (self->fmidi_event, data[0] & 0x0f);
374                         if (ev->body.size > 1) {
375                                 fluid_midi_event_set_key (self->fmidi_event, data[1]);
376                         }
377                         if (ev->body.size > 2) {
378                                 fluid_midi_event_set_value (self->fmidi_event, data[2]);
379                         }
380                         fluid_synth_handle_midi_event (self->synth, self->fmidi_event);
381                 }
382         }
383
384         if (self->queue_reinit && !self->reinit_in_progress) {
385                 self->reinit_in_progress = true;
386                 int magic = 0x4711;
387                 self->schedule->schedule_work (self->schedule->handle, sizeof(int), &magic);
388         }
389
390         /* inform the GUI */
391         if (self->inform_ui) {
392                 self->inform_ui = false;
393                 inform_ui (self);
394         }
395
396         if (n_samples > offset && self->initialized && !self->reinit_in_progress) {
397                 fluid_synth_write_float (
398                                 self->synth,
399                                 n_samples - offset,
400                                 &self->output[0][offset], 0, 1,
401                                 &self->output[1][offset], 0, 1);
402         }
403 }
404
405 static void cleanup (LV2_Handle instance)
406 {
407         AFluidSynth* self = (AFluidSynth*)instance;
408         delete_fluid_synth (self->synth);
409         delete_fluid_settings (self->settings);
410         delete_fluid_midi_event (self->fmidi_event);
411         free (self);
412 }
413
414 /* *****************************************************************************
415  * LV2 Extensions
416  */
417
418 static LV2_Worker_Status
419 work (LV2_Handle                  instance,
420       LV2_Worker_Respond_Function respond,
421       LV2_Worker_Respond_Handle   handle,
422       uint32_t                    size,
423       const void*                 data)
424 {
425         AFluidSynth* self = (AFluidSynth*)instance;
426
427   if (size != sizeof(int)) {
428                 return LV2_WORKER_ERR_UNKNOWN;
429         }
430         int magic = *((const int*)data);
431         if (magic != 0x4711) {
432                 return LV2_WORKER_ERR_UNKNOWN;
433         }
434
435         self->initialized = load_sf2 (self, self->queue_sf2_file_path);
436         respond (handle, 1, "");
437         return LV2_WORKER_SUCCESS;
438 }
439
440 static LV2_Worker_Status
441 work_response (LV2_Handle  instance,
442                uint32_t    size,
443                const void* data)
444 {
445         AFluidSynth* self = (AFluidSynth*)instance;
446         self->reinit_in_progress = false;
447         self->queue_reinit = false;
448         self->inform_ui = true;
449         self->panic = true;
450
451         if (self->initialized) {
452                 strcpy (self->current_sf2_file_path, self->queue_sf2_file_path);
453         } else {
454                 self->current_sf2_file_path[0] = 0;
455         }
456         return LV2_WORKER_SUCCESS;
457 }
458
459 static LV2_State_Status
460 save (LV2_Handle                instance,
461       LV2_State_Store_Function  store,
462       LV2_State_Handle          handle,
463       uint32_t                  flags,
464       const LV2_Feature* const* features)
465 {
466         AFluidSynth* self = (AFluidSynth*)instance;
467
468         if (strlen (self->current_sf2_file_path) == 0) {
469                 return LV2_STATE_ERR_NO_PROPERTY;
470         }
471
472         LV2_State_Map_Path* map_path = NULL;
473
474         for (int i = 0; features[i]; ++i) {
475                 if (!strcmp (features[i]->URI, LV2_STATE__mapPath)) {
476                         map_path = (LV2_State_Map_Path*) features[i]->data;
477                 }
478         }
479
480         if (!map_path) {
481                 return LV2_STATE_ERR_NO_FEATURE;
482         }
483
484         char* apath = map_path->abstract_path (map_path->handle, self->current_sf2_file_path);
485         store (handle, self->afs_sf2file,
486                         apath, strlen (apath) + 1,
487                         self->atom_Path,
488                         LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
489
490         return LV2_STATE_SUCCESS;
491 }
492
493 static LV2_State_Status
494 restore (LV2_Handle                  instance,
495          LV2_State_Retrieve_Function retrieve,
496          LV2_State_Handle            handle,
497          uint32_t                    flags,
498          const LV2_Feature* const*   features)
499 {
500         AFluidSynth* self = (AFluidSynth*)instance;
501         if (self->reinit_in_progress || self->queue_reinit) {
502                 lv2_log_warning (&self->logger, "a-fluidsynth.lv2: sf2 load already queued.\n");
503                 return LV2_STATE_ERR_UNKNOWN;
504         }
505
506   size_t   size;
507   uint32_t type;
508   uint32_t valflags;
509
510   const void* value = retrieve (handle, self->afs_sf2file, &size, &type, &valflags);
511         if (value) {
512                 strncpy (self->queue_sf2_file_path, value, 1023);
513                 self->queue_sf2_file_path[1023] = '\0';
514                 self->queue_reinit = true;
515         }
516         return LV2_STATE_SUCCESS;
517 }
518
519 static const void*
520 extension_data (const char* uri)
521 {
522         static const LV2_Worker_Interface worker = { work, work_response, NULL };
523         static const LV2_State_Interface  state  = { save, restore };
524         if (!strcmp (uri, LV2_WORKER__interface)) {
525                 return &worker;
526         }
527         else if (!strcmp (uri, LV2_STATE__interface)) {
528                 return &state;
529         }
530         return NULL;
531 }
532
533 static const LV2_Descriptor descriptor = {
534         AFS_URN,
535         instantiate,
536         connect_port,
537         activate,
538         run,
539         NULL,
540         cleanup,
541         extension_data
542 };
543
544 #undef LV2_SYMBOL_EXPORT
545 #ifdef _WIN32
546 #    define LV2_SYMBOL_EXPORT __declspec(dllexport)
547 #else
548 #    define LV2_SYMBOL_EXPORT  __attribute__ ((visibility ("default")))
549 #endif
550 LV2_SYMBOL_EXPORT
551 const LV2_Descriptor*
552 lv2_descriptor (uint32_t index)
553 {
554         switch (index) {
555         case 0:
556                 return &descriptor;
557         default:
558                 return NULL;
559         }
560 }