diff --git a/drmr.c b/drmr.c index f36b37c..2880d14 100644 --- a/drmr.c +++ b/drmr.c @@ -212,6 +212,26 @@ static inline void layer_to_sample(drmr_sample *sample, float gain) { sample->data = sample->layers[0].data; } +static inline void trigger_sample(DrMr *drmr, int nn, uint8_t* const data) { + // need to mutex this to avoid getting the samples array + // changed after the check that the midi-note is valid + pthread_mutex_lock(&drmr->load_mutex); + if (nn >= 0 && nn < drmr->num_samples) { + if (drmr->samples[nn].layer_count > 0) { + layer_to_sample(drmr->samples+nn,*(drmr->gains[nn])); + if (drmr->samples[nn].limit == 0) + fprintf(stderr,"Failed to find layer at: %i for %f\n",nn,*drmr->gains[nn]); + } + if (data) { + lv2_atom_forge_frame_time(&drmr->forge, 0); + build_midi_info_message(drmr,data); + } + drmr->samples[nn].active = 1; + drmr->samples[nn].offset = 0; + } + pthread_mutex_unlock(&drmr->load_mutex); +} + #define DB3SCALE -0.8317830986718104f #define DB3SCALEPO 1.8317830986718104f // taken from lv2 example amp plugin @@ -242,21 +262,7 @@ static void run(LV2_Handle instance, uint32_t n_samples) { case 9: { uint8_t nn = data[1]; nn-=baseNote; - // need to mutex this to avoid getting the samples array - // changed after the check that the midi-note is valid - pthread_mutex_lock(&drmr->load_mutex); - if (nn >= 0 && nn < drmr->num_samples) { - if (drmr->samples[nn].layer_count > 0) { - layer_to_sample(drmr->samples+nn,*(drmr->gains[nn])); - if (drmr->samples[nn].limit == 0) - fprintf(stderr,"Failed to find layer at: %i for %f\n",nn,*drmr->gains[nn]); - } - lv2_atom_forge_frame_time(&drmr->forge, 0); - build_midi_info_message(drmr,data); - drmr->samples[nn].active = 1; - drmr->samples[nn].offset = 0; - } - pthread_mutex_unlock(&drmr->load_mutex); + trigger_sample(drmr,nn,data); break; } default: @@ -267,10 +273,9 @@ static void run(LV2_Handle instance, uint32_t n_samples) { 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 { + const LV2_Atom* trigger = NULL; + lv2_object_get(obj, drmr->uris.kit_path, &path, drmr->uris.sample_trigger, &trigger, 0); + if (path) { int reqPos = (drmr->curReq+1)%REQ_BUF_SIZE; char *tmp = NULL; if (reqPos >= 0 && @@ -280,6 +285,14 @@ static void run(LV2_Handle instance, uint32_t n_samples) { drmr->curReq = reqPos; if (tmp) free(tmp); } + if (trigger) { + int32_t si = ((const LV2_Atom_Int*)trigger)->body; + uint8_t mdata[3]; + mdata[0] = 0x90; // note on + mdata[1] = si+baseNote; + mdata[2] = 0x7f; + trigger_sample(drmr,si,mdata); + } } else if (obj->body.otype == drmr->uris.get_state) { lv2_atom_forge_frame_time(&drmr->forge, 0); build_state_message(drmr); diff --git a/drmr.h b/drmr.h index 0bf9690..618a98f 100644 --- a/drmr.h +++ b/drmr.h @@ -150,6 +150,7 @@ typedef struct { LV2_URID string_urid; LV2_URID get_state; LV2_URID midi_info; + LV2_URID sample_trigger; } drmr_uris; typedef struct { @@ -208,6 +209,9 @@ void map_drmr_uris(LV2_URID_Map *map, uris->midi_info = map->map(map->handle, DRMR_URI "#midiinfo"); + uris->sample_trigger = + map->map(map->handle, + DRMR_URI "#sampletrigger"); uris->atom_eventTransfer = map->map(map->handle, LV2_ATOM__eventTransfer); uris->atom_resource = diff --git a/drmr_ui.c b/drmr_ui.c index a4f7871..76888bc 100644 --- a/drmr_ui.c +++ b/drmr_ui.c @@ -65,7 +65,7 @@ typedef struct { int samples; int baseNote; - GQuark gain_quark, pan_quark; + GQuark gain_quark, pan_quark, trigger_quark; int curKit; int kitReq; @@ -92,6 +92,24 @@ static gboolean pan_callback(GtkRange* range, GtkScrollType type, gdouble value, return FALSE; } +static gboolean trigger_led_clicked(GtkWidget *widget, GdkEvent *event, gpointer data) { + LV2_Atom_Forge_Frame set_frame; + DrMrUi* ui = (DrMrUi*)data; + int32_t tidx = GPOINTER_TO_INT(g_object_get_qdata(G_OBJECT(widget),ui->trigger_quark)); + uint8_t msg_buf[1024]; + lv2_atom_forge_set_buffer(&ui->forge, msg_buf, 1024); + 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.sample_trigger,0); + lv2_atom_forge_int(&ui->forge, tidx); + lv2_atom_forge_pop(&ui->forge,&set_frame); + ui->write(ui->controller,DRMR_CONTROL, + lv2_atom_total_size(msg), + ui->uris.atom_eventTransfer, + msg); + return FALSE; +} + static void fill_sample_table(DrMrUi* ui, int samples, char** names, GtkWidget** notify_leds, GtkWidget** gain_sliders, GtkWidget** pan_sliders) { int row = 0; int col = 0; @@ -116,7 +134,7 @@ static void fill_sample_table(DrMrUi* ui, int samples, char** names, GtkWidget** for(si = 0;sitrigger_quark,GINT_TO_POINTER(si)); + g_signal_connect(G_OBJECT(led_event_box),"button-release-event", + G_CALLBACK(trigger_led_clicked),ui); led = gtk_image_new_from_pixbuf(led_off_pixbuf); if (notify_leds) notify_leds[si] = led; + gtk_container_add(GTK_CONTAINER(led_event_box),led); - gtk_box_pack_start(GTK_BOX(button_box),led,false,false,0); + gtk_box_pack_start(GTK_BOX(button_box),led_event_box,false,false,0); gtk_box_pack_start(GTK_BOX(button_box),gtk_label_new(""),true,true,0); @@ -576,6 +599,7 @@ instantiate(const LV2UI_Descriptor* descriptor, ui->kits = scan_kits(); ui->gain_quark = g_quark_from_string("drmr_gain_quark"); ui->pan_quark = g_quark_from_string("drmr_pan_quark"); + ui->trigger_quark = g_quark_from_string("drmr_trigger_quark"); ui->gain_sliders = NULL; ui->pan_sliders = NULL;