diff --git a/src/avtk/avtk_clip_selector.h b/src/avtk/avtk_clip_selector.h index 0fed001..f66046f 100644 --- a/src/avtk/avtk_clip_selector.h +++ b/src/avtk/avtk_clip_selector.h @@ -27,11 +27,12 @@ #include +#include "../gridlogic.hxx" #include "../gclipselectoraction.hxx" #include "../worker.hxx" #include "../looper.hxx" -#include "../audiobuffer.hxx" +#include "../audiobuffer.hxx"./ #include "../eventhandler.hxx" @@ -125,44 +126,51 @@ class ClipSelector : public Fl_Button /** converts the Looper::State into the UI represnted ClipSelector state. * It puts some of the data into clips[], and stores unique state into the class. **/ - void setState( int clipNum, int ) + void setState( int clipNum, GridLogic::State s ) { - /* + switch(s) { - case Looper::STATE_PLAYING: + case GridLogic::STATE_EMPTY: + break; + case GridLogic::STATE_LOADED: + clips[clipNum].load(); + break; + case GridLogic::STATE_PLAYING: printf("clipSelector setState() clip %i = CLIP_PLAYING\n", clipNum); for(int i = 0; i < numClips; i++ ) clips[clipNum].stop(); clips[clipNum].play(); break; - case Looper::STATE_PLAY_QUEUED: + case GridLogic::STATE_PLAY_QUEUED: for(int i = 0; i < numClips; i++ ) clips[clipNum].unqueue(); clips[clipNum].queue(); printf("clipSelector setState() clip %i = CLIP_QUEUED\n", clipNum); break; - case Looper::STATE_RECORDING: + case GridLogic::STATE_RECORDING: for(int i = 0; i < numClips; i++ ) clips[clipNum].stopRecord(); clips[clipNum].record(); printf("clipSelector setState() clip %i = CLIP_RECORDING\n", clipNum); break; - case Looper::STATE_RECORD_QUEUED: + case GridLogic::STATE_RECORD_QUEUED: for(int i = 0; i < numClips; i++ ) clips[clipNum].unqueue(); clips[clipNum].queue(); printf("clipSelector setState() clip %i = CLIP_QUEUED\n", clipNum); break; - case Looper::STATE_STOPPED: + /* + case GridLogic::STATE_STOPPED: clips[clipNum].stop(); printf("clipSelector setState() clip %i = STATE_STOPPED\n", clipNum); break; - case Looper::STATE_STOP_QUEUED: + */ + case GridLogic::STATE_STOP_QUEUED: printf("clipSelector setState() clip %i = CLIP_QUEUED\n", clipNum); break; } - */ + redraw(); } diff --git a/src/controller/apc.cxx b/src/controller/apc.cxx index 5285053..a23c7c5 100644 --- a/src/controller/apc.cxx +++ b/src/controller/apc.cxx @@ -25,6 +25,15 @@ void AkaiAPC::recordArm(int t, bool enabled) jack->writeApcOutput( &data[0] ); } +void AkaiAPC::progress(int t, int s, float f) +{ + unsigned char data[3]; + data[0] = 176; + data[1] = 48; // record enable LED + data[2] = 127 * f; + jack->writeApcOutput( &data[0] ); +} + void AkaiAPC::setSceneState(int t, int clip, GridLogic::State s) { unsigned char data[3]; diff --git a/src/controller/apc.hxx b/src/controller/apc.hxx index 5a17744..629acc4 100644 --- a/src/controller/apc.hxx +++ b/src/controller/apc.hxx @@ -16,6 +16,7 @@ class AkaiAPC : public Controller, public MidiObserver void mute(int t, bool b); void volume(int t, float f); + void progress(int t, int s, float f); void recordArm(int t, bool b); void setSceneState(int track, int clip, GridLogic::State s); diff --git a/src/controller/controller.hxx b/src/controller/controller.hxx index c5c270c..d7aed63 100644 --- a/src/controller/controller.hxx +++ b/src/controller/controller.hxx @@ -10,27 +10,16 @@ class Controller { public: - enum ClipMode { - CLIP_MODE_EMPTY, - CLIP_MODE_PLAYING, - CLIP_MODE_PLAY_QUEUED, - CLIP_MODE_LOADED, - CLIP_MODE_STOP_QUEUED, - CLIP_MODE_RECORDING, - CLIP_MODE_RECORD_QUEUED, - }; - Controller(){}; virtual ~Controller(){}; /// name string to show in UI virtual std::string getName() = 0; - //virtual void setTrack(TrackState& t); - - /// functionality + /// track functionality virtual void mute(int t, bool b){}; virtual void volume(int t, float f){}; + virtual void progress(int t, int s, float f){}; virtual void recordArm(int t, bool r){}; virtual void setSceneState(int track, int scene, GridLogic::State s){}; }; diff --git a/src/controller/gui.cxx b/src/controller/gui.cxx new file mode 100644 index 0000000..54fee0e --- /dev/null +++ b/src/controller/gui.cxx @@ -0,0 +1,43 @@ + + +#include "gui.hxx" + +#include + +#include "../jack.hxx" +#include "../gridlogic.hxx" + +extern Jack* jack; + +LupppGUI::LupppGUI() : + Controller() +{ + +} + +void LupppGUI::recordArm(int t, bool enabled) +{ + +} + +void LupppGUI::setSceneState(int t, int clip, GridLogic::State s) +{ + +} + +void LupppGUI::mute(int t, bool b) +{ + +} + + +void LupppGUI::volume(int t, float f) +{ + +} + +void LupppGUI::progress(int t, int s, float f) +{ + EventLooperProgress e( t, f ); + writeToGuiRingbuffer( &e ); +} diff --git a/src/controller/gui.hxx b/src/controller/gui.hxx new file mode 100644 index 0000000..6600b91 --- /dev/null +++ b/src/controller/gui.hxx @@ -0,0 +1,26 @@ + + +#ifndef LUPPP_CONTROLLER_GUI_H +#define LUPPP_CONTROLLER_GUI_H + +#include "controller.hxx" + +#include "../observer/midi.hxx" + +class LupppGUI : public Controller +{ + public: + LupppGUI(); + + std::string getName(){return "Luppp GUI";} + + void mute(int t, bool b); + void volume(int t, float f); + void progress(int t, int s, float p); + void recordArm(int t, bool b); + void setSceneState(int track, int clip, GridLogic::State s); + +}; + +#endif // LUPPP_CONTROLLER_GUI_H + diff --git a/src/controllerupdater.hxx b/src/controllerupdater.hxx index df0dcd7..2cfca66 100644 --- a/src/controllerupdater.hxx +++ b/src/controllerupdater.hxx @@ -33,6 +33,12 @@ class ControllerUpdater c.at(i)->mute(t,b); } + void setTrackSceneProgress(int t, int s, float p) + { + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->progress(t,s,p); + } + void setSceneState(int t, int clip, GridLogic::State s) { for(unsigned int i = 0; i < c.size(); i++) diff --git a/src/gridlogic.cxx b/src/gridlogic.cxx index 362e36d..5ac3f48 100644 --- a/src/gridlogic.cxx +++ b/src/gridlogic.cxx @@ -14,7 +14,7 @@ GridLogic::GridLogic() void GridLogic::pressed( int track, int scene ) { state[track*NTRACKS + scene] = STATE_PLAYING; - jack->getControllerUpdater()->setSceneState(track, scene, STATE_PLAYING); + jack->getControllerUpdater()->setSceneState(track, scene, STATE_PLAY_QUEUED); } @@ -28,3 +28,52 @@ void GridLogic::updateState() { } + + +void GridLogic::updateState( int track, int scene ) +{ + jack->getControllerUpdater()->setSceneState(track, scene, state[track*NTRACKS + scene] ); +} + + +void GridLogic::bar() +{ + printf("GridLogic::bar()\n" ); + + for( int i = 0; i < NTRACKS*NSCENES; i++ ) + { + bool change = false; + + if ( state[i] == STATE_PLAY_QUEUED ) + { + state[i] = STATE_PLAYING; + change = true; + } + else if ( state[i] == STATE_STOP_QUEUED ) + { + state[i] = STATE_LOADED; + change = true; + } + else if ( state[i] == STATE_RECORD_QUEUED ) + { + state[i] = STATE_RECORDING; + change = true; + } + + if ( change ) + { + int scene = i % NTRACKS; + int track = i - scene; + updateState( track, scene ); + printf("GridLogic::bar(), updated %i, %i\n", track, scene ); + } + + } +} + + +void GridLogic::beat() +{ + + +} diff --git a/src/gridlogic.hxx b/src/gridlogic.hxx index 20a49c3..1cc9225 100644 --- a/src/gridlogic.hxx +++ b/src/gridlogic.hxx @@ -44,8 +44,16 @@ class GridLogic : public TimeObserver /// button release / click-release event void released( int track, int scene ); - /// resend entire grid state to controller + /// resend entire grid state to controllers void updateState(); + + /// resend track / scene combo to controllers + void updateState( int track, int scene ); + + + /// time functions, not for use by Controller subclasses + void bar(); + void beat(); private: /// contains the current state of each grid square diff --git a/src/jack.cxx b/src/jack.cxx index cd05512..145cdcc 100644 --- a/src/jack.cxx +++ b/src/jack.cxx @@ -7,6 +7,8 @@ #include "eventhandler.hxx" +#include "controller/gui.hxx" + using namespace std; extern int jackSamplerate; @@ -14,7 +16,10 @@ extern int jackSamplerate; Jack::Jack() : clientActive(false), client( 0 ), - controllerUpdater( new ControllerUpdater() ) + controllerUpdater( new ControllerUpdater() ), + timeManager(), + metronome( new Metronome() ), + gridLogic( new GridLogic() ) { // open the client client = jack_client_open ( "Luppp", JackNullOption , 0 , 0 ); @@ -76,7 +81,7 @@ Jack::Jack() : timeManager.registerObserver( loopers.back() ); } - timeManager.registerObserver( &metronome ); + //timeManager.registerObserver( &metronome ); /// setup FX reverb = new Reverb( buffers.samplerate ); @@ -106,6 +111,12 @@ void Jack::activate() // move to "settings" class or so Controller* c = new AkaiAPC(); controllerUpdater->registerController( c ); + Controller* g = new LupppGUI(); + controllerUpdater->registerController( g ); + + // move to time class, get instantiate order right + jack->getTimeManager()->registerObserver( metronome ); + jack->getTimeManager()->registerObserver( gridLogic ); jack_activate( client ); jack_transport_start(client); @@ -184,7 +195,7 @@ int Jack::process (jack_nframes_t nframes) } - metronome.process( nframes, &buffers ); + metronome->process( nframes, &buffers ); // process fx diff --git a/src/jack.hxx b/src/jack.hxx index b8aeae8..dbc5d21 100644 --- a/src/jack.hxx +++ b/src/jack.hxx @@ -43,8 +43,8 @@ class Jack /// get functions for components owned by Jack Looper* getLooper(int t) {return loopers.at(t); } - Metronome* getMetronome(){return &metronome;} - GridLogic* getGridLogic(){return &gridLogic;} + Metronome* getMetronome(){return metronome;} + GridLogic* getGridLogic(){return gridLogic;} TrackOutput* getTrackOutput(int t){return trackOutputs.at(t);} TimeManager* getTimeManager(){return &timeManager;} ControllerUpdater* getControllerUpdater(){return controllerUpdater;} @@ -64,18 +64,15 @@ class Jack void writeApcOutput( unsigned char* data ); private: - Buffers buffers; - Metronome metronome; - GridLogic gridLogic; - TimeManager timeManager; + Buffers buffers; + TimeManager timeManager; + Metronome* metronome; + GridLogic* gridLogic; + ControllerUpdater* controllerUpdater; - ControllerUpdater* controllerUpdater; - - vector loopers; - - vector trackOutputs; - - vector midiObservers; + vector loopers; + vector trackOutputs; + vector midiObservers; int nframes; int samplerate; diff --git a/src/looper.cxx b/src/looper.cxx index 85d9e6d..7d47950 100644 --- a/src/looper.cxx +++ b/src/looper.cxx @@ -215,9 +215,7 @@ void Looper::process(int nframes, Buffers* buffers) // update UI of progress if ( uiUpdateCounter > uiUpdateConstant ) { - EventLooperProgress e(track, clips[clip].getProgress() ); - writeToGuiRingbuffer( &e ); - //printf("writing event\n"); + jack->getControllerUpdater()->setTrackSceneProgress(track, clip, clips[clip].getProgress() ); uiUpdateCounter = 0; } uiUpdateCounter += nframes; diff --git a/src/observer/time.cxx b/src/observer/time.cxx new file mode 100644 index 0000000..b695abe --- /dev/null +++ b/src/observer/time.cxx @@ -0,0 +1,11 @@ + +#include "time.hxx" + +#include "../jack.hxx" +extern Jack* jack; + +TimeObserver::TimeObserver() +{ + //jack->getTimeManager()->registerObserver( this ); +} + diff --git a/src/observer/time.hxx b/src/observer/time.hxx index f74e0ab..18e9458 100644 --- a/src/observer/time.hxx +++ b/src/observer/time.hxx @@ -5,6 +5,9 @@ class TimeObserver { public: + /// registers with TimeManager + TimeObserver(); + virtual void setFpb(int fpb){}; virtual void bar(){}; diff --git a/src/timemanager.hxx b/src/timemanager.hxx index 05bb784..969a222 100644 --- a/src/timemanager.hxx +++ b/src/timemanager.hxx @@ -17,12 +17,15 @@ class TimeManager public: TimeManager(): fpb(22050), - oldBeat(0) + oldBeat(0), + observers() { tapTempoPos = 0; tapTempo[0] = 0; tapTempo[1] = 0; tapTempo[2] = 0; + + cout << "TimeManager() done" << endl; } void setBpm(float bpm) diff --git a/wscript b/wscript index 5c178b5..6cc3638 100644 --- a/wscript +++ b/wscript @@ -27,9 +27,12 @@ def build(bld): 'src/looper.cxx', 'src/gridlogic.cxx', + 'src/observer/time.cxx', 'src/observer/midi.cxx', 'src/controller/apc.cxx', + 'src/controller/gui.cxx', + 'src/eventhandlergui.cxx', 'src/eventhandlerdsp.cxx']