diff --git a/src/event.hxx b/src/event.hxx index 99cdb9c..e272191 100644 --- a/src/event.hxx +++ b/src/event.hxx @@ -22,6 +22,7 @@ namespace Event RECORD, LOOPER_STATE, + LOOPER_PROGRESS, LOOPER_LOOP_LENGTH, METRONOME_ACTIVE, @@ -66,6 +67,18 @@ class EventLooperState : public EventBase EventLooperState(int t, Looper::State s) : track(t), state(s){} }; +class EventLooperProgress : public EventBase +{ + public: + int type() { return int(LOOPER_PROGRESS); } + uint32_t size() { return sizeof(EventLooperProgress); } + + int track; + float progress; + EventLooperProgress(){} + EventLooperProgress(int t, float p) : track(t), progress(p) {} +}; + class EventLooperLoopLength : public EventBase { public: diff --git a/src/eventhandler.hxx b/src/eventhandler.hxx index d8e7bd4..792ce04 100644 --- a/src/eventhandler.hxx +++ b/src/eventhandler.hxx @@ -6,18 +6,18 @@ #include extern char* processDspMem; -extern char* processOscMem; +extern char* processGuiMem; extern jack_ringbuffer_t* rbToDsp; -//extern jack_ringbuffer_t* ringbufferDspToGui; +extern jack_ringbuffer_t* rbToGui; // to process events in the ringbuffer extern void handleDspEvents(); -//extern void handleGuiEvents(); +extern void handleGuiEvents(); // to write events to the ringbuffer extern void writeToDspRingbuffer(EventBase* e); -//extern void writeToGuiRingbuffer(EventBase* e); +extern void writeToGuiRingbuffer(EventBase* e); #endif // LUPPP_EVENT_HANDLER_H diff --git a/src/eventhandlergui.cxx b/src/eventhandlergui.cxx new file mode 100644 index 0000000..cd5839d --- /dev/null +++ b/src/eventhandlergui.cxx @@ -0,0 +1,112 @@ + +#ifndef LUPPP_EVENT_HANDLER_DSP_H +#define LUPPP_EVENT_HANDLER_DSP_H + + +// Library +#include +#include +#include + +// Internal +#include "gui.hxx" +#include "event.hxx" +#include "eventhandler.hxx" + +extern Gui* gui; + +using namespace std; + +void handleGuiEvents() +{ + uint availableRead = jack_ringbuffer_read_space( rbToGui ); + + while ( availableRead >= sizeof(EventBase) ) + { + jack_ringbuffer_peek( rbToGui, (char*)processGuiMem, sizeof(EventBase) ); + + EventBase* e = (EventBase*)processGuiMem; + + // recheck the size against the actual event size + if ( availableRead >= e->size() ) + { + //cout << "reading event type " << e->type() << endl; + + switch ( e->type() ) + { + case Event::MASTER_VOL: { + if ( availableRead >= sizeof(EventMasterVol) ) { + EventMasterVol ev(0); + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterVol) ); + //jack->masterVolume = ev.vol; + } break; } + case Event::LOAD_SAMPLE: { + if ( availableRead >= sizeof(EventLoadSample) ) { + EventLoadSample ev(0); + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLoadSample) ); + //jack->addAudioBuffer( ev.audioBufferPtr ); + } break; } + case Event::PLAY_SAMPLE: { + if ( availableRead >= sizeof(EventPlaySample) ) { + EventPlaySample ev(0,0); + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventPlaySample) ); + //jack->setPlayBuffer( ev.track, ev.bufferID ); + } break; } + case Event::METRONOME_ACTIVE: { + if ( availableRead >= sizeof(EventMetronomeActive) ) { + EventMetronomeActive ev(false); + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMetronomeActive) ); + //jack->getMetronome()->setActive(ev.active); + } break; } + case Event::LOOPER_STATE: { + if ( availableRead >= sizeof(EventLooperState) ) { + EventLooperState ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperState) ); + //jack->setLooperState( ev.track, ev.state ); + } break; } + case Event::LOOPER_LOOP_LENGTH: { + if ( availableRead >= sizeof(EventLooperLoopLength) ) { + EventLooperLoopLength ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperLoopLength) ); + //jack->setLooperLoopLength( ev.track, ev.scale ); + } break; } + case Event::LOOPER_PROGRESS: { + if ( availableRead >= sizeof(EventLooperProgress) ) { + EventLooperProgress ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperProgress) ); + gui->getTrack(ev.track)->progress.value(ev.progress); + //jack->setLooperLoopLength( ev.track, ev.scale ); + } break; } + default: + { + cout << "Unkown message!! Will clog ringbuffer" << endl; + // just do nothing + break; + } + } + } + else + { + // next call will get the half-written event + return; + } + + // update available read, and loop over events + availableRead = jack_ringbuffer_read_space( rbToGui ); + } +} + +void writeToGuiRingbuffer(EventBase* e) +{ + if ( jack_ringbuffer_write_space(rbToGui) >= e->size() ) + { + jack_ringbuffer_write( rbToGui, (const char*)e, e->size() ); + } + else + { + cout << "->GUI ringbuffer full!" << endl; + } +} + +#endif // LUPPP_EVENT_HANDLER_DSP_H + diff --git a/src/gtrack.hxx b/src/gtrack.hxx index 4aa8242..35ec618 100644 --- a/src/gtrack.hxx +++ b/src/gtrack.hxx @@ -7,6 +7,7 @@ #include #include #include +#include #include "avtk/avtk_dial.h" #include "avtk/avtk_button.h" @@ -70,7 +71,9 @@ class GTrack : public Fl_Group dial1(x+15, y +155, 24, 24, "A"), dial2(x+45, y +155, 24, 24, "B"), - dial3(x+75, y +155, 24, 24, "C") + dial3(x+75, y +155, 24, 24, "C"), + + progress(x, y, 100, 20, "prog") { ID = privateID++; @@ -81,6 +84,9 @@ class GTrack : public Fl_Group button5.callback( gtrack_button_callback, &ID ); button6.callback( gtrack_button_callback, &ID ); + progress.maximum(1.0f); + progress.minimum(0.0f); + end(); // close the group } @@ -89,8 +95,6 @@ class GTrack : public Fl_Group free(title); } - - private: int ID; char* title; @@ -104,10 +108,11 @@ class GTrack : public Fl_Group Avtk::Button button5; Avtk::Button button6; - Avtk::Dial dial1; - Avtk::Dial dial2; - Avtk::Dial dial3; + Avtk::Dial dial1; + Avtk::Dial dial2; + Avtk::Dial dial3; + Fl_Progress progress; static int privateID; }; diff --git a/src/gui.cxx b/src/gui.cxx index a256be0..3b613ac 100644 --- a/src/gui.cxx +++ b/src/gui.cxx @@ -10,6 +10,14 @@ int GMasterTrack::privateID = 0; using namespace std; + +static void gui_static_read_rb(void* inst) +{ + //cout << "read gui" << endl; + handleGuiEvents(); + Fl::repeat_timeout( 1 / 30.f, &gui_static_read_rb, inst); +} + Gui::Gui() : window(1200,280) { @@ -37,8 +45,16 @@ Gui::Gui() : window.end(); } +GTrack* Gui::getTrack(int id) +{ + return tracks.at(id); +} + int Gui::show() { window.show(); + + gui_static_read_rb( this); + return Fl::run(); } diff --git a/src/gui.hxx b/src/gui.hxx index 4a06156..01651e1 100644 --- a/src/gui.hxx +++ b/src/gui.hxx @@ -21,6 +21,7 @@ class Gui public: Gui(); int show(); + GTrack* getTrack(int id); private: Fl_Double_Window window; diff --git a/src/looper.cxx b/src/looper.cxx index 1d1e72f..f9cceff 100644 --- a/src/looper.cxx +++ b/src/looper.cxx @@ -3,6 +3,8 @@ #include "looper.hxx" #include "jack.hxx" +#include "eventhandler.hxx" + extern Jack* jack; void Looper::setState(State s) @@ -15,3 +17,35 @@ void Looper::setState(State s) } } +void Looper::process(int nframes, Buffers* buffers) +{ + float* in = buffers->audio[Buffers::MASTER_INPUT]; + float* out = buffers->audio[Buffers::MASTER_OUTPUT]; + + if ( state == STATE_PLAYING ) + { + for(int i = 0; i < nframes; i++) + { + if ( playPoint < endPoint ) + { + out[i] += sample[playPoint++]; + } + } + + // update UI + EventLooperProgress e(track, float(playPoint) / endPoint ); + writeToGuiRingbuffer( &e ); + } + + else if ( state == STATE_RECORDING ) + { + cout << "recording " << endl; + for(int i = 0; i < nframes; i++) + { + if ( lastWrittenSampleIndex < 44100 * 60 ) + { + sample[lastWrittenSampleIndex++] = in[i]; + } + } + } +} diff --git a/src/looper.hxx b/src/looper.hxx index 714229b..1192414 100644 --- a/src/looper.hxx +++ b/src/looper.hxx @@ -5,7 +5,6 @@ #include #include "buffers.hxx" - #include "observer/observer.hxx" using namespace std; @@ -92,35 +91,7 @@ class Looper : public Observer // for notifications void setState(State s); - void process(int nframes, Buffers* buffers) - { - float* in = buffers->audio[Buffers::MASTER_INPUT]; - float* out = buffers->audio[Buffers::MASTER_OUTPUT]; - - if ( state == STATE_PLAYING ) - { - for(int i = 0; i < nframes; i++) - { - if ( playPoint < endPoint ) - { - out[i] += sample[playPoint++]; - } - - } - } - - else if ( state == STATE_RECORDING ) - { - cout << "recording " << endl; - for(int i = 0; i < nframes; i++) - { - if ( lastWrittenSampleIndex < 44100 * 60 ) - { - sample[lastWrittenSampleIndex++] = in[i]; - } - } - } - } + void process(int nframes, Buffers* buffers); private: int track; diff --git a/src/main.cxx b/src/main.cxx index 9307c13..635452f 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -14,11 +14,13 @@ char* processDspMem = 0; -char* processOscMem = 0; +char* processGuiMem = 0; jack_ringbuffer_t* rbToDsp = 0; jack_ringbuffer_t* rbToGui = 0; +// global static pointers, for access from EventHandlerGui and EventHandlerDsp +Gui * gui = 0; Jack* jack = 0; int main() @@ -28,16 +30,16 @@ int main() // allocate data to read from processDspMem = (char*)malloc( sizeof(EventBase) ); - processOscMem = (char*)malloc( sizeof(EventBase) ); + processGuiMem = (char*)malloc( sizeof(EventBase) ); - rbToDsp = jack_ringbuffer_create( 2000 * sizeof(EventBase)); - rbToGui = jack_ringbuffer_create( 2000 * sizeof(EventBase)); + rbToDsp = jack_ringbuffer_create( 5000 * sizeof(EventBase)); + rbToGui = jack_ringbuffer_create( 5000 * sizeof(EventBase)); jack = new Jack(); jack->activate(); - Gui gui; - gui.show(); + gui = new Gui(); + gui->show(); } diff --git a/wscript b/wscript index 8cb8fe5..68f8837 100644 --- a/wscript +++ b/wscript @@ -23,6 +23,7 @@ def build(bld): 'src/main.cxx', 'src/jack.cxx', 'src/looper.cxx', + 'src/eventhandlergui.cxx', 'src/eventhandlerdsp.cxx'] bld.program(source = sources, target='luppp5', use='JACK NTK')