diff --git a/src/MidiKeyBoard.cpp b/src/MidiKeyBoard.cpp index 13f09b1..652beaf 100644 --- a/src/MidiKeyBoard.cpp +++ b/src/MidiKeyBoard.cpp @@ -82,8 +82,7 @@ XKeyBoard::XKeyBoard(xjack::XJack *xjack_, xalsa::XAlsa *xalsa_, xsynth::XSynth midimapper::MidiMapper *midimap, mamba::MidiMessenger *mmessage_, nsmhandler::NsmSignalHandler& nsmsig_, PosixSignalHandler& xsig_, AnimatedKeyBoard * animidi_) - : xjack(xjack_), - xalsa(xalsa_), + : xalsa(xalsa_), xsynth(xsynth_), mmapper(midimap), save(), @@ -91,7 +90,8 @@ XKeyBoard::XKeyBoard(xjack::XJack *xjack_, xalsa::XAlsa *xalsa_, xsynth::XSynth mmessage(mmessage_), animidi(animidi_), nsmsig(nsmsig_), - xsig(xsig_) { + xsig(xsig_), + xjack(xjack_) { client_name = xjack->client_name; if (getenv("XDG_CONFIG_HOME")) { path = getenv("XDG_CONFIG_HOME"); @@ -580,11 +580,13 @@ void XKeyBoard::draw_my_combobox_entrys(void *w_, void* user_data) noexcept{ void XKeyBoard::rounded_rectangle(cairo_t *cr,float x, float y, float width, float height) { cairo_new_path (cr); - cairo_move_to (cr, x, (y + height)/2); - cairo_curve_to (cr, x ,y, x, y, (x + width)/2, y); - cairo_curve_to (cr, width, y, width, y, width, (y + height)/2); - cairo_curve_to (cr, width, height, width, height, (width + x)/2, height); - cairo_curve_to (cr, x, height, x, height, x, (y + height)/2); + float r = height * 0.33334; + cairo_new_path (cr); + cairo_arc(cr, x+r, y+r, r, M_PI, 3*M_PI/2); + cairo_arc(cr, x+width-1-r, y+r, r, 3*M_PI/2, 0); + cairo_arc(cr, x+width-1-r, y+height-1-r, r, 0, M_PI/2); + cairo_arc(cr, x+r, y+height-1-r, r, M_PI/2, M_PI); + cairo_close_path(cr); cairo_close_path (cr); } @@ -709,6 +711,11 @@ void XKeyBoard::draw_button(void *w_, void* user_data) noexcept{ cairo_move_to (w->crb, (width-extents.width)*0.5 +offset + set_line, (height+extents.height)*0.55 +offset); cairo_line_to(w->crb,(width-extents.width)*0.5 +offset + set_line + underline, (height+extents.height)*0.55 +offset); cairo_stroke(w->crb); + } else if (strstr(w->label, "-") || strstr(w->label, "+" )) { + cairo_text_extents(w->crb,w->label , &extents); + cairo_move_to (w->crb, (width-extents.width)*0.55 +offset, (height+extents.height)*0.65 +offset); + cairo_show_text(w->crb, w->label); + } else { cairo_text_extents(w->crb,w->label , &extents); cairo_move_to (w->crb, (width-extents.width)*0.5 +offset, (height+extents.height)*0.5 +offset); @@ -1076,6 +1083,8 @@ void XKeyBoard::init_ui(Xputty *app) { looper->flags |= NO_AUTOREPEAT; free_wheel = menu_add_check_entry(looper,_("Freewheel")); free_wheel->func.value_changed_callback = freewheel_callback; + lmc = menu_add_check_entry(looper,_("Channel Control")); + lmc->func.value_changed_callback = lmc_callback; menu_add_entry(looper,_("Clear All Channels")); menu_add_entry(looper,_("Clear Current Channel")); looper->func.value_changed_callback = clear_loops_callback; @@ -1313,6 +1322,7 @@ void XKeyBoard::init_ui(Xputty *app) { build_sfont_menu(); init_synth_ui(win); + init_looper_ui(win); // start the timeout thread for keyboard animation animidi->start(30, std::bind(animate_midi_keyboard,(void*)wid)); is_inited.store(true, std::memory_order_release); @@ -1439,11 +1449,17 @@ void XKeyBoard::win_configure_callback(void *w_, void* user_data) { xjmkb->main_w = width; xjmkb->main_h = height; + int y = xjmkb->main_y-226; XGetWindowAttributes(w->app->dpy, (Window)xjmkb->synth_ui->widget, &attrs); + if (attrs.map_state == IsViewable) { + if (xjmkb->main_y < 230) y = xjmkb->main_y + xjmkb->main_h+21; + XMoveWindow(xjmkb->win->app->dpy,xjmkb->synth_ui->widget, xjmkb->main_x, y); + } + XGetWindowAttributes(w->app->dpy, (Window)xjmkb->looper_control->widget, &attrs); if (attrs.map_state != IsViewable) return; - int y = xjmkb->main_y-226; - if (xjmkb->main_y < 230) y = xjmkb->main_y + xjmkb->main_h+21; - XMoveWindow(xjmkb->win->app->dpy,xjmkb->synth_ui->widget, xjmkb->main_x, y); + y = xjmkb->main_y-71; + if (xjmkb->main_y < 75) y = xjmkb->main_y + xjmkb->main_h+21; + XMoveWindow(xjmkb->win->app->dpy,xjmkb->looper_control->widget, xjmkb->main_x+650, y); } //static @@ -2717,12 +2733,21 @@ void XKeyBoard::freewheel_callback(void *w_, void* user_data) noexcept{ xjmkb->xjack->freewheel = xjmkb->freewheel = xjmkb->save.freewheel = value; } +// static +void XKeyBoard::lmc_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + XKeyBoard *xjmkb = XKeyBoard::get_instance(w); + int value = (int)adj_get_value(w->adj); + if (value) xjmkb->show_looper_ui(1); + else xjmkb->show_looper_ui(0); +} + // static void XKeyBoard::clear_loops_callback(void *w_, void* user_data) noexcept{ Widget_t *w = (Widget_t*)w_; XKeyBoard *xjmkb = XKeyBoard::get_instance(w); MambaKeyboard *keys = (MambaKeyboard*)xjmkb->wid->parent_struct; - if ((int)adj_get_value(w->adj) == 2) { + if ((int)adj_get_value(w->adj) == 3) { xjmkb->xjack->play = 0.0; //adj_set_value(xjmkb->play->adj, 0.0); //set_play_label(xjmkb->play,NULL); @@ -2747,7 +2772,7 @@ void XKeyBoard::clear_loops_callback(void *w_, void* user_data) noexcept{ xjmkb->time_line->label = xjmkb->time_line->input_label; expose_widget(xjmkb->time_line); xjmkb->need_save = true; - } else if ((int)adj_get_value(w->adj) == 3) { + } else if ((int)adj_get_value(w->adj) == 4) { if (xjmkb->xjack->rec.channel == 0) { xjmkb->file_names.clear(); xjmkb->build_remove_menu(); @@ -3500,6 +3525,272 @@ void XKeyBoard::init_synth_ui(Widget_t *parent) { } +/******************* Looper Controls *****************/ + +void XKeyBoard::show_looper_ui(int present) { + if(present) { + widget_show_all(looper_control); + int y = main_y-71; + if (main_y < 75) y = main_y + main_h+21; + XMoveWindow(win->app->dpy,looper_control->widget, main_x+650, y); + }else { + widget_hide(looper_control); + } +} + +//static +void XKeyBoard::hide_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + adj_set_value(xjmkb->lmc->adj, 0.0); +} + +static void play_channel1_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[0] = i; + +} + +static void play_channel2_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[1] = i; + +} + +static void play_channel3_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[2] = i; + +} + +static void play_channel4_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[3] = i; + +} + +static void play_channel5_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[4] = i; + +} + +static void play_channel6_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[5] = i; + +} + +static void play_channel7_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[6] = i; + +} + +static void play_channel8_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[7] = i; + +} + +static void play_channel9_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[8] = i; + +} + +static void play_channel10_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[9] = i; + +} + +static void play_channel11_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[10] = i; + +} + +static void play_channel12_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[11] = i; + +} + +static void play_channel13_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[12] = i; + +} + +static void play_channel14_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[13] = i; + +} + +static void play_channel15_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[14] = i; + +} + +static void play_channel16_callback(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + Widget_t *win = get_toplevel_widget(w->app); + XKeyBoard *xjmkb = (XKeyBoard*) win->parent_struct; + int i = (int)adj_get_value(w->adj); + xjmkb->xjack->channel_matrix[15] = i; + +} + +void XKeyBoard::init_looper_ui(Widget_t *parent) { + looper_control = create_window(parent->app, DefaultRootWindow(parent->app->dpy), 0, 0, 415, 45); + XSelectInput(parent->app->dpy, looper_control->widget,StructureNotifyMask|ExposureMask|KeyPressMask + |EnterWindowMask|LeaveWindowMask|ButtonReleaseMask|KeyReleaseMask + |ButtonPressMask|Button1MotionMask|PointerMotionMask); + XSetTransientForHint(parent->app->dpy, looper_control->widget, parent->widget); + soundfontname = basename((char*)soundfont.c_str()); + std::string title = _("Looper Channel Control "); + widget_set_title(looper_control, title.c_str()); + looper_control->flags &= ~USE_TRANSPARENCY; + looper_control->flags |= NO_AUTOREPEAT | NO_PROPAGATE | HIDE_ON_DELETE; + looper_control->func.expose_callback = draw_synth_ui; + looper_control->scale.gravity = CENTER; + looper_control->parent = parent; + looper_control->parent_struct = this; + looper_control->func.key_press_callback = key_press; + looper_control->func.key_release_callback = key_release; + looper_control->func.unmap_notify_callback = hide_callback; + + Widget_t *tmp = mamba_add_keyboard_button(looper_control, _("1"), 10, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel1_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("2"), 35, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel2_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("3"), 60, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel3_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("4"), 85, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel4_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("5"), 105, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel5_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("6"), 130, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel6_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("7"), 155, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel7_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("8"), 180, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel8_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("9"), 205, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel9_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("10"), 230, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel10_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("11"), 255, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel11_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("12"), 280, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel12_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("13"), 305, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel13_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("14"), 330, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel14_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("15"), 355, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel15_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; + tmp = mamba_add_keyboard_button(looper_control, _("16"), 380, 10, 25, 25); + tmp->flags |= NO_AUTOREPEAT | NO_PROPAGATE; + tmp->func.value_changed_callback = play_channel16_callback; + tmp->func.key_press_callback = key_press; + tmp->func.key_release_callback = key_release; +} + /******************* Exit handlers ********************/ void XKeyBoard::signal_handle (int sig) { diff --git a/src/MidiKeyBoard.h b/src/MidiKeyBoard.h index 535a325..fb77e74 100644 --- a/src/MidiKeyBoard.h +++ b/src/MidiKeyBoard.h @@ -142,7 +142,6 @@ class AnimatedKeyBoard { class XKeyBoard { private: - xjack::XJack *xjack; xalsa::XAlsa *xalsa; xsynth::XSynth *xsynth; midimapper::MidiMapper *mmapper; @@ -162,8 +161,10 @@ class XKeyBoard { Widget_t *play; Widget_t *filemenu; Widget_t *looper; + Widget_t *looper_control; Widget_t *view_channels; Widget_t *free_wheel; + Widget_t *lmc; Widget_t *info; Widget_t *mapping; Widget_t *keymap; @@ -279,6 +280,7 @@ class XKeyBoard { static void record_callback(void *w_, void* user_data); static void play_callback(void *w_, void* user_data) noexcept; static void freewheel_callback(void *w_, void* user_data) noexcept; + static void lmc_callback(void *w_, void* user_data) noexcept; static void clear_loops_callback(void *w_, void* user_data) noexcept; static void view_channels_callback(void *w_, void* user_data) noexcept; static void animate_midi_keyboard(void *w_); @@ -334,6 +336,10 @@ class XKeyBoard { static void check_edo_mapfile(XKeyBoard *xjmkb, int edo); static void remamba_set_edos(XKeyBoard *xjmkb) noexcept; + static void hide_callback(void *w_, void* user_data) noexcept; + void show_looper_ui(int present); + void init_looper_ui(Widget_t *parent); + Widget_t *mamba_add_keyboard_knob(Widget_t *parent, const char * label, int x, int y, int width, int height); Widget_t *mamba_add_keyboard_button(Widget_t *parent, const char * label, @@ -365,6 +371,8 @@ class XKeyBoard { PosixSignalHandler& xsig, AnimatedKeyBoard * animidi); ~XKeyBoard(); + xjack::XJack *xjack; + std::string client_name; std::string config_file; std::string keymap_file; diff --git a/src/XJack.cpp b/src/XJack.cpp index d250f19..7262d50 100644 --- a/src/XJack.cpp +++ b/src/XJack.cpp @@ -137,6 +137,7 @@ XJack::XJack(mamba::MidiMessenger *mmessage_, for ( int i = 0; i < 16; i++) posPlay[i] = 0; for ( int i = 0; i < 16; i++) startPlay[i] = 0; for ( int i = 0; i < 16; i++) stopPlay[i] = 0; + for ( int i = 0; i < 16; i++) channel_matrix[i] = 0; } XJack::~XJack() { @@ -270,30 +271,32 @@ inline void XJack::play_midi(void *buf, unsigned int n) { const mamba::MidiEvent ev = rec.play[i][posPlay[i]]; if (deltaTime >= ev.deltaTime * bpm_ratio) { playPosTime = ev.absoluteTime; - unsigned char* midi_send = jack_midi_event_reserve(buf, n, ev.num); - if (midi_send) { - midi_send[0] = ev.buffer[0]; - midi_send[1] = ev.buffer[1]; - if(ev.num > 2) - midi_send[2] = ev.buffer[2]; - bool ch = true; - if (mmessage->channel < 16 && view_channels) { - if ((mmessage->channel) != (int(ev.buffer[0]&0x0f))) { - ch = false; + if (!channel_matrix[int(ev.buffer[0]&0x0f)] || ((ev.buffer[0] & 0xf0) == 0x80 )) { + unsigned char* midi_send = jack_midi_event_reserve(buf, n, ev.num); + if (midi_send) { + midi_send[0] = ev.buffer[0]; + midi_send[1] = ev.buffer[1]; + if(ev.num > 2) + midi_send[2] = ev.buffer[2]; + bool ch = true; + if (mmessage->channel < 16 && view_channels) { + if ((mmessage->channel) != (int(ev.buffer[0]&0x0f))) { + ch = false; + } } - } - send_to_alsa(midi_send, ev.num); + send_to_alsa(midi_send, ev.num); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-result" - if ((ev.buffer[0] & 0xf0) == 0x90 && ch) { // Note On - if (ev.buffer[2] > 0) // velocity 0 treaded as Note Off - std::async(std::launch::async, trigger_get_midi_in, (int(ev.buffer[0]&0x0f)), ev.buffer[1], true); - else + if ((ev.buffer[0] & 0xf0) == 0x90 && ch) { // Note On + if (ev.buffer[2] > 0) // velocity 0 treaded as Note Off + std::async(std::launch::async, trigger_get_midi_in, (int(ev.buffer[0]&0x0f)), ev.buffer[1], true); + else + std::async(std::launch::async, trigger_get_midi_in, (int(ev.buffer[0]&0x0f)), ev.buffer[1], false); + } else if ((ev.buffer[0] & 0xf0) == 0x80 && ch) { // Note Off std::async(std::launch::async, trigger_get_midi_in, (int(ev.buffer[0]&0x0f)), ev.buffer[1], false); - } else if ((ev.buffer[0] & 0xf0) == 0x80 && ch) { // Note Off - std::async(std::launch::async, trigger_get_midi_in, (int(ev.buffer[0]&0x0f)), ev.buffer[1], false); - } + } #pragma GCC diagnostic pop + } } startPlay[i] = jack_last_frame_time(client)+n; posPlay[i]++; diff --git a/src/XJack.h b/src/XJack.h index cd30355..b87a2f2 100644 --- a/src/XJack.h +++ b/src/XJack.h @@ -150,6 +150,7 @@ class XJack : public sigc::trackable { unsigned int bpm; float max_loop_time; int midi_map; + unsigned int channel_matrix[16]; float get_max_loop_time() noexcept; sigc::signal trigger_quit_by_jack;