a-fluid synth: list all bank/programs
This commit is contained in:
parent
9c20892c27
commit
f26ed23fd9
@ -20,9 +20,14 @@
|
|||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#define AFS_URN "urn:ardour:a-fluidsynth"
|
#define AFS_URN "urn:ardour:a-fluidsynth"
|
||||||
@ -75,6 +80,27 @@ enum {
|
|||||||
CMD_FREE = 1,
|
CMD_FREE = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BankProgram {
|
||||||
|
BankProgram (const std::string& n, int b, int p)
|
||||||
|
: name (n)
|
||||||
|
, bank (b)
|
||||||
|
, program (p)
|
||||||
|
{}
|
||||||
|
|
||||||
|
BankProgram (const BankProgram& other)
|
||||||
|
: name (other.name)
|
||||||
|
, bank (other.bank)
|
||||||
|
, program (other.program)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
int bank;
|
||||||
|
int program;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<BankProgram> BPList;
|
||||||
|
typedef std::map<int, BPList> BPMap;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* ports */
|
/* ports */
|
||||||
const LV2_Atom_Sequence* control;
|
const LV2_Atom_Sequence* control;
|
||||||
@ -109,7 +135,9 @@ typedef struct {
|
|||||||
|
|
||||||
#ifdef LV2_EXTENDED
|
#ifdef LV2_EXTENDED
|
||||||
LV2_Midnam* midnam;
|
LV2_Midnam* midnam;
|
||||||
|
BPMap presets;
|
||||||
#endif
|
#endif
|
||||||
|
pthread_mutex_t bp_lock;
|
||||||
|
|
||||||
/* state */
|
/* state */
|
||||||
bool panic;
|
bool panic;
|
||||||
@ -134,6 +162,12 @@ load_sf2 (AFluidSynth* self, const char* fn)
|
|||||||
{
|
{
|
||||||
const int synth_id = fluid_synth_sfload (self->synth, fn, 1);
|
const int synth_id = fluid_synth_sfload (self->synth, fn, 1);
|
||||||
|
|
||||||
|
#ifdef LV2_EXTENDED
|
||||||
|
pthread_mutex_lock (&self->bp_lock);
|
||||||
|
self->presets.clear ();
|
||||||
|
pthread_mutex_unlock (&self->bp_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (synth_id == FLUID_FAILED) {
|
if (synth_id == FLUID_FAILED) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -146,10 +180,23 @@ load_sf2 (AFluidSynth* self, const char* fn)
|
|||||||
int chn;
|
int chn;
|
||||||
fluid_preset_t preset;
|
fluid_preset_t preset;
|
||||||
sfont->iteration_start (sfont);
|
sfont->iteration_start (sfont);
|
||||||
for (chn = 0; sfont->iteration_next (sfont, &preset) && chn < 16; ++chn) {
|
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,
|
fluid_synth_program_select (self->synth, chn, synth_id,
|
||||||
preset.get_banknum (&preset), preset.get_num (&preset));
|
preset.get_banknum (&preset), preset.get_num (&preset));
|
||||||
}
|
}
|
||||||
|
#ifndef LV2_EXTENDED
|
||||||
|
else { break ; }
|
||||||
|
#else
|
||||||
|
self->presets[preset.get_banknum (&preset)].push_back (
|
||||||
|
BankProgram (
|
||||||
|
preset.get_name (&preset),
|
||||||
|
preset.get_banknum (&preset),
|
||||||
|
preset.get_num (&preset)));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock (&self->bp_lock);
|
||||||
|
|
||||||
if (chn == 0) {
|
if (chn == 0) {
|
||||||
return false;
|
return false;
|
||||||
@ -293,6 +340,8 @@ instantiate (const LV2_Descriptor* descriptor,
|
|||||||
|
|
||||||
/* initialize plugin state */
|
/* initialize plugin state */
|
||||||
|
|
||||||
|
pthread_mutex_init (&self->bp_lock, NULL);
|
||||||
|
self->presets = BPMap();
|
||||||
self->panic = false;
|
self->panic = false;
|
||||||
self->inform_ui = false;
|
self->inform_ui = false;
|
||||||
self->initialized = false;
|
self->initialized = false;
|
||||||
@ -500,6 +549,7 @@ static void cleanup (LV2_Handle instance)
|
|||||||
delete_fluid_synth (self->synth);
|
delete_fluid_synth (self->synth);
|
||||||
delete_fluid_settings (self->settings);
|
delete_fluid_settings (self->settings);
|
||||||
delete_fluid_midi_event (self->fmidi_event);
|
delete_fluid_midi_event (self->fmidi_event);
|
||||||
|
pthread_mutex_destroy (&self->bp_lock);
|
||||||
free (self);
|
free (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,6 +574,7 @@ work (LV2_Handle instance,
|
|||||||
return LV2_WORKER_ERR_UNKNOWN;
|
return LV2_WORKER_ERR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
self->initialized = load_sf2 (self, self->queue_sf2_file_path);
|
self->initialized = load_sf2 (self, self->queue_sf2_file_path);
|
||||||
|
|
||||||
if (self->initialized) {
|
if (self->initialized) {
|
||||||
@ -618,20 +669,16 @@ restore (LV2_Handle instance,
|
|||||||
return LV2_STATE_SUCCESS;
|
return LV2_STATE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* xml_escape (const char* s) {
|
static std::string xml_escape (const std::string& s)
|
||||||
// crude, but hey
|
{
|
||||||
if (!s) {
|
std::string r (s);
|
||||||
return strdup ("");
|
std::replace (r.begin (), r.end(), '"', '\'');
|
||||||
|
size_t pos = 0;
|
||||||
|
while((pos = r.find ("&", pos)) != std::string::npos) {
|
||||||
|
r.replace (pos, 1, "&");
|
||||||
|
pos += 4;
|
||||||
}
|
}
|
||||||
char* tmp;
|
return r;
|
||||||
char* rv = strdup (s);
|
|
||||||
while ((tmp = strchr(rv, '"'))) {
|
|
||||||
*tmp = '\'';
|
|
||||||
}
|
|
||||||
while ((tmp = strchr(rv, '&'))) {
|
|
||||||
*tmp = '+';
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LV2_EXTENDED
|
#ifdef LV2_EXTENDED
|
||||||
@ -642,12 +689,6 @@ mn_file (LV2_Handle instance)
|
|||||||
char* rv = NULL;
|
char* rv = NULL;
|
||||||
char tmp[1024];
|
char tmp[1024];
|
||||||
|
|
||||||
fluid_sfont_t* sfont = NULL;
|
|
||||||
if (self->initialized && !self->reinit_in_progress) {
|
|
||||||
sfont = fluid_synth_get_sfont (self->synth, 0);
|
|
||||||
}
|
|
||||||
// TODO collect program info during load_sf2();
|
|
||||||
|
|
||||||
rv = (char*) calloc (1, sizeof (char));
|
rv = (char*) calloc (1, sizeof (char));
|
||||||
|
|
||||||
#define pf(...) \
|
#define pf(...) \
|
||||||
@ -684,27 +725,26 @@ mn_file (LV2_Handle instance)
|
|||||||
}
|
}
|
||||||
pf (" </AvailableForChannels>\n");
|
pf (" </AvailableForChannels>\n");
|
||||||
pf (" <UsesControlNameList Name=\"Controls\"/>\n");
|
pf (" <UsesControlNameList Name=\"Controls\"/>\n");
|
||||||
pf (" <PatchBank Name=\"Patch Bank 1\">\n");
|
|
||||||
pf (" <UsesPatchNameList Name=\"Programmes\"/>\n");
|
|
||||||
pf (" </PatchBank>\n");
|
|
||||||
pf (" </ChannelNameSet>\n");
|
|
||||||
|
|
||||||
|
int bn = 1;
|
||||||
|
pthread_mutex_lock (&self->bp_lock);
|
||||||
|
const BPMap& ps (self->presets);
|
||||||
|
pthread_mutex_unlock (&self->bp_lock);
|
||||||
|
|
||||||
pf (" <PatchNameList Name=\"Programmes\">\n");
|
for (BPMap::const_iterator i = ps.begin (); i != ps.end (); ++i, ++bn) {
|
||||||
if (sfont) {
|
pf (" <PatchBank Name=\"Patch Bank %d\">\n", i->first);
|
||||||
fluid_preset_t preset;
|
if (i->second.size() > 0) {
|
||||||
sfont->iteration_start (sfont);
|
pf (" <PatchNameList>\n");
|
||||||
for (int num = 1; sfont->iteration_next (sfont, &preset); ++num) {
|
int n = 0;
|
||||||
if (preset.get_banknum (&preset) != 0) {
|
for (BPList::const_iterator j = i->second.begin(); j != i->second.end(); ++j, ++n) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
char* pn = xml_escape (preset.get_name (&preset));
|
|
||||||
pf (" <Patch Number=\"%d\" Name=\"%s\" ProgramChange=\"%d\"/>\n",
|
pf (" <Patch Number=\"%d\" Name=\"%s\" ProgramChange=\"%d\"/>\n",
|
||||||
num, pn, preset.get_num (&preset));
|
n, xml_escape (j->name).c_str(), j->program);
|
||||||
free (pn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pf (" </PatchNameList>\n");
|
pf (" </PatchNameList>\n");
|
||||||
|
}
|
||||||
|
pf (" </PatchBank>\n");
|
||||||
|
}
|
||||||
|
pf (" </ChannelNameSet>\n");
|
||||||
|
|
||||||
pf (" <ControlNameList Name=\"Controls\">\n");
|
pf (" <ControlNameList Name=\"Controls\">\n");
|
||||||
pf (" <Control Type=\"7bit\" Number=\"7\" Name=\"Channel Volume\"/>\n");
|
pf (" <Control Type=\"7bit\" Number=\"7\" Name=\"Channel Volume\"/>\n");
|
||||||
@ -715,12 +755,12 @@ mn_file (LV2_Handle instance)
|
|||||||
pf (" <Control Type=\"7bit\" Number=\"66\" Name=\"Sostenuto\"/>\n");
|
pf (" <Control Type=\"7bit\" Number=\"66\" Name=\"Sostenuto\"/>\n");
|
||||||
pf (" </ControlNameList>\n");
|
pf (" </ControlNameList>\n");
|
||||||
|
|
||||||
|
|
||||||
pf (
|
pf (
|
||||||
" </MasterDeviceNames>\n"
|
" </MasterDeviceNames>\n"
|
||||||
"</MIDINameDocument>"
|
"</MIDINameDocument>"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//printf("-----\n%s\n------\n", rv);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user