Skip to content

Commit

Permalink
Implement LV2:BankPatch extension
Browse files Browse the repository at this point in the history
  • Loading branch information
x42 committed Sep 8, 2017
1 parent 7e2ff95 commit 1550c0e
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 6 deletions.
13 changes: 13 additions & 0 deletions src/bankpatch_lv2.h
@@ -0,0 +1,13 @@
#define LV2_BANKPATCH_URI "http://ardour.org/lv2/bankpatch"
#define LV2_BANKPATCH_PREFIX LV2_BANKPATCH_URI "#"
#define LV2_BANKPATCH__notify LV2_BANKPATCH_PREFIX "notify"

typedef void* LV2_BankPatch_Handle;

/** a LV2 Feature provided by the Host to the plugin */
typedef struct {
/** Opaque host data */
LV2_BankPatch_Handle handle;
/** Info from plugin's run(), notify host that bank/program changed */
void (*notify)(LV2_BankPatch_Handle handle, uint8_t channel, uint32_t bank, uint8_t pgm);
} LV2_BankPatch;
49 changes: 43 additions & 6 deletions src/gmsynth.c
Expand Up @@ -37,6 +37,7 @@
#include <lv2/lv2plug.in/ns/ext/urid/urid.h>

#include "midnam_lv2.h"
#include "bankpatch_lv2.h"

#include "fluidsynth.h"

Expand Down Expand Up @@ -163,11 +164,16 @@ typedef struct {
struct Bank* presets;
pthread_mutex_t bp_lock;

/* bank/patch notifications */
LV2_BankPatch* bankpatch;

/* state */
bool panic;
bool send_bankpgm;

uint8_t last_bank_lsb;
uint8_t last_bank_msb;
uint8_t last_bank_lsb[16];
uint8_t last_bank_msb[16];
uint8_t last_program[16];

fluid_midi_event_t* fmidi_event;

Expand Down Expand Up @@ -202,8 +208,14 @@ load_sf2 (GFSSynth* self, const char* fn)
pthread_mutex_lock (&self->bp_lock);
for (chn = 0; sfont->iteration_next (sfont, &preset); ++chn) {
if (chn < 16) {
fluid_synth_program_select (self->synth, chn, synth_id,
preset.get_banknum (&preset), preset.get_num (&preset));
int bank = preset.get_banknum (&preset);
int pgm = preset.get_num (&preset);

fluid_synth_program_select (self->synth, chn, synth_id, bank, pgm);
self->last_bank_msb[chn] = bank >> 7;
self->last_bank_lsb[chn] = bank & 127;
self->last_program[chn] = pgm;

}

add_program (get_pgmlist (self->presets, preset.get_banknum (&preset)),
Expand Down Expand Up @@ -253,6 +265,8 @@ instantiate (const LV2_Descriptor* descriptor,
self->log = (LV2_Log_Log*)features[i]->data;
} else if (!strcmp (features[i]->URI, LV2_MIDNAM__update)) {
self->midnam = (LV2_Midnam*)features[i]->data;
} else if (!strcmp (features[i]->URI, LV2_BANKPATCH__notify)) {
self->bankpatch = (LV2_BankPatch*)features[i]->data;
}
}

Expand Down Expand Up @@ -319,6 +333,11 @@ instantiate (const LV2_Descriptor* descriptor,
self->midi_MidiEvent = map->map (map->handle, LV2_MIDI__MidiEvent);

self->panic = false;
self->send_bankpgm = true;

for (uint8_t chn = 0; chn < 16; ++chn) {
self->last_program[chn] = 255;
}

/* load .sf2 */
if (load_sf2 (self, sf2_file_path)) {
Expand Down Expand Up @@ -405,6 +424,14 @@ run (LV2_Handle instance, uint32_t n_samples)
if (ev->body.size > 1) {
fluid_midi_event_set_key (self->fmidi_event, data[1]);
}
if (ev->body.size == 2 && 0xc0 /* Pgm */ == fluid_midi_event_get_type (self->fmidi_event)) {
int chn = fluid_midi_event_get_channel (self->fmidi_event);
self->last_program[chn] = data[1];
if (self->bankpatch) {
self->bankpatch->notify (self->bankpatch->handle, chn,
(self->last_bank_msb[chn] << 7) | self->last_bank_lsb[chn], data[1]);
}
}
if (ev->body.size > 2) {
if (0xe0 /*PITCH_BEND*/ == fluid_midi_event_get_type (self->fmidi_event)) {
fluid_midi_event_set_value (self->fmidi_event, 0);
Expand All @@ -413,8 +440,9 @@ run (LV2_Handle instance, uint32_t n_samples)
fluid_midi_event_set_value (self->fmidi_event, data[2]);
}
if (0xb0 /* CC */ == fluid_midi_event_get_type (self->fmidi_event)) {
if (data[1] == 0x00) { self->last_bank_msb = data[2]; }
if (data[1] == 0x20) { self->last_bank_lsb = data[2]; }
int chn = fluid_midi_event_get_channel (self->fmidi_event);
if (data[1] == 0x00) { self->last_bank_msb[chn] = data[2]; }
if (data[1] == 0x20) { self->last_bank_lsb[chn] = data[2]; }
}
}

Expand All @@ -429,6 +457,15 @@ run (LV2_Handle instance, uint32_t n_samples)
&self->p_ports[GFS_PORT_OUT_L][offset], 0, 1,
&self->p_ports[GFS_PORT_OUT_R][offset], 0, 1);
}

if (self->send_bankpgm && self->bankpatch) {
self->send_bankpgm = false;
for (uint8_t chn = 0; chn < 16; ++chn) {
self->bankpatch->notify (self->bankpatch->handle, chn,
(self->last_bank_msb[chn] << 7) | self->last_bank_lsb[chn],
self->last_program[chn] > 127 ? 255 : self->last_program[chn]);
}
}
}

static void cleanup (LV2_Handle instance)
Expand Down

0 comments on commit 1550c0e

Please sign in to comment.