From 0b1d0d230bf06d673c076505f333917e8e199cf9 Mon Sep 17 00:00:00 2001 From: brummer10 Date: Fri, 22 Mar 2024 05:52:44 +0100 Subject: [PATCH] Show channel color in Looper Channel Control --- src/MidiKeyBoard.cpp | 41 ++++++++++++++++++++++++++++++++--------- src/MidiKeyBoard.h | 1 + src/XJack.cpp | 32 ++++++++++++++++++++++---------- src/XJack.h | 6 +++--- 4 files changed, 58 insertions(+), 22 deletions(-) diff --git a/src/MidiKeyBoard.cpp b/src/MidiKeyBoard.cpp index 2b97eae..3970254 100644 --- a/src/MidiKeyBoard.cpp +++ b/src/MidiKeyBoard.cpp @@ -1362,15 +1362,17 @@ void XKeyBoard::animate_midi_keyboard(void *w_) { XUnlockDisplay(w->app->dpy); } - if ((xjmkb->xjack->record || xjmkb->xjack->play) && !xjmkb->xjack->freewheel) { + if ((xjmkb->xjack->record.load(std::memory_order_acquire) || + xjmkb->xjack->play.load(std::memory_order_acquire)) && !xjmkb->xjack->freewheel) { static int scip = 8; if (scip >= 8) { XLockDisplay(w->app->dpy); - if ( xjmkb->xjack->play && xjmkb->xjack->get_max_loop_time() > 0.0) { + if ( xjmkb->xjack->play.load(std::memory_order_acquire) && xjmkb->xjack->get_max_loop_time() > 0.0) { snprintf(xjmkb->time_line->input_label, 31,"%.2f sec", xjmkb->xjack->get_max_loop_time() - (double)((xjmkb->xjack->stPlay - xjmkb->xjack->stStart)/(double)xjmkb->xjack->SampleRate)); - } else if (xjmkb->xjack->record && xjmkb->xjack->play) { + } else if (xjmkb->xjack->record.load(std::memory_order_acquire) && + xjmkb->xjack->play.load(std::memory_order_acquire)) { snprintf(xjmkb->time_line->input_label, 31, "%.2f sec", (double)((xjmkb->xjack->stPlay - xjmkb->xjack->rcStart)/(double)xjmkb->xjack->SampleRate)); } else { @@ -2326,7 +2328,7 @@ void XKeyBoard::channel_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 (xjmkb->xjack->play>0) { + if (xjmkb->xjack->play.load(std::memory_order_acquire)) { for (int i = 0; i<16;i++) mamba_clear_key_matrix(keys->in_key_matrix[i]); } @@ -2664,7 +2666,7 @@ void XKeyBoard::record_callback(void *w_, void* user_data) { Widget_t *w = (Widget_t*)w_; XKeyBoard *xjmkb = XKeyBoard::get_instance(w); int value = (int)adj_get_value(w->adj); - xjmkb->xjack->record = value; + xjmkb->xjack->record.store(value, std::memory_order_release); if (value > 0) { std::string tittle = xjmkb->client_name + _(" - Virtual Midi Keyboard"); widget_set_title(xjmkb->win, tittle.c_str()); @@ -2698,7 +2700,7 @@ void XKeyBoard::record_callback(void *w_, void* user_data) { mamba::MidiEvent ev = {{0x80, 0, 0}, 3, deltaTime, absoluteTime}; xjmkb->xjack->rec.st->push_back(ev); xjmkb->xjack->rec.stop(); - xjmkb->xjack->record_finished = 1; + xjmkb->xjack->record_finished.store(1, std::memory_order_release); snprintf(xjmkb->time_line->input_label, 31,"%.2f sec", xjmkb->xjack->get_max_loop_time()); xjmkb->time_line->label = xjmkb->time_line->input_label; expose_widget(xjmkb->time_line); @@ -2710,7 +2712,7 @@ void XKeyBoard::play_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); - xjmkb->xjack->play = value; + xjmkb->xjack->play.store(value, std::memory_order_release); if (value < 1) { MambaKeyboard *keys = (MambaKeyboard*)xjmkb->wid->parent_struct; for (int i = 0; i<16;i++) @@ -2759,7 +2761,7 @@ void XKeyBoard::clear_loops_callback(void *w_, void* user_data) noexcept{ XKeyBoard *xjmkb = XKeyBoard::get_instance(w); MambaKeyboard *keys = (MambaKeyboard*)xjmkb->wid->parent_struct; if ((int)adj_get_value(w->adj) == 3) { - xjmkb->xjack->play = 0.0; + xjmkb->xjack->play.store(0, std::memory_order_release); //adj_set_value(xjmkb->play->adj, 0.0); //set_play_label(xjmkb->play,NULL); //adj_set_value(xjmkb->record->adj, 0.0); @@ -3538,6 +3540,27 @@ void XKeyBoard::init_synth_ui(Widget_t *parent) { /******************* Looper Controls *****************/ +void XKeyBoard::draw_looper_ui(void *w_, void* user_data) noexcept{ + Widget_t *w = (Widget_t*)w_; + set_pattern(w,&w->app->color_scheme->selected,&w->app->color_scheme->normal,BACKGROUND_); + cairo_paint (w->crb); + widget_set_scale(w); + for(int i = 0;i<16;i++) { + double ci = ((i+1)/100.0)*12.0; + if (i<4) + cairo_set_source_rgba(w->crb, ci, 0.2, 0.4, 1.00); + else if (i<8) + cairo_set_source_rgba(w->crb, 0.6, 0.2+ci-0.48, 0.4, 1.00); + else if (i<12) + cairo_set_source_rgba(w->crb, 0.6-(ci-0.96), 0.68-(ci-1.08), 0.4, 1.00); + else + cairo_set_source_rgba(w->crb, 0.12+(ci-1.56), 0.32, 0.4-(ci-1.44), 1.00); + cairo_rectangle(w->crb, 10+(i*25), 0, 25, 25); + cairo_fill_preserve(w->crb); + cairo_stroke(w->crb); + } +} + void XKeyBoard::show_looper_ui(int present) { if(present) { widget_show_all(looper_control); @@ -3695,7 +3718,7 @@ void XKeyBoard::init_looper_ui(Widget_t *parent) { 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->func.expose_callback = draw_looper_ui; looper_control->scale.gravity = CENTER; looper_control->parent = parent; looper_control->parent_struct = this; diff --git a/src/MidiKeyBoard.h b/src/MidiKeyBoard.h index 0292941..5082d30 100644 --- a/src/MidiKeyBoard.h +++ b/src/MidiKeyBoard.h @@ -338,6 +338,7 @@ class XKeyBoard { static void remamba_set_edos(XKeyBoard *xjmkb) noexcept; static void hide_callback(void *w_, void* user_data) noexcept; + static void draw_looper_ui(void *w_, void* user_data) noexcept; void show_looper_ui(int present); void init_looper_ui(Widget_t *parent); diff --git a/src/XJack.cpp b/src/XJack.cpp index 55aa854..d44fb3d 100644 --- a/src/XJack.cpp +++ b/src/XJack.cpp @@ -107,12 +107,14 @@ XJack::XJack(mamba::MidiMessenger *mmessage_, bpm_changed.store(false, std::memory_order_release); bpm_set.store(0, std::memory_order_release); record_off.store(false, std::memory_order_release); + record_finished.store(0, std::memory_order_release); + record.store(0, std::memory_order_release); + play.store(0, std::memory_order_release); start = 0; NotOn = 0; absoluteStart = 0; - record = 0; - record_finished = 0; - play = 0; + absoluteRecordTime = 0.0; + absoluteRecordStart = 0.0; pos = 0; bank = 0; program = 0; @@ -249,7 +251,7 @@ inline void XJack::play_midi(void *buf, unsigned int n) { for ( int i = 0; i < 16; i++) { stPlay = jack_last_frame_time(client)+n; if (!rec.play[i].size()) continue; - if (record && i == mmessage->channel) continue; + if (record.load(std::memory_order_acquire) && i == mmessage->channel) continue; stopPlay[i] = jack_last_frame_time(client)+n; if (posPlay[i] >= rec.play[i].size()) { @@ -316,18 +318,28 @@ inline void XJack::process_midi_out(void *buf, jack_nframes_t nframes) { if (midi_send) { mmessage->fill(midi_send, i); send_to_alsa(midi_send, mmessage->size(i)); - if (record) record_midi(midi_send, n, mmessage->size(i)); + if (record.load(std::memory_order_acquire)) record_midi(midi_send, n, mmessage->size(i)); } i = mmessage->next(i); - } else if (play) { + } else if (play.load(std::memory_order_acquire)) { play_midi(buf, n); } } + if (record.load(std::memory_order_acquire)) { + stop = jack_last_frame_time(client); + deltaTime = (double)(((stop) - start)/(double)SampleRate); // seconds + absoluteTime = (double)(((stop) - absoluteStart)/(double)SampleRate); // seconds + absoluteRecordTime = (double)(((stop) - absoluteRecordStart)/(double)SampleRate); // seconds + if (absoluteRecordTime >= max_loop_time && !NotOn && (get_max_time_loop() > -1)) { + record_off.store(true, std::memory_order_release); + } + } + } // jack process callback for the midi input inline void XJack::process_midi_in(void* buf, void* out_buf) { - if (record && fresh_take) { + if (record.load(std::memory_order_acquire) && fresh_take) { start = jack_last_frame_time(client); absoluteStart = jack_last_frame_time(client); absoluteRecordStart = jack_last_frame_time(client); @@ -345,8 +357,8 @@ inline void XJack::process_midi_in(void* buf, void* out_buf) { start = startPlay[mmessage->channel]; absoluteStart = startPlay[mmessage->channel]; } - } else if (record_finished && !freewheel && (get_max_time_loop() > -1)) { - record_finished = 0; + } else if (record_finished.load(std::memory_order_acquire) && !freewheel && (get_max_time_loop() > -1)) { + record_finished.store(0, std::memory_order_release); if (rec.is_sorted.load(std::memory_order_acquire)) { posPlay[mmessage->channel] = find_pos_for_playtime(); rec.is_sorted.store(false, std::memory_order_release); @@ -372,7 +384,7 @@ inline void XJack::process_midi_in(void* buf, void* out_buf) { midi_send[1] = in_event.buffer[1]; // implement mapping if (in_event.size>2) midi_send[2] = in_event.buffer[2]; - if (record) + if (record.load(std::memory_order_acquire)) record_midi(midi_send, i, in_event.size); send_to_alsa(midi_send, in_event.size); } diff --git a/src/XJack.h b/src/XJack.h index b6121b7..2127992 100644 --- a/src/XJack.h +++ b/src/XJack.h @@ -120,6 +120,9 @@ class XJack : public sigc::trackable { std::atomic bpm_set; std::atomic record_off; std::atomic channel_matrix[16]; + std::atomic record_finished; + std::atomic record; + std::atomic play; jack_client_t *client; jack_port_t *in_port; jack_port_t *out_port; @@ -135,9 +138,6 @@ class XJack : public sigc::trackable { std::vector store2; std::vector *st; - int record; - int record_finished; - int play; int bank; int program; int freewheel;