diff --git a/drmr.c b/drmr.c index 2d78cd3..39915bc 100644 --- a/drmr.c +++ b/drmr.c @@ -24,6 +24,8 @@ #define REQ_BUF_SIZE 10 +static int current_kit_changed = 0; + static void* load_thread(void* arg) { DrMr* drmr = (DrMr*)arg; drmr_sample *loaded_samples,*old_samples; @@ -55,6 +57,7 @@ static void* load_thread(void* arg) { } if (old_scount > 0) free_samples(old_samples,old_scount); drmr->current_path = request; + current_kit_changed = 1; } return 0; } @@ -96,12 +99,7 @@ instantiate(const LV2_Descriptor* descriptor, } map_drmr_uris(drmr->map,&(drmr->uris)); - drmr->kits = scan_kits(); - if (!drmr->kits) { - fprintf(stderr, "No drum kits found\n"); - free(drmr); - return 0; - } + lv2_atom_forge_init(&drmr->forge, drmr->map); if (pthread_create(&drmr->load_thread, 0, load_thread, drmr)) { fprintf(stderr, "Could not initialize loading thread.\n"); @@ -132,8 +130,8 @@ 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; + case DRMR_CORE_EVENT: + drmr->core_event_port = (LV2_Atom_Sequence*)data; break; case DRMR_LEFT: drmr->left = (float*)data; @@ -161,6 +159,16 @@ connect_port(LV2_Handle instance, } } +static inline LV2_Atom* build_update_message(DrMr *drmr, const char* kit) { + LV2_Atom_Forge_Frame set_frame; + LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_resource + (&drmr->forge, &set_frame, 1, drmr->uris.ui_msg); + lv2_atom_forge_property_head(&drmr->forge, drmr->uris.kit_path,0); + lv2_atom_forge_string(&drmr->forge, kit, strlen(kit)); + lv2_atom_forge_pop(&drmr->forge,&set_frame); + return msg; +} + static inline void layer_to_sample(drmr_sample *sample, float gain) { int i; float mapped_gain = (1-(gain/GAIN_MIN)); @@ -194,6 +202,13 @@ static void run(LV2_Handle instance, uint32_t n_samples) { baseNote = (int)floorf(*(drmr->baseNote)); + const uint32_t event_capacity = drmr->core_event_port->atom.size; + lv2_atom_forge_set_buffer(&drmr->forge, + (uint8_t*)drmr->core_event_port, + event_capacity); + LV2_Atom_Forge_Frame seq_frame; + lv2_atom_forge_sequence_head(&drmr->forge, &seq_frame, 0); + LV2_SEQUENCE_FOREACH(drmr->control_port, i) { LV2_Atom_Event* const ev = lv2_sequence_iter_get(i); if (ev->body.type == drmr->uris.midi_event) { @@ -254,6 +269,14 @@ static void run(LV2_Handle instance, uint32_t n_samples) { drmr->request_buf[drmr->curReq]))) pthread_cond_signal(&drmr->load_cond); + if (current_kit_changed) { + current_kit_changed = 0; + lv2_atom_forge_frame_time(&drmr->forge, 0); + build_update_message(drmr,drmr->current_path); + } + + lv2_atom_forge_pop(&drmr->forge, &seq_frame); + for(i = 0;ileft[i] = 0.0f; drmr->right[i] = 0.0f; @@ -303,7 +326,6 @@ static void cleanup(LV2_Handle instance) { pthread_join(drmr->load_thread, 0); if (drmr->num_samples > 0) free_samples(drmr->samples,drmr->num_samples); - free_kits(drmr->kits); free(drmr->gains); free(instance); } diff --git a/drmr.h b/drmr.h index 123152f..d06e79d 100644 --- a/drmr.h +++ b/drmr.h @@ -137,7 +137,7 @@ typedef enum { DRMR_PAN_THIRTY, DRMR_PAN_THIRTYONE, DRMR_PAN_THIRTYTWO, - DRMR_KITPATH, + DRMR_CORE_EVENT, DRMR_NUM_PORTS } DrMrPortIndex; @@ -154,7 +154,9 @@ typedef struct { float* left; float* right; LV2_Atom_Sequence *control_port; - LV2_Atom_Sequence *kitpath_port; + LV2_Atom_Sequence *core_event_port; + + LV2_Atom_Forge forge; // params float** gains; @@ -166,8 +168,7 @@ typedef struct { LV2_URID_Map* map; drmr_uris uris; - // Available kits - kits* kits; + // Kit info char* current_path; char** request_buf; int curReq; diff --git a/drmr.ttl b/drmr.ttl index 6f70fc6..c151c2c 100644 --- a/drmr.ttl +++ b/drmr.ttl @@ -23,11 +23,19 @@ a lv2:InputPort , atom:MessagePort; atom:bufferType atom:Sequence ; atom:supports , - ; + ; lv2:index 0; lv2:symbol "control"; lv2:name "Control"; ], + [ + a lv2:OutputPort , atom:MessagePort ; + atom:bufferType atom:Sequence ; + atom:supports ; + lv2:index 69 ; + lv2:symbol "core_events" ; + lv2:name "Core Events" + ], [ a lv2:AudioPort, lv2:OutputPort; lv2:index 1; diff --git a/drmr_ui.c b/drmr_ui.c index 9b5d067..fad17ee 100644 --- a/drmr_ui.c +++ b/drmr_ui.c @@ -304,15 +304,6 @@ static void kit_combobox_changed(GtkComboBox* box, gpointer data) { ui->uris.atom_eventTransfer, msg); } - - /* Call our update func after 100 milliseconds. - * - * This is a hack to deal with hosts that don't send - * back port_events properly after the write function. - * In particular, qtractor doesn't, at the moment. - */ - ui->kitReq = new_kit; - g_timeout_add(100,kit_callback,ui); } static void position_combobox_changed(GtkComboBox* box, gpointer data) { @@ -536,7 +527,32 @@ port_event(LV2UI_Handle handle, DrMrPortIndex index = (DrMrPortIndex)port_index; DrMrUi* ui = (DrMrUi*)handle; - if (index == DRMR_BASENOTE) { + if (index == DRMR_CORE_EVENT) { + if (format == ui->uris.atom_eventTransfer) { + LV2_Atom* atom = (LV2_Atom*)buffer; + if (atom->type == ui->uris.atom_resource) { + LV2_Atom_Object* obj = (LV2_Atom_Object*)atom; + const LV2_Atom* path = NULL; + lv2_object_get(obj, ui->uris.kit_path, &path, 0); + if (!path) + fprintf(stderr,"Got UI message without kit_path, ignoring\n"); + else { + char *kitpath = LV2_ATOM_BODY(path); + int i; + for(i = 0;i < ui->kits->num_kits;i++) + if (!strcmp(ui->kits->kits[i].path,kitpath)) + break; + if (i < ui->kits->num_kits) { + ui->kitReq = i; + g_idle_add(kit_callback,ui); + } + } + } else + fprintf(stderr, "Unknown message type.\n"); + } else + fprintf(stderr, "Unknown format.\n"); + } + else if (index == DRMR_BASENOTE) { int base = (int)(*((float*)buffer)); if (base >= 21 && base <= 107) { setBaseLabel((int)base);