diff --git a/drmr.c b/drmr.c index 6570807..2d78cd3 100644 --- a/drmr.c +++ b/drmr.c @@ -22,35 +22,39 @@ #include "drmr.h" #include "drmr_hydrogen.h" +#define REQ_BUF_SIZE 10 + static void* load_thread(void* arg) { DrMr* drmr = (DrMr*)arg; drmr_sample *loaded_samples,*old_samples; int loaded_count, old_scount; + char *request; for(;;) { pthread_mutex_lock(&drmr->load_mutex); pthread_cond_wait(&drmr->load_cond, &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_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); drmr->num_samples = 0; drmr->samples = NULL; pthread_mutex_unlock(&drmr->load_mutex); - } else { - printf("loading kit: %i\n",request); - loaded_samples = load_hydrogen_kit(drmr->kits->kits[request].path,drmr->rate,&loaded_count); + } + else { // 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); drmr->samples = loaded_samples; drmr->num_samples = loaded_count; pthread_mutex_unlock(&drmr->load_mutex); } if (old_scount > 0) free_samples(old_samples,old_scount); - drmr->curKit = request; + drmr->current_path = request; } return 0; } @@ -65,7 +69,8 @@ instantiate(const LV2_Descriptor* descriptor, drmr->map = NULL; drmr->samples = NULL; drmr->num_samples = 0; - drmr->curKit = -1; + drmr->current_path = NULL; + drmr->curReq = -1; drmr->rate = rate; if (pthread_mutex_init(&drmr->load_mutex, 0)) { @@ -79,21 +84,17 @@ instantiate(const LV2_Descriptor* descriptor, return 0; } - // Map midi uri 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->uris.midi_event = - drmr->map->map(drmr->map->handle, - "http://lv2plug.in/ns/ext/midi#MidiEvent"); - } features++; } if (!drmr->map) { fprintf(stderr, "LV2 host does not support urid#map.\n"); free(drmr); return 0; - } + } + map_drmr_uris(drmr->map,&(drmr->uris)); drmr->kits = scan_kits(); if (!drmr->kits) { @@ -108,6 +109,9 @@ instantiate(const LV2_Descriptor* descriptor, 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->pans = malloc(32*sizeof(float*)); for(i = 0;i<32;i++) { @@ -128,6 +132,9 @@ connect_port(LV2_Handle instance, case DRMR_CONTROL: drmr->control_port = (LV2_Atom_Sequence*)data; break; + case DRMR_KITPATH: + drmr->kitpath_port = (LV2_Atom_Sequence*)data; + break; case DRMR_LEFT: drmr->left = (float*)data; break; @@ -135,7 +142,7 @@ connect_port(LV2_Handle instance, drmr->right = (float*)data; break; case DRMR_KITNUM: - if(data) drmr->kitReq = (float*)data; + //if(data) drmr->kitReq = (float*)data; break; case DRMR_BASENOTE: 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) static void run(LV2_Handle instance, uint32_t n_samples) { - int i,kitInt,baseNote; + int i,baseNote; DrMr* drmr = (DrMr*)instance; - kitInt = (int)floorf(*(drmr->kitReq)); 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_Atom_Event* const ev = lv2_sequence_iter_get(i); @@ -220,9 +224,36 @@ static void run(LV2_Handle instance, uint32_t n_samples) { default: 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;ileft[i] = 0.0f; drmr->right[i] = 0.0f; diff --git a/drmr.h b/drmr.h index fa79b54..123152f 100644 --- a/drmr.h +++ b/drmr.h @@ -137,31 +137,40 @@ typedef enum { DRMR_PAN_THIRTY, DRMR_PAN_THIRTYONE, DRMR_PAN_THIRTYTWO, + DRMR_KITPATH, DRMR_NUM_PORTS } 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 { // Ports float* left; float* right; LV2_Atom_Sequence *control_port; + LV2_Atom_Sequence *kitpath_port; // params float** gains; float** pans; - float* kitReq; float* baseNote; double rate; // URIs LV2_URID_Map* map; - struct { - LV2_URID midi_event; - } uris; + drmr_uris uris; // Available kits kits* kits; - int curKit; + char* current_path; + char** request_buf; + int curReq; // Samples drmr_sample* samples; @@ -174,5 +183,23 @@ typedef struct { } 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 diff --git a/drmr_ui.c b/drmr_ui.c index 9ea6b89..9b5d067 100644 --- a/drmr_ui.c +++ b/drmr_ui.c @@ -21,6 +21,11 @@ #include "drmr.h" #include "drmr_hydrogen.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" #define DRMR_UI_URI "http://github.com/nicklan/drmr#ui" @@ -28,6 +33,10 @@ typedef struct { LV2UI_Write_Function write; LV2UI_Controller controller; + LV2_Atom_Forge forge; + + LV2_URID_Map *map; + drmr_uris uris; GtkWidget *drmr_widget; GtkTable *sample_table; @@ -271,12 +280,30 @@ static gboolean kit_callback(gpointer data) { 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) { DrMrUi* ui = (DrMrUi*)data; gint new_kit = gtk_combo_box_get_active (GTK_COMBO_BOX(box)); - float fkit = (float)new_kit; - if (ui->curKit != new_kit) - ui->write(ui->controller,DRMR_KITNUM,4,0,&fkit); + + if (ui->curKit != new_kit) { + 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. * @@ -424,11 +451,27 @@ instantiate(const LV2UI_Descriptor* descriptor, ui->write = write_function; ui->controller = controller; ui->drmr_widget = NULL; + ui->map = NULL; ui->curKit = -1; ui->samples = 0; - ui->bundle_path = g_strdup(bundle_path); *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); ui->kits = scan_kits(); @@ -493,19 +536,7 @@ port_event(LV2UI_Handle handle, DrMrPortIndex index = (DrMrPortIndex)port_index; DrMrUi* ui = (DrMrUi*)handle; - if (index == DRMR_KITNUM) { - 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) { + if (index == DRMR_BASENOTE) { int base = (int)(*((float*)buffer)); if (base >= 21 && base <= 107) { setBaseLabel((int)base);