diff --git a/drmr2.c b/drmr2.c index cefff9d..0f45c81 100644 --- a/drmr2.c +++ b/drmr2.c @@ -84,6 +84,7 @@ instantiate(const LV2_Descriptor* descriptor, drmr->rate = rate; drmr->ignore_velocity = false; drmr->ignore_note_off = true; + drmr->channel_nb = 0; #ifdef DRMR_UI_ZERO_SAMP drmr->zero_position = DRMR_UI_ZERO_SAMP; @@ -225,6 +226,8 @@ static inline LV2_Atom *build_state_message(DrMr *drmr) { lv2_atom_forge_bool(&drmr->forge, drmr->ignore_velocity?true:false); lv2_atom_forge_property_head(&drmr->forge, drmr->uris.note_off_toggle,0); lv2_atom_forge_bool(&drmr->forge, drmr->ignore_note_off?true:false); + lv2_atom_forge_property_head(&drmr->forge, drmr->uris.channel_nb,0); + lv2_atom_forge_int(&drmr->forge, drmr->channel_nb); lv2_atom_forge_property_head(&drmr->forge, drmr->uris.zero_position,0); lv2_atom_forge_int(&drmr->forge, drmr->zero_position); lv2_atom_forge_pop(&drmr->forge,&set_frame); @@ -346,24 +349,36 @@ static void run(LV2_Handle instance, uint32_t n_samples) { uint8_t nn; uint8_t* const data = (uint8_t* const)(ev + 1); uint32_t offset = (ev->time.frames > 0 && ev->time.frames < n_samples) ? ev->time.frames : 0; - //int channel = *data & 15; - switch ((*data) >> 4) { - case 8: - if (!drmr->ignore_note_off) { - nn = data[1]; - nn-=baseNote; - untrigger_sample(drmr,nn,offset); - } - break; - case 9: { - nn = data[1]; - nn-=baseNote; - trigger_sample(drmr,nn,data,offset); - break; - } - default: - //printf("Unhandeled status: %i\n",(*data)>>4); - break; + int channel = *data & 15; + + if( ( drmr->channel_nb == 0) || ( channel == ( drmr->channel_nb - 1))) + { + switch ((*data) >> 4) + { + case 8: + { + if (!drmr->ignore_note_off) { + nn = data[1]; + nn-=baseNote; + untrigger_sample(drmr,nn,offset); + } + break; + } + + case 9: + { + nn = data[1]; + nn-=baseNote; + trigger_sample(drmr,nn,data,offset); + break; + } + + default: + { + //printf("Unhandeled status: %i\n",(*data)>>4); + break; + } + } } } else if (ev->body.type == drmr->uris.atom_resource) { @@ -373,12 +388,14 @@ static void run(LV2_Handle instance, uint32_t n_samples) { const LV2_Atom* trigger = NULL; const LV2_Atom* ignvel = NULL; const LV2_Atom* ignno = NULL; + const LV2_Atom* channel_nb = NULL; const LV2_Atom* zerop = NULL; lv2_atom_object_get(obj, drmr->uris.kit_path, &path, drmr->uris.sample_trigger, &trigger, drmr->uris.velocity_toggle, &ignvel, drmr->uris.note_off_toggle, &ignno, + drmr->uris.channel_nb, &channel_nb, drmr->uris.zero_position, &zerop, 0); if (path) { @@ -404,6 +421,8 @@ static void run(LV2_Handle instance, uint32_t n_samples) { drmr->ignore_velocity = ((const LV2_Atom_Bool*)ignvel)->body; if (ignno) drmr->ignore_note_off = ((const LV2_Atom_Bool*)ignno)->body; + if (channel_nb) + drmr->channel_nb = ((const LV2_Atom_Int*)channel_nb)->body; if (zerop) drmr->zero_position = ((const LV2_Atom_Int*)zerop)->body; } else if (obj->body.otype == drmr->uris.get_state) { @@ -572,6 +591,14 @@ save_state(LV2_Handle instance, LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); if (stat) return stat; + stat = store(handle, + drmr->uris.channel_nb, + &drmr->channel_nb, + sizeof(int), + drmr->uris.int_urid, + LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); + if (stat) return stat; + stat = store(handle, drmr->uris.zero_position, &drmr->zero_position, @@ -639,6 +666,11 @@ restore_state(LV2_Handle instance, if (ignore_note_off) drmr->ignore_note_off = *ignore_note_off?true:false; + const int* channel_nb = + retrieve(handle, drmr->uris.channel_nb, &size, &type, &fgs); + if (channel_nb) + drmr->channel_nb = *channel_nb; + const int* zero_position = retrieve(handle, drmr->uris.zero_position, &size, &type, &fgs); if (zero_position) diff --git a/drmr2.h b/drmr2.h index c1f5974..5df0ce3 100644 --- a/drmr2.h +++ b/drmr2.h @@ -219,6 +219,7 @@ typedef struct { LV2_URID sample_trigger; LV2_URID velocity_toggle; LV2_URID note_off_toggle; + LV2_URID channel_nb; LV2_URID zero_position; } drmr_uris; @@ -232,8 +233,10 @@ typedef struct { LV2_Atom_Forge forge; // params + int channel; bool ignore_velocity; bool ignore_note_off; + int channel_nb; int zero_position; float** gains; float** pans; @@ -293,6 +296,9 @@ void map_drmr_uris(LV2_URID_Map *map, uris->note_off_toggle = map->map(map->handle, DRMR_URI "#noteofftoggle"); + uris->channel_nb = + map->map(map->handle, + DRMR_URI "#channelnb"); uris->zero_position = map->map(map->handle, DRMR_URI "#zeroposition"); diff --git a/drmr2_ui.c b/drmr2_ui.c index 0112d3b..d52ad62 100644 --- a/drmr2_ui.c +++ b/drmr2_ui.c @@ -52,7 +52,7 @@ typedef struct { GtkWidget** gain_sliders; GtkWidget** pan_sliders; GtkWidget** notify_leds; - GtkWidget *position_combo_box, *velocity_checkbox, *note_off_checkbox; + GtkWidget *channel_combo_box, *position_combo_box, *velocity_checkbox, *note_off_checkbox; GtkScrolledWindow *sample_view; float *gain_vals,*pan_vals; @@ -60,6 +60,7 @@ typedef struct { gchar *bundle_path; + int channel; int cols; int startSamp; @@ -417,10 +418,63 @@ static void kit_combobox_changed(GtkComboBox* box, gpointer data) { } } +static void channel_data(DrMrUi *ui, gpointer data) { + lv2_atom_forge_property_head(&ui->forge, ui->uris.channel_nb,0); + lv2_atom_forge_int(&ui->forge, GPOINTER_TO_INT(data)); +} + +static void channel_combobox_changed(GtkComboBox* box, gpointer data) { + DrMrUi* ui = (DrMrUi*)data; + gint channel = gtk_combo_box_get_active (GTK_COMBO_BOX(box)); + + printf( "Channel Change: [%d]\n", channel); + + if (channel != ui->channel) { + ui->channel = channel; + ui->forceUpdate = true; + kit_callback(ui); + send_ui_msg(ui,&channel_data,GINT_TO_POINTER(channel)); + } +} + +static GtkWidget *create_channel_combo(void) +{ + GtkWidget *combo; + GtkListStore *list_store; + GtkCellRenderer *cell; + GtkTreeIter iter; + int i; + char label[8]; + + list_store = gtk_list_store_new(1, G_TYPE_STRING); + + gtk_list_store_append(list_store, &iter); + gtk_list_store_set (list_store, &iter, 0, "Omni", -1); + + for( i = 1; i <= 16; i++) { + sprintf( label, "%02d", i); + gtk_list_store_append(list_store, &iter); + gtk_list_store_set (list_store, &iter, 0, label, -1); + } + + combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(list_store)); + + gtk_combo_box_set_active(GTK_COMBO_BOX(combo),0); + + g_object_unref(list_store); + + cell = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), cell, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), cell, "text", 0, NULL); + + return combo; +} + static void position_data(DrMrUi *ui, gpointer data) { lv2_atom_forge_property_head(&ui->forge, ui->uris.zero_position,0); lv2_atom_forge_int(&ui->forge, GPOINTER_TO_INT(data)); } + static void position_combobox_changed(GtkComboBox* box, gpointer data) { DrMrUi* ui = (DrMrUi*)data; gint ss = gtk_combo_box_get_active (GTK_COMBO_BOX(box)); @@ -458,7 +512,6 @@ static GtkWidget *create_position_combo(void) gtk_combo_box_set_active(GTK_COMBO_BOX(combo),0); #endif - g_object_unref(list_store); cell = gtk_cell_renderer_text_new(); @@ -510,7 +563,7 @@ static void build_drmr_ui(DrMrUi* ui) { GtkWidget *drmr_ui_widget; GtkWidget *opts_hbox1, *opts_hbox2, *kit_combo_box, *kit_label, *no_kit_label, - *base_label, *base_spin, *position_label, *sample_view; + *base_label, *base_spin, *channel_label, *position_label, *sample_view; GtkCellRenderer *cell_rend; GtkAdjustment *base_adj; @@ -551,6 +604,9 @@ static void build_drmr_ui(DrMrUi* ui) { 5.0,0.0)); // page adj/size base_spin = gtk_spin_button_new(base_adj, 1.0, 0); + channel_label = gtk_label_new("Midi Channel: "); + ui->channel_combo_box = create_channel_combo(); + position_label = gtk_label_new("Sample Zero Position: "); ui->position_combo_box = create_position_combo(); @@ -568,6 +624,10 @@ static void build_drmr_ui(DrMrUi* ui) { gtk_box_pack_start(GTK_BOX(opts_hbox1),base_spin, true,true,0); + gtk_box_pack_start(GTK_BOX(opts_hbox2),channel_label, + false,false,15); + gtk_box_pack_start(GTK_BOX(opts_hbox2),ui->channel_combo_box, + false,false,0); gtk_box_pack_start(GTK_BOX(opts_hbox2),position_label, false,false,15); gtk_box_pack_start(GTK_BOX(opts_hbox2),ui->position_combo_box, @@ -604,6 +664,7 @@ static void build_drmr_ui(DrMrUi* ui) { g_signal_connect(G_OBJECT(kit_combo_box),"changed",G_CALLBACK(kit_combobox_changed),ui); g_signal_connect(G_OBJECT(base_spin),"value-changed",G_CALLBACK(base_changed),ui); + g_signal_connect(G_OBJECT(ui->channel_combo_box),"changed",G_CALLBACK(channel_combobox_changed),ui); g_signal_connect(G_OBJECT(ui->position_combo_box),"changed",G_CALLBACK(position_combobox_changed),ui); g_signal_connect(G_OBJECT(ui->velocity_checkbox),"toggled",G_CALLBACK(ignore_velocity_toggled),ui); g_signal_connect(G_OBJECT(ui->note_off_checkbox),"toggled",G_CALLBACK(ignore_note_off_toggled),ui); @@ -755,10 +816,12 @@ port_event(LV2UI_Handle handle, if (obj->body.otype == ui->uris.get_state) { // read out extra state info const LV2_Atom* ignvel = NULL; const LV2_Atom* ignno = NULL; + const LV2_Atom* channel_nb = NULL; const LV2_Atom* zerop = NULL; lv2_atom_object_get(obj, ui->uris.velocity_toggle, &ignvel, ui->uris.note_off_toggle, &ignno, + ui->uris.channel_nb, &channel_nb, ui->uris.zero_position, &zerop, 0); if (ignvel) @@ -767,6 +830,9 @@ port_event(LV2UI_Handle handle, if (ignno) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ui->note_off_checkbox), ((const LV2_Atom_Bool*)ignno)->body); + if (channel_nb) + gtk_combo_box_set_active(GTK_COMBO_BOX(ui->channel_combo_box), + ((const LV2_Atom_Int*)channel_nb)->body); if (zerop) gtk_combo_box_set_active(GTK_COMBO_BOX(ui->position_combo_box), ((const LV2_Atom_Int*)zerop)->body);