Switch to using atoms to pass paths from ui to core for kit loading

This commit is contained in:
Nick Lanham 2012-03-22 19:37:18 +01:00
parent 990caaf510
commit 20e94c55fb
3 changed files with 132 additions and 43 deletions

71
drmr.c
View File

@ -22,35 +22,39 @@
#include "drmr.h" #include "drmr.h"
#include "drmr_hydrogen.h" #include "drmr_hydrogen.h"
#define REQ_BUF_SIZE 10
static void* load_thread(void* arg) { static void* load_thread(void* arg) {
DrMr* drmr = (DrMr*)arg; DrMr* drmr = (DrMr*)arg;
drmr_sample *loaded_samples,*old_samples; drmr_sample *loaded_samples,*old_samples;
int loaded_count, old_scount; int loaded_count, old_scount;
char *request;
for(;;) { for(;;) {
pthread_mutex_lock(&drmr->load_mutex); pthread_mutex_lock(&drmr->load_mutex);
pthread_cond_wait(&drmr->load_cond, pthread_cond_wait(&drmr->load_cond,
&drmr->load_mutex); &drmr->load_mutex);
pthread_mutex_unlock(&drmr->load_mutex); pthread_mutex_unlock(&drmr->load_mutex);
int request = (int)floorf(*(drmr->kitReq));
if (request == drmr->curKit) continue;
old_samples = drmr->samples; old_samples = drmr->samples;
old_scount = drmr->num_samples; old_scount = drmr->num_samples;
if (request < 0 || request >= drmr->kits->num_kits) { request = drmr->request_buf[drmr->curReq];
loaded_samples = load_hydrogen_kit(request,drmr->rate,&loaded_count);
if (!loaded_samples) {
fprintf(stderr,"Failed to load kit at: %s\n",request);
pthread_mutex_lock(&drmr->load_mutex); pthread_mutex_lock(&drmr->load_mutex);
drmr->num_samples = 0; drmr->num_samples = 0;
drmr->samples = NULL; drmr->samples = NULL;
pthread_mutex_unlock(&drmr->load_mutex); pthread_mutex_unlock(&drmr->load_mutex);
} else { }
printf("loading kit: %i\n",request); else {
loaded_samples = load_hydrogen_kit(drmr->kits->kits[request].path,drmr->rate,&loaded_count);
// just lock for the critical moment when we swap in the new kit // just lock for the critical moment when we swap in the new kit
printf("loaded kit at: %s\n",request);
pthread_mutex_lock(&drmr->load_mutex); pthread_mutex_lock(&drmr->load_mutex);
drmr->samples = loaded_samples; drmr->samples = loaded_samples;
drmr->num_samples = loaded_count; drmr->num_samples = loaded_count;
pthread_mutex_unlock(&drmr->load_mutex); pthread_mutex_unlock(&drmr->load_mutex);
} }
if (old_scount > 0) free_samples(old_samples,old_scount); if (old_scount > 0) free_samples(old_samples,old_scount);
drmr->curKit = request; drmr->current_path = request;
} }
return 0; return 0;
} }
@ -65,7 +69,8 @@ instantiate(const LV2_Descriptor* descriptor,
drmr->map = NULL; drmr->map = NULL;
drmr->samples = NULL; drmr->samples = NULL;
drmr->num_samples = 0; drmr->num_samples = 0;
drmr->curKit = -1; drmr->current_path = NULL;
drmr->curReq = -1;
drmr->rate = rate; drmr->rate = rate;
if (pthread_mutex_init(&drmr->load_mutex, 0)) { if (pthread_mutex_init(&drmr->load_mutex, 0)) {
@ -79,14 +84,9 @@ instantiate(const LV2_Descriptor* descriptor,
return 0; return 0;
} }
// Map midi uri
while(*features) { while(*features) {
if (!strcmp((*features)->URI, LV2_URID_URI "#map")) { if (!strcmp((*features)->URI, LV2_URID_URI "#map"))
drmr->map = (LV2_URID_Map *)((*features)->data); drmr->map = (LV2_URID_Map *)((*features)->data);
drmr->uris.midi_event =
drmr->map->map(drmr->map->handle,
"http://lv2plug.in/ns/ext/midi#MidiEvent");
}
features++; features++;
} }
if (!drmr->map) { if (!drmr->map) {
@ -94,6 +94,7 @@ instantiate(const LV2_Descriptor* descriptor,
free(drmr); free(drmr);
return 0; return 0;
} }
map_drmr_uris(drmr->map,&(drmr->uris));
drmr->kits = scan_kits(); drmr->kits = scan_kits();
if (!drmr->kits) { if (!drmr->kits) {
@ -108,6 +109,9 @@ instantiate(const LV2_Descriptor* descriptor,
return 0; return 0;
} }
drmr->request_buf = malloc(REQ_BUF_SIZE*sizeof(char*));
memset(drmr->request_buf,0,REQ_BUF_SIZE*sizeof(char*));
drmr->gains = malloc(32*sizeof(float*)); drmr->gains = malloc(32*sizeof(float*));
drmr->pans = malloc(32*sizeof(float*)); drmr->pans = malloc(32*sizeof(float*));
for(i = 0;i<32;i++) { for(i = 0;i<32;i++) {
@ -128,6 +132,9 @@ connect_port(LV2_Handle instance,
case DRMR_CONTROL: case DRMR_CONTROL:
drmr->control_port = (LV2_Atom_Sequence*)data; drmr->control_port = (LV2_Atom_Sequence*)data;
break; break;
case DRMR_KITPATH:
drmr->kitpath_port = (LV2_Atom_Sequence*)data;
break;
case DRMR_LEFT: case DRMR_LEFT:
drmr->left = (float*)data; drmr->left = (float*)data;
break; break;
@ -135,7 +142,7 @@ connect_port(LV2_Handle instance,
drmr->right = (float*)data; drmr->right = (float*)data;
break; break;
case DRMR_KITNUM: case DRMR_KITNUM:
if(data) drmr->kitReq = (float*)data; //if(data) drmr->kitReq = (float*)data;
break; break;
case DRMR_BASENOTE: case DRMR_BASENOTE:
if (data) drmr->baseNote = (float*)data; if (data) drmr->baseNote = (float*)data;
@ -182,13 +189,10 @@ static inline void layer_to_sample(drmr_sample *sample, float gain) {
#define DB_CO(g) ((g) > GAIN_MIN ? powf(10.0f, (g) * 0.05f) : 0.0f) #define DB_CO(g) ((g) > GAIN_MIN ? powf(10.0f, (g) * 0.05f) : 0.0f)
static void run(LV2_Handle instance, uint32_t n_samples) { static void run(LV2_Handle instance, uint32_t n_samples) {
int i,kitInt,baseNote; int i,baseNote;
DrMr* drmr = (DrMr*)instance; DrMr* drmr = (DrMr*)instance;
kitInt = (int)floorf(*(drmr->kitReq));
baseNote = (int)floorf(*(drmr->baseNote)); baseNote = (int)floorf(*(drmr->baseNote));
if (kitInt != drmr->curKit) // requested a new kit
pthread_cond_signal(&drmr->load_cond);
LV2_SEQUENCE_FOREACH(drmr->control_port, i) { LV2_SEQUENCE_FOREACH(drmr->control_port, i) {
LV2_Atom_Event* const ev = lv2_sequence_iter_get(i); LV2_Atom_Event* const ev = lv2_sequence_iter_get(i);
@ -220,9 +224,36 @@ static void run(LV2_Handle instance, uint32_t n_samples) {
default: default:
printf("Unhandeled status: %i\n",(*data)>>4); printf("Unhandeled status: %i\n",(*data)>>4);
} }
} else printf("unrecognized event\n"); }
else if (ev->body.type == drmr->uris.atom_resource) {
const LV2_Atom_Object *obj = (LV2_Atom_Object*)&ev->body;
if (obj->body.otype == drmr->uris.ui_msg) {
const LV2_Atom* path = NULL;
lv2_object_get(obj, drmr->uris.kit_path, &path, 0);
if (!path)
fprintf(stderr,"Got UI message without kit_path, ignoring\n");
else {
int reqPos = (drmr->curReq+1)%REQ_BUF_SIZE;
char *tmp = NULL;
if (reqPos >= 0 &&
drmr->request_buf[reqPos])
tmp = drmr->request_buf[reqPos];
drmr->request_buf[reqPos] = strdup(LV2_ATOM_BODY(path));
drmr->curReq = reqPos;
if (tmp) free(tmp);
}
}
}
else printf("unrecognized event\n");
} }
if ((drmr->curReq >= 0) &&
drmr->request_buf[drmr->curReq] &&
(!drmr->current_path ||
strcmp(drmr->current_path,
drmr->request_buf[drmr->curReq])))
pthread_cond_signal(&drmr->load_cond);
for(i = 0;i<n_samples;i++) { for(i = 0;i<n_samples;i++) {
drmr->left[i] = 0.0f; drmr->left[i] = 0.0f;
drmr->right[i] = 0.0f; drmr->right[i] = 0.0f;

37
drmr.h
View File

@ -137,31 +137,40 @@ typedef enum {
DRMR_PAN_THIRTY, DRMR_PAN_THIRTY,
DRMR_PAN_THIRTYONE, DRMR_PAN_THIRTYONE,
DRMR_PAN_THIRTYTWO, DRMR_PAN_THIRTYTWO,
DRMR_KITPATH,
DRMR_NUM_PORTS DRMR_NUM_PORTS
} DrMrPortIndex; } DrMrPortIndex;
typedef struct {
LV2_URID midi_event;
LV2_URID ui_msg;
LV2_URID kit_path;
LV2_URID atom_eventTransfer;
LV2_URID atom_resource;
} drmr_uris;
typedef struct { typedef struct {
// Ports // Ports
float* left; float* left;
float* right; float* right;
LV2_Atom_Sequence *control_port; LV2_Atom_Sequence *control_port;
LV2_Atom_Sequence *kitpath_port;
// params // params
float** gains; float** gains;
float** pans; float** pans;
float* kitReq;
float* baseNote; float* baseNote;
double rate; double rate;
// URIs // URIs
LV2_URID_Map* map; LV2_URID_Map* map;
struct { drmr_uris uris;
LV2_URID midi_event;
} uris;
// Available kits // Available kits
kits* kits; kits* kits;
int curKit; char* current_path;
char** request_buf;
int curReq;
// Samples // Samples
drmr_sample* samples; drmr_sample* samples;
@ -174,5 +183,23 @@ typedef struct {
} DrMr; } DrMr;
static inline
void map_drmr_uris(LV2_URID_Map *map,
drmr_uris *uris) {
uris->midi_event =
map->map(map->handle,
"http://lv2plug.in/ns/ext/midi#MidiEvent");
uris->ui_msg =
map->map(map->handle,
DRMR_URI "#uimsg");
uris->kit_path =
map->map(map->handle,
DRMR_URI "#kitpath");
uris->atom_eventTransfer =
map->map(map->handle, LV2_ATOM__eventTransfer);
uris->atom_resource =
map->map(map->handle, LV2_ATOM__Resource);
}
#endif // DRMR_H #endif // DRMR_H

View File

@ -21,6 +21,11 @@
#include "drmr.h" #include "drmr.h"
#include "drmr_hydrogen.h" #include "drmr_hydrogen.h"
#include "nknob.h" #include "nknob.h"
#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
#include "lv2/lv2plug.in/ns/ext/atom/forge.h"
#include "lv2/lv2plug.in/ns/ext/atom/util.h"
#include "lv2/lv2plug.in/ns/ext/urid/urid.h"
#include "lv2/lv2plug.in/ns/extensions/ui/ui.h" #include "lv2/lv2plug.in/ns/extensions/ui/ui.h"
#define DRMR_UI_URI "http://github.com/nicklan/drmr#ui" #define DRMR_UI_URI "http://github.com/nicklan/drmr#ui"
@ -28,6 +33,10 @@
typedef struct { typedef struct {
LV2UI_Write_Function write; LV2UI_Write_Function write;
LV2UI_Controller controller; LV2UI_Controller controller;
LV2_Atom_Forge forge;
LV2_URID_Map *map;
drmr_uris uris;
GtkWidget *drmr_widget; GtkWidget *drmr_widget;
GtkTable *sample_table; GtkTable *sample_table;
@ -271,12 +280,30 @@ static gboolean kit_callback(gpointer data) {
return FALSE; // don't keep calling return FALSE; // don't keep calling
} }
static LV2_Atom* build_path_message(DrMrUi *ui, const char* path) {
LV2_Atom_Forge_Frame set_frame;
LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_resource
(&ui->forge, &set_frame, 1, ui->uris.ui_msg);
lv2_atom_forge_property_head(&ui->forge, ui->uris.kit_path,0);
lv2_atom_forge_path(&ui->forge, path, strlen(path));
lv2_atom_forge_pop(&ui->forge,&set_frame);
return msg;
}
static void kit_combobox_changed(GtkComboBox* box, gpointer data) { static void kit_combobox_changed(GtkComboBox* box, gpointer data) {
DrMrUi* ui = (DrMrUi*)data; DrMrUi* ui = (DrMrUi*)data;
gint new_kit = gtk_combo_box_get_active (GTK_COMBO_BOX(box)); gint new_kit = gtk_combo_box_get_active (GTK_COMBO_BOX(box));
float fkit = (float)new_kit;
if (ui->curKit != new_kit) if (ui->curKit != new_kit) {
ui->write(ui->controller,DRMR_KITNUM,4,0,&fkit); uint8_t msg_buf[1024];
lv2_atom_forge_set_buffer(&ui->forge, msg_buf, 1024);
LV2_Atom *msg = build_path_message(ui,ui->kits->kits[new_kit].path);
ui->write(ui->controller,DRMR_CONTROL,
lv2_atom_total_size(msg),
ui->uris.atom_eventTransfer,
msg);
}
/* Call our update func after 100 milliseconds. /* Call our update func after 100 milliseconds.
* *
@ -424,11 +451,27 @@ instantiate(const LV2UI_Descriptor* descriptor,
ui->write = write_function; ui->write = write_function;
ui->controller = controller; ui->controller = controller;
ui->drmr_widget = NULL; ui->drmr_widget = NULL;
ui->map = NULL;
ui->curKit = -1; ui->curKit = -1;
ui->samples = 0; ui->samples = 0;
ui->bundle_path = g_strdup(bundle_path);
*widget = NULL; *widget = NULL;
while(*features) {
if (!strcmp((*features)->URI, LV2_URID_URI "#map"))
ui->map = (LV2_URID_Map *)((*features)->data);
features++;
}
if (!ui->map) {
fprintf(stderr, "LV2 host does not support urid#map.\n");
free(ui);
return 0;
}
map_drmr_uris(ui->map,&(ui->uris));
ui->bundle_path = g_strdup(bundle_path);
lv2_atom_forge_init(&ui->forge,ui->map);
build_drmr_ui(ui); build_drmr_ui(ui);
ui->kits = scan_kits(); ui->kits = scan_kits();
@ -493,19 +536,7 @@ port_event(LV2UI_Handle handle,
DrMrPortIndex index = (DrMrPortIndex)port_index; DrMrPortIndex index = (DrMrPortIndex)port_index;
DrMrUi* ui = (DrMrUi*)handle; DrMrUi* ui = (DrMrUi*)handle;
if (index == DRMR_KITNUM) { if (index == DRMR_BASENOTE) {
if (format != 0)
fprintf(stderr,"Invalid format for kitnum: %i\n",format);
else {
int kit = (int)(*((float*)buffer));
ui->kitReq = kit;
if (!idle) {
idle = TRUE;
g_idle_add(kit_callback,ui);
}
}
}
else if (index == DRMR_BASENOTE) {
int base = (int)(*((float*)buffer)); int base = (int)(*((float*)buffer));
if (base >= 21 && base <= 107) { if (base >= 21 && base <= 107) {
setBaseLabel((int)base); setBaseLabel((int)base);