From 01f71ec5e4481f06609b3b4d5f5dfbea676218df Mon Sep 17 00:00:00 2001 From: Harry van Haaren Date: Tue, 27 Dec 2016 12:47:19 +0000 Subject: [PATCH] astyle: global restyle of codebase (fixes #153) This to bring common fomatting to the whole project, including submissions. To format a file to this style: astyle --style=linux -t8 Future patches / pull-requests should be in this format. --- .gitignore | 1 + src/audiobuffer.cxx | 67 +- src/audiobuffer.hxx | 92 +- src/audioprocessor.hxx | 47 +- src/avtk/avtk_background.h | 257 +++--- src/avtk/avtk_box.h | 161 ++-- src/avtk/avtk_button.h | 338 ++++--- src/avtk/avtk_dial.h | 336 ++++--- src/avtk/avtk_image.h | 146 ++- src/avtk/avtk_light_button.h | 290 +++--- src/avtk/avtk_radial_status.h | 339 ++++--- src/avtk/avtk_reverb.h | 396 +++++---- src/avtk/avtk_sidechain_gain.h | 373 ++++---- src/avtk/avtk_unit.h | 323 ++++--- src/avtk/bindings.cxx | 228 +++-- src/avtk/bindings.h | 40 +- src/avtk/clipselector.cxx | 674 +++++++------- src/avtk/clipselector.hxx | 132 +-- src/avtk/volume.cxx | 346 ++++--- src/avtk/volume.hxx | 72 +- src/avtk/waveform.h | 529 ++++++----- src/buffers.hxx | 172 ++-- src/config.hxx | 6 +- src/controller/binding.hxx | 61 +- src/controller/controller.cxx | 10 +- src/controller/controller.hxx | 130 +-- src/controller/genericmidi.cxx | 1192 ++++++++++++------------- src/controller/genericmidi.hxx | 184 ++-- src/controller/guicontroller.cxx | 84 +- src/controller/guicontroller.hxx | 69 +- src/controller/nonseq.cxx | 72 +- src/controller/nonseq.hxx | 28 +- src/controllerupdater.cxx | 157 ++-- src/controllerupdater.hxx | 96 +- src/debug.cxx | 52 +- src/debug.hxx | 14 +- src/denormals.hxx | 18 +- src/diskreader.cxx | 1149 ++++++++++++------------ src/diskreader.hxx | 76 +- src/diskwriter.cxx | 871 +++++++++--------- src/diskwriter.hxx | 115 ++- src/dsp/dsp_dbmeter.hxx | 125 +-- src/dsp/dsp_reverb.hxx | 917 ++++++++++--------- src/dsp/dsp_sidechain_gain.cxx | 149 ++-- src/dsp/dsp_sidechain_gain.hxx | 87 +- src/event.cxx | 114 ++- src/event.hxx | 1435 ++++++++++++++++++------------ src/eventhandler.hxx | 6 +- src/eventhandlerdsp.cxx | 821 +++++++++-------- src/eventhandlergui.cxx | 804 +++++++++-------- src/gaudioeditor.cxx | 269 +++--- src/gaudioeditor.hxx | 59 +- src/gmastertrack.cxx | 488 +++++----- src/gmastertrack.hxx | 138 +-- src/goptions.cxx | 685 +++++++------- src/goptions.hxx | 144 +-- src/gridlogic.cxx | 358 ++++---- src/gridlogic.hxx | 135 +-- src/gtrack.cxx | 294 +++--- src/gtrack.hxx | 123 +-- src/gui.cxx | 1311 +++++++++++++++------------ src/gui.hxx | 191 ++-- src/gunittrack.hxx | 64 +- src/jack.cxx | 1020 ++++++++++----------- src/jack.hxx | 288 +++--- src/jacksendreturn.cxx | 67 +- src/jacksendreturn.hxx | 30 +- src/logic.cxx | 160 ++-- src/logic.hxx | 56 +- src/looper.cxx | 263 +++--- src/looper.hxx | 102 +-- src/looperclip.cxx | 602 ++++++------- src/looperclip.hxx | 191 ++-- src/main.cxx | 163 ++-- src/metronome.cxx | 117 ++- src/metronome.hxx | 54 +- src/observer/midi.cxx | 162 ++-- src/observer/midi.hxx | 58 +- src/observer/time.cxx | 8 +- src/observer/time.hxx | 40 +- src/state/state.cxx | 40 +- src/state/state.hxx | 42 +- src/state/stately.cxx | 50 +- src/state/stately.hxx | 60 +- src/tests/diskreadertest.cxx | 36 +- src/tests/diskwritertest.cxx | 96 +- src/tests/goptionstest.cxx | 22 +- src/tests/gridlogictests.cxx | 242 ++--- src/timemanager.cxx | 394 ++++---- src/timemanager.hxx | 108 +-- src/trackoutput.cxx | 218 +++-- src/trackoutput.hxx | 96 +- src/transport.hxx | 13 +- 93 files changed, 11792 insertions(+), 11466 deletions(-) diff --git a/.gitignore b/.gitignore index ec15721..e840d19 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ src/*.o luppp *.zip +*.orig build/* buildTest/* diff --git a/src/audiobuffer.cxx b/src/audiobuffer.cxx index 06a99da..cb4f8e6 100644 --- a/src/audiobuffer.cxx +++ b/src/audiobuffer.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -22,95 +22,94 @@ AudioBuffer::AudioBuffer() { - ID = privateID++; - init(); + ID = privateID++; + init(); } AudioBuffer::AudioBuffer(unsigned long size) { - // FIXME recorded buffers don't get an ID, using garbage IDs - /// no ID assigned: it *takes* the one from the previous buffer! - init(); - buffer.resize(size); + // FIXME recorded buffers don't get an ID, using garbage IDs + /// no ID assigned: it *takes* the one from the previous buffer! + init(); + buffer.resize(size); } - + void AudioBuffer::init() { - numBeats = 0; - audioFrames = 0; - memset( name, 0, sizeof(char)*20 ); - //sprintf( name, "%i", ID ); + numBeats = 0; + audioFrames = 0; + memset( name, 0, sizeof(char)*20 ); + //sprintf( name, "%i", ID ); } /// this function is used for "resizing" an exisiting buffer, and should /// not be called for any other reason. void AudioBuffer::setID(int id) { - ID = id; + ID = id; } int AudioBuffer::getID() { - return ID; + return ID; } void AudioBuffer::setName(const char* n) { - memcpy( name, n, sizeof(char)* 19 ); - - if ( strlen(n) > 19 ) - { + memcpy( name, n, sizeof(char)* 19 ); + + if ( strlen(n) > 19 ) { #ifdef DEBUG_BUFFER - cout << "AudioBuffer setName too long, truncating." << endl; + cout << "AudioBuffer setName too long, truncating." << endl; #endif - return; - } - + return; + } + } char* AudioBuffer::getName() { - return name; + return name; } int AudioBuffer::getBeats() { - return numBeats; + return numBeats; } void AudioBuffer::setBeats(int b) { #ifdef DEBUG_BUFFER - cout << "AudioBuffer now has " << b << " beats\n" << endl; + cout << "AudioBuffer now has " << b << " beats\n" << endl; #endif - numBeats = b; + numBeats = b; } void AudioBuffer::setAudioFrames(long af) { - audioFrames = af; + audioFrames = af; #ifdef DEBUG_BUFFER - cout << "AudioBuffer " << ID << " has " << audioFrames << " audioFrames\n" << endl; + cout << "AudioBuffer " << ID << " has " << audioFrames << " audioFrames\n" << endl; #endif } long AudioBuffer::getAudioFrames() { - return audioFrames; + return audioFrames; } std::vector& AudioBuffer::getData() { - return buffer; + return buffer; } void AudioBuffer::nonRtSetSample(std::vector& sample) { - buffer.swap(sample); + buffer.swap(sample); } void AudioBuffer::nonRtResize(unsigned long size) { - buffer.resize(size); + buffer.resize(size); } /* diff --git a/src/audiobuffer.hxx b/src/audiobuffer.hxx index 2db923e..ff49fd6 100644 --- a/src/audiobuffer.hxx +++ b/src/audiobuffer.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -30,49 +30,49 @@ using namespace std; /// AudioBuffer stores float samples in a big vector. class AudioBuffer { - public: - AudioBuffer(); - AudioBuffer(unsigned long size); - - void init(); - - /// this function is used for "resizing" an exisiting buffer, and should - /// not be called for any other reason. - void setID(int id); - - int getID(); - void setName(const char* n); - - char* getName(); - int getBeats(); - - void setBeats(int b); - - void setAudioFrames(long af); - - long getAudioFrames(); - - std::vector& getData(); - - void nonRtSetSample(std::vector& sample); - - void nonRtResize(unsigned long size); - - //friend ostream& operator<<(ostream& o, const AudioBuffer& a); - - protected: - static int privateID; - int ID; - - int numBeats; - - /// holds the number of samples that are usable audio, as opposed to - /// buffer.size(), which also has non-used space at the end. - long audioFrames; - - char name[20]; - - std::vector buffer; +public: + AudioBuffer(); + AudioBuffer(unsigned long size); + + void init(); + + /// this function is used for "resizing" an exisiting buffer, and should + /// not be called for any other reason. + void setID(int id); + + int getID(); + void setName(const char* n); + + char* getName(); + int getBeats(); + + void setBeats(int b); + + void setAudioFrames(long af); + + long getAudioFrames(); + + std::vector& getData(); + + void nonRtSetSample(std::vector& sample); + + void nonRtResize(unsigned long size); + + //friend ostream& operator<<(ostream& o, const AudioBuffer& a); + +protected: + static int privateID; + int ID; + + int numBeats; + + /// holds the number of samples that are usable audio, as opposed to + /// buffer.size(), which also has non-used space at the end. + long audioFrames; + + char name[20]; + + std::vector buffer; }; #endif diff --git a/src/audioprocessor.hxx b/src/audioprocessor.hxx index 8bbd71f..520cbbf 100644 --- a/src/audioprocessor.hxx +++ b/src/audioprocessor.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -25,25 +25,28 @@ class AudioProcessor { - public: - AudioProcessor(){} - - /// copies the track output to master buffer, sidechain & post-side buffer - virtual void process(unsigned int nframes, Buffers* buffers){printf("AudioProcessor::process() not derived\n");} - - /// set main mix, 0-1 - virtual void setMaster(float value){} - - /// set sidechain mix, 0-1 - virtual void setSidechain(float value){} - - /// set post sidechain mix, 0-1 - virtual void setPostSidechain(float value){} - - /// set reverb mix, 0-1 - virtual void setReverb(float value){} - - virtual ~AudioProcessor(){}; +public: + AudioProcessor() {} + + /// copies the track output to master buffer, sidechain & post-side buffer + virtual void process(unsigned int nframes, Buffers* buffers) + { + printf("AudioProcessor::process() not derived\n"); + } + + /// set main mix, 0-1 + virtual void setMaster(float value) {} + + /// set sidechain mix, 0-1 + virtual void setSidechain(float value) {} + + /// set post sidechain mix, 0-1 + virtual void setPostSidechain(float value) {} + + /// set reverb mix, 0-1 + virtual void setReverb(float value) {} + + virtual ~AudioProcessor() {}; }; #endif // LUPPP_AUDIO_PROCESSOR_H diff --git a/src/avtk/avtk_background.h b/src/avtk/avtk_background.h index 9997e66..6fc07c0 100644 --- a/src/avtk/avtk_background.h +++ b/src/avtk/avtk_background.h @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -32,134 +32,129 @@ namespace Avtk // FIXME: Refactor to .hxx .cxx class Background : public Fl_Widget { - public: - Background(int _x, int _y, int _w, int _h, const char *_label = 0): - Fl_Widget(_x, _y, _w, _h, _label) - { - x = _x; - y = _y; - w = _w; - h = _h; - - label = strdup(_label); - - highlight = false; - } - bool highlight; - int x, y, w, h; - const char* label; - - void setLabel(const char* l) - { - if( label ) - free( (char*) label); - - label = strdup( l ); - redraw(); - } - const char* getLabel() - { - return label; - } - - void draw() - { - if (damage() & FL_DAMAGE_ALL) - { - cairo_t *cr = Fl::cairo_cc(); - - cairo_save( cr ); - - cairo_set_line_width(cr, 1.5); - - - // fill background - cairo_rectangle( cr, x, y, w, h); - cairo_set_source_rgba( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f , 1 ); - cairo_fill( cr ); - - // draw header - // backing - cairo_rectangle(cr, x, y, w, 20); - cairo_set_source_rgb( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f ); - cairo_fill( cr ); - - // text - cairo_move_to( cr, x + 10, y + 14 ); - cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); - cairo_set_font_size( cr, 10 ); - cairo_show_text( cr, label ); - - // lower stripe - cairo_move_to( cr, x , y + 20 ); - cairo_line_to( cr, x + w, y + 20 ); - cairo_stroke( cr ); - - - // stroke rim - cairo_rectangle(cr, x, y, w, h); - cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 1 ); - cairo_stroke( cr ); - - - cairo_restore( cr ); - } - } - - void resize(int X, int Y, int W, int H) - { - Fl_Widget::resize(X,Y,W,H); - x = X; - y = Y; - w = W; - h = H; - redraw(); - } - - int handle(int event) - { - switch(event) - { - case FL_PUSH: - if ( Fl::event_state(FL_BUTTON3) && Fl::event_y() < y + 20 ) - { - const char* name = fl_input( "Track name: ", "" ); - if ( name ) - { - free( (char*) label ); - label = strdup( name ); - redraw(); - } - return 1; - } - - redraw(); - return 1; - case FL_DRAG: { - int t = Fl::event_inside(this); - if (t != highlight) { - redraw(); - } - } - return 1; - case FL_RELEASE: - if (highlight) { - highlight = 0; - redraw(); - do_callback(); - } - return 1; - case FL_SHORTCUT: - if ( test_shortcut() ) - { - do_callback(); - return 1; - } - return 0; - default: - return Fl_Widget::handle(event); - } - } +public: + Background(int _x, int _y, int _w, int _h, const char *_label = 0): + Fl_Widget(_x, _y, _w, _h, _label) + { + x = _x; + y = _y; + w = _w; + h = _h; + + label = strdup(_label); + + highlight = false; + } + bool highlight; + int x, y, w, h; + const char* label; + + void setLabel(const char* l) + { + if( label ) + free( (char*) label); + + label = strdup( l ); + redraw(); + } + const char* getLabel() + { + return label; + } + + void draw() + { + if (damage() & FL_DAMAGE_ALL) { + cairo_t *cr = Fl::cairo_cc(); + + cairo_save( cr ); + + cairo_set_line_width(cr, 1.5); + + + // fill background + cairo_rectangle( cr, x, y, w, h); + cairo_set_source_rgba( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f , 1 ); + cairo_fill( cr ); + + // draw header + // backing + cairo_rectangle(cr, x, y, w, 20); + cairo_set_source_rgb( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f ); + cairo_fill( cr ); + + // text + cairo_move_to( cr, x + 10, y + 14 ); + cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); + cairo_set_font_size( cr, 10 ); + cairo_show_text( cr, label ); + + // lower stripe + cairo_move_to( cr, x , y + 20 ); + cairo_line_to( cr, x + w, y + 20 ); + cairo_stroke( cr ); + + + // stroke rim + cairo_rectangle(cr, x, y, w, h); + cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 1 ); + cairo_stroke( cr ); + + + cairo_restore( cr ); + } + } + + void resize(int X, int Y, int W, int H) + { + Fl_Widget::resize(X,Y,W,H); + x = X; + y = Y; + w = W; + h = H; + redraw(); + } + + int handle(int event) + { + switch(event) { + case FL_PUSH: + if ( Fl::event_state(FL_BUTTON3) && Fl::event_y() < y + 20 ) { + const char* name = fl_input( "Track name: ", "" ); + if ( name ) { + free( (char*) label ); + label = strdup( name ); + redraw(); + } + return 1; + } + + redraw(); + return 1; + case FL_DRAG: { + int t = Fl::event_inside(this); + if (t != highlight) { + redraw(); + } + } + return 1; + case FL_RELEASE: + if (highlight) { + highlight = 0; + redraw(); + do_callback(); + } + return 1; + case FL_SHORTCUT: + if ( test_shortcut() ) { + do_callback(); + return 1; + } + return 0; + default: + return Fl_Widget::handle(event); + } + } }; } // Avtk diff --git a/src/avtk/avtk_box.h b/src/avtk/avtk_box.h index 4efe59f..f36525b 100644 --- a/src/avtk/avtk_box.h +++ b/src/avtk/avtk_box.h @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -28,84 +28,83 @@ namespace Avtk // FIXME: Refactor to .hxx .cxx class Box : public Fl_Widget { - public: - Box(int _x, int _y, int _w, int _h, const char *_label = 0): - Fl_Widget(_x, _y, _w, _h, _label) - { - x = _x; - y = _y; - w = _w; - h = _h; - - r = g = b = 0; - - label = strdup(_label); - - highlight = false; - } - bool highlight; - int x, y, w, h; - const char* label; - - int r,g,b; - - void setLabel(const char* l) - { - if( label ) - free( (char*) label); - - label = strdup( l ); - redraw(); - } - const char* getLabel() - { - return label; - } - - void setColor( int red, int green, int blue ) - { - r = red; - g = green; - b = blue; - - redraw(); - } - - void draw() - { - if (damage() & FL_DAMAGE_ALL) - { - cairo_t *cr = Fl::cairo_cc(); - - cairo_save( cr ); - - cairo_set_line_width(cr, 1.5); - - // fill background - cairo_rectangle( cr, x, y, w, h); - cairo_set_source_rgba( cr, r, g, b, 1 ); - cairo_fill( cr ); - - /* - // stroke rim - cairo_rectangle(cr, x, y, w, h); - cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 1 ); - cairo_stroke( cr ); - */ - - cairo_restore( cr ); - } - } - - void resize(int X, int Y, int W, int H) - { - Fl_Widget::resize(X,Y,W,H); - x = X; - y = Y; - w = W; - h = H; - redraw(); - } +public: + Box(int _x, int _y, int _w, int _h, const char *_label = 0): + Fl_Widget(_x, _y, _w, _h, _label) + { + x = _x; + y = _y; + w = _w; + h = _h; + + r = g = b = 0; + + label = strdup(_label); + + highlight = false; + } + bool highlight; + int x, y, w, h; + const char* label; + + int r,g,b; + + void setLabel(const char* l) + { + if( label ) + free( (char*) label); + + label = strdup( l ); + redraw(); + } + const char* getLabel() + { + return label; + } + + void setColor( int red, int green, int blue ) + { + r = red; + g = green; + b = blue; + + redraw(); + } + + void draw() + { + if (damage() & FL_DAMAGE_ALL) { + cairo_t *cr = Fl::cairo_cc(); + + cairo_save( cr ); + + cairo_set_line_width(cr, 1.5); + + // fill background + cairo_rectangle( cr, x, y, w, h); + cairo_set_source_rgba( cr, r, g, b, 1 ); + cairo_fill( cr ); + + /* + // stroke rim + cairo_rectangle(cr, x, y, w, h); + cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 1 ); + cairo_stroke( cr ); + */ + + cairo_restore( cr ); + } + } + + void resize(int X, int Y, int W, int H) + { + Fl_Widget::resize(X,Y,W,H); + x = X; + y = Y; + w = W; + h = H; + redraw(); + } }; } // Avtk diff --git a/src/avtk/avtk_button.h b/src/avtk/avtk_button.h index a77030a..3fe7996 100644 --- a/src/avtk/avtk_button.h +++ b/src/avtk/avtk_button.h @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -27,174 +27,170 @@ namespace Avtk class Button : public Fl_Button { - public: - Button(int _x, int _y, int _w, int _h, const char *_label): - Fl_Button(_x, _y, _w, _h, _label) - { - x = _x; - y = _y; - w = _w; - h = _h; - - labelMe = _label; - setLabel( labelMe ); - - _r = 1.0; - _g = 0.48; - _b = 0.0; - - _bgr = 0.11; - _bgg = 0.11; - _bgb = 0.11; - - highlight = false; - mouseOver = false; - - greyedOut = false; - } - - void setGreyOut( bool g ) - { - greyedOut = g; - } - - bool greyedOut; - - bool mouseOver; - bool highlight; - int x, y, w, h; - const char* labelMe; - - void setLabel( const char* l) - { - labelMe = l; - label( labelMe ); - redraw(); - } - - float _r, _g, _b; // foreground colour - float _bgr, _bgg, _bgb; // background colour - float _outr, _outg, _outb; // outline colour - - void setColor(float r, float g, float b) - { - _r = r; - _g = g; - _b = b; - } - - void setBgColor(float r, float g, float b) - { - _bgr = r; - _bgg = g; - _bgb = b; - } - - void setHighlight(bool b) - { - highlight = b; redraw(); - } - - void draw() - { - if (damage() & FL_DAMAGE_ALL) - { - cairo_t *cr = Fl::cairo_cc(); - - cairo_save( cr ); - - cairo_rectangle( cr, x+1, y+1, w-2, h-2 ); - if ( !greyedOut ) - cairo_set_source_rgb( cr, _bgr, _bgg, _bgb ); - else - { - float grey = (_bgr + _bgg + _bgb) / 3; - cairo_set_source_rgb( cr, grey, grey, grey ); - } - cairo_fill_preserve(cr); - - cairo_set_line_width(cr, 1.3); - cairo_rectangle( cr, x+1, y+1, w-2, h-2 ); - - if ( highlight && !greyedOut ) - { - cairo_set_source_rgba(cr, _r, _g, _b, 0.4); - cairo_fill_preserve(cr); - } - - float alpha = 0.6; - if (mouseOver) - alpha = 1; - - if ( !greyedOut ) - cairo_set_source_rgba(cr, _r, _g, _b, alpha); - else - { - float grey = (_r + _g + _b) / 3; - cairo_set_source_rgb( cr, grey, grey, grey ); - } - - if ( highlight && !greyedOut ) - cairo_set_line_width(cr, 2.2); - cairo_stroke(cr); - - cairo_restore( cr ); - - draw_label(); - } - } - - void resize(int X, int Y, int W, int H) - { - Fl_Widget::resize(X,Y,W,H); - x = X; - y = Y; - w = W; - h = H; - redraw(); - } - - int handle(int event) - { - switch(event) { - case FL_PUSH: - highlight = 1; - redraw(); - return 1; - case FL_DRAG: { - int t = Fl::event_inside(this); - if (t != highlight) { - highlight = t; - redraw(); - } - } - return 1; - case FL_ENTER: - mouseOver = true; - redraw(); - return 1; - case FL_LEAVE: - mouseOver = false; - redraw(); - return 1; - case FL_RELEASE: - if (highlight) { - highlight = 0; - redraw(); - do_callback(); - } - return 1; - case FL_SHORTCUT: - if ( test_shortcut() ) - { - do_callback(); - return 1; - } - return 0; - default: - return Fl_Widget::handle(event); - } - } +public: + Button(int _x, int _y, int _w, int _h, const char *_label): + Fl_Button(_x, _y, _w, _h, _label) + { + x = _x; + y = _y; + w = _w; + h = _h; + + labelMe = _label; + setLabel( labelMe ); + + _r = 1.0; + _g = 0.48; + _b = 0.0; + + _bgr = 0.11; + _bgg = 0.11; + _bgb = 0.11; + + highlight = false; + mouseOver = false; + + greyedOut = false; + } + + void setGreyOut( bool g ) + { + greyedOut = g; + } + + bool greyedOut; + + bool mouseOver; + bool highlight; + int x, y, w, h; + const char* labelMe; + + void setLabel( const char* l) + { + labelMe = l; + label( labelMe ); + redraw(); + } + + float _r, _g, _b; // foreground colour + float _bgr, _bgg, _bgb; // background colour + float _outr, _outg, _outb; // outline colour + + void setColor(float r, float g, float b) + { + _r = r; + _g = g; + _b = b; + } + + void setBgColor(float r, float g, float b) + { + _bgr = r; + _bgg = g; + _bgb = b; + } + + void setHighlight(bool b) + { + highlight = b; + redraw(); + } + + void draw() + { + if (damage() & FL_DAMAGE_ALL) { + cairo_t *cr = Fl::cairo_cc(); + + cairo_save( cr ); + + cairo_rectangle( cr, x+1, y+1, w-2, h-2 ); + if ( !greyedOut ) + cairo_set_source_rgb( cr, _bgr, _bgg, _bgb ); + else { + float grey = (_bgr + _bgg + _bgb) / 3; + cairo_set_source_rgb( cr, grey, grey, grey ); + } + cairo_fill_preserve(cr); + + cairo_set_line_width(cr, 1.3); + cairo_rectangle( cr, x+1, y+1, w-2, h-2 ); + + if ( highlight && !greyedOut ) { + cairo_set_source_rgba(cr, _r, _g, _b, 0.4); + cairo_fill_preserve(cr); + } + + float alpha = 0.6; + if (mouseOver) + alpha = 1; + + if ( !greyedOut ) + cairo_set_source_rgba(cr, _r, _g, _b, alpha); + else { + float grey = (_r + _g + _b) / 3; + cairo_set_source_rgb( cr, grey, grey, grey ); + } + + if ( highlight && !greyedOut ) + cairo_set_line_width(cr, 2.2); + cairo_stroke(cr); + + cairo_restore( cr ); + + draw_label(); + } + } + + void resize(int X, int Y, int W, int H) + { + Fl_Widget::resize(X,Y,W,H); + x = X; + y = Y; + w = W; + h = H; + redraw(); + } + + int handle(int event) + { + switch(event) { + case FL_PUSH: + highlight = 1; + redraw(); + return 1; + case FL_DRAG: { + int t = Fl::event_inside(this); + if (t != highlight) { + highlight = t; + redraw(); + } + } + return 1; + case FL_ENTER: + mouseOver = true; + redraw(); + return 1; + case FL_LEAVE: + mouseOver = false; + redraw(); + return 1; + case FL_RELEASE: + if (highlight) { + highlight = 0; + redraw(); + do_callback(); + } + return 1; + case FL_SHORTCUT: + if ( test_shortcut() ) { + do_callback(); + return 1; + } + return 0; + default: + return Fl_Widget::handle(event); + } + } }; } // Avtk diff --git a/src/avtk/avtk_dial.h b/src/avtk/avtk_dial.h index 72fa357..7f9e310 100644 --- a/src/avtk/avtk_dial.h +++ b/src/avtk/avtk_dial.h @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -29,174 +29,168 @@ namespace Avtk class Dial : public Fl_Slider { - public: - Dial(int _x, int _y, int _w, int _h, const char* _lab=0): - Fl_Slider(_x, _y, _w, _h, _lab) - { - x = _x; - y = _y; - w = _w; - h = _h; - - drawLabel = true; - - mouseClickedY = 0; - mouseClicked = false; - - highlight = false; - _label = strdup( _lab ); - } - - ~Dial() - { - if( _label ) - free( _label ); - } - - bool highlight; - int x, y, w, h; - char* _label; - - float radius; - float lineWidth; - - int mouseClickedY; - bool mouseClicked; - - bool drawLabel; - - void setLabel( const char* newLabel ) - { - if( _label ) - free( _label ); - - _label = strdup( newLabel ); - - label( _label ); - redraw(); - } - - void draw() - { - if (damage() & FL_DAMAGE_ALL) - { - if ( drawLabel ) - { - draw_label(); - } - - // * 0.9 for line width to remain inside redraw area - if ( w > h ) - radius = (h / 2.f)*0.9; - else - radius = (w / 2.f)*0.9; - - lineWidth = 1.4 + radius / 12.f; - - cairo_t *cr = Fl::cairo_cc(); - - cairo_save( cr ); - - cairo_rectangle( cr, x, y, w, h ); - cairo_set_source_rgba(cr, 1.1, 0.1, 0.1, 0 ); - cairo_fill(cr); - - cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); - cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); - - cairo_set_line_width(cr, lineWidth-0.2); - cairo_move_to( cr, x+w/2,y+h/2); - cairo_line_to( cr, x+w/2,y+h/2); - cairo_set_source_rgba(cr, 0.1, 0.1, 0.1, 0 ); - cairo_stroke(cr); - - cairo_arc(cr, x+w/2,y+h/2, radius, 2.46, 0.75 ); - cairo_set_source_rgb(cr, 0.1, 0.1, 0.1 ); - cairo_stroke(cr); - - float angle = 2.46 + ( 4.54 * value() ); - cairo_set_line_width(cr, lineWidth); - cairo_arc(cr, x+w/2,y+h/2, radius, 2.46, angle ); - cairo_line_to(cr, x+w/2,y+h/2); - cairo_set_source_rgba(cr, 1.0, 0.48, 0, 0.8); - cairo_stroke(cr); - - cairo_restore( cr ); - } - } - - void resize(int X, int Y, int W, int H) - { - Fl_Slider::resize(X,Y,W,H); - x = X; - y = Y; - w = W; - h = H; - redraw(); - } - - int handle(int event) - { - //cout << "handle event type = " << event << " value = " << value() << endl; - - //Fl_Slider::handle( event ); - - switch(event) { - case FL_PUSH: - highlight = 1; - redraw(); - return 1; - case FL_DRAG: - { - if ( Fl::event_state(FL_BUTTON1) ) - { - if ( mouseClicked == false ) // catch the "click" event - { - mouseClickedY = Fl::event_y(); - mouseClicked = true; - } - - float deltaY = mouseClickedY - Fl::event_y(); - - float val = value(); - val += deltaY / 100.f; - - if ( val > 1.0 ) val = 1.0; - if ( val < 0.0 ) val = 0.0; - - set_value( val ); - - mouseClickedY = Fl::event_y(); - redraw(); - do_callback(); // makes FLTK call "extra" code entered in FLUID - } - } - return 1; - case FL_MOUSEWHEEL: - { - float val = value() - Fl::event_dy() * 0.1; - //printf("dial scroll event: %f\n", val); - if ( val > 1.0 ) val = 1.0; - if ( val < 0.0 ) val = 0.0; - set_value( val ); - redraw(); - do_callback(); - return 1; - } - break; - case FL_RELEASE: - if (highlight) { - highlight = 0; - redraw(); - // never do anything after a callback, as the callback - // may delete the widget! - } - mouseClicked = false; - return 1; - default: - return Fl_Widget::handle(event); - } - } +public: + Dial(int _x, int _y, int _w, int _h, const char* _lab=0): + Fl_Slider(_x, _y, _w, _h, _lab) + { + x = _x; + y = _y; + w = _w; + h = _h; + + drawLabel = true; + + mouseClickedY = 0; + mouseClicked = false; + + highlight = false; + _label = strdup( _lab ); + } + + ~Dial() + { + if( _label ) + free( _label ); + } + + bool highlight; + int x, y, w, h; + char* _label; + + float radius; + float lineWidth; + + int mouseClickedY; + bool mouseClicked; + + bool drawLabel; + + void setLabel( const char* newLabel ) + { + if( _label ) + free( _label ); + + _label = strdup( newLabel ); + + label( _label ); + redraw(); + } + + void draw() + { + if (damage() & FL_DAMAGE_ALL) { + if ( drawLabel ) { + draw_label(); + } + + // * 0.9 for line width to remain inside redraw area + if ( w > h ) + radius = (h / 2.f)*0.9; + else + radius = (w / 2.f)*0.9; + + lineWidth = 1.4 + radius / 12.f; + + cairo_t *cr = Fl::cairo_cc(); + + cairo_save( cr ); + + cairo_rectangle( cr, x, y, w, h ); + cairo_set_source_rgba(cr, 1.1, 0.1, 0.1, 0 ); + cairo_fill(cr); + + cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); + cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); + + cairo_set_line_width(cr, lineWidth-0.2); + cairo_move_to( cr, x+w/2,y+h/2); + cairo_line_to( cr, x+w/2,y+h/2); + cairo_set_source_rgba(cr, 0.1, 0.1, 0.1, 0 ); + cairo_stroke(cr); + + cairo_arc(cr, x+w/2,y+h/2, radius, 2.46, 0.75 ); + cairo_set_source_rgb(cr, 0.1, 0.1, 0.1 ); + cairo_stroke(cr); + + float angle = 2.46 + ( 4.54 * value() ); + cairo_set_line_width(cr, lineWidth); + cairo_arc(cr, x+w/2,y+h/2, radius, 2.46, angle ); + cairo_line_to(cr, x+w/2,y+h/2); + cairo_set_source_rgba(cr, 1.0, 0.48, 0, 0.8); + cairo_stroke(cr); + + cairo_restore( cr ); + } + } + + void resize(int X, int Y, int W, int H) + { + Fl_Slider::resize(X,Y,W,H); + x = X; + y = Y; + w = W; + h = H; + redraw(); + } + + int handle(int event) + { + //cout << "handle event type = " << event << " value = " << value() << endl; + + //Fl_Slider::handle( event ); + + switch(event) { + case FL_PUSH: + highlight = 1; + redraw(); + return 1; + case FL_DRAG: { + if ( Fl::event_state(FL_BUTTON1) ) { + if ( mouseClicked == false ) { // catch the "click" event + mouseClickedY = Fl::event_y(); + mouseClicked = true; + } + + float deltaY = mouseClickedY - Fl::event_y(); + + float val = value(); + val += deltaY / 100.f; + + if ( val > 1.0 ) val = 1.0; + if ( val < 0.0 ) val = 0.0; + + set_value( val ); + + mouseClickedY = Fl::event_y(); + redraw(); + do_callback(); // makes FLTK call "extra" code entered in FLUID + } + } + return 1; + case FL_MOUSEWHEEL: { + float val = value() - Fl::event_dy() * 0.1; + //printf("dial scroll event: %f\n", val); + if ( val > 1.0 ) val = 1.0; + if ( val < 0.0 ) val = 0.0; + set_value( val ); + redraw(); + do_callback(); + return 1; + } + break; + case FL_RELEASE: + if (highlight) { + highlight = 0; + redraw(); + // never do anything after a callback, as the callback + // may delete the widget! + } + mouseClicked = false; + return 1; + default: + return Fl_Widget::handle(event); + } + } }; } // Avtk diff --git a/src/avtk/avtk_image.h b/src/avtk/avtk_image.h index c73b398..09fe8c0 100644 --- a/src/avtk/avtk_image.h +++ b/src/avtk/avtk_image.h @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -38,78 +38,74 @@ namespace Avtk class Image : public Fl_Widget { - public: - Image(int _x, int _y, int _w, int _h, const char *_label=0 ): - Fl_Widget(_x, _y, _w, _h, _label) - { - x = _x; - y = _y; - w = _w; - h = _h; - - label = _label; - - bits = -1; - imageDataPtr = 0; - - stickToRight = false; - } - - // used to keep images on the right hand side of the window - bool stickToRight; - - void setPixbuf(const unsigned char* data, int b ) - { - bits = b; - imageDataPtr = data; - } - - int x, y, w, h; - const char* label; - - int bits; - const unsigned char* imageDataPtr; - - void draw() - { - if ( damage() & FL_DAMAGE_ALL && imageDataPtr != 0 ) - { - fl_draw_image((const uchar*)imageDataPtr, x, y, w, h, bits, w*bits); - } - } - - void resize(int X, int Y, int W, int H) - { - if ( stickToRight ) - { - x = gui->getWindowWidth() - w; - } - - redraw(); - } - - int handle(int event) - { - switch(event) - { - case FL_PUSH: - do_callback(); - return 1; - case FL_DRAG: - return 1; - case FL_RELEASE: - return 1; - case FL_SHORTCUT: - if ( test_shortcut() ) - { - do_callback(); - return 1; - } - return 0; - default: - return Fl_Widget::handle(event); - } - } +public: + Image(int _x, int _y, int _w, int _h, const char *_label=0 ): + Fl_Widget(_x, _y, _w, _h, _label) + { + x = _x; + y = _y; + w = _w; + h = _h; + + label = _label; + + bits = -1; + imageDataPtr = 0; + + stickToRight = false; + } + + // used to keep images on the right hand side of the window + bool stickToRight; + + void setPixbuf(const unsigned char* data, int b ) + { + bits = b; + imageDataPtr = data; + } + + int x, y, w, h; + const char* label; + + int bits; + const unsigned char* imageDataPtr; + + void draw() + { + if ( damage() & FL_DAMAGE_ALL && imageDataPtr != 0 ) { + fl_draw_image((const uchar*)imageDataPtr, x, y, w, h, bits, w*bits); + } + } + + void resize(int X, int Y, int W, int H) + { + if ( stickToRight ) { + x = gui->getWindowWidth() - w; + } + + redraw(); + } + + int handle(int event) + { + switch(event) { + case FL_PUSH: + do_callback(); + return 1; + case FL_DRAG: + return 1; + case FL_RELEASE: + return 1; + case FL_SHORTCUT: + if ( test_shortcut() ) { + do_callback(); + return 1; + } + return 0; + default: + return Fl_Widget::handle(event); + } + } }; } // Avtk diff --git a/src/avtk/avtk_light_button.h b/src/avtk/avtk_light_button.h index df91400..441a1ca 100644 --- a/src/avtk/avtk_light_button.h +++ b/src/avtk/avtk_light_button.h @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -27,152 +27,144 @@ namespace Avtk class LightButton : public Fl_Button { - public: - LightButton(int _x, int _y, int _w, int _h, const char *_label): - Fl_Button(_x, _y, _w, _h, _label) - { - x = _x; - y = _y; - w = _w; - h = _h; - - _r = 1.0; - _g = 0.48; - _b = 0.0; - - _bgr = 0.11; - _bgg = 0.11; - _bgb = 0.11; - - _outr = _r; - _outg = _g; - _outb = _b; - - label = _label; - - _highlight = false; - mouseOver = false; - } - - bool mouseOver; - bool _highlight; - int x, y, w, h; - const char* label; - float _r, _g, _b; // foreground colour - float _bgr, _bgg, _bgb; // background colour - float _outr, _outg, _outb; // outline colour - - void setColor(float r, float g, float b) - { - _r = r; - _g = g; - _b = b; - } - - void setBgColor(float r, float g, float b) - { - _bgr = r; - _bgg = g; - _bgb = b; - } - - void draw() - { - if (damage() & FL_DAMAGE_ALL) - { - if ( value() ) - { - _highlight = true; - } - else - { - _highlight = false; - } - - cairo_t *cr = Fl::cairo_cc(); - - cairo_save( cr ); - - cairo_rectangle( cr, x+1, y+1, w-2, h-2 ); - cairo_set_source_rgba( cr, _bgr, _bgg, _bgb, 0.4 ); - cairo_fill_preserve(cr); - - cairo_set_line_width(cr, 1.5); - cairo_rectangle( cr, x+1, y+1, w-2, h-2 ); - - if ( _highlight ) - { - cairo_set_source_rgba(cr, _r, _g, _b, 0.4); - cairo_fill_preserve(cr); - } - - float alpha = 0.7; - if (mouseOver) - alpha = 1; - cairo_set_source_rgba(cr, _r, _g, _b, alpha); - cairo_stroke(cr); - - cairo_restore( cr ); - - draw_label(); - } - } - - void resize(int X, int Y, int W, int H) - { - Fl_Widget::resize(X,Y,W,H); - x = X; - y = Y; - w = W; - h = H; - redraw(); - } - - - - int handle(int event) - { - switch(event) { - case FL_ACTIVATE: - { - } - case FL_DEACTIVATE: - { - } - return 1; - case FL_PUSH: - - do_callback(); - return 1; - case FL_DRAG: { - int t = Fl::event_inside(this); - if (t != _highlight) { - _highlight = t; - redraw(); - } - } - return 1; - case FL_ENTER: - mouseOver = true; - redraw(); - return 1; - case FL_LEAVE: - mouseOver = false; - redraw(); - return 1; - case FL_RELEASE: - return 1; - case FL_SHORTCUT: - if ( test_shortcut() ) - { - do_callback(); - return 1; - } - return 0; - default: - return Fl_Widget::handle(event); - } - } +public: + LightButton(int _x, int _y, int _w, int _h, const char *_label): + Fl_Button(_x, _y, _w, _h, _label) + { + x = _x; + y = _y; + w = _w; + h = _h; + + _r = 1.0; + _g = 0.48; + _b = 0.0; + + _bgr = 0.11; + _bgg = 0.11; + _bgb = 0.11; + + _outr = _r; + _outg = _g; + _outb = _b; + + label = _label; + + _highlight = false; + mouseOver = false; + } + + bool mouseOver; + bool _highlight; + int x, y, w, h; + const char* label; + float _r, _g, _b; // foreground colour + float _bgr, _bgg, _bgb; // background colour + float _outr, _outg, _outb; // outline colour + + void setColor(float r, float g, float b) + { + _r = r; + _g = g; + _b = b; + } + + void setBgColor(float r, float g, float b) + { + _bgr = r; + _bgg = g; + _bgb = b; + } + + void draw() + { + if (damage() & FL_DAMAGE_ALL) { + if ( value() ) { + _highlight = true; + } else { + _highlight = false; + } + + cairo_t *cr = Fl::cairo_cc(); + + cairo_save( cr ); + + cairo_rectangle( cr, x+1, y+1, w-2, h-2 ); + cairo_set_source_rgba( cr, _bgr, _bgg, _bgb, 0.4 ); + cairo_fill_preserve(cr); + + cairo_set_line_width(cr, 1.5); + cairo_rectangle( cr, x+1, y+1, w-2, h-2 ); + + if ( _highlight ) { + cairo_set_source_rgba(cr, _r, _g, _b, 0.4); + cairo_fill_preserve(cr); + } + + float alpha = 0.7; + if (mouseOver) + alpha = 1; + cairo_set_source_rgba(cr, _r, _g, _b, alpha); + cairo_stroke(cr); + + cairo_restore( cr ); + + draw_label(); + } + } + + void resize(int X, int Y, int W, int H) + { + Fl_Widget::resize(X,Y,W,H); + x = X; + y = Y; + w = W; + h = H; + redraw(); + } + + + + int handle(int event) + { + switch(event) { + case FL_ACTIVATE: { + } + case FL_DEACTIVATE: { + } + return 1; + case FL_PUSH: + + do_callback(); + return 1; + case FL_DRAG: { + int t = Fl::event_inside(this); + if (t != _highlight) { + _highlight = t; + redraw(); + } + } + return 1; + case FL_ENTER: + mouseOver = true; + redraw(); + return 1; + case FL_LEAVE: + mouseOver = false; + redraw(); + return 1; + case FL_RELEASE: + return 1; + case FL_SHORTCUT: + if ( test_shortcut() ) { + do_callback(); + return 1; + } + return 0; + default: + return Fl_Widget::handle(event); + } + } }; } // Avtk diff --git a/src/avtk/avtk_radial_status.h b/src/avtk/avtk_radial_status.h index 8e5c32e..29227e9 100644 --- a/src/avtk/avtk_radial_status.h +++ b/src/avtk/avtk_radial_status.h @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -27,173 +27,172 @@ namespace Avtk class RadialStatus : public Fl_Slider { - public: - RadialStatus(int _x, int _y, int _w, int _h, const char *_label = 0): - Fl_Slider(_x, _y, _w, _h, _label) - { - x = _x; - y = _y; - w = _w; - h = _h; - - label = _label; - - previousAngle = -1; - - _r = 1.0; - _g = 0.48; - _b = 0.0; - - _bgr = 0.11; - _bgg = 0.11; - _bgb = 0.11; - - highlight = false; - mouseOver = false; - - _recording = false; - } - - bool _recording; - void recording(bool r){_recording = r; redraw();} - - bool mouseOver; - bool highlight; - int x, y, w, h; - const char* label; - - int previousAngle; - - float _r, _g, _b; // foreground colour - float _bgr, _bgg, _bgb; // background colour - float _outr, _outg, _outb; // outline colour - - void setColor(float r, float g, float b) - { - _r = r; - _g = g; - _b = b; - } - - void setBgColor(float r, float g, float b) - { - _bgr = r; - _bgg = g; - _bgb = b; - } - - void draw() - { - // check that its a new "segment" to redraw - int newAngle = (value() * 16); - - if (damage() & FL_DAMAGE_ALL && - previousAngle != newAngle ) - { - cairo_t *cr = Fl::cairo_cc(); - - cairo_save( cr ); - - int xc = (w) / 2.f; - int yc = (h) / 2.f; - - int radius = xc > yc ? yc : xc; - radius -= 10; - - float angle = newAngle / 16.f; - - cairo_set_line_cap ( cr, CAIRO_LINE_CAP_ROUND ); - //cairo_move_to( cr, x + xc, y + yc ); - cairo_arc( cr, x + xc, y + yc, radius, -(3.1415/2), angle * 6.28 - (3.1415/2) ); - cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5 ); - cairo_set_line_width(cr, 12); - cairo_stroke_preserve(cr); - - cairo_set_source_rgba (cr, 1.0, 0.48, 0.0, 1 ); - cairo_set_line_width(cr, 8.2); - cairo_stroke(cr); - - - // recording? - if ( _recording ) - { - cairo_set_source_rgba(cr,1.0,0.0,0.0, 0.8); - cairo_arc(cr, x + xc, y + yc, radius-4, 0, 2 * 3.1415); - cairo_fill_preserve(cr); - cairo_set_source_rgba(cr,0.0,0.0,0.0, 0.8); - cairo_set_line_width(cr, 2.2); - cairo_stroke(cr); - - // color of internal dot depending on rec state - cairo_set_source_rgba(cr,0.0,0.0,0.0, 1); - } - else - { - cairo_set_source_rgba(cr,0.3,0.3,0.3, 1); - } - - // inside circle - cairo_arc(cr, x + xc, y + yc, 10, 0, 2 * 3.1415); - cairo_set_line_width(cr, 4.2); - cairo_fill(cr); - - cairo_restore( cr ); - - draw_label(); - } - } - - void resize(int X, int Y, int W, int H) - { - Fl_Widget::resize(X,Y,W,H); - x = X; - y = Y; - w = W; - h = H; - redraw(); - } - - int handle(int event) - { - switch(event) { - case FL_PUSH: - highlight = 1; - redraw(); - return 1; - case FL_DRAG: { - int t = Fl::event_inside(this); - if (t != highlight) { - highlight = t; - redraw(); - } - } - return 1; - case FL_ENTER: - mouseOver = true; - redraw(); - return 1; - case FL_LEAVE: - mouseOver = false; - redraw(); - return 1; - case FL_RELEASE: - if (highlight) { - highlight = 0; - redraw(); - do_callback(); - } - return 1; - case FL_SHORTCUT: - if ( test_shortcut() ) - { - do_callback(); - return 1; - } - return 0; - default: - return Fl_Widget::handle(event); - } - } +public: + RadialStatus(int _x, int _y, int _w, int _h, const char *_label = 0): + Fl_Slider(_x, _y, _w, _h, _label) + { + x = _x; + y = _y; + w = _w; + h = _h; + + label = _label; + + previousAngle = -1; + + _r = 1.0; + _g = 0.48; + _b = 0.0; + + _bgr = 0.11; + _bgg = 0.11; + _bgb = 0.11; + + highlight = false; + mouseOver = false; + + _recording = false; + } + + bool _recording; + void recording(bool r) + { + _recording = r; + redraw(); + } + + bool mouseOver; + bool highlight; + int x, y, w, h; + const char* label; + + int previousAngle; + + float _r, _g, _b; // foreground colour + float _bgr, _bgg, _bgb; // background colour + float _outr, _outg, _outb; // outline colour + + void setColor(float r, float g, float b) + { + _r = r; + _g = g; + _b = b; + } + + void setBgColor(float r, float g, float b) + { + _bgr = r; + _bgg = g; + _bgb = b; + } + + void draw() + { + // check that its a new "segment" to redraw + int newAngle = (value() * 16); + + if (damage() & FL_DAMAGE_ALL && + previousAngle != newAngle ) { + cairo_t *cr = Fl::cairo_cc(); + + cairo_save( cr ); + + int xc = (w) / 2.f; + int yc = (h) / 2.f; + + int radius = xc > yc ? yc : xc; + radius -= 10; + + float angle = newAngle / 16.f; + + cairo_set_line_cap ( cr, CAIRO_LINE_CAP_ROUND ); + //cairo_move_to( cr, x + xc, y + yc ); + cairo_arc( cr, x + xc, y + yc, radius, -(3.1415/2), angle * 6.28 - (3.1415/2) ); + cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5 ); + cairo_set_line_width(cr, 12); + cairo_stroke_preserve(cr); + + cairo_set_source_rgba (cr, 1.0, 0.48, 0.0, 1 ); + cairo_set_line_width(cr, 8.2); + cairo_stroke(cr); + + + // recording? + if ( _recording ) { + cairo_set_source_rgba(cr,1.0,0.0,0.0, 0.8); + cairo_arc(cr, x + xc, y + yc, radius-4, 0, 2 * 3.1415); + cairo_fill_preserve(cr); + cairo_set_source_rgba(cr,0.0,0.0,0.0, 0.8); + cairo_set_line_width(cr, 2.2); + cairo_stroke(cr); + + // color of internal dot depending on rec state + cairo_set_source_rgba(cr,0.0,0.0,0.0, 1); + } else { + cairo_set_source_rgba(cr,0.3,0.3,0.3, 1); + } + + // inside circle + cairo_arc(cr, x + xc, y + yc, 10, 0, 2 * 3.1415); + cairo_set_line_width(cr, 4.2); + cairo_fill(cr); + + cairo_restore( cr ); + + draw_label(); + } + } + + void resize(int X, int Y, int W, int H) + { + Fl_Widget::resize(X,Y,W,H); + x = X; + y = Y; + w = W; + h = H; + redraw(); + } + + int handle(int event) + { + switch(event) { + case FL_PUSH: + highlight = 1; + redraw(); + return 1; + case FL_DRAG: { + int t = Fl::event_inside(this); + if (t != highlight) { + highlight = t; + redraw(); + } + } + return 1; + case FL_ENTER: + mouseOver = true; + redraw(); + return 1; + case FL_LEAVE: + mouseOver = false; + redraw(); + return 1; + case FL_RELEASE: + if (highlight) { + highlight = 0; + redraw(); + do_callback(); + } + return 1; + case FL_SHORTCUT: + if ( test_shortcut() ) { + do_callback(); + return 1; + } + return 0; + default: + return Fl_Widget::handle(event); + } + } }; } // Avtk diff --git a/src/avtk/avtk_reverb.h b/src/avtk/avtk_reverb.h index a94af0f..a3a05d3 100644 --- a/src/avtk/avtk_reverb.h +++ b/src/avtk/avtk_reverb.h @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -27,190 +27,212 @@ namespace Avtk class Reverb : public Fl_Slider { - public: - Reverb(int _x, int _y, int _w, int _h, const char *_label =0): - Fl_Slider(_x, _y, _w, _h, _label) - { - x = _x; - y = _y; - w = _w; - h = _h; - - amp = 0.5; - s = 0.5; - damp= 0.5; - - active = false; - - label = _label; - - highlight = false; - mouseOver = false; - } - - void size(float v) { s = v; redraw(); } - void wet(float v) { amp = v; redraw(); } - void damping(float v){damp = v; redraw();} - - float size(){return s;} - float wet (){return amp;} - float damping(){return damp;} - - bool getActive(){return active;} - void setActive(bool a){active = a; redraw();} - - float s; - float amp; - float damp; - - bool active; - - bool mouseOver; - bool highlight; - int x, y, w, h; - const char* label; - - void draw() - { - if (damage() & FL_DAMAGE_ALL) - { - cairo_t *cr = Fl::cairo_cc(); - - cairo_save( cr ); - - // graph - cairo_rectangle( cr, x, y, w, h ); - cairo_set_source_rgb( cr,28 / 255.f, 28 / 255.f , 28 / 255.f ); - cairo_fill(cr); - - - // set up dashed lines, 1 px off, 1 px on - double dashes[1]; - dashes[0] = 2.0; - - cairo_set_dash ( cr, dashes, 1, 0.0); - - // loop over each 2nd line, drawing dots - cairo_set_line_width(cr, 1.0); - cairo_set_source_rgb(cr, 0.4,0.4,0.4); - for ( int i = 0; i < 4; i++ ) - { - cairo_move_to( cr, x + ((w / 4.f)*i), y ); - cairo_line_to( cr, x + ((w / 4.f)*i), y + h ); - } - for ( int i = 0; i < 4; i++ ) - { - cairo_move_to( cr, x , y + ((h / 4.f)*i) ); - cairo_line_to( cr, x + w, y + ((h / 4.f)*i) ); - } - cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 ); - cairo_stroke(cr); - cairo_set_dash ( cr, dashes, 0, 0.0); - - // draw "damping" control - cairo_move_to( cr, x+w*0.1 , y + h*0.85 - (h*0.7*amp)); - cairo_line_to( cr, x+w*0.1 + (w-20)*damp, y + h*0.85 - (h*0.7*amp)); - cairo_set_source_rgba(cr, 1.0, 0.48, 0, 1); - cairo_set_line_join( cr, CAIRO_LINE_JOIN_ROUND); - cairo_set_line_cap ( cr, CAIRO_LINE_CAP_ROUND); - cairo_set_line_width(cr, 1.9); - cairo_stroke( cr ); - - // draw reverb triangle - cairo_move_to( cr, x , y + h*0.99 ); - cairo_line_to( cr, x + w*0.1, y + h*0.85 - (h*0.7*amp)); - cairo_line_to( cr, x + w*0.3+w*0.7*s, y + (h*0.99)); - - // stroke - cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 ); - cairo_fill_preserve(cr); - cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); - cairo_set_line_width(cr, 1.2); - cairo_stroke( cr ); - - // stroke rim - cairo_rectangle(cr, x, y, w, h); - //cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); - cairo_set_source_rgba( cr, 126 / 255.f, 126 / 255.f , 126 / 255.f , 0.8 ); - cairo_set_line_width(cr, 0.9); - cairo_stroke( cr ); - - if ( !active ) - { - // big grey X - cairo_set_line_width(cr, 12.0); - cairo_set_source_rgba(cr, 0.0,0.0,0.0, 1.0); - - cairo_move_to( cr, x + (3 * w / 4.f), y + ( h / 4.f ) ); - cairo_line_to( cr, x + (w / 4.f), y + ( 3 *h / 4.f ) ); - - cairo_move_to( cr, x + (w / 4.f), y + ( h / 4.f ) ); - cairo_line_to( cr, x + (3 * w / 4.f), y + ( 3 *h / 4.f ) ); - cairo_set_line_cap ( cr, CAIRO_LINE_CAP_BUTT); - cairo_stroke( cr ); - } - - cairo_restore( cr ); - - draw_label(); - } - } - - void resize(int X, int Y, int W, int H) - { - Fl_Widget::resize(X,Y,W,H); - x = X; - y = Y; - w = W; - h = H; - redraw(); - } - - int handle(int event) - { - switch(event) { - case FL_PUSH: - highlight = 1; - if ( Fl::event_button() == FL_RIGHT_MOUSE ) - { - active = !active; - redraw(); - do_callback(); - } - return 1; - case FL_DRAG: { - int t = Fl::event_inside(this); - if (t != highlight) { - highlight = t; - redraw(); - } - } - return 1; - case FL_ENTER: - mouseOver = true; - redraw(); - return 1; - case FL_LEAVE: - mouseOver = false; - redraw(); - return 1; - case FL_RELEASE: - if (highlight) { - highlight = 0; - redraw(); - } - return 1; - case FL_SHORTCUT: - if ( test_shortcut() ) - { - do_callback(); - return 1; - } - return 0; - default: - return Fl_Widget::handle(event); - } - } +public: + Reverb(int _x, int _y, int _w, int _h, const char *_label =0): + Fl_Slider(_x, _y, _w, _h, _label) + { + x = _x; + y = _y; + w = _w; + h = _h; + + amp = 0.5; + s = 0.5; + damp= 0.5; + + active = false; + + label = _label; + + highlight = false; + mouseOver = false; + } + + void size(float v) + { + s = v; + redraw(); + } + void wet(float v) + { + amp = v; + redraw(); + } + void damping(float v) + { + damp = v; + redraw(); + } + + float size() + { + return s; + } + float wet () + { + return amp; + } + float damping() + { + return damp; + } + + bool getActive() + { + return active; + } + void setActive(bool a) + { + active = a; + redraw(); + } + + float s; + float amp; + float damp; + + bool active; + + bool mouseOver; + bool highlight; + int x, y, w, h; + const char* label; + + void draw() + { + if (damage() & FL_DAMAGE_ALL) { + cairo_t *cr = Fl::cairo_cc(); + + cairo_save( cr ); + + // graph + cairo_rectangle( cr, x, y, w, h ); + cairo_set_source_rgb( cr,28 / 255.f, 28 / 255.f , 28 / 255.f ); + cairo_fill(cr); + + + // set up dashed lines, 1 px off, 1 px on + double dashes[1]; + dashes[0] = 2.0; + + cairo_set_dash ( cr, dashes, 1, 0.0); + + // loop over each 2nd line, drawing dots + cairo_set_line_width(cr, 1.0); + cairo_set_source_rgb(cr, 0.4,0.4,0.4); + for ( int i = 0; i < 4; i++ ) { + cairo_move_to( cr, x + ((w / 4.f)*i), y ); + cairo_line_to( cr, x + ((w / 4.f)*i), y + h ); + } + for ( int i = 0; i < 4; i++ ) { + cairo_move_to( cr, x , y + ((h / 4.f)*i) ); + cairo_line_to( cr, x + w, y + ((h / 4.f)*i) ); + } + cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 ); + cairo_stroke(cr); + cairo_set_dash ( cr, dashes, 0, 0.0); + + // draw "damping" control + cairo_move_to( cr, x+w*0.1 , y + h*0.85 - (h*0.7*amp)); + cairo_line_to( cr, x+w*0.1 + (w-20)*damp, y + h*0.85 - (h*0.7*amp)); + cairo_set_source_rgba(cr, 1.0, 0.48, 0, 1); + cairo_set_line_join( cr, CAIRO_LINE_JOIN_ROUND); + cairo_set_line_cap ( cr, CAIRO_LINE_CAP_ROUND); + cairo_set_line_width(cr, 1.9); + cairo_stroke( cr ); + + // draw reverb triangle + cairo_move_to( cr, x , y + h*0.99 ); + cairo_line_to( cr, x + w*0.1, y + h*0.85 - (h*0.7*amp)); + cairo_line_to( cr, x + w*0.3+w*0.7*s, y + (h*0.99)); + + // stroke + cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 ); + cairo_fill_preserve(cr); + cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); + cairo_set_line_width(cr, 1.2); + cairo_stroke( cr ); + + // stroke rim + cairo_rectangle(cr, x, y, w, h); + //cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); + cairo_set_source_rgba( cr, 126 / 255.f, 126 / 255.f , 126 / 255.f , 0.8 ); + cairo_set_line_width(cr, 0.9); + cairo_stroke( cr ); + + if ( !active ) { + // big grey X + cairo_set_line_width(cr, 12.0); + cairo_set_source_rgba(cr, 0.0,0.0,0.0, 1.0); + + cairo_move_to( cr, x + (3 * w / 4.f), y + ( h / 4.f ) ); + cairo_line_to( cr, x + (w / 4.f), y + ( 3 *h / 4.f ) ); + + cairo_move_to( cr, x + (w / 4.f), y + ( h / 4.f ) ); + cairo_line_to( cr, x + (3 * w / 4.f), y + ( 3 *h / 4.f ) ); + cairo_set_line_cap ( cr, CAIRO_LINE_CAP_BUTT); + cairo_stroke( cr ); + } + + cairo_restore( cr ); + + draw_label(); + } + } + + void resize(int X, int Y, int W, int H) + { + Fl_Widget::resize(X,Y,W,H); + x = X; + y = Y; + w = W; + h = H; + redraw(); + } + + int handle(int event) + { + switch(event) { + case FL_PUSH: + highlight = 1; + if ( Fl::event_button() == FL_RIGHT_MOUSE ) { + active = !active; + redraw(); + do_callback(); + } + return 1; + case FL_DRAG: { + int t = Fl::event_inside(this); + if (t != highlight) { + highlight = t; + redraw(); + } + } + return 1; + case FL_ENTER: + mouseOver = true; + redraw(); + return 1; + case FL_LEAVE: + mouseOver = false; + redraw(); + return 1; + case FL_RELEASE: + if (highlight) { + highlight = 0; + redraw(); + } + return 1; + case FL_SHORTCUT: + if ( test_shortcut() ) { + do_callback(); + return 1; + } + return 0; + default: + return Fl_Widget::handle(event); + } + } }; } // Avtk diff --git a/src/avtk/avtk_sidechain_gain.h b/src/avtk/avtk_sidechain_gain.h index 5c11d95..b141230 100644 --- a/src/avtk/avtk_sidechain_gain.h +++ b/src/avtk/avtk_sidechain_gain.h @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -29,185 +29,198 @@ namespace Avtk { - + class SidechainGain : public Fl_Slider { - public: - SidechainGain(int _x, int _y, int _w, int _h, const char *_label = 0): - Fl_Slider(_x, _y, _w, _h, _label) - { - x = _x; - y = _y; - w = _w; - h = _h; - - label = _label; - - mouseClickedX = 0; - mouseClickedY = 0; - mouseClicked = false; - - active = true; - highlight = false; - - _threshold = 1.0; - _target = 1.f; - _reduce = 1.f; - _release = 0.5; - - _sidechainAmp = 0; - } - - void threshold(float t) {_threshold = t; redraw();} - void reduce (float r) {_reduce = r; redraw();} - void release (float r) {_release = r; redraw();} - - /// sets the sidechain amplitude - void sidechain(float s) {_sidechainAmp = s; redraw();} - - bool active; - bool highlight; - int x, y, w, h; - const char* label; - - int mouseClickedX; - int mouseClickedY; - bool mouseClicked; - bool mouseRightClicked; - - float _threshold; - float _target; - float _reduce; - float _release; - - float _sidechainAmp; - - void set_active(bool a) - { - active = a; - redraw(); - } - - void draw() - { - if (damage() & FL_DAMAGE_ALL) - { - cairo_t *cr = Fl::cairo_cc(); - - cairo_save( cr ); - - cairo_set_line_width(cr, 1.5); - - - // fill background - cairo_rectangle( cr, x, y, w, h); - cairo_set_source_rgb( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f ); - cairo_fill_preserve( cr ); - cairo_clip( cr ); - - - // set up dashed lines, 1 px off, 1 px on - double dashes[1]; - dashes[0] = 2.0; - - cairo_set_dash ( cr, dashes, 1, 0.0); - cairo_set_line_width( cr, 1.0); - - // loop over each 2nd line, drawing dots - cairo_set_line_width(cr, 1.0); - cairo_set_source_rgb(cr, 0.4,0.4,0.4); - for ( int i = 0; i < 4; i++ ) - { - cairo_move_to( cr, x + ((w / 4.f)*i), y ); - cairo_line_to( cr, x + ((w / 4.f)*i), y + h ); - } - for ( int i = 0; i < 4; i++ ) - { - cairo_move_to( cr, x , y + ((h / 4.f)*i) ); - cairo_line_to( cr, x + w, y + ((h / 4.f)*i) ); - } - - cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 ); - cairo_stroke(cr); - cairo_set_dash ( cr, dashes, 0, 0.0); - - - // draw threshold / ducked line - cairo_move_to( cr, x + w * 0.750 - (w * 0.5 * (1-_threshold)), y ); - - cairo_line_to( cr, x + w * 0.750 - (w * 0.5 * (1-_threshold)) + _sidechainAmp* _reduce*( w * 0.5 ), y + h / 2 ); - - cairo_line_to( cr, x + w * 0.750 - (w * 0.5 * (1-_threshold)), y + h ); - - cairo_line_to( cr, x + w , y + h ); - cairo_line_to( cr, x + w , y ); - cairo_close_path( cr ); - cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 ); - cairo_fill_preserve( cr ); - cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); - cairo_stroke( cr ); - - // _sidechainAmp => arrow - cairo_move_to( cr, x + w * 0.00 * _sidechainAmp, y + h * 0.4 - (h*0.1*_sidechainAmp) ); - cairo_line_to( cr, x + w * 0.65 * _sidechainAmp, y + h * 0.4 ); - cairo_line_to( cr, x + w * 0.1 + w * 0.65 * _sidechainAmp, y + h * 0.5 ); - cairo_line_to( cr, x + w * 0.65 * _sidechainAmp, y + h * 0.6 ); - cairo_line_to( cr, x + w * 0.00 * _sidechainAmp, y + h * 0.6 + (h*0.1*_sidechainAmp) ); - cairo_close_path( cr ); - cairo_set_source_rgba( cr, 1.0, 0.48, 0.f , 0.21 ); - cairo_fill_preserve( cr ); - cairo_set_source_rgba( cr, 1.0, 0.48, 0.f , 1 ); - cairo_stroke( cr ); - - - // _release horizontal line - cairo_move_to( cr, x , y + h * 0.25 + h/2 * _release ); - cairo_line_to( cr, x + w, y + h * 0.25 + h/2 * _release ); - cairo_set_source_rgba( cr, 1.0, 0.0, 0.f , 1 ); - cairo_stroke( cr ); - - // stroke outline - cairo_rectangle(cr, x, y, w, h); - cairo_set_source_rgba( cr, 126 / 255.f, 126 / 255.f , 126 / 255.f , 0.8 ); - cairo_set_line_width(cr, 1.9); - cairo_stroke( cr ); - - if ( !active ) - { - // big grey X - cairo_set_line_width(cr, 20.0); - cairo_set_source_rgba(cr, 0.4,0.4,0.4, 0.7); - - cairo_move_to( cr, x + (3 * w / 4.f), y + ( h / 4.f ) ); - cairo_line_to( cr, x + (w / 4.f), y + ( 3 *h / 4.f ) ); - - cairo_move_to( cr, x + (w / 4.f), y + ( h / 4.f ) ); - cairo_line_to( cr, x + (3 * w / 4.f), y + ( 3 *h / 4.f ) ); - cairo_set_line_cap ( cr, CAIRO_LINE_CAP_BUTT); - cairo_stroke( cr ); - } - - cairo_restore( cr ); - } - } - - void resize(int X, int Y, int W, int H) - { - Fl_Widget::resize(X,Y,W,H); - x = X; - y = Y; - w = W; - h = H; - redraw(); - } - - int handle(int event) - { //TODO needed? - - return 0; - } - - private: +public: + SidechainGain(int _x, int _y, int _w, int _h, const char *_label = 0): + Fl_Slider(_x, _y, _w, _h, _label) + { + x = _x; + y = _y; + w = _w; + h = _h; + + label = _label; + + mouseClickedX = 0; + mouseClickedY = 0; + mouseClicked = false; + + active = true; + highlight = false; + + _threshold = 1.0; + _target = 1.f; + _reduce = 1.f; + _release = 0.5; + + _sidechainAmp = 0; + } + + void threshold(float t) + { + _threshold = t; + redraw(); + } + void reduce (float r) + { + _reduce = r; + redraw(); + } + void release (float r) + { + _release = r; + redraw(); + } + + /// sets the sidechain amplitude + void sidechain(float s) + { + _sidechainAmp = s; + redraw(); + } + + bool active; + bool highlight; + int x, y, w, h; + const char* label; + + int mouseClickedX; + int mouseClickedY; + bool mouseClicked; + bool mouseRightClicked; + + float _threshold; + float _target; + float _reduce; + float _release; + + float _sidechainAmp; + + void set_active(bool a) + { + active = a; + redraw(); + } + + void draw() + { + if (damage() & FL_DAMAGE_ALL) { + cairo_t *cr = Fl::cairo_cc(); + + cairo_save( cr ); + + cairo_set_line_width(cr, 1.5); + + + // fill background + cairo_rectangle( cr, x, y, w, h); + cairo_set_source_rgb( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f ); + cairo_fill_preserve( cr ); + cairo_clip( cr ); + + + // set up dashed lines, 1 px off, 1 px on + double dashes[1]; + dashes[0] = 2.0; + + cairo_set_dash ( cr, dashes, 1, 0.0); + cairo_set_line_width( cr, 1.0); + + // loop over each 2nd line, drawing dots + cairo_set_line_width(cr, 1.0); + cairo_set_source_rgb(cr, 0.4,0.4,0.4); + for ( int i = 0; i < 4; i++ ) { + cairo_move_to( cr, x + ((w / 4.f)*i), y ); + cairo_line_to( cr, x + ((w / 4.f)*i), y + h ); + } + for ( int i = 0; i < 4; i++ ) { + cairo_move_to( cr, x , y + ((h / 4.f)*i) ); + cairo_line_to( cr, x + w, y + ((h / 4.f)*i) ); + } + + cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 ); + cairo_stroke(cr); + cairo_set_dash ( cr, dashes, 0, 0.0); + + + // draw threshold / ducked line + cairo_move_to( cr, x + w * 0.750 - (w * 0.5 * (1-_threshold)), y ); + + cairo_line_to( cr, x + w * 0.750 - (w * 0.5 * (1-_threshold)) + _sidechainAmp* _reduce*( w * 0.5 ), y + h / 2 ); + + cairo_line_to( cr, x + w * 0.750 - (w * 0.5 * (1-_threshold)), y + h ); + + cairo_line_to( cr, x + w , y + h ); + cairo_line_to( cr, x + w , y ); + cairo_close_path( cr ); + cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 ); + cairo_fill_preserve( cr ); + cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); + cairo_stroke( cr ); + + // _sidechainAmp => arrow + cairo_move_to( cr, x + w * 0.00 * _sidechainAmp, y + h * 0.4 - (h*0.1*_sidechainAmp) ); + cairo_line_to( cr, x + w * 0.65 * _sidechainAmp, y + h * 0.4 ); + cairo_line_to( cr, x + w * 0.1 + w * 0.65 * _sidechainAmp, y + h * 0.5 ); + cairo_line_to( cr, x + w * 0.65 * _sidechainAmp, y + h * 0.6 ); + cairo_line_to( cr, x + w * 0.00 * _sidechainAmp, y + h * 0.6 + (h*0.1*_sidechainAmp) ); + cairo_close_path( cr ); + cairo_set_source_rgba( cr, 1.0, 0.48, 0.f , 0.21 ); + cairo_fill_preserve( cr ); + cairo_set_source_rgba( cr, 1.0, 0.48, 0.f , 1 ); + cairo_stroke( cr ); + + + // _release horizontal line + cairo_move_to( cr, x , y + h * 0.25 + h/2 * _release ); + cairo_line_to( cr, x + w, y + h * 0.25 + h/2 * _release ); + cairo_set_source_rgba( cr, 1.0, 0.0, 0.f , 1 ); + cairo_stroke( cr ); + + // stroke outline + cairo_rectangle(cr, x, y, w, h); + cairo_set_source_rgba( cr, 126 / 255.f, 126 / 255.f , 126 / 255.f , 0.8 ); + cairo_set_line_width(cr, 1.9); + cairo_stroke( cr ); + + if ( !active ) { + // big grey X + cairo_set_line_width(cr, 20.0); + cairo_set_source_rgba(cr, 0.4,0.4,0.4, 0.7); + + cairo_move_to( cr, x + (3 * w / 4.f), y + ( h / 4.f ) ); + cairo_line_to( cr, x + (w / 4.f), y + ( 3 *h / 4.f ) ); + + cairo_move_to( cr, x + (w / 4.f), y + ( h / 4.f ) ); + cairo_line_to( cr, x + (3 * w / 4.f), y + ( 3 *h / 4.f ) ); + cairo_set_line_cap ( cr, CAIRO_LINE_CAP_BUTT); + cairo_stroke( cr ); + } + + cairo_restore( cr ); + } + } + + void resize(int X, int Y, int W, int H) + { + Fl_Widget::resize(X,Y,W,H); + x = X; + y = Y; + w = W; + h = H; + redraw(); + } + + int handle(int event) + { + //TODO needed? + + return 0; + } + +private: }; } // Avtk diff --git a/src/avtk/avtk_unit.h b/src/avtk/avtk_unit.h index 21dc1d3..9bc4bb7 100644 --- a/src/avtk/avtk_unit.h +++ b/src/avtk/avtk_unit.h @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -29,171 +29,166 @@ namespace Avtk class UnitState { - public: - enum State { - UNIT_EMPTY = 0, - UNIT_LOADED, - UNIT_QUEUED, - UNIT_PLAYING, - UNIT_RECORDING, - UNIT_STOPPING, - }; - UnitState() - { - state = UNIT_EMPTY; - name = "Clip"; - } - UnitState(std::string n) - { - state = UNIT_EMPTY; - name = n; - } - - State state; - std::string name; +public: + enum State { + UNIT_EMPTY = 0, + UNIT_LOADED, + UNIT_QUEUED, + UNIT_PLAYING, + UNIT_RECORDING, + UNIT_STOPPING, + }; + UnitState() + { + state = UNIT_EMPTY; + name = "Clip"; + } + UnitState(std::string n) + { + state = UNIT_EMPTY; + name = n; + } + + State state; + std::string name; }; class Unit : public Fl_Button { - public: - Unit(int _x, int _y, int _w, int _h, const char *_label): - Fl_Button(_x, _y, _w, _h, _label) - { - x = _x; - y = _y; - w = _w; - h = _h; - - label = _label; - - highlight = false; - mouseOver = false; - - clips[0].state = UnitState::UNIT_EMPTY; - clips[1].state = UnitState::UNIT_LOADED; - clips[2].state = UnitState::UNIT_QUEUED; - clips[3].state = UnitState::UNIT_PLAYING; - clips[4].state = UnitState::UNIT_RECORDING; - clips[5].state = UnitState::UNIT_STOPPING; - } - - static const int numClips = 10; - UnitState clips[numClips]; - - bool mouseOver; - bool highlight; - int x, y, w, h; - const char* label; - - void draw() - { - if (damage() & FL_DAMAGE_ALL) - { - if ( value() ) - { - highlight = true; - } - else - { - highlight = false; - } - - cairo_t *cr = Fl::cairo_cc(); - - cairo_save( cr ); - - cairo_rectangle( cr, x+2, y + 2, w - 2, h - 2 ); - cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 0.4); - cairo_fill(cr); - - //cairo_rectangle( cr, x+1, drawY, clipHeight - 2, clipHeight - 2 ); - /* - cairo_rectangle( cr, x+1, drawY, clipWidth, clipHeight - 2 ); - - float alpha = 0.7; - if (mouseOver) { alpha = 1; } - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, alpha); - cairo_set_line_width( cr, 1.4); - cairo_move_to( cr, x+clipHeight-1, drawY ); - cairo_line_to( cr, x+clipHeight-1, drawY + clipHeight - 2); - cairo_stroke(cr); - - // clip name - cairo_move_to( cr, x+clipHeight-1+ 10, drawY + 15 ); - cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 1 ); - cairo_set_font_size( cr, 10 ); - cairo_show_text( cr, label ); - */ - - // outline - float alpha = 0.7; - if (mouseOver) { alpha = 1; } - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, alpha); - cairo_rectangle( cr, x+2, y + 2, w - 2, h - 2 ); - cairo_set_line_width( cr, 1.4); - cairo_stroke( cr ); - - cairo_restore( cr ); - - draw_label(); - } - } - - void resize(int X, int Y, int W, int H) - { - Fl_Widget::resize(X,Y,W,H); - x = X; - y = Y; - w = W; - h = H; - redraw(); - } - - - - int handle(int event) - { - switch(event) { - case FL_ACTIVATE: - { - } - case FL_DEACTIVATE: - { - } - return 1; - case FL_PUSH: - highlight = 1; - do_callback(); - return 1; - case FL_DRAG: { - int t = Fl::event_inside(this); - if (t != highlight) { - highlight = t; - redraw(); - } - } - return 1; - case FL_ENTER: - mouseOver = true; - redraw(); - return 1; - case FL_LEAVE: - mouseOver = false; - redraw(); - return 1; - case FL_RELEASE: - return 1; - case FL_SHORTCUT: - if ( test_shortcut() ) - { - do_callback(); - return 1; - } - return 0; - default: - return Fl_Widget::handle(event); - } - } +public: + Unit(int _x, int _y, int _w, int _h, const char *_label): + Fl_Button(_x, _y, _w, _h, _label) + { + x = _x; + y = _y; + w = _w; + h = _h; + + label = _label; + + highlight = false; + mouseOver = false; + + clips[0].state = UnitState::UNIT_EMPTY; + clips[1].state = UnitState::UNIT_LOADED; + clips[2].state = UnitState::UNIT_QUEUED; + clips[3].state = UnitState::UNIT_PLAYING; + clips[4].state = UnitState::UNIT_RECORDING; + clips[5].state = UnitState::UNIT_STOPPING; + } + + static const int numClips = 10; + UnitState clips[numClips]; + + bool mouseOver; + bool highlight; + int x, y, w, h; + const char* label; + + void draw() + { + if (damage() & FL_DAMAGE_ALL) { + if ( value() ) { + highlight = true; + } else { + highlight = false; + } + + cairo_t *cr = Fl::cairo_cc(); + + cairo_save( cr ); + + cairo_rectangle( cr, x+2, y + 2, w - 2, h - 2 ); + cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 0.4); + cairo_fill(cr); + + //cairo_rectangle( cr, x+1, drawY, clipHeight - 2, clipHeight - 2 ); + /* + cairo_rectangle( cr, x+1, drawY, clipWidth, clipHeight - 2 ); + + float alpha = 0.7; + if (mouseOver) { alpha = 1; } + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, alpha); + cairo_set_line_width( cr, 1.4); + cairo_move_to( cr, x+clipHeight-1, drawY ); + cairo_line_to( cr, x+clipHeight-1, drawY + clipHeight - 2); + cairo_stroke(cr); + + // clip name + cairo_move_to( cr, x+clipHeight-1+ 10, drawY + 15 ); + cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 1 ); + cairo_set_font_size( cr, 10 ); + cairo_show_text( cr, label ); + */ + + // outline + float alpha = 0.7; + if (mouseOver) { + alpha = 1; + } + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, alpha); + cairo_rectangle( cr, x+2, y + 2, w - 2, h - 2 ); + cairo_set_line_width( cr, 1.4); + cairo_stroke( cr ); + + cairo_restore( cr ); + + draw_label(); + } + } + + void resize(int X, int Y, int W, int H) + { + Fl_Widget::resize(X,Y,W,H); + x = X; + y = Y; + w = W; + h = H; + redraw(); + } + + + + int handle(int event) + { + switch(event) { + case FL_ACTIVATE: { + } + case FL_DEACTIVATE: { + } + return 1; + case FL_PUSH: + highlight = 1; + do_callback(); + return 1; + case FL_DRAG: { + int t = Fl::event_inside(this); + if (t != highlight) { + highlight = t; + redraw(); + } + } + return 1; + case FL_ENTER: + mouseOver = true; + redraw(); + return 1; + case FL_LEAVE: + mouseOver = false; + redraw(); + return 1; + case FL_RELEASE: + return 1; + case FL_SHORTCUT: + if ( test_shortcut() ) { + do_callback(); + return 1; + } + return 0; + default: + return Fl_Widget::handle(event); + } + } }; } // Avtk diff --git a/src/avtk/bindings.cxx b/src/avtk/bindings.cxx index 3835849..3800886 100644 --- a/src/avtk/bindings.cxx +++ b/src/avtk/bindings.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -27,132 +27,130 @@ namespace Avtk { Bindings::Bindings( int _x, int _y, int _w, int _h, const char *_label ) : - Fl_Button(_x, _y, _w, _h, _label) + Fl_Button(_x, _y, _w, _h, _label) { - x = _x; - y = _y; - w = _w; - h = _h; - - label = _label; - - bindYPx = 25; - - highlight = false; - mouseOver = false; + x = _x; + y = _y; + w = _w; + h = _h; + + label = _label; + + bindYPx = 25; + + highlight = false; + mouseOver = false; } void Bindings::draw() { - if (damage() & FL_DAMAGE_ALL) - { - cairo_t *cr = Fl::cairo_cc(); - cairo_save( cr ); - - cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 1 ); - cairo_set_font_size( cr, 11 ); - cairo_move_to( cr, x + 7, y+15 ); - cairo_show_text( cr, "Action:" ); - - cairo_move_to( cr, x + 140, y+15 ); - cairo_show_text( cr, "T:" ); - cairo_move_to( cr, x + 160, y+15 ); - cairo_show_text( cr, "S:" ); - - - cairo_move_to( cr, x + 200, y+15 ); - cairo_show_text( cr, "B1:" ); - cairo_move_to( cr, x + 230, y+15 ); - cairo_show_text( cr, "B2:" ); - - - int drawY = y + bindYPx; - for(unsigned int i = 0; i < binds.size(); i++) // draw each binding - { - cairo_rectangle( cr, x+2, drawY, 179, 23 ); - cairo_set_source_rgba(cr, 0 / 255.f, 0 / 255.f , 0 / 255.f, 0.4); - cairo_fill(cr); - - // action - cairo_move_to( cr, x + 7, drawY+15 ); - cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 1 ); - cairo_set_font_size( cr, 11 ); - const char* action = Event::getPrettyName( binds.at(i)->action ); - if ( action ) - cairo_show_text( cr, action ); - - // track - cairo_move_to( cr, x + 140, drawY+15 ); - { - std::stringstream s; - s << binds.at(i)->track; - cairo_show_text( cr, s.str().c_str() ); - } - // scene - cairo_move_to( cr, x + 150, drawY+15 ); - { - std::stringstream s; - s << binds.at(i)->scene; - cairo_show_text( cr, s.str().c_str() ); - } - - // status - cairo_move_to( cr, x + 165, drawY+15 ); - { - std::stringstream s; - s << binds.at(i)->status; - cairo_show_text( cr, s.str().c_str() ); - } - // data - cairo_move_to( cr, x + 175, drawY+15 ); - { - std::stringstream s; - s << binds.at(i)->data; - cairo_show_text( cr, s.str().c_str() ); - } - // move to next line - drawY += bindYPx; - } - - //printf("done drawing\n"); - - cairo_restore( cr ); - } + if (damage() & FL_DAMAGE_ALL) { + cairo_t *cr = Fl::cairo_cc(); + cairo_save( cr ); + + cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 1 ); + cairo_set_font_size( cr, 11 ); + cairo_move_to( cr, x + 7, y+15 ); + cairo_show_text( cr, "Action:" ); + + cairo_move_to( cr, x + 140, y+15 ); + cairo_show_text( cr, "T:" ); + cairo_move_to( cr, x + 160, y+15 ); + cairo_show_text( cr, "S:" ); + + + cairo_move_to( cr, x + 200, y+15 ); + cairo_show_text( cr, "B1:" ); + cairo_move_to( cr, x + 230, y+15 ); + cairo_show_text( cr, "B2:" ); + + + int drawY = y + bindYPx; + for(unsigned int i = 0; i < binds.size(); i++) { // draw each binding + cairo_rectangle( cr, x+2, drawY, 179, 23 ); + cairo_set_source_rgba(cr, 0 / 255.f, 0 / 255.f , 0 / 255.f, 0.4); + cairo_fill(cr); + + // action + cairo_move_to( cr, x + 7, drawY+15 ); + cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 1 ); + cairo_set_font_size( cr, 11 ); + const char* action = Event::getPrettyName( binds.at(i)->action ); + if ( action ) + cairo_show_text( cr, action ); + + // track + cairo_move_to( cr, x + 140, drawY+15 ); + { + std::stringstream s; + s << binds.at(i)->track; + cairo_show_text( cr, s.str().c_str() ); + } + // scene + cairo_move_to( cr, x + 150, drawY+15 ); + { + std::stringstream s; + s << binds.at(i)->scene; + cairo_show_text( cr, s.str().c_str() ); + } + + // status + cairo_move_to( cr, x + 165, drawY+15 ); + { + std::stringstream s; + s << binds.at(i)->status; + cairo_show_text( cr, s.str().c_str() ); + } + // data + cairo_move_to( cr, x + 175, drawY+15 ); + { + std::stringstream s; + s << binds.at(i)->data; + cairo_show_text( cr, s.str().c_str() ); + } + // move to next line + drawY += bindYPx; + } + + //printf("done drawing\n"); + + cairo_restore( cr ); + } } void Bindings::add( Binding* b ) { - // FIXME: Refactor to use copy-constructor? - Binding* tmp = new Binding(); - tmp->action = b->action; - tmp->status = b->status; - tmp->data = b->data; - - tmp->active = b->active; - tmp->track = b->track; - tmp->scene = b->scene; - tmp->send = b->send; - - binds.push_back( tmp ); - - /* - int height = binds.size() * bindYPx; - printf("resize to %i, %i, %i, %i\n", x, y, w, height ); - resize( x, y, w, height ); - */ - - redraw(); + // FIXME: Refactor to use copy-constructor? + Binding* tmp = new Binding(); + tmp->action = b->action; + tmp->status = b->status; + tmp->data = b->data; + + tmp->active = b->active; + tmp->track = b->track; + tmp->scene = b->scene; + tmp->send = b->send; + + binds.push_back( tmp ); + + /* + int height = binds.size() * bindYPx; + printf("resize to %i, %i, %i, %i\n", x, y, w, height ); + resize( x, y, w, height ); + */ + + redraw(); } void Bindings::resize(int X, int Y, int W, int H) { - Fl_Widget::resize(X,Y,W,H); - x = X; - y = Y; - w = W; - h = H; - redraw(); + Fl_Widget::resize(X,Y,W,H); + x = X; + y = Y; + w = W; + h = H; + redraw(); } } // namespace Avtk diff --git a/src/avtk/bindings.h b/src/avtk/bindings.h index 246f7de..bc82a79 100644 --- a/src/avtk/bindings.h +++ b/src/avtk/bindings.h @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -31,23 +31,23 @@ namespace Avtk class Bindings : public Fl_Button { - public: - Bindings( int _x, int _y, int _w, int _h, const char *_label = 0 ); - - bool mouseOver; - bool highlight; - int x, y, w, h; - const char* label; - - void add( Binding* b ); - - void draw(); - //int handle(int event); - void resize(int X, int Y, int W, int H); - - int bindYPx; - std::vector binds; - +public: + Bindings( int _x, int _y, int _w, int _h, const char *_label = 0 ); + + bool mouseOver; + bool highlight; + int x, y, w, h; + const char* label; + + void add( Binding* b ); + + void draw(); + //int handle(int event); + void resize(int X, int Y, int W, int H); + + int bindYPx; + std::vector binds; + }; } diff --git a/src/avtk/clipselector.cxx b/src/avtk/clipselector.cxx index b6690b9..738e81a 100644 --- a/src/avtk/clipselector.cxx +++ b/src/avtk/clipselector.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -32,38 +32,36 @@ namespace Avtk ClipSelector::ClipSelector( int _x, int _y, int _w, int _h, const char *_label, bool master ) : - Fl_Button(_x, _y, _w, _h, _label) + Fl_Button(_x, _y, _w, _h, _label) { - x = _x; - y = _y; - w = _w; - h = _h; - - special = -1; - - label = _label; - _master = master; - - if ( _master ) - { - for(int i = 0; i < 10; i++ ) - { - stringstream s; - s << "Scene " << i + 1; - clips[i].setName( s.str() ); - } - - } - - highlight = false; - mouseOver = false; + x = _x; + y = _y; + w = _w; + h = _h; + + special = -1; + + label = _label; + _master = master; + + if ( _master ) { + for(int i = 0; i < 10; i++ ) { + stringstream s; + s << "Scene " << i + 1; + clips[i].setName( s.str() ); + } + + } + + highlight = false; + mouseOver = false; } void ClipSelector::setID( int id ) { - ID = id; + ID = id; } @@ -71,366 +69,320 @@ void ClipSelector::setID( int id ) void ClipSelector::setState( int clipNum, GridLogic::State s ) { #ifdef DEBUG_CLIP - //cout << "ClipSelector::setState() t = " << ID << " clipNum = " << clipNum << " state = " << s << endl; + //cout << "ClipSelector::setState() t = " << ID << " clipNum = " << clipNum << " state = " << s << endl; #endif - clips[clipNum].setState( s ); - if ( s == GridLogic::STATE_EMPTY ) - { - clips[clipNum].setName(""); - } - - redraw(); + clips[clipNum].setState( s ); + if ( s == GridLogic::STATE_EMPTY ) { + clips[clipNum].setName(""); + } + + redraw(); } std::string ClipSelector::clipName(int clip) { - return clips[clip].getName(); + return clips[clip].getName(); } void ClipSelector::clipName(int clip, std::string name) { - clips[clip].setName( name ); - redraw(); + clips[clip].setName( name ); + redraw(); } void ClipSelector::setSpecial(int scene) { - if ( special == -1 && scene == -1 ) - { - // no change - return; - } - - special = scene; - redraw(); + if ( special == -1 && scene == -1 ) { + // no change + return; + } + + special = scene; + redraw(); } void ClipSelector::draw() { - if (damage() & FL_DAMAGE_ALL) - { - if ( value() ) - { - highlight = true; - } - else - { - highlight = false; - } - - cairo_t *cr = Fl::cairo_cc(); - - cairo_save( cr ); - - int clipWidth = w - 2; - int clipHeight = (h / numClips); - - // text height adjustment based on clip size - // small 22, 13 - // start 29, 17 - //printf("clipHeight %i\n", clipHeight); - int textHeight = 13 + ((clipHeight - 22) * 0.66 ); - - - - int xOff = x+clipHeight/2; - - int drawY = y + 1; - for( int i = 0; i < numClips; i++) // draw each clip - { - int yOff = drawY+ clipHeight/2 -1; - - cairo_rectangle( cr, x+2, drawY, clipWidth-1, clipHeight - 4 ); - cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 0.4); - cairo_fill(cr); - - cairo_rectangle( cr, x+2, drawY, clipHeight-4, clipHeight - 4 ); - - if ( clips[i].getState() == GridLogic::STATE_RECORDING ) - { - cairo_set_source_rgba(cr, 1.f, 0 / 255.f , 0 / 255.f, 1.f); - cairo_fill(cr); - //cairo_arc( cr, x+14, drawY+13, 4.3, 0, 6.29 ); - cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 ); - cairo_set_source_rgba(cr, 0, 0, 0, 1.f); - cairo_fill(cr); - } - else if ( clips[i].getState() == GridLogic::STATE_PLAYING ) - { - cairo_set_source_rgba(cr, 0.0, 1.0, 0, 1.f ); - cairo_fill(cr); - cairo_move_to( cr, xOff-4, yOff-5 ); - cairo_line_to( cr, xOff+5, yOff ); - cairo_line_to( cr, xOff-4, yOff+5 ); - cairo_close_path(cr); - cairo_set_source_rgba(cr, 0, 0, 0, 1.f); - cairo_fill(cr); - } - else if ( clips[i].getState() == GridLogic::STATE_PLAY_QUEUED ) - { - cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); - cairo_fill(cr); - cairo_move_to( cr, xOff-4, yOff-5 ); - cairo_line_to( cr, xOff+5, yOff ); - cairo_line_to( cr, xOff-4, yOff +5 ); - cairo_close_path(cr); - cairo_set_source_rgba(cr, 0, 0, 0, 1.f); - cairo_fill(cr); - } - else if ( clips[i].getState() == GridLogic::STATE_STOP_QUEUED ) - { - cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); - cairo_fill(cr); - cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 ); - cairo_set_source_rgba(cr, 0, 0, 0, 1.f); - cairo_set_line_width(cr, 2.2f); - cairo_stroke(cr); - } - else if ( clips[i].getState() == GridLogic::STATE_RECORD_QUEUED ) - { - cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); - cairo_fill(cr); - cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 ); - cairo_set_source_rgba(cr, 0, 0, 0, 1.f); - cairo_fill(cr); - } - else if ( clips[i].getState() == GridLogic::STATE_STOPPED ) - { - cairo_set_source_rgba(cr, 1.0, 0.6, 0, 1.f); - cairo_fill(cr); - cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 ); - cairo_set_source_rgba(cr, 0, 0, 0, 1.f); - cairo_set_line_width(cr, 2.2f); - cairo_stroke(cr); - } - else - { - cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 1.f); - cairo_fill(cr); - } - - cairo_rectangle( cr, x+2, drawY, clipWidth -1, clipHeight - 3 ); - - float alpha = 1; - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, alpha); - cairo_set_line_width( cr, 1.3); - cairo_move_to( cr, x+clipHeight-1, drawY ); - cairo_line_to( cr, x+clipHeight-1, drawY + clipHeight - 2); - cairo_stroke(cr); - - // clip name - cairo_move_to( cr, x + clipHeight + 5, drawY + textHeight ); - cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 0.9 ); - cairo_set_font_size( cr, 11 ); - - std::string tmp = clips[i].getName().substr(0,8); - - cairo_show_text( cr, tmp.c_str() ); - - // special indicator? - if ( i == special ) - { - cairo_rectangle( cr, x+2, drawY, clipWidth -1, clipHeight - 3 ); - cairo_set_source_rgba(cr, 0.0, 153 / 255.f, 1.0, alpha); - cairo_stroke( cr ); - } - - drawY += clipHeight; - - } - - cairo_restore( cr ); - - //draw_label(); - } + if (damage() & FL_DAMAGE_ALL) { + if ( value() ) { + highlight = true; + } else { + highlight = false; + } + + cairo_t *cr = Fl::cairo_cc(); + + cairo_save( cr ); + + int clipWidth = w - 2; + int clipHeight = (h / numClips); + + // text height adjustment based on clip size + // small 22, 13 + // start 29, 17 + //printf("clipHeight %i\n", clipHeight); + int textHeight = 13 + ((clipHeight - 22) * 0.66 ); + + + + int xOff = x+clipHeight/2; + + int drawY = y + 1; + for( int i = 0; i < numClips; i++) { // draw each clip + int yOff = drawY+ clipHeight/2 -1; + + cairo_rectangle( cr, x+2, drawY, clipWidth-1, clipHeight - 4 ); + cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 0.4); + cairo_fill(cr); + + cairo_rectangle( cr, x+2, drawY, clipHeight-4, clipHeight - 4 ); + + if ( clips[i].getState() == GridLogic::STATE_RECORDING ) { + cairo_set_source_rgba(cr, 1.f, 0 / 255.f , 0 / 255.f, 1.f); + cairo_fill(cr); + //cairo_arc( cr, x+14, drawY+13, 4.3, 0, 6.29 ); + cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 ); + cairo_set_source_rgba(cr, 0, 0, 0, 1.f); + cairo_fill(cr); + } else if ( clips[i].getState() == GridLogic::STATE_PLAYING ) { + cairo_set_source_rgba(cr, 0.0, 1.0, 0, 1.f ); + cairo_fill(cr); + cairo_move_to( cr, xOff-4, yOff-5 ); + cairo_line_to( cr, xOff+5, yOff ); + cairo_line_to( cr, xOff-4, yOff+5 ); + cairo_close_path(cr); + cairo_set_source_rgba(cr, 0, 0, 0, 1.f); + cairo_fill(cr); + } else if ( clips[i].getState() == GridLogic::STATE_PLAY_QUEUED ) { + cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); + cairo_fill(cr); + cairo_move_to( cr, xOff-4, yOff-5 ); + cairo_line_to( cr, xOff+5, yOff ); + cairo_line_to( cr, xOff-4, yOff +5 ); + cairo_close_path(cr); + cairo_set_source_rgba(cr, 0, 0, 0, 1.f); + cairo_fill(cr); + } else if ( clips[i].getState() == GridLogic::STATE_STOP_QUEUED ) { + cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); + cairo_fill(cr); + cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 ); + cairo_set_source_rgba(cr, 0, 0, 0, 1.f); + cairo_set_line_width(cr, 2.2f); + cairo_stroke(cr); + } else if ( clips[i].getState() == GridLogic::STATE_RECORD_QUEUED ) { + cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); + cairo_fill(cr); + cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 ); + cairo_set_source_rgba(cr, 0, 0, 0, 1.f); + cairo_fill(cr); + } else if ( clips[i].getState() == GridLogic::STATE_STOPPED ) { + cairo_set_source_rgba(cr, 1.0, 0.6, 0, 1.f); + cairo_fill(cr); + cairo_arc( cr, xOff, yOff, 4.3, 0, 6.29 ); + cairo_set_source_rgba(cr, 0, 0, 0, 1.f); + cairo_set_line_width(cr, 2.2f); + cairo_stroke(cr); + } else { + cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 1.f); + cairo_fill(cr); + } + + cairo_rectangle( cr, x+2, drawY, clipWidth -1, clipHeight - 3 ); + + float alpha = 1; + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, alpha); + cairo_set_line_width( cr, 1.3); + cairo_move_to( cr, x+clipHeight-1, drawY ); + cairo_line_to( cr, x+clipHeight-1, drawY + clipHeight - 2); + cairo_stroke(cr); + + // clip name + cairo_move_to( cr, x + clipHeight + 5, drawY + textHeight ); + cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 0.9 ); + cairo_set_font_size( cr, 11 ); + + std::string tmp = clips[i].getName().substr(0,8); + + cairo_show_text( cr, tmp.c_str() ); + + // special indicator? + if ( i == special ) { + cairo_rectangle( cr, x+2, drawY, clipWidth -1, clipHeight - 3 ); + cairo_set_source_rgba(cr, 0.0, 153 / 255.f, 1.0, alpha); + cairo_stroke( cr ); + } + + drawY += clipHeight; + + } + + cairo_restore( cr ); + + //draw_label(); + } } void ClipSelector::resize(int X, int Y, int W, int H) { - Fl_Widget::resize(X,Y,W,H); - x = X; - y = Y; - w = W; - h = H; - redraw(); + Fl_Widget::resize(X,Y,W,H); + x = X; + y = Y; + w = W; + h = H; + redraw(); } int ClipSelector::handle(int event) { - switch(event) { - case FL_ACTIVATE: - { - } - case FL_DEACTIVATE: - { - } - return 1; - case FL_PUSH: - highlight = 1; - { - // calculate the clicked clip number - int clipHeight = (h / numClips); - int clipNum = ( (Fl::event_y() ) - y ) / clipHeight; - if (clipNum >= numClips) - clipNum = numClips -1; // fix for clicking the lowest pixel - - // handle right clicks: popup menu - if ( Fl::event_state(FL_BUTTON3) ) - { - if ( _master ) - { - // ask new name for clip, then - const char* name = fl_input( "Scene name: ", clips[clipNum].getName().c_str() ); - if ( name ) - clips[clipNum].setName( name ); - - redraw(); - return 1; - } - - - Fl_Menu_Item rclick_menu[] = - { - { "Load" }, - { "Save" }, - { "Special"}, - { "Beats", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER }, - {"1 "}, - {"2"}, - {"4"}, - {"8"}, - {"16"}, - {"32"}, - {"64"}, - {0}, - //{ "Record" }, - { "Use as tempo" }, - { "Rename", 0, 0, 0, FL_MENU_DIVIDER}, - { "Clear" }, - { 0 } - }; - Fl_Menu_Item *m = (Fl_Menu_Item*) rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0); - if ( !m ) - { - return 0; - } - else if ( strcmp(m->label(), "Load") == 0 ) - { - gui->selectLoadSample( ID, clipNum ); - } - else if ( strcmp(m->label(), "Save") == 0 ) - { - //gui->saveBufferPath = "/tmp/test.wav"; - char* tmp = gui->selectSavePath(); - if(tmp && strlen(tmp)) { - if( access( tmp, F_OK ) != -1 ) { - int overwrite = fl_choice("Overwrite file?","Cancel","Overwrite",0); - if (!overwrite) { - return 0; - } - } - gui->saveBufferPath = tmp; - free(tmp); - gui->selectSaveSample( ID, clipNum ); - } - } - else if ( strcmp(m->label(), "1 ") == 0 ) { - EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,1); - writeToDspRingbuffer( &e ); - } else if ( strcmp(m->label(), "2") == 0 ) { - EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,2); - writeToDspRingbuffer( &e ); - } else if ( strcmp(m->label(), "4") == 0 ) { - EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,4); - writeToDspRingbuffer( &e ); - } else if ( strcmp(m->label(), "8") == 0 ) { - EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,8); - writeToDspRingbuffer( &e ); - } else if ( strcmp(m->label(), "16") == 0 ) { - EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,16); - writeToDspRingbuffer( &e ); - } else if ( strcmp(m->label(), "32") == 0 ) { - EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,32); - writeToDspRingbuffer( &e ); - } else if ( strcmp(m->label(), "64") == 0 ) { - EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,64); - writeToDspRingbuffer( &e ); - } - else if ( strcmp(m->label(), "Use as tempo") == 0 ) - { - EventLooperUseAsTempo e (ID, clipNum); - writeToDspRingbuffer( &e ); - } - else if ( strcmp(m->label(), "Special") == 0 ) - { - //printf("special selected %i, %i\n", ID, clipNum ); - EventGridSelectNewChosen e( ID, clipNum); - writeToDspRingbuffer( &e ); - } - else if ( strcmp(m->label(), "Rename") == 0 ) - { - const char* name = fl_input( "Clip name: ", clips[clipNum].getName().c_str() ); - if ( name ) - clips[clipNum].setName( name ); - } - else if ( strcmp(m->label(), "Clear") == 0 ) - { - // for a clip to become 0 - EventGridState e( ID, clipNum, GridLogic::STATE_EMPTY ); - writeToDspRingbuffer( &e ); - } - } - else - { - if ( _master ) - { - EventGridLaunchScene e( clipNum ); - writeToDspRingbuffer( &e ); - redraw(); - return 1; - } - - // write "pressed" event for this track,scene - EventGridEvent e( ID, clipNum, true ); - writeToDspRingbuffer( &e ); - } - } - redraw(); - do_callback(); - return 1; - case FL_DRAG: - { - int t = Fl::event_inside(this); - if (t != highlight) - { - highlight = t; - redraw(); - } - } - return 1; - case FL_ENTER: - mouseOver = true; - - redraw(); - return 1; - case FL_LEAVE: - mouseOver = false; - redraw(); - return 1; - case FL_RELEASE: - return 1; - case FL_SHORTCUT: - if ( test_shortcut() ) - { - do_callback(); - return 1; - } - return 0; - default: - return Fl_Widget::handle(event); - } + switch(event) { + case FL_ACTIVATE: { + } + case FL_DEACTIVATE: { + } + return 1; + case FL_PUSH: + highlight = 1; + { + // calculate the clicked clip number + int clipHeight = (h / numClips); + int clipNum = ( (Fl::event_y() ) - y ) / clipHeight; + if (clipNum >= numClips) + clipNum = numClips -1; // fix for clicking the lowest pixel + + // handle right clicks: popup menu + if ( Fl::event_state(FL_BUTTON3) ) { + if ( _master ) { + // ask new name for clip, then + const char* name = fl_input( "Scene name: ", clips[clipNum].getName().c_str() ); + if ( name ) + clips[clipNum].setName( name ); + + redraw(); + return 1; + } + + + Fl_Menu_Item rclick_menu[] = { + { "Load" }, + { "Save" }, + { "Special"}, + { "Beats", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER }, + {"1 "}, + {"2"}, + {"4"}, + {"8"}, + {"16"}, + {"32"}, + {"64"}, + {0}, + //{ "Record" }, + { "Use as tempo" }, + { "Rename", 0, 0, 0, FL_MENU_DIVIDER}, + { "Clear" }, + { 0 } + }; + Fl_Menu_Item *m = (Fl_Menu_Item*) rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0); + if ( !m ) { + return 0; + } else if ( strcmp(m->label(), "Load") == 0 ) { + gui->selectLoadSample( ID, clipNum ); + } else if ( strcmp(m->label(), "Save") == 0 ) { + //gui->saveBufferPath = "/tmp/test.wav"; + char* tmp = gui->selectSavePath(); + if(tmp && strlen(tmp)) { + if( access( tmp, F_OK ) != -1 ) { + int overwrite = fl_choice("Overwrite file?","Cancel","Overwrite",0); + if (!overwrite) { + return 0; + } + } + gui->saveBufferPath = tmp; + free(tmp); + gui->selectSaveSample( ID, clipNum ); + } + } else if ( strcmp(m->label(), "1 ") == 0 ) { + EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,1); + writeToDspRingbuffer( &e ); + } else if ( strcmp(m->label(), "2") == 0 ) { + EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,2); + writeToDspRingbuffer( &e ); + } else if ( strcmp(m->label(), "4") == 0 ) { + EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,4); + writeToDspRingbuffer( &e ); + } else if ( strcmp(m->label(), "8") == 0 ) { + EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,8); + writeToDspRingbuffer( &e ); + } else if ( strcmp(m->label(), "16") == 0 ) { + EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,16); + writeToDspRingbuffer( &e ); + } else if ( strcmp(m->label(), "32") == 0 ) { + EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,32); + writeToDspRingbuffer( &e ); + } else if ( strcmp(m->label(), "64") == 0 ) { + EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,64); + writeToDspRingbuffer( &e ); + } else if ( strcmp(m->label(), "Use as tempo") == 0 ) { + EventLooperUseAsTempo e (ID, clipNum); + writeToDspRingbuffer( &e ); + } else if ( strcmp(m->label(), "Special") == 0 ) { + //printf("special selected %i, %i\n", ID, clipNum ); + EventGridSelectNewChosen e( ID, clipNum); + writeToDspRingbuffer( &e ); + } else if ( strcmp(m->label(), "Rename") == 0 ) { + const char* name = fl_input( "Clip name: ", clips[clipNum].getName().c_str() ); + if ( name ) + clips[clipNum].setName( name ); + } else if ( strcmp(m->label(), "Clear") == 0 ) { + // for a clip to become 0 + EventGridState e( ID, clipNum, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + } + } else { + if ( _master ) { + EventGridLaunchScene e( clipNum ); + writeToDspRingbuffer( &e ); + redraw(); + return 1; + } + + // write "pressed" event for this track,scene + EventGridEvent e( ID, clipNum, true ); + writeToDspRingbuffer( &e ); + } + } + redraw(); + do_callback(); + return 1; + case FL_DRAG: { + int t = Fl::event_inside(this); + if (t != highlight) { + highlight = t; + redraw(); + } + } + return 1; + case FL_ENTER: + mouseOver = true; + + redraw(); + return 1; + case FL_LEAVE: + mouseOver = false; + redraw(); + return 1; + case FL_RELEASE: + return 1; + case FL_SHORTCUT: + if ( test_shortcut() ) { + do_callback(); + return 1; + } + return 0; + default: + return Fl_Widget::handle(event); + } } } // Avtk diff --git a/src/avtk/clipselector.hxx b/src/avtk/clipselector.hxx index 282e5a9..1b688f2 100644 --- a/src/avtk/clipselector.hxx +++ b/src/avtk/clipselector.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -38,73 +38,73 @@ namespace Avtk class ClipState { - public: - ClipState() : - state(GridLogic::STATE_EMPTY), - name("") - {} - - void setName(std::string n) - { - name = n; - } - - void setState(GridLogic::State s) - { - state = s; - } - - std::string getName() - { - return name; - } - - GridLogic::State getState() - { - return state; - } - - private: - GridLogic::State state; - std::string name; +public: + ClipState() : + state(GridLogic::STATE_EMPTY), + name("") + {} + + void setName(std::string n) + { + name = n; + } + + void setState(GridLogic::State s) + { + state = s; + } + + std::string getName() + { + return name; + } + + GridLogic::State getState() + { + return state; + } + +private: + GridLogic::State state; + std::string name; }; class ClipSelector : public Fl_Button { - public: - ClipSelector( int _x, int _y, int _w, int _h, - const char *_label, bool master = false); - - int ID; - - // FIXME: NSCENES? - static const int numClips = 10; - ClipState clips[numClips]; - - /// indicates if a clip is the "special" clip - void setSpecial(int scene); - int special; - - bool _master; - bool mouseOver; - bool highlight; - int x, y, w, h; - const char* label; - - void setID( int id ); - - /** 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, GridLogic::State s ); - - void clipName(int clip, std::string name); - std::string clipName(int clip); - - void draw(); - int handle(int event); - - void resize(int X, int Y, int W, int H); +public: + ClipSelector( int _x, int _y, int _w, int _h, + const char *_label, bool master = false); + + int ID; + + // FIXME: NSCENES? + static const int numClips = 10; + ClipState clips[numClips]; + + /// indicates if a clip is the "special" clip + void setSpecial(int scene); + int special; + + bool _master; + bool mouseOver; + bool highlight; + int x, y, w, h; + const char* label; + + void setID( int id ); + + /** 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, GridLogic::State s ); + + void clipName(int clip, std::string name); + std::string clipName(int clip); + + void draw(); + int handle(int event); + + void resize(int X, int Y, int W, int H); }; } // Avtk diff --git a/src/avtk/volume.cxx b/src/avtk/volume.cxx index 4b9a340..9a3deda 100644 --- a/src/avtk/volume.cxx +++ b/src/avtk/volume.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -21,218 +21,206 @@ using namespace Avtk; Volume::Volume(int _x, int _y, int _w, int _h, const char *_label ): - Fl_Slider(_x, _y, _w, _h, _label) + Fl_Slider(_x, _y, _w, _h, _label) { - x = _x; - y = _y; - w = _w; - h = _h; - - label = _label; - - mouseClickedX = 0; - mouseClickedY = 0; - mouseClicked = false; - - active = true; - highlight = false; - - ampL = 0; - ampR = 0; - compress = 0; - value( 0.78f ); + x = _x; + y = _y; + w = _w; + h = _h; - orientationHorizontal = false; + label = _label; + + mouseClickedX = 0; + mouseClickedY = 0; + mouseClicked = false; + + active = true; + highlight = false; + + ampL = 0; + ampR = 0; + compress = 0; + value( 0.78f ); + + orientationHorizontal = false; } void Volume::fader( float f ) { - // redraw on larger value change - //if ( fabsf( value() - f ) > 0.025 ) - value( f ); + // redraw on larger value change + //if ( fabsf( value() - f ) > 0.025 ) + value( f ); } void Volume::amplitude (float aL, float aR) { - if ( aL < 0.1 ) aL = 0.f; - if ( aR < 0.1 ) aR = 0.f; - - // only redraw if changed more than X amount - if ( fabsf(ampL - aL) > 0.025 || - fabsf(ampR - aR) > 0.025 ) - { - ampL = aL; - ampR = aR; - redraw(); - } + if ( aL < 0.1 ) aL = 0.f; + if ( aR < 0.1 ) aR = 0.f; + + // only redraw if changed more than X amount + if ( fabsf(ampL - aL) > 0.025 || + fabsf(ampR - aR) > 0.025 ) { + ampL = aL; + ampR = aR; + redraw(); + } } void Volume::compression(float c) { - compress = c; - redraw(); + compress = c; + redraw(); } void Volume::setOrientationHorizontal() { - orientationHorizontal = true; - redraw(); + orientationHorizontal = true; + redraw(); } void Volume::set_active(bool a) { - active = a; - redraw(); + active = a; + redraw(); } void Volume::draw() { - if (damage() & FL_DAMAGE_ALL) - { - cairo_t *cr = Fl::cairo_cc(); - - cairo_save( cr ); - - cairo_set_line_width(cr, 1.5); - - // fill background - cairo_rectangle( cr, x, y, w, h); - cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 0.4); - //cairo_set_source_rgb( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f ); - cairo_fill( cr ); - - //cairo_set_dash ( cr, dashes, 1, 0.0); - cairo_set_line_width( cr, 1.0); - - // loop over each 2nd line, drawing dots - cairo_set_line_width(cr, 1.0); - cairo_set_source_rgb(cr, 0.4,0.4,0.4); - for ( int i = 0; i < 2; i++ ) - { - cairo_move_to( cr, x + ((w / 2.f)*i), y ); - cairo_line_to( cr, x + ((w / 2.f)*i), y + h ); - } - for ( int i = 0; i < 4; i++ ) - { - cairo_move_to( cr, x , y + ((h / 4.f)*i) ); - cairo_line_to( cr, x + w, y + ((h / 4.f)*i) ); - } - - cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 ); - cairo_stroke(cr); - //cairo_set_dash ( cr, dashes, 0, 0.0); - - - // audio level - if ( orientationHorizontal ) - { - cairo_rectangle(cr, x, y+h*0.15, w * ampL, 9.9 ); - cairo_rectangle(cr, x, y+h*0.56, w * ampR, 9.9 ); - } - else - { - cairo_rectangle(cr, x+w*0.15, y+h*(1-ampL), 9.9, h - h*(1-ampL) ); - cairo_rectangle(cr, x+w*0.56, y+h*(1-ampR), 9.9, h - h*(1-ampR) ); - } - cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 ); - cairo_fill_preserve( cr ); - cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); - cairo_stroke(cr); - - // fader - if ( orientationHorizontal ) - cairo_rectangle(cr, x+2+(w-24)*(value()), y+5, 20, h-10); - else - cairo_rectangle(cr, x+5, y+2+(h-24)*(1-value()), w-10, 20); - - cairo_set_source_rgba( cr, 1.0f, 0.48, 0.f, 1); - cairo_set_line_width(cr, 1.9); - cairo_stroke( cr ); - - // stroke outline - cairo_rectangle(cr, x, y, w, h); - cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); - cairo_set_line_width(cr, 1.9); - cairo_stroke( cr ); - - cairo_restore( cr ); - } + if (damage() & FL_DAMAGE_ALL) { + cairo_t *cr = Fl::cairo_cc(); + + cairo_save( cr ); + + cairo_set_line_width(cr, 1.5); + + // fill background + cairo_rectangle( cr, x, y, w, h); + cairo_set_source_rgba(cr, 66 / 255.f, 66 / 255.f , 66 / 255.f, 0.4); + //cairo_set_source_rgb( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f ); + cairo_fill( cr ); + + //cairo_set_dash ( cr, dashes, 1, 0.0); + cairo_set_line_width( cr, 1.0); + + // loop over each 2nd line, drawing dots + cairo_set_line_width(cr, 1.0); + cairo_set_source_rgb(cr, 0.4,0.4,0.4); + for ( int i = 0; i < 2; i++ ) { + cairo_move_to( cr, x + ((w / 2.f)*i), y ); + cairo_line_to( cr, x + ((w / 2.f)*i), y + h ); + } + for ( int i = 0; i < 4; i++ ) { + cairo_move_to( cr, x , y + ((h / 4.f)*i) ); + cairo_line_to( cr, x + w, y + ((h / 4.f)*i) ); + } + + cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 ); + cairo_stroke(cr); + //cairo_set_dash ( cr, dashes, 0, 0.0); + + + // audio level + if ( orientationHorizontal ) { + cairo_rectangle(cr, x, y+h*0.15, w * ampL, 9.9 ); + cairo_rectangle(cr, x, y+h*0.56, w * ampR, 9.9 ); + } else { + cairo_rectangle(cr, x+w*0.15, y+h*(1-ampL), 9.9, h - h*(1-ampL) ); + cairo_rectangle(cr, x+w*0.56, y+h*(1-ampR), 9.9, h - h*(1-ampR) ); + } + cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 ); + cairo_fill_preserve( cr ); + cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 ); + cairo_stroke(cr); + + // fader + if ( orientationHorizontal ) + cairo_rectangle(cr, x+2+(w-24)*(value()), y+5, 20, h-10); + else + cairo_rectangle(cr, x+5, y+2+(h-24)*(1-value()), w-10, 20); + + cairo_set_source_rgba( cr, 1.0f, 0.48, 0.f, 1); + cairo_set_line_width(cr, 1.9); + cairo_stroke( cr ); + + // stroke outline + cairo_rectangle(cr, x, y, w, h); + cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); + cairo_set_line_width(cr, 1.9); + cairo_stroke( cr ); + + cairo_restore( cr ); + } } void Volume::resize(int X, int Y, int W, int H) { - Fl_Widget::resize(X,Y,W,H); - x = X; - y = Y; - w = W; - h = H; - redraw(); + Fl_Widget::resize(X,Y,W,H); + x = X; + y = Y; + w = W; + h = H; + redraw(); } int Volume::handle(int event) { - switch(event) - { - case FL_PUSH: - highlight = 0; - redraw(); - return 1; - case FL_DRAG: - { - if ( Fl::event_state(FL_BUTTON1) ) - { - if ( mouseClicked == false ) // catch the "click" event - { - mouseClickedX = Fl::event_x(); - mouseClickedY = Fl::event_y(); - mouseClicked = true; - } - - float delta = (mouseClickedY - Fl::event_y() ) / float(h); - // handle the x / y swap, and the inverting of direction (mouseX / Y relative) - if ( orientationHorizontal ) - delta = ( Fl::event_x() - mouseClickedX ) / float(w); - - float valY = value(); - valY += delta; - - if ( valY > 1.0 ) valY = 1.0; - if ( valY < 0.0 ) valY = 0.0; - - set_value( valY ); - - mouseClickedX = Fl::event_x(); - mouseClickedY = Fl::event_y(); - redraw(); - do_callback(); - } - } - return 1; - case FL_ENTER: - return 1; - case FL_MOUSEWHEEL: - //printf("no scroll on faders\n"); - return 1; - case FL_RELEASE: - if (highlight) { - highlight = 0; - redraw(); - do_callback(); - } - mouseClicked = false; - return 1; - case FL_SHORTCUT: - if ( test_shortcut() ) - { - do_callback(); - return 1; - } - return 0; - default: - return Fl_Widget::handle(event); - } + switch(event) { + case FL_PUSH: + highlight = 0; + redraw(); + return 1; + case FL_DRAG: { + if ( Fl::event_state(FL_BUTTON1) ) { + if ( mouseClicked == false ) { // catch the "click" event + mouseClickedX = Fl::event_x(); + mouseClickedY = Fl::event_y(); + mouseClicked = true; + } + + float delta = (mouseClickedY - Fl::event_y() ) / float(h); + // handle the x / y swap, and the inverting of direction (mouseX / Y relative) + if ( orientationHorizontal ) + delta = ( Fl::event_x() - mouseClickedX ) / float(w); + + float valY = value(); + valY += delta; + + if ( valY > 1.0 ) valY = 1.0; + if ( valY < 0.0 ) valY = 0.0; + + set_value( valY ); + + mouseClickedX = Fl::event_x(); + mouseClickedY = Fl::event_y(); + redraw(); + do_callback(); + } + } + return 1; + case FL_ENTER: + return 1; + case FL_MOUSEWHEEL: + //printf("no scroll on faders\n"); + return 1; + case FL_RELEASE: + if (highlight) { + highlight = 0; + redraw(); + do_callback(); + } + mouseClicked = false; + return 1; + case FL_SHORTCUT: + if ( test_shortcut() ) { + do_callback(); + return 1; + } + return 0; + default: + return Fl_Widget::handle(event); + } } diff --git a/src/avtk/volume.hxx b/src/avtk/volume.hxx index fc00493..ae592d0 100644 --- a/src/avtk/volume.hxx +++ b/src/avtk/volume.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -28,39 +28,39 @@ namespace Avtk { - class Volume : public Fl_Slider - { - public: - Volume(int _x, int _y, int _w, int _h, const char *_label = 0); - - void set_active(bool a); - void setOrientationHorizontal(); - - void fader( float f ); - void compression(float c); - void amplitude (float aL, float aR); - - void draw(); - int handle(int event); - - void resize(int X, int Y, int W, int H); - - - private: - bool active; - bool highlight; - bool orientationHorizontal; - - int x, y, w, h; - const char* label; - - int mouseClickedX; - int mouseClickedY; - bool mouseClicked; - - float ampL, ampR; - float compress; - }; +class Volume : public Fl_Slider +{ +public: + Volume(int _x, int _y, int _w, int _h, const char *_label = 0); + + void set_active(bool a); + void setOrientationHorizontal(); + + void fader( float f ); + void compression(float c); + void amplitude (float aL, float aR); + + void draw(); + int handle(int event); + + void resize(int X, int Y, int W, int H); + + +private: + bool active; + bool highlight; + bool orientationHorizontal; + + int x, y, w, h; + const char* label; + + int mouseClickedX; + int mouseClickedY; + bool mouseClicked; + + float ampL, ampR; + float compress; +}; } // Avtk #endif // AVTK_VOLUME_H diff --git a/src/avtk/waveform.h b/src/avtk/waveform.h index d0810fd..32cca90 100644 --- a/src/avtk/waveform.h +++ b/src/avtk/waveform.h @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -33,276 +33,259 @@ namespace Avtk class Waveform : public Fl_Widget { - public: - Waveform(int _x, int _y, int _w, int _h, const char *_label=0 ): - Fl_Widget(_x, _y, _w, _h, _label) - { - x = _x; - y = _y; - w = _w; - h = _h; - - label = _label; - - highlight = false; - newWaveform = false; - - waveformCr = 0; - waveformSurf = 0; - - - data = (float*)malloc( sizeof(float) * w ); - - srand (time(NULL)); - - for (int i = 0; i < _w; i++) - { - data[i] = rand() / RAND_MAX / 0.75; - } - - newWaveform = true; - - strokeRim = true; - } - - bool strokeRim; - bool highlight; - int x, y, w, h; - const char* label; - - cairo_t* waveformCr; - cairo_surface_t* waveformSurf; - - bool newWaveform; - - long dataSize; - float* data; - - void setData( float* d, long size ) - { - //cout << "AvtkWaveform: setDataPtr = " << data << endl; - dataSize = size; - data = d; - newWaveform = true; - - - damage(FL_DAMAGE_ALL); - } - - void draw() - { - if (damage() & FL_DAMAGE_ALL) - { - cairo_t *cr = Fl::cairo_cc(); - cairo_save(cr); - - // clear the surface - cairo_rectangle(cr, x, y, w, h); - cairo_set_source_rgb (cr, 0.1,0.1,0.1); - cairo_fill( cr ); - - if ( newWaveform ) - { - if ( !waveformCr ) - { - // create the waveform surface and context - //cout << "waveform draw() creating new objects" << endl; - waveformSurf= cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, w, h); - waveformCr = cairo_create ( waveformSurf ); - //cout << "waveform draw() creating objects done" << endl; - } - - // clear the surface - cairo_rectangle(waveformCr, 0, 0, w, h); - cairo_set_source_rgb (waveformCr, 0.1,0.1,0.1); - cairo_fill( waveformCr ); - - // set up dashed lines, 1 px off, 1 px on - double dashes[1]; - dashes[0] = 2.0; - - cairo_set_dash ( waveformCr, dashes, 1, 0.0); - cairo_set_line_width( waveformCr, 1.0); - - // loop over each 2nd line, drawing dots - cairo_set_line_width(waveformCr, 1.0); - cairo_set_source_rgb(waveformCr, 0.4,0.4,0.4); - for ( int i = 1; i < 4; i++ ) - { - cairo_move_to( waveformCr, ((w / 4.f)*i), 0); - cairo_line_to( waveformCr, ((w / 4.f)*i), h ); - } - for ( int i = 1; i < 4; i++ ) - { - cairo_move_to( waveformCr, 0, ((h / 4.f)*i) ); - cairo_line_to( waveformCr, w, ((h / 4.f)*i) ); - } - - cairo_set_source_rgba( waveformCr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 ); - cairo_stroke(waveformCr); - cairo_set_dash ( waveformCr, dashes, 0, 0.0); - - - if ( !data ) - { - // draw X - cairo_move_to( cr, 0 , 0 ); - cairo_line_to( cr, 0 + w, 0 + h ); - cairo_move_to( cr, 0 , 0 + h ); - cairo_line_to( cr, 0 + w, 0 ); - cairo_set_source_rgb ( cr, 0.2,0.2,0.2); - cairo_stroke(cr); - - // draw text - cairo_move_to( cr, 0 + (w/2.f) - 65, 0 + (h/2.f) + 10 ); - cairo_set_source_rgb ( cr, 0.6,0.6,0.6); - cairo_set_font_size( cr, 20 ); - cairo_show_text( cr, "No data loaded" ); - } - else - { - // don't draw every sample - int sampleCountForDrawing = -1; - - float currentTop = 0.f; - float previousTop = 0.f; - float currentSample = 0.f; - - // find how many samples per pixel - int samplesPerPix = int(dataSize / float(w)); - //cout << "width = " << w << " sampsPerPx " << samplesPerPix << endl; - - // loop over each pixel value we need - for( int p = 0; p < w; p++ ) - { - float averageMax = 0.f; - float averageMin = 0.f; - - // calc value for this pixel - for( int i = 0; i < samplesPerPix; i++ ) - { - float tmp = data[i + (p * samplesPerPix)]; - if ( tmp < 0 ) - { - averageMin -= tmp; - } - else - { - averageMax += tmp; - } - } - - // - 0.1 to keep in bounds of square - averageMin = (averageMin / samplesPerPix); - averageMax = (averageMax / samplesPerPix); - - // don't use to the *very* top of the widget, only 0.8 (top & bottom) - float dH = h * 0.4; - - // emulate log shape - float tmpMin = log( 0.1 + (averageMin*4.9) ); - float tmpMax = log( 0.1 + (averageMax*4.9) ); - - // logMin range == -2.3 -> 1.6: add 2.3, then / 3.9 - float logMin = -((tmpMin + 2.3) / 3.9); - float logMax = ((tmpMax + 2.3) / 3.9); - - //printf("input %f, output %f\n", averageMin, logMin ); - - // draw lines - cairo_move_to( waveformCr, p, h * 0.5 + (logMin * dH ) ); - cairo_line_to( waveformCr, p, h * 0.5 + (logMax * dH ) ); - } - - // stroke the waveform - cairo_set_source_rgb( waveformCr, 1.0,1.0,1.0); - cairo_stroke( waveformCr ); - - newWaveform = false; - } - } - - cairo_set_source_surface(cr, waveformSurf, x, y); - cairo_rectangle( cr, x, y, w, h); - cairo_paint(cr); - - if ( strokeRim ) - { - // stroke rim - cairo_set_line_width(cr, 1); - cairo_rectangle(cr, x, y, w, h); - cairo_set_source_rgba( cr, 100 / 255.f, 100 / 255.f , 100 / 255.f , 1 ); - cairo_stroke( cr ); - } - - //cout << "waveform draw() done" << endl; - - cairo_restore(cr); - } - } - - void resize(int X, int Y, int W, int H) - { - Fl_Widget::resize(X,Y,W,H); - - // take the smaller value - long newSize = W > w ? W : w; - printf("Waveform new size %li, from %i\n", newSize, w ); - - x = X; - y = Y; - w = W; - h = H; - - // FIXME: needs to be resampled, not clipped at end - // delete old data, and resize it - float* newData = (float*)malloc( sizeof(float) * w ); - - memcpy( newData, data, newSize ); - free ( data ); - data = newData; - - newWaveform = true; - - - redraw(); - } - - int handle(int event) - { - return 0; - - switch(event) - { - case FL_PUSH: - highlight = 0; - redraw(); - return 1; - case FL_DRAG: { - int t = Fl::event_inside(this); - if (t != highlight) { - redraw(); - } - } - return 1; - case FL_RELEASE: - if (highlight) { - highlight = 0; - redraw(); - do_callback(); - } - return 1; - case FL_SHORTCUT: - if ( test_shortcut() ) - { - do_callback(); - return 1; - } - return 0; - default: - return Fl_Widget::handle(event); - } - } +public: + Waveform(int _x, int _y, int _w, int _h, const char *_label=0 ): + Fl_Widget(_x, _y, _w, _h, _label) + { + x = _x; + y = _y; + w = _w; + h = _h; + + label = _label; + + highlight = false; + newWaveform = false; + + waveformCr = 0; + waveformSurf = 0; + + + data = (float*)malloc( sizeof(float) * w ); + + srand (time(NULL)); + + for (int i = 0; i < _w; i++) { + data[i] = rand() / RAND_MAX / 0.75; + } + + newWaveform = true; + + strokeRim = true; + } + + bool strokeRim; + bool highlight; + int x, y, w, h; + const char* label; + + cairo_t* waveformCr; + cairo_surface_t* waveformSurf; + + bool newWaveform; + + long dataSize; + float* data; + + void setData( float* d, long size ) + { + //cout << "AvtkWaveform: setDataPtr = " << data << endl; + dataSize = size; + data = d; + newWaveform = true; + + + damage(FL_DAMAGE_ALL); + } + + void draw() + { + if (damage() & FL_DAMAGE_ALL) { + cairo_t *cr = Fl::cairo_cc(); + cairo_save(cr); + + // clear the surface + cairo_rectangle(cr, x, y, w, h); + cairo_set_source_rgb (cr, 0.1,0.1,0.1); + cairo_fill( cr ); + + if ( newWaveform ) { + if ( !waveformCr ) { + // create the waveform surface and context + //cout << "waveform draw() creating new objects" << endl; + waveformSurf= cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, w, h); + waveformCr = cairo_create ( waveformSurf ); + //cout << "waveform draw() creating objects done" << endl; + } + + // clear the surface + cairo_rectangle(waveformCr, 0, 0, w, h); + cairo_set_source_rgb (waveformCr, 0.1,0.1,0.1); + cairo_fill( waveformCr ); + + // set up dashed lines, 1 px off, 1 px on + double dashes[1]; + dashes[0] = 2.0; + + cairo_set_dash ( waveformCr, dashes, 1, 0.0); + cairo_set_line_width( waveformCr, 1.0); + + // loop over each 2nd line, drawing dots + cairo_set_line_width(waveformCr, 1.0); + cairo_set_source_rgb(waveformCr, 0.4,0.4,0.4); + for ( int i = 1; i < 4; i++ ) { + cairo_move_to( waveformCr, ((w / 4.f)*i), 0); + cairo_line_to( waveformCr, ((w / 4.f)*i), h ); + } + for ( int i = 1; i < 4; i++ ) { + cairo_move_to( waveformCr, 0, ((h / 4.f)*i) ); + cairo_line_to( waveformCr, w, ((h / 4.f)*i) ); + } + + cairo_set_source_rgba( waveformCr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 ); + cairo_stroke(waveformCr); + cairo_set_dash ( waveformCr, dashes, 0, 0.0); + + + if ( !data ) { + // draw X + cairo_move_to( cr, 0 , 0 ); + cairo_line_to( cr, 0 + w, 0 + h ); + cairo_move_to( cr, 0 , 0 + h ); + cairo_line_to( cr, 0 + w, 0 ); + cairo_set_source_rgb ( cr, 0.2,0.2,0.2); + cairo_stroke(cr); + + // draw text + cairo_move_to( cr, 0 + (w/2.f) - 65, 0 + (h/2.f) + 10 ); + cairo_set_source_rgb ( cr, 0.6,0.6,0.6); + cairo_set_font_size( cr, 20 ); + cairo_show_text( cr, "No data loaded" ); + } else { + // don't draw every sample + int sampleCountForDrawing = -1; + + float currentTop = 0.f; + float previousTop = 0.f; + float currentSample = 0.f; + + // find how many samples per pixel + int samplesPerPix = int(dataSize / float(w)); + //cout << "width = " << w << " sampsPerPx " << samplesPerPix << endl; + + // loop over each pixel value we need + for( int p = 0; p < w; p++ ) { + float averageMax = 0.f; + float averageMin = 0.f; + + // calc value for this pixel + for( int i = 0; i < samplesPerPix; i++ ) { + float tmp = data[i + (p * samplesPerPix)]; + if ( tmp < 0 ) { + averageMin -= tmp; + } else { + averageMax += tmp; + } + } + + // - 0.1 to keep in bounds of square + averageMin = (averageMin / samplesPerPix); + averageMax = (averageMax / samplesPerPix); + + // don't use to the *very* top of the widget, only 0.8 (top & bottom) + float dH = h * 0.4; + + // emulate log shape + float tmpMin = log( 0.1 + (averageMin*4.9) ); + float tmpMax = log( 0.1 + (averageMax*4.9) ); + + // logMin range == -2.3 -> 1.6: add 2.3, then / 3.9 + float logMin = -((tmpMin + 2.3) / 3.9); + float logMax = ((tmpMax + 2.3) / 3.9); + + //printf("input %f, output %f\n", averageMin, logMin ); + + // draw lines + cairo_move_to( waveformCr, p, h * 0.5 + (logMin * dH ) ); + cairo_line_to( waveformCr, p, h * 0.5 + (logMax * dH ) ); + } + + // stroke the waveform + cairo_set_source_rgb( waveformCr, 1.0,1.0,1.0); + cairo_stroke( waveformCr ); + + newWaveform = false; + } + } + + cairo_set_source_surface(cr, waveformSurf, x, y); + cairo_rectangle( cr, x, y, w, h); + cairo_paint(cr); + + if ( strokeRim ) { + // stroke rim + cairo_set_line_width(cr, 1); + cairo_rectangle(cr, x, y, w, h); + cairo_set_source_rgba( cr, 100 / 255.f, 100 / 255.f , 100 / 255.f , 1 ); + cairo_stroke( cr ); + } + + //cout << "waveform draw() done" << endl; + + cairo_restore(cr); + } + } + + void resize(int X, int Y, int W, int H) + { + Fl_Widget::resize(X,Y,W,H); + + // take the smaller value + long newSize = W > w ? W : w; + printf("Waveform new size %li, from %i\n", newSize, w ); + + x = X; + y = Y; + w = W; + h = H; + + // FIXME: needs to be resampled, not clipped at end + // delete old data, and resize it + float* newData = (float*)malloc( sizeof(float) * w ); + + memcpy( newData, data, newSize ); + free ( data ); + data = newData; + + newWaveform = true; + + + redraw(); + } + + int handle(int event) + { + return 0; + + switch(event) { + case FL_PUSH: + highlight = 0; + redraw(); + return 1; + case FL_DRAG: { + int t = Fl::event_inside(this); + if (t != highlight) { + redraw(); + } + } + return 1; + case FL_RELEASE: + if (highlight) { + highlight = 0; + redraw(); + do_callback(); + } + return 1; + case FL_SHORTCUT: + if ( test_shortcut() ) { + do_callback(); + return 1; + } + return 0; + default: + return Fl_Widget::handle(event); + } + } }; } // Avtk diff --git a/src/buffers.hxx b/src/buffers.hxx index 0469263..1e2342e 100644 --- a/src/buffers.hxx +++ b/src/buffers.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -24,91 +24,91 @@ class Buffers { - public: - - enum BUFFER { - // AUDIO - MASTER_INPUT = 0, - - MASTER_OUT_L, - MASTER_OUT_R, - - JACK_SEND_OUT, - JACK_MASTER_OUT_L, - JACK_MASTER_OUT_R, - JACK_SIDECHAIN_KEY, - JACK_SIDECHAIN_SIGNAL, - - SEND, - SIDECHAIN_KEY, - SIDECHAIN_SIGNAL, - - MASTER_RETURN_L, - MASTER_RETURN_R, - - HEADPHONES_OUT, - - // MIDI - MASTER_MIDI_INPUT, - - // track buffers: they are the "working" buffers per track: - // the end result is mixed into the master output, while each - // stage along the way the amplitude etc can be analysed - TRACK_0, - TRACK_1, - TRACK_2, - TRACK_3, - TRACK_4, - TRACK_5, - TRACK_6, - TRACK_7, - //Per track sends/returns - SEND_TRACK_0, - SEND_TRACK_1, - SEND_TRACK_2, - SEND_TRACK_3, - SEND_TRACK_4, - SEND_TRACK_5, - SEND_TRACK_6, - SEND_TRACK_7, - RETURN_TRACK_0, - RETURN_TRACK_1, - RETURN_TRACK_2, - RETURN_TRACK_3, - RETURN_TRACK_4, - RETURN_TRACK_5, - RETURN_TRACK_6, - RETURN_TRACK_7, +public: - JACK_TRACK_0, - JACK_TRACK_1, - JACK_TRACK_2, - JACK_TRACK_3, - JACK_TRACK_4, - JACK_TRACK_5, - JACK_TRACK_6, - JACK_TRACK_7, + enum BUFFER { + // AUDIO + MASTER_INPUT = 0, + + MASTER_OUT_L, + MASTER_OUT_R, + + JACK_SEND_OUT, + JACK_MASTER_OUT_L, + JACK_MASTER_OUT_R, + JACK_SIDECHAIN_KEY, + JACK_SIDECHAIN_SIGNAL, + + SEND, + SIDECHAIN_KEY, + SIDECHAIN_SIGNAL, + + MASTER_RETURN_L, + MASTER_RETURN_R, + + HEADPHONES_OUT, + + // MIDI + MASTER_MIDI_INPUT, + + // track buffers: they are the "working" buffers per track: + // the end result is mixed into the master output, while each + // stage along the way the amplitude etc can be analysed + TRACK_0, + TRACK_1, + TRACK_2, + TRACK_3, + TRACK_4, + TRACK_5, + TRACK_6, + TRACK_7, + //Per track sends/returns + SEND_TRACK_0, + SEND_TRACK_1, + SEND_TRACK_2, + SEND_TRACK_3, + SEND_TRACK_4, + SEND_TRACK_5, + SEND_TRACK_6, + SEND_TRACK_7, + RETURN_TRACK_0, + RETURN_TRACK_1, + RETURN_TRACK_2, + RETURN_TRACK_3, + RETURN_TRACK_4, + RETURN_TRACK_5, + RETURN_TRACK_6, + RETURN_TRACK_7, + + JACK_TRACK_0, + JACK_TRACK_1, + JACK_TRACK_2, + JACK_TRACK_3, + JACK_TRACK_4, + JACK_TRACK_5, + JACK_TRACK_6, + JACK_TRACK_7, + + + BUFFER_COUNT, + }; + + Buffers() + { + memset( audio, 0, sizeof(float*)*BUFFER_COUNT); + memset( midi , 0, sizeof(void *)*BUFFER_COUNT); + } + float* audio[BUFFER_COUNT]; + void* midi [BUFFER_COUNT]; + + // Jack details + jack_nframes_t nframes; + jack_nframes_t samplerate; + + jack_nframes_t transportFrame; + jack_position_t* transportPosition; + jack_transport_state_t* transportState; - - BUFFER_COUNT, - }; - - Buffers() - { - memset( audio, 0, sizeof(float*)*BUFFER_COUNT); - memset( midi , 0, sizeof(void *)*BUFFER_COUNT); - } - float* audio[BUFFER_COUNT]; - void* midi [BUFFER_COUNT]; - - // Jack details - jack_nframes_t nframes; - jack_nframes_t samplerate; - - jack_nframes_t transportFrame; - jack_position_t* transportPosition; - jack_transport_state_t* transportState; - }; #endif // LUPPP_BUFFERS_H diff --git a/src/config.hxx b/src/config.hxx index 6469cc4..bc035ab 100644 --- a/src/config.hxx +++ b/src/config.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ diff --git a/src/controller/binding.hxx b/src/controller/binding.hxx index 286a22c..19958c5 100644 --- a/src/controller/binding.hxx +++ b/src/controller/binding.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -27,32 +27,35 @@ typedef int LupppAction; class Binding { - public: - Binding() : status(0), data(0), action(0), active(-1), - track(-2),scene(-1),send(-1) { ID = privateID++; } - - int ID; - - unsigned char status; - unsigned char data; - - /// the action this binding relates to: this is an integer based on the - /// event.hxx enumeration of event types - LupppAction action; - - /// arguments to the event: track number, scene number etc - int active; - int track; - int scene; - int send; - - /// maps from Gridlogic::State to MIDI output value from binding - std::map clipStateMap; - - private: - /// static int counter to allow deleting this specific instance - static int privateID; - +public: + Binding() : status(0), data(0), action(0), active(-1), + track(-2),scene(-1),send(-1) + { + ID = privateID++; + } + + int ID; + + unsigned char status; + unsigned char data; + + /// the action this binding relates to: this is an integer based on the + /// event.hxx enumeration of event types + LupppAction action; + + /// arguments to the event: track number, scene number etc + int active; + int track; + int scene; + int send; + + /// maps from Gridlogic::State to MIDI output value from binding + std::map clipStateMap; + +private: + /// static int counter to allow deleting this specific instance + static int privateID; + }; #endif diff --git a/src/controller/controller.cxx b/src/controller/controller.cxx index a25e5b9..66f9730 100644 --- a/src/controller/controller.cxx +++ b/src/controller/controller.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -29,7 +29,7 @@ int Controller::privateID = 0; Controller::Controller() { - ID = privateID++; + ID = privateID++; } void Controller::reset() @@ -38,5 +38,5 @@ void Controller::reset() int Controller::getID() { - return ID; + return ID; } diff --git a/src/controller/controller.hxx b/src/controller/controller.hxx index cb6b36e..21f1217 100644 --- a/src/controller/controller.hxx +++ b/src/controller/controller.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -31,66 +31,72 @@ **/ class Controller { - public: - /// used to report the controller status - enum STATUS { - CONTROLLER_ERROR = 0, - CONTROLLER_OK, - }; - - /// creates the controller instance: this is called in the non-RT thread - Controller(); - - /// controllers have a unique ID - int getID(); - - /// allows instance to register MIDI observer type functionality - virtual int registerComponents(){return 0;} - - virtual ~Controller(){}; - - /// get the status of the controller - virtual STATUS status(){return CONTROLLER_OK;} - - /// name string to show in UI - virtual std::string getName() = 0; - - /// master - virtual void masterInputVol(float f){} - virtual void masterInputTo(int to,float f){} - virtual void masterInputToActive(int to,float f){} - virtual void masterVolume(float f){} - virtual void masterReturnVolume(float f){} - virtual void metronomeEnable(bool b){} - - /// FX - virtual void trackSend(int t, int send, float v){} - virtual void trackSendActive(int t, int send, bool a){} +public: + /// used to report the controller status + enum STATUS { + CONTROLLER_ERROR = 0, + CONTROLLER_OK, + }; - virtual void trackJackSend(int t, float v){} - virtual void trackJackSendActivate(int t, bool a){} - - /// Time - virtual void bpm(int bpm){} - virtual void tapTempo(bool b){} - - /// Special - virtual void specialScene(int t, int scene){} - - /// 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){} - virtual void launchScene( int scene ){} - - /// reset controller - virtual void reset(); - - private: - static int privateID; - int ID; + /// creates the controller instance: this is called in the non-RT thread + Controller(); + + /// controllers have a unique ID + int getID(); + + /// allows instance to register MIDI observer type functionality + virtual int registerComponents() + { + return 0; + } + + virtual ~Controller() {}; + + /// get the status of the controller + virtual STATUS status() + { + return CONTROLLER_OK; + } + + /// name string to show in UI + virtual std::string getName() = 0; + + /// master + virtual void masterInputVol(float f) {} + virtual void masterInputTo(int to,float f) {} + virtual void masterInputToActive(int to,float f) {} + virtual void masterVolume(float f) {} + virtual void masterReturnVolume(float f) {} + virtual void metronomeEnable(bool b) {} + + /// FX + virtual void trackSend(int t, int send, float v) {} + virtual void trackSendActive(int t, int send, bool a) {} + + virtual void trackJackSend(int t, float v) {} + virtual void trackJackSendActivate(int t, bool a) {} + + /// Time + virtual void bpm(int bpm) {} + virtual void tapTempo(bool b) {} + + /// Special + virtual void specialScene(int t, int scene) {} + + /// 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) {} + virtual void launchScene( int scene ) {} + + /// reset controller + virtual void reset(); + +private: + static int privateID; + int ID; }; #endif // LUPPP_CONTROLLER_H diff --git a/src/controller/genericmidi.cxx b/src/controller/genericmidi.cxx index def9146..9033643 100644 --- a/src/controller/genericmidi.cxx +++ b/src/controller/genericmidi.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -35,178 +35,162 @@ extern Jack* jack; int Binding::privateID = 0; GenericMIDI::GenericMIDI(int waste, std::string n) : - Controller(), - MidiIO() + Controller(), + MidiIO() { - LUPPP_NOTE("Adding GenericMIDI %s", n.c_str() ); - name = n; - registerMidiPorts( name ); - stat = CONTROLLER_OK; - - setFootswitchToNextScene( 0 ); + LUPPP_NOTE("Adding GenericMIDI %s", n.c_str() ); + name = n; + registerMidiPorts( name ); + stat = CONTROLLER_OK; + + setFootswitchToNextScene( 0 ); } void GenericMIDI::setFootswitchToNextScene(int v) { - LUPPP_NOTE("Set Footswitch to %i", v ); - if ( v == 0 ) - { - footswitchNextScene = false; - footswitchPrevScene = false; - } - else if ( v > 0 ) - { - footswitchNextScene = true; - footswitchPrevScene = false; - } - else - { - footswitchNextScene = false; - footswitchPrevScene = true; - } + LUPPP_NOTE("Set Footswitch to %i", v ); + if ( v == 0 ) { + footswitchNextScene = false; + footswitchPrevScene = false; + } else if ( v > 0 ) { + footswitchNextScene = true; + footswitchPrevScene = false; + } else { + footswitchNextScene = false; + footswitchPrevScene = true; + } } void GenericMIDI::setName(std::string n) { - name = n; + name = n; } GenericMIDI::GenericMIDI(std::string file) : - Controller(), - MidiIO() + Controller(), + MidiIO() { - // default name for each controller - name = "generic"; - - // load the JSON config file - int result = loadController( file ); - - if ( result == LUPPP_RETURN_OK ) - { - LUPPP_NOTE("GenericMIDI registering ports: %s", name.c_str() ); - registerMidiPorts( name ); - stat = CONTROLLER_OK; - } - else - { - LUPPP_ERROR("Error in loading controller map!" ); - stat = CONTROLLER_ERROR; - } + // default name for each controller + name = "generic"; + + // load the JSON config file + int result = loadController( file ); + + if ( result == LUPPP_RETURN_OK ) { + LUPPP_NOTE("GenericMIDI registering ports: %s", name.c_str() ); + registerMidiPorts( name ); + stat = CONTROLLER_OK; + } else { + LUPPP_ERROR("Error in loading controller map!" ); + stat = CONTROLLER_ERROR; + } } const std::vector& GenericMIDI::getMidiToAction() { - return midiToAction; + return midiToAction; } Controller::STATUS GenericMIDI::status() { - return stat; + return stat; } int GenericMIDI::registerComponents() { - // makes JACK add this controller to the midiObservers list: - // note the static_cast<>() is *needed* here for multiple-inheritance - MidiIO* m = static_cast(this); - - jack->registerMidiIO( m ); - - return LUPPP_RETURN_OK; + // makes JACK add this controller to the midiObservers list: + // note the static_cast<>() is *needed* here for multiple-inheritance + MidiIO* m = static_cast(this); + + jack->registerMidiIO( m ); + + return LUPPP_RETURN_OK; } std::string GenericMIDI::getName() { - return name; + return name; } std::string GenericMIDI::getAuthor() { - return author; + return author; } std::string GenericMIDI::getEmail() { - return email; + return email; } void GenericMIDI::volume(int t, float f) { - + } void GenericMIDI::recordArm(int t, bool enabled) { - for(unsigned int i = 0; i < actionToMidi.size(); i++) - { - Binding* b = actionToMidi.at(i); - - if ( b->action == TRACK_RECORD_ARM && b->track == t ) - { - unsigned char data[3]; - data[0] = b->status; - data[1] = b->data; - data[2] = enabled ? 127 : 0; - writeMidi( data ); - return; - } - } + for(unsigned int i = 0; i < actionToMidi.size(); i++) { + Binding* b = actionToMidi.at(i); + + if ( b->action == TRACK_RECORD_ARM && b->track == t ) { + unsigned char data[3]; + data[0] = b->status; + data[1] = b->data; + data[2] = enabled ? 127 : 0; + writeMidi( data ); + return; + } + } } void GenericMIDI::metronomeEnable(bool enabled) { - for(unsigned int i = 0; i < actionToMidi.size(); i++) - { - Binding* b = actionToMidi.at(i); - - if ( b->action == METRONOME_ACTIVE ) - { - unsigned char data[3]; - data[0] = b->status; - data[1] = b->data; - data[2] = enabled ? 127 : 0; - writeMidi( data ); - return; - } - } + for(unsigned int i = 0; i < actionToMidi.size(); i++) { + Binding* b = actionToMidi.at(i); + + if ( b->action == METRONOME_ACTIVE ) { + unsigned char data[3]; + data[0] = b->status; + data[1] = b->data; + data[2] = enabled ? 127 : 0; + writeMidi( data ); + return; + } + } } void GenericMIDI::trackSend(int t, int send, float v) { - - for(unsigned int i = 0; i < actionToMidi.size(); i++) - { - Binding* b = actionToMidi.at(i); - - if ( b->action == TRACK_SEND && b->track == t && b->send == send ) - { - unsigned char data[3]; - data[0] = b->status; - data[1] = b->data; - data[2] = v * 127; - writeMidi( data ); - return; - } - } + + for(unsigned int i = 0; i < actionToMidi.size(); i++) { + Binding* b = actionToMidi.at(i); + + if ( b->action == TRACK_SEND && b->track == t && b->send == send ) { + unsigned char data[3]; + data[0] = b->status; + data[1] = b->data; + data[2] = v * 127; + writeMidi( data ); + return; + } + } } void GenericMIDI::trackSendActive(int t, int send, bool a) { - for(unsigned int i = 0; i < actionToMidi.size(); i++) - { - Binding* b = actionToMidi.at(i); - - if ( b->action == TRACK_SEND_ACTIVE && b->track == t && b->send == send ) - { - unsigned char data[3]; - data[0] = b->status; - data[1] = b->data; - data[2] = a ? 127 : 0; - writeMidi( data ); - return; - } - } + for(unsigned int i = 0; i < actionToMidi.size(); i++) { + Binding* b = actionToMidi.at(i); + + if ( b->action == TRACK_SEND_ACTIVE && b->track == t && b->send == send ) { + unsigned char data[3]; + data[0] = b->status; + data[1] = b->data; + data[2] = a ? 127 : 0; + writeMidi( data ); + return; + } + } } void GenericMIDI::trackJackSend(int t, float v) @@ -222,13 +206,13 @@ void GenericMIDI::trackJackSendActivate(int t, bool a) /* void GenericMIDI::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->midiObserverWriteMIDI( _port, &data[0] ); - + } void GenericMIDI::trackSend(int t, int send, float v) @@ -238,9 +222,9 @@ void GenericMIDI::trackSend(int t, int send, float v) // master track return; } - + unsigned char data[3]; - + if ( send == SEND_KEY ) { data[0] = 144 + t; @@ -259,14 +243,14 @@ void GenericMIDI::trackSend(int t, int send, float v) data[1] = 17; data[2] = 127 * v; } - + jack->midiObserverWriteMIDI( _port, &data[0] ); } void GenericMIDI::launchScene( int s ) { unsigned char data[3]; - + for(int i = 0; i < 5; i++ ) { data[0] = 128; @@ -274,7 +258,7 @@ void GenericMIDI::launchScene( int s ) data[2] = 0; jack->midiObserverWriteMIDI( _port, &data[0] ); } - + data[0] = 144; data[1] = 82 + s; data[2] = 127; @@ -283,13 +267,13 @@ void GenericMIDI::launchScene( int s ) void GenericMIDI::mute(int t, bool b) { - + } void GenericMIDI::volume(int t, float f) { - + } void GenericMIDI::noteOn( int track, int note, int vel ) @@ -306,8 +290,8 @@ void GenericMIDI::noteOn( int track, int note, int vel ) jack->getGridLogic()->pressed( track, note - 53 ); return; } - - + + switch( note ) { case 48: { // record @@ -316,35 +300,35 @@ void GenericMIDI::noteOn( int track, int note, int vel ) case 49: { // solo / cue jack->getLogic()->trackSend(track, SEND_KEY, 1); } break; - + case 82: // Master Scene Clips - case 83: - case 84: - case 85: + case 83: + case 84: + case 85: case 86: { jack->getGridLogic()->launchScene(note - 82); } break; - + case 98: { // Shift shiftPressed = true; break; } - + case 99: { // tap tempo jack->getLogic()->tapTempo(); jack->getControllerUpdater()->tapTempo( true ); - } break; + } break; case 100: { // nudge + - - } break; + + } break; case 101: { // nudge - - - } break; - + + } break; + default: break; } - - + + } void GenericMIDI::noteOff( int track, int note, int vel ) @@ -354,7 +338,7 @@ void GenericMIDI::noteOff( int track, int note, int vel ) { jack->getGridLogic()->released( track, note - 53 ); } - + switch( note ) { case 48: { // record @@ -363,12 +347,12 @@ void GenericMIDI::noteOff( int track, int note, int vel ) case 49: { // solo / cue jack->getLogic()->trackSend(track, SEND_KEY, 0); } - + case 99: { // tap tempo EventTimeTempoTap e(false); writeToGuiRingbuffer( &e ); - } break; - + } break; + case 82: // scene launch case 83: case 84: @@ -377,7 +361,7 @@ void GenericMIDI::noteOff( int track, int note, int vel ) int s = jack->getGridLogic()->getLaunchedScene(); launchScene( s ); } break ; - + case 98: { // Shift shiftPressed = false; break; } @@ -397,12 +381,12 @@ void GenericMIDI::ccChange( int track, int cc, float value ) case 14: { // master jack->getLogic()->trackVolume( -1, value ); break; } - + /// X-Fader case 15: { jack->getTimeManager()->setBpm( 60 + value * 180 ); break; } - + /// Device Control case 16: { //jack->getLogic()->trackSend( track, SEND_KEY, value ); @@ -413,8 +397,8 @@ void GenericMIDI::ccChange( int track, int cc, float value ) case 18: { jack->getLogic()->trackSend( track, SEND_POSTFADER, value ); break; } - - + + case 64: { // FootSwitch 1 if ( value > 0.5 ) { @@ -427,7 +411,7 @@ void GenericMIDI::ccChange( int track, int cc, float value ) jack->getGridLogic()->released( footpedalTrack, footpedalScene ); } break; } case 67: { // FootSwitch 2 - + break; } } } @@ -437,7 +421,7 @@ void GenericMIDI::ccChange( int track, int cc, float value ) { if ( cc == 16 ) // master device control select { - + } } } @@ -447,512 +431,466 @@ void GenericMIDI::ccChange( int track, int cc, float value ) void GenericMIDI::midi(unsigned char* midi) { - int status = midi[0]; - int data = midi[1]; - float value = midi[2] / 127.f; - - - // create new MIDI binding? - if ( jack->bindingEventRecordEnable ) - { - //LUPPP_NOTE("making binding from: %i %i %f", status, data, value ); - setupBinding( jack->bindingEventType, status, data, - jack->bindingTrack, - jack->bindingScene, - jack->bindingSend, - jack->bindingActive ); - - // reset jack state, so bindings defaults are setup after each creation - jack->resetMidiBindingState(); - - // binding is now created, so disable GUI binding enable button - EventControllerBindingEnable e( getID(), false ); - writeToGuiRingbuffer( &e ); - - // update GUI of new binding - EventControllerBindingMade e2( getID(), (void*)midiToAction.back() ); - writeToGuiRingbuffer( &e2 ); - } - - if ( status == 0x90 && data == 0x64 ) // nudge + - { - // footpedal to scene++ - setFootswitchToNextScene( 1 ); - } - else if ( status == 0x90 && data == 0x65 ) // nudge - { - // footpedal to scene-- - setFootswitchToNextScene( -1 ); - } - else if ( status == 0x90 && data == 0x60 ) // > on bank select: clear scene - { - // footpedal to special clip - setFootswitchToNextScene( 0 ); - } - - // iterate over bindings, execute binding action if matches - for(unsigned int i = 0; i < midiToAction.size(); i++) - { - Binding* b = midiToAction.at(i); - - if ( b->status == status && b->data == data ) - { - //LUPPP_NOTE("Executing action %s, send %i value %f, b->active %i", Event::getPrettyName(b->action), b->send, value, int(b->active) ); - - switch( b->action ) - { - case Event::TRACK_VOLUME: jack->getLogic()->trackVolume( b->track, value ); break; - case Event::TRACK_SEND: jack->getLogic()->trackSend( b->track, b->send, value ); break; - case Event::TRACK_SEND_ACTIVE: jack->getLogic()->trackSendActive( b->track, b->send, b->active ); break; - case Event::TRACK_RECORD_ARM: jack->getLogic()->trackRecordArm( b->track, b->active ); break; - case Event::TRACK_JACKSEND: jack->getLogic()->trackJackSend(b->track,value); break; - case Event::TRACK_JACKSEND_ACTIVATE: jack->getLogic()->trackJackSendActivate(b->track,b->active); break; - case Event::GRID_EVENT: - if ( b->active ) - jack->getGridLogic()->pressed( b->track, b->scene ); - else - jack->getGridLogic()->released( b->track, b->scene ); - break; - - case Event::GRID_SELECT_CLIP_EVENT: - // hack to do scene ++ / -- with footswitch - if ( footswitchNextScene && value > 0.5 ) // avoid note offs - { - cout << "footswitch next scene *now*" << endl; - jack->getGridLogic()->launchScene( jack->getGridLogic()->getCurrentScene() + 1 ); - } - else if ( footswitchPrevScene && value > 0.5 ) - { - cout << "footswitch prev scene *now*" << endl; - jack->getGridLogic()->launchScene( jack->getGridLogic()->getCurrentScene() - 1 ); - } - else - { - cout << "footswitch special clip action now" << endl; - jack->getGridLogic()->selectedTrackSceneEvent( value ); - } - break; - case Event::GRID_SELECT_CLIP_ENABLE: - jack->getGridLogic()->setSelectTrackScene( b->active ); - break; - case Event::GRID_LAUNCH_SCENE: - jack->getGridLogic()->launchScene( b->scene ); - break; - - case Event::MASTER_RETURN: - jack->getLogic()->masterReturn( RETURN_MAIN, value ); - break; - case Event::MASTER_INPUT_VOL: - jack->getLogic()->masterInputVol( value ); - break; - case Event::MASTER_INPUT_TO: - //LUPPP_NOTE("GenMidi event INPUT_TO %i", b->send ); - jack->getLogic()->masterInputTo( b->send, value ); - break; - case Event::MASTER_INPUT_TO_ACTIVE: - //LUPPP_NOTE("GenMidi event INPUT_TO_ACTIVE %i", b->send ); - jack->getLogic()->masterInputToActive( b->send, b->active ); - break; - - case Event::TIME_TEMPO_TAP: - jack->getLogic()->tapTempo(); - break; - case Event::TIME_BPM: - // FIXME: quick-fix for "ZeroOne" type value -> BPM range - jack->getLogic()->setBpm( value * 160 + 60 ); - break; - case Event::METRONOME_ACTIVE: - jack->getLogic()->metronomeEnable( b->active ); - break; - - case Event::MASTER_VOL: jack->getLogic()->trackVolume( -1 , value ); break; - } - } - - - } - + int status = midi[0]; + int data = midi[1]; + float value = midi[2] / 127.f; + + + // create new MIDI binding? + if ( jack->bindingEventRecordEnable ) { + //LUPPP_NOTE("making binding from: %i %i %f", status, data, value ); + setupBinding( jack->bindingEventType, status, data, + jack->bindingTrack, + jack->bindingScene, + jack->bindingSend, + jack->bindingActive ); + + // reset jack state, so bindings defaults are setup after each creation + jack->resetMidiBindingState(); + + // binding is now created, so disable GUI binding enable button + EventControllerBindingEnable e( getID(), false ); + writeToGuiRingbuffer( &e ); + + // update GUI of new binding + EventControllerBindingMade e2( getID(), (void*)midiToAction.back() ); + writeToGuiRingbuffer( &e2 ); + } + + if ( status == 0x90 && data == 0x64 ) { // nudge + + // footpedal to scene++ + setFootswitchToNextScene( 1 ); + } else if ( status == 0x90 && data == 0x65 ) { // nudge + // footpedal to scene-- + setFootswitchToNextScene( -1 ); + } else if ( status == 0x90 && data == 0x60 ) { // > on bank select: clear scene + // footpedal to special clip + setFootswitchToNextScene( 0 ); + } + + // iterate over bindings, execute binding action if matches + for(unsigned int i = 0; i < midiToAction.size(); i++) { + Binding* b = midiToAction.at(i); + + if ( b->status == status && b->data == data ) { + //LUPPP_NOTE("Executing action %s, send %i value %f, b->active %i", Event::getPrettyName(b->action), b->send, value, int(b->active) ); + + switch( b->action ) { + case Event::TRACK_VOLUME: + jack->getLogic()->trackVolume( b->track, value ); + break; + case Event::TRACK_SEND: + jack->getLogic()->trackSend( b->track, b->send, value ); + break; + case Event::TRACK_SEND_ACTIVE: + jack->getLogic()->trackSendActive( b->track, b->send, b->active ); + break; + case Event::TRACK_RECORD_ARM: + jack->getLogic()->trackRecordArm( b->track, b->active ); + break; + case Event::TRACK_JACKSEND: + jack->getLogic()->trackJackSend(b->track,value); + break; + case Event::TRACK_JACKSEND_ACTIVATE: + jack->getLogic()->trackJackSendActivate(b->track,b->active); + break; + case Event::GRID_EVENT: + if ( b->active ) + jack->getGridLogic()->pressed( b->track, b->scene ); + else + jack->getGridLogic()->released( b->track, b->scene ); + break; + + case Event::GRID_SELECT_CLIP_EVENT: + // hack to do scene ++ / -- with footswitch + if ( footswitchNextScene && value > 0.5 ) { // avoid note offs + cout << "footswitch next scene *now*" << endl; + jack->getGridLogic()->launchScene( jack->getGridLogic()->getCurrentScene() + 1 ); + } else if ( footswitchPrevScene && value > 0.5 ) { + cout << "footswitch prev scene *now*" << endl; + jack->getGridLogic()->launchScene( jack->getGridLogic()->getCurrentScene() - 1 ); + } else { + cout << "footswitch special clip action now" << endl; + jack->getGridLogic()->selectedTrackSceneEvent( value ); + } + break; + case Event::GRID_SELECT_CLIP_ENABLE: + jack->getGridLogic()->setSelectTrackScene( b->active ); + break; + case Event::GRID_LAUNCH_SCENE: + jack->getGridLogic()->launchScene( b->scene ); + break; + + case Event::MASTER_RETURN: + jack->getLogic()->masterReturn( RETURN_MAIN, value ); + break; + case Event::MASTER_INPUT_VOL: + jack->getLogic()->masterInputVol( value ); + break; + case Event::MASTER_INPUT_TO: + //LUPPP_NOTE("GenMidi event INPUT_TO %i", b->send ); + jack->getLogic()->masterInputTo( b->send, value ); + break; + case Event::MASTER_INPUT_TO_ACTIVE: + //LUPPP_NOTE("GenMidi event INPUT_TO_ACTIVE %i", b->send ); + jack->getLogic()->masterInputToActive( b->send, b->active ); + break; + + case Event::TIME_TEMPO_TAP: + jack->getLogic()->tapTempo(); + break; + case Event::TIME_BPM: + // FIXME: quick-fix for "ZeroOne" type value -> BPM range + jack->getLogic()->setBpm( value * 160 + 60 ); + break; + case Event::METRONOME_ACTIVE: + jack->getLogic()->metronomeEnable( b->active ); + break; + + case Event::MASTER_VOL: + jack->getLogic()->trackVolume( -1 , value ); + break; + } + } + + + } + } void GenericMIDI::setSceneState(int t, int scene, GridLogic::State s) { - for(unsigned int i = 0; i < actionToMidi.size(); i++) - { - Binding* b = actionToMidi.at(i); - - if ( b->action == GRID_STATE && b->track == t && b->scene == scene ) - { - for( map::iterator it = b->clipStateMap.begin(); it != b->clipStateMap.end(); ++it) - { - // check if its the right clip state - if ( it->first == int(s) ) - { - unsigned char data[3]; - data[0] = b->status; - data[1] = b->data; - data[2] = it->second; - - //LUPPP_NOTE("GenericMIDI::sceneState() writing event %i, %i, %i", data[0],data[1],data[2] ); - writeMidi( data ); - } - } - } - } + for(unsigned int i = 0; i < actionToMidi.size(); i++) { + Binding* b = actionToMidi.at(i); + + if ( b->action == GRID_STATE && b->track == t && b->scene == scene ) { + for( map::iterator it = b->clipStateMap.begin(); it != b->clipStateMap.end(); ++it) { + // check if its the right clip state + if ( it->first == int(s) ) { + unsigned char data[3]; + data[0] = b->status; + data[1] = b->data; + data[2] = it->second; + + //LUPPP_NOTE("GenericMIDI::sceneState() writing event %i, %i, %i", data[0],data[1],data[2] ); + writeMidi( data ); + } + } + } + } } void GenericMIDI::reset() -{//TODO needed? - /* - unsigned char data[3]; - // setup "volume" style rotary display - for(int i = 0; i < NTRACKS; i++) - { - data[0] = 176 + i; - data[1] = 0x19; - data[2] = 2; - jack->midiObserverWriteMIDI( _port, &data[0] ); - } - */ +{ + //TODO needed? + /* + unsigned char data[3]; + // setup "volume" style rotary display + for(int i = 0; i < NTRACKS; i++) + { + data[0] = 176 + i; + data[1] = 0x19; + data[2] = 2; + jack->midiObserverWriteMIDI( _port, &data[0] ); + } + */ } void GenericMIDI::launchScene( int scene ) { - for(unsigned int i = 0; i < actionToMidi.size(); i++) - { - Binding* b = actionToMidi.at(i); - - if ( b->action == GRID_LAUNCH_SCENE ) - { - for( int i = 0; i < 5; i++ ) - { - if ( i != scene ) - { - unsigned char data[3]; - data[0] = b->status; - data[1] = b->data + i; - data[2] = 0; - writeMidi( data ); - } - } - unsigned char data[3]; - data[0] = b->status; - data[1] = b->data + scene; - data[2] = 127; - //LUPPP_NOTE("this = %i GenericMIDI::launchScene()", this ); - writeMidi( data ); - - return; - } - } - + for(unsigned int i = 0; i < actionToMidi.size(); i++) { + Binding* b = actionToMidi.at(i); + + if ( b->action == GRID_LAUNCH_SCENE ) { + for( int i = 0; i < 5; i++ ) { + if ( i != scene ) { + unsigned char data[3]; + data[0] = b->status; + data[1] = b->data + i; + data[2] = 0; + writeMidi( data ); + } + } + unsigned char data[3]; + data[0] = b->status; + data[1] = b->data + scene; + data[2] = 127; + //LUPPP_NOTE("this = %i GenericMIDI::launchScene()", this ); + writeMidi( data ); + + return; + } + } + } int GenericMIDI::loadController( std::string file ) { - - /// open and read whole file + + /// open and read whole file #ifdef DEBUG_CONTROLLER - LUPPP_NOTE("%s%s","Loading controller : ", file.c_str() ); + LUPPP_NOTE("%s%s","Loading controller : ", file.c_str() ); #endif - std::ifstream sampleFile( file.c_str(), std::ios_base::in|std::ios_base::ate); - long file_length = sampleFile.tellg(); - if ( file_length > 0 ) - { - sampleFile.seekg(0, std::ios_base::beg); - sampleFile.clear(); - char *sampleString = new char[file_length]; - sampleFile.read(sampleString, file_length); - - cJSON* controllerJson = cJSON_Parse( sampleString ); - if (!controllerJson) { - std::string error = cJSON_GetErrorPtr(); - - std::istringstream ss( error ); - - std::string line; - std::getline( ss, line ); - LUPPP_ERROR("%s %s","Error in JSON *before*: ", line.c_str() ); - - for(int i = 0; i < 5; i++) - { - std::getline( ss, line ); - LUPPP_ERROR("%s %s","Error in JSON : ", line.c_str() ); - } - return LUPPP_RETURN_ERROR; - } - - cJSON* nameJson = cJSON_GetObjectItem( controllerJson, "name" ); - if ( nameJson ) - { - name = nameJson->valuestring; - LUPPP_NOTE("Device %s", name.c_str() ); - } - else - { - LUPPP_NOTE("Has no name field"); - } - - cJSON* authorJson = cJSON_GetObjectItem( controllerJson, "author" ); - if ( authorJson ) - { - author = authorJson->valuestring; - LUPPP_NOTE("Author %s", author.c_str() ); - } - else - { - LUPPP_NOTE("Has no author field"); - } - - cJSON* linkJson = cJSON_GetObjectItem( controllerJson, "link" ); - if ( linkJson ) - { - email = linkJson->valuestring; - LUPPP_NOTE("Link %s", email.c_str() ); - } - else - { - LUPPP_NOTE("Has no link field"); - } - - - int nInputBindings = 0; - cJSON* inputBindings = cJSON_GetObjectItem( controllerJson, "inputBindings"); - if ( inputBindings ) - { - int nBindings = cJSON_GetArraySize( inputBindings ); - for(int i = 0; i < nBindings; i++ ) - { - cJSON* bindingJson = cJSON_GetArrayItem( inputBindings, i ); - Binding* tmp = setupBinding( bindingJson ); - if ( tmp ) - midiToAction.push_back( tmp ); - - nInputBindings++; - } - } - else - { - LUPPP_WARN("No input bindings array in .ctlr map." ); - nInputBindings++; // hack to avoid 2 prints - } - - if ( nInputBindings == 0 ) - { - LUPPP_NOTE("Zero input bindings present in .ctlr map."); - } - - - int nOutputBindings = 0; - cJSON* outputBindings = cJSON_GetObjectItem( controllerJson, "outputBindings"); - if ( outputBindings ) - { - int nBindings = cJSON_GetArraySize( outputBindings ); - for(int i = 0; i < nBindings; i++ ) - { - cJSON* bindingJson = cJSON_GetArrayItem( outputBindings, i ); - Binding* tmp = setupBinding( bindingJson ); - if ( tmp ) - actionToMidi.push_back( tmp ); - - nOutputBindings++; - //LUPPP_NOTE("Binding from %s to %i %i", actionJ->valuestring, statusJson->valueint, dataJson->valueint ); - } - } - else - { - LUPPP_NOTE("No output bindings array in .ctlr map." ); - nOutputBindings++; // hack to avoid 2 prints - } - if ( nOutputBindings == 0 ) - { - LUPPP_NOTE("Zero output bindings present in .ctlr map." ); - } - - - cJSON_Delete( controllerJson ); - delete[] sampleString; - } - else - { - LUPPP_WARN("%s %s","No controller file found at ", file.c_str() ); - return LUPPP_RETURN_WARNING; - } - - - LUPPP_NOTE("Controller loading complete." ); - - return LUPPP_RETURN_OK; + std::ifstream sampleFile( file.c_str(), std::ios_base::in|std::ios_base::ate); + long file_length = sampleFile.tellg(); + if ( file_length > 0 ) { + sampleFile.seekg(0, std::ios_base::beg); + sampleFile.clear(); + char *sampleString = new char[file_length]; + sampleFile.read(sampleString, file_length); + + cJSON* controllerJson = cJSON_Parse( sampleString ); + if (!controllerJson) { + std::string error = cJSON_GetErrorPtr(); + + std::istringstream ss( error ); + + std::string line; + std::getline( ss, line ); + LUPPP_ERROR("%s %s","Error in JSON *before*: ", line.c_str() ); + + for(int i = 0; i < 5; i++) { + std::getline( ss, line ); + LUPPP_ERROR("%s %s","Error in JSON : ", line.c_str() ); + } + return LUPPP_RETURN_ERROR; + } + + cJSON* nameJson = cJSON_GetObjectItem( controllerJson, "name" ); + if ( nameJson ) { + name = nameJson->valuestring; + LUPPP_NOTE("Device %s", name.c_str() ); + } else { + LUPPP_NOTE("Has no name field"); + } + + cJSON* authorJson = cJSON_GetObjectItem( controllerJson, "author" ); + if ( authorJson ) { + author = authorJson->valuestring; + LUPPP_NOTE("Author %s", author.c_str() ); + } else { + LUPPP_NOTE("Has no author field"); + } + + cJSON* linkJson = cJSON_GetObjectItem( controllerJson, "link" ); + if ( linkJson ) { + email = linkJson->valuestring; + LUPPP_NOTE("Link %s", email.c_str() ); + } else { + LUPPP_NOTE("Has no link field"); + } + + + int nInputBindings = 0; + cJSON* inputBindings = cJSON_GetObjectItem( controllerJson, "inputBindings"); + if ( inputBindings ) { + int nBindings = cJSON_GetArraySize( inputBindings ); + for(int i = 0; i < nBindings; i++ ) { + cJSON* bindingJson = cJSON_GetArrayItem( inputBindings, i ); + Binding* tmp = setupBinding( bindingJson ); + if ( tmp ) + midiToAction.push_back( tmp ); + + nInputBindings++; + } + } else { + LUPPP_WARN("No input bindings array in .ctlr map." ); + nInputBindings++; // hack to avoid 2 prints + } + + if ( nInputBindings == 0 ) { + LUPPP_NOTE("Zero input bindings present in .ctlr map."); + } + + + int nOutputBindings = 0; + cJSON* outputBindings = cJSON_GetObjectItem( controllerJson, "outputBindings"); + if ( outputBindings ) { + int nBindings = cJSON_GetArraySize( outputBindings ); + for(int i = 0; i < nBindings; i++ ) { + cJSON* bindingJson = cJSON_GetArrayItem( outputBindings, i ); + Binding* tmp = setupBinding( bindingJson ); + if ( tmp ) + actionToMidi.push_back( tmp ); + + nOutputBindings++; + //LUPPP_NOTE("Binding from %s to %i %i", actionJ->valuestring, statusJson->valueint, dataJson->valueint ); + } + } else { + LUPPP_NOTE("No output bindings array in .ctlr map." ); + nOutputBindings++; // hack to avoid 2 prints + } + if ( nOutputBindings == 0 ) { + LUPPP_NOTE("Zero output bindings present in .ctlr map." ); + } + + + cJSON_Delete( controllerJson ); + delete[] sampleString; + } else { + LUPPP_WARN("%s %s","No controller file found at ", file.c_str() ); + return LUPPP_RETURN_WARNING; + } + + + LUPPP_NOTE("Controller loading complete." ); + + return LUPPP_RETURN_OK; } void GenericMIDI::removeBinding( int bindingID ) { - for(unsigned int i = 0; i < midiToAction.size(); i++) - { - if ( midiToAction.at(i)->ID == bindingID ) - { - //LUPPP_NOTE("MIDI binding REMOVED with bindingID %i\n", bindingID ); - Binding* tmp = midiToAction.at(i); - midiToAction.erase( midiToAction.begin()+i ); - - if ( tmp ) - { - delete tmp; - } - return; - } - } + for(unsigned int i = 0; i < midiToAction.size(); i++) { + if ( midiToAction.at(i)->ID == bindingID ) { + //LUPPP_NOTE("MIDI binding REMOVED with bindingID %i\n", bindingID ); + Binding* tmp = midiToAction.at(i); + midiToAction.erase( midiToAction.begin()+i ); + + if ( tmp ) { + delete tmp; + } + return; + } + } } void GenericMIDI::setupBinding( LupppAction eventType, int midiStatus, int midiData, int track, int scene, int send, int active ) { - LUPPP_NOTE("MIDI binding, track %d, send %d from eventType %d to %d, %d", track, send, eventType, midiStatus, midiData ); - - // FIXME: NON-RT Have stack of Bindings() available, or push in GUI thread? - Binding* tmp = new Binding(); - - tmp->action = eventType; - tmp->status = midiStatus; - tmp->data = midiData; - tmp->track = track; - tmp->scene = scene; - tmp->send = send; - tmp->active = active; - - // FIXME: Could allocate memory! Issue? Shouldn't be binding during performance? - midiToAction.push_back( tmp ); + LUPPP_NOTE("MIDI binding, track %d, send %d from eventType %d to %d, %d", track, send, eventType, midiStatus, midiData ); + + // FIXME: NON-RT Have stack of Bindings() available, or push in GUI thread? + Binding* tmp = new Binding(); + + tmp->action = eventType; + tmp->status = midiStatus; + tmp->data = midiData; + tmp->track = track; + tmp->scene = scene; + tmp->send = send; + tmp->active = active; + + // FIXME: Could allocate memory! Issue? Shouldn't be binding during performance? + midiToAction.push_back( tmp ); } Binding* GenericMIDI::setupBinding( cJSON* binding ) { - // include Event::getPrettyName, and avoid Event::TRACK_VOLUME etc each time - using namespace Event; - - // create binding, then fill in data as from JSON. - Binding* tmp = new Binding(); - - - cJSON* actionJson = cJSON_GetObjectItem( binding, "action" ); - if ( !actionJson ) - { - LUPPP_WARN("Binding doesn't have action field: fix .ctlr file"); - return 0; - } - - cJSON* statusJson = cJSON_GetObjectItem( binding, "status" ); - cJSON* dataJson = cJSON_GetObjectItem( binding, "data" ); - if ( !statusJson || !dataJson ) - { - LUPPP_WARN("Binding w Action:%s doesn't have status / data field: fix .ctlr file", actionJson->valuestring); - return 0; - } - - tmp->status = statusJson->valueint; - tmp->data = dataJson->valueint; - - // gets the Action type from the JSON string - cJSON* activeJson = cJSON_GetObjectItem( binding, "active" ); - if ( activeJson ) - { - tmp->active = activeJson->valueint; - } - - // gets the active bool from the JSON - tmp->action = Event::getTypeFromName( actionJson->valuestring ); - - // check what our send value should be: - cJSON* sendJson = cJSON_GetObjectItem( binding, "send" ); - if ( sendJson ) - { - tmp->send = sendJson->valueint; - } - - if ( strcmp( actionJson->valuestring, "grid:clip_state" ) == 0 ) - { - tmp->action = Event::GRID_STATE; - - // read "state", to bind multiple values depending on clip state - - cJSON* stateBindings = cJSON_GetObjectItem( binding, "state"); - if ( stateBindings ) - { - cJSON* empty = cJSON_GetObjectItem( stateBindings, "empty"); - cJSON* stopped = cJSON_GetObjectItem( stateBindings, "stopped"); - cJSON* playing = cJSON_GetObjectItem( stateBindings, "playing"); - cJSON* recording = cJSON_GetObjectItem( stateBindings, "recording"); - cJSON* qPlaying = cJSON_GetObjectItem( stateBindings, "queuePlaying"); - cJSON* qStopped = cJSON_GetObjectItem( stateBindings, "queueStopped"); - cJSON* qRecording = cJSON_GetObjectItem( stateBindings, "queueRecording"); - - // keep a map of GridLogic::STATE to the MIDI byte 3 output from .ctlr file - if ( empty ) - tmp->clipStateMap.insert( std::pair( GridLogic::STATE_EMPTY, empty->valueint ) ); - if ( stopped ) - tmp->clipStateMap.insert( std::pair( GridLogic::STATE_STOPPED, stopped->valueint ) ); - if ( playing ) - tmp->clipStateMap.insert( std::pair( GridLogic::STATE_PLAYING, playing->valueint ) ); - if ( recording ) - tmp->clipStateMap.insert( std::pair( GridLogic::STATE_RECORDING, recording->valueint ) ); - - if ( qPlaying ) - tmp->clipStateMap.insert( std::pair( GridLogic::STATE_PLAY_QUEUED, qPlaying->valueint ) ); - if ( qStopped ) - tmp->clipStateMap.insert( std::pair( GridLogic::STATE_STOP_QUEUED, qStopped->valueint ) ); - if ( qRecording ) - tmp->clipStateMap.insert( std::pair( GridLogic::STATE_RECORD_QUEUED, qRecording->valueint ) ); - } - /* // Extreme debugging - for( map::iterator it = tmp->clipStateMap.begin(); it != tmp->clipStateMap.end(); ++it) - { - std::co ut << it->first << " " << it->second << "\n"; - } - */ - } - - else if ( strcmp( actionJson->valuestring, "grid:launch_scene" ) == 0 ) { - tmp->action = Event::GRID_LAUNCH_SCENE; - } - else if ( strcmp( actionJson->valuestring, "grid:special_clip_event" ) == 0 ) { - tmp->action = Event::GRID_SELECT_CLIP_EVENT; - } - else if ( strcmp( actionJson->valuestring, "grid:select_clip_enable" ) == 0 ) { - tmp->action = Event::GRID_SELECT_CLIP_ENABLE; - } - else if ( strcmp( actionJson->valuestring, "master:volume" ) == 0 ) { - tmp->action = Event::MASTER_VOL; - } - else if ( strcmp( actionJson->valuestring, "metronome:active" ) == 0 ) { - tmp->action = Event::METRONOME_ACTIVE; - LUPPP_NOTE("binding metro active event, tmp->active == %i", tmp->active ); - } - - // check for valid event: otherwise pass - if ( tmp->action != Event::EVENT_NULL ) - { - //LUPPP_NOTE("Binding from %i %i %s", statusJson->valueint, dataJson->valueint, actionJson->valuestring); - - cJSON* track = cJSON_GetObjectItem( binding, "track" ); - cJSON* scene = cJSON_GetObjectItem( binding, "scene" ); - cJSON* activeJson = cJSON_GetObjectItem( binding, "active" ); - - if ( track ) - tmp->track = track->valueint; - if ( scene ) - tmp->scene = scene->valueint; - if ( activeJson ) - tmp->active = activeJson->valueint; - - return tmp; - } - else - { - LUPPP_WARN("Binding action not recognized: %s", actionJson->valuestring ); - } - - return 0; - + // include Event::getPrettyName, and avoid Event::TRACK_VOLUME etc each time + using namespace Event; + + // create binding, then fill in data as from JSON. + Binding* tmp = new Binding(); + + + cJSON* actionJson = cJSON_GetObjectItem( binding, "action" ); + if ( !actionJson ) { + LUPPP_WARN("Binding doesn't have action field: fix .ctlr file"); + return 0; + } + + cJSON* statusJson = cJSON_GetObjectItem( binding, "status" ); + cJSON* dataJson = cJSON_GetObjectItem( binding, "data" ); + if ( !statusJson || !dataJson ) { + LUPPP_WARN("Binding w Action:%s doesn't have status / data field: fix .ctlr file", actionJson->valuestring); + return 0; + } + + tmp->status = statusJson->valueint; + tmp->data = dataJson->valueint; + + // gets the Action type from the JSON string + cJSON* activeJson = cJSON_GetObjectItem( binding, "active" ); + if ( activeJson ) { + tmp->active = activeJson->valueint; + } + + // gets the active bool from the JSON + tmp->action = Event::getTypeFromName( actionJson->valuestring ); + + // check what our send value should be: + cJSON* sendJson = cJSON_GetObjectItem( binding, "send" ); + if ( sendJson ) { + tmp->send = sendJson->valueint; + } + + if ( strcmp( actionJson->valuestring, "grid:clip_state" ) == 0 ) { + tmp->action = Event::GRID_STATE; + + // read "state", to bind multiple values depending on clip state + + cJSON* stateBindings = cJSON_GetObjectItem( binding, "state"); + if ( stateBindings ) { + cJSON* empty = cJSON_GetObjectItem( stateBindings, "empty"); + cJSON* stopped = cJSON_GetObjectItem( stateBindings, "stopped"); + cJSON* playing = cJSON_GetObjectItem( stateBindings, "playing"); + cJSON* recording = cJSON_GetObjectItem( stateBindings, "recording"); + cJSON* qPlaying = cJSON_GetObjectItem( stateBindings, "queuePlaying"); + cJSON* qStopped = cJSON_GetObjectItem( stateBindings, "queueStopped"); + cJSON* qRecording = cJSON_GetObjectItem( stateBindings, "queueRecording"); + + // keep a map of GridLogic::STATE to the MIDI byte 3 output from .ctlr file + if ( empty ) + tmp->clipStateMap.insert( std::pair( GridLogic::STATE_EMPTY, empty->valueint ) ); + if ( stopped ) + tmp->clipStateMap.insert( std::pair( GridLogic::STATE_STOPPED, stopped->valueint ) ); + if ( playing ) + tmp->clipStateMap.insert( std::pair( GridLogic::STATE_PLAYING, playing->valueint ) ); + if ( recording ) + tmp->clipStateMap.insert( std::pair( GridLogic::STATE_RECORDING, recording->valueint ) ); + + if ( qPlaying ) + tmp->clipStateMap.insert( std::pair( GridLogic::STATE_PLAY_QUEUED, qPlaying->valueint ) ); + if ( qStopped ) + tmp->clipStateMap.insert( std::pair( GridLogic::STATE_STOP_QUEUED, qStopped->valueint ) ); + if ( qRecording ) + tmp->clipStateMap.insert( std::pair( GridLogic::STATE_RECORD_QUEUED, qRecording->valueint ) ); + } + /* // Extreme debugging + for( map::iterator it = tmp->clipStateMap.begin(); it != tmp->clipStateMap.end(); ++it) + { + std::co ut << it->first << " " << it->second << "\n"; + } + */ + } + + else if ( strcmp( actionJson->valuestring, "grid:launch_scene" ) == 0 ) { + tmp->action = Event::GRID_LAUNCH_SCENE; + } else if ( strcmp( actionJson->valuestring, "grid:special_clip_event" ) == 0 ) { + tmp->action = Event::GRID_SELECT_CLIP_EVENT; + } else if ( strcmp( actionJson->valuestring, "grid:select_clip_enable" ) == 0 ) { + tmp->action = Event::GRID_SELECT_CLIP_ENABLE; + } else if ( strcmp( actionJson->valuestring, "master:volume" ) == 0 ) { + tmp->action = Event::MASTER_VOL; + } else if ( strcmp( actionJson->valuestring, "metronome:active" ) == 0 ) { + tmp->action = Event::METRONOME_ACTIVE; + LUPPP_NOTE("binding metro active event, tmp->active == %i", tmp->active ); + } + + // check for valid event: otherwise pass + if ( tmp->action != Event::EVENT_NULL ) { + //LUPPP_NOTE("Binding from %i %i %s", statusJson->valueint, dataJson->valueint, actionJson->valuestring); + + cJSON* track = cJSON_GetObjectItem( binding, "track" ); + cJSON* scene = cJSON_GetObjectItem( binding, "scene" ); + cJSON* activeJson = cJSON_GetObjectItem( binding, "active" ); + + if ( track ) + tmp->track = track->valueint; + if ( scene ) + tmp->scene = scene->valueint; + if ( activeJson ) + tmp->active = activeJson->valueint; + + return tmp; + } else { + LUPPP_WARN("Binding action not recognized: %s", actionJson->valuestring ); + } + + return 0; + } diff --git a/src/controller/genericmidi.hxx b/src/controller/genericmidi.hxx index f5841b4..9b7f0a7 100644 --- a/src/controller/genericmidi.hxx +++ b/src/controller/genericmidi.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -36,96 +36,96 @@ **/ class GenericMIDI : public Controller, public MidiIO { - public: - /// Creates a blank GenericMIDI instance, which can be bound dynamically - GenericMIDI(int waste = 0, std::string name = "generic"); - - /// Attempts to load a .ctlr file, pointed to by the string - GenericMIDI(std::string file); - - int registerComponents(); - - Controller::STATUS status(); - - void setName(std::string ); - std::string getName(); - std::string getAuthor(); - std::string getEmail(); - - /// track actions - //void mute(int t, bool b); - - void metronomeEnable(bool b); - - void launchScene( int scene ); - - void volume(int t, float f); - - - void recordArm(int t, bool b); - void setSceneState(int track, int clip, GridLogic::State s); - - /* - void progress(int t, int s, float f); - void launchScene( int scene ); - - /// track FX - void trackSend(int t, int send, float v); - */ - - void trackSend(int t, int send, float v); - void trackSendActive(int t, int send, bool a); +public: + /// Creates a blank GenericMIDI instance, which can be bound dynamically + GenericMIDI(int waste = 0, std::string name = "generic"); - virtual void trackJackSend(int t, float v); - virtual void trackJackSendActivate(int t, bool a); - - /// footswitch -> scene launch controls - void setFootswitchToNextScene(int v); - bool footswitchNextScene; - bool footswitchPrevScene; - - - void reset(); - - void midi(unsigned char* data); - - void process(int nframes); - - const std::vector& getMidiToAction(); - - // for adding bindings from MIDI / GUI event pair - void setupBinding( LupppAction eventType, int midiStatus, int midiData, int track, int scene, int send, int active ); - void removeBinding( int bindingID ); - - private: - STATUS stat; - - std::string name; - std::string author; - std::string email; - - /// contains midi binding instances - std::vector midiToAction; - std::vector actionToMidi; - - int loadController(std::string controllerFile); - - /// creates a binding from a cJSON inputBindings / outputBindings object - Binding* setupBinding( cJSON* bindings ); - - - /// for "sampling" a clip in the grid, and applying events to it: - /// footpedal for example - bool shiftPressed; - int footpedalTrack; - int footpedalScene; - - /* - /// for handling events - void ccChange( int track, int cc, float value ); - void noteOff( int track, int note, int vel ); - void noteOn( int track, int note, int vel ); - */ + /// Attempts to load a .ctlr file, pointed to by the string + GenericMIDI(std::string file); + + int registerComponents(); + + Controller::STATUS status(); + + void setName(std::string ); + std::string getName(); + std::string getAuthor(); + std::string getEmail(); + + /// track actions + //void mute(int t, bool b); + + void metronomeEnable(bool b); + + void launchScene( int scene ); + + void volume(int t, float f); + + + void recordArm(int t, bool b); + void setSceneState(int track, int clip, GridLogic::State s); + + /* + void progress(int t, int s, float f); + void launchScene( int scene ); + + /// track FX + void trackSend(int t, int send, float v); + */ + + void trackSend(int t, int send, float v); + void trackSendActive(int t, int send, bool a); + + virtual void trackJackSend(int t, float v); + virtual void trackJackSendActivate(int t, bool a); + + /// footswitch -> scene launch controls + void setFootswitchToNextScene(int v); + bool footswitchNextScene; + bool footswitchPrevScene; + + + void reset(); + + void midi(unsigned char* data); + + void process(int nframes); + + const std::vector& getMidiToAction(); + + // for adding bindings from MIDI / GUI event pair + void setupBinding( LupppAction eventType, int midiStatus, int midiData, int track, int scene, int send, int active ); + void removeBinding( int bindingID ); + +private: + STATUS stat; + + std::string name; + std::string author; + std::string email; + + /// contains midi binding instances + std::vector midiToAction; + std::vector actionToMidi; + + int loadController(std::string controllerFile); + + /// creates a binding from a cJSON inputBindings / outputBindings object + Binding* setupBinding( cJSON* bindings ); + + + /// for "sampling" a clip in the grid, and applying events to it: + /// footpedal for example + bool shiftPressed; + int footpedalTrack; + int footpedalScene; + + /* + /// for handling events + void ccChange( int track, int cc, float value ); + void noteOff( int track, int note, int vel ); + void noteOn( int track, int note, int vel ); + */ }; #endif // LUPPP_GENERIC_MIDI_H diff --git a/src/controller/guicontroller.cxx b/src/controller/guicontroller.cxx index bc7a5c3..2a91f22 100644 --- a/src/controller/guicontroller.cxx +++ b/src/controller/guicontroller.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -30,120 +30,120 @@ extern Jack* jack; LupppGUI::LupppGUI() : - Controller() + Controller() { } void LupppGUI::masterInputVol(float f) { - EventMasterInputVol e( f ); - writeToGuiRingbuffer( &e ); + EventMasterInputVol e( f ); + writeToGuiRingbuffer( &e ); } void LupppGUI::masterInputTo(int to,float f) { - EventMasterInputTo e( (Event::INPUT_TO)to, f ); - writeToGuiRingbuffer( &e ); + EventMasterInputTo e( (Event::INPUT_TO)to, f ); + writeToGuiRingbuffer( &e ); } void LupppGUI::masterInputToActive(int to,float f) { - EventMasterInputToActive e( (Event::INPUT_TO)to, f ); - writeToGuiRingbuffer( &e ); + EventMasterInputToActive e( (Event::INPUT_TO)to, f ); + writeToGuiRingbuffer( &e ); } void LupppGUI::masterVolume(float f) { - EventMasterVol e( f ); - writeToGuiRingbuffer( &e ); + EventMasterVol e( f ); + writeToGuiRingbuffer( &e ); } void LupppGUI::masterReturnVolume(float f) { - printf(" return %f ", f ); - EventMasterReturn e( RETURN_MAIN, f ); - writeToGuiRingbuffer( &e ); + printf(" return %f ", f ); + EventMasterReturn e( RETURN_MAIN, f ); + writeToGuiRingbuffer( &e ); } void LupppGUI::metronomeEnable(bool r) { - EventMetronomeActive e( r ); - writeToGuiRingbuffer( &e ); + EventMetronomeActive e( r ); + writeToGuiRingbuffer( &e ); } void LupppGUI::recordArm(int t, bool r) { - EventTrackRecordArm e( t, r ); - writeToGuiRingbuffer( &e ); + EventTrackRecordArm e( t, r ); + writeToGuiRingbuffer( &e ); } void LupppGUI::trackSend(int t, int send, float r) { - EventTrackSend e( t, static_cast(send), r ); - writeToGuiRingbuffer( &e ); + EventTrackSend e( t, static_cast(send), r ); + writeToGuiRingbuffer( &e ); } void LupppGUI::specialScene(int t, int s) { - EventGridSelectNewChosen e( t, s ); - writeToGuiRingbuffer( &e ); + EventGridSelectNewChosen e( t, s ); + writeToGuiRingbuffer( &e ); } void LupppGUI::trackSendActive(int t, int send, bool a) { - EventTrackSendActive e( t, static_cast(send), a ); - writeToGuiRingbuffer( &e ); + EventTrackSendActive e( t, static_cast(send), a ); + writeToGuiRingbuffer( &e ); } void LupppGUI::trackJackSend(int t, float v) { - EventTrackJackSend e(t,v); - writeToGuiRingbuffer(&e); + EventTrackJackSend e(t,v); + writeToGuiRingbuffer(&e); } void LupppGUI::trackJackSendActivate(int t, bool a) { - EventTrackJackSendActivate e(t,a); - writeToGuiRingbuffer(&e); + EventTrackJackSendActivate e(t,a); + writeToGuiRingbuffer(&e); } void LupppGUI::setSceneState(int t, int clip, GridLogic::State s) { - EventGridState e( t, clip, s ); - writeToGuiRingbuffer( &e ); + EventGridState e( t, clip, s ); + writeToGuiRingbuffer( &e ); } void LupppGUI::launchScene( int scene ) { - EventGridLaunchScene e( scene ); - writeToGuiRingbuffer( &e ); + EventGridLaunchScene e( scene ); + writeToGuiRingbuffer( &e ); } void LupppGUI::mute(int t, bool b) { - + } void LupppGUI::tapTempo( bool b ) { - EventTimeTempoTap e(b); - writeToGuiRingbuffer( &e ); + EventTimeTempoTap e(b); + writeToGuiRingbuffer( &e ); } void LupppGUI::bpm(int bpm) { - EventTimeBPM e(bpm); - writeToGuiRingbuffer( &e ); + EventTimeBPM e(bpm); + writeToGuiRingbuffer( &e ); } void LupppGUI::volume(int t, float f) { - EventTrackVol e( t, f ); - writeToGuiRingbuffer( &e ); + EventTrackVol e( t, f ); + writeToGuiRingbuffer( &e ); } void LupppGUI::progress(int t, int s, float f) { - EventLooperProgress e( t, f ); - writeToGuiRingbuffer( &e ); + EventLooperProgress e( t, f ); + writeToGuiRingbuffer( &e ); } diff --git a/src/controller/guicontroller.hxx b/src/controller/guicontroller.hxx index f346b50..b4cc766 100644 --- a/src/controller/guicontroller.hxx +++ b/src/controller/guicontroller.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -26,37 +26,40 @@ class LupppGUI : public Controller { - public: - LupppGUI(); - - std::string getName(){return "Luppp GUI";} - - void masterVolume(float f); - void masterReturnVolume(float f); - void masterInputVol(float v); - void masterInputTo(int to,float f); - void masterInputToActive(int to,float f); - - void metronomeEnable(bool b); - - void trackSend(int t, int send, float r); - void trackSendActive(int t, int send, bool a); +public: + LupppGUI(); + + std::string getName() + { + return "Luppp GUI"; + } + + void masterVolume(float f); + void masterReturnVolume(float f); + void masterInputVol(float v); + void masterInputTo(int to,float f); + void masterInputToActive(int to,float f); + + void metronomeEnable(bool b); + + void trackSend(int t, int send, float r); + void trackSendActive(int t, int send, bool a); + + virtual void trackJackSend(int t, float v); + virtual void trackJackSendActivate(int t, bool a); + + void bpm(int bpm); + void tapTempo( bool b ); + + void specialScene(int t, int scene); + + 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 launchScene( int scene ); + void setSceneState(int track, int clip, GridLogic::State s); - virtual void trackJackSend(int t, float v); - virtual void trackJackSendActivate(int t, bool a); - - void bpm(int bpm); - void tapTempo( bool b ); - - void specialScene(int t, int scene); - - 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 launchScene( int scene ); - void setSceneState(int track, int clip, GridLogic::State s); - }; #endif // LUPPP_CONTROLLER_GUI_H diff --git a/src/controller/nonseq.cxx b/src/controller/nonseq.cxx index 7bb6060..33d0de3 100644 --- a/src/controller/nonseq.cxx +++ b/src/controller/nonseq.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -26,56 +26,56 @@ #include "../looperclip.hxx" NonSeq::NonSeq() : - Controller(), - MidiIO() + Controller(), + MidiIO() { - std::string name = "non-seq"; - registerMidiPorts( name ); + std::string name = "non-seq"; + registerMidiPorts( name ); } void NonSeq::launchScene( int scene ) { - unsigned char data[3]; - data[0] = 176; - data[1] = 20; - data[2] = scene; - - //LUPPP_NOTE("NonSeq::launchScene() %i, %i, %i\n", data[0],data[1],data[2] ); - writeMidi( data ); + unsigned char data[3]; + data[0] = 176; + data[1] = 20; + data[2] = scene; + + //LUPPP_NOTE("NonSeq::launchScene() %i, %i, %i\n", data[0],data[1],data[2] ); + writeMidi( data ); } std::string NonSeq::getName() { - return "non-seq"; + return "non-seq"; } void NonSeq::setSceneState(int track, int scene, GridLogic::State s) { - unsigned char data[3]; - data[0] = 176; - data[1] = 22; // off - - // check *actual* value of playing: *NOT* GridState::s, because it could be queued - // for something else, but we want the *actual* here, not "queued". This is a unique - // use case because were trying to control non-seq as if it were part of Luppp. - if( jack->getLooper( track )->getClip( scene )->playing() ) - data[1] = 21; - - data[2] = track; - - //LUPPP_NOTE("NonSeq::setSceneState() %i, %i, %i\n", data[0],data[1],data[2] ); - writeMidi( data ); + unsigned char data[3]; + data[0] = 176; + data[1] = 22; // off + + // check *actual* value of playing: *NOT* GridState::s, because it could be queued + // for something else, but we want the *actual* here, not "queued". This is a unique + // use case because were trying to control non-seq as if it were part of Luppp. + if( jack->getLooper( track )->getClip( scene )->playing() ) + data[1] = 21; + + data[2] = track; + + //LUPPP_NOTE("NonSeq::setSceneState() %i, %i, %i\n", data[0],data[1],data[2] ); + writeMidi( data ); } int NonSeq::registerComponents() { - // makes JACK add this controller to the midiObservers list: - // note the static_cast<>() is *needed* here for multiple-inheritance - MidiIO* m = static_cast(this); - - jack->registerMidiIO( m ); - - return LUPPP_RETURN_OK; + // makes JACK add this controller to the midiObservers list: + // note the static_cast<>() is *needed* here for multiple-inheritance + MidiIO* m = static_cast(this); + + jack->registerMidiIO( m ); + + return LUPPP_RETURN_OK; } diff --git a/src/controller/nonseq.hxx b/src/controller/nonseq.hxx index 6bcc3a4..fb20666 100644 --- a/src/controller/nonseq.hxx +++ b/src/controller/nonseq.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -29,17 +29,17 @@ **/ class NonSeq : public Controller, public MidiIO { - public: - NonSeq(); - ~NonSeq(){}; - - std::string getName(); - - int registerComponents(); - - void launchScene( int scene ); - - void setSceneState(int track, int scene, GridLogic::State s); +public: + NonSeq(); + ~NonSeq() {}; + + std::string getName(); + + int registerComponents(); + + void launchScene( int scene ); + + void setSceneState(int track, int scene, GridLogic::State s); }; #endif // LUPPP_NON_SEQ_H diff --git a/src/controllerupdater.cxx b/src/controllerupdater.cxx index 546dcb5..12a7240 100644 --- a/src/controllerupdater.cxx +++ b/src/controllerupdater.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -22,167 +22,162 @@ ControllerUpdater::ControllerUpdater() { - // CAREFUL size of controllers: otherwise malloc() called - c.reserve( CONTROLLERS_PREALLOC ); + // CAREFUL size of controllers: otherwise malloc() called + c.reserve( CONTROLLERS_PREALLOC ); } void ControllerUpdater::registerController( Controller* controller ) { - if (!controller) - { - LUPPP_ERROR("Register Controller passed NULL controller!"); - return; - } - - //LUPPP_NOTE("Registering controller %s", controller->getName().c_str() ); - - // store the controller instance - c.push_back( controller ); - - // and tell it to register itself (MidiObserver / AudioObserver etc) - controller->registerComponents(); + if (!controller) { + LUPPP_ERROR("Register Controller passed NULL controller!"); + return; + } + + //LUPPP_NOTE("Registering controller %s", controller->getName().c_str() ); + + // store the controller instance + c.push_back( controller ); + + // and tell it to register itself (MidiObserver / AudioObserver etc) + controller->registerComponents(); } void ControllerUpdater::removeController( int id ) { - for( unsigned int i = 0; i < c.size(); i++) - { - if ( c.at(i)->getID() == id ) - { - // keep pointer: otherwise we mem-leak - Controller* removed = c.at( i ); - - cout << "Removing item " << i << " with name " << removed->getName() << endl; - - // remove the instance at - c.erase( c.begin() + i ); - - // send it for de-allocation - EventControllerInstance e( removed ); - writeToGuiRingbuffer( &e ); - } - } - + for( unsigned int i = 0; i < c.size(); i++) { + if ( c.at(i)->getID() == id ) { + // keep pointer: otherwise we mem-leak + Controller* removed = c.at( i ); + + cout << "Removing item " << i << " with name " << removed->getName() << endl; + + // remove the instance at + c.erase( c.begin() + i ); + + // send it for de-allocation + EventControllerInstance e( removed ); + writeToGuiRingbuffer( &e ); + } + } + } Controller* ControllerUpdater::getController(int id) { - // search controllers for ID, if found return a pointer to it - for( unsigned int i = 0; i < c.size(); i++) - { - if ( c.at(i)->getID() == id ) - { - LUPPP_NOTE("getController target ID: %i, found ID: %i, returning %s", id, i, c.at(i)->getName().c_str() ); - return c.at(i); - } - } - return 0; + // search controllers for ID, if found return a pointer to it + for( unsigned int i = 0; i < c.size(); i++) { + if ( c.at(i)->getID() == id ) { + LUPPP_NOTE("getController target ID: %i, found ID: %i, returning %s", id, i, c.at(i)->getName().c_str() ); + return c.at(i); + } + } + return 0; } void ControllerUpdater::reset() { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->reset(); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->reset(); } void ControllerUpdater::mute(int t, bool b) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->mute(t,b); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->mute(t,b); } void ControllerUpdater::masterVolume(float v) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->masterVolume(v); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->masterVolume(v); } void ControllerUpdater::masterReturnVolume(float v) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->masterReturnVolume( v ); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->masterReturnVolume( v ); } void ControllerUpdater::setTrackSceneProgress(int t, int s, float p) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->progress(t,s,p); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->progress(t,s,p); } void ControllerUpdater::setTrackSendActive(int t, int send, bool v) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->trackSendActive(t, send, v); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->trackSendActive(t, send, v); } void ControllerUpdater::setTrackSend(int t, int send, float v) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->trackSend(t, send, v); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->trackSend(t, send, v); } void ControllerUpdater::setTrackJackSendActive(int t, bool v) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->trackJackSendActivate(t, v); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->trackJackSendActivate(t, v); } void ControllerUpdater::setTrackJackSend(int t, float v) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->trackJackSend(t, v); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->trackJackSend(t, v); } void ControllerUpdater::specialScene(int t, int scene) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->specialScene(t, scene); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->specialScene(t, scene); } void ControllerUpdater::masterInputToActive(int to, bool v) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->masterInputToActive( to, v); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->masterInputToActive( to, v); } void ControllerUpdater::masterInputTo( int to, float v ) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->masterInputTo( to, v); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->masterInputTo( to, v); } void ControllerUpdater::masterInputVol( float v ) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->masterInputVol( v ); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->masterInputVol( v ); } void ControllerUpdater::launchScene( int scene ) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->launchScene(scene); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->launchScene(scene); } void ControllerUpdater::setSceneState(int t, int clip, GridLogic::State s) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->setSceneState(t,clip,s); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->setSceneState(t,clip,s); } void ControllerUpdater::recordArm(int t, bool r) { - for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->recordArm(t,r); + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->recordArm(t,r); } void ControllerUpdater::volume(int t, float v) { - for(unsigned int i = 0; i < c.size(); i++) c.at(i)->volume(t,v); + for(unsigned int i = 0; i < c.size(); i++) c.at(i)->volume(t,v); } void ControllerUpdater::tapTempo(bool b) { - for(unsigned int i = 0; i < c.size(); i++) c.at(i)->tapTempo(b); + for(unsigned int i = 0; i < c.size(); i++) c.at(i)->tapTempo(b); } void ControllerUpdater::metronomeEnable(bool b) { - for(unsigned int i = 0; i < c.size(); i++) c.at(i)->metronomeEnable(b); + for(unsigned int i = 0; i < c.size(); i++) c.at(i)->metronomeEnable(b); } diff --git a/src/controllerupdater.hxx b/src/controllerupdater.hxx index 216cb54..c46a050 100644 --- a/src/controllerupdater.hxx +++ b/src/controllerupdater.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -33,60 +33,60 @@ using namespace std; * Updates each registered controller when a certain event occurs. All output * devices (MIDI controllers, GUI, OSC-UI's etc) are registered in order to * stay up-to-date. - * + * * This class does no scheduling, it passes the events to the Controllers * immidiatly. - * + * * The Logic class is the opposite of this: it takes input and Luppp processes * it, pushing the relevant updates in state through ControllerUpdater to each * registered device. **/ class ControllerUpdater { - public: - ControllerUpdater(); - - /// add a Controller* to Controllers that recieve updates - void registerController( Controller* controller ); - - /// removes a controller by ID - void removeController( int controllerID ); - - /// returns a Controller* from ID - Controller* getController(int id); - - void reset(); - void mute(int t, bool b); - - void masterVolume(float v); - void masterReturnVolume(float v); - void masterInputToActive(int to, bool v); - void masterInputTo( int inputTo, float vol ); - void masterInputVol( float vol ); - - void setTrackSceneProgress(int t, int s, float p); - void setTrackSendActive(int t, int send, bool v); - void setTrackSend(int t, int send, float v); +public: + ControllerUpdater(); - void setTrackJackSendActive(int t, bool v); - void setTrackJackSend(int t, float v); - - void specialScene(int t, int scene); - - void launchScene( int scene ); - - void setSceneState(int t, int clip, GridLogic::State s); - - void recordArm(int t, bool r); - - void volume(int t, float v); - - void tapTempo(bool b); - - void metronomeEnable(bool b); - - private: - std::vector c; + /// add a Controller* to Controllers that recieve updates + void registerController( Controller* controller ); + + /// removes a controller by ID + void removeController( int controllerID ); + + /// returns a Controller* from ID + Controller* getController(int id); + + void reset(); + void mute(int t, bool b); + + void masterVolume(float v); + void masterReturnVolume(float v); + void masterInputToActive(int to, bool v); + void masterInputTo( int inputTo, float vol ); + void masterInputVol( float vol ); + + void setTrackSceneProgress(int t, int s, float p); + void setTrackSendActive(int t, int send, bool v); + void setTrackSend(int t, int send, float v); + + void setTrackJackSendActive(int t, bool v); + void setTrackJackSend(int t, float v); + + void specialScene(int t, int scene); + + void launchScene( int scene ); + + void setSceneState(int t, int clip, GridLogic::State s); + + void recordArm(int t, bool r); + + void volume(int t, float v); + + void tapTempo(bool b); + + void metronomeEnable(bool b); + +private: + std::vector c; }; #endif // LUPPP_CONTROLLER_UPDATER_H diff --git a/src/debug.cxx b/src/debug.cxx index a816a91..7e01396 100644 --- a/src/debug.cxx +++ b/src/debug.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -24,34 +24,26 @@ void luppp_debug( int warnLevel, const char* name, const char* file, const char* func, int line, const char* format, ... ) { - if ( warnLevel == DEBUG_LEVEL_ERROR ) - { - printf( "[\033[1;31m%s\033[0m] %s:%i: ", name, func, line ); - } - else if ( warnLevel == DEBUG_LEVEL_WARN ) - { - printf( "[\033[1;33m%s\033[0m] %s:%i: ", name, func, line ); - } - else if ( warnLevel == DEBUG_LEVEL_TEST ) - { + if ( warnLevel == DEBUG_LEVEL_ERROR ) { + printf( "[\033[1;31m%s\033[0m] %s:%i: ", name, func, line ); + } else if ( warnLevel == DEBUG_LEVEL_WARN ) { + printf( "[\033[1;33m%s\033[0m] %s:%i: ", name, func, line ); + } else if ( warnLevel == DEBUG_LEVEL_TEST ) { #ifdef BUILD_TESTS - printf( "[\033[1;33m%s\033[0m] %s:%i: ", name, func, line ); + printf( "[\033[1;33m%s\033[0m] %s:%i: ", name, func, line ); #endif - } - else // NOTE - { - printf( "[\033[1;32m%s\033[0m] %s:%i: ", name, func, line ); - } - printf( "\033[0m" ); - - if ( format ) - { - va_list args; - va_start( args, format ); - vfprintf( stdout, format, args ); - va_end( args ); - } - printf( "\n" ); - + } else { // NOTE + printf( "[\033[1;32m%s\033[0m] %s:%i: ", name, func, line ); + } + printf( "\033[0m" ); + + if ( format ) { + va_list args; + va_start( args, format ); + vfprintf( stdout, format, args ); + va_end( args ); + } + printf( "\n" ); + } diff --git a/src/debug.hxx b/src/debug.hxx index 1dbc079..c30525b 100644 --- a/src/debug.hxx +++ b/src/debug.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -29,10 +29,10 @@ LUPPP_KILL( "%s", "MessageHere" ); */ enum DEBUG_LEVEL { - DEBUG_LEVEL_NOTE = 0, - DEBUG_LEVEL_WARN, - DEBUG_LEVEL_ERROR, - DEBUG_LEVEL_TEST + DEBUG_LEVEL_NOTE = 0, + DEBUG_LEVEL_WARN, + DEBUG_LEVEL_ERROR, + DEBUG_LEVEL_TEST }; void luppp_debug( int warnLevel, const char* name, const char* file, const char* func, int line, diff --git a/src/denormals.hxx b/src/denormals.hxx index 7b6eed5..833c954 100644 --- a/src/denormals.hxx +++ b/src/denormals.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -29,23 +29,23 @@ #include inline void AVOIDDENORMALS() { - //LUPPP_NOTE("Denormals: FZ DAZ using SSE3"); - _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); - _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); + //LUPPP_NOTE("Denormals: FZ DAZ using SSE3"); + _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); + _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); } #else #include inline void AVOIDDENORMALS() { - //LUPPP_NOTE("Denormals: FZ"); - _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); + //LUPPP_NOTE("Denormals: FZ"); + _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); } #endif //__SSE3__ #else inline void AVOIDDENORMALS() { - LUPPP_NOTE( "Denormals: Warning! No protection" ); + LUPPP_NOTE( "Denormals: Warning! No protection" ); } #endif //__SSE__ diff --git a/src/diskreader.cxx b/src/diskreader.cxx index 68f4de4..fba02d9 100644 --- a/src/diskreader.cxx +++ b/src/diskreader.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -43,650 +43,593 @@ using namespace std; DiskReader::DiskReader() { - resampleQuality = 1; - - // FIXME: could use a config item of sample location? - lastLoadedSamplePath = getenv("HOME"); + resampleQuality = 1; + + // FIXME: could use a config item of sample location? + lastLoadedSamplePath = getenv("HOME"); } int DiskReader::loadPreferences() { - stringstream s; - s << getenv("HOME") << "/.config/openAV/luppp/luppp.prfs"; - std::ifstream sampleFile( s.str().c_str(), std::ios_base::in|std::ios_base::ate); - - long file_length = sampleFile.tellg(); - if ( file_length > 0 ) - { - sampleFile.seekg(0, std::ios_base::beg); - sampleFile.clear(); - char *sampleString = new char[file_length]; - sampleFile.read(sampleString, file_length); - - cJSON* preferencesJson = cJSON_Parse( sampleString ); - if (!preferencesJson) - { - LUPPP_WARN("Preferences JSON not valid"); - return LUPPP_RETURN_ERROR; - } - - - cJSON* resample = cJSON_GetObjectItem( preferencesJson, "resampleQuality" ); - if ( resample ) - { - resampleQuality = resample->valueint; - if ( resampleQuality == 0 ) - { - LUPPP_NOTE("Using Linear resampling, may reduce quality. Check .config/openAV/luppp/luppp.prfs"); - } - } - cJSON* ctlrs = cJSON_GetObjectItem( preferencesJson, "defaultControllers" ); - if ( ctlrs ) - { - //cout << ".ctlr HAS items." << endl; - int nCtlrs = cJSON_GetArraySize( ctlrs ); - for(int i = 0; i < nCtlrs; i++ ) - { - cJSON* ctlr = cJSON_GetArrayItem( ctlrs, i ); - if( ctlr ) - { - LUPPP_NOTE("Loading controller %s", ctlr->valuestring); - stringstream s; - s << getenv("HOME") << "/.config/openAV/luppp/controllers/" << ctlr->valuestring; - gui->addMidiControllerToSetup( s.str() ); - } - } - } - else - { - LUPPP_NOTE("No default controllers active."); - } + stringstream s; + s << getenv("HOME") << "/.config/openAV/luppp/luppp.prfs"; + std::ifstream sampleFile( s.str().c_str(), std::ios_base::in|std::ios_base::ate); + + long file_length = sampleFile.tellg(); + if ( file_length > 0 ) { + sampleFile.seekg(0, std::ios_base::beg); + sampleFile.clear(); + char *sampleString = new char[file_length]; + sampleFile.read(sampleString, file_length); + + cJSON* preferencesJson = cJSON_Parse( sampleString ); + if (!preferencesJson) { + LUPPP_WARN("Preferences JSON not valid"); + return LUPPP_RETURN_ERROR; + } - cJSON* projDir=cJSON_GetObjectItem(preferencesJson,"saveDirectory"); - string dir=getenv("HOME"); - if(projDir) - { - stringstream s; - s<valuestring; - dir=s.str(); - } - gui->setProjectsDir(dir); + cJSON* resample = cJSON_GetObjectItem( preferencesJson, "resampleQuality" ); + if ( resample ) { + resampleQuality = resample->valueint; + if ( resampleQuality == 0 ) { + LUPPP_NOTE("Using Linear resampling, may reduce quality. Check .config/openAV/luppp/luppp.prfs"); + } + } + cJSON* ctlrs = cJSON_GetObjectItem( preferencesJson, "defaultControllers" ); + if ( ctlrs ) { + //cout << ".ctlr HAS items." << endl; + int nCtlrs = cJSON_GetArraySize( ctlrs ); + for(int i = 0; i < nCtlrs; i++ ) { + cJSON* ctlr = cJSON_GetArrayItem( ctlrs, i ); + if( ctlr ) { + LUPPP_NOTE("Loading controller %s", ctlr->valuestring); + stringstream s; + s << getenv("HOME") << "/.config/openAV/luppp/controllers/" << ctlr->valuestring; + gui->addMidiControllerToSetup( s.str() ); + } + } + } else { + LUPPP_NOTE("No default controllers active."); + } - //Enable per track send and resturn jack ports? - cJSON* jackPerTrackOutput=cJSON_GetObjectItem(preferencesJson,"enablePerTrackOutput"); - if(jackPerTrackOutput) - { - gui->enablePerTrackOutput=jackPerTrackOutput->valueint; - if(gui->enablePerTrackOutput) - LUPPP_NOTE("Enabling per track output ports"); - } - //Metronome on by default? - cJSON* metronomeActive=cJSON_GetObjectItem(preferencesJson,"metronomeActiveByDefault"); - if(metronomeActive) - { - EventMetronomeActive e = EventMetronomeActive( metronomeActive->valueint); - writeToDspRingbuffer( &e ); - } + cJSON* projDir=cJSON_GetObjectItem(preferencesJson,"saveDirectory"); + string dir=getenv("HOME"); + if(projDir) { + stringstream s; + s<valuestring; + dir=s.str(); + } + gui->setProjectsDir(dir); - //Metronome default volume - cJSON* metronomeVol=cJSON_GetObjectItem(preferencesJson,"metronomeDefaultVolume"); - if(metronomeVol) - { - float vol=metronomeVol->valueint/100.0f; - EventMetronomeVolume e(vol); - writeToDspRingbuffer(&e); - } - - - cJSON_Delete( preferencesJson ); - delete[] sampleString; - } - else - { - // empty file / file no exists: - LUPPP_WARN("Preferences, file doesn't exist: ~/.config/openAV/luppp/luppp.prefs"); - - // so write default file - gui->getDiskWriter()->writeDefaultConfigToUserHome(); - - return LUPPP_RETURN_OK; - } - - return LUPPP_RETURN_OK; + //Enable per track send and resturn jack ports? + cJSON* jackPerTrackOutput=cJSON_GetObjectItem(preferencesJson,"enablePerTrackOutput"); + if(jackPerTrackOutput) { + gui->enablePerTrackOutput=jackPerTrackOutput->valueint; + if(gui->enablePerTrackOutput) + LUPPP_NOTE("Enabling per track output ports"); + } + + //Metronome on by default? + cJSON* metronomeActive=cJSON_GetObjectItem(preferencesJson,"metronomeActiveByDefault"); + if(metronomeActive) { + EventMetronomeActive e = EventMetronomeActive( metronomeActive->valueint); + writeToDspRingbuffer( &e ); + } + + //Metronome default volume + cJSON* metronomeVol=cJSON_GetObjectItem(preferencesJson,"metronomeDefaultVolume"); + if(metronomeVol) { + float vol=metronomeVol->valueint/100.0f; + EventMetronomeVolume e(vol); + writeToDspRingbuffer(&e); + } + + + cJSON_Delete( preferencesJson ); + delete[] sampleString; + } else { + // empty file / file no exists: + LUPPP_WARN("Preferences, file doesn't exist: ~/.config/openAV/luppp/luppp.prefs"); + + // so write default file + gui->getDiskWriter()->writeDefaultConfigToUserHome(); + + return LUPPP_RETURN_OK; + } + + return LUPPP_RETURN_OK; } int DiskReader::showAudioEditor(AudioBuffer* ab) { - while ( ab->getBeats() == 0 ) - { - // FIXME: Cancel = no load sample? - gui->getAudioEditor()->show( ab, true ); - - while ( gui->getAudioEditor()->shown() ) Fl::wait(); - - // handle "cancel" return - if ( ab->getBeats() == -1 ) - { - return LUPPP_RETURN_ERROR; - } - } - - return LUPPP_RETURN_OK; + while ( ab->getBeats() == 0 ) { + // FIXME: Cancel = no load sample? + gui->getAudioEditor()->show( ab, true ); + + while ( gui->getAudioEditor()->shown() ) Fl::wait(); + + // handle "cancel" return + if ( ab->getBeats() == -1 ) { + return LUPPP_RETURN_ERROR; + } + } + + return LUPPP_RETURN_OK; } int DiskReader::loadSample( int track, int scene, string path ) { - /// load the sample - SndfileHandle infile( path, SFM_READ ); - std::vector buf( infile.frames() * infile.channels() ); - infile.read( (float*)&buf[0] , infile.frames() * infile.channels() ); - - if ( infile.error() ) - { - LUPPP_ERROR("File %s, Error %s", path.c_str(), infile.strError() ); - return LUPPP_RETURN_ERROR; - } - - LUPPP_NOTE("Loading file with %i chnls, frames %i,buffer size %i", infile.channels(), infile.frames(), buf.size() ); - - /// kick stereo channel? - int chnls = infile.channels(); - if ( chnls > 1 ) - { - // we're gonna kick all samples that are *not* channel 1 - std::vector tmp( buf.size() / chnls ); - - LUPPP_NOTE("Non mono file: %i chnls found, old size %i, new size %i ", infile.channels(), buf.size(), tmp.size() ); - - for(size_t i = 0; i < tmp.size(); i++ ) - { - tmp.at(i) = buf.at( i * chnls ); - } - - // swap the buffers - buf.swap( tmp ); - } - - /// resample? - if ( infile.samplerate() != gui->samplerate ) - { - LUPPP_NOTE("%s%i%s%i", "Resampling from ", infile.samplerate(), " to ", gui->samplerate); - - float resampleRatio = float(gui->samplerate) / infile.samplerate(); - std::vector resampled( infile.frames() * resampleRatio ); - - SRC_DATA data; - data.data_in = &buf[0]; - data.data_out = &resampled[0]; - - data.input_frames = infile.frames(); - data.output_frames = infile.frames() * resampleRatio; - - data.end_of_input = 0; - data.src_ratio = resampleRatio; - - int q = SRC_SINC_FASTEST; - - switch( resampleQuality ) - { - case 0: q = SRC_LINEAR; break; - case 1: q = SRC_SINC_FASTEST; break; - case 2: q = SRC_SINC_BEST_QUALITY; break; - } - - - // resample quality taken from config file, - int ret = src_simple ( &data, q, 1 ); - if ( ret == 0 ) - LUPPP_NOTE("%s%i%s%i", "Resampling finished, from ", data.input_frames_used, " to ", data.output_frames_gen ); - else - LUPPP_ERROR("%s%i%s%i", "Resampling finished, from ", data.input_frames_used, " to ", data.output_frames_gen ); - - /// exchange buffers, so buf contains the resampled audio - buf.swap( resampled ); - } - - - /// create buffer, and set the data - AudioBuffer* ab = new AudioBuffer(); - ab->setAudioFrames( buf.size() ); - ab->nonRtSetSample( buf ); - - //cout << "DiskReader::loadSample() " << path << endl; - - bool loadableBuffer = false; - - // retrieve sample metadata from sample.cfg using filename as key - char* tmp = strdup( path.c_str() ); - char* baseName = basename( tmp ); - //cout << "tmp " << tmp << " baseName " << baseName << endl; - ab->setName( baseName ); - - if ( infile.frames() > 0 ) - { - char* basePath = strdup( path.c_str() ); - stringstream base; - base << dirname( basePath ) << "/audio.cfg"; - - free( basePath ); - - /// open audio.cfg, reading whole file + /// load the sample + SndfileHandle infile( path, SFM_READ ); + std::vector buf( infile.frames() * infile.channels() ); + infile.read( (float*)&buf[0] , infile.frames() * infile.channels() ); + + if ( infile.error() ) { + LUPPP_ERROR("File %s, Error %s", path.c_str(), infile.strError() ); + return LUPPP_RETURN_ERROR; + } + + LUPPP_NOTE("Loading file with %i chnls, frames %i,buffer size %i", infile.channels(), infile.frames(), buf.size() ); + + /// kick stereo channel? + int chnls = infile.channels(); + if ( chnls > 1 ) { + // we're gonna kick all samples that are *not* channel 1 + std::vector tmp( buf.size() / chnls ); + + LUPPP_NOTE("Non mono file: %i chnls found, old size %i, new size %i ", infile.channels(), buf.size(), tmp.size() ); + + for(size_t i = 0; i < tmp.size(); i++ ) { + tmp.at(i) = buf.at( i * chnls ); + } + + // swap the buffers + buf.swap( tmp ); + } + + /// resample? + if ( infile.samplerate() != gui->samplerate ) { + LUPPP_NOTE("%s%i%s%i", "Resampling from ", infile.samplerate(), " to ", gui->samplerate); + + float resampleRatio = float(gui->samplerate) / infile.samplerate(); + std::vector resampled( infile.frames() * resampleRatio ); + + SRC_DATA data; + data.data_in = &buf[0]; + data.data_out = &resampled[0]; + + data.input_frames = infile.frames(); + data.output_frames = infile.frames() * resampleRatio; + + data.end_of_input = 0; + data.src_ratio = resampleRatio; + + int q = SRC_SINC_FASTEST; + + switch( resampleQuality ) { + case 0: + q = SRC_LINEAR; + break; + case 1: + q = SRC_SINC_FASTEST; + break; + case 2: + q = SRC_SINC_BEST_QUALITY; + break; + } + + + // resample quality taken from config file, + int ret = src_simple ( &data, q, 1 ); + if ( ret == 0 ) + LUPPP_NOTE("%s%i%s%i", "Resampling finished, from ", data.input_frames_used, " to ", data.output_frames_gen ); + else + LUPPP_ERROR("%s%i%s%i", "Resampling finished, from ", data.input_frames_used, " to ", data.output_frames_gen ); + + /// exchange buffers, so buf contains the resampled audio + buf.swap( resampled ); + } + + + /// create buffer, and set the data + AudioBuffer* ab = new AudioBuffer(); + ab->setAudioFrames( buf.size() ); + ab->nonRtSetSample( buf ); + + //cout << "DiskReader::loadSample() " << path << endl; + + bool loadableBuffer = false; + + // retrieve sample metadata from sample.cfg using filename as key + char* tmp = strdup( path.c_str() ); + char* baseName = basename( tmp ); + //cout << "tmp " << tmp << " baseName " << baseName << endl; + ab->setName( baseName ); + + if ( infile.frames() > 0 ) { + char* basePath = strdup( path.c_str() ); + stringstream base; + base << dirname( basePath ) << "/audio.cfg"; + + free( basePath ); + + /// open audio.cfg, reading whole file #ifdef DEBUG_STATE - cout << "loading sample metadata file " << base.str().c_str() << endl; + cout << "loading sample metadata file " << base.str().c_str() << endl; #endif - std::ifstream sampleFile( base.str().c_str(), std::ios_base::in|std::ios_base::ate); - long file_length = sampleFile.tellg(); - if ( file_length > 0 ) - { - sampleFile.seekg(0, std::ios_base::beg); - sampleFile.clear(); - char *sampleString = new char[file_length]; - sampleFile.read(sampleString, file_length); - - //cout << "Sample file:" << endl << sampleString << endl; - //cout << "Sample file (parsed):" << endl << cJSON_Parse( sampleString ) << endl; - - cJSON* audioJson = cJSON_Parse( sampleString ); - if (!audioJson) { - LUPPP_ERROR("%s %s","Error in Sample JSON before: ", cJSON_GetErrorPtr() ); - return LUPPP_RETURN_ERROR; - } - - cJSON* sample = cJSON_GetObjectItem( audioJson, baseName ); - if ( sample ) - { - cJSON* beats = cJSON_GetObjectItem( sample, "beats" ); - cJSON* name = cJSON_GetObjectItem( sample, "name" ); - //cout << "Clip @ " << track << " " << scene << " gets " << beats->valuedouble << " beats."<< endl; - if ( beats ) - { - loadableBuffer = true; - ab->setBeats( beats->valuedouble ); - } - - if ( name ) - { - ab->setName( name->valuestring ); - } - } - - // if we don't find the beats from audio.cfg, show dialog - if ( loadableBuffer == false ) - { - LUPPP_NOTE("Warning: audio.cfg has no entry for beats."); - int ret = showAudioEditor( ab ); - - if ( ret == LUPPP_RETURN_OK ) - { - // flag that we can load this sample OK - loadableBuffer = true; - } - else - { - delete ab; - } - } - - cJSON_Delete( audioJson ); - delete[] sampleString; - free ( tmp ); - } - else - { - // this means there's no audio.cfg file found for the sample: show the user - // the file, and ask what the intended beat number is, and load the AudioBuffer - LUPPP_WARN("%s %s","Empty or no audio.cfg found at ",base.str().c_str() ); - int error = showAudioEditor( ab ); - if ( error == LUPPP_RETURN_ERROR ) - { - LUPPP_WARN("cancel clicked, deleting audiobuffer" ); - delete ab; - } - else - { - std::string name = path; - int i = name.find_last_of('/') + 1; - std::string sub = name.substr( i ); - ab->setName( sub.c_str() ); - - LUPPP_NOTE("AudioBuffer %s set %i beats", ab->getName(), ab->getBeats() ); - - loadableBuffer = true; - } - } - - if ( loadableBuffer ) - { - std::string n = ab->getName(); - - // write audioBuffer to DSP - EventLooperLoad e = EventLooperLoad( track, scene, ab ); - writeToDspRingbuffer( &e ); - - // now write audiobuffer name to GUI on track, scene - gui->getTrack( track )->getClipSelector()->clipName( scene, n ); - - char* tmp = strdup( path.c_str() ); - lastLoadedSamplePath = dirname( tmp ); - free(tmp); - } - else - { - LUPPP_NOTE("AudioBuffer not loaded, missing beats info and dialog was Canceled" ); - } - } - - return LUPPP_RETURN_OK; - + std::ifstream sampleFile( base.str().c_str(), std::ios_base::in|std::ios_base::ate); + long file_length = sampleFile.tellg(); + if ( file_length > 0 ) { + sampleFile.seekg(0, std::ios_base::beg); + sampleFile.clear(); + char *sampleString = new char[file_length]; + sampleFile.read(sampleString, file_length); + + //cout << "Sample file:" << endl << sampleString << endl; + //cout << "Sample file (parsed):" << endl << cJSON_Parse( sampleString ) << endl; + + cJSON* audioJson = cJSON_Parse( sampleString ); + if (!audioJson) { + LUPPP_ERROR("%s %s","Error in Sample JSON before: ", cJSON_GetErrorPtr() ); + return LUPPP_RETURN_ERROR; + } + + cJSON* sample = cJSON_GetObjectItem( audioJson, baseName ); + if ( sample ) { + cJSON* beats = cJSON_GetObjectItem( sample, "beats" ); + cJSON* name = cJSON_GetObjectItem( sample, "name" ); + //cout << "Clip @ " << track << " " << scene << " gets " << beats->valuedouble << " beats."<< endl; + if ( beats ) { + loadableBuffer = true; + ab->setBeats( beats->valuedouble ); + } + + if ( name ) { + ab->setName( name->valuestring ); + } + } + + // if we don't find the beats from audio.cfg, show dialog + if ( loadableBuffer == false ) { + LUPPP_NOTE("Warning: audio.cfg has no entry for beats."); + int ret = showAudioEditor( ab ); + + if ( ret == LUPPP_RETURN_OK ) { + // flag that we can load this sample OK + loadableBuffer = true; + } else { + delete ab; + } + } + + cJSON_Delete( audioJson ); + delete[] sampleString; + free ( tmp ); + } else { + // this means there's no audio.cfg file found for the sample: show the user + // the file, and ask what the intended beat number is, and load the AudioBuffer + LUPPP_WARN("%s %s","Empty or no audio.cfg found at ",base.str().c_str() ); + int error = showAudioEditor( ab ); + if ( error == LUPPP_RETURN_ERROR ) { + LUPPP_WARN("cancel clicked, deleting audiobuffer" ); + delete ab; + } else { + std::string name = path; + int i = name.find_last_of('/') + 1; + std::string sub = name.substr( i ); + ab->setName( sub.c_str() ); + + LUPPP_NOTE("AudioBuffer %s set %i beats", ab->getName(), ab->getBeats() ); + + loadableBuffer = true; + } + } + + if ( loadableBuffer ) { + std::string n = ab->getName(); + + // write audioBuffer to DSP + EventLooperLoad e = EventLooperLoad( track, scene, ab ); + writeToDspRingbuffer( &e ); + + // now write audiobuffer name to GUI on track, scene + gui->getTrack( track )->getClipSelector()->clipName( scene, n ); + + char* tmp = strdup( path.c_str() ); + lastLoadedSamplePath = dirname( tmp ); + free(tmp); + } else { + LUPPP_NOTE("AudioBuffer not loaded, missing beats info and dialog was Canceled" ); + } + } + + return LUPPP_RETURN_OK; + } std::string DiskReader::getLastLoadedSamplePath() { - return lastLoadedSamplePath; + return lastLoadedSamplePath; } int DiskReader::readSession( std::string path ) { - cout << "DiskReader::readSession() " << path << endl; - sessionPath = path; - - stringstream s; - s << path << "/session.luppp"; - - stringstream samplePath; - samplePath << path << "/audio/audio.cfg"; - - cout << "session path: " << s.str() << endl; - cout << "audio path: " << samplePath.str() << endl; - - // open session, read all - std::ifstream file( s.str().c_str(), std::ios_base::in|std::ios_base::ate); - long file_length = file.tellg(); - if ( file_length < 0 ) - { - // empty file / file no exists: - LUPPP_ERROR("no session file exists!"); - return LUPPP_RETURN_ERROR; - } - - file.seekg(0, std::ios_base::beg); - file.clear(); - char *sessionString = new char[file_length]; - file.read(sessionString, file_length); - - // create cJSON nodes from strings - sessionJson = cJSON_Parse( sessionString ); - if (!sessionJson) { - LUPPP_ERROR("%s %s", "Error in Session JSON before: ", cJSON_GetErrorPtr() ); - return LUPPP_RETURN_ERROR; - } - - - int tr = readTracks(); - - int mr = readMaster(); - - if( tr == mr ){}; - - // cleanup - cJSON_Delete( sessionJson ); - delete[] sessionString; - - return LUPPP_RETURN_OK; + cout << "DiskReader::readSession() " << path << endl; + sessionPath = path; + + stringstream s; + s << path << "/session.luppp"; + + stringstream samplePath; + samplePath << path << "/audio/audio.cfg"; + + cout << "session path: " << s.str() << endl; + cout << "audio path: " << samplePath.str() << endl; + + // open session, read all + std::ifstream file( s.str().c_str(), std::ios_base::in|std::ios_base::ate); + long file_length = file.tellg(); + if ( file_length < 0 ) { + // empty file / file no exists: + LUPPP_ERROR("no session file exists!"); + return LUPPP_RETURN_ERROR; + } + + file.seekg(0, std::ios_base::beg); + file.clear(); + char *sessionString = new char[file_length]; + file.read(sessionString, file_length); + + // create cJSON nodes from strings + sessionJson = cJSON_Parse( sessionString ); + if (!sessionJson) { + LUPPP_ERROR("%s %s", "Error in Session JSON before: ", cJSON_GetErrorPtr() ); + return LUPPP_RETURN_ERROR; + } + + + int tr = readTracks(); + + int mr = readMaster(); + + if( tr == mr ) {}; + + // cleanup + cJSON_Delete( sessionJson ); + delete[] sessionString; + + return LUPPP_RETURN_OK; } int DiskReader::readMaster() { - cJSON* master = cJSON_GetObjectItem( sessionJson, "master"); - if ( master ) - { - // bpm - { - cJSON* bpm = cJSON_GetObjectItem( master, "bpm"); - if ( bpm ) { - LUPPP_NOTE("%s %i","Session: BPM ",bpm->valueint); - EventTimeBPM e( bpm->valuedouble ); - writeToDspRingbuffer( &e ); - } - } - // fader - { - cJSON* fader = cJSON_GetObjectItem( master, "fader"); - if ( fader ) { - EventTrackVol e( -1, fader->valuedouble ); - writeToDspRingbuffer( &e ); - } - } - // input volume - { - cJSON* cjson = cJSON_GetObjectItem( master, "inputVolume"); - if ( cjson ) { - EventMasterInputVol e( cjson->valuedouble ); - writeToDspRingbuffer( &e ); } - } - // input to send - { - cJSON* cjson = cJSON_GetObjectItem( master, "inputToSndVol"); - if ( cjson ) { - EventMasterInputTo e( INPUT_TO_SEND, cjson->valuedouble ); - writeToDspRingbuffer( &e ); } - } - // input to key - { - cJSON* cjson = cJSON_GetObjectItem( master, "inputToXSide"); - if ( cjson ) { - EventMasterInputTo e( INPUT_TO_XSIDE, cjson->valuedouble ); - writeToDspRingbuffer( &e ); } - } - // input to mix - { - cJSON* cjson = cJSON_GetObjectItem( master, "inputToMixVol"); - if ( cjson ) { - EventMasterInputTo e( INPUT_TO_MIX, cjson->valuedouble ); - writeToDspRingbuffer( &e ); } - } - - // input to send active - { - cJSON* cjson = cJSON_GetObjectItem( master, "inputToSndActive"); - if ( cjson ) { - EventMasterInputTo e( INPUT_TO_SEND, cjson->valuedouble ); - writeToDspRingbuffer( &e ); } - } - // input to key active - { - cJSON* cjson = cJSON_GetObjectItem( master, "inputToKeyActive"); - if ( cjson ) { - EventMasterInputTo e( INPUT_TO_SIDE_KEY, cjson->valuedouble ); - writeToDspRingbuffer( &e ); } - } - // input to mix active - { - cJSON* cjson = cJSON_GetObjectItem( master, "inputToMixActive"); - if ( cjson ) { - EventMasterInputTo e( INPUT_TO_MIX, cjson->valuedouble ); - writeToDspRingbuffer( &e ); } - } - - // reverb - { - cJSON* reverb = cJSON_GetObjectItem( master, "reverb"); - if ( reverb ) - { - cJSON* active = cJSON_GetObjectItem( reverb, "active"); - cJSON* size = cJSON_GetObjectItem( reverb, "size"); - cJSON* wet = cJSON_GetObjectItem( reverb, "wet"); - cJSON* damping = cJSON_GetObjectItem( reverb, "damping"); - - if ( active && size && wet && damping ) - { - EventFxReverb e( active->valuedouble, size->valuedouble, - wet->valuedouble, damping->valuedouble ); - writeToDspRingbuffer( &e ); - } - } - else - { + cJSON* master = cJSON_GetObjectItem( sessionJson, "master"); + if ( master ) { + // bpm + { + cJSON* bpm = cJSON_GetObjectItem( master, "bpm"); + if ( bpm ) { + LUPPP_NOTE("%s %i","Session: BPM ",bpm->valueint); + EventTimeBPM e( bpm->valuedouble ); + writeToDspRingbuffer( &e ); + } + } + // fader + { + cJSON* fader = cJSON_GetObjectItem( master, "fader"); + if ( fader ) { + EventTrackVol e( -1, fader->valuedouble ); + writeToDspRingbuffer( &e ); + } + } + // input volume + { + cJSON* cjson = cJSON_GetObjectItem( master, "inputVolume"); + if ( cjson ) { + EventMasterInputVol e( cjson->valuedouble ); + writeToDspRingbuffer( &e ); + } + } + // input to send + { + cJSON* cjson = cJSON_GetObjectItem( master, "inputToSndVol"); + if ( cjson ) { + EventMasterInputTo e( INPUT_TO_SEND, cjson->valuedouble ); + writeToDspRingbuffer( &e ); + } + } + // input to key + { + cJSON* cjson = cJSON_GetObjectItem( master, "inputToXSide"); + if ( cjson ) { + EventMasterInputTo e( INPUT_TO_XSIDE, cjson->valuedouble ); + writeToDspRingbuffer( &e ); + } + } + // input to mix + { + cJSON* cjson = cJSON_GetObjectItem( master, "inputToMixVol"); + if ( cjson ) { + EventMasterInputTo e( INPUT_TO_MIX, cjson->valuedouble ); + writeToDspRingbuffer( &e ); + } + } + + // input to send active + { + cJSON* cjson = cJSON_GetObjectItem( master, "inputToSndActive"); + if ( cjson ) { + EventMasterInputTo e( INPUT_TO_SEND, cjson->valuedouble ); + writeToDspRingbuffer( &e ); + } + } + // input to key active + { + cJSON* cjson = cJSON_GetObjectItem( master, "inputToKeyActive"); + if ( cjson ) { + EventMasterInputTo e( INPUT_TO_SIDE_KEY, cjson->valuedouble ); + writeToDspRingbuffer( &e ); + } + } + // input to mix active + { + cJSON* cjson = cJSON_GetObjectItem( master, "inputToMixActive"); + if ( cjson ) { + EventMasterInputTo e( INPUT_TO_MIX, cjson->valuedouble ); + writeToDspRingbuffer( &e ); + } + } + + // reverb + { + cJSON* reverb = cJSON_GetObjectItem( master, "reverb"); + if ( reverb ) { + cJSON* active = cJSON_GetObjectItem( reverb, "active"); + cJSON* size = cJSON_GetObjectItem( reverb, "size"); + cJSON* wet = cJSON_GetObjectItem( reverb, "wet"); + cJSON* damping = cJSON_GetObjectItem( reverb, "damping"); + + if ( active && size && wet && damping ) { + EventFxReverb e( active->valuedouble, size->valuedouble, + wet->valuedouble, damping->valuedouble ); + writeToDspRingbuffer( &e ); + } + } else { #ifdef DEBUG_STATE - cout << "Session has no reverb element" << endl; + cout << "Session has no reverb element" << endl; #endif - } - } - // TODO add samplerate to session JSON - - // sceneNames - { - cJSON* names = cJSON_GetObjectItem( master, "sceneNames"); - if ( names ) - { - GMasterTrack* master = gui->getMasterTrack(); - Avtk::ClipSelector* clipSelector = master->getClipSelector(); - int nscenes = cJSON_GetArraySize( names ); - for(int s = 0; s < nscenes; s++ ) - { - cJSON* name = cJSON_GetArrayItem( names, s ); - clipSelector->clipName( s, name->valuestring ); - } - clipSelector->redraw(); - } - } - - } - else - { - LUPPP_ERROR("%s", "Error getting master from JSON" ); - return LUPPP_RETURN_ERROR; - } - - return LUPPP_RETURN_OK; + } + } + // TODO add samplerate to session JSON + + // sceneNames + { + cJSON* names = cJSON_GetObjectItem( master, "sceneNames"); + if ( names ) { + GMasterTrack* master = gui->getMasterTrack(); + Avtk::ClipSelector* clipSelector = master->getClipSelector(); + int nscenes = cJSON_GetArraySize( names ); + for(int s = 0; s < nscenes; s++ ) { + cJSON* name = cJSON_GetArrayItem( names, s ); + clipSelector->clipName( s, name->valuestring ); + } + clipSelector->redraw(); + } + } + + } else { + LUPPP_ERROR("%s", "Error getting master from JSON" ); + return LUPPP_RETURN_ERROR; + } + + return LUPPP_RETURN_OK; } int DiskReader::readScenes(int t, cJSON* track) { - cJSON* clips = cJSON_GetObjectItem( track, "clips"); - if ( clips ) - { - - int nClips = cJSON_GetArraySize( clips ); - for(int s = 0; s < nClips; s++ ) - { - // get metadata for Clip - cJSON* clip = cJSON_GetArrayItem( clips, s ); - - if ( strcmp(clip->valuestring, "") != 0 ) - { - stringstream sampleFilePath; - sampleFilePath << sessionPath << "/audio/" << clip->valuestring; + cJSON* clips = cJSON_GetObjectItem( track, "clips"); + if ( clips ) { + + int nClips = cJSON_GetArraySize( clips ); + for(int s = 0; s < nClips; s++ ) { + // get metadata for Clip + cJSON* clip = cJSON_GetArrayItem( clips, s ); + + if ( strcmp(clip->valuestring, "") != 0 ) { + stringstream sampleFilePath; + sampleFilePath << sessionPath << "/audio/" << clip->valuestring; #ifdef DEBUG_STATE - LUPPP_NOTE << "clip t " << t << " s " << s << " path " << sampleFilePath.str() << endl; + LUPPP_NOTE << "clip t " << t << " s " << s << " path " << sampleFilePath.str() << endl; #endif - // load it, checking for sample.cfg, and using metadata if there - loadSample( t, s, sampleFilePath.str() ); - } - - // FIXME: check GUI ringbuffer after each sample: with resampling it can - // take quite some time, and the ->GUI ringbuffer can fill up - handleGuiEvents(); - - } // nClips loop - } - - return LUPPP_RETURN_OK; + // load it, checking for sample.cfg, and using metadata if there + loadSample( t, s, sampleFilePath.str() ); + } + + // FIXME: check GUI ringbuffer after each sample: with resampling it can + // take quite some time, and the ->GUI ringbuffer can fill up + handleGuiEvents(); + + } // nClips loop + } + + return LUPPP_RETURN_OK; } int DiskReader::readTracks() { - cJSON* tracks = cJSON_GetObjectItem( sessionJson, "tracks"); - if ( tracks ) - { - int nTracks = cJSON_GetArraySize( tracks ); - for(int t = 0; t < nTracks; t++ ) - { - cJSON* track = cJSON_GetArrayItem( tracks, t ); - - if( !track ) - { - LUPPP_WARN("Track %i has no name track saved.", t); - } - else - { - readScenes( t, track ); - - // name - { - cJSON* name = cJSON_GetObjectItem( track, "name"); - if( !name ) - { - LUPPP_WARN("Track %i has no name data saved.", t); - } - else - { - gui->getTrack(t)->bg.setLabel( name->valuestring ); - } - } - // fader - { - cJSON* fader = cJSON_GetObjectItem( track, "fader"); - if( !fader ) - { - LUPPP_WARN("Track %i has no fader data saved.", t); - } - else - { - EventTrackVol e( t, fader->valuedouble ); - writeToDspRingbuffer( &e ); - } - } - // sends - { - cJSON* send = cJSON_GetObjectItem( track, "sendAmount"); - cJSON* sendActive = cJSON_GetObjectItem( track, "sendActive"); - - cJSON* xside = cJSON_GetObjectItem( track, "xsideAmount"); - cJSON* keyActive = cJSON_GetObjectItem( track, "keyActive"); - - if( !send || !sendActive || !xside || !keyActive ) - { - LUPPP_WARN("Track %i has no send data saved.", t); - } - else - { - EventTrackSendActive e1( t, SEND_POSTFADER, sendActive->valueint ); - EventTrackSendActive e2( t, SEND_KEY , keyActive ->valueint ); - - EventTrackSend e3( t, SEND_XSIDE , xside->valuedouble ); - EventTrackSend e4( t, SEND_POSTFADER , send->valuedouble ); - - - writeToDspRingbuffer( &e1 ); - writeToDspRingbuffer( &e2 ); - writeToDspRingbuffer( &e3 ); - } + cJSON* tracks = cJSON_GetObjectItem( sessionJson, "tracks"); + if ( tracks ) { + int nTracks = cJSON_GetArraySize( tracks ); + for(int t = 0; t < nTracks; t++ ) { + cJSON* track = cJSON_GetArrayItem( tracks, t ); - cJSON* jacksend = cJSON_GetObjectItem( track, "jacksendAmount"); - cJSON* jacksendActive = cJSON_GetObjectItem( track, "jacksendActive"); - if(jacksend) - { - EventTrackJackSend ev(t,jacksend->valuedouble); - writeToDspRingbuffer(&ev); - } - if(jacksendActive) - { - EventTrackJackSendActivate ev(t,jacksendActive->valueint); - writeToDspRingbuffer(&ev); - } - } - }// if track - } // nTracks loop - } - else - { - LUPPP_ERROR("%s", "Error getting clip" ); - return LUPPP_RETURN_ERROR; - } - return LUPPP_RETURN_OK; + if( !track ) { + LUPPP_WARN("Track %i has no name track saved.", t); + } else { + readScenes( t, track ); + + // name + { + cJSON* name = cJSON_GetObjectItem( track, "name"); + if( !name ) { + LUPPP_WARN("Track %i has no name data saved.", t); + } else { + gui->getTrack(t)->bg.setLabel( name->valuestring ); + } + } + // fader + { + cJSON* fader = cJSON_GetObjectItem( track, "fader"); + if( !fader ) { + LUPPP_WARN("Track %i has no fader data saved.", t); + } else { + EventTrackVol e( t, fader->valuedouble ); + writeToDspRingbuffer( &e ); + } + } + // sends + { + cJSON* send = cJSON_GetObjectItem( track, "sendAmount"); + cJSON* sendActive = cJSON_GetObjectItem( track, "sendActive"); + + cJSON* xside = cJSON_GetObjectItem( track, "xsideAmount"); + cJSON* keyActive = cJSON_GetObjectItem( track, "keyActive"); + + if( !send || !sendActive || !xside || !keyActive ) { + LUPPP_WARN("Track %i has no send data saved.", t); + } else { + EventTrackSendActive e1( t, SEND_POSTFADER, sendActive->valueint ); + EventTrackSendActive e2( t, SEND_KEY , keyActive ->valueint ); + + EventTrackSend e3( t, SEND_XSIDE , xside->valuedouble ); + EventTrackSend e4( t, SEND_POSTFADER , send->valuedouble ); + + + writeToDspRingbuffer( &e1 ); + writeToDspRingbuffer( &e2 ); + writeToDspRingbuffer( &e3 ); + } + + cJSON* jacksend = cJSON_GetObjectItem( track, "jacksendAmount"); + cJSON* jacksendActive = cJSON_GetObjectItem( track, "jacksendActive"); + if(jacksend) { + EventTrackJackSend ev(t,jacksend->valuedouble); + writeToDspRingbuffer(&ev); + } + if(jacksendActive) { + EventTrackJackSendActivate ev(t,jacksendActive->valueint); + writeToDspRingbuffer(&ev); + } + } + }// if track + } // nTracks loop + } else { + LUPPP_ERROR("%s", "Error getting clip" ); + return LUPPP_RETURN_ERROR; + } + return LUPPP_RETURN_OK; } diff --git a/src/diskreader.hxx b/src/diskreader.hxx index 62ba60f..46b17ac 100644 --- a/src/diskreader.hxx +++ b/src/diskreader.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -28,51 +28,51 @@ class AudioBuffer; /** DiskReader * This class reads a previously saved session from disk, restoring Luppp's * internal state to that of when the save took place. - * - * The directory is the main point of loading. The user selects + * + * The directory is the main point of loading. The user selects * that directory to load the session from. .luppp is the name of * the session file: it contains all info about the session: Volumes, loaded * samples etc. - * + * * Samples are read from the directory /samples, in which there is a * sample.cfg file, which can be parsed to get sample metadata. **/ class DiskReader { - public: - DiskReader(); - - /// loads default settings for Luppp: controller instances etc - int loadPreferences(); - - /// loads a sample into a new AudioBuffer, returning the buffer - int loadSample( int track, int scene, std::string path ); - std::string getLastLoadedSamplePath(); - - /// reads a session from disk, parsing and restoring state - int readSession( std::string path ); - +public: + DiskReader(); + + /// loads default settings for Luppp: controller instances etc + int loadPreferences(); + + /// loads a sample into a new AudioBuffer, returning the buffer + int loadSample( int track, int scene, std::string path ); + std::string getLastLoadedSamplePath(); + + /// reads a session from disk, parsing and restoring state + int readSession( std::string path ); + #ifdef BUILD_TESTS - int runTests(); + int runTests(); #endif - - private: - cJSON* sessionJson; - - std::string sessionName; - std::string sessionPath; - - // convinience functions - int readTracks(); - int readMaster(); - int readScenes(int t, cJSON* track); - - // ui show editor - int showAudioEditor(AudioBuffer* ); - - // sample load dialog - int resampleQuality; - std::string lastLoadedSamplePath; + +private: + cJSON* sessionJson; + + std::string sessionName; + std::string sessionPath; + + // convinience functions + int readTracks(); + int readMaster(); + int readScenes(int t, cJSON* track); + + // ui show editor + int showAudioEditor(AudioBuffer* ); + + // sample load dialog + int resampleQuality; + std::string lastLoadedSamplePath; }; #endif // LUPPP_DISK_READER_H diff --git a/src/diskwriter.cxx b/src/diskwriter.cxx index 7b3e58b..f70a53e 100644 --- a/src/diskwriter.cxx +++ b/src/diskwriter.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -43,498 +43,451 @@ using namespace std; DiskWriter::DiskWriter() { - sessionJson = cJSON_CreateObject(); - audioJson = cJSON_CreateObject(); - - // setup default controller name / author etc - controllerInfo[CONTROLLER_NAME] = "no name"; - controllerInfo[CONTROLLER_AUTHOR] = "no author"; - controllerInfo[CONTROLLER_LINK] = "no link"; - - sessionDir = getenv("HOME"); - sessionName = "session"; - foldersCreated = false; - - // create .config/openAV/luppp/ directory - stringstream dotConfig; - dotConfig << getenv("HOME") << "/.config/openAV/"; - int dotConfigDir = mkdir( dotConfig.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ); - if ( errno == EEXIST ) - { - //LUPPP_NOTE("dotConfigDir exists"); - } - else if ( dotConfigDir ) - { - LUPPP_WARN("Error creating dotConfigDir: %s", strerror(errno)); - } - else - { - LUPPP_NOTE("Creating .config/openAV/ directory"); - } - - stringstream dotConfigLuppp; - dotConfigLuppp << getenv("HOME") << "/.config/openAV/luppp"; - int dotConfigLupppDir = mkdir( dotConfigLuppp.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ); - if ( errno == EEXIST ) - { - //LUPPP_NOTE("dotConfigLupppDir exists"); - } - else if ( dotConfigLupppDir ) - { - LUPPP_WARN("Error creating dotConfigLupppDir: %s", strerror(errno)); - } - else - { - LUPPP_NOTE("Creating .config/openAV/luppp directory"); - } - - stringstream dotConfigCtlr; - dotConfigCtlr << getenv("HOME") << "/.config/openAV/luppp/controllers/"; - int dotConfigCtlrDir = mkdir( dotConfigCtlr.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ); - if ( errno == EEXIST ) - { - //LUPPP_NOTE("dotConfigCtlrDir exists"); - } - else if ( dotConfigCtlrDir ) - { - LUPPP_WARN("Error creating dotConfigCtlrDir: %s", strerror(errno)); - } - else - { - LUPPP_NOTE("Creating .config/openAV/luppp directory"); - } + sessionJson = cJSON_CreateObject(); + audioJson = cJSON_CreateObject(); + + // setup default controller name / author etc + controllerInfo[CONTROLLER_NAME] = "no name"; + controllerInfo[CONTROLLER_AUTHOR] = "no author"; + controllerInfo[CONTROLLER_LINK] = "no link"; + + sessionDir = getenv("HOME"); + sessionName = "session"; + foldersCreated = false; + + // create .config/openAV/luppp/ directory + stringstream dotConfig; + dotConfig << getenv("HOME") << "/.config/openAV/"; + int dotConfigDir = mkdir( dotConfig.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ); + if ( errno == EEXIST ) { + //LUPPP_NOTE("dotConfigDir exists"); + } else if ( dotConfigDir ) { + LUPPP_WARN("Error creating dotConfigDir: %s", strerror(errno)); + } else { + LUPPP_NOTE("Creating .config/openAV/ directory"); + } + + stringstream dotConfigLuppp; + dotConfigLuppp << getenv("HOME") << "/.config/openAV/luppp"; + int dotConfigLupppDir = mkdir( dotConfigLuppp.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ); + if ( errno == EEXIST ) { + //LUPPP_NOTE("dotConfigLupppDir exists"); + } else if ( dotConfigLupppDir ) { + LUPPP_WARN("Error creating dotConfigLupppDir: %s", strerror(errno)); + } else { + LUPPP_NOTE("Creating .config/openAV/luppp directory"); + } + + stringstream dotConfigCtlr; + dotConfigCtlr << getenv("HOME") << "/.config/openAV/luppp/controllers/"; + int dotConfigCtlrDir = mkdir( dotConfigCtlr.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ); + if ( errno == EEXIST ) { + //LUPPP_NOTE("dotConfigCtlrDir exists"); + } else if ( dotConfigCtlrDir ) { + LUPPP_WARN("Error creating dotConfigCtlrDir: %s", strerror(errno)); + } else { + LUPPP_NOTE("Creating .config/openAV/luppp directory"); + } }; void DiskWriter::initialize(std::string path, std::string name ) { - sessionName = name; - sessionPath = path; - - // write session.luppp JSON node to /.luppp - stringstream sessionDirStream; - - sessionDirStream << path; - - if ( !gui->getNsm() ) - sessionDirStream << "/" << sessionName << ".luppp"; - - sessionDir = sessionDirStream.str(); - - LUPPP_NOTE( "Creating session dir %s", sessionDir.c_str() ); - - int sessionDirError = mkdir( sessionDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ); - if ( sessionDirError ) - { - // handle by using different filename? - LUPPP_WARN("Error creating session directory. Does the path: %s exist?",path.c_str()); - } - - stringstream audioDirStream; - audioDirStream << sessionDir << "/audio"; - audioDir = audioDirStream.str(); - LUPPP_NOTE("Creating audio dir %s", audioDir.c_str() ); - - int audioDirError = mkdir( audioDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ); - if ( audioDirError ) - { - LUPPP_WARN("Error creating sample directory"); - } - - foldersCreated = true; + sessionName = name; + sessionPath = path; + + // write session.luppp JSON node to /.luppp + stringstream sessionDirStream; + + sessionDirStream << path; + + if ( !gui->getNsm() ) + sessionDirStream << "/" << sessionName << ".luppp"; + + sessionDir = sessionDirStream.str(); + + LUPPP_NOTE( "Creating session dir %s", sessionDir.c_str() ); + + int sessionDirError = mkdir( sessionDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ); + if ( sessionDirError ) { + // handle by using different filename? + LUPPP_WARN("Error creating session directory. Does the path: %s exist?",path.c_str()); + } + + stringstream audioDirStream; + audioDirStream << sessionDir << "/audio"; + audioDir = audioDirStream.str(); + LUPPP_NOTE("Creating audio dir %s", audioDir.c_str() ); + + int audioDirError = mkdir( audioDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ); + if ( audioDirError ) { + LUPPP_WARN("Error creating sample directory"); + } + + foldersCreated = true; } std::string DiskWriter::getLastSaveName() { - return sessionName; + return sessionName; } std::string DiskWriter::getLastSavePath() { - return sessionPath; + return sessionPath; } void DiskWriter::writeControllerInfo( CONTROLLER_INFO c, std::string s ) { - controllerInfo[c] = s; + controllerInfo[c] = s; } int DiskWriter::writeControllerFile( Controller* c ) { - if ( c ) - { - LUPPP_NOTE("DiskWriter Controller* id: %i", c->getID() ); - } - else - { - LUPPP_ERROR("DiskWriter Controller* passed NULL" ); - return LUPPP_RETURN_ERROR; - } - - // check if controller of ID is actually a GenericMIDI controller - GenericMIDI* g = dynamic_cast( c ); - - if ( g ) - { - LUPPP_NOTE("Creating JSON for .ctlr file..."); - - cJSON* controllerJson = cJSON_CreateObject(); - - cJSON_AddItemToObject( controllerJson, "name", - cJSON_CreateString( controllerInfo[CONTROLLER_NAME].c_str() ) ); - cJSON_AddItemToObject( controllerJson, "author", - cJSON_CreateString( controllerInfo[CONTROLLER_AUTHOR].c_str() ) ); - cJSON_AddItemToObject( controllerJson, "link", - cJSON_CreateString( controllerInfo[CONTROLLER_LINK].c_str() ) ); - - // input bindings - std::vector b = g->getMidiToAction(); - - cJSON* inputBindings = cJSON_CreateArray(); - cJSON_AddItemToObject(controllerJson, "inputBindings", inputBindings ); - for(unsigned int i = 0; i < b.size(); i++ ) - { - // create binding - cJSON* binding = cJSON_CreateObject(); - cJSON_AddItemToArray( inputBindings, binding ); - - // add metadata to binding - const char* actionName = Event::getPrettyName( b.at(i)->action ); - - if ( actionName ) - { - cJSON_AddItemToObject( binding, "action", cJSON_CreateString( actionName ) ); - - cJSON_AddNumberToObject( binding, "status", b.at(i)->status ); - cJSON_AddNumberToObject( binding, "data" , b.at(i)->data ); - - // only add JSON elements if they're not the "invalid" defaults - if ( b.at(i)->track != -2 ) - cJSON_AddNumberToObject( binding, "track" , b.at(i)->track ); - if ( b.at(i)->scene != -1 ) - cJSON_AddNumberToObject( binding, "scene" , b.at(i)->scene ); - if ( b.at(i)->send != -1 ) - cJSON_AddNumberToObject( binding, "send" , b.at(i)->send ); - if ( b.at(i)->active!= -1 ) - cJSON_AddNumberToObject( binding, "active", b.at(i)->active ); - - LUPPP_NOTE("Creating Binding: action %i == %s!", b.at(i)->action, actionName ); - } - else - { - LUPPP_WARN("Binding action %i has no prettyName!", b.at(i)->action ); - } - } - - - //std::vector b = g->getMidiToAction(); - /* - cJSON* outputBindings = cJSON_CreateArray(); - cJSON_AddItemToObject(controllerJson, "outputBindings", outputBindings ); - - for(unsigned int i = 0; i < b.size(); i++ ) - { - // create binding - cJSON* binding = cJSON_CreateObject(); - cJSON_AddItemToArray( outputBindings, binding ); - - // add metadata to binding - // FIXME: get action string from Event class: need to move function from GenericMIDI to there - cJSON_AddItemToObject( binding, "action", cJSON_CreateString( "gridlogic:launchscene" ) ); - - cJSON_AddNumberToObject( binding, "status", b.at(i)->status ); - cJSON_AddNumberToObject( binding, "data" , b.at(i)->data ); - - cJSON_AddNumberToObject( binding, "track" , b.at(i)->track ); - cJSON_AddNumberToObject( binding, "scene" , b.at(i)->scene ); - cJSON_AddNumberToObject( binding, "send" , b.at(i)->send ); - cJSON_AddNumberToObject( binding, "active", b.at(i)->active ); - } - */ - - - // write the sample JSON node to /sample.cfg - stringstream controllerCfgPath; - controllerCfgPath << getenv("HOME") << "/.config/openAV/luppp/controllers/" << g->getName() << ".ctlr"; - - ifstream infile( controllerCfgPath.str().c_str() ); - if ( infile.good() ) - { - // file exists: ask user overwrite or rename? - //LUPPP_WARN("Controller filename exists: prompting user to overwrite y/n?"); - int action = fl_choice("Controller exists, action?", "Cancel", "Rename", "Overwrite"); - if ( action == 0 ) - { - // return OK, as user has chosen to cancel writing the file - return LUPPP_RETURN_OK; - } - else if ( action == 1 ) - { - // rename here - const char* name = fl_input("New name for .ctlr file:"); - if ( name ) - { - // clear the filename - controllerCfgPath.str( "" ); - controllerCfgPath << getenv("HOME") << "/.config/openAV/luppp/controllers/" << name << ".ctlr"; - LUPPP_NOTE( "New .ctlr filename %s", controllerCfgPath.str().c_str() ); - } - else - { - LUPPP_NOTE("No name entered for .ctlr file, canceling!"); - return LUPPP_RETURN_ERROR; - } - } - else - { - // just overwrite the file, no action - } - - - } - - LUPPP_NOTE("Writing %s.ctlr file to disk", g->getName().c_str() ); - - ofstream controllerCfgFile; - controllerCfgFile.open ( controllerCfgPath.str().c_str() ); - controllerCfgFile << cJSON_Print( controllerJson ); - controllerCfgFile.close(); - } - else - { - LUPPP_WARN("Invalid Controller pointer: cannot write %s as is not a GenericMIDI controller!", c->getName().c_str() ); - return LUPPP_RETURN_ERROR; - } - - return LUPPP_RETURN_OK; + if ( c ) { + LUPPP_NOTE("DiskWriter Controller* id: %i", c->getID() ); + } else { + LUPPP_ERROR("DiskWriter Controller* passed NULL" ); + return LUPPP_RETURN_ERROR; + } + + // check if controller of ID is actually a GenericMIDI controller + GenericMIDI* g = dynamic_cast( c ); + + if ( g ) { + LUPPP_NOTE("Creating JSON for .ctlr file..."); + + cJSON* controllerJson = cJSON_CreateObject(); + + cJSON_AddItemToObject( controllerJson, "name", + cJSON_CreateString( controllerInfo[CONTROLLER_NAME].c_str() ) ); + cJSON_AddItemToObject( controllerJson, "author", + cJSON_CreateString( controllerInfo[CONTROLLER_AUTHOR].c_str() ) ); + cJSON_AddItemToObject( controllerJson, "link", + cJSON_CreateString( controllerInfo[CONTROLLER_LINK].c_str() ) ); + + // input bindings + std::vector b = g->getMidiToAction(); + + cJSON* inputBindings = cJSON_CreateArray(); + cJSON_AddItemToObject(controllerJson, "inputBindings", inputBindings ); + for(unsigned int i = 0; i < b.size(); i++ ) { + // create binding + cJSON* binding = cJSON_CreateObject(); + cJSON_AddItemToArray( inputBindings, binding ); + + // add metadata to binding + const char* actionName = Event::getPrettyName( b.at(i)->action ); + + if ( actionName ) { + cJSON_AddItemToObject( binding, "action", cJSON_CreateString( actionName ) ); + + cJSON_AddNumberToObject( binding, "status", b.at(i)->status ); + cJSON_AddNumberToObject( binding, "data" , b.at(i)->data ); + + // only add JSON elements if they're not the "invalid" defaults + if ( b.at(i)->track != -2 ) + cJSON_AddNumberToObject( binding, "track" , b.at(i)->track ); + if ( b.at(i)->scene != -1 ) + cJSON_AddNumberToObject( binding, "scene" , b.at(i)->scene ); + if ( b.at(i)->send != -1 ) + cJSON_AddNumberToObject( binding, "send" , b.at(i)->send ); + if ( b.at(i)->active!= -1 ) + cJSON_AddNumberToObject( binding, "active", b.at(i)->active ); + + LUPPP_NOTE("Creating Binding: action %i == %s!", b.at(i)->action, actionName ); + } else { + LUPPP_WARN("Binding action %i has no prettyName!", b.at(i)->action ); + } + } + + + //std::vector b = g->getMidiToAction(); + /* + cJSON* outputBindings = cJSON_CreateArray(); + cJSON_AddItemToObject(controllerJson, "outputBindings", outputBindings ); + + for(unsigned int i = 0; i < b.size(); i++ ) + { + // create binding + cJSON* binding = cJSON_CreateObject(); + cJSON_AddItemToArray( outputBindings, binding ); + + // add metadata to binding + // FIXME: get action string from Event class: need to move function from GenericMIDI to there + cJSON_AddItemToObject( binding, "action", cJSON_CreateString( "gridlogic:launchscene" ) ); + + cJSON_AddNumberToObject( binding, "status", b.at(i)->status ); + cJSON_AddNumberToObject( binding, "data" , b.at(i)->data ); + + cJSON_AddNumberToObject( binding, "track" , b.at(i)->track ); + cJSON_AddNumberToObject( binding, "scene" , b.at(i)->scene ); + cJSON_AddNumberToObject( binding, "send" , b.at(i)->send ); + cJSON_AddNumberToObject( binding, "active", b.at(i)->active ); + } + */ + + + // write the sample JSON node to /sample.cfg + stringstream controllerCfgPath; + controllerCfgPath << getenv("HOME") << "/.config/openAV/luppp/controllers/" << g->getName() << ".ctlr"; + + ifstream infile( controllerCfgPath.str().c_str() ); + if ( infile.good() ) { + // file exists: ask user overwrite or rename? + //LUPPP_WARN("Controller filename exists: prompting user to overwrite y/n?"); + int action = fl_choice("Controller exists, action?", "Cancel", "Rename", "Overwrite"); + if ( action == 0 ) { + // return OK, as user has chosen to cancel writing the file + return LUPPP_RETURN_OK; + } else if ( action == 1 ) { + // rename here + const char* name = fl_input("New name for .ctlr file:"); + if ( name ) { + // clear the filename + controllerCfgPath.str( "" ); + controllerCfgPath << getenv("HOME") << "/.config/openAV/luppp/controllers/" << name << ".ctlr"; + LUPPP_NOTE( "New .ctlr filename %s", controllerCfgPath.str().c_str() ); + } else { + LUPPP_NOTE("No name entered for .ctlr file, canceling!"); + return LUPPP_RETURN_ERROR; + } + } else { + // just overwrite the file, no action + } + + + } + + LUPPP_NOTE("Writing %s.ctlr file to disk", g->getName().c_str() ); + + ofstream controllerCfgFile; + controllerCfgFile.open ( controllerCfgPath.str().c_str() ); + controllerCfgFile << cJSON_Print( controllerJson ); + controllerCfgFile.close(); + } else { + LUPPP_WARN("Invalid Controller pointer: cannot write %s as is not a GenericMIDI controller!", c->getName().c_str() ); + return LUPPP_RETURN_ERROR; + } + + return LUPPP_RETURN_OK; } int DiskWriter::writeAudioBuffer(int track, int scene, AudioBuffer* ab, - const char *gui_path) + const char *gui_path) { - stringstream path; - if ( gui_path && strlen(gui_path) ) { - printf("saving single buffer to %s\n", gui_path); - path << gui_path; - } - else if ( foldersCreated ) - { - stringstream filename; - filename << "t_" << track << "_s_" << scene << ".wav"; - - // store the clip in clipData, we will write the session JSON for it in writeSession - clipData.push_back( ClipData( track, scene, filename.str() ) ); - - // add the AudioBuffer metadata to the sample JSON node - cJSON* sampleClip = cJSON_CreateObject(); - cJSON_AddItemToObject(audioJson, filename.str().c_str(), sampleClip ); - cJSON_AddNumberToObject(sampleClip,"beats", ab->getBeats() ); - - // get pretty name from GUI - std::string clipName = gui->getTrack(track)->getClipSelector()->clipName( scene ); - cJSON_AddItemToObject ( sampleClip, "name", cJSON_CreateString( clipName.c_str() )); - - // write the AudioBuffer contents to /audio/ as .wav - // or alternatively t__s_.wav - - path << audioDir << "/" << filename.str(); - } - else - { - LUPPP_WARN("%s", "Session folders not created yet, while trying to write audioBuffers."); - return LUPPP_RETURN_ERROR; - } - - - SndfileHandle outfile( path.str(), SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_FLOAT, 1, gui->samplerate ); - - // FIXME: the size of the buffer is bigger than the audio contained in it: - // calculate the length that needs saving using getBeats() * framesPerBeat - if ( ab->getAudioFrames() > 0 ) - outfile.write( &ab->getData()[0], ab->getAudioFrames() ); - else - { - LUPPP_WARN("%s","Sample has zero samples"); - } - - return LUPPP_RETURN_OK; + stringstream path; + if ( gui_path && strlen(gui_path) ) { + printf("saving single buffer to %s\n", gui_path); + path << gui_path; + } else if ( foldersCreated ) { + stringstream filename; + filename << "t_" << track << "_s_" << scene << ".wav"; + + // store the clip in clipData, we will write the session JSON for it in writeSession + clipData.push_back( ClipData( track, scene, filename.str() ) ); + + // add the AudioBuffer metadata to the sample JSON node + cJSON* sampleClip = cJSON_CreateObject(); + cJSON_AddItemToObject(audioJson, filename.str().c_str(), sampleClip ); + cJSON_AddNumberToObject(sampleClip,"beats", ab->getBeats() ); + + // get pretty name from GUI + std::string clipName = gui->getTrack(track)->getClipSelector()->clipName( scene ); + cJSON_AddItemToObject ( sampleClip, "name", cJSON_CreateString( clipName.c_str() )); + + // write the AudioBuffer contents to /audio/ as .wav + // or alternatively t__s_.wav + + path << audioDir << "/" << filename.str(); + } else { + LUPPP_WARN("%s", "Session folders not created yet, while trying to write audioBuffers."); + return LUPPP_RETURN_ERROR; + } + + + SndfileHandle outfile( path.str(), SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_FLOAT, 1, gui->samplerate ); + + // FIXME: the size of the buffer is bigger than the audio contained in it: + // calculate the length that needs saving using getBeats() * framesPerBeat + if ( ab->getAudioFrames() > 0 ) + outfile.write( &ab->getData()[0], ab->getAudioFrames() ); + else { + LUPPP_WARN("%s","Sample has zero samples"); + } + + return LUPPP_RETURN_OK; } void DiskWriter::writeMaster() { - // Master track stuff - cJSON* masterTrack = cJSON_CreateObject(); - cJSON_AddItemToObject(sessionJson, "master", masterTrack ); - GMasterTrack* master = gui->getMasterTrack(); - - cJSON_AddNumberToObject( masterTrack, "fader", master->getVolume()->value() ); - cJSON_AddNumberToObject( masterTrack, "bpm", gui->getMasterTrack()->getBpm() ); - // TODO add samplerate to session JSON - //cJSON_AddNumberToObject( masterTrack, "samplerate", gui->getMasterTrack()->getBpm() ); - - cJSON_AddNumberToObject( masterTrack, "inputVolume", gui->getMasterTrack()->getInputVolume()->value() ); - - cJSON_AddNumberToObject( masterTrack, "inputToSndActive", gui->getMasterTrack()->getInputToSend()->value() ); - cJSON_AddNumberToObject( masterTrack, "inputToKeyActive", gui->getMasterTrack()->getInputToSidechainKey()->value() ); - cJSON_AddNumberToObject( masterTrack, "inputToMixActive", gui->getMasterTrack()->getInputToMix()->value() ); - - cJSON_AddNumberToObject( masterTrack, "inputToSndVol", gui->getMasterTrack()->getInputToSendVol()->value() ); - cJSON_AddNumberToObject( masterTrack, "inputToXSide", gui->getMasterTrack()->getInputToXSide()->value() ); - cJSON_AddNumberToObject( masterTrack, "inputToMixVol", gui->getMasterTrack()->getInputToMixVol()->value() ); - - // scene names - Avtk::ClipSelector* clipSelector = master->getClipSelector(); - cJSON* sceneNames = cJSON_CreateArray(); - cJSON_AddItemToObject( masterTrack, "sceneNames", sceneNames ); - for(int i = 0; i < NSCENES; i++) - { - cJSON* sceneName = cJSON_CreateString( clipSelector->clipName(i).c_str() ); - cJSON_AddItemToArray( sceneNames, sceneName ); - } - + // Master track stuff + cJSON* masterTrack = cJSON_CreateObject(); + cJSON_AddItemToObject(sessionJson, "master", masterTrack ); + GMasterTrack* master = gui->getMasterTrack(); + + cJSON_AddNumberToObject( masterTrack, "fader", master->getVolume()->value() ); + cJSON_AddNumberToObject( masterTrack, "bpm", gui->getMasterTrack()->getBpm() ); + // TODO add samplerate to session JSON + //cJSON_AddNumberToObject( masterTrack, "samplerate", gui->getMasterTrack()->getBpm() ); + + cJSON_AddNumberToObject( masterTrack, "inputVolume", gui->getMasterTrack()->getInputVolume()->value() ); + + cJSON_AddNumberToObject( masterTrack, "inputToSndActive", gui->getMasterTrack()->getInputToSend()->value() ); + cJSON_AddNumberToObject( masterTrack, "inputToKeyActive", gui->getMasterTrack()->getInputToSidechainKey()->value() ); + cJSON_AddNumberToObject( masterTrack, "inputToMixActive", gui->getMasterTrack()->getInputToMix()->value() ); + + cJSON_AddNumberToObject( masterTrack, "inputToSndVol", gui->getMasterTrack()->getInputToSendVol()->value() ); + cJSON_AddNumberToObject( masterTrack, "inputToXSide", gui->getMasterTrack()->getInputToXSide()->value() ); + cJSON_AddNumberToObject( masterTrack, "inputToMixVol", gui->getMasterTrack()->getInputToMixVol()->value() ); + + // scene names + Avtk::ClipSelector* clipSelector = master->getClipSelector(); + cJSON* sceneNames = cJSON_CreateArray(); + cJSON_AddItemToObject( masterTrack, "sceneNames", sceneNames ); + for(int i = 0; i < NSCENES; i++) { + cJSON* sceneName = cJSON_CreateString( clipSelector->clipName(i).c_str() ); + cJSON_AddItemToArray( sceneNames, sceneName ); + } + } int DiskWriter::writeSession() { - if ( !foldersCreated ) - { - LUPPP_WARN("%s", "Session folders not created yet, while trying to write session."); - return LUPPP_RETURN_ERROR; - } - - // add session metadata - cJSON_AddItemToObject ( sessionJson, "session", cJSON_CreateString( sessionName.c_str() )); - - cJSON_AddNumberToObject( sessionJson, "version_major", 1 ); - cJSON_AddNumberToObject( sessionJson, "version_minor", 0 ); - cJSON_AddNumberToObject( sessionJson, "version_patch", 0 ); - - - writeMaster(); - - - // add JSON "tracks" array - cJSON* trackArray = cJSON_CreateArray(); - cJSON_AddItemToObject(sessionJson, "tracks", trackArray ); - - // write tracks into JSON tracks array - for(int t = 0; t < NTRACKS; t++) - { - cJSON* track = cJSON_CreateObject(); - cJSON_AddItemToArray( trackArray, track ); - - // add track metadata: volumes, sends etc - cJSON_AddNumberToObject( track, "ID", t ); - cJSON_AddStringToObject( track, "name", gui->getTrack(t)->bg.getLabel() ); - - cJSON_AddNumberToObject( track, "fader", gui->getTrack(t)->getVolume()->value() ); - - - cJSON_AddNumberToObject( track, "sendAmount" , gui->getTrack(t)->getSend() ); - cJSON_AddNumberToObject( track, "sendActive" , gui->getTrack(t)->getSendActive() ); + if ( !foldersCreated ) { + LUPPP_WARN("%s", "Session folders not created yet, while trying to write session."); + return LUPPP_RETURN_ERROR; + } - cJSON_AddNumberToObject( track, "jacksendAmount" , gui->getTrack(t)->getJackSend() ); - cJSON_AddNumberToObject( track, "jacksendActive" , gui->getTrack(t)->getJackSendActivate() ); - - cJSON_AddNumberToObject( track, "xsideAmount", gui->getTrack(t)->getXSide() ); - cJSON_AddNumberToObject( track, "keyActive" , gui->getTrack(t)->getKeyActive() ); - - // write clipData vector into clip placeholder - cJSON* clips = cJSON_CreateArray(); - cJSON_AddItemToObject( track, "clips", clips ); - - - - for(int s = 0; s < NSCENES; s++) - { - // add empty string to array - cJSON* clip = cJSON_CreateString( "" ); - cJSON_AddItemToArray( clips, clip ); - - // replace blank string if clip exists - for(unsigned int i = 0; i < clipData.size(); i++) - { - if ( clipData.at(i).track == t && - clipData.at(i).scene == s ) - { - cJSON* newClip = cJSON_CreateString( clipData.at(i).name.c_str() ); - cJSON_ReplaceItemInArray( clips, s, newClip ); - } - } - - } - - } - - - - stringstream sessionLuppp; - sessionLuppp << sessionDir << "/session.luppp"; - //c out << "Session dir: " << sessionDir.str() << "\n" << "Sample dir : " << audioDir.str() << endl; - ofstream sessionFile; - sessionFile.open ( sessionLuppp.str().c_str() ); - sessionFile << cJSON_Print( sessionJson ); - sessionFile.close(); - - // write the sample JSON node to /sample.cfg - stringstream audioCfg; - audioCfg << audioDir << "/audio.cfg"; - - ofstream audioCfgFile; - audioCfgFile.open ( audioCfg.str().c_str() ); - audioCfgFile << cJSON_Print( audioJson ); - audioCfgFile.close(); - - // clear the clipData, clean page for next save - clipData.clear(); - - - // reset the cJSON objects - cJSON_Delete( sessionJson ); - cJSON_Delete( audioJson ); - - sessionJson = cJSON_CreateObject(); - audioJson = cJSON_CreateObject(); - - - return LUPPP_RETURN_OK; + // add session metadata + cJSON_AddItemToObject ( sessionJson, "session", cJSON_CreateString( sessionName.c_str() )); + + cJSON_AddNumberToObject( sessionJson, "version_major", 1 ); + cJSON_AddNumberToObject( sessionJson, "version_minor", 0 ); + cJSON_AddNumberToObject( sessionJson, "version_patch", 0 ); + + + writeMaster(); + + + // add JSON "tracks" array + cJSON* trackArray = cJSON_CreateArray(); + cJSON_AddItemToObject(sessionJson, "tracks", trackArray ); + + // write tracks into JSON tracks array + for(int t = 0; t < NTRACKS; t++) { + cJSON* track = cJSON_CreateObject(); + cJSON_AddItemToArray( trackArray, track ); + + // add track metadata: volumes, sends etc + cJSON_AddNumberToObject( track, "ID", t ); + cJSON_AddStringToObject( track, "name", gui->getTrack(t)->bg.getLabel() ); + + cJSON_AddNumberToObject( track, "fader", gui->getTrack(t)->getVolume()->value() ); + + + cJSON_AddNumberToObject( track, "sendAmount" , gui->getTrack(t)->getSend() ); + cJSON_AddNumberToObject( track, "sendActive" , gui->getTrack(t)->getSendActive() ); + + cJSON_AddNumberToObject( track, "jacksendAmount" , gui->getTrack(t)->getJackSend() ); + cJSON_AddNumberToObject( track, "jacksendActive" , gui->getTrack(t)->getJackSendActivate() ); + + cJSON_AddNumberToObject( track, "xsideAmount", gui->getTrack(t)->getXSide() ); + cJSON_AddNumberToObject( track, "keyActive" , gui->getTrack(t)->getKeyActive() ); + + // write clipData vector into clip placeholder + cJSON* clips = cJSON_CreateArray(); + cJSON_AddItemToObject( track, "clips", clips ); + + + + for(int s = 0; s < NSCENES; s++) { + // add empty string to array + cJSON* clip = cJSON_CreateString( "" ); + cJSON_AddItemToArray( clips, clip ); + + // replace blank string if clip exists + for(unsigned int i = 0; i < clipData.size(); i++) { + if ( clipData.at(i).track == t && + clipData.at(i).scene == s ) { + cJSON* newClip = cJSON_CreateString( clipData.at(i).name.c_str() ); + cJSON_ReplaceItemInArray( clips, s, newClip ); + } + } + + } + + } + + + + stringstream sessionLuppp; + sessionLuppp << sessionDir << "/session.luppp"; + //c out << "Session dir: " << sessionDir.str() << "\n" << "Sample dir : " << audioDir.str() << endl; + ofstream sessionFile; + sessionFile.open ( sessionLuppp.str().c_str() ); + sessionFile << cJSON_Print( sessionJson ); + sessionFile.close(); + + // write the sample JSON node to /sample.cfg + stringstream audioCfg; + audioCfg << audioDir << "/audio.cfg"; + + ofstream audioCfgFile; + audioCfgFile.open ( audioCfg.str().c_str() ); + audioCfgFile << cJSON_Print( audioJson ); + audioCfgFile.close(); + + // clear the clipData, clean page for next save + clipData.clear(); + + + // reset the cJSON objects + cJSON_Delete( sessionJson ); + cJSON_Delete( audioJson ); + + sessionJson = cJSON_CreateObject(); + audioJson = cJSON_CreateObject(); + + + return LUPPP_RETURN_OK; } void DiskWriter::writeDefaultConfigToUserHome() { - LUPPP_NOTE("Writing default preferences file."); - - cJSON* prfs = cJSON_CreateObject(); - - // "__COMMENT__" : "users home + " - // "saveDirectory" : "luppp" - cJSON_AddItemToObject ( prfs, "__COMMENT__", - cJSON_CreateString("users home + ") ); - cJSON_AddItemToObject ( prfs, "saveDirectory", cJSON_CreateString( "luppp" )); - - - // "__COMMENT__" : "0 = LINEAR, 1 = SINC_FASTEST, 2 = SINC_BEST", - // "resampleQuality" : 2 - cJSON_AddItemToObject ( prfs, "__COMMENT__", - cJSON_CreateString("0 = LINEAR, 1 = SINC_FASTEST, 2 = SINC_BEST") ); - cJSON_AddNumberToObject( prfs, "resampleQuality", 1 ); - - // "defaultControllers" : [], - cJSON* defCtrls = cJSON_CreateArray(); - cJSON_AddItemToObject( prfs, "defaultControllers", defCtrls ); - - // per track send and return option - cJSON_AddNumberToObject( prfs, "enablePerTrackSendReturns", 0 ); - // test output on console - // cout << endl << cJSON_Print( prfs ) << endl << endl; - - - // write JSON to .config/openAV/luppp/luppp.prfs - stringstream f; - f << getenv("HOME") << "/.config/openAV/luppp/luppp.prfs"; - - ofstream outFile; - outFile.open ( f.str().c_str() ); - outFile << cJSON_Print( prfs ); - outFile.close(); + LUPPP_NOTE("Writing default preferences file."); + + cJSON* prfs = cJSON_CreateObject(); + + // "__COMMENT__" : "users home + " + // "saveDirectory" : "luppp" + cJSON_AddItemToObject ( prfs, "__COMMENT__", + cJSON_CreateString("users home + ") ); + cJSON_AddItemToObject ( prfs, "saveDirectory", cJSON_CreateString( "luppp" )); + + + // "__COMMENT__" : "0 = LINEAR, 1 = SINC_FASTEST, 2 = SINC_BEST", + // "resampleQuality" : 2 + cJSON_AddItemToObject ( prfs, "__COMMENT__", + cJSON_CreateString("0 = LINEAR, 1 = SINC_FASTEST, 2 = SINC_BEST") ); + cJSON_AddNumberToObject( prfs, "resampleQuality", 1 ); + + // "defaultControllers" : [], + cJSON* defCtrls = cJSON_CreateArray(); + cJSON_AddItemToObject( prfs, "defaultControllers", defCtrls ); + + // per track send and return option + cJSON_AddNumberToObject( prfs, "enablePerTrackSendReturns", 0 ); + // test output on console + // cout << endl << cJSON_Print( prfs ) << endl << endl; + + + // write JSON to .config/openAV/luppp/luppp.prfs + stringstream f; + f << getenv("HOME") << "/.config/openAV/luppp/luppp.prfs"; + + ofstream outFile; + outFile.open ( f.str().c_str() ); + outFile << cJSON_Print( prfs ); + outFile.close(); } diff --git a/src/diskwriter.hxx b/src/diskwriter.hxx index 14c252c..838d781 100644 --- a/src/diskwriter.hxx +++ b/src/diskwriter.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -27,23 +27,22 @@ class AudioBuffer; class Controller; -enum CONTROLLER_INFO -{ - CONTROLLER_NAME, - CONTROLLER_AUTHOR, - CONTROLLER_LINK, - CONTROLLER_INFO_SIZE, +enum CONTROLLER_INFO { + CONTROLLER_NAME, + CONTROLLER_AUTHOR, + CONTROLLER_LINK, + CONTROLLER_INFO_SIZE, }; /// To hold data about loaded clips until we write the JSON out class ClipData { - public: - ClipData(int tr, int sc, std::string na) : - track(tr), scene(sc), name(na) {} - int track; - int scene; - std::string name; +public: + ClipData(int tr, int sc, std::string na) : + track(tr), scene(sc), name(na) {} + int track; + int scene; + std::string name; }; /** DiskWriter @@ -53,51 +52,51 @@ class ClipData **/ class DiskWriter { - public: - DiskWriter(); - - /// sets up session write path etc - void initialize( std::string path, std::string sessionName ); - - /// writes a single audio buffer to disk for saving whole state. - // When gui_path is set, it only saves a single AB* to that path - int writeAudioBuffer(int track, int scene, AudioBuffer* ab, - const char* gui_path = 0); - - /// flush the JSON to disk, finalizing the save - int writeSession(); - - std::string getLastSaveName(); - std::string getLastSavePath(); - - /// sets a piece of info to be written to the controller - void writeControllerInfo( CONTROLLER_INFO c, std::string s ); - /// writes a controller definition .ctlr JSON file from a GenericMIDI instance - int writeControllerFile( Controller* c ); - - /// writes default config file to users home if it doesn't exist - void writeDefaultConfigToUserHome(); - +public: + DiskWriter(); + + /// sets up session write path etc + void initialize( std::string path, std::string sessionName ); + + /// writes a single audio buffer to disk for saving whole state. + // When gui_path is set, it only saves a single AB* to that path + int writeAudioBuffer(int track, int scene, AudioBuffer* ab, + const char* gui_path = 0); + + /// flush the JSON to disk, finalizing the save + int writeSession(); + + std::string getLastSaveName(); + std::string getLastSavePath(); + + /// sets a piece of info to be written to the controller + void writeControllerInfo( CONTROLLER_INFO c, std::string s ); + /// writes a controller definition .ctlr JSON file from a GenericMIDI instance + int writeControllerFile( Controller* c ); + + /// writes default config file to users home if it doesn't exist + void writeDefaultConfigToUserHome(); + #ifdef BUILD_TESTS - int runTests(); + int runTests(); #endif - - private: - cJSON* sessionJson; - cJSON* audioJson; - - bool foldersCreated; - std::string sessionName; - std::string sessionPath; - std::string audioDir; - std::string sessionDir; - - std::vector clipData; - - // convienice functions for code separation - void writeMaster(); - - std::string controllerInfo[CONTROLLER_INFO_SIZE]; + +private: + cJSON* sessionJson; + cJSON* audioJson; + + bool foldersCreated; + std::string sessionName; + std::string sessionPath; + std::string audioDir; + std::string sessionDir; + + std::vector clipData; + + // convienice functions for code separation + void writeMaster(); + + std::string controllerInfo[CONTROLLER_INFO_SIZE]; }; #endif // LUPPP_DISK_WRITER_H diff --git a/src/dsp/dsp_dbmeter.hxx b/src/dsp/dsp_dbmeter.hxx index 8140b31..bfde25d 100644 --- a/src/dsp/dsp_dbmeter.hxx +++ b/src/dsp/dsp_dbmeter.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -26,63 +26,68 @@ class DBMeter { - public: - DBMeter(int rate) - { - fSamplingFreq = rate; - fConst0 = (96.f / float(min(192000, max(1, fSamplingFreq)))); - - fRec0[0] = -96.f; - fRec0[1] = -96.f; - fRec1[0] = -96.f; - fRec1[1] = -96.f; - - fvbargraph0 = -96.f; - fvbargraph1 = -96.f; - } - - int getNumInputs() { return 2;} - int getNumOutputs(){ return 2;} - - // call these to get the current dB values - float getLeftDB() - { - // range scale from range = -96 -> +10, to 0 -> 1 - float zeroOneL = (1-(fvbargraph0 / -96.f)); - fvbargraph0 = -96; - return pow(zeroOneL, 4); - } - float getRightDB() - { - float zeroOneR = (1-(fvbargraph1 / -96.f)); - fvbargraph1 = -96; - return pow(zeroOneR, 4); - } - - void process(int count, float* inputL, float* inputR ) - { - for (int i = 0; (i < count); i = (i + 1)) - { - fRec0[0] = max((fRec0[1] - fConst0), min(10.f, (20.f * log10f(max(1.58489e-05f, fabsf(*inputL)))))); - if ( fvbargraph0 < fRec0[0] ) - fvbargraph0 = fRec0[0]; - - fRec1[0] = max((fRec1[1] - fConst0), min(10.f, (20.f * log10f(max(1.58489e-05f, fabsf(*inputR)))))); - if ( fvbargraph1 < fRec1[0] ) - fvbargraph1 = fRec1[0]; - - fRec0[1] = fRec0[0]; - fRec1[1] = fRec1[0]; - } - } - - private: - float fRec0[2]; - float fRec1[2]; - int fSamplingFreq; - float fConst0; - float fvbargraph0; - float fvbargraph1; +public: + DBMeter(int rate) + { + fSamplingFreq = rate; + fConst0 = (96.f / float(min(192000, max(1, fSamplingFreq)))); + + fRec0[0] = -96.f; + fRec0[1] = -96.f; + fRec1[0] = -96.f; + fRec1[1] = -96.f; + + fvbargraph0 = -96.f; + fvbargraph1 = -96.f; + } + + int getNumInputs() + { + return 2; + } + int getNumOutputs() + { + return 2; + } + + // call these to get the current dB values + float getLeftDB() + { + // range scale from range = -96 -> +10, to 0 -> 1 + float zeroOneL = (1-(fvbargraph0 / -96.f)); + fvbargraph0 = -96; + return pow(zeroOneL, 4); + } + float getRightDB() + { + float zeroOneR = (1-(fvbargraph1 / -96.f)); + fvbargraph1 = -96; + return pow(zeroOneR, 4); + } + + void process(int count, float* inputL, float* inputR ) + { + for (int i = 0; (i < count); i = (i + 1)) { + fRec0[0] = max((fRec0[1] - fConst0), min(10.f, (20.f * log10f(max(1.58489e-05f, fabsf(*inputL)))))); + if ( fvbargraph0 < fRec0[0] ) + fvbargraph0 = fRec0[0]; + + fRec1[0] = max((fRec1[1] - fConst0), min(10.f, (20.f * log10f(max(1.58489e-05f, fabsf(*inputR)))))); + if ( fvbargraph1 < fRec1[0] ) + fvbargraph1 = fRec1[0]; + + fRec0[1] = fRec0[0]; + fRec1[1] = fRec1[0]; + } + } + +private: + float fRec0[2]; + float fRec1[2]; + int fSamplingFreq; + float fConst0; + float fvbargraph0; + float fvbargraph1; }; #endif // OPENAV_DSP_DBMETER_H diff --git a/src/dsp/dsp_reverb.hxx b/src/dsp/dsp_reverb.hxx index 7def688..28faf44 100644 --- a/src/dsp/dsp_reverb.hxx +++ b/src/dsp/dsp_reverb.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -24,450 +24,479 @@ #include #include -template inline float faustpower(float x) { return powf(x,N); } -template inline double faustpower(double x) { return pow(x,N); } -template inline int faustpower(int x) { return faustpower(x) * faustpower(x); } -template <> inline int faustpower<0>(int x) { return 1; } -template <> inline int faustpower<1>(int x) { return x; } +template inline float faustpower(float x) +{ + return powf(x,N); +} +template inline double faustpower(double x) +{ + return pow(x,N); +} +template inline int faustpower(int x) +{ + return faustpower(x) * faustpower(x); +} +template <> inline int faustpower<0>(int x) +{ + return 1; +} +template <> inline int faustpower<1>(int x) +{ + return x; +} class Reverb // : Effect { - public: - Reverb(int sr) - { - init( sr ); - } - - int getNumInputs() { return 2; } - int getNumOutputs(){ return 2; } - - void damping(float d) - { - if( d > 1.0 ) d = 1.0f; - if( d < 0.0 ) d = 0.0f; - - _damping = (1-d) * 18500 + 1500.f; - } - - void rt60(float rt) - { - if( rt > 1.0 ) rt = 1.0f; - if( rt < 0.0 ) rt = 0.0f; - - _rt60 = 1 + rt * 5; - } - - void dryWet(float dw) - { - if( dw > 1.0 ) dw = 1.0f; - if( dw < 0.0 ) dw = 0.0f; - _dryWet = dw; - } - - void process (int count, float** input, float** output) - { - float fSlow0 = _rt60; - float fSlow1 = expf((fConst2 / fSlow0)); - float fSlow2 = faustpower<2>(fSlow1); - float fSlow3 = (1.0f - fSlow2); - float fSlow4 = cosf((fConst3 * _damping)); - float fSlow5 = (1.0f - (fSlow4 * fSlow2)); - float fSlow6 = sqrtf(max(0.f, ((faustpower<2>(fSlow5) / faustpower<2>(fSlow3)) - 1.0f))); - float fSlow7 = (fSlow5 / fSlow3); - float fSlow8 = (fSlow7 - fSlow6); - float fSlow9 = (fSlow0 - 0.5f); - float fSlow10 = ((expf((fConst2 / fSlow9)) / fSlow1) - 1); - float fSlow11 = (fSlow1 * ((1.0f + fSlow6) - fSlow7)); - float fSlow12 = expf((fConst12 / fSlow0)); - float fSlow13 = faustpower<2>(fSlow12); - float fSlow14 = (1.0f - fSlow13); - float fSlow15 = (1.0f - (fSlow4 * fSlow13)); - float fSlow16 = sqrtf(max(0.f, ((faustpower<2>(fSlow15) / faustpower<2>(fSlow14)) - 1.0f))); - float fSlow17 = (fSlow15 / fSlow14); - float fSlow18 = (fSlow17 - fSlow16); - float fSlow19 = ((expf((fConst12 / fSlow9)) / fSlow12) - 1); - float fSlow20 = (fSlow12 * ((1.0f + fSlow16) - fSlow17)); - float fSlow21 = expf((fConst17 / fSlow0)); - float fSlow22 = faustpower<2>(fSlow21); - float fSlow23 = (1.0f - fSlow22); - float fSlow24 = (1.0f - (fSlow4 * fSlow22)); - float fSlow25 = sqrtf(max(0.f, ((faustpower<2>(fSlow24) / faustpower<2>(fSlow23)) - 1.0f))); - float fSlow26 = (fSlow24 / fSlow23); - float fSlow27 = (fSlow26 - fSlow25); - float fSlow28 = ((expf((fConst17 / fSlow9)) / fSlow21) - 1); - float fSlow29 = (fSlow21 * ((1.0f + fSlow25) - fSlow26)); - float fSlow30 = expf((fConst22 / fSlow0)); - float fSlow31 = faustpower<2>(fSlow30); - float fSlow32 = (1.0f - fSlow31); - float fSlow33 = (1.0f - (fSlow4 * fSlow31)); - float fSlow34 = sqrtf(max(0.f, ((faustpower<2>(fSlow33) / faustpower<2>(fSlow32)) - 1.0f))); - float fSlow35 = (fSlow33 / fSlow32); - float fSlow36 = (fSlow35 - fSlow34); - float fSlow37 = ((expf((fConst22 / fSlow9)) / fSlow30) - 1); - float fSlow38 = (fSlow30 * ((1.0f + fSlow34) - fSlow35)); - float fSlow39 = expf((fConst27 / fSlow0)); - float fSlow40 = faustpower<2>(fSlow39); - float fSlow41 = (1.0f - fSlow40); - float fSlow42 = (1.0f - (fSlow4 * fSlow40)); - float fSlow43 = sqrtf(max(0.f, ((faustpower<2>(fSlow42) / faustpower<2>(fSlow41)) - 1.0f))); - float fSlow44 = (fSlow42 / fSlow41); - float fSlow45 = (fSlow44 - fSlow43); - float fSlow46 = ((expf((fConst27 / fSlow9)) / fSlow39) - 1); - float fSlow47 = (fSlow39 * ((1.0f + fSlow43) - fSlow44)); - float fSlow48 = expf((fConst32 / fSlow0)); - float fSlow49 = faustpower<2>(fSlow48); - float fSlow50 = (1.0f - fSlow49); - float fSlow51 = (1.0f - (fSlow4 * fSlow49)); - float fSlow52 = sqrtf(max(0.f, ((faustpower<2>(fSlow51) / faustpower<2>(fSlow50)) - 1.0f))); - float fSlow53 = (fSlow51 / fSlow50); - float fSlow54 = (fSlow53 - fSlow52); - float fSlow55 = ((expf((fConst32 / fSlow9)) / fSlow48) - 1); - float fSlow56 = (fSlow48 * ((1.0f + fSlow52) - fSlow53)); - float fSlow57 = expf((fConst37 / fSlow0)); - float fSlow58 = faustpower<2>(fSlow57); - float fSlow59 = (1.0f - fSlow58); - float fSlow60 = (1.0f - (fSlow4 * fSlow58)); - float fSlow61 = sqrtf(max(0.f, ((faustpower<2>(fSlow60) / faustpower<2>(fSlow59)) - 1.0f))); - float fSlow62 = (fSlow60 / fSlow59); - float fSlow63 = (fSlow62 - fSlow61); - float fSlow64 = ((expf((fConst37 / fSlow9)) / fSlow57) - 1); - float fSlow65 = (fSlow57 * ((1.0f + fSlow61) - fSlow62)); - float fSlow66 = expf((fConst42 / fSlow0)); - float fSlow67 = faustpower<2>(fSlow66); - float fSlow68 = (1.0f - fSlow67); - float fSlow69 = (1.0f - (fSlow67 * fSlow4)); - float fSlow70 = sqrtf(max(0.f, ((faustpower<2>(fSlow69) / faustpower<2>(fSlow68)) - 1.0f))); - float fSlow71 = (fSlow69 / fSlow68); - float fSlow72 = (fSlow71 - fSlow70); - float fSlow73 = ((expf((fConst42 / fSlow9)) / fSlow66) - 1); - float fSlow74 = (fSlow66 * ((1.0f + fSlow70) - fSlow71)); - float* input0 = input[0]; - float* input1 = input[1]; - float* output0 = output[0]; - float* output1 = output[1]; - for (int i=0; i 1.0 ) d = 1.0f; + if( d < 0.0 ) d = 0.0f; + + _damping = (1-d) * 18500 + 1500.f; + } + + void rt60(float rt) + { + if( rt > 1.0 ) rt = 1.0f; + if( rt < 0.0 ) rt = 0.0f; + + _rt60 = 1 + rt * 5; + } + + void dryWet(float dw) + { + if( dw > 1.0 ) dw = 1.0f; + if( dw < 0.0 ) dw = 0.0f; + _dryWet = dw; + } + + void process (int count, float** input, float** output) + { + float fSlow0 = _rt60; + float fSlow1 = expf((fConst2 / fSlow0)); + float fSlow2 = faustpower<2>(fSlow1); + float fSlow3 = (1.0f - fSlow2); + float fSlow4 = cosf((fConst3 * _damping)); + float fSlow5 = (1.0f - (fSlow4 * fSlow2)); + float fSlow6 = sqrtf(max(0.f, ((faustpower<2>(fSlow5) / faustpower<2>(fSlow3)) - 1.0f))); + float fSlow7 = (fSlow5 / fSlow3); + float fSlow8 = (fSlow7 - fSlow6); + float fSlow9 = (fSlow0 - 0.5f); + float fSlow10 = ((expf((fConst2 / fSlow9)) / fSlow1) - 1); + float fSlow11 = (fSlow1 * ((1.0f + fSlow6) - fSlow7)); + float fSlow12 = expf((fConst12 / fSlow0)); + float fSlow13 = faustpower<2>(fSlow12); + float fSlow14 = (1.0f - fSlow13); + float fSlow15 = (1.0f - (fSlow4 * fSlow13)); + float fSlow16 = sqrtf(max(0.f, ((faustpower<2>(fSlow15) / faustpower<2>(fSlow14)) - 1.0f))); + float fSlow17 = (fSlow15 / fSlow14); + float fSlow18 = (fSlow17 - fSlow16); + float fSlow19 = ((expf((fConst12 / fSlow9)) / fSlow12) - 1); + float fSlow20 = (fSlow12 * ((1.0f + fSlow16) - fSlow17)); + float fSlow21 = expf((fConst17 / fSlow0)); + float fSlow22 = faustpower<2>(fSlow21); + float fSlow23 = (1.0f - fSlow22); + float fSlow24 = (1.0f - (fSlow4 * fSlow22)); + float fSlow25 = sqrtf(max(0.f, ((faustpower<2>(fSlow24) / faustpower<2>(fSlow23)) - 1.0f))); + float fSlow26 = (fSlow24 / fSlow23); + float fSlow27 = (fSlow26 - fSlow25); + float fSlow28 = ((expf((fConst17 / fSlow9)) / fSlow21) - 1); + float fSlow29 = (fSlow21 * ((1.0f + fSlow25) - fSlow26)); + float fSlow30 = expf((fConst22 / fSlow0)); + float fSlow31 = faustpower<2>(fSlow30); + float fSlow32 = (1.0f - fSlow31); + float fSlow33 = (1.0f - (fSlow4 * fSlow31)); + float fSlow34 = sqrtf(max(0.f, ((faustpower<2>(fSlow33) / faustpower<2>(fSlow32)) - 1.0f))); + float fSlow35 = (fSlow33 / fSlow32); + float fSlow36 = (fSlow35 - fSlow34); + float fSlow37 = ((expf((fConst22 / fSlow9)) / fSlow30) - 1); + float fSlow38 = (fSlow30 * ((1.0f + fSlow34) - fSlow35)); + float fSlow39 = expf((fConst27 / fSlow0)); + float fSlow40 = faustpower<2>(fSlow39); + float fSlow41 = (1.0f - fSlow40); + float fSlow42 = (1.0f - (fSlow4 * fSlow40)); + float fSlow43 = sqrtf(max(0.f, ((faustpower<2>(fSlow42) / faustpower<2>(fSlow41)) - 1.0f))); + float fSlow44 = (fSlow42 / fSlow41); + float fSlow45 = (fSlow44 - fSlow43); + float fSlow46 = ((expf((fConst27 / fSlow9)) / fSlow39) - 1); + float fSlow47 = (fSlow39 * ((1.0f + fSlow43) - fSlow44)); + float fSlow48 = expf((fConst32 / fSlow0)); + float fSlow49 = faustpower<2>(fSlow48); + float fSlow50 = (1.0f - fSlow49); + float fSlow51 = (1.0f - (fSlow4 * fSlow49)); + float fSlow52 = sqrtf(max(0.f, ((faustpower<2>(fSlow51) / faustpower<2>(fSlow50)) - 1.0f))); + float fSlow53 = (fSlow51 / fSlow50); + float fSlow54 = (fSlow53 - fSlow52); + float fSlow55 = ((expf((fConst32 / fSlow9)) / fSlow48) - 1); + float fSlow56 = (fSlow48 * ((1.0f + fSlow52) - fSlow53)); + float fSlow57 = expf((fConst37 / fSlow0)); + float fSlow58 = faustpower<2>(fSlow57); + float fSlow59 = (1.0f - fSlow58); + float fSlow60 = (1.0f - (fSlow4 * fSlow58)); + float fSlow61 = sqrtf(max(0.f, ((faustpower<2>(fSlow60) / faustpower<2>(fSlow59)) - 1.0f))); + float fSlow62 = (fSlow60 / fSlow59); + float fSlow63 = (fSlow62 - fSlow61); + float fSlow64 = ((expf((fConst37 / fSlow9)) / fSlow57) - 1); + float fSlow65 = (fSlow57 * ((1.0f + fSlow61) - fSlow62)); + float fSlow66 = expf((fConst42 / fSlow0)); + float fSlow67 = faustpower<2>(fSlow66); + float fSlow68 = (1.0f - fSlow67); + float fSlow69 = (1.0f - (fSlow67 * fSlow4)); + float fSlow70 = sqrtf(max(0.f, ((faustpower<2>(fSlow69) / faustpower<2>(fSlow68)) - 1.0f))); + float fSlow71 = (fSlow69 / fSlow68); + float fSlow72 = (fSlow71 - fSlow70); + float fSlow73 = ((expf((fConst42 / fSlow9)) / fSlow66) - 1); + float fSlow74 = (fSlow66 * ((1.0f + fSlow70) - fSlow71)); + float* input0 = input[0]; + float* input1 = input[1]; + float* output0 = output[0]; + float* output1 = output[1]; + for (int i=0; i. */ @@ -22,84 +22,77 @@ #include SidechainGain::SidechainGain(int rate) : - /// initial control values - controlThreshold(0.2), - controlReduction(1), - controlReleaseTime(0.5), - - /// filter state init - w(10.0f / (rate * 0.02)), - a(0.07f), - b(1.0f / (1.0f - a)), - g1(0.0f), - g2(0.0f), - - - peakFrameCounter(0), - peakCountDuration( rate / 4 ), - currentTarget(0) + /// initial control values + controlThreshold(0.2), + controlReduction(1), + controlReleaseTime(0.5), + + /// filter state init + w(10.0f / (rate * 0.02)), + a(0.07f), + b(1.0f / (1.0f - a)), + g1(0.0f), + g2(0.0f), + + + peakFrameCounter(0), + peakCountDuration( rate / 4 ), + currentTarget(0) { } void SidechainGain::process(unsigned int n_samples, float** inputs, float** outputs) { - /// audio inputs - float* inL = inputs[0]; - float* inR = inputs[1]; - float* side = inputs[2]; - float* outL = outputs[0]; - float* outR = outputs[1]; - - /// control inputs - float threshold = controlThreshold; - float reduction = controlReduction; - float releaseTime = controlReleaseTime; - - - /// analyse sidechain input for peak - float sum = 0.f; - for( unsigned int i = 0; i < n_samples; i++ ) - { - if ( *side > 0.000001 ) - sum += *side++; - else - sum += -*side++; - } - - currentTarget = 0.f; - - /// check for peak level (offset to avoid "always on" peak) - if ( sum / n_samples > threshold + 0.05 ) - { - peakFrameCounter = peakCountDuration * releaseTime; - currentTarget = 1.f - reduction; - } - else if ( peakFrameCounter < 0 ) - { - currentTarget = 1.f; - } - else - { - currentTarget = 1.f - reduction; - } - - if ( currentTarget < 0.f ) - currentTarget = 0.f; - - peakFrameCounter -= n_samples; - - for( unsigned int i = 0; i < n_samples; i++ ) - { - /// smoothing algo is a lowpass, to de-zip the fades - /// x^^4 approximates linear volume increase for human ears - g1 += w * ( pow ( currentTarget, 4.f ) - g1 - a * g2 - 1e-20f); - g2 += w * (b * g1 - g2 + 1e-20f); - float gain = g2; - - *outL++ = *inL++ * gain; - *outR++ = *inR++ * gain; - } - - /// update output value - controlSidechainAmp = currentTarget; + /// audio inputs + float* inL = inputs[0]; + float* inR = inputs[1]; + float* side = inputs[2]; + float* outL = outputs[0]; + float* outR = outputs[1]; + + /// control inputs + float threshold = controlThreshold; + float reduction = controlReduction; + float releaseTime = controlReleaseTime; + + + /// analyse sidechain input for peak + float sum = 0.f; + for( unsigned int i = 0; i < n_samples; i++ ) { + if ( *side > 0.000001 ) + sum += *side++; + else + sum += -*side++; + } + + currentTarget = 0.f; + + /// check for peak level (offset to avoid "always on" peak) + if ( sum / n_samples > threshold + 0.05 ) { + peakFrameCounter = peakCountDuration * releaseTime; + currentTarget = 1.f - reduction; + } else if ( peakFrameCounter < 0 ) { + currentTarget = 1.f; + } else { + currentTarget = 1.f - reduction; + } + + if ( currentTarget < 0.f ) + currentTarget = 0.f; + + peakFrameCounter -= n_samples; + + for( unsigned int i = 0; i < n_samples; i++ ) { + /// smoothing algo is a lowpass, to de-zip the fades + /// x^^4 approximates linear volume increase for human ears + g1 += w * ( pow ( currentTarget, 4.f ) - g1 - a * g2 - 1e-20f); + g2 += w * (b * g1 - g2 + 1e-20f); + float gain = g2; + + *outL++ = *inL++ * gain; + *outR++ = *inR++ * gain; + } + + /// update output value + controlSidechainAmp = currentTarget; } diff --git a/src/dsp/dsp_sidechain_gain.hxx b/src/dsp/dsp_sidechain_gain.hxx index 89cb875..e097c69 100644 --- a/src/dsp/dsp_sidechain_gain.hxx +++ b/src/dsp/dsp_sidechain_gain.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -25,42 +25,51 @@ class SidechainGain { - public: - SidechainGain(int rate); - ~SidechainGain(){} - - void threshold(float t){controlThreshold = t;} - void reduction(float r){controlReduction = r;} - void time (float t){controlReleaseTime = t;} - - void process(unsigned int n_samples, float** inputs, float** outputs); - - private: - /// audio buffers - float* audioInputL; - float* audioInputR; - float* audioSidechain; - float* audioOutputL; - float* audioOutputR; - - /// control signals - float controlThreshold; - float controlReduction; - float controlReleaseTime; - float controlSidechainAmp; - - /// filter state - float w, a, b, g1, g2; - - /// last peak history - bool nowIsAPeak; - long peakFrameCounter; - - /// nframes available for countdown - long peakCountDuration; - - /// control output - float currentTarget; +public: + SidechainGain(int rate); + ~SidechainGain() {} + + void threshold(float t) + { + controlThreshold = t; + } + void reduction(float r) + { + controlReduction = r; + } + void time (float t) + { + controlReleaseTime = t; + } + + void process(unsigned int n_samples, float** inputs, float** outputs); + +private: + /// audio buffers + float* audioInputL; + float* audioInputR; + float* audioSidechain; + float* audioOutputL; + float* audioOutputR; + + /// control signals + float controlThreshold; + float controlReduction; + float controlReleaseTime; + float controlSidechainAmp; + + /// filter state + float w, a, b, g1, g2; + + /// last peak history + bool nowIsAPeak; + long peakFrameCounter; + + /// nframes available for countdown + long peakCountDuration; + + /// control output + float currentTarget; }; #endif // OPENAV_DSP_SIDECHAIN_GAIN_H diff --git a/src/event.cxx b/src/event.cxx index d8e3c3c..cf52316 100644 --- a/src/event.cxx +++ b/src/event.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -42,46 +42,78 @@ const char* EventGridLaunchScene::prettyName = "grid:launch_scene"; EVENT_TYPE Event::getTypeFromName(const char* name) { - for(int i = 0; i < EVENT_TYPE_FINAL; i++) - { - const char* tmp = getPrettyName(i); - if ( tmp ) - { - if ( strcmp( name, tmp ) == 0 ) { - return (EVENT_TYPE)i; - } - } - } - - return EVENT_NULL; + for(int i = 0; i < EVENT_TYPE_FINAL; i++) { + const char* tmp = getPrettyName(i); + if ( tmp ) { + if ( strcmp( name, tmp ) == 0 ) { + return (EVENT_TYPE)i; + } + } + } + + return EVENT_NULL; } const char* Event::getPrettyName( int type ) { - switch ( type ) - { - case MASTER_VOL:{ return EventMasterVol::prettyName; } - case MASTER_RETURN:{ return EventMasterReturn::prettyName; } - case MASTER_INPUT_VOL:{ return EventMasterInputVol::prettyName; } - case MASTER_INPUT_TO:{ return EventMasterInputTo::prettyName; } - case MASTER_INPUT_TO_ACTIVE:{ return EventMasterInputToActive::prettyName; } - - case TRACK_VOLUME:{ return EventTrackVol::prettyName; } - case TRACK_SEND:{ return EventTrackSend::prettyName; } - case TRACK_SEND_ACTIVE:{ return EventTrackSendActive::prettyName; } - case TRACK_JACKSEND:{ return EventTrackJackSend::prettyName; } - case TRACK_JACKSEND_ACTIVATE:{ return EventTrackJackSendActivate::prettyName; } - case TRACK_RECORD_ARM:{ return EventTrackRecordArm::prettyName; } - - case TIME_BPM:{ return EventTimeBPM::prettyName; } - case TIME_TEMPO_TAP:{ return EventTimeTempoTap::prettyName; } - - case GRID_EVENT:{ return EventGridEvent::prettyName; } - case GRID_LAUNCH_SCENE:{ return EventGridLaunchScene::prettyName; } - - case METRONOME_ACTIVE:{ return EventMetronomeActive::prettyName; } - case METRONOME_VOLUME:{ return EventMetronomeVolume::prettyName; } - - default: return 0; - } + switch ( type ) { + case MASTER_VOL: { + return EventMasterVol::prettyName; + } + case MASTER_RETURN: { + return EventMasterReturn::prettyName; + } + case MASTER_INPUT_VOL: { + return EventMasterInputVol::prettyName; + } + case MASTER_INPUT_TO: { + return EventMasterInputTo::prettyName; + } + case MASTER_INPUT_TO_ACTIVE: { + return EventMasterInputToActive::prettyName; + } + + case TRACK_VOLUME: { + return EventTrackVol::prettyName; + } + case TRACK_SEND: { + return EventTrackSend::prettyName; + } + case TRACK_SEND_ACTIVE: { + return EventTrackSendActive::prettyName; + } + case TRACK_JACKSEND: { + return EventTrackJackSend::prettyName; + } + case TRACK_JACKSEND_ACTIVATE: { + return EventTrackJackSendActivate::prettyName; + } + case TRACK_RECORD_ARM: { + return EventTrackRecordArm::prettyName; + } + + case TIME_BPM: { + return EventTimeBPM::prettyName; + } + case TIME_TEMPO_TAP: { + return EventTimeTempoTap::prettyName; + } + + case GRID_EVENT: { + return EventGridEvent::prettyName; + } + case GRID_LAUNCH_SCENE: { + return EventGridLaunchScene::prettyName; + } + + case METRONOME_ACTIVE: { + return EventMetronomeActive::prettyName; + } + case METRONOME_VOLUME: { + return EventMetronomeVolume::prettyName; + } + + default: + return 0; + } } diff --git a/src/event.hxx b/src/event.hxx index e3efca1..3cc598d 100644 --- a/src/event.hxx +++ b/src/event.hxx @@ -1,21 +1,21 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #ifndef LUPPP_EVENT_H #define LUPPP_EVENT_H @@ -24,7 +24,7 @@ /* event.hxx - + This file provides declarations for each type of event that the engine uses. */ @@ -38,104 +38,101 @@ using namespace std; namespace Event { - enum SEND_TYPE - { - SEND_POSTFADER = 0, - SEND_KEY, - SEND_XSIDE, - }; - enum RETURN_TYPE - { - RETURN_INVALID = 0, - RETURN_MAIN, - }; - enum INPUT_TO - { - INPUT_TO_SEND = 0, - INPUT_TO_MIX, - INPUT_TO_XSIDE, - INPUT_TO_SIDE_KEY, - }; - - enum EVENT_TYPE { - // default event type - EVENT_NULL = 0, - - MASTER_VOL, - MASTER_INPUT_VOL, - MASTER_INPUT_TO, - MASTER_INPUT_TO_ACTIVE, - MASTER_RETURN, - RECORD, - - STATE_SAVE, // save action - STATE_RESET, // reset all state - STATE_SAVE_FINISH,// save action finished, flush metadata to disk - STATE_SAVE_BUFFER,// save an individual AudioBuffer* to disk - - REQUEST_SAVE_BUFFER, // gets an audioBuffer of a certain size - - /// Grid - GRID_EVENT, // press / release events - GRID_STATE, // state of one block - GRID_LAUNCH_SCENE, // launches a scene - GRID_SELECT_CLIP_ENABLE, // enable selecting a clip from the grid - GRID_SELECT_CLIP_EVENT, // a press / release on the selected clip - GRID_SELECT_NEW_CHOSEN, // a different clip is now "special" - - /// Track - TRACK_JACKSEND, - TRACK_JACKSEND_ACTIVATE, - TRACK_SEND, - TRACK_SEND_ACTIVE, - TRACK_SIGNAL_LEVEL, - TRACK_VOLUME, - TRACK_RECORD_ARM, - - FX_REVERB, - - LOOPER_LOAD, - LOOPER_STATE, - LOOPER_PROGRESS, - LOOPER_LOOP_LENGTH, - LOOPER_LOOP_USE_AS_TEMPO, - - /// Transport etc - METRONOME_ACTIVE, - METRONOME_VOLUME, - TRANSPORT, /// rolling or stopped - - TIME_BPM, - TIME_BAR_BEAT, - TIME_TEMPO_TAP, - - GUI_PRINT, - - LOOPER_REQUEST_BUFFER, - DEALLOCATE_BUFFER, - - SAMPLERATE, - - // Controller - CONTROLLER_INSTANCE, - CONTROLLER_INSTANCE_REMOVE, - CONTROLLER_INSTANCE_GET_TO_WRITE, - CONTROLLER_BINDING_ENABLE, - CONTROLLER_BINDING_TARGET, - CONTROLLER_BINDING_MADE, - CONTROLLER_BINDING_REMOVE, - - QUIT, - - // for keeping loop index's inside the enum - EVENT_TYPE_FINAL, - }; - - /// returns the pretty name of an event - const char* getPrettyName( int type ); - - /// returns an EVENT_TYPE from a pretty name - EVENT_TYPE getTypeFromName(const char* name); +enum SEND_TYPE { + SEND_POSTFADER = 0, + SEND_KEY, + SEND_XSIDE, +}; +enum RETURN_TYPE { + RETURN_INVALID = 0, + RETURN_MAIN, +}; +enum INPUT_TO { + INPUT_TO_SEND = 0, + INPUT_TO_MIX, + INPUT_TO_XSIDE, + INPUT_TO_SIDE_KEY, +}; + +enum EVENT_TYPE { + // default event type + EVENT_NULL = 0, + + MASTER_VOL, + MASTER_INPUT_VOL, + MASTER_INPUT_TO, + MASTER_INPUT_TO_ACTIVE, + MASTER_RETURN, + RECORD, + + STATE_SAVE, // save action + STATE_RESET, // reset all state + STATE_SAVE_FINISH,// save action finished, flush metadata to disk + STATE_SAVE_BUFFER,// save an individual AudioBuffer* to disk + + REQUEST_SAVE_BUFFER, // gets an audioBuffer of a certain size + + /// Grid + GRID_EVENT, // press / release events + GRID_STATE, // state of one block + GRID_LAUNCH_SCENE, // launches a scene + GRID_SELECT_CLIP_ENABLE, // enable selecting a clip from the grid + GRID_SELECT_CLIP_EVENT, // a press / release on the selected clip + GRID_SELECT_NEW_CHOSEN, // a different clip is now "special" + + /// Track + TRACK_JACKSEND, + TRACK_JACKSEND_ACTIVATE, + TRACK_SEND, + TRACK_SEND_ACTIVE, + TRACK_SIGNAL_LEVEL, + TRACK_VOLUME, + TRACK_RECORD_ARM, + + FX_REVERB, + + LOOPER_LOAD, + LOOPER_STATE, + LOOPER_PROGRESS, + LOOPER_LOOP_LENGTH, + LOOPER_LOOP_USE_AS_TEMPO, + + /// Transport etc + METRONOME_ACTIVE, + METRONOME_VOLUME, + TRANSPORT, /// rolling or stopped + + TIME_BPM, + TIME_BAR_BEAT, + TIME_TEMPO_TAP, + + GUI_PRINT, + + LOOPER_REQUEST_BUFFER, + DEALLOCATE_BUFFER, + + SAMPLERATE, + + // Controller + CONTROLLER_INSTANCE, + CONTROLLER_INSTANCE_REMOVE, + CONTROLLER_INSTANCE_GET_TO_WRITE, + CONTROLLER_BINDING_ENABLE, + CONTROLLER_BINDING_TARGET, + CONTROLLER_BINDING_MADE, + CONTROLLER_BINDING_REMOVE, + + QUIT, + + // for keeping loop index's inside the enum + EVENT_TYPE_FINAL, +}; + +/// returns the pretty name of an event +const char* getPrettyName( int type ); + +/// returns an EVENT_TYPE from a pretty name +EVENT_TYPE getTypeFromName(const char* name); }; using namespace Event; @@ -144,654 +141,984 @@ class AudioBuffer; class EventBase { - public: - virtual ~EventBase() {} - - virtual int type() = 0; - virtual uint32_t size() = 0; - - /// returns const char* to static char buffer: is the pretty name for event - /// optional override: if function isn't overriden, no target update sent - virtual const char* name(){return 0;} +public: + virtual ~EventBase() {} + + virtual int type() = 0; + virtual uint32_t size() = 0; + + /// returns const char* to static char buffer: is the pretty name for event + /// optional override: if function isn't overriden, no target update sent + virtual const char* name() + { + return 0; + } }; class EventTransportState : public EventBase { - public: - int type() { return int(TRANSPORT); } - uint32_t size() { return sizeof(EventTransportState); } - TRANSPORT_STATE ts; - EventTransportState(): ts( TRANSPORT_STOPPED ){} - EventTransportState( TRANSPORT_STATE t): ts(t){} +public: + int type() + { + return int(TRANSPORT); + } + uint32_t size() + { + return sizeof(EventTransportState); + } + TRANSPORT_STATE ts; + EventTransportState(): ts( TRANSPORT_STOPPED ) {} + EventTransportState( TRANSPORT_STATE t): ts(t) {} }; class EventControllerBindingMade : public EventBase { - public: - int type() { return int(CONTROLLER_BINDING_MADE); } - uint32_t size() { return sizeof(EventControllerBindingMade); } - int controllerID; - void* binding; - EventControllerBindingMade(int id = 0, void* b=0): controllerID(id), binding(b){} +public: + int type() + { + return int(CONTROLLER_BINDING_MADE); + } + uint32_t size() + { + return sizeof(EventControllerBindingMade); + } + int controllerID; + void* binding; + EventControllerBindingMade(int id = 0, void* b=0): controllerID(id), binding(b) {} }; class EventControllerBindingRemove : public EventBase { - public: - int type() { return int(CONTROLLER_BINDING_REMOVE); } - uint32_t size() { return sizeof(EventControllerBindingRemove); } - int controllerID; - int bindingID; - void* binding; - EventControllerBindingRemove(int ctlrID = 0, int bindID=0, void* b=0): controllerID(ctlrID), bindingID(bindID), binding(b){} +public: + int type() + { + return int(CONTROLLER_BINDING_REMOVE); + } + uint32_t size() + { + return sizeof(EventControllerBindingRemove); + } + int controllerID; + int bindingID; + void* binding; + EventControllerBindingRemove(int ctlrID = 0, int bindID=0, void* b=0): controllerID(ctlrID), bindingID(bindID), binding(b) {} }; class EventControllerBindingEnable : public EventBase { - public: - int type() { return int(CONTROLLER_BINDING_ENABLE); } - uint32_t size() { return sizeof(EventControllerBindingEnable); } - int controllerID; - bool enable; - EventControllerBindingEnable(int id = 0, bool e=false):controllerID(id),enable(e){} +public: + int type() + { + return int(CONTROLLER_BINDING_ENABLE); + } + uint32_t size() + { + return sizeof(EventControllerBindingEnable); + } + int controllerID; + bool enable; + EventControllerBindingEnable(int id = 0, bool e=false):controllerID(id),enable(e) {} }; class EventGridSelectClipEvent : public EventBase { - public: - int type() { return int(GRID_SELECT_CLIP_EVENT); } - uint32_t size() { return sizeof(EventGridSelectClipEvent); } - bool pressed; - EventGridSelectClipEvent(bool p=false):pressed(p){} +public: + int type() + { + return int(GRID_SELECT_CLIP_EVENT); + } + uint32_t size() + { + return sizeof(EventGridSelectClipEvent); + } + bool pressed; + EventGridSelectClipEvent(bool p=false):pressed(p) {} }; class EventGridSelectClipEnable : public EventBase { - public: - int type() { return int(GRID_SELECT_CLIP_ENABLE); } - uint32_t size() { return sizeof(EventGridSelectClipEnable); } - bool enable; - EventGridSelectClipEnable(bool e=false):enable(e){} +public: + int type() + { + return int(GRID_SELECT_CLIP_ENABLE); + } + uint32_t size() + { + return sizeof(EventGridSelectClipEnable); + } + bool enable; + EventGridSelectClipEnable(bool e=false):enable(e) {} }; class EventGridSelectNewChosen : public EventBase { - public: - int type() { return int(GRID_SELECT_NEW_CHOSEN); } - uint32_t size() { return sizeof(EventGridSelectNewChosen); } - int track; - int scene; - EventGridSelectNewChosen(int t = -1, int s = -1):track(t),scene(s){} +public: + int type() + { + return int(GRID_SELECT_NEW_CHOSEN); + } + uint32_t size() + { + return sizeof(EventGridSelectNewChosen); + } + int track; + int scene; + EventGridSelectNewChosen(int t = -1, int s = -1):track(t),scene(s) {} }; class EventQuit : public EventBase { - public: - int type() { return int(QUIT); } - uint32_t size() { return sizeof(EventQuit); } - EventQuit(){} +public: + int type() + { + return int(QUIT); + } + uint32_t size() + { + return sizeof(EventQuit); + } + EventQuit() {} }; class EventSamplerate : public EventBase { - public: - int type() { return int(SAMPLERATE); } - uint32_t size() { return sizeof(EventSamplerate); } - int samplerate; - EventSamplerate(int sr = 0): samplerate(sr){} +public: + int type() + { + return int(SAMPLERATE); + } + uint32_t size() + { + return sizeof(EventSamplerate); + } + int samplerate; + EventSamplerate(int sr = 0): samplerate(sr) {} }; class EventControllerInstance : public EventBase { - public: - int type() { return int(CONTROLLER_INSTANCE); } - uint32_t size() { return sizeof(EventControllerInstance); } - void* controller; - EventControllerInstance(void* c = 0) : controller(c) {} +public: + int type() + { + return int(CONTROLLER_INSTANCE); + } + uint32_t size() + { + return sizeof(EventControllerInstance); + } + void* controller; + EventControllerInstance(void* c = 0) : controller(c) {} }; class EventControllerInstanceRemove : public EventBase { - public: - int type() { return int(CONTROLLER_INSTANCE_REMOVE); } - uint32_t size() { return sizeof(EventControllerInstanceRemove); } - int ID; - EventControllerInstanceRemove(int i = -1) : ID(i) {} +public: + int type() + { + return int(CONTROLLER_INSTANCE_REMOVE); + } + uint32_t size() + { + return sizeof(EventControllerInstanceRemove); + } + int ID; + EventControllerInstanceRemove(int i = -1) : ID(i) {} }; /// writes the GenericMIDI controller instance to a .ctlr file class EventControllerInstanceGetToWrite : public EventBase { - public: - int type() { return int(CONTROLLER_INSTANCE_GET_TO_WRITE); } - uint32_t size() { return sizeof(EventControllerInstanceGetToWrite); } - int ID; - void* controller; - EventControllerInstanceGetToWrite(int id = 0, void* c = 0) : ID(id), controller(c) {} +public: + int type() + { + return int(CONTROLLER_INSTANCE_GET_TO_WRITE); + } + uint32_t size() + { + return sizeof(EventControllerInstanceGetToWrite); + } + int ID; + void* controller; + EventControllerInstanceGetToWrite(int id = 0, void* c = 0) : ID(id), controller(c) {} }; class EventMasterInputTo : public EventBase { - public: - int type() { return int(MASTER_INPUT_TO); } - uint32_t size() { return sizeof(EventMasterInputTo); } - static const char* prettyName; - const char* name(){ return prettyName; } - - int place; - float value; - EventMasterInputTo(int p=-1, float v=0) : place(p), value(v){} +public: + int type() + { + return int(MASTER_INPUT_TO); + } + uint32_t size() + { + return sizeof(EventMasterInputTo); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } + + int place; + float value; + EventMasterInputTo(int p=-1, float v=0) : place(p), value(v) {} }; class EventMasterInputToActive : public EventBase { - public: - int type() { return int(MASTER_INPUT_TO_ACTIVE); } - uint32_t size() { return sizeof(EventMasterInputToActive); } - static const char* prettyName; - const char* name(){ return prettyName; } - - int place; - bool active; - EventMasterInputToActive(int p=-1, bool a=false) : place(p), active(a){} +public: + int type() + { + return int(MASTER_INPUT_TO_ACTIVE); + } + uint32_t size() + { + return sizeof(EventMasterInputToActive); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } + + int place; + bool active; + EventMasterInputToActive(int p=-1, bool a=false) : place(p), active(a) {} }; class EventMasterVol : public EventBase { - public: - static const char* prettyName; - const char* name(){ return prettyName; } - int type() { return int(MASTER_VOL); } - uint32_t size() { return sizeof(EventMasterVol); } - - float vol; - EventMasterVol(float v = 0) : vol(v){} +public: + static const char* prettyName; + const char* name() + { + return prettyName; + } + int type() + { + return int(MASTER_VOL); + } + uint32_t size() + { + return sizeof(EventMasterVol); + } + + float vol; + EventMasterVol(float v = 0) : vol(v) {} }; class EventMasterInputVol : public EventBase { - public: - static const char* prettyName; - const char* name(){ return prettyName; } - int type() { return int(MASTER_INPUT_VOL); } - uint32_t size() { return sizeof(EventMasterInputVol); } - float vol; - EventMasterInputVol(float v = 0) : vol(v){} +public: + static const char* prettyName; + const char* name() + { + return prettyName; + } + int type() + { + return int(MASTER_INPUT_VOL); + } + uint32_t size() + { + return sizeof(EventMasterInputVol); + } + float vol; + EventMasterInputVol(float v = 0) : vol(v) {} }; class EventMasterReturn : public EventBase { - public: - int type() { return int(MASTER_RETURN); } - uint32_t size() { return sizeof(EventMasterReturn); } - static const char* prettyName; - const char* name(){ return prettyName; } - - RETURN_TYPE ret; - float vol; - EventMasterReturn(RETURN_TYPE s=RETURN_INVALID, float v=0): ret(s), vol(v){} +public: + int type() + { + return int(MASTER_RETURN); + } + uint32_t size() + { + return sizeof(EventMasterReturn); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } + + RETURN_TYPE ret; + float vol; + EventMasterReturn(RETURN_TYPE s=RETURN_INVALID, float v=0): ret(s), vol(v) {} }; class EventTrackVol : public EventBase { - public: - int type() { return int(TRACK_VOLUME); } - uint32_t size() { return sizeof(EventTrackVol); } - static const char* prettyName; - const char* name(){ return prettyName; } - - int track; - float vol; - - EventTrackVol(){}; - EventTrackVol(int t, float v) - { - track = t; - vol = v; - } +public: + int type() + { + return int(TRACK_VOLUME); + } + uint32_t size() + { + return sizeof(EventTrackVol); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } + + int track; + float vol; + + EventTrackVol() {}; + EventTrackVol(int t, float v) + { + track = t; + vol = v; + } }; class EventTrackRecordArm : public EventBase { - public: - int type() { return int(TRACK_RECORD_ARM); } - uint32_t size() { return sizeof(EventTrackRecordArm); } - static const char* prettyName; - const char* name(){ return prettyName; } - - int track; - float recordArm; - - EventTrackRecordArm(){}; - EventTrackRecordArm(int t, bool r) - { - track = t; - recordArm = r; - } +public: + int type() + { + return int(TRACK_RECORD_ARM); + } + uint32_t size() + { + return sizeof(EventTrackRecordArm); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } + + int track; + float recordArm; + + EventTrackRecordArm() {}; + EventTrackRecordArm(int t, bool r) + { + track = t; + recordArm = r; + } }; class EventStateSave : public EventBase { - public: - int type() { return int(STATE_SAVE); } - uint32_t size() { return sizeof(EventStateSave); } - - EventStateSave() {} +public: + int type() + { + return int(STATE_SAVE); + } + uint32_t size() + { + return sizeof(EventStateSave); + } + + EventStateSave() {} }; class EventStateReset : public EventBase { - public: - int type() { return int(STATE_RESET); } - uint32_t size() { return sizeof(EventStateReset); } - - EventStateReset() {} +public: + int type() + { + return int(STATE_RESET); + } + uint32_t size() + { + return sizeof(EventStateReset); + } + + EventStateReset() {} }; class EventStateSaveFinish : public EventBase { - public: - int type() { return int(STATE_SAVE_FINISH); } - uint32_t size() { return sizeof(EventStateSaveFinish); } - - EventStateSaveFinish(){}; +public: + int type() + { + return int(STATE_SAVE_FINISH); + } + uint32_t size() + { + return sizeof(EventStateSaveFinish); + } + + EventStateSaveFinish() {}; }; class EventGridEvent : public EventBase { - public: - int type() { return int(GRID_EVENT); } - uint32_t size() { return sizeof(EventGridEvent); } - static const char* prettyName; - const char* name(){ return prettyName; } - - int track; - int scene; - bool pressed; - - EventGridEvent(){}; - EventGridEvent(int t, int s, bool p): track(t), scene(s), pressed(p) {} +public: + int type() + { + return int(GRID_EVENT); + } + uint32_t size() + { + return sizeof(EventGridEvent); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } + + int track; + int scene; + bool pressed; + + EventGridEvent() {}; + EventGridEvent(int t, int s, bool p): track(t), scene(s), pressed(p) {} }; class EventGridState : public EventBase { - public: - int type() { return int(GRID_STATE); } - uint32_t size() { return sizeof(EventGridState); } - - int track; - int scene; - GridLogic::State state; - - EventGridState(){}; - EventGridState(int t, int s, GridLogic::State st): track(t), scene(s), state(st) {} +public: + int type() + { + return int(GRID_STATE); + } + uint32_t size() + { + return sizeof(EventGridState); + } + + int track; + int scene; + GridLogic::State state; + + EventGridState() {}; + EventGridState(int t, int s, GridLogic::State st): track(t), scene(s), state(st) {} }; class EventGridLaunchScene : public EventBase { - public: - int type() { return int(GRID_LAUNCH_SCENE); } - uint32_t size() { return sizeof(EventGridLaunchScene); } - static const char* prettyName; - const char* name(){ return prettyName; } - - int scene; - - EventGridLaunchScene(){}; - EventGridLaunchScene(int s): scene(s){} +public: + int type() + { + return int(GRID_LAUNCH_SCENE); + } + uint32_t size() + { + return sizeof(EventGridLaunchScene); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } + + int scene; + + EventGridLaunchScene() {}; + EventGridLaunchScene(int s): scene(s) {} }; class EventFxReverb : public EventBase { - public: - int type() { return int(FX_REVERB); } - uint32_t size() { return sizeof(EventFxReverb); } - - bool enable; - - float rtSize; - float wet; - float damping; - - EventFxReverb(){}; - EventFxReverb(bool e, float s, float w, float d): enable(e), rtSize(s), wet(w), damping(d) {} +public: + int type() + { + return int(FX_REVERB); + } + uint32_t size() + { + return sizeof(EventFxReverb); + } + + bool enable; + + float rtSize; + float wet; + float damping; + + EventFxReverb() {}; + EventFxReverb(bool e, float s, float w, float d): enable(e), rtSize(s), wet(w), damping(d) {} }; class EventTrackSend : public EventBase { - public: - int type() { return int(TRACK_SEND); } - uint32_t size() { return sizeof(EventTrackSend); } - static const char* prettyName; - const char* name(){ return prettyName; } - - int track; - SEND_TYPE send; - float value; - - EventTrackSend(){}; - EventTrackSend(int t, SEND_TYPE s, float v): track(t), send(s), value(v){} +public: + int type() + { + return int(TRACK_SEND); + } + uint32_t size() + { + return sizeof(EventTrackSend); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } + + int track; + SEND_TYPE send; + float value; + + EventTrackSend() {}; + EventTrackSend(int t, SEND_TYPE s, float v): track(t), send(s), value(v) {} }; class EventTrackJackSend : public EventBase { - public: - int type() { return int(TRACK_JACKSEND); } - uint32_t size() { return sizeof(EventTrackJackSend); } - static const char* prettyName; - const char* name(){ return prettyName; } +public: + int type() + { + return int(TRACK_JACKSEND); + } + uint32_t size() + { + return sizeof(EventTrackJackSend); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } - int track; + int track; - float value; + float value; - EventTrackJackSend(){}; - EventTrackJackSend(int t, float v): track(t), value(v){} + EventTrackJackSend() {}; + EventTrackJackSend(int t, float v): track(t), value(v) {} }; class EventTrackSendActive : public EventBase { - public: - int type() { return int(TRACK_SEND_ACTIVE); } - uint32_t size() { return sizeof(EventTrackSendActive); } - static const char* prettyName; - const char* name(){ return prettyName; } - - int track; - SEND_TYPE send; - bool active; - - EventTrackSendActive(){}; - EventTrackSendActive(int t, SEND_TYPE s, bool a): track(t), send(s), active(a){} +public: + int type() + { + return int(TRACK_SEND_ACTIVE); + } + uint32_t size() + { + return sizeof(EventTrackSendActive); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } + + int track; + SEND_TYPE send; + bool active; + + EventTrackSendActive() {}; + EventTrackSendActive(int t, SEND_TYPE s, bool a): track(t), send(s), active(a) {} }; class EventTrackJackSendActivate : public EventBase { - public: - int type() { return int(TRACK_JACKSEND_ACTIVATE); } - uint32_t size() { return sizeof(EventTrackJackSendActivate); } - static const char* prettyName; - const char* name(){ return prettyName; } +public: + int type() + { + return int(TRACK_JACKSEND_ACTIVATE); + } + uint32_t size() + { + return sizeof(EventTrackJackSendActivate); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } - int track; - bool active; + int track; + bool active; - EventTrackJackSendActivate(){}; - EventTrackJackSendActivate(int t, bool a): track(t), active(a){} + EventTrackJackSendActivate() {}; + EventTrackJackSendActivate(int t, bool a): track(t), active(a) {} }; class EventLooperState : public EventBase { - public: - int type() { return int(LOOPER_STATE); } - uint32_t size() { return sizeof(EventLooperState); } - - int track; - int scene; - //Looper::State state; - - EventLooperState(){} - //EventLooperState(int t, int sc, Looper::State s) : track(t), scene(sc), state(s){} +public: + int type() + { + return int(LOOPER_STATE); + } + uint32_t size() + { + return sizeof(EventLooperState); + } + + int track; + int scene; + //Looper::State state; + + EventLooperState() {} + //EventLooperState(int t, int sc, Looper::State s) : track(t), scene(sc), 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) {} +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: - int type() { return int(LOOPER_LOOP_LENGTH); } - uint32_t size() { return sizeof(EventLooperLoopLength); } - - int track; - int scene; - int beats; - EventLooperLoopLength(){} - EventLooperLoopLength(int t, int s, int b) : track(t), scene(s), beats(b) {} +public: + int type() + { + return int(LOOPER_LOOP_LENGTH); + } + uint32_t size() + { + return sizeof(EventLooperLoopLength); + } + + int track; + int scene; + int beats; + EventLooperLoopLength() {} + EventLooperLoopLength(int t, int s, int b) : track(t), scene(s), beats(b) {} }; class EventLooperUseAsTempo : public EventBase { - public: - int type() { return int(LOOPER_LOOP_USE_AS_TEMPO); } - uint32_t size() { return sizeof(EventLooperUseAsTempo); } - - int track; - int scene; - int beats; - EventLooperUseAsTempo(){} - EventLooperUseAsTempo(int t, int s) : track(t), scene(s){} +public: + int type() + { + return int(LOOPER_LOOP_USE_AS_TEMPO); + } + uint32_t size() + { + return sizeof(EventLooperUseAsTempo); + } + + int track; + int scene; + int beats; + EventLooperUseAsTempo() {} + EventLooperUseAsTempo(int t, int s) : track(t), scene(s) {} }; class EventLooperLoad : public EventBase { - public: - int type() { return int(LOOPER_LOAD); } - uint32_t size() { return sizeof(EventLooperLoad); } - - int track; - int clip; - void* audioBuffer; - - EventLooperLoad(){} - EventLooperLoad(int t, int c, void* ab) : track(t), clip(c), audioBuffer(ab) - { - } +public: + int type() + { + return int(LOOPER_LOAD); + } + uint32_t size() + { + return sizeof(EventLooperLoad); + } + + int track; + int clip; + void* audioBuffer; + + EventLooperLoad() {} + EventLooperLoad(int t, int c, void* ab) : track(t), clip(c), audioBuffer(ab) + { + } }; class EventMetronomeActive : public EventBase { - public: - int type() { return int(METRONOME_ACTIVE); } - uint32_t size() { return sizeof(EventMetronomeActive); } - static const char* prettyName; - const char* name(){ return prettyName; } - - bool active; - EventMetronomeActive(bool a = false) : active(a) {} +public: + int type() + { + return int(METRONOME_ACTIVE); + } + uint32_t size() + { + return sizeof(EventMetronomeActive); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } + + bool active; + EventMetronomeActive(bool a = false) : active(a) {} }; class EventMetronomeVolume : public EventBase { - public: - int type() { return int(METRONOME_VOLUME); } - uint32_t size() { return sizeof(EventMetronomeVolume); } - static const char* prettyName; - const char* name(){ return prettyName; } - - float vol; - EventMetronomeVolume(float v = 0.f) : vol(v){} +public: + int type() + { + return int(METRONOME_VOLUME); + } + uint32_t size() + { + return sizeof(EventMetronomeVolume); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } + + float vol; + EventMetronomeVolume(float v = 0.f) : vol(v) {} }; class EventTimeBPM : public EventBase { - public: - int type() { return int(TIME_BPM); } - uint32_t size() { return sizeof(EventTimeBPM); } - static const char* prettyName; - const char* name(){ return prettyName; } - - float bpm; - - EventTimeBPM(){} - EventTimeBPM(float b) : bpm(b) {} +public: + int type() + { + return int(TIME_BPM); + } + uint32_t size() + { + return sizeof(EventTimeBPM); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } + + float bpm; + + EventTimeBPM() {} + EventTimeBPM(float b) : bpm(b) {} }; class EventTrackSignalLevel : public EventBase { - public: - int type() { return int(TRACK_SIGNAL_LEVEL); } - uint32_t size() { return sizeof(EventTrackSignalLevel); } - - int track; - float left; - float right; - - EventTrackSignalLevel(){} - EventTrackSignalLevel(int t, float l,float r) : track(t), left(l), right(r) {} +public: + int type() + { + return int(TRACK_SIGNAL_LEVEL); + } + uint32_t size() + { + return sizeof(EventTrackSignalLevel); + } + + int track; + float left; + float right; + + EventTrackSignalLevel() {} + EventTrackSignalLevel(int t, float l,float r) : track(t), left(l), right(r) {} }; class EventTimeTempoTap : public EventBase { - public: - int type() { return int(TIME_TEMPO_TAP); } - uint32_t size() { return sizeof(EventTimeTempoTap); } - static const char* prettyName; - const char* name(){ return prettyName; } - - bool pressed; // only used to turn on / off the button in GUI - EventTimeTempoTap():pressed(false){} - EventTimeTempoTap(bool p): pressed(p) {} +public: + int type() + { + return int(TIME_TEMPO_TAP); + } + uint32_t size() + { + return sizeof(EventTimeTempoTap); + } + static const char* prettyName; + const char* name() + { + return prettyName; + } + + bool pressed; // only used to turn on / off the button in GUI + EventTimeTempoTap():pressed(false) {} + EventTimeTempoTap(bool p): pressed(p) {} }; class EventTimeBarBeat : public EventBase { - public: - int type() { return int(TIME_BAR_BEAT); } - uint32_t size() { return sizeof(EventTimeBarBeat); } - - int bar; - int beat; - EventTimeBarBeat(): bar(0), beat(0){} - EventTimeBarBeat(int ba, int be): bar(ba), beat(be) {} +public: + int type() + { + return int(TIME_BAR_BEAT); + } + uint32_t size() + { + return sizeof(EventTimeBarBeat); + } + + int bar; + int beat; + EventTimeBarBeat(): bar(0), beat(0) {} + EventTimeBarBeat(int ba, int be): bar(ba), beat(be) {} }; class EventLooperClipRequestBuffer : public EventBase { - public: - int type() { return int(LOOPER_REQUEST_BUFFER); } - uint32_t size() { return sizeof(EventLooperClipRequestBuffer); } - - int track; - int scene; - - // number of floats to contain - unsigned long numElements; - - // pointer to the new AudioBuffer being passed back - AudioBuffer* ab; - - EventLooperClipRequestBuffer(): track(0), scene(0), numElements(0), ab(0) {} - EventLooperClipRequestBuffer(int t, int s, int siz): track(t), scene(s), numElements(siz), ab(0) {} - EventLooperClipRequestBuffer(int t, int s, AudioBuffer* a): track(t), scene(s), numElements(0), ab(a) {} +public: + int type() + { + return int(LOOPER_REQUEST_BUFFER); + } + uint32_t size() + { + return sizeof(EventLooperClipRequestBuffer); + } + + int track; + int scene; + + // number of floats to contain + unsigned long numElements; + + // pointer to the new AudioBuffer being passed back + AudioBuffer* ab; + + EventLooperClipRequestBuffer(): track(0), scene(0), numElements(0), ab(0) {} + EventLooperClipRequestBuffer(int t, int s, int siz): track(t), scene(s), numElements(siz), ab(0) {} + EventLooperClipRequestBuffer(int t, int s, AudioBuffer* a): track(t), scene(s), numElements(0), ab(a) {} }; class EventStateSaveBuffer : public EventBase { - public: - int type() { return int(STATE_SAVE_BUFFER); } - uint32_t size() { return sizeof(EventStateSaveBuffer); } - - int track; - int scene; - // pointer to the AudioBuffer to be saved - AudioBuffer* ab; - bool no_dealloc; - - EventStateSaveBuffer(): track(0), scene(0), ab(0), no_dealloc(0) {} - EventStateSaveBuffer(int t, int s, AudioBuffer* a): track(t), scene(s), ab(a) {} +public: + int type() + { + return int(STATE_SAVE_BUFFER); + } + uint32_t size() + { + return sizeof(EventStateSaveBuffer); + } + + int track; + int scene; + // pointer to the AudioBuffer to be saved + AudioBuffer* ab; + bool no_dealloc; + + EventStateSaveBuffer(): track(0), scene(0), ab(0), no_dealloc(0) {} + EventStateSaveBuffer(int t, int s, AudioBuffer* a): track(t), scene(s), ab(a) {} }; class EventRequestSaveBuffer : public EventBase { - public: - int type() { return int(REQUEST_SAVE_BUFFER); } - uint32_t size() { return sizeof(EventRequestSaveBuffer); } - - int track; - int scene; - - size_t bufferSize; - - // pointer to the AudioBuffer to be saved - AudioBuffer* ab; - - EventRequestSaveBuffer(): track(0), scene(0), ab(0) {} - EventRequestSaveBuffer(int t, int s, size_t si): track(t), scene(s), bufferSize(si), ab(0) {} - EventRequestSaveBuffer(int t, int s, AudioBuffer* a): track(t), scene(s), ab(a) {} +public: + int type() + { + return int(REQUEST_SAVE_BUFFER); + } + uint32_t size() + { + return sizeof(EventRequestSaveBuffer); + } + + int track; + int scene; + + size_t bufferSize; + + // pointer to the AudioBuffer to be saved + AudioBuffer* ab; + + EventRequestSaveBuffer(): track(0), scene(0), ab(0) {} + EventRequestSaveBuffer(int t, int s, size_t si): track(t), scene(s), bufferSize(si), ab(0) {} + EventRequestSaveBuffer(int t, int s, AudioBuffer* a): track(t), scene(s), ab(a) {} }; class EventDeallocateBuffer : public EventBase { - public: - int type() { return int(DEALLOCATE_BUFFER); } - uint32_t size() { return sizeof(EventDeallocateBuffer); } - - AudioBuffer* ab; - - EventDeallocateBuffer(): ab(0) {} - EventDeallocateBuffer(AudioBuffer* a): ab(a) {} +public: + int type() + { + return int(DEALLOCATE_BUFFER); + } + uint32_t size() + { + return sizeof(EventDeallocateBuffer); + } + + AudioBuffer* ab; + + EventDeallocateBuffer(): ab(0) {} + EventDeallocateBuffer(AudioBuffer* a): ab(a) {} }; // prints the string S in the GUI console class EventGuiPrint : public EventBase { - public: - int type() { return int(GUI_PRINT); } - uint32_t size() { return sizeof(EventGuiPrint); } - - char stringArray[50]; - - EventGuiPrint(){} - EventGuiPrint(const char* s) - { - if ( strlen( s ) > 49 ) - { - // this will be called from an RT context, and should be removed from - // production code. It is here for the programmer to notice when they - // are using code which causes too long a message. - cout << "EventGuiPrint() error! Size of string too long!" << endl; - } - else - { - // move the sting into this event - strcpy( &stringArray[0], s ); - } - } - char* getMessage() - { - return &stringArray[0]; - } +public: + int type() + { + return int(GUI_PRINT); + } + uint32_t size() + { + return sizeof(EventGuiPrint); + } + + char stringArray[50]; + + EventGuiPrint() {} + EventGuiPrint(const char* s) + { + if ( strlen( s ) > 49 ) { + // this will be called from an RT context, and should be removed from + // production code. It is here for the programmer to notice when they + // are using code which causes too long a message. + cout << "EventGuiPrint() error! Size of string too long!" << endl; + } else { + // move the sting into this event + strcpy( &stringArray[0], s ); + } + } + char* getMessage() + { + return &stringArray[0]; + } }; class EventControllerBindingTarget : public EventBase { - public: - int type() { return int(CONTROLLER_BINDING_TARGET); } - uint32_t size() { return sizeof(EventControllerBindingTarget); } - char target[50]; - - EventControllerBindingTarget(){} - EventControllerBindingTarget(const char* s) - { - if ( strlen( s ) > 49 ) - { - // this will be called from an RT context, and should be removed from - // production code. It is here for the programmer to notice when they - // are using code which causes too long a message. - cout << "EventControllerBindingTarget() error! Size of string too long!" << endl; - } - else - { - // move the sting into this event - strcpy( &target[0], s ); - } - } - char* getMessage() - { - return &target[0]; - } +public: + int type() + { + return int(CONTROLLER_BINDING_TARGET); + } + uint32_t size() + { + return sizeof(EventControllerBindingTarget); + } + char target[50]; + + EventControllerBindingTarget() {} + EventControllerBindingTarget(const char* s) + { + if ( strlen( s ) > 49 ) { + // this will be called from an RT context, and should be removed from + // production code. It is here for the programmer to notice when they + // are using code which causes too long a message. + cout << "EventControllerBindingTarget() error! Size of string too long!" << endl; + } else { + // move the sting into this event + strcpy( &target[0], s ); + } + } + char* getMessage() + { + return &target[0]; + } }; diff --git a/src/eventhandler.hxx b/src/eventhandler.hxx index e35d9aa..d8e9a58 100644 --- a/src/eventhandler.hxx +++ b/src/eventhandler.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ diff --git a/src/eventhandlerdsp.cxx b/src/eventhandlerdsp.cxx index 9a165b0..a53986f 100644 --- a/src/eventhandlerdsp.cxx +++ b/src/eventhandlerdsp.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -44,394 +44,447 @@ extern Jack* jack; void handleDspEvents() { - uint availableRead = jack_ringbuffer_read_space( rbToDsp ); - - while ( availableRead >= sizeof(EventBase) ) - { - jack_ringbuffer_peek( rbToDsp, (char*)processDspMem, sizeof(EventBase) ); - - EventBase* e = (EventBase*)processDspMem; - - // recheck the size against the actual event size - if ( availableRead >= e->size() ) - { - - // MIDI binding creation: sample the Event. - if( jack->bindingEventRecordEnable ) - { - //printf("event %i\n", e->type() ); - jack->bindingEventType = e->type(); - - const char* target = e->name(); - if ( target ) - { - EventControllerBindingTarget event( target ); - writeToGuiRingbuffer( &event ); - } - } - - switch ( e->type() ) - { - case Event::QUIT: { - if ( availableRead >= sizeof(EventQuit) ) { - EventQuit ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventQuit) ); - jack->quit(); - // we want to *quit* *fast*: remaining events don't matter! - return; - - } break; } - - - // ======== TRANSPORT == - case Event::TRANSPORT: { - if ( availableRead >= sizeof(EventTransportState) ) { - EventTransportState ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTransportState) ); - jack->getTimeManager()->setTransportState( ev.ts ); - } break; } - - // ========= SAVE ===== - case Event::STATE_SAVE: { - if ( availableRead >= sizeof(EventStateSave) ) { - EventStateSave ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventStateSave) ); - jack->getState()->save(); - } break; } - case Event::STATE_RESET: { - if ( availableRead >= sizeof(EventStateReset) ) { - EventStateReset ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventStateReset) ); - jack->getState()->reset(); - } break; } - case Event::STATE_SAVE_BUFFER: { - if ( availableRead >= sizeof(EventStateReset) ) { - EventStateSaveBuffer ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventStateSaveBuffer) ); - printf("jack got save buffer in %d, %d\n", ev.track, ev.scene); - LooperClip* lc = jack->getLooper(ev.track)->getClip(ev.scene); - if(!lc) break; - EventStateSaveBuffer e; - e.track = ev.track; - e.scene = ev.scene; - e.ab = lc->getAudioBuffer(); - e.no_dealloc = 1; - writeToGuiRingbuffer( &e ); - } break; } - - // ========= MASTER === - case Event::MASTER_VOL: { - if ( availableRead >= sizeof(EventMasterVol) ) { - EventMasterVol ev(0); - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterVol) ); - jack->masterVolume( ev.vol ); - } break; } - case Event::MASTER_RETURN: { - if ( availableRead >= sizeof(EventMasterReturn) ) { - EventMasterReturn ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterReturn) ); - if ( ev.ret == RETURN_MAIN ) { - jack->returnVolume( ev.vol ); - } - } break; } - case Event::MASTER_INPUT_VOL: { - if ( availableRead >= sizeof(EventMasterVol) ) { - EventMasterVol ev(0); - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterVol) ); - jack->getLogic()->masterInputVol( ev.vol ); - } break; } - case Event::MASTER_INPUT_TO: { - if ( availableRead >= sizeof(EventMasterInputTo) ) { - EventMasterInputTo ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterInputTo) ); - jack->bindingSend = ev.place; - jack->getLogic()->masterInputTo( ev.place, ev.value ); - } break; } - case Event::MASTER_INPUT_TO_ACTIVE: { - if ( availableRead >= sizeof(EventMasterInputToActive) ) { - EventMasterInputToActive ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterInputToActive) ); - jack->bindingSend = ev.place; - jack->bindingActive = ev.active; - jack->getLogic()->masterInputToActive( ev.place, ev.active ); - } break; } - - // ========= GRID ===== - case Event::GRID_STATE: { - if ( availableRead >= sizeof(EventGridState) ) { - EventGridState ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridState) ); - // clear clips in Controllers - if ( ev.state == GridLogic::STATE_EMPTY ) - { - jack->getLooper( ev.track )->getClip( ev.scene )->init(); - jack->getControllerUpdater()->setTrackSceneProgress(ev.track, ev.scene, 0 ); - jack->getControllerUpdater()->setSceneState( ev.track, ev.scene, GridLogic::STATE_EMPTY ); - } - } break; } - - case Event::GRID_EVENT: { - if ( availableRead >= sizeof(EventGridEvent) ) { - EventGridEvent ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridEvent) ); - jack->bindingTrack = ev.track; - jack->bindingScene = ev.scene; - if ( ev.pressed ) - jack->getGridLogic()->pressed( ev.track, ev.scene ); - else - jack->getGridLogic()->released( ev.track, ev.scene ); - } break; } - - case Event::GRID_LAUNCH_SCENE: { - EventGridLaunchScene ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridLaunchScene) ); - jack->getGridLogic()->launchScene( ev.scene ); - jack->bindingScene = ev.scene; - break; } - - case Event::GRID_SELECT_CLIP_ENABLE: { - EventGridSelectClipEnable ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridSelectClipEnable) ); - jack->getGridLogic()->setSelectTrackScene( ev.enable ); - break; } - case Event::GRID_SELECT_CLIP_EVENT: { - EventGridSelectClipEvent ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridSelectClipEvent) ); - jack->getGridLogic()->selectedTrackSceneEvent( ev.pressed ); - break; } - - case Event::GRID_SELECT_NEW_CHOSEN: { - EventGridSelectNewChosen ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridSelectNewChosen) ); - jack->getGridLogic()->specialScene( ev.track, ev.scene ); - break; } - - - case Event::LOOPER_LOAD: { - if ( availableRead >= sizeof(EventLooperLoad) ) { - EventLooperLoad ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperLoad) ); - jack->getGridLogic()->load( ev.track, ev.clip, (AudioBuffer*)ev.audioBuffer ); - } break; } - case Event::METRONOME_ACTIVE: { - if ( availableRead >= sizeof(EventMetronomeActive) ) { - EventMetronomeActive ev(false); - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMetronomeActive) ); - jack->getLogic()->metronomeEnable(ev.active); - } break; } - case Event::METRONOME_VOLUME: { - if ( availableRead >= sizeof(EventMetronomeVolume) ) { - EventMetronomeVolume ev(false); - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMetronomeVolume) ); - LUPPP_NOTE("EventDSP: MetroVol %f", ev.vol ); - jack->getMetronome()->setVolume(ev.vol); - } break; } - case Event::LOOPER_STATE: { - if ( availableRead >= sizeof(EventLooperState) ) { - EventLooperState ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperState) ); - //jack->setLooperState( ev.track, ev.scene, ev.state ); - } break; } - case Event::LOOPER_LOOP_LENGTH: { - if ( availableRead >= sizeof(EventLooperLoopLength) ) { - EventLooperLoopLength ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperLoopLength) ); - jack->getLogic()->looperClipLenght( ev.track, ev.scene, ev.beats ); - } break; } - - - case Event::LOOPER_LOOP_USE_AS_TEMPO: { - if ( availableRead >= sizeof(EventLooperUseAsTempo) ) { - EventLooperUseAsTempo ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperUseAsTempo) ); - jack->getLogic()->looperUseAsTempo( ev.track, ev.scene ); - } break; } - - - - case Event::TIME_BPM: { - if ( availableRead >= sizeof(EventTimeBPM) ) { - EventTimeBPM ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTimeBPM) ); - jack->getTimeManager()->setBpm(ev.bpm); - } break; } - case Event::TIME_TEMPO_TAP: { - if ( availableRead >= sizeof(EventTimeTempoTap) ) { - EventTimeTempoTap ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTimeTempoTap) ); - jack->getTimeManager()->tap(); - } break; } - - // ======== FX =========== - - case Event::FX_REVERB: break; - /*{ - if ( availableRead >= sizeof(EventFxReverb) ) { - EventFxReverb ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventFxReverb) ); - // TODO implement reverb - break; } - } - */ - case Event::TRACK_VOLUME: { - if ( availableRead >= sizeof(EventTrackVol) ) { - EventTrackVol ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackVol) ); - jack->getLogic()->trackVolume( ev.track, ev.vol ); - jack->bindingTrack = ev.track; - break; } - } - - case Event::TRACK_RECORD_ARM: { - if ( availableRead >= sizeof(EventTrackRecordArm) ) { - EventTrackRecordArm ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackRecordArm) ); - jack->getLogic()->trackRecordArm( ev.track, ev.recordArm ); - jack->bindingTrack = ev.track; - jack->bindingActive = ev.recordArm; - break; } - } - - case Event::TRACK_SEND_ACTIVE: { - if ( availableRead >= sizeof(EventTrackSendActive) ) { - EventTrackSendActive ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackSendActive) ); - jack->getLogic()->trackSendActive( ev.track, ev.send, ev.active ); - jack->bindingTrack = ev.track; - jack->bindingSend = ev.send; - jack->bindingActive = ev.active; - } break; } + uint availableRead = jack_ringbuffer_read_space( rbToDsp ); - case Event::TRACK_JACKSEND_ACTIVATE: { - if ( availableRead >= sizeof(EventTrackJackSendActivate) ) { - EventTrackJackSendActivate ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackJackSendActivate) ); - jack->getLogic()->trackJackSendActivate(ev.track,ev.active); - jack->bindingTrack = ev.track; + while ( availableRead >= sizeof(EventBase) ) { + jack_ringbuffer_peek( rbToDsp, (char*)processDspMem, sizeof(EventBase) ); - jack->bindingActive = ev.active; - } break; } + EventBase* e = (EventBase*)processDspMem; - case Event::TRACK_JACKSEND: { - if ( availableRead >= sizeof(EventTrackJackSend) ) { - EventTrackJackSend ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackJackSend) ); - jack->getLogic()->trackJackSend(ev.track,ev.value); - jack->bindingTrack = ev.track; - } break; } - - case Event::TRACK_SEND: { - if ( availableRead >= sizeof(EventTrackSend) ) { - EventTrackSend ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackSend) ); - jack->getLogic()->trackSend( ev.track, ev.send, ev.value ); - jack->bindingTrack = ev.track; - jack->bindingSend = ev.send; - } break; } - - - // ========= LUPPP INTERNAL ===== - case Event::LOOPER_REQUEST_BUFFER: { - if ( availableRead >= sizeof(EventLooperClipRequestBuffer) ) { - EventLooperClipRequestBuffer ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperClipRequestBuffer) ); - jack->getLooper( ev.track )->setRequestedBuffer( ev.scene, ev.ab ); - } break; } - - case Event::REQUEST_SAVE_BUFFER: { - if ( availableRead >= sizeof(EventRequestSaveBuffer) ) { - EventRequestSaveBuffer ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventRequestSaveBuffer) ); - jack->getLooper( ev.track )->getClip(ev.scene)->recieveSaveBuffer( ev.ab ); - } break; } - - case Event::CONTROLLER_INSTANCE: { - if ( availableRead >= sizeof(EventControllerInstance) ) { - EventControllerInstance ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerInstance) ); - jack->getControllerUpdater()->registerController( static_cast(ev.controller) ); - } break; } - - case Event::CONTROLLER_INSTANCE_REMOVE: { - if ( availableRead >= sizeof(EventControllerInstanceRemove) ) { - EventControllerInstanceRemove ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerInstanceRemove) ); - - jack->getControllerUpdater()->removeController( ev.ID ); - } break; } - - case Event::CONTROLLER_BINDING_ENABLE: { - if ( availableRead >= sizeof(EventControllerBindingEnable) ) { - EventControllerBindingEnable ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerBindingEnable) ); - jack->bindingEventRecordEnable = ev.enable; - } break; } - - - case Event::CONTROLLER_BINDING_REMOVE: { - if ( availableRead >= sizeof(EventControllerBindingRemove) ) { - EventControllerBindingRemove ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerBindingRemove) ); - // get Controller* from controllerID - Controller* c =jack->getControllerUpdater()->getController(ev.controllerID); - // dynamic cast to check for GenericMIDI controller - GenericMIDI* g = dynamic_cast(c); - if ( g ) - { - // kick out BindingID - g->removeBinding( ev.bindingID ); - } - else - { - // GUI print notify of error removing binding - } - } break; } - - case Event::CONTROLLER_INSTANCE_GET_TO_WRITE: { - if ( availableRead >= sizeof(EventControllerInstanceGetToWrite) ) { - EventControllerInstanceGetToWrite ev; - jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerInstanceGetToWrite) ); - - // get the corresponding Controller with ID, and return it - - Controller* c = jack->getControllerUpdater()->getController( ev.ID ); - - cout << "controller instance get to write id " << ev.ID << endl; - - EventControllerInstanceGetToWrite tmp( ev.ID, c ); - writeToGuiRingbuffer( &tmp ); - } break; } - - default: - { - cout << "DSP: 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( rbToDsp ); - } + // recheck the size against the actual event size + if ( availableRead >= e->size() ) { + + // MIDI binding creation: sample the Event. + if( jack->bindingEventRecordEnable ) { + //printf("event %i\n", e->type() ); + jack->bindingEventType = e->type(); + + const char* target = e->name(); + if ( target ) { + EventControllerBindingTarget event( target ); + writeToGuiRingbuffer( &event ); + } + } + + switch ( e->type() ) { + case Event::QUIT: { + if ( availableRead >= sizeof(EventQuit) ) { + EventQuit ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventQuit) ); + jack->quit(); + // we want to *quit* *fast*: remaining events don't matter! + return; + + } + break; + } + + + // ======== TRANSPORT == + case Event::TRANSPORT: { + if ( availableRead >= sizeof(EventTransportState) ) { + EventTransportState ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTransportState) ); + jack->getTimeManager()->setTransportState( ev.ts ); + } + break; + } + + // ========= SAVE ===== + case Event::STATE_SAVE: { + if ( availableRead >= sizeof(EventStateSave) ) { + EventStateSave ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventStateSave) ); + jack->getState()->save(); + } + break; + } + case Event::STATE_RESET: { + if ( availableRead >= sizeof(EventStateReset) ) { + EventStateReset ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventStateReset) ); + jack->getState()->reset(); + } + break; + } + case Event::STATE_SAVE_BUFFER: { + if ( availableRead >= sizeof(EventStateReset) ) { + EventStateSaveBuffer ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventStateSaveBuffer) ); + printf("jack got save buffer in %d, %d\n", ev.track, ev.scene); + LooperClip* lc = jack->getLooper(ev.track)->getClip(ev.scene); + if(!lc) break; + EventStateSaveBuffer e; + e.track = ev.track; + e.scene = ev.scene; + e.ab = lc->getAudioBuffer(); + e.no_dealloc = 1; + writeToGuiRingbuffer( &e ); + } + break; + } + + // ========= MASTER === + case Event::MASTER_VOL: { + if ( availableRead >= sizeof(EventMasterVol) ) { + EventMasterVol ev(0); + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterVol) ); + jack->masterVolume( ev.vol ); + } + break; + } + case Event::MASTER_RETURN: { + if ( availableRead >= sizeof(EventMasterReturn) ) { + EventMasterReturn ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterReturn) ); + if ( ev.ret == RETURN_MAIN ) { + jack->returnVolume( ev.vol ); + } + } + break; + } + case Event::MASTER_INPUT_VOL: { + if ( availableRead >= sizeof(EventMasterVol) ) { + EventMasterVol ev(0); + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterVol) ); + jack->getLogic()->masterInputVol( ev.vol ); + } + break; + } + case Event::MASTER_INPUT_TO: { + if ( availableRead >= sizeof(EventMasterInputTo) ) { + EventMasterInputTo ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterInputTo) ); + jack->bindingSend = ev.place; + jack->getLogic()->masterInputTo( ev.place, ev.value ); + } + break; + } + case Event::MASTER_INPUT_TO_ACTIVE: { + if ( availableRead >= sizeof(EventMasterInputToActive) ) { + EventMasterInputToActive ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterInputToActive) ); + jack->bindingSend = ev.place; + jack->bindingActive = ev.active; + jack->getLogic()->masterInputToActive( ev.place, ev.active ); + } + break; + } + + // ========= GRID ===== + case Event::GRID_STATE: { + if ( availableRead >= sizeof(EventGridState) ) { + EventGridState ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridState) ); + // clear clips in Controllers + if ( ev.state == GridLogic::STATE_EMPTY ) { + jack->getLooper( ev.track )->getClip( ev.scene )->init(); + jack->getControllerUpdater()->setTrackSceneProgress(ev.track, ev.scene, 0 ); + jack->getControllerUpdater()->setSceneState( ev.track, ev.scene, GridLogic::STATE_EMPTY ); + } + } + break; + } + + case Event::GRID_EVENT: { + if ( availableRead >= sizeof(EventGridEvent) ) { + EventGridEvent ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridEvent) ); + jack->bindingTrack = ev.track; + jack->bindingScene = ev.scene; + if ( ev.pressed ) + jack->getGridLogic()->pressed( ev.track, ev.scene ); + else + jack->getGridLogic()->released( ev.track, ev.scene ); + } + break; + } + + case Event::GRID_LAUNCH_SCENE: { + EventGridLaunchScene ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridLaunchScene) ); + jack->getGridLogic()->launchScene( ev.scene ); + jack->bindingScene = ev.scene; + break; + } + + case Event::GRID_SELECT_CLIP_ENABLE: { + EventGridSelectClipEnable ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridSelectClipEnable) ); + jack->getGridLogic()->setSelectTrackScene( ev.enable ); + break; + } + case Event::GRID_SELECT_CLIP_EVENT: { + EventGridSelectClipEvent ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridSelectClipEvent) ); + jack->getGridLogic()->selectedTrackSceneEvent( ev.pressed ); + break; + } + + case Event::GRID_SELECT_NEW_CHOSEN: { + EventGridSelectNewChosen ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventGridSelectNewChosen) ); + jack->getGridLogic()->specialScene( ev.track, ev.scene ); + break; + } + + + case Event::LOOPER_LOAD: { + if ( availableRead >= sizeof(EventLooperLoad) ) { + EventLooperLoad ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperLoad) ); + jack->getGridLogic()->load( ev.track, ev.clip, (AudioBuffer*)ev.audioBuffer ); + } + break; + } + case Event::METRONOME_ACTIVE: { + if ( availableRead >= sizeof(EventMetronomeActive) ) { + EventMetronomeActive ev(false); + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMetronomeActive) ); + jack->getLogic()->metronomeEnable(ev.active); + } + break; + } + case Event::METRONOME_VOLUME: { + if ( availableRead >= sizeof(EventMetronomeVolume) ) { + EventMetronomeVolume ev(false); + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMetronomeVolume) ); + LUPPP_NOTE("EventDSP: MetroVol %f", ev.vol ); + jack->getMetronome()->setVolume(ev.vol); + } + break; + } + case Event::LOOPER_STATE: { + if ( availableRead >= sizeof(EventLooperState) ) { + EventLooperState ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperState) ); + //jack->setLooperState( ev.track, ev.scene, ev.state ); + } + break; + } + case Event::LOOPER_LOOP_LENGTH: { + if ( availableRead >= sizeof(EventLooperLoopLength) ) { + EventLooperLoopLength ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperLoopLength) ); + jack->getLogic()->looperClipLenght( ev.track, ev.scene, ev.beats ); + } + break; + } + + + case Event::LOOPER_LOOP_USE_AS_TEMPO: { + if ( availableRead >= sizeof(EventLooperUseAsTempo) ) { + EventLooperUseAsTempo ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperUseAsTempo) ); + jack->getLogic()->looperUseAsTempo( ev.track, ev.scene ); + } + break; + } + + + + case Event::TIME_BPM: { + if ( availableRead >= sizeof(EventTimeBPM) ) { + EventTimeBPM ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTimeBPM) ); + jack->getTimeManager()->setBpm(ev.bpm); + } + break; + } + case Event::TIME_TEMPO_TAP: { + if ( availableRead >= sizeof(EventTimeTempoTap) ) { + EventTimeTempoTap ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTimeTempoTap) ); + jack->getTimeManager()->tap(); + } + break; + } + + // ======== FX =========== + + case Event::FX_REVERB: + break; + /*{ + if ( availableRead >= sizeof(EventFxReverb) ) { + EventFxReverb ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventFxReverb) ); + // TODO implement reverb + break; } + } + */ + case Event::TRACK_VOLUME: { + if ( availableRead >= sizeof(EventTrackVol) ) { + EventTrackVol ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackVol) ); + jack->getLogic()->trackVolume( ev.track, ev.vol ); + jack->bindingTrack = ev.track; + break; + } + } + + case Event::TRACK_RECORD_ARM: { + if ( availableRead >= sizeof(EventTrackRecordArm) ) { + EventTrackRecordArm ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackRecordArm) ); + jack->getLogic()->trackRecordArm( ev.track, ev.recordArm ); + jack->bindingTrack = ev.track; + jack->bindingActive = ev.recordArm; + break; + } + } + + case Event::TRACK_SEND_ACTIVE: { + if ( availableRead >= sizeof(EventTrackSendActive) ) { + EventTrackSendActive ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackSendActive) ); + jack->getLogic()->trackSendActive( ev.track, ev.send, ev.active ); + jack->bindingTrack = ev.track; + jack->bindingSend = ev.send; + jack->bindingActive = ev.active; + } + break; + } + + case Event::TRACK_JACKSEND_ACTIVATE: { + if ( availableRead >= sizeof(EventTrackJackSendActivate) ) { + EventTrackJackSendActivate ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackJackSendActivate) ); + jack->getLogic()->trackJackSendActivate(ev.track,ev.active); + jack->bindingTrack = ev.track; + + jack->bindingActive = ev.active; + } + break; + } + + case Event::TRACK_JACKSEND: { + if ( availableRead >= sizeof(EventTrackJackSend) ) { + EventTrackJackSend ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackJackSend) ); + jack->getLogic()->trackJackSend(ev.track,ev.value); + jack->bindingTrack = ev.track; + } + break; + } + + case Event::TRACK_SEND: { + if ( availableRead >= sizeof(EventTrackSend) ) { + EventTrackSend ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackSend) ); + jack->getLogic()->trackSend( ev.track, ev.send, ev.value ); + jack->bindingTrack = ev.track; + jack->bindingSend = ev.send; + } + break; + } + + + // ========= LUPPP INTERNAL ===== + case Event::LOOPER_REQUEST_BUFFER: { + if ( availableRead >= sizeof(EventLooperClipRequestBuffer) ) { + EventLooperClipRequestBuffer ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperClipRequestBuffer) ); + jack->getLooper( ev.track )->setRequestedBuffer( ev.scene, ev.ab ); + } + break; + } + + case Event::REQUEST_SAVE_BUFFER: { + if ( availableRead >= sizeof(EventRequestSaveBuffer) ) { + EventRequestSaveBuffer ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventRequestSaveBuffer) ); + jack->getLooper( ev.track )->getClip(ev.scene)->recieveSaveBuffer( ev.ab ); + } + break; + } + + case Event::CONTROLLER_INSTANCE: { + if ( availableRead >= sizeof(EventControllerInstance) ) { + EventControllerInstance ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerInstance) ); + jack->getControllerUpdater()->registerController( static_cast(ev.controller) ); + } + break; + } + + case Event::CONTROLLER_INSTANCE_REMOVE: { + if ( availableRead >= sizeof(EventControllerInstanceRemove) ) { + EventControllerInstanceRemove ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerInstanceRemove) ); + + jack->getControllerUpdater()->removeController( ev.ID ); + } + break; + } + + case Event::CONTROLLER_BINDING_ENABLE: { + if ( availableRead >= sizeof(EventControllerBindingEnable) ) { + EventControllerBindingEnable ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerBindingEnable) ); + jack->bindingEventRecordEnable = ev.enable; + } + break; + } + + + case Event::CONTROLLER_BINDING_REMOVE: { + if ( availableRead >= sizeof(EventControllerBindingRemove) ) { + EventControllerBindingRemove ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerBindingRemove) ); + // get Controller* from controllerID + Controller* c =jack->getControllerUpdater()->getController(ev.controllerID); + // dynamic cast to check for GenericMIDI controller + GenericMIDI* g = dynamic_cast(c); + if ( g ) { + // kick out BindingID + g->removeBinding( ev.bindingID ); + } else { + // GUI print notify of error removing binding + } + } break; + } + + case Event::CONTROLLER_INSTANCE_GET_TO_WRITE: { + if ( availableRead >= sizeof(EventControllerInstanceGetToWrite) ) { + EventControllerInstanceGetToWrite ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventControllerInstanceGetToWrite) ); + + // get the corresponding Controller with ID, and return it + + Controller* c = jack->getControllerUpdater()->getController( ev.ID ); + + cout << "controller instance get to write id " << ev.ID << endl; + + EventControllerInstanceGetToWrite tmp( ev.ID, c ); + writeToGuiRingbuffer( &tmp ); + } + break; + } + + default: { + cout << "DSP: 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( rbToDsp ); + } } void writeToDspRingbuffer(EventBase* e) { - if ( jack_ringbuffer_write_space(rbToDsp) >= e->size() ) - { - jack_ringbuffer_write( rbToDsp, (const char*)e, e->size() ); - } - else - { - // non-RT context, printing is OK! - cout << "->DSP ringbuffer full!" << endl; - } + if ( jack_ringbuffer_write_space(rbToDsp) >= e->size() ) { + jack_ringbuffer_write( rbToDsp, (const char*)e, e->size() ); + } else { + // non-RT context, printing is OK! + cout << "->DSP ringbuffer full!" << endl; + } } #endif // LUPPP_EVENT_HANDLER_DSP_H diff --git a/src/eventhandlergui.cxx b/src/eventhandlergui.cxx index 467cd7b..b8b78fb 100644 --- a/src/eventhandlergui.cxx +++ b/src/eventhandlergui.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -41,395 +41,445 @@ 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::QUIT: { - if ( availableRead >= sizeof(EventQuit) ) { - EventQuit ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventQuit) ); - LUPPP_NOTE("%s","GUI QUIT"); - gui->quit(); - } break; } - - case Event::SAMPLERATE: { - if ( availableRead >= sizeof(EventSamplerate) ) { - EventSamplerate ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventSamplerate) ); - gui->samplerate = ev.samplerate; - //LUPPP_NOTE("Gui Samplerate: %i", gui->samplerate); - } break; } - - /// master - case Event::MASTER_INPUT_TO: { - if ( availableRead >= sizeof(EventMasterInputTo) ) { - EventMasterInputTo ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterInputTo) ); - gui->getMasterTrack()->setInputTo( (int)ev.place, ev.value ); - } break; } - case Event::MASTER_INPUT_TO_ACTIVE: { - if ( availableRead >= sizeof(EventMasterInputToActive) ) { - EventMasterInputToActive ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterInputToActive) ); - gui->getMasterTrack()->setInputToActive( (int)ev.place, ev.active ); - } break; } - case Event::MASTER_INPUT_VOL: { - if ( availableRead >= sizeof(EventMasterInputVol) ) { - EventMasterInputVol ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterInputVol) ); - gui->getMasterTrack()->setInputVol( ev.vol ); - } break; } - case Event::MASTER_RETURN: { - if ( availableRead >= sizeof(EventMasterReturn) ) { - EventMasterReturn ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterReturn) ); - gui->getMasterTrack()->setReturnVol( ev.vol ); - } break; } - case Event::MASTER_VOL: { - if ( availableRead >= sizeof(EventMasterVol) ) { - EventMasterVol ev(0); - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterVol) ); - gui->getMasterTrack()->getVolume()->fader( ev.vol ); - } break; } - - - case Event::METRONOME_ACTIVE: { - if ( availableRead >= sizeof(EventMetronomeActive) ) { - EventMetronomeActive ev(false); - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMetronomeActive) ); - gui->getMasterTrack()->metronomeEnable(ev.active); - } break; } - case Event::LOOPER_STATE: { - if ( availableRead >= sizeof(EventLooperState) ) { - EventLooperState ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperState) ); - //gui->getTrack(ev.track)->getClipSelector()->setState(ev.scene, ev.state); - //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) ); - - // only update if significant change - //if ( ev.progress - gui->getTrack(ev.track)->radial.value() >= 0.05 || - // ev.progress > 0.9 ) - gui->getTrack(ev.track)->radial.value(ev.progress); - - } break; } - - - // FIXME: reset signal level to 0 - case Event::TRACK_SIGNAL_LEVEL: { - if ( availableRead >= sizeof(EventTrackSignalLevel) ) { - EventTrackSignalLevel ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackSignalLevel) ); - if ( ev.track == -2 ) { - gui->getMasterTrack()->getInputVolume()->amplitude( ev.left, ev.right ); - } else if ( ev.track == -1 ) { - gui->getMasterTrack()->getVolume()->amplitude( ev.left, ev.right ); - } else { - gui->getTrack(ev.track)->getVolume()->amplitude( ev.left, ev.right ); } - } break; } - case Event::TRACK_VOLUME: { - if ( availableRead >= sizeof(EventTrackVol) ) { - EventTrackVol ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackVol) ); - gui->getTrack(ev.track)->getVolume()->fader( ev.vol ); - } break; } - - - case Event::TRACK_RECORD_ARM: { - if ( availableRead >= sizeof(EventTrackRecordArm) ) { - EventTrackRecordArm ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackRecordArm) ); - gui->getTrack(ev.track)->setRecordActive( ev.recordArm ); - break; } - } - - case Event::TIME_BPM: { - if ( availableRead >= sizeof(EventTimeBPM) ) { - EventTimeBPM ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTimeBPM) ); - gui->getMasterTrack()->setBpm( ev.bpm ); - } break; } - - - case Event::STATE_SAVE_BUFFER: { - if ( availableRead >= sizeof(EventStateSaveBuffer) ) { - EventStateSaveBuffer ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventStateSaveBuffer) ); + 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::QUIT: { + if ( availableRead >= sizeof(EventQuit) ) { + EventQuit ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventQuit) ); + LUPPP_NOTE("%s","GUI QUIT"); + gui->quit(); + } + break; + } + + case Event::SAMPLERATE: { + if ( availableRead >= sizeof(EventSamplerate) ) { + EventSamplerate ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventSamplerate) ); + gui->samplerate = ev.samplerate; + //LUPPP_NOTE("Gui Samplerate: %i", gui->samplerate); + } + break; + } + + /// master + case Event::MASTER_INPUT_TO: { + if ( availableRead >= sizeof(EventMasterInputTo) ) { + EventMasterInputTo ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterInputTo) ); + gui->getMasterTrack()->setInputTo( (int)ev.place, ev.value ); + } + break; + } + case Event::MASTER_INPUT_TO_ACTIVE: { + if ( availableRead >= sizeof(EventMasterInputToActive) ) { + EventMasterInputToActive ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterInputToActive) ); + gui->getMasterTrack()->setInputToActive( (int)ev.place, ev.active ); + } + break; + } + case Event::MASTER_INPUT_VOL: { + if ( availableRead >= sizeof(EventMasterInputVol) ) { + EventMasterInputVol ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterInputVol) ); + gui->getMasterTrack()->setInputVol( ev.vol ); + } + break; + } + case Event::MASTER_RETURN: { + if ( availableRead >= sizeof(EventMasterReturn) ) { + EventMasterReturn ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterReturn) ); + gui->getMasterTrack()->setReturnVol( ev.vol ); + } + break; + } + case Event::MASTER_VOL: { + if ( availableRead >= sizeof(EventMasterVol) ) { + EventMasterVol ev(0); + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterVol) ); + gui->getMasterTrack()->getVolume()->fader( ev.vol ); + } + break; + } + + + case Event::METRONOME_ACTIVE: { + if ( availableRead >= sizeof(EventMetronomeActive) ) { + EventMetronomeActive ev(false); + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMetronomeActive) ); + gui->getMasterTrack()->metronomeEnable(ev.active); + } + break; + } + case Event::LOOPER_STATE: { + if ( availableRead >= sizeof(EventLooperState) ) { + EventLooperState ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperState) ); + //gui->getTrack(ev.track)->getClipSelector()->setState(ev.scene, ev.state); + //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) ); + + // only update if significant change + //if ( ev.progress - gui->getTrack(ev.track)->radial.value() >= 0.05 || + // ev.progress > 0.9 ) + gui->getTrack(ev.track)->radial.value(ev.progress); + + } + break; + } + + + // FIXME: reset signal level to 0 + case Event::TRACK_SIGNAL_LEVEL: { + if ( availableRead >= sizeof(EventTrackSignalLevel) ) { + EventTrackSignalLevel ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackSignalLevel) ); + if ( ev.track == -2 ) { + gui->getMasterTrack()->getInputVolume()->amplitude( ev.left, ev.right ); + } else if ( ev.track == -1 ) { + gui->getMasterTrack()->getVolume()->amplitude( ev.left, ev.right ); + } else { + gui->getTrack(ev.track)->getVolume()->amplitude( ev.left, ev.right ); + } + } + break; + } + case Event::TRACK_VOLUME: { + if ( availableRead >= sizeof(EventTrackVol) ) { + EventTrackVol ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackVol) ); + gui->getTrack(ev.track)->getVolume()->fader( ev.vol ); + } + break; + } + + + case Event::TRACK_RECORD_ARM: { + if ( availableRead >= sizeof(EventTrackRecordArm) ) { + EventTrackRecordArm ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackRecordArm) ); + gui->getTrack(ev.track)->setRecordActive( ev.recordArm ); + break; + } + } + + case Event::TIME_BPM: { + if ( availableRead >= sizeof(EventTimeBPM) ) { + EventTimeBPM ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTimeBPM) ); + gui->getMasterTrack()->setBpm( ev.bpm ); + } + break; + } + + + case Event::STATE_SAVE_BUFFER: { + if ( availableRead >= sizeof(EventStateSaveBuffer) ) { + EventStateSaveBuffer ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventStateSaveBuffer) ); #ifdef DEBUG_SAVE - cout << "EventSaveBuffer: " << ev.track << " " << ev.scene << " " << ev.ab->getID() << endl; + cout << "EventSaveBuffer: " << ev.track << " " << ev.scene << " " << ev.ab->getID() << endl; #endif - gui->getDiskWriter()->writeAudioBuffer( ev.track, ev.scene, ev.ab ); - // de allocate the AudioBuffer only if reqested - if(!ev.no_dealloc) { - gui->getDiskWriter()->writeAudioBuffer( ev.track, ev.scene, ev.ab ); - delete ev.ab; - } else - { - gui->getDiskWriter()->writeAudioBuffer(ev.track, ev.scene, ev.ab, - gui->saveBufferPath.c_str()); - gui->saveBufferPath = ""; - } + gui->getDiskWriter()->writeAudioBuffer( ev.track, ev.scene, ev.ab ); + // de allocate the AudioBuffer only if reqested + if(!ev.no_dealloc) { + gui->getDiskWriter()->writeAudioBuffer( ev.track, ev.scene, ev.ab ); + delete ev.ab; + } else { + gui->getDiskWriter()->writeAudioBuffer(ev.track, ev.scene, ev.ab, + gui->saveBufferPath.c_str()); + gui->saveBufferPath = ""; + } - } break; } - - case Event::STATE_SAVE_FINISH: { - if ( availableRead >= sizeof(EventStateSaveFinish) ) { - EventStateSaveFinish ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventStateSaveFinish) ); + } + break; + } + + case Event::STATE_SAVE_FINISH: { + if ( availableRead >= sizeof(EventStateSaveFinish) ) { + EventStateSaveFinish ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventStateSaveFinish) ); #ifdef DEBUG_SAVE - cout << "EventSaveFinish!" << endl; + cout << "EventSaveFinish!" << endl; #endif - gui->getDiskWriter()->writeSession(); - } break; } - - - case Event::GRID_STATE: { - if ( availableRead >= sizeof(EventGridState) ) { - EventGridState ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGridState) ); - gui->getTrack(ev.track)->getClipSelector()->setState( ev.scene, ev.state ); - if ( ev.state == GridLogic::STATE_RECORDING ) - gui->getTrack(ev.track)->getRadialStatus()->recording( true ); - else - gui->getTrack(ev.track)->getRadialStatus()->recording( false ); - } break; } - case Event::GRID_LAUNCH_SCENE: { - if ( availableRead >= sizeof(EventGridLaunchScene) ) { - EventGridLaunchScene ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGridLaunchScene) ); - for(int i = 0; i < NSCENES; i++) - gui->getMasterTrack()->getClipSelector()->setState( i, GridLogic::STATE_EMPTY ); - gui->getMasterTrack()->getClipSelector()->setState( ev.scene, GridLogic::STATE_PLAYING ); - } break; } - - case Event::GRID_SELECT_NEW_CHOSEN: { - if ( availableRead >= sizeof(EventGridSelectNewChosen) ) { - EventGridSelectNewChosen ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGridSelectNewChosen) ); - //LUPPP_NOTE("New special, %i, %i", ev.track, ev.scene); - for(int i = 0; i < NTRACKS; i++) - { - gui->getTrack(i)->getClipSelector()->setSpecial( i == ev.track ? ev.scene : -1 ); - } - gui->specialTrack = ev.track; - gui->specialScene = ev.scene; - } break; } - - - case Event::TRACK_SEND: { - if ( availableRead >= sizeof(EventTrackSend) ) { - EventTrackSend ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackSend) ); - if ( ev.send == SEND_POSTFADER ) - if ( ev.track < NTRACKS ) - { - gui->getTrack(ev.track)->setSend(ev.value ); - } - if ( ev.send == SEND_XSIDE ) - if ( ev.track < NTRACKS ) - { - gui->getTrack(ev.track)->setXSide( ev.value ); - } - } break; } + gui->getDiskWriter()->writeSession(); + } + break; + } - case Event::TRACK_JACKSEND: { - if ( availableRead >= sizeof(EventTrackJackSend) ) { - EventTrackJackSend ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackJackSend) ); - gui->getTrack(ev.track)->setJackSend(ev.value); - } break; } - case Event::TRACK_JACKSEND_ACTIVATE: { - if ( availableRead >= sizeof(EventTrackJackSendActivate) ) { - EventTrackJackSendActivate ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackJackSendActivate) ); - gui->getTrack(ev.track)->setJackSendActivate(ev.active); - } break; } - - case Event::TRACK_SEND_ACTIVE: { - if ( availableRead >= sizeof(EventTrackSendActive) ) { - EventTrackSendActive ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackSendActive) ); - if ( ev.send == SEND_POSTFADER ) - if ( ev.track < NTRACKS ) - { - gui->getTrack(ev.track)->setSendActive(ev.active ); - } - if ( ev.send == SEND_KEY ) - { - if ( ev.track < NTRACKS ) - { - gui->getTrack(ev.track)->setKeyActive( ev.active ); - } - } - } break; } - - case Event::GUI_PRINT: { - if ( availableRead >= sizeof(EventGuiPrint) ) { - EventGuiPrint ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGuiPrint) ); - //cout << "DSP: " << ev.getMessage() << endl; - LUPPP_DSP("%s", ev.getMessage() ); - } break; } - case Event::TIME_BAR_BEAT: { - if ( availableRead >= sizeof(EventTimeBarBeat) ) { - EventTimeBarBeat ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTimeBarBeat) ); - gui->getMasterTrack()->setBarBeat( ev.bar, ev.beat); - } break; } - case Event::TIME_TEMPO_TAP: { - if ( availableRead >= sizeof(EventTimeTempoTap) ) { - EventTimeTempoTap ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTimeTempoTap) ); - gui->getMasterTrack()->setTapTempo( ev.pressed ); - } break; } - - - case Event::LOOPER_REQUEST_BUFFER: { - if ( availableRead >= sizeof(EventLooperClipRequestBuffer) ) { - EventLooperClipRequestBuffer ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperClipRequestBuffer) ); - - /// allocate a new AudioBuffer with ev.numElements, pass back to DSP - AudioBuffer* ab = new AudioBuffer(ev.numElements); - EventLooperClipRequestBuffer returnEvent(ev.track, ev.scene, ab); - writeToDspRingbuffer( &returnEvent ); + case Event::GRID_STATE: { + if ( availableRead >= sizeof(EventGridState) ) { + EventGridState ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGridState) ); + gui->getTrack(ev.track)->getClipSelector()->setState( ev.scene, ev.state ); + if ( ev.state == GridLogic::STATE_RECORDING ) + gui->getTrack(ev.track)->getRadialStatus()->recording( true ); + else + gui->getTrack(ev.track)->getRadialStatus()->recording( false ); + } + break; + } + case Event::GRID_LAUNCH_SCENE: { + if ( availableRead >= sizeof(EventGridLaunchScene) ) { + EventGridLaunchScene ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGridLaunchScene) ); + for(int i = 0; i < NSCENES; i++) + gui->getMasterTrack()->getClipSelector()->setState( i, GridLogic::STATE_EMPTY ); + gui->getMasterTrack()->getClipSelector()->setState( ev.scene, GridLogic::STATE_PLAYING ); + } + break; + } + + case Event::GRID_SELECT_NEW_CHOSEN: { + if ( availableRead >= sizeof(EventGridSelectNewChosen) ) { + EventGridSelectNewChosen ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGridSelectNewChosen) ); + //LUPPP_NOTE("New special, %i, %i", ev.track, ev.scene); + for(int i = 0; i < NTRACKS; i++) { + gui->getTrack(i)->getClipSelector()->setSpecial( i == ev.track ? ev.scene : -1 ); + } + gui->specialTrack = ev.track; + gui->specialScene = ev.scene; + } + break; + } + + + case Event::TRACK_SEND: { + if ( availableRead >= sizeof(EventTrackSend) ) { + EventTrackSend ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackSend) ); + if ( ev.send == SEND_POSTFADER ) + if ( ev.track < NTRACKS ) { + gui->getTrack(ev.track)->setSend(ev.value ); + } + if ( ev.send == SEND_XSIDE ) + if ( ev.track < NTRACKS ) { + gui->getTrack(ev.track)->setXSide( ev.value ); + } + } + break; + } + + case Event::TRACK_JACKSEND: { + if ( availableRead >= sizeof(EventTrackJackSend) ) { + EventTrackJackSend ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackJackSend) ); + gui->getTrack(ev.track)->setJackSend(ev.value); + } + break; + } + + case Event::TRACK_JACKSEND_ACTIVATE: { + if ( availableRead >= sizeof(EventTrackJackSendActivate) ) { + EventTrackJackSendActivate ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackJackSendActivate) ); + gui->getTrack(ev.track)->setJackSendActivate(ev.active); + } + break; + } + + case Event::TRACK_SEND_ACTIVE: { + if ( availableRead >= sizeof(EventTrackSendActive) ) { + EventTrackSendActive ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackSendActive) ); + if ( ev.send == SEND_POSTFADER ) + if ( ev.track < NTRACKS ) { + gui->getTrack(ev.track)->setSendActive(ev.active ); + } + if ( ev.send == SEND_KEY ) { + if ( ev.track < NTRACKS ) { + gui->getTrack(ev.track)->setKeyActive( ev.active ); + } + } + } + break; + } + + case Event::GUI_PRINT: { + if ( availableRead >= sizeof(EventGuiPrint) ) { + EventGuiPrint ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventGuiPrint) ); + //cout << "DSP: " << ev.getMessage() << endl; + LUPPP_DSP("%s", ev.getMessage() ); + } + break; + } + case Event::TIME_BAR_BEAT: { + if ( availableRead >= sizeof(EventTimeBarBeat) ) { + EventTimeBarBeat ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTimeBarBeat) ); + gui->getMasterTrack()->setBarBeat( ev.bar, ev.beat); + } + break; + } + case Event::TIME_TEMPO_TAP: { + if ( availableRead >= sizeof(EventTimeTempoTap) ) { + EventTimeTempoTap ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTimeTempoTap) ); + gui->getMasterTrack()->setTapTempo( ev.pressed ); + } + break; + } + + + case Event::LOOPER_REQUEST_BUFFER: { + if ( availableRead >= sizeof(EventLooperClipRequestBuffer) ) { + EventLooperClipRequestBuffer ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperClipRequestBuffer) ); + + /// allocate a new AudioBuffer with ev.numElements, pass back to DSP + AudioBuffer* ab = new AudioBuffer(ev.numElements); + EventLooperClipRequestBuffer returnEvent(ev.track, ev.scene, ab); + writeToDspRingbuffer( &returnEvent ); #ifdef DEBUG_BUFFER - printf("new buffer going to track %i, scene %i\n",ev.track, ev.scene); + printf("new buffer going to track %i, scene %i\n",ev.track, ev.scene); #endif - } break; } - - case Event::REQUEST_SAVE_BUFFER: { - if ( availableRead >= sizeof(EventRequestSaveBuffer) ) { - EventRequestSaveBuffer ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventRequestSaveBuffer) ); + } + break; + } + + case Event::REQUEST_SAVE_BUFFER: { + if ( availableRead >= sizeof(EventRequestSaveBuffer) ) { + EventRequestSaveBuffer ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventRequestSaveBuffer) ); #ifdef DEBUG_BUFFER - printf("Save buffer to track %i, scene %i\n",ev.track, ev.scene); + printf("Save buffer to track %i, scene %i\n",ev.track, ev.scene); #endif - /// allocate a new AudioBuffer with ev.numElements, pass back to DSP - AudioBuffer* ab = new AudioBuffer(ev.bufferSize); - - if ( ab ) - { - //LUPPP_NOTE("Save buffer sent with t %i, s %i, ab* %i", ev.track, ev.scene, ab ); - EventRequestSaveBuffer returnEvent( ev.track, ev.scene, ab); - writeToDspRingbuffer( &returnEvent ); - } - else - { - cout << "error allocating save buffer!" << endl; - } - } break; } - - case Event::DEALLOCATE_BUFFER: { - if ( availableRead >= sizeof(EventDeallocateBuffer) ) { - EventDeallocateBuffer ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventDeallocateBuffer) ); - delete ev.ab; - } break; } - - case Event::CONTROLLER_BINDING_ENABLE: { - if ( availableRead >= sizeof(EventControllerBindingEnable) ) { - EventControllerBindingEnable ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerBindingEnable) ); - ControllerUI* c = gui->getOptionsWindow()->getControllerUI( ev.controllerID ); - if ( c ) - c->setBindEnable( ev.enable ); - else - LUPPP_WARN("ControllerUI %i doesn't exist in the UI", ev.controllerID ); - } break; } - - case Event::CONTROLLER_BINDING_TARGET: { - if ( availableRead >= sizeof(EventControllerBindingTarget) ) { - EventControllerBindingTarget ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerBindingTarget) ); - gui->getOptionsWindow()->setTarget( ev.target ); - } break; } - - case Event::CONTROLLER_BINDING_MADE: { - if ( availableRead >= sizeof(EventControllerBindingMade) ) { - EventControllerBindingMade ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerBindingMade) ); - ControllerUI* c = gui->getOptionsWindow()->getControllerUI( ev.controllerID ); - if ( c ) - c->addBinding( (Binding*)ev.binding ); - else - LUPPP_WARN("ControllerUI %i doesn't exist in the UI", ev.controllerID ); - } break; } - - case Event::CONTROLLER_INSTANCE_GET_TO_WRITE: { - if ( availableRead >= sizeof(EventControllerInstanceGetToWrite) ) { - EventControllerInstanceGetToWrite ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerInstanceGetToWrite) ); - // write the contents of the GenericMIDI controller to .ctlr file - gui->getDiskWriter()->writeControllerFile( (Controller*)ev.controller ); - } break; } - - case Event::CONTROLLER_INSTANCE: { - if ( availableRead >= sizeof(EventControllerInstance) ) { - EventControllerInstance ev; - jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerInstance) ); - // remove this controller from use: - Controller* c = (Controller*)ev.controller; - LUPPP_NOTE("Deleting controller %s", c->getName().c_str() ); - // delete will call the destructor for the Controller: this should - // clean up ports etc, all from the GUI thread as appropriate - delete c; - } break; } - - - - default: - { - cout << "GUI: 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 ); - } + /// allocate a new AudioBuffer with ev.numElements, pass back to DSP + AudioBuffer* ab = new AudioBuffer(ev.bufferSize); + + if ( ab ) { + //LUPPP_NOTE("Save buffer sent with t %i, s %i, ab* %i", ev.track, ev.scene, ab ); + EventRequestSaveBuffer returnEvent( ev.track, ev.scene, ab); + writeToDspRingbuffer( &returnEvent ); + } else { + cout << "error allocating save buffer!" << endl; + } + } + break; + } + + case Event::DEALLOCATE_BUFFER: { + if ( availableRead >= sizeof(EventDeallocateBuffer) ) { + EventDeallocateBuffer ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventDeallocateBuffer) ); + delete ev.ab; + } + break; + } + + case Event::CONTROLLER_BINDING_ENABLE: { + if ( availableRead >= sizeof(EventControllerBindingEnable) ) { + EventControllerBindingEnable ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerBindingEnable) ); + ControllerUI* c = gui->getOptionsWindow()->getControllerUI( ev.controllerID ); + if ( c ) + c->setBindEnable( ev.enable ); + else + LUPPP_WARN("ControllerUI %i doesn't exist in the UI", ev.controllerID ); + } + break; + } + + case Event::CONTROLLER_BINDING_TARGET: { + if ( availableRead >= sizeof(EventControllerBindingTarget) ) { + EventControllerBindingTarget ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerBindingTarget) ); + gui->getOptionsWindow()->setTarget( ev.target ); + } + break; + } + + case Event::CONTROLLER_BINDING_MADE: { + if ( availableRead >= sizeof(EventControllerBindingMade) ) { + EventControllerBindingMade ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerBindingMade) ); + ControllerUI* c = gui->getOptionsWindow()->getControllerUI( ev.controllerID ); + if ( c ) + c->addBinding( (Binding*)ev.binding ); + else + LUPPP_WARN("ControllerUI %i doesn't exist in the UI", ev.controllerID ); + } + break; + } + + case Event::CONTROLLER_INSTANCE_GET_TO_WRITE: { + if ( availableRead >= sizeof(EventControllerInstanceGetToWrite) ) { + EventControllerInstanceGetToWrite ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerInstanceGetToWrite) ); + // write the contents of the GenericMIDI controller to .ctlr file + gui->getDiskWriter()->writeControllerFile( (Controller*)ev.controller ); + } + break; + } + + case Event::CONTROLLER_INSTANCE: { + if ( availableRead >= sizeof(EventControllerInstance) ) { + EventControllerInstance ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventControllerInstance) ); + // remove this controller from use: + Controller* c = (Controller*)ev.controller; + LUPPP_NOTE("Deleting controller %s", c->getName().c_str() ); + // delete will call the destructor for the Controller: this should + // clean up ports etc, all from the GUI thread as appropriate + delete c; + } + break; + } + + + + default: { + cout << "GUI: 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; - } + 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/gaudioeditor.cxx b/src/gaudioeditor.cxx index eccb0c0..a511f46 100644 --- a/src/gaudioeditor.cxx +++ b/src/gaudioeditor.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -31,154 +31,157 @@ extern Gui* gui; #include "avtk/avtk_button.h" -void oneCB (Fl_Widget*,void* data) { ((AudioEditor*)data)->setBeatsAndQuit( 1 ); } -void twoCB (Fl_Widget*,void* data) { ((AudioEditor*)data)->setBeatsAndQuit( 2 ); } -void fourCB (Fl_Widget*,void* data) { ((AudioEditor*)data)->setBeatsAndQuit( 4 ); } -void eightCB (Fl_Widget*,void* data) { ((AudioEditor*)data)->setBeatsAndQuit( 8 ); } -void sixteenCB (Fl_Widget*,void* data) { ((AudioEditor*)data)->setBeatsAndQuit( 16); } -void thirtyTwoCB(Fl_Widget*,void* data) { ((AudioEditor*)data)->setBeatsAndQuit( 32); } -void sixtyfourCB(Fl_Widget*,void* data) { ((AudioEditor*)data)->setBeatsAndQuit( 64); } +void oneCB (Fl_Widget*,void* data) +{ + ((AudioEditor*)data)->setBeatsAndQuit( 1 ); +} +void twoCB (Fl_Widget*,void* data) +{ + ((AudioEditor*)data)->setBeatsAndQuit( 2 ); +} +void fourCB (Fl_Widget*,void* data) +{ + ((AudioEditor*)data)->setBeatsAndQuit( 4 ); +} +void eightCB (Fl_Widget*,void* data) +{ + ((AudioEditor*)data)->setBeatsAndQuit( 8 ); +} +void sixteenCB (Fl_Widget*,void* data) +{ + ((AudioEditor*)data)->setBeatsAndQuit( 16); +} +void thirtyTwoCB(Fl_Widget*,void* data) +{ + ((AudioEditor*)data)->setBeatsAndQuit( 32); +} +void sixtyfourCB(Fl_Widget*,void* data) +{ + ((AudioEditor*)data)->setBeatsAndQuit( 64); +} void cancelCB(Fl_Widget*,void* data) { - printf("button, beats = 4\n"); - AudioEditor* ae = (AudioEditor*) data; - ae->setBeatsAndQuit( -1 ); + printf("button, beats = 4\n"); + AudioEditor* ae = (AudioEditor*) data; + ae->setBeatsAndQuit( -1 ); } AudioEditor::AudioEditor() { - window = new Fl_Double_Window(460,200,"Audio Editor : Beats?"); - waveform = new Avtk::Waveform(5, 5, 450, 150, "Waveform"); - cancel = new Avtk::Button(360, 160, 80,30, "Cancel"); - - const char* names[] = { - "1","2","4","8","16","32","64" - }; - - for(int i = 0; i < 7; i++) - { - stringstream s; - s << i; - beatButtons[i] = new Avtk::Button(5 + i * 50, 160, 40,30, strdup(names[i]) ); - } - window->end(); - - beatButtons[0]->callback( oneCB , this); - beatButtons[1]->callback( twoCB , this); - beatButtons[2]->callback( fourCB , this); - beatButtons[3]->callback( eightCB , this); - beatButtons[4]->callback( sixteenCB , this); - beatButtons[5]->callback( thirtyTwoCB, this); - beatButtons[6]->callback( sixtyfourCB, this); - - cancel->callback( cancelCB, this ); + window = new Fl_Double_Window(460,200,"Audio Editor : Beats?"); + waveform = new Avtk::Waveform(5, 5, 450, 150, "Waveform"); + cancel = new Avtk::Button(360, 160, 80,30, "Cancel"); + + const char* names[] = { + "1","2","4","8","16","32","64" + }; + + for(int i = 0; i < 7; i++) { + stringstream s; + s << i; + beatButtons[i] = new Avtk::Button(5 + i * 50, 160, 40,30, strdup(names[i]) ); + } + window->end(); + + beatButtons[0]->callback( oneCB , this); + beatButtons[1]->callback( twoCB , this); + beatButtons[2]->callback( fourCB , this); + beatButtons[3]->callback( eightCB , this); + beatButtons[4]->callback( sixteenCB , this); + beatButtons[5]->callback( thirtyTwoCB, this); + beatButtons[6]->callback( sixtyfourCB, this); + + cancel->callback( cancelCB, this ); } void AudioEditor::show( AudioBuffer* buf, bool modal ) { - ab = buf; - - if ( !ab ) - { - LUPPP_WARN("called with ab == 0"); - } - else - { - std::vector& tmp = ab->getData(); - int size = tmp.size(); - waveform->setData( &tmp[0], size ); - - const int beats[]={1,2,4,8,16,32,64}; - - int iBeatOne = -1; - int iBeatTwo = -1; - - // figure out BPM values from size - for( int i = 0; i < 7; i++ ) - { - int beat = beats[i]; - - int fpb = size / beat; - - int bpm = (gui->samplerate / fpb) * 60; - - - if ( bpm < 60 || bpm > 220 ) - { - // disable option: not valid - beatButtons[i]->setGreyOut( true ); - beatButtons[i]->setColor( 0.4, 0.4, 0.4 ); - } - else - { - //printf("%i, fpb = %i, bpm= = %i\n", beat, fpb, bpm ); - // enable option ( may be disabled previously! ) - beatButtons[i]->setGreyOut( false ); - - // remember this beat was a valid one, to check for best match - if ( iBeatOne == -1 ) - iBeatOne = i; - else - iBeatTwo = i; - } - } - - // both valid: compare, and adjust color - if ( iBeatOne != -1 && iBeatTwo != -1 ) - { - int masterFpb = (gui->samplerate * 60) / gui->getMasterTrack()->getBpm(); - int oneFpb = size / beats[iBeatOne]; - int twoFpb = size / beats[iBeatTwo]; - - int oneDelta = masterFpb - oneFpb; - int twoDelta = masterFpb - twoFpb; - - if ( oneDelta < 0 ) oneDelta = -oneDelta; - if ( twoDelta < 0 ) twoDelta = -twoDelta; - - if ( oneDelta == twoDelta ) - { - beatButtons[iBeatOne]->setColor( 0.0, 1.0, 0.0 ); - beatButtons[iBeatTwo]->setColor( 0.0, 1.0, 0.0 ); - } - else if ( oneDelta <= twoDelta ) - { - // one is the better match - beatButtons[iBeatOne]->setColor( 0.0, 1.0, 0.0 ); - beatButtons[iBeatTwo]->setColor( 1.0, 0.0, 0.0 ); - } - else - { - beatButtons[iBeatTwo]->setColor( 0.0, 1.0, 0.0 ); - beatButtons[iBeatOne]->setColor( 1.0, 0.0, 0.0 ); - } - } - else if( iBeatOne != -1 && iBeatTwo == -1) // only one valid - { - beatButtons[iBeatOne]->setColor( 0.0, 1.0, 0.0 ); - } - else - { - // no valid BPM range..? - } - - } - - window->set_modal(); - window->show(); + ab = buf; + + if ( !ab ) { + LUPPP_WARN("called with ab == 0"); + } else { + std::vector& tmp = ab->getData(); + int size = tmp.size(); + waveform->setData( &tmp[0], size ); + + const int beats[]= {1,2,4,8,16,32,64}; + + int iBeatOne = -1; + int iBeatTwo = -1; + + // figure out BPM values from size + for( int i = 0; i < 7; i++ ) { + int beat = beats[i]; + + int fpb = size / beat; + + int bpm = (gui->samplerate / fpb) * 60; + + + if ( bpm < 60 || bpm > 220 ) { + // disable option: not valid + beatButtons[i]->setGreyOut( true ); + beatButtons[i]->setColor( 0.4, 0.4, 0.4 ); + } else { + //printf("%i, fpb = %i, bpm= = %i\n", beat, fpb, bpm ); + // enable option ( may be disabled previously! ) + beatButtons[i]->setGreyOut( false ); + + // remember this beat was a valid one, to check for best match + if ( iBeatOne == -1 ) + iBeatOne = i; + else + iBeatTwo = i; + } + } + + // both valid: compare, and adjust color + if ( iBeatOne != -1 && iBeatTwo != -1 ) { + int masterFpb = (gui->samplerate * 60) / gui->getMasterTrack()->getBpm(); + int oneFpb = size / beats[iBeatOne]; + int twoFpb = size / beats[iBeatTwo]; + + int oneDelta = masterFpb - oneFpb; + int twoDelta = masterFpb - twoFpb; + + if ( oneDelta < 0 ) oneDelta = -oneDelta; + if ( twoDelta < 0 ) twoDelta = -twoDelta; + + if ( oneDelta == twoDelta ) { + beatButtons[iBeatOne]->setColor( 0.0, 1.0, 0.0 ); + beatButtons[iBeatTwo]->setColor( 0.0, 1.0, 0.0 ); + } else if ( oneDelta <= twoDelta ) { + // one is the better match + beatButtons[iBeatOne]->setColor( 0.0, 1.0, 0.0 ); + beatButtons[iBeatTwo]->setColor( 1.0, 0.0, 0.0 ); + } else { + beatButtons[iBeatTwo]->setColor( 0.0, 1.0, 0.0 ); + beatButtons[iBeatOne]->setColor( 1.0, 0.0, 0.0 ); + } + } else if( iBeatOne != -1 && iBeatTwo == -1) { // only one valid + beatButtons[iBeatOne]->setColor( 0.0, 1.0, 0.0 ); + } else { + // no valid BPM range..? + } + + } + + window->set_modal(); + window->show(); } void AudioEditor::hide() { - window->hide(); + window->hide(); } void AudioEditor::setBeatsAndQuit(int beats) { - ab->setBeats(beats); - window->hide(); + ab->setBeats(beats); + window->hide(); } /* @@ -190,10 +193,10 @@ AudioBuffer* AudioEditor::getAudioBuffer() bool AudioEditor::shown() { - return window->shown(); + return window->shown(); } AudioEditor::~AudioEditor() { - delete window; + delete window; } diff --git a/src/gaudioeditor.hxx b/src/gaudioeditor.hxx index d6d62b6..59beefe 100644 --- a/src/gaudioeditor.hxx +++ b/src/gaudioeditor.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -24,38 +24,39 @@ #include class AudioBuffer; -namespace Avtk { +namespace Avtk +{ class Waveform; class Button; } class AudioEditor { - public: - AudioEditor(); - ~AudioEditor(); - - /// shows the window, and loads the audio buffer into the display - void show( AudioBuffer* ab, bool modal = false ); - - void hide(); - - /// returns true if the editor window is shown - bool shown(); - - void setBeatsAndQuit( int beats ); - - //AudioBuffer* getAudioBuffer(); - - private: - // GUI elements - Fl_Double_Window* window; - Avtk::Waveform* waveform; - Avtk::Button* cancel; - Avtk::Button* beatButtons[7]; - - // Contents - AudioBuffer* ab; +public: + AudioEditor(); + ~AudioEditor(); + + /// shows the window, and loads the audio buffer into the display + void show( AudioBuffer* ab, bool modal = false ); + + void hide(); + + /// returns true if the editor window is shown + bool shown(); + + void setBeatsAndQuit( int beats ); + + //AudioBuffer* getAudioBuffer(); + +private: + // GUI elements + Fl_Double_Window* window; + Avtk::Waveform* waveform; + Avtk::Button* cancel; + Avtk::Button* beatButtons[7]; + + // Contents + AudioBuffer* ab; }; #endif // LUPPP_AUDIO_EDITOR_H diff --git a/src/gmastertrack.cxx b/src/gmastertrack.cxx index 35da00b..c95ab69 100644 --- a/src/gmastertrack.cxx +++ b/src/gmastertrack.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -22,378 +22,358 @@ static void gmastertrack_tempoDial_callback(Fl_Widget *w, void *data) { - Avtk::Dial* b = (Avtk::Dial*)w; - float bpm = (int)(b->value() * 160.f + 60); - if(std::fabs(bpm-round(bpm))) - { - LUPPP_WARN("%f",bpm); - } - EventTimeBPM e = EventTimeBPM( bpm ); - writeToDspRingbuffer( &e ); + Avtk::Dial* b = (Avtk::Dial*)w; + float bpm = (int)(b->value() * 160.f + 60); + if(std::fabs(bpm-round(bpm))) { + LUPPP_WARN("%f",bpm); + } + EventTimeBPM e = EventTimeBPM( bpm ); + writeToDspRingbuffer( &e ); } static void gmastertrack_volume_callback(Fl_Widget *w, void *data) { - Avtk::Volume* b = (Avtk::Volume*)w; - float v = b->value(); - EventMasterVol e( v ); - writeToDspRingbuffer( &e ); + Avtk::Volume* b = (Avtk::Volume*)w; + float v = b->value(); + EventMasterVol e( v ); + writeToDspRingbuffer( &e ); } static void gmastertrack_inputVolume_callback(Fl_Widget *w, void *data) { - Avtk::Volume* b = (Avtk::Volume*)w; - float v = b->value(); - EventMasterInputVol e( v ); - writeToDspRingbuffer( &e ); + Avtk::Volume* b = (Avtk::Volume*)w; + float v = b->value(); + EventMasterInputVol e( v ); + writeToDspRingbuffer( &e ); } static void gmastertrack_sidchainKeyButton_callback(Fl_Widget *w, void *data) { - Avtk::LightButton* b = (Avtk::LightButton*)w; - b->value( !b->value() ); - EventMasterInputToActive e( INPUT_TO_SIDE_KEY, b->value() ); - writeToDspRingbuffer( &e ); - //printf("Key button\n"); + Avtk::LightButton* b = (Avtk::LightButton*)w; + b->value( !b->value() ); + EventMasterInputToActive e( INPUT_TO_SIDE_KEY, b->value() ); + writeToDspRingbuffer( &e ); + //printf("Key button\n"); } static void gmastertrack_mixButton_callback(Fl_Widget *w, void *data) { - Avtk::LightButton* b = (Avtk::LightButton*)w; - b->value( !b->value() ); - EventMasterInputToActive e( INPUT_TO_MIX, b->value() ); - writeToDspRingbuffer( &e ); - //printf("Mix button\n"); + Avtk::LightButton* b = (Avtk::LightButton*)w; + b->value( !b->value() ); + EventMasterInputToActive e( INPUT_TO_MIX, b->value() ); + writeToDspRingbuffer( &e ); + //printf("Mix button\n"); } static void gmastertrack_sendButton_callback(Fl_Widget *w, void *data) { - Avtk::LightButton* b = (Avtk::LightButton*)w; - b->value( !b->value() ); - EventMasterInputToActive e( INPUT_TO_SEND, b->value() ); - writeToDspRingbuffer( &e ); - //printf("Send button\n"); + Avtk::LightButton* b = (Avtk::LightButton*)w; + b->value( !b->value() ); + EventMasterInputToActive e( INPUT_TO_SEND, b->value() ); + writeToDspRingbuffer( &e ); + //printf("Send button\n"); } static void gmastertrack_sendVol_callback(Fl_Widget *w, void *data) { - Avtk::Dial* b = (Avtk::Dial*)w; - float v = b->value(); - EventMasterInputTo e = EventMasterInputTo( INPUT_TO_SEND, v ); - writeToDspRingbuffer( &e ); - ///printf("Send dial\n"); + Avtk::Dial* b = (Avtk::Dial*)w; + float v = b->value(); + EventMasterInputTo e = EventMasterInputTo( INPUT_TO_SEND, v ); + writeToDspRingbuffer( &e ); + ///printf("Send dial\n"); } static void gmastertrack_xSideVol_callback(Fl_Widget *w, void *data) { - Avtk::Dial* b = (Avtk::Dial*)w; - float v = b->value(); - EventMasterInputTo e = EventMasterInputTo( INPUT_TO_XSIDE, v ); - writeToDspRingbuffer( &e ); - //printf("XSide dial\n"); + Avtk::Dial* b = (Avtk::Dial*)w; + float v = b->value(); + EventMasterInputTo e = EventMasterInputTo( INPUT_TO_XSIDE, v ); + writeToDspRingbuffer( &e ); + //printf("XSide dial\n"); } /// return volume static void gmastertrack_returnVol_callback(Fl_Widget *w, void *data) { - Avtk::Dial* b = (Avtk::Dial*)w; - float v = b->value(); - EventMasterReturn e( RETURN_MAIN, v ); - writeToDspRingbuffer( &e ); - //printf("Return dial\n"); + Avtk::Dial* b = (Avtk::Dial*)w; + float v = b->value(); + EventMasterReturn e( RETURN_MAIN, v ); + writeToDspRingbuffer( &e ); + //printf("Return dial\n"); } static void gmastertrack_mixVol_callback(Fl_Widget *w, void *data) { - Avtk::Dial* b = (Avtk::Dial*)w; - float v = b->value(); - EventMasterInputTo e = EventMasterInputTo( INPUT_TO_MIX, v ); - writeToDspRingbuffer( &e ); + Avtk::Dial* b = (Avtk::Dial*)w; + float v = b->value(); + EventMasterInputTo e = EventMasterInputTo( INPUT_TO_MIX, v ); + writeToDspRingbuffer( &e ); } static void gmastertrack_transport_callback(Fl_Widget *w, void *data) { - Avtk::LightButton* b = (Avtk::LightButton*)w; - if( b->value() ) - { - EventTransportState e = EventTransportState( TRANSPORT_ROLLING ); - writeToDspRingbuffer( &e ); - w->label( "Stop" ); - b->value( 0 ); - } - else - { - EventTransportState e = EventTransportState( TRANSPORT_STOPPED ); - writeToDspRingbuffer( &e ); - w->label( "Play" ); - b->value( 1 ); - } - + Avtk::LightButton* b = (Avtk::LightButton*)w; + if( b->value() ) { + EventTransportState e = EventTransportState( TRANSPORT_ROLLING ); + writeToDspRingbuffer( &e ); + w->label( "Stop" ); + b->value( 0 ); + } else { + EventTransportState e = EventTransportState( TRANSPORT_STOPPED ); + writeToDspRingbuffer( &e ); + w->label( "Play" ); + b->value( 1 ); + } + } static void gmastertrack_button_callback(Fl_Widget *w, void *data) { - if ( strcmp( w->label(), "Metro" ) == 0 ) - { - if ( Fl::event_button() == FL_RIGHT_MOUSE ) - { - // popup volume menu: 10 "steps of volume" - Fl_Menu_Item rclick_menu[] = - { - { "Vol 100%" }, - { "Vol 75%" }, - { "Vol 50%" }, - { "Vol 25%"}, - { 0 } - }; - - Fl_Menu_Item *m = (Fl_Menu_Item*) rclick_menu->popup( Fl::event_x(), Fl::event_y(), 0, 0, 0); - - float v = 0.f; - if ( !m ) - { - return; - } - else if ( strcmp(m->label(), "Vol 100%") == 0 ) { - v = 1; - } - else if ( strcmp(m->label(), "Vol 75%") == 0 ) { - v = 0.75; - } - else if ( strcmp(m->label(), "Vol 50%") == 0 ) { - v = 0.5; - } - else - v = 0.25; - - LUPPP_NOTE("metro vol = %f", v ); - - EventMetronomeVolume e( v ); - writeToDspRingbuffer( &e ); - } - else - { - Avtk::LightButton* b = (Avtk::LightButton*)w; - b->value( !b->value() ); - EventMetronomeActive e = EventMetronomeActive( b->value() ); - writeToDspRingbuffer( &e ); - } - - - - } - else if ( strcmp( w->label(), "Tap" ) == 0 ) - { - EventTimeTempoTap e; - writeToDspRingbuffer( &e ); - } - else - { - LUPPP_WARN("Error: unknown command string"); - } + if ( strcmp( w->label(), "Metro" ) == 0 ) { + if ( Fl::event_button() == FL_RIGHT_MOUSE ) { + // popup volume menu: 10 "steps of volume" + Fl_Menu_Item rclick_menu[] = { + { "Vol 100%" }, + { "Vol 75%" }, + { "Vol 50%" }, + { "Vol 25%"}, + { 0 } + }; + + Fl_Menu_Item *m = (Fl_Menu_Item*) rclick_menu->popup( Fl::event_x(), Fl::event_y(), 0, 0, 0); + + float v = 0.f; + if ( !m ) { + return; + } else if ( strcmp(m->label(), "Vol 100%") == 0 ) { + v = 1; + } else if ( strcmp(m->label(), "Vol 75%") == 0 ) { + v = 0.75; + } else if ( strcmp(m->label(), "Vol 50%") == 0 ) { + v = 0.5; + } else + v = 0.25; + + LUPPP_NOTE("metro vol = %f", v ); + + EventMetronomeVolume e( v ); + writeToDspRingbuffer( &e ); + } else { + Avtk::LightButton* b = (Avtk::LightButton*)w; + b->value( !b->value() ); + EventMetronomeActive e = EventMetronomeActive( b->value() ); + writeToDspRingbuffer( &e ); + } + + + + } else if ( strcmp( w->label(), "Tap" ) == 0 ) { + EventTimeTempoTap e; + writeToDspRingbuffer( &e ); + } else { + LUPPP_WARN("Error: unknown command string"); + } } #define OFST 33 GMasterTrack::GMasterTrack(int x, int y, int w, int h, const char* l ) : - Fl_Group(x, y, w, h), - title( strdup(l) ), - bg( x, y , w, h, title ), - - // with "true" master flag: launches scenes instead of clips on tracks - clipSel(x + 5, y + 26 + 102, 140, 294,"", true), - - source(x+5, y+26, 140, 100, ""), - volBox(x+5, y+422, 140, 232, ""), - - transport ( x + w * 2/4.f - 18, y + 436 + OFST * 0, 44,28, "Stop" ), - tapTempo ( x + w * 2/4.f - 18, y + 436 + OFST * 1, 44,28, "Tap" ), - metronomeButton( x + w * 2/4.f - 18, y + 436 + OFST * 2, 44,28,"Metro"), - - tempoDial ( x + w * 2/4.f - 18, y + 436 + OFST * 3.5, 45, 38,"BPM"), - returnVol ( x + w * 2/4.f - 18, y + 436 + OFST * 5, 45, 38,"Return"), - - inputVolume(x + 9,y + 26 + 4, w - 18, 30,""), - - inputToSend (x + 10,y + 28 + 68, 40, 26,"Snd"), - inputToSendVol(x + w*0.2-15,y + 28 + 36, 30, 30,""), - - inputToSidechainKey (x + w*0.5-20,y + 28 + 68, 40, 26,"Key"), - inputToSidechainSignalVol(x + w*0.5-15,y + 28 + 36, 30, 30,""), - - inputToMix (x + w*0.8-20,y + 28 + 68, 40, 26,"Mix"), - inputToMixVol(x + w*0.8-15,y + 28 + 36, 30, 30,""), - - volume(x+106, y +425, 36, 216, "") + Fl_Group(x, y, w, h), + title( strdup(l) ), + bg( x, y , w, h, title ), + + // with "true" master flag: launches scenes instead of clips on tracks + clipSel(x + 5, y + 26 + 102, 140, 294,"", true), + + source(x+5, y+26, 140, 100, ""), + volBox(x+5, y+422, 140, 232, ""), + + transport ( x + w * 2/4.f - 18, y + 436 + OFST * 0, 44,28, "Stop" ), + tapTempo ( x + w * 2/4.f - 18, y + 436 + OFST * 1, 44,28, "Tap" ), + metronomeButton( x + w * 2/4.f - 18, y + 436 + OFST * 2, 44,28,"Metro"), + + tempoDial ( x + w * 2/4.f - 18, y + 436 + OFST * 3.5, 45, 38,"BPM"), + returnVol ( x + w * 2/4.f - 18, y + 436 + OFST * 5, 45, 38,"Return"), + + inputVolume(x + 9,y + 26 + 4, w - 18, 30,""), + + inputToSend (x + 10,y + 28 + 68, 40, 26,"Snd"), + inputToSendVol(x + w*0.2-15,y + 28 + 36, 30, 30,""), + + inputToSidechainKey (x + w*0.5-20,y + 28 + 68, 40, 26,"Key"), + inputToSidechainSignalVol(x + w*0.5-15,y + 28 + 36, 30, 30,""), + + inputToMix (x + w*0.8-20,y + 28 + 68, 40, 26,"Mix"), + inputToMixVol(x + w*0.8-15,y + 28 + 36, 30, 30,""), + + volume(x+106, y +425, 36, 216, "") { - ID = privateID++; - - bar = 0; - - inputVolume.value(0.5); - inputVolume.setOrientationHorizontal(); - - inputVolume.callback( gmastertrack_inputVolume_callback, 0 ); - - transport.callback( gmastertrack_transport_callback, &ID ); - - tapTempo.callback( gmastertrack_button_callback, &ID ); - - metronomeButton.callback( gmastertrack_button_callback, 0 ); - - tempoDial.callback( gmastertrack_tempoDial_callback, 0 ); - - inputToSend.setColor( 0, 1.0, 0 ); - inputToSend.callback( gmastertrack_sendButton_callback, 0 ); - inputToSendVol.callback( gmastertrack_sendVol_callback, 0 ); - - inputToSidechainKey.setColor( 0, 0.6, 1 ); - inputToSidechainKey.callback( gmastertrack_sidchainKeyButton_callback, 0 ); - inputToSidechainSignalVol.value( 0 ); - inputToSidechainSignalVol.callback( gmastertrack_xSideVol_callback, 0 ); - - inputToMix.callback ( gmastertrack_mixButton_callback, 0 ); - inputToMixVol.callback ( gmastertrack_mixVol_callback, 0 ); - - tempoDial.align( FL_ALIGN_CENTER ); - - returnVol.value( 1.f ); - returnVol.align( FL_ALIGN_CENTER ); - returnVol.callback( gmastertrack_returnVol_callback, 0 ); - - for(int i = 0; i < 4; i++) - { - beatLights[i] = new Avtk::LightButton( x + 10, y + 437 + 54 * i, 40, 42, "" ); - } - beatLights[0]->setColor( 1.0, 0.0 , 0.0 ); - beatLights[1]->setColor( 1.0, 0.48, 0.0 ); - beatLights[2]->setColor( 1.0, 1.0 , 0.0 ); - beatLights[3]->setColor( 0.0, 1.0 , 0.0 ); - - volume.amplitude( 0.0, 0.0 ); - volume.callback( gmastertrack_volume_callback, 0 ); - - end(); // close the group + ID = privateID++; + + bar = 0; + + inputVolume.value(0.5); + inputVolume.setOrientationHorizontal(); + + inputVolume.callback( gmastertrack_inputVolume_callback, 0 ); + + transport.callback( gmastertrack_transport_callback, &ID ); + + tapTempo.callback( gmastertrack_button_callback, &ID ); + + metronomeButton.callback( gmastertrack_button_callback, 0 ); + + tempoDial.callback( gmastertrack_tempoDial_callback, 0 ); + + inputToSend.setColor( 0, 1.0, 0 ); + inputToSend.callback( gmastertrack_sendButton_callback, 0 ); + inputToSendVol.callback( gmastertrack_sendVol_callback, 0 ); + + inputToSidechainKey.setColor( 0, 0.6, 1 ); + inputToSidechainKey.callback( gmastertrack_sidchainKeyButton_callback, 0 ); + inputToSidechainSignalVol.value( 0 ); + inputToSidechainSignalVol.callback( gmastertrack_xSideVol_callback, 0 ); + + inputToMix.callback ( gmastertrack_mixButton_callback, 0 ); + inputToMixVol.callback ( gmastertrack_mixVol_callback, 0 ); + + tempoDial.align( FL_ALIGN_CENTER ); + + returnVol.value( 1.f ); + returnVol.align( FL_ALIGN_CENTER ); + returnVol.callback( gmastertrack_returnVol_callback, 0 ); + + for(int i = 0; i < 4; i++) { + beatLights[i] = new Avtk::LightButton( x + 10, y + 437 + 54 * i, 40, 42, "" ); + } + beatLights[0]->setColor( 1.0, 0.0 , 0.0 ); + beatLights[1]->setColor( 1.0, 0.48, 0.0 ); + beatLights[2]->setColor( 1.0, 1.0 , 0.0 ); + beatLights[3]->setColor( 0.0, 1.0 , 0.0 ); + + volume.amplitude( 0.0, 0.0 ); + volume.callback( gmastertrack_volume_callback, 0 ); + + end(); // close the group } void GMasterTrack::setBpm( int b ) { - bpm = b; - tempoDial.value( ( bpm - 60 ) / 160.f ); - std::stringstream s; - s << bpm; - tempoDial.setLabel( s.str().c_str() ); + bpm = b; + tempoDial.value( ( bpm - 60 ) / 160.f ); + std::stringstream s; + s << bpm; + tempoDial.setLabel( s.str().c_str() ); } void GMasterTrack::setInputVol(float f) { - //LUPPP_NOTE(" gmtrck, inputVol %f", f ); - inputVolume.value( f ); + //LUPPP_NOTE(" gmtrck, inputVol %f", f ); + inputVolume.value( f ); } void GMasterTrack::setReturnVol(float f) { - LUPPP_NOTE(" gmtrck, returnVol %f", f ); - returnVol.value( f ); + LUPPP_NOTE(" gmtrck, returnVol %f", f ); + returnVol.value( f ); } void GMasterTrack::setInputTo(int to, float f) { - //LUPPP_NOTE(" gmtrck, inputTO %i, %f", to, f ); - if ( to == Event::INPUT_TO_MIX ) - inputToMixVol.value( f ); - else if ( to == Event::INPUT_TO_SEND ) - inputToSendVol.value( f ); - else if ( to == Event::INPUT_TO_XSIDE ) - inputToSidechainSignalVol.value( f ); + //LUPPP_NOTE(" gmtrck, inputTO %i, %f", to, f ); + if ( to == Event::INPUT_TO_MIX ) + inputToMixVol.value( f ); + else if ( to == Event::INPUT_TO_SEND ) + inputToSendVol.value( f ); + else if ( to == Event::INPUT_TO_XSIDE ) + inputToSidechainSignalVol.value( f ); } void GMasterTrack::setInputToActive(int to, bool f) { - //LUPPP_NOTE(" gmtrck, inputToActive %i, %i", to, int(f) ); - - if ( to == Event::INPUT_TO_MIX ) - inputToMix.value( f ); - else if ( to == Event::INPUT_TO_SEND ) - inputToSend.value( f ); - else if ( to == Event::INPUT_TO_SIDE_KEY ) - inputToSidechainKey.value( f ); + //LUPPP_NOTE(" gmtrck, inputToActive %i, %i", to, int(f) ); + + if ( to == Event::INPUT_TO_MIX ) + inputToMix.value( f ); + else if ( to == Event::INPUT_TO_SEND ) + inputToSend.value( f ); + else if ( to == Event::INPUT_TO_SIDE_KEY ) + inputToSidechainKey.value( f ); } void GMasterTrack::metronomeEnable( bool b ) { - metronomeButton.value( b ); + metronomeButton.value( b ); } int GMasterTrack::getBpm() { - return bpm; + return bpm; } void GMasterTrack::setTapTempo( bool b ) { - tapTempo.setHighlight( b ); + tapTempo.setHighlight( b ); } void GMasterTrack::setBarBeat(int b, int beat) { - // FIXME: hard coded 4/4 time here - if ( beat % 4 == 0 ) - { - bar = bar % 4 + 1; - } - - // turn all off - for( int i = 0; i < 4; i++) - beatLights[i]->value( 0 ); - - // beat starts at 4 - // FIXME: hard coded 4/4 time - beatLights[ 3 - beat%4 ]->value( 1 ); + // FIXME: hard coded 4/4 time here + if ( beat % 4 == 0 ) { + bar = bar % 4 + 1; + } + + // turn all off + for( int i = 0; i < 4; i++) + beatLights[i]->value( 0 ); + + // beat starts at 4 + // FIXME: hard coded 4/4 time + beatLights[ 3 - beat%4 ]->value( 1 ); } Avtk::Volume* GMasterTrack::getInputVolume() { - return &inputVolume; + return &inputVolume; } Avtk::Volume* GMasterTrack::getVolume() { - return &volume; + return &volume; } Avtk::LightButton* GMasterTrack::getInputToSend() { - return &inputToSend; + return &inputToSend; } Avtk::LightButton* GMasterTrack::getInputToSidechainKey() { - return &inputToSidechainKey; + return &inputToSidechainKey; } Avtk::LightButton* GMasterTrack::getInputToMix() { - return &inputToMix; + return &inputToMix; } Avtk::Dial* GMasterTrack::getInputToSendVol() { - return &inputToSendVol; + return &inputToSendVol; } Avtk::Dial* GMasterTrack::getInputToXSide() { - return &inputToSidechainSignalVol; + return &inputToSidechainSignalVol; } Avtk::Dial* GMasterTrack::getInputToMixVol() { - return &inputToMixVol; + return &inputToMixVol; } Avtk::ClipSelector* GMasterTrack::getClipSelector() { - return &clipSel; + return &clipSel; } GMasterTrack::~GMasterTrack() { - free(title); + free(title); } diff --git a/src/gmastertrack.hxx b/src/gmastertrack.hxx index 06f5c13..2b57b81 100644 --- a/src/gmastertrack.hxx +++ b/src/gmastertrack.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -45,72 +45,72 @@ using namespace std; class GMasterTrack : public Fl_Group { - public: - GMasterTrack(int x, int y, int w, int h, const char* l = 0 ); - - int getBpm(); - void setBpm( int bpm ); - void setTapTempo( bool b ); - void setBarBeat(int b, int beat); - - void setReturnVol(float f); - void setInputVol(float f); - void setInputTo(int to, float f); - void setInputToActive(int to, bool f); - - void metronomeEnable( bool b ); - - Avtk::Volume* getInputVolume(); - Avtk::Volume* getVolume(); - Avtk::ClipSelector* getClipSelector(); - - Avtk::LightButton* getInputToSend(); - Avtk::LightButton* getInputToSidechainKey(); - Avtk::LightButton* getInputToMix(); - - Avtk::Dial* getInputToSendVol(); - Avtk::Dial* getInputToXSide(); - Avtk::Dial* getInputToMixVol(); - - ~GMasterTrack(); - - private: - int ID; - char* title; - - int bar; - int bpm; - - Avtk::Background bg; - - Avtk::ClipSelector clipSel; - - Avtk::Box source; - Avtk::Box volBox; - - Avtk::Button transport; - Avtk::Button tapTempo; - Avtk::LightButton metronomeButton; - Avtk::Dial tempoDial; - - Avtk::Dial returnVol; - - Avtk::LightButton* beatLights[4]; - - Avtk::Volume inputVolume; - - Avtk::LightButton inputToSend; - Avtk::Dial inputToSendVol; - - Avtk::LightButton inputToSidechainKey; - Avtk::Dial inputToSidechainSignalVol; - - Avtk::LightButton inputToMix; - Avtk::Dial inputToMixVol; - - Avtk::Volume volume; - - static int privateID; +public: + GMasterTrack(int x, int y, int w, int h, const char* l = 0 ); + + int getBpm(); + void setBpm( int bpm ); + void setTapTempo( bool b ); + void setBarBeat(int b, int beat); + + void setReturnVol(float f); + void setInputVol(float f); + void setInputTo(int to, float f); + void setInputToActive(int to, bool f); + + void metronomeEnable( bool b ); + + Avtk::Volume* getInputVolume(); + Avtk::Volume* getVolume(); + Avtk::ClipSelector* getClipSelector(); + + Avtk::LightButton* getInputToSend(); + Avtk::LightButton* getInputToSidechainKey(); + Avtk::LightButton* getInputToMix(); + + Avtk::Dial* getInputToSendVol(); + Avtk::Dial* getInputToXSide(); + Avtk::Dial* getInputToMixVol(); + + ~GMasterTrack(); + +private: + int ID; + char* title; + + int bar; + int bpm; + + Avtk::Background bg; + + Avtk::ClipSelector clipSel; + + Avtk::Box source; + Avtk::Box volBox; + + Avtk::Button transport; + Avtk::Button tapTempo; + Avtk::LightButton metronomeButton; + Avtk::Dial tempoDial; + + Avtk::Dial returnVol; + + Avtk::LightButton* beatLights[4]; + + Avtk::Volume inputVolume; + + Avtk::LightButton inputToSend; + Avtk::Dial inputToSendVol; + + Avtk::LightButton inputToSidechainKey; + Avtk::Dial inputToSidechainSignalVol; + + Avtk::LightButton inputToMix; + Avtk::Dial inputToMixVol; + + Avtk::Volume volume; + + static int privateID; }; #endif // LUPPP_G_MASTER_TRACK_H diff --git a/src/goptions.cxx b/src/goptions.cxx index 72b7ded..cffbc2c 100644 --- a/src/goptions.cxx +++ b/src/goptions.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -33,449 +33,432 @@ extern Gui* gui; static void addControllerUiDsp(OptionsWindow* self, GenericMIDI* c) { - // add the controller to the UI - int x, y, w, h; - self->tabs->client_area( x, y, w, h, 25 ); - self->controllers.push_back( new ControllerUI( x, y, w, h, c->getName().c_str(), c->getID() ) ); - - // store the pointer to the options window: needed to make remove button work - self->controllers.back()->optionsWindow = self; - - LUPPP_NOTE("Added controller %s, ID %i", c->getName().c_str(), c->getID() ); + // add the controller to the UI + int x, y, w, h; + self->tabs->client_area( x, y, w, h, 25 ); + self->controllers.push_back( new ControllerUI( x, y, w, h, c->getName().c_str(), c->getID() ) ); - // add widget before "add" button - self->tabs->insert( *self->controllers.back()->widget, self->addGroup ); - - // tell the ControllerUI to add the bindings from this Controller* - self->controllers.back()->setAuthor( c->getAuthor() ); - self->controllers.back()->setLink( c->getEmail() ); - self->controllers.back()->addBindings( c ); - - self->tabs->redraw(); - - // send to DSP side - EventControllerInstance e(c); - writeToDspRingbuffer( &e ); + // store the pointer to the options window: needed to make remove button work + self->controllers.back()->optionsWindow = self; + + LUPPP_NOTE("Added controller %s, ID %i", c->getName().c_str(), c->getID() ); + + // add widget before "add" button + self->tabs->insert( *self->controllers.back()->widget, self->addGroup ); + + // tell the ControllerUI to add the bindings from this Controller* + self->controllers.back()->setAuthor( c->getAuthor() ); + self->controllers.back()->setLink( c->getEmail() ); + self->controllers.back()->addBindings( c ); + + self->tabs->redraw(); + + // send to DSP side + EventControllerInstance e(c); + writeToDspRingbuffer( &e ); } static void updateAuthorCB(Fl_Widget* w, void* data) { - ControllerUI* c = (ControllerUI*)data; - const char* s = fl_input( "Author: ", "" ); - if ( s ) - { - c->setAuthor( s ); - } + ControllerUI* c = (ControllerUI*)data; + const char* s = fl_input( "Author: ", "" ); + if ( s ) { + c->setAuthor( s ); + } } static void updateLinkCB(Fl_Widget* w, void* data) { - ControllerUI* c = (ControllerUI*)data; - - stringstream str; - str << "xdg-open "; - - // add http:// if its not in the string - std::string l = c->getLink(); - if ( ( l.find("http") ) == std::string::npos ) - str << " http://"; - - str << l; - - system( str.str().c_str() ); + ControllerUI* c = (ControllerUI*)data; + + stringstream str; + str << "xdg-open "; + + // add http:// if its not in the string + std::string l = c->getLink(); + if ( ( l.find("http") ) == std::string::npos ) + str << " http://"; + + str << l; + + system( str.str().c_str() ); } static void writeBindEnable(Fl_Widget* w, void* data) { - OptionsWindow* o = (OptionsWindow*) data; - //LUPPP_NOTE("MIDI bind mode"); - - Avtk::LightButton* l = (Avtk::LightButton*)w; - l->value( !l->value() ); - - int controllerID = -1; // waste? - EventControllerBindingEnable e( controllerID, l->value() ); - writeToDspRingbuffer( &e ); + OptionsWindow* o = (OptionsWindow*) data; + //LUPPP_NOTE("MIDI bind mode"); + + Avtk::LightButton* l = (Avtk::LightButton*)w; + l->value( !l->value() ); + + int controllerID = -1; // waste? + EventControllerBindingEnable e( controllerID, l->value() ); + writeToDspRingbuffer( &e ); } static void removeControllerCB(Fl_Widget* w, void* data) { - ControllerUI* self = (ControllerUI*)data; - - // Remove UI tab for that controller - // should return "tabs" from OptionsWindow - self->optionsWindow->tabs->remove( self->widget ); - self->optionsWindow->tabs->redraw(); - - // FIXME: confirm action here? - - //LUPPP_NOTE("Removing controllerID %i", self->controllerID ); - EventControllerInstanceRemove e( self->controllerID ); - writeToDspRingbuffer( &e ); - - delete self; + ControllerUI* self = (ControllerUI*)data; + + // Remove UI tab for that controller + // should return "tabs" from OptionsWindow + self->optionsWindow->tabs->remove( self->widget ); + self->optionsWindow->tabs->redraw(); + + // FIXME: confirm action here? + + //LUPPP_NOTE("Removing controllerID %i", self->controllerID ); + EventControllerInstanceRemove e( self->controllerID ); + writeToDspRingbuffer( &e ); + + delete self; } static void addNewController(Fl_Widget* w, void* ud) { - OptionsWindow* self = (OptionsWindow*)ud; - LUPPP_NOTE("%s","ADD Controller cb"); - - GenericMIDI* c = 0; - - const char* name = fl_input( "Controller name: ", "" ); - if ( name ) - { - c = new GenericMIDI( 0, name); - } - else - { - return; - } - - - if ( c->status() == Controller::CONTROLLER_OK ) - { - addControllerUiDsp( self, c ); - } - else - { - LUPPP_ERROR("Controller initialization failed!"); - } + OptionsWindow* self = (OptionsWindow*)ud; + LUPPP_NOTE("%s","ADD Controller cb"); + + GenericMIDI* c = 0; + + const char* name = fl_input( "Controller name: ", "" ); + if ( name ) { + c = new GenericMIDI( 0, name); + } else { + return; + } + + + if ( c->status() == Controller::CONTROLLER_OK ) { + addControllerUiDsp( self, c ); + } else { + LUPPP_ERROR("Controller initialization failed!"); + } } static void selectLoadController(Fl_Widget* w, void* data) { - OptionsWindow* self = (OptionsWindow*)data; - - // FIXME: refactor - string path; - Fl_Native_File_Chooser fnfc; - fnfc.title("Pick a controller definition"); - fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE); - fnfc.filter("Controllers\t*.ctlr"); - - stringstream s; - s << getenv("HOME") << "/.config/openAV/luppp/controllers/"; - fnfc.directory( s.str().c_str() ); // default directory to use - // Show native chooser - switch ( fnfc.show() ) { - case -1: /*printf("ERROR: %s\n", fnfc.errmsg());*/ break; // ERROR - case 1: /*printf("CANCEL\n"); */ break; // CANCEL - default: - //printf("Loading controller at %s\n", fnfc.filename()); - path = fnfc.filename(); - break; - } - - if ( strcmp( path.c_str(), "" ) == 0 ) - return; - - //LUPPP_NOTE("%s","ADD Controller cb"); - GenericMIDI* c = new GenericMIDI( path ); - - if ( c->status() == Controller::CONTROLLER_OK ) - { - addControllerUiDsp( self, c ); - } - else - { - LUPPP_ERROR("Controller initialization failed!"); - } + OptionsWindow* self = (OptionsWindow*)data; + + // FIXME: refactor + string path; + Fl_Native_File_Chooser fnfc; + fnfc.title("Pick a controller definition"); + fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE); + fnfc.filter("Controllers\t*.ctlr"); + + stringstream s; + s << getenv("HOME") << "/.config/openAV/luppp/controllers/"; + fnfc.directory( s.str().c_str() ); // default directory to use + // Show native chooser + switch ( fnfc.show() ) { + case -1: /*printf("ERROR: %s\n", fnfc.errmsg());*/ + break; // ERROR + case 1: /*printf("CANCEL\n"); */ + break; // CANCEL + default: + //printf("Loading controller at %s\n", fnfc.filename()); + path = fnfc.filename(); + break; + } + + if ( strcmp( path.c_str(), "" ) == 0 ) + return; + + //LUPPP_NOTE("%s","ADD Controller cb"); + GenericMIDI* c = new GenericMIDI( path ); + + if ( c->status() == Controller::CONTROLLER_OK ) { + addControllerUiDsp( self, c ); + } else { + LUPPP_ERROR("Controller initialization failed!"); + } } static void writeControllerFile(Fl_Widget* w, void* data) { - ControllerUI* c = (ControllerUI*)data; - - LUPPP_NOTE("Writing controller %li, %s ID %i .ctlr to disk", c, c->name.c_str(), c->controllerID ); - - // Set the Controller details in diskWriter, so it write it pretty - gui->getDiskWriter()->writeControllerInfo( CONTROLLER_NAME , c->name ); - gui->getDiskWriter()->writeControllerInfo( CONTROLLER_AUTHOR, c->getAuthor()); - gui->getDiskWriter()->writeControllerInfo( CONTROLLER_LINK , c->getLink() ); - - EventControllerInstanceGetToWrite e( c->controllerID ); - writeToDspRingbuffer( &e ); + ControllerUI* c = (ControllerUI*)data; + + LUPPP_NOTE("Writing controller %li, %s ID %i .ctlr to disk", c, c->name.c_str(), c->controllerID ); + + // Set the Controller details in diskWriter, so it write it pretty + gui->getDiskWriter()->writeControllerInfo( CONTROLLER_NAME , c->name ); + gui->getDiskWriter()->writeControllerInfo( CONTROLLER_AUTHOR, c->getAuthor()); + gui->getDiskWriter()->writeControllerInfo( CONTROLLER_LINK , c->getLink() ); + + EventControllerInstanceGetToWrite e( c->controllerID ); + writeToDspRingbuffer( &e ); } static void deleteBindingFromController(Fl_Widget* w, void* ud) { - ControllerUI* self = (ControllerUI*)ud; - stringstream s; - s << w->label(); - int tmp; - s >> tmp; - LUPPP_NOTE("CtlrID %i: Deleting binding with ID %i", self->controllerID, tmp ); - - EventControllerBindingRemove e( self->controllerID, tmp ); - writeToDspRingbuffer( &e ); - - // remove "this" widget (and its parent Pack) from the list of MIDI bindings: - self->bindingsPack->remove( w->parent() ); - self->bindingsPack->redraw(); - self->scroll->redraw(); + ControllerUI* self = (ControllerUI*)ud; + stringstream s; + s << w->label(); + int tmp; + s >> tmp; + LUPPP_NOTE("CtlrID %i: Deleting binding with ID %i", self->controllerID, tmp ); + + EventControllerBindingRemove e( self->controllerID, tmp ); + writeToDspRingbuffer( &e ); + + // remove "this" widget (and its parent Pack) from the list of MIDI bindings: + self->bindingsPack->remove( w->parent() ); + self->bindingsPack->redraw(); + self->scroll->redraw(); } ControllerUI::ControllerUI(int x, int y, int w, int h, std::string n, int ID) { - name = n; - - widget = new Fl_Group( x, y, w, h, name.c_str()); - { - // author / link - authorLabel = new Avtk::Button( x + 5, y + 5, 190, 25, "Author?" ); - linkLabel = new Avtk::Button( x + 7+ w/2, y + 5, 190, 25, "Link?" ); - - authorLabel->label("Author?"); - authorLabel->label("Link?"); - - authorLabel->callback( updateAuthorCB, this ); - linkLabel->callback( updateLinkCB, this ); - - // binding / target - targetLabelStat = new Fl_Box(x + 100,y + 32, 75, 25,"Target: "); - targetLabel = new Fl_Box(x + 140,y + 32, 200, 25,""); - bindEnable = new Avtk::LightButton(x + 5, y + 32, 100, 25, "Bind Enable"); - - writeControllerBtn = new Avtk::Button( x + 5, y + h - 27, 100, 25, "Save" ); - removeController = new Avtk::Button( x + 110, y + h - 27, 100, 25, "Remove"); - - scroll = new Fl_Scroll( x + 5, y + 82, 395, 265 ); - { - bindingsPack = new Fl_Pack( x + 5, y + 82, w - 15, 270-10); - bindingsPack->end(); - bindingsPack->spacing( 2 ); - bindingsPack->box(FL_DOWN_FRAME); - } - scroll->resizable( bindingsPack ); - scroll->box( FL_DOWN_FRAME ); - scroll->type( Fl_Scroll::VERTICAL_ALWAYS ); - scroll->end(); - - widget->resizable( scroll ); - } - widget->end(); - - widget->redraw(); - - // save the controller ID this ControllerUI represents - controllerID = ID; - LUPPP_NOTE("Controller %li ID on create %i", this, controllerID ); - - //ctlrButton->callback( selectLoadController ); - bindEnable->callback( writeBindEnable, this ); - removeController->callback( removeControllerCB, this ); - writeControllerBtn->callback( writeControllerFile, this ); + name = n; + + widget = new Fl_Group( x, y, w, h, name.c_str()); + { + // author / link + authorLabel = new Avtk::Button( x + 5, y + 5, 190, 25, "Author?" ); + linkLabel = new Avtk::Button( x + 7+ w/2, y + 5, 190, 25, "Link?" ); + + authorLabel->label("Author?"); + authorLabel->label("Link?"); + + authorLabel->callback( updateAuthorCB, this ); + linkLabel->callback( updateLinkCB, this ); + + // binding / target + targetLabelStat = new Fl_Box(x + 100,y + 32, 75, 25,"Target: "); + targetLabel = new Fl_Box(x + 140,y + 32, 200, 25,""); + bindEnable = new Avtk::LightButton(x + 5, y + 32, 100, 25, "Bind Enable"); + + writeControllerBtn = new Avtk::Button( x + 5, y + h - 27, 100, 25, "Save" ); + removeController = new Avtk::Button( x + 110, y + h - 27, 100, 25, "Remove"); + + scroll = new Fl_Scroll( x + 5, y + 82, 395, 265 ); + { + bindingsPack = new Fl_Pack( x + 5, y + 82, w - 15, 270-10); + bindingsPack->end(); + bindingsPack->spacing( 2 ); + bindingsPack->box(FL_DOWN_FRAME); + } + scroll->resizable( bindingsPack ); + scroll->box( FL_DOWN_FRAME ); + scroll->type( Fl_Scroll::VERTICAL_ALWAYS ); + scroll->end(); + + widget->resizable( scroll ); + } + widget->end(); + + widget->redraw(); + + // save the controller ID this ControllerUI represents + controllerID = ID; + LUPPP_NOTE("Controller %li ID on create %i", this, controllerID ); + + //ctlrButton->callback( selectLoadController ); + bindEnable->callback( writeBindEnable, this ); + removeController->callback( removeControllerCB, this ); + writeControllerBtn->callback( writeControllerFile, this ); } void OptionsWindow::setTarget(const char* n) { - for(unsigned int i = 0; i < controllers.size(); i++ ) - { - controllers.at(i)->setTarget( n ); - } + for(unsigned int i = 0; i < controllers.size(); i++ ) { + controllers.at(i)->setTarget( n ); + } } void ControllerUI::setTarget( const char* n ) { - target = n; - targetLabel->label( target.c_str() ); - targetLabel->redraw(); + target = n; + targetLabel->label( target.c_str() ); + targetLabel->redraw(); } void ControllerUI::setAuthor(std::string a) { - author = a; - authorLabel->label( author.c_str() ); - authorLabel->redraw(); + author = a; + authorLabel->label( author.c_str() ); + authorLabel->redraw(); } void ControllerUI::setLink(std::string e) { - link = e; - linkLabel->label( link.c_str() ); - linkLabel->redraw(); + link = e; + linkLabel->label( link.c_str() ); + linkLabel->redraw(); } void ControllerUI::setBindEnable( bool b ) { - bindEnable->value( b ); + bindEnable->value( b ); } void ControllerUI::addBinding( Binding* b ) { - if ( b->action != EVENT_NULL ) - { - // add individual bindings as they're made - const char* tmp = Event::getPrettyName( b->action ); - if ( !tmp ) - { + if ( b->action != EVENT_NULL ) { + // add individual bindings as they're made + const char* tmp = Event::getPrettyName( b->action ); + if ( !tmp ) { #ifdef DEBUG_MIDI - LUPPP_NOTE("new binding, action string returned NULL, action number %i ", b->action ); + LUPPP_NOTE("new binding, action string returned NULL, action number %i ", b->action ); #endif - return; - } - } - else - { - LUPPP_WARN("new binding, action: == EVENT_NULL" ); - return; - } - - // push the bindingID onto the vector - bindingID.push_back( b->ID ); - - // create a horizontal pack, add that to the bindingsPack - Fl_Pack* tmp = new Fl_Pack( 35, 35, 25, 25); - { - tmp->type( Fl_Pack::HORIZONTAL ); - tmp->spacing( 2 ); - - stringstream s; - - if ( b->action == MASTER_VOL ) - s << "Master Volume"; - else if ( false ) - s << "stuff"; - else - s << Event::getPrettyName( b->action ); - - - - if (b->track != -2) - s << " Track:" << b->track + 1; - - if (b->scene != -1) - s << " Scene:" << b->scene + 1; - - if ( b->send == Event::SEND_POSTFADER ) - s << " Post-fader Send"; - if ( b->send == Event::SEND_XSIDE ) - s << " Sidechain Crossfade"; - if ( b->send == Event::SEND_KEY ) - s << " Sidechain Key"; - - if ( b->active != -1) - { - if ( b->active == true ) - s << " On"; - if ( b->active == false ) - s << " Off"; - } - - // button to remove a binding, uses bindingsID vector to get unique number - stringstream id; - id << b->ID; - Fl_Button* but = new Fl_Button(35, 35, 25, 25, strdup(id.str().c_str() ) ); - but->callback( deleteBindingFromController, this ); - but->redraw(); - - Fl_Box* b = new Fl_Box(35, 35, 400, 25, strdup(s.str().c_str()) ); - b->align( FL_ALIGN_LEFT | FL_ALIGN_INSIDE ); - b->redraw(); - } - tmp->end(); - - // push the binding to the UI pack, *and* store its binding ID in the same - // array element in the bindingID vector. Used to remove bindings - bindingsPack->add( tmp ); - - bindingsPack->resize( bindingsPack->x(),bindingsPack->y(),bindingsPack->w(),bindingsPack->children() * 36 ); - bindingsPack->redraw(); - scroll->redraw(); - - //LUPPP_NOTE("binding size %i %i", bindingsPack->w(), bindingsPack->h() ); + return; + } + } else { + LUPPP_WARN("new binding, action: == EVENT_NULL" ); + return; + } + + // push the bindingID onto the vector + bindingID.push_back( b->ID ); + + // create a horizontal pack, add that to the bindingsPack + Fl_Pack* tmp = new Fl_Pack( 35, 35, 25, 25); + { + tmp->type( Fl_Pack::HORIZONTAL ); + tmp->spacing( 2 ); + + stringstream s; + + if ( b->action == MASTER_VOL ) + s << "Master Volume"; + else if ( false ) + s << "stuff"; + else + s << Event::getPrettyName( b->action ); + + + + if (b->track != -2) + s << " Track:" << b->track + 1; + + if (b->scene != -1) + s << " Scene:" << b->scene + 1; + + if ( b->send == Event::SEND_POSTFADER ) + s << " Post-fader Send"; + if ( b->send == Event::SEND_XSIDE ) + s << " Sidechain Crossfade"; + if ( b->send == Event::SEND_KEY ) + s << " Sidechain Key"; + + if ( b->active != -1) { + if ( b->active == true ) + s << " On"; + if ( b->active == false ) + s << " Off"; + } + + // button to remove a binding, uses bindingsID vector to get unique number + stringstream id; + id << b->ID; + Fl_Button* but = new Fl_Button(35, 35, 25, 25, strdup(id.str().c_str() ) ); + but->callback( deleteBindingFromController, this ); + but->redraw(); + + Fl_Box* b = new Fl_Box(35, 35, 400, 25, strdup(s.str().c_str()) ); + b->align( FL_ALIGN_LEFT | FL_ALIGN_INSIDE ); + b->redraw(); + } + tmp->end(); + + // push the binding to the UI pack, *and* store its binding ID in the same + // array element in the bindingID vector. Used to remove bindings + bindingsPack->add( tmp ); + + bindingsPack->resize( bindingsPack->x(),bindingsPack->y(),bindingsPack->w(),bindingsPack->children() * 36 ); + bindingsPack->redraw(); + scroll->redraw(); + + //LUPPP_NOTE("binding size %i %i", bindingsPack->w(), bindingsPack->h() ); } void ControllerUI::addBindings( GenericMIDI* c ) { - std::vector bindingVector= c->getMidiToAction(); - - for(unsigned int i = 0; i < bindingVector.size(); i++ ) - { - addBinding( bindingVector.at(i) ); - } + std::vector bindingVector= c->getMidiToAction(); + + for(unsigned int i = 0; i < bindingVector.size(); i++ ) { + addBinding( bindingVector.at(i) ); + } } ControllerUI::~ControllerUI() { - - // free all binding resources here: - - - delete authorLabel; - delete linkLabel; - - delete targetLabel; - delete targetLabelStat; - delete bindEnable; - delete removeController; - delete writeControllerBtn; + + // free all binding resources here: + + + delete authorLabel; + delete linkLabel; + + delete targetLabel; + delete targetLabelStat; + delete bindEnable; + delete removeController; + delete writeControllerBtn; } OptionsWindow::OptionsWindow() { - window = new Fl_Double_Window(400,400,"Options"); - - window->set_non_modal(); - - tabs = new Fl_Tabs(0, 0, 400, 400); - - window->resizable( tabs ); - - int x, y, w, h; - tabs->client_area( x, y, w, h, 25 ); - - addGroup = new Fl_Group(x,y,w,h,"Add"); - { - newButton = new Avtk::Button( x+2, y+2, w-4, 30, "New Generic MIDI"); - loadButton = new Avtk::Button( x+2, y+2+32, w-4, 30, "Load Generic MIDI"); - } - addGroup->end(); - tabs->end(); - - newButton ->callback( addNewController, this ); - loadButton->callback( selectLoadController, this ); - - window->end(); + window = new Fl_Double_Window(400,400,"Options"); + + window->set_non_modal(); + + tabs = new Fl_Tabs(0, 0, 400, 400); + + window->resizable( tabs ); + + int x, y, w, h; + tabs->client_area( x, y, w, h, 25 ); + + addGroup = new Fl_Group(x,y,w,h,"Add"); + { + newButton = new Avtk::Button( x+2, y+2, w-4, 30, "New Generic MIDI"); + loadButton = new Avtk::Button( x+2, y+2+32, w-4, 30, "Load Generic MIDI"); + } + addGroup->end(); + tabs->end(); + + newButton ->callback( addNewController, this ); + loadButton->callback( selectLoadController, this ); + + window->end(); } OptionsWindow::~OptionsWindow() { - delete newButton; - delete loadButton; - delete addGroup; - delete tabs; - delete window; + delete newButton; + delete loadButton; + delete addGroup; + delete tabs; + delete window; } void OptionsWindow::show() { - window->show(); + window->show(); } void OptionsWindow::hide() { - window->hide(); + window->hide(); } ControllerUI* OptionsWindow::getControllerUI(int id) { - for(unsigned int i = 0; i < controllers.size(); i++ ) - { - if ( controllers.at(i)->controllerID == id ) - { - return controllers.at(i); - } - } - - // error: controller not found! - return 0; + for(unsigned int i = 0; i < controllers.size(); i++ ) { + if ( controllers.at(i)->controllerID == id ) { + return controllers.at(i); + } + } + + // error: controller not found! + return 0; } diff --git a/src/goptions.hxx b/src/goptions.hxx index 8e1adc1..d8bc0ba 100644 --- a/src/goptions.hxx +++ b/src/goptions.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -43,78 +43,84 @@ class OptionsWindow; /// contains UI elements to represent one controller class ControllerUI { - public: - ControllerUI( int x, int y, int w, int h, std::string name,int id); - ~ControllerUI(); - - void setAuthor(std::string author); - void setLink (std::string link ); - std::string getAuthor(){return author;} - std::string getLink(){return link;} - - void setTarget(const char* n); - void setBindEnable( bool b ); - - void addBinding( Binding* b ); - void addBindings( GenericMIDI* c ); - - // the ControllerID this UI class represents - int controllerID; - - // for adding to GOptions tabs - Fl_Group* widget; - - std::string name; - - OptionsWindow* optionsWindow; - - // public to redraw when removing from static - Fl_Scroll* scroll; - Fl_Pack* bindingsPack; - - private: - // bindings - std::string target; - std::string author; - std::string link; - - Avtk::Button* authorLabel; - Avtk::Button* linkLabel; - - std::vector bindingID; - - Fl_Box* targetLabel; - Fl_Box* targetLabelStat; - //Avtk::Bindings* bindings; - Avtk::LightButton* bindEnable; - Avtk::Button* removeController; - Avtk::Button* writeControllerBtn; +public: + ControllerUI( int x, int y, int w, int h, std::string name,int id); + ~ControllerUI(); + + void setAuthor(std::string author); + void setLink (std::string link ); + std::string getAuthor() + { + return author; + } + std::string getLink() + { + return link; + } + + void setTarget(const char* n); + void setBindEnable( bool b ); + + void addBinding( Binding* b ); + void addBindings( GenericMIDI* c ); + + // the ControllerID this UI class represents + int controllerID; + + // for adding to GOptions tabs + Fl_Group* widget; + + std::string name; + + OptionsWindow* optionsWindow; + + // public to redraw when removing from static + Fl_Scroll* scroll; + Fl_Pack* bindingsPack; + +private: + // bindings + std::string target; + std::string author; + std::string link; + + Avtk::Button* authorLabel; + Avtk::Button* linkLabel; + + std::vector bindingID; + + Fl_Box* targetLabel; + Fl_Box* targetLabelStat; + //Avtk::Bindings* bindings; + Avtk::LightButton* bindEnable; + Avtk::Button* removeController; + Avtk::Button* writeControllerBtn; }; class OptionsWindow { - public: - OptionsWindow(); - ~OptionsWindow(); - - void show(); - void hide(); - - void setTarget(const char* n); - ControllerUI* getControllerUI(int id); - - // public for static methods only - Fl_Tabs* tabs; - std::vector controllers; - Fl_Group* addGroup; +public: + OptionsWindow(); + ~OptionsWindow(); + + void show(); + void hide(); + + void setTarget(const char* n); + ControllerUI* getControllerUI(int id); + + // public for static methods only + Fl_Tabs* tabs; + std::vector controllers; + Fl_Group* addGroup; #ifdef BUILD_TESTS - int runTests(); + int runTests(); #endif - - private: - Fl_Double_Window* window; - Avtk::Button* newButton; - Avtk::Button* loadButton; + +private: + Fl_Double_Window* window; + Avtk::Button* newButton; + Avtk::Button* loadButton; }; #endif // LUPPP_OPTIONS_H diff --git a/src/gridlogic.cxx b/src/gridlogic.cxx index 3eb9370..721723b 100644 --- a/src/gridlogic.cxx +++ b/src/gridlogic.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -26,269 +26,245 @@ extern Jack* jack; const char* GridLogic::StateString[8] = { - "Empty", - "Playing", - "Play queued", - "Stopped", - "Stop queued", - "Recording", - "Record queued" + "Empty", + "Playing", + "Play queued", + "Stopped", + "Stop queued", + "Recording", + "Record queued" }; GridLogic::GridLogic() { - sceneLaunch = 0; - - sampleTrackScene = false; - selectedTrack = 0; - selectedScene = 0; + sceneLaunch = 0; + + sampleTrackScene = false; + selectedTrack = 0; + selectedScene = 0; } void GridLogic::selectedTrackSceneEvent(bool p) { - if ( p ) - { - pressed( selectedTrack, selectedScene ); - } - else - { - released( selectedTrack, selectedScene ); - } + if ( p ) { + pressed( selectedTrack, selectedScene ); + } else { + released( selectedTrack, selectedScene ); + } } void GridLogic::setSelectTrackScene(bool b) { - char tmp[40]; - sprintf( tmp, "Select track enable %i", int(b) ); - EventGuiPrint e( tmp ); - writeToGuiRingbuffer( &e ); - sampleTrackScene = b; + char tmp[40]; + sprintf( tmp, "Select track enable %i", int(b) ); + EventGuiPrint e( tmp ); + writeToGuiRingbuffer( &e ); + sampleTrackScene = b; } int GridLogic::getLaunchedScene() { - return sceneLaunch; + return sceneLaunch; } int GridLogic::getSelectedTrack() { - return selectedTrack; + return selectedTrack; } int GridLogic::getSelectedScene() { - return selectedScene; + return selectedScene; } void GridLogic::setSelectedTrack(int t) { - selectedTrack = t; + selectedTrack = t; } void GridLogic::setSelectedScene(int s) { - selectedScene = s; + selectedScene = s; } void GridLogic::launchScene( int scene ) { - for(unsigned int t = 0; t < NTRACKS; t++ ) - { - for(int s = 0; s < NSCENES; s++ ) - { - LooperClip* lc = jack->getLooper( t )->getClip( s ); - if ( s == scene ) - { - lc->queuePlay(); - jack->getControllerUpdater()->setSceneState( t, s, lc->getState() ); - } - else - { - if ( lc->playing() ) - { - lc->queueStop(); - jack->getControllerUpdater()->setSceneState( t, s, lc->getState() ); - } - else if ( lc->somethingQueued() ) - { - lc->neutralize(); - jack->getControllerUpdater()->setSceneState( t, s, lc->getState() ); - } - } - } - } - - sceneLaunch = scene; - - jack->getControllerUpdater()->launchScene( scene ); + for(unsigned int t = 0; t < NTRACKS; t++ ) { + for(int s = 0; s < NSCENES; s++ ) { + LooperClip* lc = jack->getLooper( t )->getClip( s ); + if ( s == scene ) { + lc->queuePlay(); + jack->getControllerUpdater()->setSceneState( t, s, lc->getState() ); + } else { + if ( lc->playing() ) { + lc->queueStop(); + jack->getControllerUpdater()->setSceneState( t, s, lc->getState() ); + } else if ( lc->somethingQueued() ) { + lc->neutralize(); + jack->getControllerUpdater()->setSceneState( t, s, lc->getState() ); + } + } + } + } + + sceneLaunch = scene; + + jack->getControllerUpdater()->launchScene( scene ); } void GridLogic::specialScene(int t, int s) { - if ( t < 0 ) t = 0; - if ( t >= NTRACKS ) t = NTRACKS-1; - - if ( s < 0 ) s = 0; - if ( s >= NSCENES ) s = NSCENES-1; - - selectedTrack = t; - selectedScene = s; - - // update UI's - jack->getControllerUpdater()->specialScene( t, s ); + if ( t < 0 ) t = 0; + if ( t >= NTRACKS ) t = NTRACKS-1; + + if ( s < 0 ) s = 0; + if ( s >= NSCENES ) s = NSCENES-1; + + selectedTrack = t; + selectedScene = s; + + // update UI's + jack->getControllerUpdater()->specialScene( t, s ); } void GridLogic::pressed( int track, int scene ) { - if ( sampleTrackScene ) - { - specialScene( track, scene ); - - // don't act on grid press! - return; - } - - - // get the clip, do the "press" action based on current state. - LooperClip* lc = jack->getLooper( track )->getClip( scene ); - TrackOutput* to = jack->getTrackOutput( track ); - GridLogic::State s = lc->getState(); + if ( sampleTrackScene ) { + specialScene( track, scene ); + + // don't act on grid press! + return; + } + + + // get the clip, do the "press" action based on current state. + LooperClip* lc = jack->getLooper( track )->getClip( scene ); + TrackOutput* to = jack->getTrackOutput( track ); + GridLogic::State s = lc->getState(); #ifdef DEBUG_CLIP - printf("GridLogic::pressed() before press state = %s\n", StateString[ int(scene) ] ); -#endif - - if ( to->recordArm() && !lc->recording() ) - { - lc->queueRecord(); - to->recordArm(false); - jack->getControllerUpdater()->recordArm( track, false ); - } - else - { - if ( s == STATE_EMPTY ) - lc->queueRecord(); - - if ( s == STATE_STOPPED ) - { - // hack, stop all scenes, then launch proper one - for( int i = 0; i < NTRACKS; i++ ) - { - LooperClip* ilc = jack->getLooper( track )->getClip( i ); - if ( ilc->playing() ) - { - ilc->queueStop(); - } - } - - lc->queuePlay(); - } - - if ( s == STATE_PLAYING ) - lc->queueStop(); - - if ( s == STATE_RECORDING ) - lc->queuePlay(); - - if ( s == STATE_PLAY_QUEUED ) - lc->queueStop(); - - if ( s == STATE_STOP_QUEUED ) - lc->queuePlay(); - - // don't re-trigger if already playing! - if ( s == STATE_STOP_QUEUED && lc->playing() ) - lc->neutralize(); - - if ( s == STATE_RECORD_QUEUED ) - lc->neutralize(); - } - - // check state of new clip, if getQueuePlay() == true, queueStop() all other scenes - //if ( lc->getQueuePlay() ) - { - for(int i = 0; i < NSCENES; i++) - { - // exclude current scene - if ( i != scene ) - { - //LUPPP_NOTE("netralizing & qStop on scene %i due to press on %i", i, scene ); - LooperClip* ilc = jack->getLooper( track )->getClip( i ); - - ilc->neutralize(); - ilc->queueStop(); - jack->getControllerUpdater()->setSceneState(track, i, ilc->getState() ); - } - } - } - - - s = lc->getState(); -#ifdef DEBUG_CLIP - printf("GridLogic::pressed() after press state = %s\n", StateString[ int(s) ] ); + printf("GridLogic::pressed() before press state = %s\n", StateString[ int(scene) ] ); #endif - jack->getControllerUpdater()->setSceneState(track, scene, s ); + + if ( to->recordArm() && !lc->recording() ) { + lc->queueRecord(); + to->recordArm(false); + jack->getControllerUpdater()->recordArm( track, false ); + } else { + if ( s == STATE_EMPTY ) + lc->queueRecord(); + + if ( s == STATE_STOPPED ) { + // hack, stop all scenes, then launch proper one + for( int i = 0; i < NTRACKS; i++ ) { + LooperClip* ilc = jack->getLooper( track )->getClip( i ); + if ( ilc->playing() ) { + ilc->queueStop(); + } + } + + lc->queuePlay(); + } + + if ( s == STATE_PLAYING ) + lc->queueStop(); + + if ( s == STATE_RECORDING ) + lc->queuePlay(); + + if ( s == STATE_PLAY_QUEUED ) + lc->queueStop(); + + if ( s == STATE_STOP_QUEUED ) + lc->queuePlay(); + + // don't re-trigger if already playing! + if ( s == STATE_STOP_QUEUED && lc->playing() ) + lc->neutralize(); + + if ( s == STATE_RECORD_QUEUED ) + lc->neutralize(); + } + + // check state of new clip, if getQueuePlay() == true, queueStop() all other scenes + //if ( lc->getQueuePlay() ) + { + for(int i = 0; i < NSCENES; i++) { + // exclude current scene + if ( i != scene ) { + //LUPPP_NOTE("netralizing & qStop on scene %i due to press on %i", i, scene ); + LooperClip* ilc = jack->getLooper( track )->getClip( i ); + + ilc->neutralize(); + ilc->queueStop(); + jack->getControllerUpdater()->setSceneState(track, i, ilc->getState() ); + } + } + } + + + s = lc->getState(); +#ifdef DEBUG_CLIP + printf("GridLogic::pressed() after press state = %s\n", StateString[ int(s) ] ); +#endif + jack->getControllerUpdater()->setSceneState(track, scene, s ); } void GridLogic::released( int track, int scene ) { - GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState(); - jack->getControllerUpdater()->setSceneState(track, scene, s ); + GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState(); + jack->getControllerUpdater()->setSceneState(track, scene, s ); } void GridLogic::load(int track, int scene, AudioBuffer* ab) { - jack->getLooper( track )->getClip( scene )->load( ab ); - GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState(); - jack->getControllerUpdater()->setSceneState(track, scene, s ); + jack->getLooper( track )->getClip( scene )->load( ab ); + GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState(); + jack->getControllerUpdater()->setSceneState(track, scene, s ); } void GridLogic::updateState() { - //printf("GridLogic::updateState() stub" ); - for(int t = 0; t < NTRACKS; t++) - { - for(int s = 0; s < NSCENES; s++) - { - GridLogic::State st = jack->getLooper( t )->getClip( s )->getState(); - EventGuiPrint e( GridLogic::StateString[st] ); - writeToGuiRingbuffer( &e ); - jack->getControllerUpdater()->setSceneState(t, s, st ); - } - } + //printf("GridLogic::updateState() stub" ); + for(int t = 0; t < NTRACKS; t++) { + for(int s = 0; s < NSCENES; s++) { + GridLogic::State st = jack->getLooper( t )->getClip( s )->getState(); + EventGuiPrint e( GridLogic::StateString[st] ); + writeToGuiRingbuffer( &e ); + jack->getControllerUpdater()->setSceneState(t, s, st ); + } + } } void GridLogic::bar() { #ifdef DEBUG_CLIP - EventGuiPrint e( "GridLogic::bar()" ); - //writeToGuiRingbuffer( &e ); + EventGuiPrint e( "GridLogic::bar()" ); + //writeToGuiRingbuffer( &e ); #endif - - /// iterate over all clips, if they're set to QUEUED, set to the next state - for( int i = 0; i < NTRACKS*NSCENES; i++ ) - { - int track = i / NSCENES; - int scene = i - track * NSCENES; - jack->getLooper( track )->getClip(scene)->bar(); + + /// iterate over all clips, if they're set to QUEUED, set to the next state + for( int i = 0; i < NTRACKS*NSCENES; i++ ) { + int track = i / NSCENES; + int scene = i - track * NSCENES; + jack->getLooper( track )->getClip(scene)->bar(); #ifdef DEBUG_CLIP - GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState(); - if ( s != STATE_EMPTY ) - { - //printf("%i, %i:after bar() state = %s\n", track, scene, StateString[ int(s) ] ); - } + GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState(); + if ( s != STATE_EMPTY ) { + //printf("%i, %i:after bar() state = %s\n", track, scene, StateString[ int(s) ] ); + } #endif - } + } } void GridLogic::beat() { - - + + } diff --git a/src/gridlogic.hxx b/src/gridlogic.hxx index bbf9dfe..691bfc8 100644 --- a/src/gridlogic.hxx +++ b/src/gridlogic.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -29,82 +29,85 @@ class AudioBuffer; * separtated from the Looper class so it can be repurposed by different * controllers and input devices. The UI and eg. APC / Launchpad all have a * similar grid style interface: the logic is implemented here once. - * + * * The class sends Looper messages to change its state, thus abstracting away * the details of the Looper control, and exposing its functionality using a * convinient API. - * + * * When the state of a block changes, it will update the state of the grid on * the controller. - * + * * It inherits from TimeObserver so it can change the state of the clip on the * bar / beat. **/ class GridLogic : public TimeObserver { - public: - /// possible states of each square. Public so Controller subclasses can - /// determine the state of the square - enum State { - STATE_EMPTY = 0, - STATE_PLAYING, - STATE_PLAY_QUEUED, - STATE_STOPPED, - STATE_STOP_QUEUED, - STATE_RECORDING, - STATE_RECORD_QUEUED, - }; - - GridLogic(); - ~GridLogic(){}; - - /// button press / click event - void pressed( int track, int scene ); - - /// button release / click-release event - void released( int track, int scene ); - - /// master controls, launches a horizontal scene with one event - void launchScene( int scene ); - int getCurrentScene(){return sceneLaunch;} - int getLaunchedScene(); - - /// selected track functions - void setSelectTrackScene(bool b); - void setSelectedTrack(int t); - void setSelectedScene(int s); - int getSelectedTrack(); - int getSelectedScene(); - - void selectedTrackSceneEvent(bool pressed); - - void specialScene(int t, int s); - - /// GUI load event - void load(int track, int scene, AudioBuffer* ab); - - /// resend entire grid state to controllers - void updateState(); - - /// time functions, not for use by Controller subclasses - void bar(); - void beat(); - - /// for debug purposes: use static_cast(GridLogic::State) to access - static const char* StateString[8]; - +public: + /// possible states of each square. Public so Controller subclasses can + /// determine the state of the square + enum State { + STATE_EMPTY = 0, + STATE_PLAYING, + STATE_PLAY_QUEUED, + STATE_STOPPED, + STATE_STOP_QUEUED, + STATE_RECORDING, + STATE_RECORD_QUEUED, + }; + + GridLogic(); + ~GridLogic() {}; + + /// button press / click event + void pressed( int track, int scene ); + + /// button release / click-release event + void released( int track, int scene ); + + /// master controls, launches a horizontal scene with one event + void launchScene( int scene ); + int getCurrentScene() + { + return sceneLaunch; + } + int getLaunchedScene(); + + /// selected track functions + void setSelectTrackScene(bool b); + void setSelectedTrack(int t); + void setSelectedScene(int s); + int getSelectedTrack(); + int getSelectedScene(); + + void selectedTrackSceneEvent(bool pressed); + + void specialScene(int t, int s); + + /// GUI load event + void load(int track, int scene, AudioBuffer* ab); + + /// resend entire grid state to controllers + void updateState(); + + /// time functions, not for use by Controller subclasses + void bar(); + void beat(); + + /// for debug purposes: use static_cast(GridLogic::State) to access + static const char* StateString[8]; + #ifdef BUILD_TESTS - int runTests(); + int runTests(); #endif - private: - /// holds last scene launch - int sceneLaunch; - - /// holds selected track / scene for special clip - bool sampleTrackScene; // turn on to have selected clip, press event acted on - int selectedTrack; - int selectedScene; +private: + /// holds last scene launch + int sceneLaunch; + + /// holds selected track / scene for special clip + bool sampleTrackScene; // turn on to have selected clip, press event acted on + int selectedTrack; + int selectedScene; }; diff --git a/src/gtrack.cxx b/src/gtrack.cxx index 751b599..a13d3c8 100644 --- a/src/gtrack.cxx +++ b/src/gtrack.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -33,199 +33,217 @@ static void gtrack_jacksendactivate_cb(Fl_Widget* w,void *data); GTrack::GTrack(int x, int y, int w, int h, const char* l ) : - Fl_Group(x, y, w, h), - bg( x, y , w, h, l ), - - radial( x+5, y+ 26, 100, 100, ""), - - clipSel(x + 5, y + 26 + 102, 100, 294,""), - jackSendBox(x+5, y+422, 100, 45, ""), - jackSendDial(x+21, y+422+8, 30,30, ""), - jackSendActivate(x+66, y+422+11, 36,25, "FX"), - volBox(x+5, y+422+50, 100, 172, ""), - volume(x+66, y +425+50, 36, 166, ""), + Fl_Group(x, y, w, h), + bg( x, y , w, h, l ), + + radial( x+5, y+ 26, 100, 100, ""), + + clipSel(x + 5, y + 26 + 102, 100, 294,""), + jackSendBox(x+5, y+422, 100, 45, ""), + jackSendDial(x+21, y+422+8, 30,30, ""), + jackSendActivate(x+66, y+422+11, 36,25, "FX"), + volBox(x+5, y+422+50, 100, 172, ""), + volume(x+66, y +425+50, 36, 166, ""), - - - sendDial (x+21, y +430 + 50, 30, 30, ""), - sendActive (x+11, y +430 + 82, 50, 25, "Snd"), - - xsideDial (x+21, y +430 + 69+50, 30, 30, ""), - keyActive (x+11, y +430 + 151, 50, 25, "Key"), - - recordActive (x+11, y +430 + 182, 50, 25, "XRec") + + + sendDial (x+21, y +430 + 50, 30, 30, ""), + sendActive (x+11, y +430 + 82, 50, 25, "Snd"), + + xsideDial (x+21, y +430 + 69+50, 30, 30, ""), + keyActive (x+11, y +430 + 151, 50, 25, "Key"), + + recordActive (x+11, y +430 + 182, 50, 25, "XRec") { - ID = privateID++; - - clipSel.setID( ID ); - - sendDial.callback( gtrack_sendDial_cb, this ); - sendActive.setColor( 0, 1.0, 0.0 ); - sendActive.callback( gtrack_send_cb, this ); - - xsideDial.callback( gtrack_xsideDial_cb, this ); - xsideDial.align( FL_ALIGN_BOTTOM ); - keyActive.callback( gtrack_key_cb, this ); - keyActive.setColor( 0, 0.6, 1 ); - - - recordActive.setColor( 1, 0.0, 0.0 ); - recordActive.callback( gtrack_record_cb, this ); - - volume.callback( gtrack_vol_cb, this ); + ID = privateID++; - jackSendActivate.setColor( 1, 1, 0 ); - jackSendActivate.callback(gtrack_jacksendactivate_cb,this); - jackSendDial.align(FL_ALIGN_INSIDE); - jackSendDial.callback(gtrack_jacksend_cb,this); - jackSendDial.value(1.0); - //volBox.color( fl_rgb_color( 0,0,0 ) ); - - end(); // close the group + clipSel.setID( ID ); + + sendDial.callback( gtrack_sendDial_cb, this ); + sendActive.setColor( 0, 1.0, 0.0 ); + sendActive.callback( gtrack_send_cb, this ); + + xsideDial.callback( gtrack_xsideDial_cb, this ); + xsideDial.align( FL_ALIGN_BOTTOM ); + keyActive.callback( gtrack_key_cb, this ); + keyActive.setColor( 0, 0.6, 1 ); + + + recordActive.setColor( 1, 0.0, 0.0 ); + recordActive.callback( gtrack_record_cb, this ); + + volume.callback( gtrack_vol_cb, this ); + + jackSendActivate.setColor( 1, 1, 0 ); + jackSendActivate.callback(gtrack_jacksendactivate_cb,this); + jackSendDial.align(FL_ALIGN_INSIDE); + jackSendDial.callback(gtrack_jacksend_cb,this); + jackSendDial.value(1.0); + //volBox.color( fl_rgb_color( 0,0,0 ) ); + + end(); // close the group } -float GTrack::getSend(){return sendDial.value(); } -float GTrack::getXSide(){return xsideDial.value(); } +float GTrack::getSend() +{ + return sendDial.value(); +} +float GTrack::getXSide() +{ + return xsideDial.value(); +} -bool GTrack::getSendActive (){return sendActive.value(); } -bool GTrack::getKeyActive (){return keyActive.value(); } -bool GTrack::getRecordActive(){return recordActive.value(); } +bool GTrack::getSendActive () +{ + return sendActive.value(); +} +bool GTrack::getKeyActive () +{ + return keyActive.value(); +} +bool GTrack::getRecordActive() +{ + return recordActive.value(); +} -void GTrack::setSend(float s){ sendDial.value( s ); } -void GTrack::setXSide(float s){ xsideDial.value( s ); } +void GTrack::setSend(float s) +{ + sendDial.value( s ); +} +void GTrack::setXSide(float s) +{ + xsideDial.value( s ); +} -void GTrack::setSendActive(bool a){ sendActive.value( a ); } -void GTrack::setKeyActive(bool a){ keyActive.value( a ); } -void GTrack::setRecordActive(bool a){ recordActive.value( a ); } +void GTrack::setSendActive(bool a) +{ + sendActive.value( a ); +} +void GTrack::setKeyActive(bool a) +{ + keyActive.value( a ); +} +void GTrack::setRecordActive(bool a) +{ + recordActive.value( a ); +} void GTrack::setJackSend(float s) { - jackSendDial.value(s); + jackSendDial.value(s); } void GTrack::setJackSendActivate(bool a) { - jackSendActivate.value(a); + jackSendActivate.value(a); } float GTrack::getJackSend() { - return jackSendDial.value(); + return jackSendDial.value(); } bool GTrack::getJackSendActivate() { - return jackSendActivate.value(); + return jackSendActivate.value(); } void gtrack_sendDial_cb(Fl_Widget *w, void *data) { - GTrack* track = (GTrack*) data; - EventTrackSend e( track->ID, SEND_POSTFADER, ((Avtk::Dial*)w)->value() ); - writeToDspRingbuffer( &e ); - //printf("track %i reverb send %f\n", track->ID, ((Avtk::Dial*)w)->value() ); + GTrack* track = (GTrack*) data; + EventTrackSend e( track->ID, SEND_POSTFADER, ((Avtk::Dial*)w)->value() ); + writeToDspRingbuffer( &e ); + //printf("track %i reverb send %f\n", track->ID, ((Avtk::Dial*)w)->value() ); } void gtrack_key_cb(Fl_Widget *w, void *data) { - GTrack* track = (GTrack*) data; - Avtk::LightButton* d = (Avtk::LightButton*)w; - bool b = d->value(); - if ( b < 0.5 ) - { - EventTrackSendActive e( track->ID, SEND_KEY, true ); - writeToDspRingbuffer( &e ); - } - else - { - EventTrackSendActive e( track->ID, SEND_KEY, false ); - writeToDspRingbuffer( &e ); - } - //printf("track %i post send %s\n", track->ID, b ? "off" : "on" ); + GTrack* track = (GTrack*) data; + Avtk::LightButton* d = (Avtk::LightButton*)w; + bool b = d->value(); + if ( b < 0.5 ) { + EventTrackSendActive e( track->ID, SEND_KEY, true ); + writeToDspRingbuffer( &e ); + } else { + EventTrackSendActive e( track->ID, SEND_KEY, false ); + writeToDspRingbuffer( &e ); + } + //printf("track %i post send %s\n", track->ID, b ? "off" : "on" ); } void gtrack_xsideDial_cb(Fl_Widget *w, void *data) { - GTrack* track = (GTrack*) data; - EventTrackSend e( track->ID, SEND_XSIDE, ((Avtk::Dial*)w)->value() ); - writeToDspRingbuffer( &e ); - //printf("track %i side send %f\n", track->ID, ((Avtk::Dial*)w)->value() ); + GTrack* track = (GTrack*) data; + EventTrackSend e( track->ID, SEND_XSIDE, ((Avtk::Dial*)w)->value() ); + writeToDspRingbuffer( &e ); + //printf("track %i side send %f\n", track->ID, ((Avtk::Dial*)w)->value() ); } void gtrack_vol_cb(Fl_Widget *w, void *data) { - GTrack* track = (GTrack*) data; - EventTrackVol e( track->ID, ((Avtk::Volume*)w)->value() ); - writeToDspRingbuffer( &e ); - //printf("track %i vol %f\n", track->ID, ((Avtk::Dial*)w)->value() ); + GTrack* track = (GTrack*) data; + EventTrackVol e( track->ID, ((Avtk::Volume*)w)->value() ); + writeToDspRingbuffer( &e ); + //printf("track %i vol %f\n", track->ID, ((Avtk::Dial*)w)->value() ); } void gtrack_send_cb(Fl_Widget *w, void *data) { - GTrack* track = (GTrack*) data; - Avtk::LightButton* d = (Avtk::LightButton*)w; - bool b = d->value(); - d->value( !b ); - if ( b < 0.5 ) - { - EventTrackSendActive e( track->ID, SEND_POSTFADER, 1.0f ); - writeToDspRingbuffer( &e ); - } - else - { - EventTrackSendActive e( track->ID, SEND_POSTFADER, 0.0f ); - writeToDspRingbuffer( &e ); - } - //printf("track %i reverb send %s\n", track->ID, b ? "true" : "false" ); + GTrack* track = (GTrack*) data; + Avtk::LightButton* d = (Avtk::LightButton*)w; + bool b = d->value(); + d->value( !b ); + if ( b < 0.5 ) { + EventTrackSendActive e( track->ID, SEND_POSTFADER, 1.0f ); + writeToDspRingbuffer( &e ); + } else { + EventTrackSendActive e( track->ID, SEND_POSTFADER, 0.0f ); + writeToDspRingbuffer( &e ); + } + //printf("track %i reverb send %s\n", track->ID, b ? "true" : "false" ); } void gtrack_jacksend_cb(Fl_Widget *w, void *data) { - GTrack* track = (GTrack*) data; - Avtk::Dial* d = (Avtk::Dial*)w; - float v = d->value(); - EventTrackJackSend ev(track->ID,v); - writeToDspRingbuffer(&ev); + GTrack* track = (GTrack*) data; + Avtk::Dial* d = (Avtk::Dial*)w; + float v = d->value(); + EventTrackJackSend ev(track->ID,v); + writeToDspRingbuffer(&ev); - //printf("track %i reverb send %s\n", track->ID, b ? "true" : "false" ); + //printf("track %i reverb send %s\n", track->ID, b ? "true" : "false" ); } void gtrack_record_cb(Fl_Widget *w, void *data) { - GTrack* track = (GTrack*) data; - Avtk::LightButton* d = (Avtk::LightButton*)w; - bool b = d->value(); - if ( b < 0.5 ) - { - EventTrackRecordArm e( track->ID, 1.0f ); - writeToDspRingbuffer( &e ); - } - else - { - EventTrackRecordArm e( track->ID, 0.0f ); - writeToDspRingbuffer( &e ); - } - //printf("track %i record Arm %s\n", track->ID, b ? "off" : "on" ); + GTrack* track = (GTrack*) data; + Avtk::LightButton* d = (Avtk::LightButton*)w; + bool b = d->value(); + if ( b < 0.5 ) { + EventTrackRecordArm e( track->ID, 1.0f ); + writeToDspRingbuffer( &e ); + } else { + EventTrackRecordArm e( track->ID, 0.0f ); + writeToDspRingbuffer( &e ); + } + //printf("track %i record Arm %s\n", track->ID, b ? "off" : "on" ); } void gtrack_jacksendactivate_cb(Fl_Widget* w,void *data) { - GTrack* track = (GTrack*) data; - Avtk::LightButton* d = (Avtk::LightButton*)w; - bool b=d->value(); - // d->value(!b); - if ( b < 0.5 ) - { - EventTrackJackSendActivate e( track->ID, 1.0f ); - writeToDspRingbuffer( &e ); - } - else - { - EventTrackJackSendActivate e( track->ID, 0.0f ); - writeToDspRingbuffer( &e ); - } + GTrack* track = (GTrack*) data; + Avtk::LightButton* d = (Avtk::LightButton*)w; + bool b=d->value(); + // d->value(!b); + if ( b < 0.5 ) { + EventTrackJackSendActivate e( track->ID, 1.0f ); + writeToDspRingbuffer( &e ); + } else { + EventTrackJackSendActivate e( track->ID, 0.0f ); + writeToDspRingbuffer( &e ); + } } diff --git a/src/gtrack.hxx b/src/gtrack.hxx index a1ac8c1..8b59630 100644 --- a/src/gtrack.hxx +++ b/src/gtrack.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -45,63 +45,72 @@ using namespace std; class GTrack : public Fl_Group { - public: - - Avtk::Volume* getVolume(){return &volume;} - Avtk::RadialStatus* getRadialStatus(){return &radial;} - Avtk::ClipSelector* getClipSelector(){return &clipSel;} - - GTrack(int x, int y, int w, int h, const char* l = 0 ); - - - // getters - float getSend(); - float getXSide(); - - bool getSendActive(); - bool getKeyActive(); - bool getRecordActive(); - - // setters - void setSend(float s); - void setXSide(float s); - - void setSendActive(bool a); - void setKeyActive(bool a); - void setRecordActive(bool a); - - void setJackSend(float s); - void setJackSendActivate(bool a); - - int ID; - - Avtk::Background bg; - - Avtk::RadialStatus radial; - - Avtk::ClipSelector clipSel; +public: - Avtk::Box volBox; - - Avtk::Volume volume; - - float getJackSend(); - bool getJackSendActivate(); + Avtk::Volume* getVolume() + { + return &volume; + } + Avtk::RadialStatus* getRadialStatus() + { + return &radial; + } + Avtk::ClipSelector* getClipSelector() + { + return &clipSel; + } + + GTrack(int x, int y, int w, int h, const char* l = 0 ); + + + // getters + float getSend(); + float getXSide(); + + bool getSendActive(); + bool getKeyActive(); + bool getRecordActive(); + + // setters + void setSend(float s); + void setXSide(float s); + + void setSendActive(bool a); + void setKeyActive(bool a); + void setRecordActive(bool a); + + void setJackSend(float s); + void setJackSendActivate(bool a); + + int ID; + + Avtk::Background bg; + + Avtk::RadialStatus radial; + + Avtk::ClipSelector clipSel; + + Avtk::Box volBox; + + Avtk::Volume volume; + + float getJackSend(); + bool getJackSendActivate(); private: - Avtk::Box jackSendBox; - Avtk::Dial jackSendDial; - Avtk::LightButton jackSendActivate; + Avtk::Box jackSendBox; + Avtk::Dial jackSendDial; + Avtk::LightButton jackSendActivate; - Avtk::Dial sendDial; - Avtk::LightButton sendActive; - - Avtk::Dial xsideDial; - Avtk::LightButton keyActive; - - Avtk::LightButton recordActive; - - - static int privateID; + Avtk::Dial sendDial; + Avtk::LightButton sendActive; + + Avtk::Dial xsideDial; + Avtk::LightButton keyActive; + + Avtk::LightButton recordActive; + + + static int privateID; }; #endif // LUPPP_G_TRACK_H diff --git a/src/gui.cxx b/src/gui.cxx index b652880..da5f80f 100644 --- a/src/gui.cxx +++ b/src/gui.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -47,7 +47,7 @@ extern Jack* jack; #include // include the header.c file in the planning dir: -// its the GIMP .c export of the LUPPP header image +// its the GIMP .c export of the LUPPP header image #include "../planning/header.c" #include "../planning/luppp.c" #include "../planning/bg.c" @@ -59,275 +59,262 @@ extern int signalHanlderInt; static void signalChecker(void*) { - if ( signalHanlderInt ) - { - // Luppp recieved either a SIGTERM or SIGINT: quit gracefully - gui->quit(); - } - else - { - Fl::repeat_timeout( 0.1, (Fl_Timeout_Handler)&signalChecker, 0 ); - } + if ( signalHanlderInt ) { + // Luppp recieved either a SIGTERM or SIGINT: quit gracefully + gui->quit(); + } else { + Fl::repeat_timeout( 0.1, (Fl_Timeout_Handler)&signalChecker, 0 ); + } } void close_cb(Fl_Widget*o, void*) { - if ( (Fl::event() == FL_KEYDOWN || Fl::event() == FL_SHORTCUT) && Fl::event_key() == FL_Escape) - { - // on excape, as about quitting - gui->askQuit(); - } - else - { - gui->quit(); - } + if ( (Fl::event() == FL_KEYDOWN || Fl::event() == FL_SHORTCUT) && Fl::event_key() == FL_Escape) { + // on excape, as about quitting + gui->askQuit(); + } else { + gui->quit(); + } } static void gui_static_read_rb(void* inst) { - handleGuiEvents(); - - Fl::repeat_timeout( 1 / 30.f, &gui_static_read_rb, inst); + handleGuiEvents(); + + Fl::repeat_timeout( 1 / 30.f, &gui_static_read_rb, inst); } static void gui_static_nsm_cb(void* inst) { - nsm_check_nowait( gui->getNsm() ); - Fl::repeat_timeout( 1 / 30.f, &gui_static_nsm_cb, inst); + nsm_check_nowait( gui->getNsm() ); + Fl::repeat_timeout( 1 / 30.f, &gui_static_nsm_cb, inst); } void option_controller_cb(Fl_Widget*,void* data) { - LUPPP_NOTE("%s","Controller cb"); + LUPPP_NOTE("%s","Controller cb"); } static void gui_header_callback(Fl_Widget *w, void *data) { - Gui* g = (Gui*)data; - if ( Fl::event_x() > 130 ) - { - return; - } - - Fl_Menu_Item rclick_menu[] = - { - { "New Session" }, - { "Load Session" }, - { "Save Session ", 0, 0, 0, FL_MENU_DIVIDER}, - { "Setup", 0, 0, 0, FL_MENU_DIVIDER}, - { "Quit" }, - { 0 } - }; - - // check for NSM running, deactivate new / save / load if yes - if ( gui->getNsm() ) - { - rclick_menu[1].deactivate(); - rclick_menu[2].deactivate(); - } - - Fl_Menu_Item *m = (Fl_Menu_Item*) rclick_menu->popup( 10, 38, 0, 0, 0); - - if ( !m ) - { - return; - } - else if ( strcmp(m->label(), "New Session") == 0 ) - { - int yes = fl_choice("Start a new session?","Cancel","Yes",0); - if ( yes ) - { - gui->reset(); - } - } - else if ( strcmp(m->label(), "Load Session") == 0 ) - { - - std::string tmp; - { - // Create the file chooser, and show it - Fl_File_Chooser chooser(gui->getProjectsDir().c_str(), - "*", - Fl_File_Chooser::DIRECTORY, - "Load Session"); - chooser.show(); + Gui* g = (Gui*)data; + if ( Fl::event_x() > 130 ) { + return; + } - // Block until user picks something. - // (The other way to do this is to use a callback()) - // - while(chooser.shown()) - { Fl::wait(); } + Fl_Menu_Item rclick_menu[] = { + { "New Session" }, + { "Load Session" }, + { "Save Session ", 0, 0, 0, FL_MENU_DIVIDER}, + { "Setup", 0, 0, 0, FL_MENU_DIVIDER}, + { "Quit" }, + { 0 } + }; - // User hit cancel? - if ( chooser.value() == NULL ) - { fprintf(stderr, "(User hit 'Cancel')\n"); return; } - - // Print what the user picked - fprintf(stderr, "--------------------\n"); - fprintf(stderr, "DIRECTORY: '%s'\n", chooser.directory()); - fprintf(stderr, " VALUE: '%s'\n", chooser.value()); - fprintf(stderr, " COUNT: %d files selected\n", chooser.count()); - - tmp = chooser.value(); - chooser.hide(); - - /* - // try to make the Load window dissapear *now* - Fl::check(); - Fl::flush(); - Fl::wait(0); - */ - } - - LUPPP_NOTE( "Loading session from dir %s", tmp.c_str() ); - - // clear the current session: just do a state reset - EventStateReset e; - writeToDspRingbuffer( &e ); - - int sess = gui->getDiskReader()->readSession( tmp ); - if ( sess != LUPPP_RETURN_OK ) - LUPPP_ERROR( "Error loading session" ); - - return; - } - else if ( strcmp(m->label(), "Save Session ") == 0 ) - { - const char* name = fl_input( "Save session as", gui->getDiskWriter()->getLastSaveName().c_str() ); - if ( name ) - { - gui->getDiskWriter()->initialize( gui->getProjectsDir().c_str(), name ); - LUPPP_NOTE("%s %s","Saving session as ", name ); - EventStateSave e; - writeToDspRingbuffer( &e ); - } - } - else if ( strcmp(m->label(), "Setup") == 0 ) - { - g->getOptionsWindow()->show(); - } - else if ( strcmp(m->label(), "Quit") == 0 ) - { - g->askQuit(); - } + // check for NSM running, deactivate new / save / load if yes + if ( gui->getNsm() ) { + rclick_menu[1].deactivate(); + rclick_menu[2].deactivate(); + } + + Fl_Menu_Item *m = (Fl_Menu_Item*) rclick_menu->popup( 10, 38, 0, 0, 0); + + if ( !m ) { + return; + } else if ( strcmp(m->label(), "New Session") == 0 ) { + int yes = fl_choice("Start a new session?","Cancel","Yes",0); + if ( yes ) { + gui->reset(); + } + } else if ( strcmp(m->label(), "Load Session") == 0 ) { + + std::string tmp; + { + // Create the file chooser, and show it + Fl_File_Chooser chooser(gui->getProjectsDir().c_str(), + "*", + Fl_File_Chooser::DIRECTORY, + "Load Session"); + chooser.show(); + + // Block until user picks something. + // (The other way to do this is to use a callback()) + // + while(chooser.shown()) { + Fl::wait(); + } + + // User hit cancel? + if ( chooser.value() == NULL ) { + fprintf(stderr, "(User hit 'Cancel')\n"); + return; + } + + // Print what the user picked + fprintf(stderr, "--------------------\n"); + fprintf(stderr, "DIRECTORY: '%s'\n", chooser.directory()); + fprintf(stderr, " VALUE: '%s'\n", chooser.value()); + fprintf(stderr, " COUNT: %d files selected\n", chooser.count()); + + tmp = chooser.value(); + chooser.hide(); + + /* + // try to make the Load window dissapear *now* + Fl::check(); + Fl::flush(); + Fl::wait(0); + */ + } + + LUPPP_NOTE( "Loading session from dir %s", tmp.c_str() ); + + // clear the current session: just do a state reset + EventStateReset e; + writeToDspRingbuffer( &e ); + + int sess = gui->getDiskReader()->readSession( tmp ); + if ( sess != LUPPP_RETURN_OK ) + LUPPP_ERROR( "Error loading session" ); + + return; + } else if ( strcmp(m->label(), "Save Session ") == 0 ) { + const char* name = fl_input( "Save session as", gui->getDiskWriter()->getLastSaveName().c_str() ); + if ( name ) { + gui->getDiskWriter()->initialize( gui->getProjectsDir().c_str(), name ); + LUPPP_NOTE("%s %s","Saving session as ", name ); + EventStateSave e; + writeToDspRingbuffer( &e ); + } + } else if ( strcmp(m->label(), "Setup") == 0 ) { + g->getOptionsWindow()->show(); + } else if ( strcmp(m->label(), "Quit") == 0 ) { + g->askQuit(); + } } OptionsWindow* Gui::getOptionsWindow() { - return optionWindow; + return optionWindow; } void Gui::selectLoadController(Fl_Widget* w, void*) { - // FIXME: refactor - string path; - Fl_Native_File_Chooser fnfc; - fnfc.title("Pick a controller definition"); - fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE); - fnfc.filter("Controllers\t*.ctlr"); - fnfc.directory( getenv("HOME") ); // default directory to use - // Show native chooser - switch ( fnfc.show() ) { - case -1: printf("ERROR: %s\n", fnfc.errmsg()); break; // ERROR - case 1: printf("CANCEL\n"); break; // CANCEL - default: printf("Loading controller at %s\n", fnfc.filename()); - path = fnfc.filename(); - break; - } - - if ( strcmp( path.c_str(), "" ) == 0 ) - return; - - LUPPP_NOTE("%s","ADD Controller cb"); - Controller* c = new GenericMIDI( path ); - - if ( c->status() == Controller::CONTROLLER_OK ) - { - EventControllerInstance e(c); - writeToDspRingbuffer( &e ); - } - else - { - LUPPP_ERROR("Controller initialization failed!"); - } - + // FIXME: refactor + string path; + Fl_Native_File_Chooser fnfc; + fnfc.title("Pick a controller definition"); + fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE); + fnfc.filter("Controllers\t*.ctlr"); + fnfc.directory( getenv("HOME") ); // default directory to use + // Show native chooser + switch ( fnfc.show() ) { + case -1: + printf("ERROR: %s\n", fnfc.errmsg()); + break; // ERROR + case 1: + printf("CANCEL\n"); + break; // CANCEL + default: + printf("Loading controller at %s\n", fnfc.filename()); + path = fnfc.filename(); + break; + } + + if ( strcmp( path.c_str(), "" ) == 0 ) + return; + + LUPPP_NOTE("%s","ADD Controller cb"); + Controller* c = new GenericMIDI( path ); + + if ( c->status() == Controller::CONTROLLER_OK ) { + EventControllerInstance e(c); + writeToDspRingbuffer( &e ); + } else { + LUPPP_ERROR("Controller initialization failed!"); + } + } void Gui::setProjectsDir(string dir) { - lupppProjectsDir=dir; + lupppProjectsDir=dir; } string Gui::getProjectsDir() { - return lupppProjectsDir; + return lupppProjectsDir; } void Gui::selectSaveSample( int track, int scene ) { - EventStateSaveBuffer e; - e.track = track, - e.scene = scene, - writeToDspRingbuffer( &e ); + EventStateSaveBuffer e; + e.track = track, + e.scene = scene, + writeToDspRingbuffer( &e ); } char * Gui::selectSavePath() { - string path; - Fl_Native_File_Chooser fnfc; - fnfc.title("Save filename?"); - fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); - - std::string defLoadPath = gui->getDiskReader()->getLastLoadedSamplePath(); - fnfc.directory( defLoadPath.c_str() ); // default directory to use - - // Show native chooser - switch ( fnfc.show() ) { - case -1: /*printf("ERROR: %s\n", fnfc.errmsg()); */ break; // ERROR - case 1: /*(printf("CANCEL\n"); */ break; // CANCEL - default: /*printf("Loading directory: %s\n", fnfc.filename()); */ - path = fnfc.filename(); - break; - } - - if ( strcmp( path.c_str(), "" ) == 0 ) - return 0; + string path; + Fl_Native_File_Chooser fnfc; + fnfc.title("Save filename?"); + fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); - return strdup(path.c_str()); + std::string defLoadPath = gui->getDiskReader()->getLastLoadedSamplePath(); + fnfc.directory( defLoadPath.c_str() ); // default directory to use + + // Show native chooser + switch ( fnfc.show() ) { + case -1: /*printf("ERROR: %s\n", fnfc.errmsg()); */ + break; // ERROR + case 1: /*(printf("CANCEL\n"); */ + break; // CANCEL + default: /*printf("Loading directory: %s\n", fnfc.filename()); */ + path = fnfc.filename(); + break; + } + + if ( strcmp( path.c_str(), "" ) == 0 ) + return 0; + + return strdup(path.c_str()); } void Gui::selectLoadSample( int track, int scene ) { - // FIXME: refactor - string path; - Fl_Native_File_Chooser fnfc; - fnfc.title("Pick a file"); - fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE); - - fnfc.filter("Audio\t{*.aiff,*.wav,*.flac,*.ogg}"); - - std::string defLoadPath = gui->getDiskReader()->getLastLoadedSamplePath(); - fnfc.directory( defLoadPath.c_str() ); // default directory to use - - // Show native chooser - switch ( fnfc.show() ) { - case -1: /*printf("ERROR: %s\n", fnfc.errmsg()); */ break; // ERROR - case 1: /*(printf("CANCEL\n"); */ break; // CANCEL - default: /*printf("Loading directory: %s\n", fnfc.filename()); */ - path = fnfc.filename(); - break; - } - - if ( strcmp( path.c_str(), "" ) == 0 ) - return; - - // diskReader loads sample, and parses for sample.cfg - diskReader->loadSample( track, scene, path ); + // FIXME: refactor + string path; + Fl_Native_File_Chooser fnfc; + fnfc.title("Pick a file"); + fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE); + + fnfc.filter("Audio\t{*.aiff,*.wav,*.flac,*.ogg}"); + + std::string defLoadPath = gui->getDiskReader()->getLastLoadedSamplePath(); + fnfc.directory( defLoadPath.c_str() ); // default directory to use + + // Show native chooser + switch ( fnfc.show() ) { + case -1: /*printf("ERROR: %s\n", fnfc.errmsg()); */ + break; // ERROR + case 1: /*(printf("CANCEL\n"); */ + break; // CANCEL + default: /*printf("Loading directory: %s\n", fnfc.filename()); */ + path = fnfc.filename(); + break; + } + + if ( strcmp( path.c_str(), "" ) == 0 ) + return; + + // diskReader loads sample, and parses for sample.cfg + diskReader->loadSample( track, scene, path ); } AudioEditor* Gui::getAudioEditor() { - return audioEditor; + return audioEditor; } @@ -337,389 +324,605 @@ static int cb_nsm_open (const char *name, char **out_msg, void *userdata ) { - LUPPP_NOTE("NSM: Open, displayname: %s", display_name ); - - Jack::setup( client_id ); - - // we *must* get the samplerate here: loading files depends on this information! - gui->samplerate = jack->getSamplerate(); - - stringstream loadPath; - loadPath << name; - - // load the NSM provided directory - gui->getDiskReader()->readSession( loadPath.str() ); - - // initialize the disk-writer to the same directory: - // we *always* overwrite the old save file when using NSM - gui->getDiskWriter()->initialize( name, display_name ); - - return ERR_OK; + LUPPP_NOTE("NSM: Open, displayname: %s", display_name ); + + Jack::setup( client_id ); + + // we *must* get the samplerate here: loading files depends on this information! + gui->samplerate = jack->getSamplerate(); + + stringstream loadPath; + loadPath << name; + + // load the NSM provided directory + gui->getDiskReader()->readSession( loadPath.str() ); + + // initialize the disk-writer to the same directory: + // we *always* overwrite the old save file when using NSM + gui->getDiskWriter()->initialize( name, display_name ); + + return ERR_OK; } static int cb_nsm_save ( char **out_msg, void *userdata ) { - LUPPP_NOTE("NSM: saving..." ); - - // disk-writer already initialized to the right directory, so just write! - EventStateSave e; - writeToDspRingbuffer( &e ); - - return 0; + LUPPP_NOTE("NSM: saving..." ); + + // disk-writer already initialized to the right directory, so just write! + EventStateSave e; + writeToDspRingbuffer( &e ); + + return 0; } Gui::Gui(const char* argZero) : - samplerate( 0 ), - window(1110,700), - enablePerTrackOutput(false), - diskReader( new DiskReader() ), - diskWriter( new DiskWriter() ) + samplerate( 0 ), + window(1110,700), + enablePerTrackOutput(false), + diskReader( new DiskReader() ), + diskWriter( new DiskWriter() ) { - LUPPP_NOTE( "%s", "Gui()" ); - - gui = this; - - // setup window icon before calling show() - fl_open_display(); - Fl_Pixmap* pixmap = new Fl_Pixmap( icon_xpm ); - Fl_Offscreen lupppIcon = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), - pixmap->w(), pixmap->h(), fl_visual->depth); - fl_gc = XCreateGC(fl_display, lupppIcon, 0, 0); - fl_begin_offscreen(lupppIcon); - pixmap->draw(0,0); - fl_end_offscreen(); - delete pixmap; - XFreeGC(fl_display, fl_gc); - - window.icon( (void*)lupppIcon ); - - // setup callback to signalChecker() - Fl::add_timeout( 0.1, (Fl_Timeout_Handler)&signalChecker, 0 ); - - // add keyboard shortcut handler - Fl::add_handler( keyboardHandler ); - - //window.resize( false ); - window.xclass("luppp"); - window.iconlabel("luppp"); - - window.color(FL_BLACK); - window.label("Luppp"); - window.callback( close_cb, 0 ); - window.size_range( 800, 450 ); - - window.color( fl_rgb_color (7,7,7) ); - - /* - tooltipLabel = new Fl_2(130, 25, 500, 20, ""); - tooltipLabel->labelcolor( FL_LIGHT2 ); - tooltipLabel->color( FL_DARK2 ); - tooltipLabel->hide(); - //tooltipLabel->align( FL_ALIGN_TOP_LEFT ); - */ - - // horizontal no-resize-images group - Fl_Group* headerImages = new Fl_Group( 0, 0, 1110, 650, "header"); - { - //Fl_Pack* vHeaderImages = new Fl_Pack( 0, 0, 1110, 650, "verticalHeader"); - { - Avtk::Image* bgImage = new Avtk::Image(0,0,1920,36,"bg"); - bgImage->setPixbuf( bgImg.pixel_data, 4 ); - - Avtk::Image* lupppImage = new Avtk::Image(0,0,130,36,"luppp"); - lupppImage->setPixbuf( lupppImg.pixel_data, 4 ); - lupppImage->callback( gui_header_callback, this ); - - Avtk::Image* headerImage = new Avtk::Image( window.w() - 270,0,270,36,"header"); - headerImage->setPixbuf( header.pixel_data, 4 ); - headerImage->stickToRight = true; - - - Fl_Box* box = new Fl_Box( 130, 0, 400, 36 ); - headerImages->resizable( box ); - - //vHeaderImages->set_vertical(); - //vHeaderImages->relayout(); - } - //vHeaderImages->end(); - - Fl_Box* box = new Fl_Box( 130, 0, 400, 36 ); - headerImages->resizable( box ); - } - headerImages->end(); - - // create a new "Group" with all Luppp GUI contents, for resizing - lupppGroup = new Fl_Group( 0, 0, 1110, 700, "Luppp"); - { - int i = 0; - for (; i < NTRACKS; i++ ) - { - stringstream s; - s << "Track " << i+1; - tracks.push_back( new GTrack(8 + i * 118, 40, 110, 650, s.str().c_str() ) ); - } - master = new GMasterTrack(8 + i * 118, 40, 150, 650, "Master"); - } - lupppGroup->end(); - - window.resizable( lupppGroup ); - - window.end(); - - specialTrack = 0; - specialScene = 0; - tracks.at( specialTrack )->getClipSelector()->setSpecial( specialScene ); - - - optionWindow = new OptionsWindow(); - - // Create AudioEditor after window.end() has been called - audioEditor = new AudioEditor(); - - // read settings file using diskreader, and setup controllers etc - int prefs = diskReader->loadPreferences(); - if ( prefs != LUPPP_RETURN_OK ) - { - LUPPP_WARN("No preferences loaded, using defaults."); - } - else - { - LUPPP_NOTE("Loaded preferences"); - } - - // NSM stuff - nsm = 0; - const char *nsm_url = getenv( "NSM_URL" ); - if ( nsm_url ) - { - nsm = nsm_new(); - - nsm_set_open_callback( nsm, cb_nsm_open, this ); - nsm_set_save_callback( nsm, cb_nsm_save, this ); - - if ( nsm_init( nsm, nsm_url ) == 0 ) - { - nsm_send_announce( nsm, "Luppp", "", argZero ); - LUPPP_NOTE("Announcing to NSM"); - } - else - { - nsm_free( nsm ); - nsm = 0; - } - } - else - { - LUPPP_NOTE("No session management in use"); - } + LUPPP_NOTE( "%s", "Gui()" ); + + gui = this; + + // setup window icon before calling show() + fl_open_display(); + Fl_Pixmap* pixmap = new Fl_Pixmap( icon_xpm ); + Fl_Offscreen lupppIcon = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), + pixmap->w(), pixmap->h(), fl_visual->depth); + fl_gc = XCreateGC(fl_display, lupppIcon, 0, 0); + fl_begin_offscreen(lupppIcon); + pixmap->draw(0,0); + fl_end_offscreen(); + delete pixmap; + XFreeGC(fl_display, fl_gc); + + window.icon( (void*)lupppIcon ); + + // setup callback to signalChecker() + Fl::add_timeout( 0.1, (Fl_Timeout_Handler)&signalChecker, 0 ); + + // add keyboard shortcut handler + Fl::add_handler( keyboardHandler ); + + //window.resize( false ); + window.xclass("luppp"); + window.iconlabel("luppp"); + + window.color(FL_BLACK); + window.label("Luppp"); + window.callback( close_cb, 0 ); + window.size_range( 800, 450 ); + + window.color( fl_rgb_color (7,7,7) ); + + /* + tooltipLabel = new Fl_2(130, 25, 500, 20, ""); + tooltipLabel->labelcolor( FL_LIGHT2 ); + tooltipLabel->color( FL_DARK2 ); + tooltipLabel->hide(); + //tooltipLabel->align( FL_ALIGN_TOP_LEFT ); + */ + + // horizontal no-resize-images group + Fl_Group* headerImages = new Fl_Group( 0, 0, 1110, 650, "header"); + { + //Fl_Pack* vHeaderImages = new Fl_Pack( 0, 0, 1110, 650, "verticalHeader"); + { + Avtk::Image* bgImage = new Avtk::Image(0,0,1920,36,"bg"); + bgImage->setPixbuf( bgImg.pixel_data, 4 ); + + Avtk::Image* lupppImage = new Avtk::Image(0,0,130,36,"luppp"); + lupppImage->setPixbuf( lupppImg.pixel_data, 4 ); + lupppImage->callback( gui_header_callback, this ); + + Avtk::Image* headerImage = new Avtk::Image( window.w() - 270,0,270,36,"header"); + headerImage->setPixbuf( header.pixel_data, 4 ); + headerImage->stickToRight = true; + + + Fl_Box* box = new Fl_Box( 130, 0, 400, 36 ); + headerImages->resizable( box ); + + //vHeaderImages->set_vertical(); + //vHeaderImages->relayout(); + } + //vHeaderImages->end(); + + Fl_Box* box = new Fl_Box( 130, 0, 400, 36 ); + headerImages->resizable( box ); + } + headerImages->end(); + + // create a new "Group" with all Luppp GUI contents, for resizing + lupppGroup = new Fl_Group( 0, 0, 1110, 700, "Luppp"); + { + int i = 0; + for (; i < NTRACKS; i++ ) { + stringstream s; + s << "Track " << i+1; + tracks.push_back( new GTrack(8 + i * 118, 40, 110, 650, s.str().c_str() ) ); + } + master = new GMasterTrack(8 + i * 118, 40, 150, 650, "Master"); + } + lupppGroup->end(); + + window.resizable( lupppGroup ); + + window.end(); + + specialTrack = 0; + specialScene = 0; + tracks.at( specialTrack )->getClipSelector()->setSpecial( specialScene ); + + + optionWindow = new OptionsWindow(); + + // Create AudioEditor after window.end() has been called + audioEditor = new AudioEditor(); + + // read settings file using diskreader, and setup controllers etc + int prefs = diskReader->loadPreferences(); + if ( prefs != LUPPP_RETURN_OK ) { + LUPPP_WARN("No preferences loaded, using defaults."); + } else { + LUPPP_NOTE("Loaded preferences"); + } + + // NSM stuff + nsm = 0; + const char *nsm_url = getenv( "NSM_URL" ); + if ( nsm_url ) { + nsm = nsm_new(); + + nsm_set_open_callback( nsm, cb_nsm_open, this ); + nsm_set_save_callback( nsm, cb_nsm_save, this ); + + if ( nsm_init( nsm, nsm_url ) == 0 ) { + nsm_send_announce( nsm, "Luppp", "", argZero ); + LUPPP_NOTE("Announcing to NSM"); + } else { + nsm_free( nsm ); + nsm = 0; + } + } else { + LUPPP_NOTE("No session management in use"); + } } void Gui::addMidiControllerToSetup(std::string c) { - controllerVector.push_back( c ); + controllerVector.push_back( c ); } void Gui::setupMidiControllers() { - for(unsigned int i = 0; i < controllerVector.size(); i++) - { - GenericMIDI* c = new GenericMIDI( controllerVector.at(i).c_str() ); - if ( c ) - { - EventControllerInstance e(c); - writeToDspRingbuffer( &e ); - } - } + for(unsigned int i = 0; i < controllerVector.size(); i++) { + GenericMIDI* c = new GenericMIDI( controllerVector.at(i).c_str() ); + if ( c ) { + EventControllerInstance e(c); + writeToDspRingbuffer( &e ); + } + } } void Gui::reset() { - // signal to DSP to reset state - EventStateReset ev; - writeToDspRingbuffer( &ev ); - - // clear UI state: track names / scene names - for(unsigned int i = 0; i < NTRACKS; i++) - { - stringstream s; - s << "Track " << i+1; - tracks.at(i)->bg.setLabel( s.str().c_str() ); - - for(unsigned int s = 0; s < NSCENES; s++) - { - tracks.at(i)->getClipSelector()->clipName( s, "" ); - } - } - - for(unsigned int i = 0; i < NSCENES; i++) - { - stringstream s; - s << "Scene " << i+1; - master->getClipSelector()->clipName( i, s.str() ); - } - + // signal to DSP to reset state + EventStateReset ev; + writeToDspRingbuffer( &ev ); + + // clear UI state: track names / scene names + for(unsigned int i = 0; i < NTRACKS; i++) { + stringstream s; + s << "Track " << i+1; + tracks.at(i)->bg.setLabel( s.str().c_str() ); + + for(unsigned int s = 0; s < NSCENES; s++) { + tracks.at(i)->getClipSelector()->clipName( s, "" ); + } + } + + for(unsigned int i = 0; i < NSCENES; i++) { + stringstream s; + s << "Scene " << i+1; + master->getClipSelector()->clipName( i, s.str() ); + } + } GTrack* Gui::getTrack(int id) { - return tracks.at(id); + return tracks.at(id); } int Gui::show() { - window.show(); - - gui_static_read_rb( this ); - - // only launch NSM check callbacks if NSM is setup - if ( gui->getNsm() ) - gui_static_nsm_cb( this ); - - return Fl::run(); + window.show(); + + gui_static_read_rb( this ); + + // only launch NSM check callbacks if NSM is setup + if ( gui->getNsm() ) + gui_static_nsm_cb( this ); + + return Fl::run(); } int Gui::quit() { - // close JACK client - jack->quit(); - - // ensure the subwindows are closed - optionWindow->hide(); - audioEditor->hide(); - - // quit main window, causing program termination - window.hide(); - - return 0; + // close JACK client + jack->quit(); + + // ensure the subwindows are closed + optionWindow->hide(); + audioEditor->hide(); + + // quit main window, causing program termination + window.hide(); + + return 0; } void Gui::askQuit() { - int quit = fl_choice("Really Quit?","Cancel","Quit",0); - if ( quit ) // JUST QUIT - { - gui->quit(); - } + int quit = fl_choice("Really Quit?","Cancel","Quit",0); + if ( quit ) { // JUST QUIT + gui->quit(); + } } int Gui::keyboardHandler(int event) { - - switch( event ) - { - case FL_SHORTCUT: - if ( strcmp( Fl::event_text(), "1" ) == 0 ) { EventGridEvent e( 0, 0, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "2" ) == 0 ) { EventGridEvent e( 1, 0, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "3" ) == 0 ) { EventGridEvent e( 2, 0, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "4" ) == 0 ) { EventGridEvent e( 3, 0, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "5" ) == 0 ) { EventGridEvent e( 4, 0, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "6" ) == 0 ) { EventGridEvent e( 5, 0, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "7" ) == 0 ) { EventGridEvent e( 6, 0, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "8" ) == 0 ) { EventGridEvent e( 7, 0, true ); writeToDspRingbuffer( &e ); return 1; } - - else if( strcmp( Fl::event_text(), "!" ) == 0 ) { EventGridState e( 0, 0, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "@" ) == 0 ) { EventGridState e( 1, 0, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "\"" ) == 0 ) { EventGridState e( 1, 0, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } // for UK/Ireland keyboards - else if( strcmp( Fl::event_text(), "#" ) == 0 ) { EventGridState e( 2, 0, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "£" ) == 0 ) { EventGridState e( 2, 0, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } // for UK/Ireland keyboards - else if( strcmp( Fl::event_text(), "$" ) == 0 ) { EventGridState e( 3, 0, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "%" ) == 0 ) { EventGridState e( 4, 0, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "^" ) == 0 ) { EventGridState e( 5, 0, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "&" ) == 0 ) { EventGridState e( 6, 0, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "*" ) == 0 ) { EventGridState e( 7, 0, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "q" ) == 0 ) { EventGridEvent e( 0, 1, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "w" ) == 0 ) { EventGridEvent e( 1, 1, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "e" ) == 0 ) { EventGridEvent e( 2, 1, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "r" ) == 0 ) { EventGridEvent e( 3, 1, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "t" ) == 0 ) { EventGridEvent e( 4, 1, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "y" ) == 0 ) { EventGridEvent e( 5, 1, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "u" ) == 0 ) { EventGridEvent e( 6, 1, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "i" ) == 0 ) { EventGridEvent e( 7, 1, true ); writeToDspRingbuffer( &e ); return 1; } - - else if( strcmp( Fl::event_text(), "Q" ) == 0 ) { EventGridState e( 0, 1, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "W" ) == 0 ) { EventGridState e( 1, 1, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "E" ) == 0 ) { EventGridState e( 2, 1, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "R" ) == 0 ) { EventGridState e( 3, 1, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "T" ) == 0 ) { EventGridState e( 4, 1, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "Y" ) == 0 ) { EventGridState e( 5, 1, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "U" ) == 0 ) { EventGridState e( 6, 1, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "I" ) == 0 ) { EventGridState e( 7, 1, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - - else if( strcmp( Fl::event_text(), "a" ) == 0 ) { EventGridEvent e( 0, 2, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "s" ) == 0 ) { EventGridEvent e( 1, 2, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "d" ) == 0 ) { EventGridEvent e( 2, 2, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "f" ) == 0 ) { EventGridEvent e( 3, 2, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "g" ) == 0 ) { EventGridEvent e( 4, 2, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "h" ) == 0 ) { EventGridEvent e( 5, 2, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "j" ) == 0 ) { EventGridEvent e( 6, 2, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "k" ) == 0 ) { EventGridEvent e( 7, 2, true ); writeToDspRingbuffer( &e ); return 1; } - - else if( strcmp( Fl::event_text(), "A" ) == 0 ) { EventGridState e( 0, 2, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "S" ) == 0 ) { EventGridState e( 1, 2, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "D" ) == 0 ) { EventGridState e( 2, 2, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "F" ) == 0 ) { EventGridState e( 3, 2, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "G" ) == 0 ) { EventGridState e( 4, 2, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "H" ) == 0 ) { EventGridState e( 5, 2, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "J" ) == 0 ) { EventGridState e( 6, 2, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "K" ) == 0 ) { EventGridState e( 7, 2, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - - else if( strcmp( Fl::event_text(), "z" ) == 0 ) { EventGridEvent e( 0, 3, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "x" ) == 0 ) { EventGridEvent e( 1, 3, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "c" ) == 0 ) { EventGridEvent e( 2, 3, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "v" ) == 0 ) { EventGridEvent e( 3, 3, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "b" ) == 0 ) { EventGridEvent e( 4, 3, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "n" ) == 0 ) { EventGridEvent e( 5, 3, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "m" ) == 0 ) { EventGridEvent e( 6, 3, true ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "," ) == 0 ) { EventGridEvent e( 7, 3, true ); writeToDspRingbuffer( &e ); return 1; } - - else if( strcmp( Fl::event_text(), "Z" ) == 0 ) { EventGridState e( 0, 3, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "X" ) == 0 ) { EventGridState e( 1, 3, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "C" ) == 0 ) { EventGridState e( 2, 3, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "V" ) == 0 ) { EventGridState e( 3, 3, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "B" ) == 0 ) { EventGridState e( 4, 3, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "N" ) == 0 ) { EventGridState e( 5, 3, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "M" ) == 0 ) { EventGridState e( 6, 3, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "<" ) == 0 ) { EventGridState e( 7, 3, GridLogic::STATE_EMPTY ); writeToDspRingbuffer( &e ); return 1; } - - else if( strcmp( Fl::event_text(), "9" ) == 0 ) { EventGridLaunchScene e( 0 ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "o" ) == 0 ) { EventGridLaunchScene e( 1 ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "l" ) == 0 ) { EventGridLaunchScene e( 2 ); writeToDspRingbuffer( &e ); return 1; } - else if( strcmp( Fl::event_text(), "." ) == 0 ) { EventGridLaunchScene e( 3 ); writeToDspRingbuffer( &e ); return 1; } - - else - { - //printf("%s\n", Fl::event_text() ); return 1; - } - } - - // keyboard arrows to special key mapping - if ( Fl::event_key( FL_Left ) ) { EventGridSelectNewChosen e( gui->specialTrack-1, gui->specialScene ); writeToDspRingbuffer( &e ); return 1; } - if ( Fl::event_key( FL_Right ) ) { EventGridSelectNewChosen e( gui->specialTrack+1, gui->specialScene ); writeToDspRingbuffer( &e ); return 1; } - if ( Fl::event_key( FL_Up ) ) { EventGridSelectNewChosen e( gui->specialTrack , gui->specialScene-1); writeToDspRingbuffer( &e ); return 1; } - if ( Fl::event_key( FL_Down ) ) { EventGridSelectNewChosen e( gui->specialTrack , gui->specialScene+1); writeToDspRingbuffer( &e ); return 1; } - - return 0; + switch( event ) { + case FL_SHORTCUT: + if ( strcmp( Fl::event_text(), "1" ) == 0 ) { + EventGridEvent e( 0, 0, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "2" ) == 0 ) { + EventGridEvent e( 1, 0, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "3" ) == 0 ) { + EventGridEvent e( 2, 0, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "4" ) == 0 ) { + EventGridEvent e( 3, 0, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "5" ) == 0 ) { + EventGridEvent e( 4, 0, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "6" ) == 0 ) { + EventGridEvent e( 5, 0, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "7" ) == 0 ) { + EventGridEvent e( 6, 0, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "8" ) == 0 ) { + EventGridEvent e( 7, 0, true ); + writeToDspRingbuffer( &e ); + return 1; + } + + else if( strcmp( Fl::event_text(), "!" ) == 0 ) { + EventGridState e( 0, 0, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "@" ) == 0 ) { + EventGridState e( 1, 0, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "\"" ) == 0 ) { + EventGridState e( 1, 0, GridLogic::STATE_EMPTY ); // for UK/Ireland keyboards + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "#" ) == 0 ) { + EventGridState e( 2, 0, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "£" ) == 0 ) { + EventGridState e( 2, 0, GridLogic::STATE_EMPTY ); // for UK/Ireland keyboards + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "$" ) == 0 ) { + EventGridState e( 3, 0, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "%" ) == 0 ) { + EventGridState e( 4, 0, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "^" ) == 0 ) { + EventGridState e( 5, 0, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "&" ) == 0 ) { + EventGridState e( 6, 0, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "*" ) == 0 ) { + EventGridState e( 7, 0, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } + + else if( strcmp( Fl::event_text(), "q" ) == 0 ) { + EventGridEvent e( 0, 1, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "w" ) == 0 ) { + EventGridEvent e( 1, 1, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "e" ) == 0 ) { + EventGridEvent e( 2, 1, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "r" ) == 0 ) { + EventGridEvent e( 3, 1, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "t" ) == 0 ) { + EventGridEvent e( 4, 1, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "y" ) == 0 ) { + EventGridEvent e( 5, 1, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "u" ) == 0 ) { + EventGridEvent e( 6, 1, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "i" ) == 0 ) { + EventGridEvent e( 7, 1, true ); + writeToDspRingbuffer( &e ); + return 1; + } + + else if( strcmp( Fl::event_text(), "Q" ) == 0 ) { + EventGridState e( 0, 1, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "W" ) == 0 ) { + EventGridState e( 1, 1, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "E" ) == 0 ) { + EventGridState e( 2, 1, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "R" ) == 0 ) { + EventGridState e( 3, 1, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "T" ) == 0 ) { + EventGridState e( 4, 1, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "Y" ) == 0 ) { + EventGridState e( 5, 1, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "U" ) == 0 ) { + EventGridState e( 6, 1, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "I" ) == 0 ) { + EventGridState e( 7, 1, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } + + else if( strcmp( Fl::event_text(), "a" ) == 0 ) { + EventGridEvent e( 0, 2, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "s" ) == 0 ) { + EventGridEvent e( 1, 2, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "d" ) == 0 ) { + EventGridEvent e( 2, 2, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "f" ) == 0 ) { + EventGridEvent e( 3, 2, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "g" ) == 0 ) { + EventGridEvent e( 4, 2, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "h" ) == 0 ) { + EventGridEvent e( 5, 2, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "j" ) == 0 ) { + EventGridEvent e( 6, 2, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "k" ) == 0 ) { + EventGridEvent e( 7, 2, true ); + writeToDspRingbuffer( &e ); + return 1; + } + + else if( strcmp( Fl::event_text(), "A" ) == 0 ) { + EventGridState e( 0, 2, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "S" ) == 0 ) { + EventGridState e( 1, 2, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "D" ) == 0 ) { + EventGridState e( 2, 2, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "F" ) == 0 ) { + EventGridState e( 3, 2, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "G" ) == 0 ) { + EventGridState e( 4, 2, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "H" ) == 0 ) { + EventGridState e( 5, 2, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "J" ) == 0 ) { + EventGridState e( 6, 2, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "K" ) == 0 ) { + EventGridState e( 7, 2, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } + + else if( strcmp( Fl::event_text(), "z" ) == 0 ) { + EventGridEvent e( 0, 3, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "x" ) == 0 ) { + EventGridEvent e( 1, 3, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "c" ) == 0 ) { + EventGridEvent e( 2, 3, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "v" ) == 0 ) { + EventGridEvent e( 3, 3, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "b" ) == 0 ) { + EventGridEvent e( 4, 3, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "n" ) == 0 ) { + EventGridEvent e( 5, 3, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "m" ) == 0 ) { + EventGridEvent e( 6, 3, true ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "," ) == 0 ) { + EventGridEvent e( 7, 3, true ); + writeToDspRingbuffer( &e ); + return 1; + } + + else if( strcmp( Fl::event_text(), "Z" ) == 0 ) { + EventGridState e( 0, 3, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "X" ) == 0 ) { + EventGridState e( 1, 3, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "C" ) == 0 ) { + EventGridState e( 2, 3, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "V" ) == 0 ) { + EventGridState e( 3, 3, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "B" ) == 0 ) { + EventGridState e( 4, 3, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "N" ) == 0 ) { + EventGridState e( 5, 3, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "M" ) == 0 ) { + EventGridState e( 6, 3, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "<" ) == 0 ) { + EventGridState e( 7, 3, GridLogic::STATE_EMPTY ); + writeToDspRingbuffer( &e ); + return 1; + } + + else if( strcmp( Fl::event_text(), "9" ) == 0 ) { + EventGridLaunchScene e( 0 ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "o" ) == 0 ) { + EventGridLaunchScene e( 1 ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "l" ) == 0 ) { + EventGridLaunchScene e( 2 ); + writeToDspRingbuffer( &e ); + return 1; + } else if( strcmp( Fl::event_text(), "." ) == 0 ) { + EventGridLaunchScene e( 3 ); + writeToDspRingbuffer( &e ); + return 1; + } + + else { + //printf("%s\n", Fl::event_text() ); return 1; + } + } + + // keyboard arrows to special key mapping + if ( Fl::event_key( FL_Left ) ) { + EventGridSelectNewChosen e( gui->specialTrack-1, gui->specialScene ); + writeToDspRingbuffer( &e ); + return 1; + } + if ( Fl::event_key( FL_Right ) ) { + EventGridSelectNewChosen e( gui->specialTrack+1, gui->specialScene ); + writeToDspRingbuffer( &e ); + return 1; + } + if ( Fl::event_key( FL_Up ) ) { + EventGridSelectNewChosen e( gui->specialTrack , gui->specialScene-1); + writeToDspRingbuffer( &e ); + return 1; + } + if ( Fl::event_key( FL_Down ) ) { + EventGridSelectNewChosen e( gui->specialTrack , gui->specialScene+1); + writeToDspRingbuffer( &e ); + return 1; + } + + return 0; } Gui::~Gui() { - delete optionWindow; - delete audioEditor; - - delete diskReader; - delete diskWriter; - - delete master; - - for(unsigned int i = 0; i < tracks.size(); i++) - { - delete tracks.at(i); - } - - + delete optionWindow; + delete audioEditor; + + delete diskReader; + delete diskWriter; + + delete master; + + for(unsigned int i = 0; i < tracks.size(); i++) { + delete tracks.at(i); + } + + } diff --git a/src/gui.hxx b/src/gui.hxx index a287da6..3fcd473 100644 --- a/src/gui.hxx +++ b/src/gui.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -46,92 +46,107 @@ class AudioBuffer; class Gui { - public: - Gui(const char* argZero); - ~Gui(); - - int show(); - - int quit(); - void askQuit(); - - /// returns the options window - OptionsWindow* getOptionsWindow(); - - /// open audio editor window with an AudioBuffer - AudioEditor* getAudioEditor(); - - /// resets the state to "new" - void reset(); - - /// sets up MIDI controllers: must be done *after* backend is started - void addMidiControllerToSetup(std::string); - void setupMidiControllers(); - - GTrack* getTrack(int id); - GMasterTrack* getMasterTrack(){return master;} - - DiskWriter* getDiskWriter(){return diskWriter;} - DiskReader* getDiskReader(){return diskReader;} - - /// used to load samples into the grid - void selectLoadSample( int track, int clip ); - void selectSaveSample( int track, int clip ); - char* selectSavePath(); - - /// allows the user to select a Controller definition - static void selectLoadController(Fl_Widget* w, void*); - - - int samplerate; - - ////Enable per track send and resturn jack ports - bool enablePerTrackOutput; +public: + Gui(const char* argZero); + ~Gui(); - int getWindowWidth(){return window.w();} - - nsm_client_t* getNsm(){return nsm;} - - - /// current special clip: - int specialTrack; - int specialScene; - - /// The project directory is the default directoy which is shown upon load/save - void setProjectsDir(string dir); - string getProjectsDir(); - - // save a particular sample to path - std::string saveBufferPath; - - private: - vector controllerVector; - - Fl_Double_Window window; - - Fl_Group* lupppGroup; - - OptionsWindow* optionWindow; - - std::string lupppProjectsDir; - - AudioEditor* audioEditor; - - DiskReader* diskReader; - DiskWriter* diskWriter; - - GMasterTrack* master; - - vector tracks; - - // FIXME: refactor tooltip code out..? - std::string tooltip; - Fl_Box* tooltipLabel; - - // non-session-manager - nsm_client_t* nsm; - - static int keyboardHandler(int event); + int show(); + + int quit(); + void askQuit(); + + /// returns the options window + OptionsWindow* getOptionsWindow(); + + /// open audio editor window with an AudioBuffer + AudioEditor* getAudioEditor(); + + /// resets the state to "new" + void reset(); + + /// sets up MIDI controllers: must be done *after* backend is started + void addMidiControllerToSetup(std::string); + void setupMidiControllers(); + + GTrack* getTrack(int id); + GMasterTrack* getMasterTrack() + { + return master; + } + + DiskWriter* getDiskWriter() + { + return diskWriter; + } + DiskReader* getDiskReader() + { + return diskReader; + } + + /// used to load samples into the grid + void selectLoadSample( int track, int clip ); + void selectSaveSample( int track, int clip ); + char* selectSavePath(); + + /// allows the user to select a Controller definition + static void selectLoadController(Fl_Widget* w, void*); + + + int samplerate; + + ////Enable per track send and resturn jack ports + bool enablePerTrackOutput; + + int getWindowWidth() + { + return window.w(); + } + + nsm_client_t* getNsm() + { + return nsm; + } + + + /// current special clip: + int specialTrack; + int specialScene; + + /// The project directory is the default directoy which is shown upon load/save + void setProjectsDir(string dir); + string getProjectsDir(); + + // save a particular sample to path + std::string saveBufferPath; + +private: + vector controllerVector; + + Fl_Double_Window window; + + Fl_Group* lupppGroup; + + OptionsWindow* optionWindow; + + std::string lupppProjectsDir; + + AudioEditor* audioEditor; + + DiskReader* diskReader; + DiskWriter* diskWriter; + + GMasterTrack* master; + + vector tracks; + + // FIXME: refactor tooltip code out..? + std::string tooltip; + Fl_Box* tooltipLabel; + + // non-session-manager + nsm_client_t* nsm; + + static int keyboardHandler(int event); }; #endif // LUPPP_GUI diff --git a/src/gunittrack.hxx b/src/gunittrack.hxx index af59bec..dbd1e39 100644 --- a/src/gunittrack.hxx +++ b/src/gunittrack.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -37,35 +37,35 @@ using namespace std; class GUnitTrack : public Fl_Group { - public: - GUnitTrack(int x, int y, int w, int h, const char* l = 0 ) : - Fl_Group(x, y, w, h), - title( strdup(l) ), - bg( x, y , w, h, title ) - { - int uh = h / 5; - unit[0] = new Avtk::Unit(x + 2, y + uh * 4 - 2, w - 6, h / 5 - 2,"1"); - unit[1] = new Avtk::Unit(x + 2, y + uh * 3 - 2, w - 6, h / 5 - 2,"2"); - unit[2] = new Avtk::Unit(x + 2, y + uh * 2 - 2, w - 6, h / 5 - 2,"3"); - unit[3] = new Avtk::Unit(x + 2, y + uh * 1 - 2, w - 6, h / 5 - 2,"4"); - unit[4] = new Avtk::Unit(x + 2, y - 2 , w - 6, h / 5 - 2,"5"); - - end(); // close the group - } - - ~GUnitTrack() - { - free(title); - } - - - private: - char* title; - - Avtk::Background bg; - - Avtk::Unit* unit[5]; - +public: + GUnitTrack(int x, int y, int w, int h, const char* l = 0 ) : + Fl_Group(x, y, w, h), + title( strdup(l) ), + bg( x, y , w, h, title ) + { + int uh = h / 5; + unit[0] = new Avtk::Unit(x + 2, y + uh * 4 - 2, w - 6, h / 5 - 2,"1"); + unit[1] = new Avtk::Unit(x + 2, y + uh * 3 - 2, w - 6, h / 5 - 2,"2"); + unit[2] = new Avtk::Unit(x + 2, y + uh * 2 - 2, w - 6, h / 5 - 2,"3"); + unit[3] = new Avtk::Unit(x + 2, y + uh * 1 - 2, w - 6, h / 5 - 2,"4"); + unit[4] = new Avtk::Unit(x + 2, y - 2 , w - 6, h / 5 - 2,"5"); + + end(); // close the group + } + + ~GUnitTrack() + { + free(title); + } + + +private: + char* title; + + Avtk::Background bg; + + Avtk::Unit* unit[5]; + }; #endif // LUPPP_G_UNIT_TRACK_H diff --git a/src/jack.cxx b/src/jack.cxx index 6c39c84..6cb0398 100644 --- a/src/jack.cxx +++ b/src/jack.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -53,628 +53,596 @@ extern Jack* jack; void Jack::setup(std::string name) { - if ( jack == 0 ) - { - jack = new Jack( name ); - - jack->activate(); - return; - } - else - { - LUPPP_WARN("JACK instance already exists!"); - } + if ( jack == 0 ) { + jack = new Jack( name ); + + jack->activate(); + return; + } else { + LUPPP_WARN("JACK instance already exists!"); + } } void Jack::resetMidiBindingState() { - // MIDI binding stuff - bindingEventRecordEnable = false; - bindingEventType = EVENT_NULL; - bindingTrack = -2; - bindingScene = -1; - bindingSend = -1; - bindingActive= -1; + // MIDI binding stuff + bindingEventRecordEnable = false; + bindingEventType = EVENT_NULL; + bindingTrack = -2; + bindingScene = -1; + bindingSend = -1; + bindingActive= -1; } Jack::Jack( std::string name ) : - client( jack_client_open ( name.c_str(), JackNullOption , 0 , 0 ) ), - state( new State() ), - controllerUpdater( new ControllerUpdater() ), - clientActive(false) + client( jack_client_open ( name.c_str(), JackNullOption , 0 , 0 ) ), + state( new State() ), + controllerUpdater( new ControllerUpdater() ), + clientActive(false) { - jack = this; - lastnframes=0; - samplerate = jack_get_sample_rate( client ); - - LUPPP_NOTE("Samplerate %i", samplerate ); - - // construct Observer classes here, not in the initializer list as the Jack* - // will be 0x0 until then. - timeManager = new TimeManager(), - metronome = new Metronome(); - logic = new Logic(); - gridLogic = new GridLogic(); - - // CAREFUL: setup the size by default: otherwise malloc() is called on push_back - midiIO.reserve( CONTROLLERS_PREALLOC ); - - resetMidiBindingState(); - - //GenericMIDI* tmp = new GenericMIDI("akai_apc.ctlr"); - //tmp->registerComponents(); - //controllerUpdater->registerController( static_cast(tmp) ); - - buffers.nframes = jack_get_buffer_size( client ); - buffers.samplerate = jack_get_sample_rate( client ); - - EventSamplerate e(buffers.samplerate); - writeToGuiRingbuffer( &e ); - - uiUpdateCounter = buffers.samplerate / 30; - uiUpdateConstant = buffers.samplerate / 30; - - masterInput = jack_port_register( client, - "master_in", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsInput, - 0 ); - - masterReturnL = jack_port_register( client, - "master_return_left", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsInput, - 0 ); - - masterReturnR = jack_port_register( client, - "master_return_right", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsInput, - 0 ); - - masterOutputL = jack_port_register( client, - "master_left", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput, - 0 ); - - masterOutputR = jack_port_register( client, - "master_right", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput, - 0 ); - - headphonesPort = jack_port_register( client, - "headphone_out", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput, - 0 ); - - sendOutput = jack_port_register( client, - "send_out", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput, - 0 ); - - sidechainKeyOutput= jack_port_register( client, - "sidechain_key", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput, - 0 ); - - sidechainSignalOutput= jack_port_register( client, - "sidechain_signal", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput, - 0 ); - - /* - masterMidiInput = jack_port_register( client, - "midi_in", - JACK_DEFAULT_MIDI_TYPE, - JackPortIsInput, - 0 ); - */ - + jack = this; + lastnframes=0; + samplerate = jack_get_sample_rate( client ); - returnVol = 1.0f; - - inputToMixEnable = false; - inputToSendEnable = false; - inputToKeyEnable = false; - inputToMixVol = 0.f; - inputToSendVol = 0.f; - inputToXSideVol = 0.f; - - /// prepare internal buffers - buffers.audio[Buffers::SEND] = new float[ buffers.nframes ]; - buffers.audio[Buffers::SIDECHAIN_KEY] = new float[ buffers.nframes ]; - buffers.audio[Buffers::SIDECHAIN_SIGNAL]=new float[ buffers.nframes ]; - - buffers.audio[Buffers::MASTER_OUT_L] = new float[ buffers.nframes ]; - buffers.audio[Buffers::MASTER_OUT_R] = new float[ buffers.nframes ]; - - for(int i = 0; i < NTRACKS; i++) - { - /** Setup the tracks: - * The TrackOutput gets a pointer to the next AudioProcessor to call: - * This is either a JackSendReturn (providing send and return ports) - * or the track's Looper instance. - * This is an option in luppp.prfs - **/ - loopers.push_back( new Looper(i) ); + LUPPP_NOTE("Samplerate %i", samplerate ); - tracksendreturns.push_back(new JackSendReturn(i,loopers.back(),client)); - trackOutputs.push_back( new TrackOutput(i, tracksendreturns.back() ) ); + // construct Observer classes here, not in the initializer list as the Jack* + // will be 0x0 until then. + timeManager = new TimeManager(), + metronome = new Metronome(); + logic = new Logic(); + gridLogic = new GridLogic(); + + // CAREFUL: setup the size by default: otherwise malloc() is called on push_back + midiIO.reserve( CONTROLLERS_PREALLOC ); + + resetMidiBindingState(); + + //GenericMIDI* tmp = new GenericMIDI("akai_apc.ctlr"); + //tmp->registerComponents(); + //controllerUpdater->registerController( static_cast(tmp) ); + + buffers.nframes = jack_get_buffer_size( client ); + buffers.samplerate = jack_get_sample_rate( client ); + + EventSamplerate e(buffers.samplerate); + writeToGuiRingbuffer( &e ); + + uiUpdateCounter = buffers.samplerate / 30; + uiUpdateConstant = buffers.samplerate / 30; + + masterInput = jack_port_register( client, + "master_in", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, + 0 ); + + masterReturnL = jack_port_register( client, + "master_return_left", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, + 0 ); + + masterReturnR = jack_port_register( client, + "master_return_right", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, + 0 ); + + masterOutputL = jack_port_register( client, + "master_left", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, + 0 ); + + masterOutputR = jack_port_register( client, + "master_right", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, + 0 ); + + headphonesPort = jack_port_register( client, + "headphone_out", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, + 0 ); + + sendOutput = jack_port_register( client, + "send_out", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, + 0 ); + + sidechainKeyOutput= jack_port_register( client, + "sidechain_key", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, + 0 ); + + sidechainSignalOutput= jack_port_register( client, + "sidechain_signal", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, + 0 ); + + /* + masterMidiInput = jack_port_register( client, + "midi_in", + JACK_DEFAULT_MIDI_TYPE, + JackPortIsInput, + 0 ); + */ - buffers.audio[Buffers::TRACK_0 + i] = new float[ buffers.nframes ]; - buffers.audio[Buffers::SEND_TRACK_0+i]=new float[buffers.nframes]; - buffers.audio[Buffers::RETURN_TRACK_0+i]=new float[buffers.nframes]; + returnVol = 1.0f; + + inputToMixEnable = false; + inputToSendEnable = false; + inputToKeyEnable = false; + inputToMixVol = 0.f; + inputToSendVol = 0.f; + inputToXSideVol = 0.f; + + /// prepare internal buffers + buffers.audio[Buffers::SEND] = new float[ buffers.nframes ]; + buffers.audio[Buffers::SIDECHAIN_KEY] = new float[ buffers.nframes ]; + buffers.audio[Buffers::SIDECHAIN_SIGNAL]=new float[ buffers.nframes ]; + + buffers.audio[Buffers::MASTER_OUT_L] = new float[ buffers.nframes ]; + buffers.audio[Buffers::MASTER_OUT_R] = new float[ buffers.nframes ]; + + for(int i = 0; i < NTRACKS; i++) { + /** Setup the tracks: + * The TrackOutput gets a pointer to the next AudioProcessor to call: + * This is either a JackSendReturn (providing send and return ports) + * or the track's Looper instance. + * This is an option in luppp.prfs + **/ + loopers.push_back( new Looper(i) ); + + tracksendreturns.push_back(new JackSendReturn(i,loopers.back(),client)); + trackOutputs.push_back( new TrackOutput(i, tracksendreturns.back() ) ); - - timeManager->registerObserver( loopers.back() ); - if(gui->enablePerTrackOutput) - { - char name[50]; - sprintf(name,"track_%d\n",i); - trackJackOutputPorts[i]=jack_port_register( client, - name, - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput, - 0 ); + buffers.audio[Buffers::TRACK_0 + i] = new float[ buffers.nframes ]; + buffers.audio[Buffers::SEND_TRACK_0+i]=new float[buffers.nframes]; + buffers.audio[Buffers::RETURN_TRACK_0+i]=new float[buffers.nframes]; + + + + timeManager->registerObserver( loopers.back() ); + if(gui->enablePerTrackOutput) { + char name[50]; + sprintf(name,"track_%d\n",i); + trackJackOutputPorts[i]=jack_port_register( client, + name, + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, + 0 ); + + } + } + + /// setup DSP instances + inputVol = 1.0f; + masterVol = 0.75f; + masterVolLag =0.75f; + masterVolDiff =0.0f; + masterMeter = new DBMeter( buffers.samplerate ); + inputMeter = new DBMeter( buffers.samplerate ); + + buffers.transportPosition = 0; + + /// setup JACK callbacks + if ( jack_set_process_callback( client, + static_process, + static_cast(this)) ) { + LUPPP_ERROR("%s","Error setting process callback"); + } + + if ( jack_set_timebase_callback(client, + 0, //0, 0 == must be master, 1 == conditional + (JackTimebaseCallback)static_timebase, + static_cast(this)) ) { + LUPPP_ERROR("%s","Error setting timebase callback"); + } + + //Controller* m = new AkaiAPC(); + + // TODO: Add GUI dialog to add controllers, and insert them into the controller map. + // Watch out for RT stuff, loading file, registering ports etc: before activate?! + //Controller* m = new GenericMIDI("akai_apc.ctlr","apc"); + + Controller* g = new LupppGUI(); + controllerUpdater->registerController( g ); + + if ( !g ) { + LUPPP_ERROR("%s","Error creating LupppGUI Controller instance"); + } + + // call into the GUI, telling it to register default controllers + gui->setupMidiControllers(); - } - } - - /// setup DSP instances - inputVol = 1.0f; - masterVol = 0.75f; - masterVolLag =0.75f; - masterVolDiff =0.0f; - masterMeter = new DBMeter( buffers.samplerate ); - inputMeter = new DBMeter( buffers.samplerate ); - - buffers.transportPosition = 0; - - /// setup JACK callbacks - if ( jack_set_process_callback( client, - static_process, - static_cast(this)) ) - { - LUPPP_ERROR("%s","Error setting process callback"); - } - - if ( jack_set_timebase_callback(client, - 0, //0, 0 == must be master, 1 == conditional - (JackTimebaseCallback)static_timebase, - static_cast(this)) ) - { - LUPPP_ERROR("%s","Error setting timebase callback"); - } - - //Controller* m = new AkaiAPC(); - - // TODO: Add GUI dialog to add controllers, and insert them into the controller map. - // Watch out for RT stuff, loading file, registering ports etc: before activate?! - //Controller* m = new GenericMIDI("akai_apc.ctlr","apc"); - - Controller* g = new LupppGUI(); - controllerUpdater->registerController( g ); - - if ( !g ) - { - LUPPP_ERROR("%s","Error creating LupppGUI Controller instance"); - } - - // call into the GUI, telling it to register default controllers - gui->setupMidiControllers(); - } Jack::~Jack() { - delete timeManager; - delete metronome; - delete state; - delete logic; - delete gridLogic; - delete controllerUpdater; - - delete inputMeter; - delete masterMeter; - for(int i = 0; i < NTRACKS; i++) - { - delete [] buffers.audio[Buffers::TRACK_0+i]; - delete [] buffers.audio[Buffers::SEND_TRACK_0+i]; - delete [] buffers.audio[Buffers::RETURN_TRACK_0+i]; - delete tracksendreturns[i]; - delete loopers[i]; - delete trackOutputs[i]; - } + delete timeManager; + delete metronome; + delete state; + delete logic; + delete gridLogic; + delete controllerUpdater; + + delete inputMeter; + delete masterMeter; + for(int i = 0; i < NTRACKS; i++) { + delete [] buffers.audio[Buffers::TRACK_0+i]; + delete [] buffers.audio[Buffers::SEND_TRACK_0+i]; + delete [] buffers.audio[Buffers::RETURN_TRACK_0+i]; + delete tracksendreturns[i]; + delete loopers[i]; + delete trackOutputs[i]; + } } void Jack::activate() { - jack_activate( client ); + jack_activate( client ); } void Jack::transportRolling(bool rolling) { - if(rolling) - jack_transport_start(client); - else - jack_transport_stop(client); + if(rolling) + jack_transport_start(client); + else + jack_transport_stop(client); } void Jack::quit() { - //jack_deactivate( client ); - jack_client_close( client ); - LUPPP_NOTE("%s","Quit JACK."); + //jack_deactivate( client ); + jack_client_close( client ); + LUPPP_NOTE("%s","Quit JACK."); } TrackOutput* Jack::getTrackOutput(int t) { - if ( t >= 0 && t < NTRACKS ) - return trackOutputs.at(t); + if ( t >= 0 && t < NTRACKS ) + return trackOutputs.at(t); #ifdef DEBUG_TRACKS - else - { - printf( "Jack::getTrackOutput() returning 0x0: invalid track requested!\n" ); - } + else { + printf( "Jack::getTrackOutput() returning 0x0: invalid track requested!\n" ); + } #endif - - return 0; + + return 0; } JackSendReturn* Jack::getJackSendReturn(int t) { - if ( t >= 0 && t < NTRACKS ) - return tracksendreturns.at(t); + if ( t >= 0 && t < NTRACKS ) + return tracksendreturns.at(t); #ifdef DEBUG_TRACKS - else - { - printf( "Jack::getTrackOutput() returning 0x0: invalid track requested!\n" ); - } + else { + printf( "Jack::getTrackOutput() returning 0x0: invalid track requested!\n" ); + } #endif - return 0; + return 0; } Looper* Jack::getLooper(int t) { - if ( t >= 0 && t < NTRACKS ) - return loopers.at(t); + if ( t >= 0 && t < NTRACKS ) + return loopers.at(t); #ifdef DEBUG_TRACKS - else - { - printf( "Jack::getLooper() returning 0x0: invalid track requested!\n" ); - } + else { + printf( "Jack::getLooper() returning 0x0: invalid track requested!\n" ); + } #endif - - return 0; + + return 0; } void Jack::registerMidiIO( MidiIO* mo ) { - //LUPPP_NOTE("Jack::registerMidiIO()" ); - - // CAREFUL : this could need to resize and cause malloc() in RT thread - midiIO.push_back( mo ); + //LUPPP_NOTE("Jack::registerMidiIO()" ); + + // CAREFUL : this could need to resize and cause malloc() in RT thread + midiIO.push_back( mo ); } void Jack::unregisterMidiIO( MidiIO* mo ) { - LUPPP_NOTE("Jack::unregisterMidiIO()"); - - // unregister the observer - for(unsigned int i = 0; i < midiIO.size(); i++) - { - if ( midiIO.at(i) == mo ) - { - cout << "removing mo at " << i << endl; - midiIO.erase( midiIO.begin() + i ); - return; - } - } + LUPPP_NOTE("Jack::unregisterMidiIO()"); + + // unregister the observer + for(unsigned int i = 0; i < midiIO.size(); i++) { + if ( midiIO.at(i) == mo ) { + cout << "removing mo at " << i << endl; + midiIO.erase( midiIO.begin() + i ); + return; + } + } } int Jack::process (jack_nframes_t nframes) { - /// get buffers - buffers.audio[Buffers::MASTER_INPUT] = (float*)jack_port_get_buffer( masterInput , nframes ); - buffers.audio[Buffers::MASTER_RETURN_L] = (float*)jack_port_get_buffer( masterReturnL , nframes ); - buffers.audio[Buffers::MASTER_RETURN_R] = (float*)jack_port_get_buffer( masterReturnR , nframes ); - buffers.audio[Buffers::HEADPHONES_OUT] = (float*)jack_port_get_buffer( headphonesPort , nframes ); - - buffers.audio[Buffers::JACK_SEND_OUT] = (float*)jack_port_get_buffer( sendOutput , nframes ); - buffers.audio[Buffers::JACK_MASTER_OUT_L] = (float*)jack_port_get_buffer( masterOutputL , nframes ); - buffers.audio[Buffers::JACK_MASTER_OUT_R] = (float*)jack_port_get_buffer( masterOutputR , nframes ); - buffers.audio[Buffers::JACK_SIDECHAIN_KEY] = (float*)jack_port_get_buffer(sidechainKeyOutput,nframes); - buffers.audio[Buffers::JACK_SIDECHAIN_SIGNAL]=(float*)jack_port_get_buffer(sidechainSignalOutput,nframes); - if(gui->enablePerTrackOutput) - { - for(int t=0;tenablePerTrackOutput) { + for(int t=0; tenablePerTrackOutput) - { - for(int t=0;tinitBuffers( nframes ); - } - - /// do events from the ringbuffer - handleDspEvents(); - - /// process incoming MIDI - /* - jack_midi_event_t in_event; - int masterMidiInputIndex = 0; - int event_count = (int) jack_midi_get_event_count( buffers.midi[Buffers::MASTER_MIDI_INPUT] ); - while ( masterMidiInputIndex < event_count ) - { - jack_midi_event_get(&in_event, buffers.midi[Buffers::MASTER_MIDI_INPUT], masterMidiInputIndex); - - char buffer [50]; - sprintf (buffer, "MIDI %i %i %i", int(in_event.buffer[0]), int(in_event.buffer[1]), int(in_event.buffer[2]) ); - EventGuiPrint e( buffer ); - writeToGuiRingbuffer( &e ); - - masterMidiInputIndex++; - } - */ - - - /// update "time" from JACK master, or write master? - buffers.transportFrame = jack_get_current_transport_frame(client); - - // time manager deals with detecting bar() / beat() events, and calls - // processFrames() with the appropriate nframes - timeManager->process( &buffers ); - - return 0; + + // clear the buffers + memset( buffers.audio[Buffers::JACK_MASTER_OUT_L] , 0, sizeof(float) * nframes ); + memset( buffers.audio[Buffers::JACK_MASTER_OUT_R] , 0, sizeof(float) * nframes ); + memset( buffers.audio[Buffers::MASTER_OUT_L] , 0, sizeof(float) * nframes ); + memset( buffers.audio[Buffers::MASTER_OUT_R] , 0, sizeof(float) * nframes ); + memset( buffers.audio[Buffers::HEADPHONES_OUT] , 0, sizeof(float) * nframes ); + memset( buffers.audio[Buffers::SEND] , 0, sizeof(float) * nframes ); + memset( buffers.audio[Buffers::SIDECHAIN_KEY] , 0, sizeof(float) * nframes ); + memset( buffers.audio[Buffers::SIDECHAIN_SIGNAL] , 0, sizeof(float) * nframes ); + if(gui->enablePerTrackOutput) { + for(int t=0; tinitBuffers( nframes ); + } + + /// do events from the ringbuffer + handleDspEvents(); + + /// process incoming MIDI + /* + jack_midi_event_t in_event; + int masterMidiInputIndex = 0; + int event_count = (int) jack_midi_get_event_count( buffers.midi[Buffers::MASTER_MIDI_INPUT] ); + while ( masterMidiInputIndex < event_count ) + { + jack_midi_event_get(&in_event, buffers.midi[Buffers::MASTER_MIDI_INPUT], masterMidiInputIndex); + + char buffer [50]; + sprintf (buffer, "MIDI %i %i %i", int(in_event.buffer[0]), int(in_event.buffer[1]), int(in_event.buffer[2]) ); + EventGuiPrint e( buffer ); + writeToGuiRingbuffer( &e ); + + masterMidiInputIndex++; + } + */ + + + /// update "time" from JACK master, or write master? + buffers.transportFrame = jack_get_current_transport_frame(client); + + // time manager deals with detecting bar() / beat() events, and calls + // processFrames() with the appropriate nframes + timeManager->process( &buffers ); + + return 0; } void Jack::processFrames(int nframes) { - if ( nframes < 0 ) - { - LUPPP_WARN("Jack processFrames got nframes < 0"); - return; - } - - /* - // extreme debugging of timemanager process-split functionality - char buffer [50]; - sprintf (buffer, "Jack::processFrames() got %i", nframes ); - EventGuiPrint e2( buffer ); - writeToGuiRingbuffer( &e2 ); - */ - - /// process each MidiIO registered MIDI port - for(unsigned int i = 0; i < midiIO.size(); i++ ) - { - midiIO.at(i)->process( nframes ); - } - - /// process each track, starting at output and working up signal path - for(unsigned int i = 0; i < NTRACKS; i++) - { - trackOutputs.at(i)->process( nframes, &buffers ); - } - - /// metro signal - metronome->process( nframes, &buffers ); - - /// mix input, reverb & post-sidechain in - for(unsigned int i = 0; i < nframes; i++) - { - float input= buffers.audio[Buffers::MASTER_INPUT][i] * inputVol; - - float L = buffers.audio[Buffers::MASTER_OUT_L][i]; - float R = buffers.audio[Buffers::MASTER_OUT_R][i]; - float returnL = buffers.audio[Buffers::MASTER_RETURN_L][i]; - float returnR = buffers.audio[Buffers::MASTER_RETURN_R][i]; - - - if ( inputToMixEnable ) - { - // if sending to mix, scale by volume *and* by XSide send - float tmp = input * inputToMixVol * (1-inputToXSideVol); - L += tmp; - R += tmp; - } - if ( inputToSendEnable ) - { - // post-mix-send amount: hence * inputToMixVol - buffers.audio[Buffers::SEND][i] += input * inputToSendVol * inputToMixVol; - } - if ( inputToKeyEnable ) - { - buffers.audio[Buffers::SIDECHAIN_KEY][i] += input; - } - - - buffers.audio[Buffers::SIDECHAIN_SIGNAL][i] += input * inputToXSideVol; - - //compute master volume lag; - if(fabs(masterVol-masterVolLag)>=fabs(masterVolDiff/10.0)) - masterVolLag+=masterVolDiff/10.0; - /// mixdown returns into master buffers - buffers.audio[Buffers::JACK_MASTER_OUT_L][i] = (L + returnL*returnVol) * masterVolLag; - buffers.audio[Buffers::JACK_MASTER_OUT_R][i] = (R + returnR*returnVol) * masterVolLag; - - /// write SEND content to JACK port - buffers.audio[Buffers::JACK_SEND_OUT][i] = buffers.audio[Buffers::SEND][i]; - buffers.audio[Buffers::JACK_SIDECHAIN_KEY][i] = buffers.audio[Buffers::SIDECHAIN_KEY][i]; - buffers.audio[Buffers::JACK_SIDECHAIN_SIGNAL][i] = buffers.audio[Buffers::SIDECHAIN_SIGNAL][i]; - } - - - /// db meter on master input & output - inputMeter->process( nframes, buffers.audio[Buffers::MASTER_INPUT], buffers.audio[Buffers::MASTER_INPUT]); - masterMeter->process(nframes, buffers.audio[Buffers::JACK_MASTER_OUT_L], buffers.audio[Buffers::JACK_MASTER_OUT_R] ); - - if ( uiUpdateCounter > uiUpdateConstant ) - { - // instead of scaling whole buffer, just scale output by vol - EventTrackSignalLevel e(-1, masterMeter->getLeftDB(), masterMeter->getRightDB() ); - writeToGuiRingbuffer( &e ); - EventTrackSignalLevel e2(-2, inputMeter->getLeftDB() * inputVol, inputMeter->getRightDB() * inputVol ); - writeToGuiRingbuffer( &e2 ); - - uiUpdateCounter = 0; - } - - uiUpdateCounter += nframes; - - /* - // memcpy the internal MASTER_OUTPUT buffer to the JACK_MASTER_OUTPUT - memcpy( buffers.audio[Buffers::JACK_MASTER_OUT_L], - buffers.audio[Buffers::MASTER_OUT_L], - sizeof(float)*nframes); - - memcpy( buffers.audio[Buffers::JACK_MASTER_OUT_R], - buffers.audio[Buffers::MASTER_OUT_R], - //buffers.audio[Buffers::POST_SIDECHAIN], - //buffers.audio[Buffers::SEND], // uncomment to listen to reverb send only - sizeof(float)*nframes); - */ - - // move buffer pointers up nframes: allows processing of one "nframes" from - // JACK in multiple parts internally in Luppp: used for processing bar() / beat() - // if a full JACK nframes has been processed, this is extra work: its not that expensive - /// update buffers by nframes - if(lastnframes+nframesenablePerTrackOutput) - { - for(int t=0;tprocess( nframes ); + } + + /// process each track, starting at output and working up signal path + for(unsigned int i = 0; i < NTRACKS; i++) { + trackOutputs.at(i)->process( nframes, &buffers ); + } + + /// metro signal + metronome->process( nframes, &buffers ); + + /// mix input, reverb & post-sidechain in + for(unsigned int i = 0; i < nframes; i++) { + float input= buffers.audio[Buffers::MASTER_INPUT][i] * inputVol; + + float L = buffers.audio[Buffers::MASTER_OUT_L][i]; + float R = buffers.audio[Buffers::MASTER_OUT_R][i]; + float returnL = buffers.audio[Buffers::MASTER_RETURN_L][i]; + float returnR = buffers.audio[Buffers::MASTER_RETURN_R][i]; + + + if ( inputToMixEnable ) { + // if sending to mix, scale by volume *and* by XSide send + float tmp = input * inputToMixVol * (1-inputToXSideVol); + L += tmp; + R += tmp; + } + if ( inputToSendEnable ) { + // post-mix-send amount: hence * inputToMixVol + buffers.audio[Buffers::SEND][i] += input * inputToSendVol * inputToMixVol; + } + if ( inputToKeyEnable ) { + buffers.audio[Buffers::SIDECHAIN_KEY][i] += input; + } + + + buffers.audio[Buffers::SIDECHAIN_SIGNAL][i] += input * inputToXSideVol; + + //compute master volume lag; + if(fabs(masterVol-masterVolLag)>=fabs(masterVolDiff/10.0)) + masterVolLag+=masterVolDiff/10.0; + /// mixdown returns into master buffers + buffers.audio[Buffers::JACK_MASTER_OUT_L][i] = (L + returnL*returnVol) * masterVolLag; + buffers.audio[Buffers::JACK_MASTER_OUT_R][i] = (R + returnR*returnVol) * masterVolLag; + + /// write SEND content to JACK port + buffers.audio[Buffers::JACK_SEND_OUT][i] = buffers.audio[Buffers::SEND][i]; + buffers.audio[Buffers::JACK_SIDECHAIN_KEY][i] = buffers.audio[Buffers::SIDECHAIN_KEY][i]; + buffers.audio[Buffers::JACK_SIDECHAIN_SIGNAL][i] = buffers.audio[Buffers::SIDECHAIN_SIGNAL][i]; + } + + + /// db meter on master input & output + inputMeter->process( nframes, buffers.audio[Buffers::MASTER_INPUT], buffers.audio[Buffers::MASTER_INPUT]); + masterMeter->process(nframes, buffers.audio[Buffers::JACK_MASTER_OUT_L], buffers.audio[Buffers::JACK_MASTER_OUT_R] ); + + if ( uiUpdateCounter > uiUpdateConstant ) { + // instead of scaling whole buffer, just scale output by vol + EventTrackSignalLevel e(-1, masterMeter->getLeftDB(), masterMeter->getRightDB() ); + writeToGuiRingbuffer( &e ); + EventTrackSignalLevel e2(-2, inputMeter->getLeftDB() * inputVol, inputMeter->getRightDB() * inputVol ); + writeToGuiRingbuffer( &e2 ); + + uiUpdateCounter = 0; + } + + uiUpdateCounter += nframes; + + /* + // memcpy the internal MASTER_OUTPUT buffer to the JACK_MASTER_OUTPUT + memcpy( buffers.audio[Buffers::JACK_MASTER_OUT_L], + buffers.audio[Buffers::MASTER_OUT_L], + sizeof(float)*nframes); + + memcpy( buffers.audio[Buffers::JACK_MASTER_OUT_R], + buffers.audio[Buffers::MASTER_OUT_R], + //buffers.audio[Buffers::POST_SIDECHAIN], + //buffers.audio[Buffers::SEND], // uncomment to listen to reverb send only + sizeof(float)*nframes); + */ + + // move buffer pointers up nframes: allows processing of one "nframes" from + // JACK in multiple parts internally in Luppp: used for processing bar() / beat() + // if a full JACK nframes has been processed, this is extra work: its not that expensive + /// update buffers by nframes + if(lastnframes+nframesenablePerTrackOutput) { + for(int t=0; t(instance)->process(nframes); + return static_cast(instance)->process(nframes); } int Jack::static_timebase(jack_transport_state_t state, @@ -700,5 +668,5 @@ int Jack::static_timebase(jack_transport_state_t state, int newPos, void* instance) { - return static_cast(instance)->timebase(state,nframes, pos, newPos ); + return static_cast(instance)->timebase(state,nframes, pos, newPos ); } diff --git a/src/jack.hxx b/src/jack.hxx index 307e495..4daf330 100644 --- a/src/jack.hxx +++ b/src/jack.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -54,144 +54,162 @@ using namespace std; **/ class Jack { - public: - Jack(std::string name); - ~Jack(); - - static void setup(std::string name); - - void activate(); - /// quits the JACK client, destroying ports etc. Call only on exit of Luppp. - void quit(); - - int getBuffersize(); - int getSamplerate(); - - // Luppp process callback: bar() events can occur between these - void processFrames(int nframes); +public: + Jack(std::string name); + ~Jack(); - //Sets the first nframes of all the internal output buffers to zero. NO LIMIT CHECKS - void clearInternalBuffers(int nframes); - - /// get functions for components owned by Jack - Looper* getLooper(int t); - TrackOutput* getTrackOutput(int t); - - State* getState(){return state;} - Logic* getLogic(){return logic;} - Metronome* getMetronome(){return metronome;} - GridLogic* getGridLogic(){return gridLogic;} - TimeManager* getTimeManager(){return timeManager;} - ControllerUpdater* getControllerUpdater(){return controllerUpdater;} + static void setup(std::string name); - void transportRolling(bool rolling); - - /// register a MIDI observer - void registerMidiIO( MidiIO* mo ); - void unregisterMidiIO( MidiIO* mo ); - - /// set the master i/o volume / sends - void inputVolume( float vol ); - void masterVolume( float vol ); - void returnVolume( float vol ); - void inputTo(INPUT_TO to, float v); - void inputToActive(INPUT_TO to, bool a); - - jack_client_t* getJackClientPointer() - { - return client; - }; - - void resetMidiBindingState(); - - // MIDI binding creation - bool bindingEventRecordEnable; - int bindingEventType; - int bindingTrack; - int bindingScene; - int bindingSend; - int bindingActive; + void activate(); + /// quits the JACK client, destroying ports etc. Call only on exit of Luppp. + void quit(); - JackSendReturn *getJackSendReturn(int t); + int getBuffersize(); + int getSamplerate(); + + // Luppp process callback: bar() events can occur between these + void processFrames(int nframes); + + //Sets the first nframes of all the internal output buffers to zero. NO LIMIT CHECKS + void clearInternalBuffers(int nframes); + + /// get functions for components owned by Jack + Looper* getLooper(int t); + TrackOutput* getTrackOutput(int t); + + State* getState() + { + return state; + } + Logic* getLogic() + { + return logic; + } + Metronome* getMetronome() + { + return metronome; + } + GridLogic* getGridLogic() + { + return gridLogic; + } + TimeManager* getTimeManager() + { + return timeManager; + } + ControllerUpdater* getControllerUpdater() + { + return controllerUpdater; + } + + void transportRolling(bool rolling); + + /// register a MIDI observer + void registerMidiIO( MidiIO* mo ); + void unregisterMidiIO( MidiIO* mo ); + + /// set the master i/o volume / sends + void inputVolume( float vol ); + void masterVolume( float vol ); + void returnVolume( float vol ); + void inputTo(INPUT_TO to, float v); + void inputToActive(INPUT_TO to, bool a); + + jack_client_t* getJackClientPointer() + { + return client; + }; + + void resetMidiBindingState(); + + // MIDI binding creation + bool bindingEventRecordEnable; + int bindingEventType; + int bindingTrack; + int bindingScene; + int bindingSend; + int bindingActive; + + JackSendReturn *getJackSendReturn(int t); private: - int lastnframes; - jack_client_t* client; - - Buffers buffers; - TimeManager* timeManager; - Metronome* metronome; - State* state; - Logic* logic; - GridLogic* gridLogic; - ControllerUpdater* controllerUpdater; - - vector loopers; - vector tracksendreturns; - vector trackOutputs; - - vector midiIO; - - // FX - DBMeter* inputMeter; - DBMeter* masterMeter; - - float inputVol; - /// _toMasterLag is a volume that lags behind _toMaster when setMaster() is called - /// This prohibits audible jumps when rapidly changing the volume - float masterVol; - float masterVolLag; - float masterVolDiff; - float returnVol; - - float inputToMixVol; - float inputToSendVol; - float inputToXSideVol; - - bool inputToKeyEnable; - bool inputToMixEnable; - bool inputToSendEnable; - - // JACK member variables - bool clientActive; - int samplerate; - - jack_port_t* masterInput; - jack_port_t* masterOutputL; - jack_port_t* masterOutputR; + int lastnframes; + jack_client_t* client; - jack_port_t* masterReturnL; - jack_port_t* masterReturnR; - jack_port_t* headphonesPort; - - jack_port_t* sidechainKeyOutput; - jack_port_t* sidechainSignalOutput; - jack_port_t* sendOutput; - - jack_port_t* masterMidiInput; + Buffers buffers; + TimeManager* timeManager; + Metronome* metronome; + State* state; + Logic* logic; + GridLogic* gridLogic; + ControllerUpdater* controllerUpdater; + + vector loopers; + vector tracksendreturns; + vector trackOutputs; + + vector midiIO; + + // FX + DBMeter* inputMeter; + DBMeter* masterMeter; + + float inputVol; + /// _toMasterLag is a volume that lags behind _toMaster when setMaster() is called + /// This prohibits audible jumps when rapidly changing the volume + float masterVol; + float masterVolLag; + float masterVolDiff; + float returnVol; + + float inputToMixVol; + float inputToSendVol; + float inputToXSideVol; + + bool inputToKeyEnable; + bool inputToMixEnable; + bool inputToSendEnable; + + // JACK member variables + bool clientActive; + int samplerate; + + jack_port_t* masterInput; + jack_port_t* masterOutputL; + jack_port_t* masterOutputR; + + jack_port_t* masterReturnL; + jack_port_t* masterReturnR; + jack_port_t* headphonesPort; + + jack_port_t* sidechainKeyOutput; + jack_port_t* sidechainSignalOutput; + jack_port_t* sendOutput; + + jack_port_t* masterMidiInput; + + jack_port_t* trackJackOutputPorts[NTRACKS]; + + // JACK callback + int process (jack_nframes_t); + + int timebase(jack_transport_state_t, + jack_nframes_t, + jack_position_t*, + int ); + + // static JACK callbacks + static int static_process (jack_nframes_t, void *); + + static int static_timebase (jack_transport_state_t, + jack_nframes_t, + jack_position_t*, + int, + void* ); + + // UI update variables + int uiUpdateCounter; + int uiUpdateConstant; - jack_port_t* trackJackOutputPorts[NTRACKS]; - - // JACK callback - int process (jack_nframes_t); - - int timebase(jack_transport_state_t, - jack_nframes_t, - jack_position_t*, - int ); - - // static JACK callbacks - static int static_process (jack_nframes_t, void *); - - static int static_timebase (jack_transport_state_t, - jack_nframes_t, - jack_position_t*, - int, - void* ); - - // UI update variables - int uiUpdateCounter; - int uiUpdateConstant; - }; #endif // LUPPP_JACK_H diff --git a/src/jacksendreturn.cxx b/src/jacksendreturn.cxx index 17c078d..c58dd63 100644 --- a/src/jacksendreturn.cxx +++ b/src/jacksendreturn.cxx @@ -4,63 +4,62 @@ #include extern Jack* jack; JackSendReturn::JackSendReturn(int trackid, AudioProcessor *prev, jack_client_t *client) - :m_trackid(trackid), m_previousProcessor(prev), m_sendvol(1.0f) + :m_trackid(trackid), m_previousProcessor(prev), m_sendvol(1.0f) { - char name[50]; - sprintf(name, "Send_track_%d\n",trackid); - m_sendport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput,0); - sprintf(name, "Return_track_%d\n",trackid); - m_returnport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsInput,0); - m_active=false; - m_counter=0; + char name[50]; + sprintf(name, "Send_track_%d\n",trackid); + m_sendport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput,0); + sprintf(name, "Return_track_%d\n",trackid); + m_returnport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsInput,0); + m_active=false; + m_counter=0; } void JackSendReturn::process(unsigned int nframes, Buffers *buffers) { - //Reset send buffer - int offset=m_counter%(buffers->nframes); - float* sendtrack=&(buffers->audio[Buffers::SEND_TRACK_0+m_trackid][0]); + //Reset send buffer + int offset=m_counter%(buffers->nframes); + float* sendtrack=&(buffers->audio[Buffers::SEND_TRACK_0+m_trackid][0]); - float* rettrack=&(buffers->audio[Buffers::RETURN_TRACK_0+m_trackid][0]); + float* rettrack=&(buffers->audio[Buffers::RETURN_TRACK_0+m_trackid][0]); - memset(sendtrack,0,nframes*sizeof(float)); + memset(sendtrack,0,nframes*sizeof(float)); - //Process previous AudioProcessor - m_previousProcessor->process(nframes,buffers); - float* send=(float*)jack_port_get_buffer(m_sendport,(jack_nframes_t)(buffers->nframes)); - float* ret=(float*)jack_port_get_buffer(m_returnport,(jack_nframes_t)(buffers->nframes)); - if(offset) - { - send+=offset; - ret+=offset; - } + //Process previous AudioProcessor + m_previousProcessor->process(nframes,buffers); + float* send=(float*)jack_port_get_buffer(m_sendport,(jack_nframes_t)(buffers->nframes)); + float* ret=(float*)jack_port_get_buffer(m_returnport,(jack_nframes_t)(buffers->nframes)); + if(offset) { + send+=offset; + ret+=offset; + } - for(int i=0;inframes) // { // cout<nframes); + if(offset) + assert(offset+nframes==buffers->nframes); - if(m_active) - memcpy(rettrack,ret,nframes*sizeof(float)); - else - memcpy(rettrack, - sendtrack,nframes*sizeof(float)); - m_counter+=nframes; + if(m_active) + memcpy(rettrack,ret,nframes*sizeof(float)); + else + memcpy(rettrack, + sendtrack,nframes*sizeof(float)); + m_counter+=nframes; } void JackSendReturn::activate(bool act) { - m_active=act; + m_active=act; } void JackSendReturn::sendVolume(float vol) { - m_sendvol=vol; + m_sendvol=vol; } diff --git a/src/jacksendreturn.hxx b/src/jacksendreturn.hxx index 813eacf..13d0bf8 100644 --- a/src/jacksendreturn.hxx +++ b/src/jacksendreturn.hxx @@ -30,25 +30,25 @@ class JackSendReturn: public AudioProcessor { public: - //Constructor: the registration of the jack send/return is done here - JackSendReturn(int trackid,AudioProcessor* prev,jack_client_t* client); + //Constructor: the registration of the jack send/return is done here + JackSendReturn(int trackid,AudioProcessor* prev,jack_client_t* client); - //The process callback - virtual void process(unsigned int nframes, Buffers* buffers); + //The process callback + virtual void process(unsigned int nframes, Buffers* buffers); - //Activate the return chain. When m_active=true then Buffers::RETURN_TRACK_0+m_trackid gets the data - //from the return port. The send port always send the incoming data - void activate(bool act); - void sendVolume(float vol); + //Activate the return chain. When m_active=true then Buffers::RETURN_TRACK_0+m_trackid gets the data + //from the return port. The send port always send the incoming data + void activate(bool act); + void sendVolume(float vol); private: - bool m_active; - float m_sendvol; - jack_port_t* m_sendport; - jack_port_t* m_returnport; - int m_trackid; - AudioProcessor* m_previousProcessor; - int m_counter; + bool m_active; + float m_sendvol; + jack_port_t* m_sendport; + jack_port_t* m_returnport; + int m_trackid; + AudioProcessor* m_previousProcessor; + int m_counter; }; diff --git a/src/logic.cxx b/src/logic.cxx index 84fd3ba..8d5ecd9 100644 --- a/src/logic.cxx +++ b/src/logic.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -28,154 +28,130 @@ extern Jack* jack; #include "jacksendreturn.hxx" Logic::Logic() { - + } void Logic::tapTempo() { - jack->getTimeManager()->tap(); + jack->getTimeManager()->tap(); } void Logic::setBpm(float bpm) { - jack->getTimeManager()->setBpm( bpm ); + jack->getTimeManager()->setBpm( bpm ); } void Logic::metronomeEnable(bool b) { - jack->getMetronome()->setActive(b); - jack->getControllerUpdater()->metronomeEnable( b ); + jack->getMetronome()->setActive(b); + jack->getControllerUpdater()->metronomeEnable( b ); } void Logic::masterInputVol( float v ) { - jack->inputVolume( v ); - jack->getControllerUpdater()->masterInputVol( v ); + jack->inputVolume( v ); + jack->getControllerUpdater()->masterInputVol( v ); } void Logic::masterInputTo( int to, float v ) { - jack->inputTo( (Event::INPUT_TO)to, v ); - jack->getControllerUpdater()->masterInputTo( to, v ); + jack->inputTo( (Event::INPUT_TO)to, v ); + jack->getControllerUpdater()->masterInputTo( to, v ); } void Logic::masterInputToActive( int inputTo, bool active) { - jack->inputToActive( (Event::INPUT_TO)inputTo, active); - jack->getControllerUpdater()->masterInputToActive( (int)inputTo, active ); + jack->inputToActive( (Event::INPUT_TO)inputTo, active); + jack->getControllerUpdater()->masterInputToActive( (int)inputTo, active ); } void Logic::masterReturn( int returnNum, float value ) { - jack->returnVolume( value ); - jack->getControllerUpdater()->masterReturnVolume( value ); + jack->returnVolume( value ); + jack->getControllerUpdater()->masterReturnVolume( value ); } void Logic::trackVolume(int t, float v) { - if ( t == -1 ) // master track - { - jack->masterVolume(v); - jack->getControllerUpdater()->masterVolume( v ); - } - else if ( t >= 0 && t < NTRACKS ) - { - jack->getTrackOutput( t )->setMaster( v ); - jack->getControllerUpdater()->volume( t, v ); - } - else - { - LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); - } + if ( t == -1 ) { // master track + jack->masterVolume(v); + jack->getControllerUpdater()->masterVolume( v ); + } else if ( t >= 0 && t < NTRACKS ) { + jack->getTrackOutput( t )->setMaster( v ); + jack->getControllerUpdater()->volume( t, v ); + } else { + LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); + } } void Logic::trackRecordArm(int t, bool v) { - if ( t >= 0 && t < NTRACKS ) - { - jack->getTrackOutput( t )->recordArm( v ); - jack->getControllerUpdater()->recordArm( t, v ); - } - else - { - LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); - } + if ( t >= 0 && t < NTRACKS ) { + jack->getTrackOutput( t )->recordArm( v ); + jack->getControllerUpdater()->recordArm( t, v ); + } else { + LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); + } } void Logic::trackSendActive(int t, int s, bool v) { - if ( t >= 0 && t < NTRACKS ) - { - jack->getTrackOutput( t )->setSendActive( s, v ); - jack->getControllerUpdater()->setTrackSendActive( t, s, v ); - } - else - { - LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); - } + if ( t >= 0 && t < NTRACKS ) { + jack->getTrackOutput( t )->setSendActive( s, v ); + jack->getControllerUpdater()->setTrackSendActive( t, s, v ); + } else { + LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); + } } void Logic::trackSend(int t, int send, float v) { - if ( t >= 0 && t < NTRACKS ) - { - jack->getTrackOutput( t )->setSend( send, v ); - jack->getControllerUpdater()->setTrackSend( t, send, v ); - } - else - { - LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); - } + if ( t >= 0 && t < NTRACKS ) { + jack->getTrackOutput( t )->setSend( send, v ); + jack->getControllerUpdater()->setTrackSend( t, send, v ); + } else { + LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); + } } void Logic::trackJackSendActivate(int t, bool active) { - if ( t >= 0 && t < NTRACKS ) - { - jack->getJackSendReturn(t)->activate(active); - jack->getControllerUpdater()->setTrackJackSendActive( t, active ); - } - else - { - LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); - } + if ( t >= 0 && t < NTRACKS ) { + jack->getJackSendReturn(t)->activate(active); + jack->getControllerUpdater()->setTrackJackSendActive( t, active ); + } else { + LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); + } } void Logic::trackJackSend(int t, float vol) { - if ( t >= 0 && t < NTRACKS ) - { - jack->getJackSendReturn(t)->sendVolume(vol); - jack->getControllerUpdater()->setTrackJackSend( t, vol ); - } - else - { - LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); - } + if ( t >= 0 && t < NTRACKS ) { + jack->getJackSendReturn(t)->sendVolume(vol); + jack->getControllerUpdater()->setTrackJackSend( t, vol ); + } else { + LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); + } } void Logic::looperClipLenght(int t, int s, int l) { - if ( t >= 0 && t < NTRACKS ) - { - jack->getLooper( t )->getClip( s )->setBeats(l); - } - else - { - LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); - } + if ( t >= 0 && t < NTRACKS ) { + jack->getLooper( t )->getClip( s )->setBeats(l); + } else { + LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); + } } void Logic::looperUseAsTempo(int t, int s) { - size_t clipBeats = jack->getLooper( t )->getClip( s )->getBeats(); - size_t clipFrames = jack->getLooper( t )->getClip( s )->getBufferLenght(); - - if ( clipBeats > 0 ) - { - size_t framesPerBeat = clipFrames / clipBeats; - jack->getTimeManager()->setFpb( framesPerBeat ); - } - + size_t clipBeats = jack->getLooper( t )->getClip( s )->getBeats(); + size_t clipFrames = jack->getLooper( t )->getClip( s )->getBufferLenght(); + + if ( clipBeats > 0 ) { + size_t framesPerBeat = clipFrames / clipBeats; + jack->getTimeManager()->setFpb( framesPerBeat ); + } + } diff --git a/src/logic.hxx b/src/logic.hxx index 5f15c1f..5c6540f 100644 --- a/src/logic.hxx +++ b/src/logic.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -25,42 +25,42 @@ * This class contains an interface exposing most functionality in Luppp. The * interface is used to have one central place from where each controller can * interact with Luppp using the same function calls. - * + * * This class should be used for input from any device. The interface is * deliberatly specific with regards to scheduling events: controllers should * NOT attempt to schedule changes: use the provided functions directly when * events occur on a controller. - * + * * The ControllerUpdater class is the opposite of this class, it provides * feedback of each event that occurs. - * + * * Note: The GridLogic class provides the interface to scene selection / state. **/ class Logic { - public: - Logic(); - - void tapTempo(); - void setBpm(float bpm); /// 0-1 input - - void metronomeEnable(bool b); - - void masterInputVol( float v ); - void masterInputTo( int inputTo, float v); - void masterInputToActive( int inputTo, bool active); - - void masterReturn( int returnNum, float v); - - void trackVolume(int track, float volume); - void trackRecordArm(int track, bool armed); - void trackSendActive(int track, int send, bool active); - void trackSend(int track, int send, float value); +public: + Logic(); - void trackJackSendActivate(int t, bool active); - void trackJackSend(int t, float vol); - void looperUseAsTempo(int track, int scene); - void looperClipLenght(int track, int scene, int lenght); + void tapTempo(); + void setBpm(float bpm); /// 0-1 input + + void metronomeEnable(bool b); + + void masterInputVol( float v ); + void masterInputTo( int inputTo, float v); + void masterInputToActive( int inputTo, bool active); + + void masterReturn( int returnNum, float v); + + void trackVolume(int track, float volume); + void trackRecordArm(int track, bool armed); + void trackSendActive(int track, int send, bool active); + void trackSend(int track, int send, float value); + + void trackJackSendActivate(int t, bool active); + void trackJackSend(int t, float vol); + void looperUseAsTempo(int track, int scene); + void looperClipLenght(int track, int scene, int lenght); }; #endif // LUPPP_LOGIC_H diff --git a/src/looper.cxx b/src/looper.cxx index 27732d7..cef84c3 100644 --- a/src/looper.cxx +++ b/src/looper.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -31,50 +31,50 @@ extern Jack* jack; Looper::Looper(int t) : - AudioProcessor(), - TimeObserver(), - track(t) + AudioProcessor(), + TimeObserver(), + track(t) { - uiUpdateConstant= jack->getSamplerate() / 30.f; - uiUpdateCounter = jack->getSamplerate() / 30.f; - - // pre-zero the internal sample - //tmpRecordBuffer = (float*)malloc( sizeof(float) * MAX_BUFFER_SIZE ); - //memset( tmpRecordBuffer, 0, sizeof(float) * MAX_BUFFER_SIZE ); - - for(int i = 0; i < 10; i++ ) - { - clips[i] = new LooperClip(track, i); - } - - tmpBuffer.resize( MAX_BUFFER_SIZE ); - - fpb = 22050; - - // init faust pitch shift variables - fSamplingFreq = jack->getSamplerate(); - IOTA = 0; - - //tmpRecordBuffer.resize(MAX_BUFFER_SIZE); - - for (int i=0; i<65536; i++) - fVec0[i] = 0; - for (int i=0; i<2; i++) - fRec0[i] = 0; - semitoneShift = 0.0f; - windowSize = 1000; - crossfadeSize = 1000; + uiUpdateConstant= jack->getSamplerate() / 30.f; + uiUpdateCounter = jack->getSamplerate() / 30.f; + + // pre-zero the internal sample + //tmpRecordBuffer = (float*)malloc( sizeof(float) * MAX_BUFFER_SIZE ); + //memset( tmpRecordBuffer, 0, sizeof(float) * MAX_BUFFER_SIZE ); + + for(int i = 0; i < 10; i++ ) { + clips[i] = new LooperClip(track, i); + } + + tmpBuffer.resize( MAX_BUFFER_SIZE ); + + fpb = 22050; + + // init faust pitch shift variables + fSamplingFreq = jack->getSamplerate(); + IOTA = 0; + + //tmpRecordBuffer.resize(MAX_BUFFER_SIZE); + + for (int i=0; i<65536; i++) + fVec0[i] = 0; + for (int i=0; i<2; i++) + fRec0[i] = 0; + semitoneShift = 0.0f; + windowSize = 1000; + crossfadeSize = 1000; } LooperClip* Looper::getClip(int scene) { - return clips[scene]; + return clips[scene]; } void Looper::beat() -{//TODO needed? - //FIXME: Need to keep looperClips in sync when there exists no int N - // such that playSpeed*N==1 +{ + //TODO needed? + //FIXME: Need to keep looperClips in sync when there exists no int N + // such that playSpeed*N==1 // for(int i=0;igetPlayhead()+1.0; @@ -94,117 +94,108 @@ void Looper::beat() void Looper::setRequestedBuffer(int s, AudioBuffer* ab) { - clips[s]->setRequestedBuffer( ab ); + clips[s]->setRequestedBuffer( ab ); } void Looper::setFpb(int f) { - fpb = f; + fpb = f; } void Looper::process(unsigned int nframes, Buffers* buffers) { - // process each clip individually: this allows for playback of one clip, - // while another clip records. - for ( int clip = 0; clip < NSCENES; clip++ ) - { - // handle state of clip, and do what needs doing: - // record into buffer, play from buffer, etc - if ( clips[clip]->recording() ) - { - if ( clips[clip]->recordSpaceAvailable() < LOOPER_SAMPLES_BEFORE_REQUEST && - !clips[clip]->newBufferInTransit() ) - { - EventLooperClipRequestBuffer e( track, clip, clips[clip]->audioBufferSize() + LOOPER_SAMPLES_UPDATE_SIZE); - writeToGuiRingbuffer( &e ); - clips[clip]->newBufferInTransit(true); - } - - // copy data from input buffer to recording buffer - float* input = buffers->audio[Buffers::MASTER_INPUT]; - clips[clip]->record( nframes, input, 0 ); - } - else if ( clips[clip]->playing() ) - { - // copy data into tmpBuffer, then pitch-stretch into track buffer - long targetFrames = clips[clip]->getBeats() * fpb; - long actualFrames = clips[clip]->getActualAudioLength();//getBufferLenght(); - float playSpeed = 1.0; - - if ( targetFrames != 0 && actualFrames != 0 ) - { - playSpeed = float(actualFrames) / targetFrames; - } - - float* out = buffers->audio[Buffers::SEND_TRACK_0 + track]; - - for(unsigned int i = 0; i < nframes; i++ ) - { - // REFACTOR into system that is better than per sample function calls - float tmp = clips[clip]->getSample(playSpeed); - - float deltaPitch = 12 * log ( playSpeed ) / log (2); - semitoneShift = -deltaPitch; - - // write the pitch-shifted signal to the track buffer - //FIXME: pitchShift adds delay even for playSpeed = 1.0!! - //we should use something better (e.g librubberband) - if(playSpeed!=1.0f) - pitchShift( 1, &tmp, &out[i] ); - else - out[i]+=tmp; - } - - //printf("Looper %i playing(), speed = %f\n", track, playSpeed ); - - if ( uiUpdateCounter > uiUpdateConstant ) - { - jack->getControllerUpdater()->setTrackSceneProgress(track, clip, clips[clip]->getProgress() ); - uiUpdateCounter = 0; - } - uiUpdateCounter += nframes; - } - - } - - + // process each clip individually: this allows for playback of one clip, + // while another clip records. + for ( int clip = 0; clip < NSCENES; clip++ ) { + // handle state of clip, and do what needs doing: + // record into buffer, play from buffer, etc + if ( clips[clip]->recording() ) { + if ( clips[clip]->recordSpaceAvailable() < LOOPER_SAMPLES_BEFORE_REQUEST && + !clips[clip]->newBufferInTransit() ) { + EventLooperClipRequestBuffer e( track, clip, clips[clip]->audioBufferSize() + LOOPER_SAMPLES_UPDATE_SIZE); + writeToGuiRingbuffer( &e ); + clips[clip]->newBufferInTransit(true); + } + + // copy data from input buffer to recording buffer + float* input = buffers->audio[Buffers::MASTER_INPUT]; + clips[clip]->record( nframes, input, 0 ); + } else if ( clips[clip]->playing() ) { + // copy data into tmpBuffer, then pitch-stretch into track buffer + long targetFrames = clips[clip]->getBeats() * fpb; + long actualFrames = clips[clip]->getActualAudioLength();//getBufferLenght(); + float playSpeed = 1.0; + + if ( targetFrames != 0 && actualFrames != 0 ) { + playSpeed = float(actualFrames) / targetFrames; + } + + float* out = buffers->audio[Buffers::SEND_TRACK_0 + track]; + + for(unsigned int i = 0; i < nframes; i++ ) { + // REFACTOR into system that is better than per sample function calls + float tmp = clips[clip]->getSample(playSpeed); + + float deltaPitch = 12 * log ( playSpeed ) / log (2); + semitoneShift = -deltaPitch; + + // write the pitch-shifted signal to the track buffer + //FIXME: pitchShift adds delay even for playSpeed = 1.0!! + //we should use something better (e.g librubberband) + if(playSpeed!=1.0f) + pitchShift( 1, &tmp, &out[i] ); + else + out[i]+=tmp; + } + + //printf("Looper %i playing(), speed = %f\n", track, playSpeed ); + + if ( uiUpdateCounter > uiUpdateConstant ) { + jack->getControllerUpdater()->setTrackSceneProgress(track, clip, clips[clip]->getProgress() ); + uiUpdateCounter = 0; + } + uiUpdateCounter += nframes; + } + + } + + } void Looper::resetTimeState() { - for(int i=0;isetPlayHead(0.0); + for(int i=0; isetPlayHead(0.0); } void Looper::pitchShift(int count, float* input, float* output) { - float fSlow0 = windowSize; - float fSlow1 = ((1 + fSlow0) - powf(2,(0.08333333333333333f * semitoneShift))); - float fSlow2 = (1.0f / crossfadeSize); - float fSlow3 = (fSlow0 - 1); - float* input0 = &input[0]; - //float* output0 = &output[0]; - - for (int i=0; i. */ @@ -37,55 +37,55 @@ using namespace std; **/ class Looper : public AudioProcessor, public TimeObserver { - public: - Looper(int t); - - /// *sets* the new audiobuffer, but the content gets copied to the new buffer. - /// Used for infinite lenght recording - void setRequestedBuffer(int s, AudioBuffer* ab); - - /// stores the framesPerBeat from TimeManager. Used to stretch audio - void setFpb(int f); - - /// Retrieve a clip from the Looper - LooperClip* getClip(int scene); - - /// Override beat(). Resyncs loperclips to beat in case playSpeed is funny fraction - /// that doesnt add up to 1 (e.g if playSpeed=3/4 then 3/4+3/4+3/4+3/4=3!=1 bringing - /// looperClip out of sync) - virtual void beat(); - /// Process nframes of audio - void process(unsigned int nframes, Buffers* buffers); +public: + Looper(int t); - /// reset timestate implementation: rest all looperClips - virtual void resetTimeState(); - - private: - const int track; - - /// variables used to determing the current actions of the looper - int playingScene; - int queuedScene; - - int fpb; - - //vector tmpRecordBuffer; - LooperClip* clips[10]; - - // Pitch Shifting - void pitchShift(int count, float* input, float* output); - vector tmpBuffer; - - int IOTA; - float fVec0[65536]; - float semitoneShift; - float windowSize; - float fRec0[2]; - float crossfadeSize; - float fSamplingFreq; - - int uiUpdateConstant; - int uiUpdateCounter; + /// *sets* the new audiobuffer, but the content gets copied to the new buffer. + /// Used for infinite lenght recording + void setRequestedBuffer(int s, AudioBuffer* ab); + + /// stores the framesPerBeat from TimeManager. Used to stretch audio + void setFpb(int f); + + /// Retrieve a clip from the Looper + LooperClip* getClip(int scene); + + /// Override beat(). Resyncs loperclips to beat in case playSpeed is funny fraction + /// that doesnt add up to 1 (e.g if playSpeed=3/4 then 3/4+3/4+3/4+3/4=3!=1 bringing + /// looperClip out of sync) + virtual void beat(); + /// Process nframes of audio + void process(unsigned int nframes, Buffers* buffers); + + /// reset timestate implementation: rest all looperClips + virtual void resetTimeState(); + +private: + const int track; + + /// variables used to determing the current actions of the looper + int playingScene; + int queuedScene; + + int fpb; + + //vector tmpRecordBuffer; + LooperClip* clips[10]; + + // Pitch Shifting + void pitchShift(int count, float* input, float* output); + vector tmpBuffer; + + int IOTA; + float fVec0[65536]; + float semitoneShift; + float windowSize; + float fRec0[2]; + float crossfadeSize; + float fSamplingFreq; + + int uiUpdateConstant; + int uiUpdateCounter; }; #endif // LUPPP_LOOPER_H diff --git a/src/looperclip.cxx b/src/looperclip.cxx index cc5aa86..6527ace 100644 --- a/src/looperclip.cxx +++ b/src/looperclip.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -33,465 +33,429 @@ extern Jack* jack; LooperClip::LooperClip(int t, int s) : - Stately(), - track(t), - scene(s) + Stately(), + track(t), + scene(s) { - _buffer = new AudioBuffer(); - _buffer->nonRtResize( 4410 ); - init(); + _buffer = new AudioBuffer(); + _buffer->nonRtResize( 4410 ); + init(); } void LooperClip::init() { - _loaded = false; - _playing = false; - _recording = false; - - _queuePlay = false; - _queueStop = false; - _queueRecord= false; - - if ( _buffer ) - { - _buffer->init(); - } - _newBufferInTransit = false; - - _playhead = 0; - _recordhead = 0; - - + _loaded = false; + _playing = false; + _recording = false; + + _queuePlay = false; + _queueStop = false; + _queueRecord= false; + + if ( _buffer ) { + _buffer->init(); + } + _newBufferInTransit = false; + + _playhead = 0; + _recordhead = 0; + + } void LooperClip::save() { - // ensure the buffer exists, and is saveable (not recording) - if ( _loaded && !_recording && !_queueRecord ) - { - char buffer [50]; - sprintf (buffer, "LC::save() track %i, scene %i", track,scene); - EventGuiPrint e( buffer ); - writeToGuiRingbuffer( &e ); - - int frames = _buffer->getAudioFrames(); - EventRequestSaveBuffer e2( track, scene, frames ); - writeToGuiRingbuffer( &e2 ); - } - else - { - // notify of "success" of save if there *is* no state to save - Stately::success(); - } + // ensure the buffer exists, and is saveable (not recording) + if ( _loaded && !_recording && !_queueRecord ) { + char buffer [50]; + sprintf (buffer, "LC::save() track %i, scene %i", track,scene); + EventGuiPrint e( buffer ); + writeToGuiRingbuffer( &e ); + + int frames = _buffer->getAudioFrames(); + EventRequestSaveBuffer e2( track, scene, frames ); + writeToGuiRingbuffer( &e2 ); + } else { + // notify of "success" of save if there *is* no state to save + Stately::success(); + } } void LooperClip::reset() { - // TODO make the LooperClip reset to initial state - if ( _loaded ) - { - char buffer [50]; - sprintf (buffer, "LC::reset() track %i, scene %i", track,scene); - EventGuiPrint e( buffer ); - writeToGuiRingbuffer( &e ); - - // set "progress" to zero as there's no clip anymore - jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 ); - } - else - { - //SaveAble::done(); - } - - init(); + // TODO make the LooperClip reset to initial state + if ( _loaded ) { + char buffer [50]; + sprintf (buffer, "LC::reset() track %i, scene %i", track,scene); + EventGuiPrint e( buffer ); + writeToGuiRingbuffer( &e ); + + // set "progress" to zero as there's no clip anymore + jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 ); + } else { + //SaveAble::done(); + } + + init(); } /// loads a sample: eg from disk, unloading current sample if necessary void LooperClip::load( AudioBuffer* ab ) { - _loaded = true; - _recording = false; - _playing = false; - - _queuePlay = false; - _queueStop = false; - _queueRecord= false; - - if ( _buffer ) - { - EventDeallocateBuffer e( _buffer ); - writeToGuiRingbuffer( &e ); - } - - _buffer = ab; - - _playhead = 0; - jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 ); - - // set the endpoint to the buffer's size - _recordhead = _buffer->getData().size(); - + _loaded = true; + _recording = false; + _playing = false; + + _queuePlay = false; + _queueStop = false; + _queueRecord= false; + + if ( _buffer ) { + EventDeallocateBuffer e( _buffer ); + writeToGuiRingbuffer( &e ); + } + + _buffer = ab; + + _playhead = 0; + jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 ); + + // set the endpoint to the buffer's size + _recordhead = _buffer->getData().size(); + #ifdef DEBUG_BUFFER - char buffer [50]; - sprintf (buffer, "LC::load() t %i, s %i, aF %i",track, scene, int(_buffer->getAudioFrames()) ); - EventGuiPrint e( buffer ); - writeToGuiRingbuffer( &e ); + char buffer [50]; + sprintf (buffer, "LC::load() t %i, s %i, aF %i",track, scene, int(_buffer->getAudioFrames()) ); + EventGuiPrint e( buffer ); + writeToGuiRingbuffer( &e ); #endif } void LooperClip::setRequestedBuffer( AudioBuffer* ab ) { - if ( _buffer ) - { - size_t size = _buffer->getData().size(); - memcpy( &ab->getData().at(0), &_buffer->getData().at(0), sizeof(float)*size); - - ab->setID ( _buffer->getID() ); - ab->setBeats( _buffer->getBeats() ); - - EventDeallocateBuffer e( _buffer ); - writeToGuiRingbuffer( &e ); - } - - _buffer = ab; - - _newBufferInTransit = false; + if ( _buffer ) { + size_t size = _buffer->getData().size(); + memcpy( &ab->getData().at(0), &_buffer->getData().at(0), sizeof(float)*size); + + ab->setID ( _buffer->getID() ); + ab->setBeats( _buffer->getBeats() ); + + EventDeallocateBuffer e( _buffer ); + writeToGuiRingbuffer( &e ); + } + + _buffer = ab; + + _newBufferInTransit = false; } void LooperClip::recieveSaveBuffer( AudioBuffer* saveBuffer ) { - if ( saveBuffer->getData().size() >= _buffer->getData().at(0) ) - { - // copy current contents into save buffer, - size_t framesBySize = _buffer->getAudioFrames(); - memcpy( &saveBuffer->getData().at(0), &_buffer->getData().at(0), sizeof(float)*framesBySize); - - saveBuffer->setID ( _buffer->getID() ); - saveBuffer->setBeats( _buffer->getBeats() ); - saveBuffer->setAudioFrames( _buffer->getAudioFrames() ); - - EventStateSaveBuffer e ( track, scene, saveBuffer ); - writeToGuiRingbuffer( &e ); - - Stately::success(); - } - else - { - char buffer [50]; - sprintf (buffer, "LC:: %i, %i: can't save, buf too small",track, scene ); - EventGuiPrint e( buffer ); - writeToGuiRingbuffer( &e ); - Stately::error(""); - } + if ( saveBuffer->getData().size() >= _buffer->getData().at(0) ) { + // copy current contents into save buffer, + size_t framesBySize = _buffer->getAudioFrames(); + memcpy( &saveBuffer->getData().at(0), &_buffer->getData().at(0), sizeof(float)*framesBySize); + + saveBuffer->setID ( _buffer->getID() ); + saveBuffer->setBeats( _buffer->getBeats() ); + saveBuffer->setAudioFrames( _buffer->getAudioFrames() ); + + EventStateSaveBuffer e ( track, scene, saveBuffer ); + writeToGuiRingbuffer( &e ); + + Stately::success(); + } else { + char buffer [50]; + sprintf (buffer, "LC:: %i, %i: can't save, buf too small",track, scene ); + EventGuiPrint e( buffer ); + writeToGuiRingbuffer( &e ); + Stately::error(""); + } } void LooperClip::setPlayHead(float ph) { - if(!_recording&&_playing) - { - _playhead = ph; - jack->getControllerUpdater()->setTrackSceneProgress(track, scene, getProgress() ); - } + if(!_recording&&_playing) { + _playhead = ph; + jack->getControllerUpdater()->setTrackSceneProgress(track, scene, getProgress() ); + } } void LooperClip::record(int count, float* L, float* R) { - // write "count" samples into current buffer. - if ( _buffer ) - { - size_t size = _buffer->getData().size(); - - for(int i = 0; i < count; i++) - { - if ( _recordhead < size ) - { - _buffer->getData().at( _recordhead ) = *L++; - _recordhead++; - } - else - { - // break: this is *BAD*, audio data is lost but the buffer isn't here - // yet to hold new audio data so there's no option. This has not been - // encountered in actual usage, only during the development process. - char buffer [50]; - sprintf (buffer, "LooperClip t %i, s %i, Error: out of mem!",track, scene ); - EventGuiPrint e( buffer ); - writeToGuiRingbuffer( &e ); + // write "count" samples into current buffer. + if ( _buffer ) { + size_t size = _buffer->getData().size(); + + for(int i = 0; i < count; i++) { + if ( _recordhead < size ) { + _buffer->getData().at( _recordhead ) = *L++; + _recordhead++; + } else { + // break: this is *BAD*, audio data is lost but the buffer isn't here + // yet to hold new audio data so there's no option. This has not been + // encountered in actual usage, only during the development process. + char buffer [50]; + sprintf (buffer, "LooperClip t %i, s %i, Error: out of mem!",track, scene ); + EventGuiPrint e( buffer ); + writeToGuiRingbuffer( &e ); #ifdef BUILD_TESTS - LUPPP_WARN("%s","buffer has no space"); + LUPPP_WARN("%s","buffer has no space"); #endif - - break; - } - } - } - - _loaded = true; + + break; + } + } + } + + _loaded = true; } unsigned long LooperClip::recordSpaceAvailable() { - if ( _buffer ) - return _buffer->getData().size() - _recordhead; - - return 0; + if ( _buffer ) + return _buffer->getData().size() - _recordhead; + + return 0; } size_t LooperClip::audioBufferSize() { - if ( _buffer ) - { - return _buffer->getData().size(); - } - return 0; + if ( _buffer ) { + return _buffer->getData().size(); + } + return 0; } void LooperClip::setBeats(int beats) { - if ( _buffer ) - { - _buffer->setBeats( beats ); - } + if ( _buffer ) { + _buffer->setBeats( beats ); + } } int LooperClip::getBeats() { - if ( _buffer ) - return _buffer->getBeats(); - - return 0; + if ( _buffer ) + return _buffer->getBeats(); + + return 0; } long LooperClip::getBufferLenght() { - return _recordhead; + return _recordhead; } long LooperClip::getActualAudioLength() { - char cbuffer [50]; + char cbuffer [50]; // sprintf (cbuffer, "LooperClip recordhead %f,audioFrames %d \n",_recordhead,(int)_buffer->getAudioFrames()); // EventGuiPrint e( cbuffer ); // writeToGuiRingbuffer( &e ); // printf(cbuffer); - return _buffer->getAudioFrames(); + return _buffer->getAudioFrames(); } void LooperClip::bar() { - bool change = false; - GridLogic::State s = GridLogic::STATE_EMPTY; - - // first update the buffer, as time has passed - if ( _recording ) - { - // FIXME: assumes 4 beats in a bar - _buffer->setBeats( _buffer->getBeats() + 4 ); - _buffer->setAudioFrames( jack->getTimeManager()->getFpb() * _buffer->getBeats() ); - } - - if ( _playhead >= _recordhead ) - { - _playhead = 0.f; - } - - if ( _queuePlay && _loaded ) - { - //LUPPP_NOTE("QPLay + loaded" ); - _playing = true; - s = GridLogic::STATE_PLAYING; - _recording = false; - _queuePlay = false; - change = true; - - _playhead = 0; - } - else if ( _queueStop && _loaded ) - { - _playing = false; - s = GridLogic::STATE_STOPPED; - _recording = false; - _queueStop = false; - change = true; - // set "progress" to zero, as we're stopped! - jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 ); - } - else if ( _queueRecord ) - { - _recording = true; - s = GridLogic::STATE_RECORDING; - _playing = false; - _queueRecord = false; - change = true; - - if ( _buffer ) - { - _buffer->setBeats( 0 ); - } - - _recordhead = 0; - } - else if ( _queuePlay ) - { - // clip was queued, but there's nothing loaded - _queuePlay = false; - change = true; - } - - if ( change ) - { - jack->getControllerUpdater()->setSceneState(track, scene, s ); - } + bool change = false; + GridLogic::State s = GridLogic::STATE_EMPTY; + + // first update the buffer, as time has passed + if ( _recording ) { + // FIXME: assumes 4 beats in a bar + _buffer->setBeats( _buffer->getBeats() + 4 ); + _buffer->setAudioFrames( jack->getTimeManager()->getFpb() * _buffer->getBeats() ); + } + + if ( _playhead >= _recordhead ) { + _playhead = 0.f; + } + + if ( _queuePlay && _loaded ) { + //LUPPP_NOTE("QPLay + loaded" ); + _playing = true; + s = GridLogic::STATE_PLAYING; + _recording = false; + _queuePlay = false; + change = true; + + _playhead = 0; + } else if ( _queueStop && _loaded ) { + _playing = false; + s = GridLogic::STATE_STOPPED; + _recording = false; + _queueStop = false; + change = true; + // set "progress" to zero, as we're stopped! + jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 ); + } else if ( _queueRecord ) { + _recording = true; + s = GridLogic::STATE_RECORDING; + _playing = false; + _queueRecord = false; + change = true; + + if ( _buffer ) { + _buffer->setBeats( 0 ); + } + + _recordhead = 0; + } else if ( _queuePlay ) { + // clip was queued, but there's nothing loaded + _queuePlay = false; + change = true; + } + + if ( change ) { + jack->getControllerUpdater()->setSceneState(track, scene, s ); + } } void LooperClip::neutralize() { - _queuePlay = false; - _queueRecord = false; - _queueStop = false; + _queuePlay = false; + _queueRecord = false; + _queueStop = false; } bool LooperClip::somethingQueued() { - if ( _queuePlay || _queueStop || _queueRecord ) - { - return true; - } - return false; + if ( _queuePlay || _queueStop || _queueRecord ) { + return true; + } + return false; } void LooperClip::queuePlay(bool qP) { - _queuePlay = true; - _queueStop = false; - _queueRecord = false; + _queuePlay = true; + _queueStop = false; + _queueRecord = false; } void LooperClip::queueStop() { - // comment - if ( _loaded ) - { - _queueStop = true; - _queuePlay = false; - } + // comment + if ( _loaded ) { + _queueStop = true; + _queuePlay = false; + } } void LooperClip::queueRecord() { - _queueRecord = true; - _queuePlay = false; - _queueStop = false; + _queueRecord = true; + _queuePlay = false; + _queueStop = false; } GridLogic::State LooperClip::getState() { - GridLogic::State s = GridLogic::STATE_EMPTY; - - if ( _loaded ) - s = GridLogic::STATE_STOPPED; - if ( _playing ) - s = GridLogic::STATE_PLAYING; - if ( _recording ) - s = GridLogic::STATE_RECORDING; - if ( _queuePlay ) - s = GridLogic::STATE_PLAY_QUEUED; - if ( _queueStop ) - s = GridLogic::STATE_STOP_QUEUED; - if ( _queueRecord ) - s = GridLogic::STATE_RECORD_QUEUED; - - return s; + GridLogic::State s = GridLogic::STATE_EMPTY; + + if ( _loaded ) + s = GridLogic::STATE_STOPPED; + if ( _playing ) + s = GridLogic::STATE_PLAYING; + if ( _recording ) + s = GridLogic::STATE_RECORDING; + if ( _queuePlay ) + s = GridLogic::STATE_PLAY_QUEUED; + if ( _queueStop ) + s = GridLogic::STATE_STOP_QUEUED; + if ( _queueRecord ) + s = GridLogic::STATE_RECORD_QUEUED; + + return s; } bool LooperClip::playing() { - return _playing; + return _playing; } bool LooperClip::getQueueStop() { - return _queueStop; + return _queueStop; } bool LooperClip::getQueuePlay() { - return _queuePlay; + return _queuePlay; } bool LooperClip::getLoaded() { - return _loaded; + return _loaded; } bool LooperClip::recording() { - return _recording; + return _recording; } void LooperClip::newBufferInTransit(bool n) { - _newBufferInTransit = n; + _newBufferInTransit = n; } bool LooperClip::newBufferInTransit() { - return _newBufferInTransit; + return _newBufferInTransit; } float LooperClip::getSample(float playSpeed) { - if ( _buffer && _buffer->getData().size() > 0 ) - { - if ( _playhead >= _recordhead || - _playhead >= _buffer->getData().size() || - _playhead < 0 ) - { - _playhead = 0; - - EventGuiPrint e( "LooperClip resetting _playhead" ); - //writeToGuiRingbuffer( &e ); - } - - std::vector& v = _buffer->getData(); - float tmp = v.at(_playhead); - _playhead +=playSpeed; + if ( _buffer && _buffer->getData().size() > 0 ) { + if ( _playhead >= _recordhead || + _playhead >= _buffer->getData().size() || + _playhead < 0 ) { + _playhead = 0; - return tmp; - } - - return 0.f; + EventGuiPrint e( "LooperClip resetting _playhead" ); + //writeToGuiRingbuffer( &e ); + } + + std::vector& v = _buffer->getData(); + float tmp = v.at(_playhead); + _playhead +=playSpeed; + + return tmp; + } + + return 0.f; } float LooperClip::getProgress() { - if ( _buffer && _playing ) - { - float p = float(_playhead) / _recordhead; - //printf("LooperClip progress %f\n", p ); - return p; - } - return 0.f; + if ( _buffer && _playing ) { + float p = float(_playhead) / _recordhead; + //printf("LooperClip progress %f\n", p ); + return p; + } + return 0.f; } float LooperClip::getPlayhead() { - return _playhead; + return _playhead; } #ifdef BUILD_TESTS void LooperClip::setState( bool load, bool play, bool rec, bool qPlay, bool qStop, bool qRec ) { - _loaded = load; - _playing = play; - _recording = rec; - - _queuePlay = qPlay; - _queueStop = qStop; - _queueRecord = qRec; + _loaded = load; + _playing = play; + _recording = rec; + + _queuePlay = qPlay; + _queueStop = qStop; + _queueRecord = qRec; } #endif diff --git a/src/looperclip.hxx b/src/looperclip.hxx index a419ba4..b2bae9c 100644 --- a/src/looperclip.hxx +++ b/src/looperclip.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -34,110 +34,113 @@ class AudioBuffer; * The transition between AudioBuffer instances is seamless: when the clip is * running out, the new one is requested. Upon its arrival the current data is * copied, and the old buffer is returned for deallocation. - * + * * This system allows for arbitrary length recordings, without huge * pre-allocated buffers while it is still quite simple. - * + * * Each clip has its properties like length and bars/beats, so the Looper knows * to dynamically stretch / process the audio appropriately. Controllers and the * UI are updated from this data. - * + * * This class inherits from SaveAble to save its state. **/ class LooperClip : public Stately { - public: - LooperClip(int track, int scene); - - void init(); - - /// loads a sample: eg from disk, unloading current sample if necessary - void load( AudioBuffer* ab ); - - /// audio functionality - float getSample(float playSpeed); - void record(int count, float* L, float* R); - - /// TimeObserver override - void bar(); - - /// SaveAble overrides - void save(); - void reset(); - - /// analyses current _playing _recording vars, returns the current State - GridLogic::State getState(); - bool playing(); - bool getLoaded(); - bool getQueueStop(); - bool getQueuePlay(); - bool recording(); - - /// get buffer details - int getBeats(); - float getProgress(); - float getPlayhead(); - //Return the length of the complete buffer - long getBufferLenght(); - //Return the nr of samples holding actual audio. This is less then getBufferLength(); - long getActualAudioLength(); - size_t audioBufferSize(); +public: + LooperClip(int track, int scene); - AudioBuffer* getAudioBuffer() {return _buffer;} - - /// set clip state - void queuePlay(bool=true); - void queueStop(); - void queueRecord(); - - void neutralize(); // removes all play || record states if on - bool somethingQueued(); // returns true if any state is queued - - /// set buffer state - void setBeats(int beats); - - /// Luppp internal buffer resizing - void newBufferInTransit(bool n); - bool newBufferInTransit(); - unsigned long recordSpaceAvailable(); - - /** used to update the size of the buffer for this looperclip. The current - * data is copied into the new buffer, then the smaller buffer is sent - * for de-allocation. - **/ - void setRequestedBuffer( AudioBuffer* ab ); - - /// used for saving the contents of this buffer to disk - void recieveSaveBuffer( AudioBuffer* ab ); + void init(); + + /// loads a sample: eg from disk, unloading current sample if necessary + void load( AudioBuffer* ab ); + + /// audio functionality + float getSample(float playSpeed); + void record(int count, float* L, float* R); + + /// TimeObserver override + void bar(); + + /// SaveAble overrides + void save(); + void reset(); + + /// analyses current _playing _recording vars, returns the current State + GridLogic::State getState(); + bool playing(); + bool getLoaded(); + bool getQueueStop(); + bool getQueuePlay(); + bool recording(); + + /// get buffer details + int getBeats(); + float getProgress(); + float getPlayhead(); + //Return the length of the complete buffer + long getBufferLenght(); + //Return the nr of samples holding actual audio. This is less then getBufferLength(); + long getActualAudioLength(); + size_t audioBufferSize(); + + AudioBuffer* getAudioBuffer() + { + return _buffer; + } + + /// set clip state + void queuePlay(bool=true); + void queueStop(); + void queueRecord(); + + void neutralize(); // removes all play || record states if on + bool somethingQueued(); // returns true if any state is queued + + /// set buffer state + void setBeats(int beats); + + /// Luppp internal buffer resizing + void newBufferInTransit(bool n); + bool newBufferInTransit(); + unsigned long recordSpaceAvailable(); + + /** used to update the size of the buffer for this looperclip. The current + * data is copied into the new buffer, then the smaller buffer is sent + * for de-allocation. + **/ + void setRequestedBuffer( AudioBuffer* ab ); + + /// used for saving the contents of this buffer to disk + void recieveSaveBuffer( AudioBuffer* ab ); + + ///reset the play head to zero. Does nothing when recording + void setPlayHead(float ph); - ///reset the play head to zero. Does nothing when recording - void setPlayHead(float ph); - #ifdef BUILD_TESTS - // used only in test cases - void setState( bool load, bool play, bool rec, bool qPlay, bool qStop, bool qRec ); + // used only in test cases + void setState( bool load, bool play, bool rec, bool qPlay, bool qStop, bool qRec ); #endif - - private: - int track, scene; - - /** Luppp needs more than the current state of the clip to accuratly handle - * it. The current state of the grid is kept up-to-date by GridLogic - * abstracting detail away, sending GridLogic::State to Controllers. - **/ - bool _loaded; - bool _playing; - bool _recording; - - bool _queuePlay; - bool _queueStop; - bool _queueRecord; - - bool _newBufferInTransit; - - float _playhead; - float _recordhead; - AudioBuffer* _buffer; + +private: + int track, scene; + + /** Luppp needs more than the current state of the clip to accuratly handle + * it. The current state of the grid is kept up-to-date by GridLogic + * abstracting detail away, sending GridLogic::State to Controllers. + **/ + bool _loaded; + bool _playing; + bool _recording; + + bool _queuePlay; + bool _queueStop; + bool _queueRecord; + + bool _newBufferInTransit; + + float _playhead; + float _recordhead; + AudioBuffer* _buffer; }; #endif // LUPPP_LOOPER_CLIP_H diff --git a/src/main.cxx b/src/main.cxx index eb33f29..c4cc787 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -45,99 +45,92 @@ Jack* jack = 0; void signalHanlder(int signum) { - signalHanlderInt = signum; + signalHanlderInt = signum; } static void gui_static_loadSession_cb(void* inst) { - char* tmp = (char*) inst; - int sess = gui->getDiskReader()->readSession( tmp ); - if ( sess != LUPPP_RETURN_OK ) - LUPPP_ERROR( "Error loading session" ); + char* tmp = (char*) inst; + int sess = gui->getDiskReader()->readSession( tmp ); + if ( sess != LUPPP_RETURN_OK ) + LUPPP_ERROR( "Error loading session" ); } int main(int argc, char** argv) { - LUPPP_NOTE("Git: %s", GIT_VERSION ); - - bool runTests = false; - if ( runTests ){} // remove unused warning if not built with BUILD_TESTS - - for(int i = 0; i < argc; i++) - { - if ( strcmp(argv[i], "-test" ) == 0 ) { - runTests = true; - } - else if ( i != 0 ) // don't try load with the program name! - { - // assume filename, try load it - Fl::repeat_timeout( 1 / 30.f, &gui_static_loadSession_cb, argv[i] ); - } - } - - // setup the environment - AVOIDDENORMALS(); - signal(SIGINT , signalHanlder); - signal(SIGTERM, signalHanlder); - - // allocate data to read from - processDspMem = (EventBase*)malloc( sizeof(EventBase) ); - processGuiMem = (EventBase*)malloc( sizeof(EventBase) ); - - rbToDsp = jack_ringbuffer_create( 5000 * sizeof(EventBase)); - rbToGui = jack_ringbuffer_create( 5000 * sizeof(EventBase)); - - + LUPPP_NOTE("Git: %s", GIT_VERSION ); + + bool runTests = false; + if ( runTests ) {} // remove unused warning if not built with BUILD_TESTS + + for(int i = 0; i < argc; i++) { + if ( strcmp(argv[i], "-test" ) == 0 ) { + runTests = true; + } else if ( i != 0 ) { // don't try load with the program name! + // assume filename, try load it + Fl::repeat_timeout( 1 / 30.f, &gui_static_loadSession_cb, argv[i] ); + } + } + + // setup the environment + AVOIDDENORMALS(); + signal(SIGINT , signalHanlder); + signal(SIGTERM, signalHanlder); + + // allocate data to read from + processDspMem = (EventBase*)malloc( sizeof(EventBase) ); + processGuiMem = (EventBase*)malloc( sizeof(EventBase) ); + + rbToDsp = jack_ringbuffer_create( 5000 * sizeof(EventBase)); + rbToGui = jack_ringbuffer_create( 5000 * sizeof(EventBase)); + + #ifdef BUILD_TESTS - LUPPP_NOTE("Built with BUILD_TESTS enabled"); - if ( runTests ) - { - // counts failures - int testResult = 0; - - // setup the testing Gui / JACK: Jack first, then GUI - gui = new Gui( argv[0] ); - Jack::setup("LupppTEST"); - - // test offline functionality - testResult += gui->getDiskReader()->runTests(); - testResult += gui->getDiskWriter()->runTests(); - - // test realtime functionality - testResult += jack->getGridLogic()->runTests(); - - jack->quit(); - - delete gui; - delete jack; - jack = 0; - - // running tests == quitting after testing finishes - return testResult; - } - + LUPPP_NOTE("Built with BUILD_TESTS enabled"); + if ( runTests ) { + // counts failures + int testResult = 0; + + // setup the testing Gui / JACK: Jack first, then GUI + gui = new Gui( argv[0] ); + Jack::setup("LupppTEST"); + + // test offline functionality + testResult += gui->getDiskReader()->runTests(); + testResult += gui->getDiskWriter()->runTests(); + + // test realtime functionality + testResult += jack->getGridLogic()->runTests(); + + jack->quit(); + + delete gui; + delete jack; + jack = 0; + + // running tests == quitting after testing finishes + return testResult; + } + #endif - - - // Create a GUI, check for NSM integration - gui = new Gui( argv[0] ); - - if ( gui->getNsm() ) - { - // the NSM OSC Open message will trigger Jack initialization: necessary - // to use the right name to create the JACK client. - } - else - { - Jack::setup("Luppp"); - jack->activate(); - } - - gui->show(); - - - return 0; + + + // Create a GUI, check for NSM integration + gui = new Gui( argv[0] ); + + if ( gui->getNsm() ) { + // the NSM OSC Open message will trigger Jack initialization: necessary + // to use the right name to create the JACK client. + } else { + Jack::setup("Luppp"); + jack->activate(); + } + + gui->show(); + + + return 0; } diff --git a/src/metronome.cxx b/src/metronome.cxx index b9354c5..bb75a19 100644 --- a/src/metronome.cxx +++ b/src/metronome.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -30,91 +30,88 @@ extern Jack* jack; using namespace std; Metronome::Metronome() : - TimeObserver(), - playBar (false), - active (false), - vol (1), - playPoint (0) + TimeObserver(), + playBar (false), + active (false), + vol (1), + playPoint (0) { - //Create Beat/Bar samples - beatSample=new float[jack->getSamplerate()]; - barSample=new float[jack->getSamplerate()]; - // create beat and bar samples - endPoint = ( jack->getSamplerate()/10 ); - // samples per cycle of - float scale = 2 * 3.1415 *880/jack->getSamplerate(); - - // And fill it up - for(int i=0;i < jack->getSamplerate();i++){ - beatSample[i]= sin(i*scale); - barSample [i]= sin(i*scale*2); - } - - // don't play after creation - playPoint = endPoint + 1; + //Create Beat/Bar samples + beatSample=new float[jack->getSamplerate()]; + barSample=new float[jack->getSamplerate()]; + // create beat and bar samples + endPoint = ( jack->getSamplerate()/10 ); + // samples per cycle of + float scale = 2 * 3.1415 *880/jack->getSamplerate(); + + // And fill it up + for(int i=0; i < jack->getSamplerate(); i++) { + beatSample[i]= sin(i*scale); + barSample [i]= sin(i*scale*2); + } + + // don't play after creation + playPoint = endPoint + 1; } Metronome::~Metronome() { - if(beatSample) - delete [] beatSample; - if(barSample) - delete [] barSample; + if(beatSample) + delete [] beatSample; + if(barSample) + delete [] barSample; } void Metronome::setActive(bool a) { - active = a; - // don't play immidiatly - playPoint = endPoint + 1; + active = a; + // don't play immidiatly + playPoint = endPoint + 1; } void Metronome::setVolume( float v ) { - vol = v; - printf(" vol = %f \n", vol ); + vol = v; + printf(" vol = %f \n", vol ); } void Metronome::bar() { - playPoint = 0; - playBar = true; + playPoint = 0; + playBar = true; } void Metronome::beat() { - playPoint = 0; - playBar = false; + playPoint = 0; + playBar = false; } void Metronome::setFpb(int f) { - fpb = f; - - // disable play until next beat - playPoint = endPoint + 1; + fpb = f; + + // disable play until next beat + playPoint = endPoint + 1; } void Metronome::process(int nframes, Buffers* buffers) { - if ( not active ) - return; - - float* out = buffers->audio[Buffers::HEADPHONES_OUT]; - - float* sample = &beatSample[0]; - if( playBar ) - { - sample = &barSample[0]; - } - - for(int i = 0; i < nframes; i++) - { - if ( playPoint < endPoint ) - { - out[i] += sample[playPoint] * vol; - playPoint++; - } - } + if ( not active ) + return; + + float* out = buffers->audio[Buffers::HEADPHONES_OUT]; + + float* sample = &beatSample[0]; + if( playBar ) { + sample = &barSample[0]; + } + + for(int i = 0; i < nframes; i++) { + if ( playPoint < endPoint ) { + out[i] += sample[playPoint] * vol; + playPoint++; + } + } } diff --git a/src/metronome.hxx b/src/metronome.hxx index a33c842..19fd299 100644 --- a/src/metronome.hxx +++ b/src/metronome.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -30,30 +30,30 @@ using namespace std; class Metronome : public TimeObserver { - public: - Metronome(); - ~Metronome(); - - void setActive(bool a); - - void bar(); - void beat(); - void setFpb(int f); - - void setVolume( float v ); - - void process(int nframes, Buffers* buffers); - - private: - int fpb; - bool playBar; - bool active; - float vol; - - int playPoint, endPoint; - float* barSample; - float* beatSample; - +public: + Metronome(); + ~Metronome(); + + void setActive(bool a); + + void bar(); + void beat(); + void setFpb(int f); + + void setVolume( float v ); + + void process(int nframes, Buffers* buffers); + +private: + int fpb; + bool playBar; + bool active; + float vol; + + int playPoint, endPoint; + float* barSample; + float* beatSample; + }; #endif // LUPPP_METRONOME_H diff --git a/src/observer/midi.cxx b/src/observer/midi.cxx index e730157..e3ed147 100644 --- a/src/observer/midi.cxx +++ b/src/observer/midi.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -25,109 +25,101 @@ extern Jack* jack; MidiIO::MidiIO() : - portsRegistered(false), - jackInputPort(0), - jackOutputPort(0) + portsRegistered(false), + jackInputPort(0), + jackOutputPort(0) { - //LUPPP_NOTE("MidiIO %i",this); + //LUPPP_NOTE("MidiIO %i",this); } MidiIO::~MidiIO() { - jack->unregisterMidiIO( this ); - - //LUPPP_NOTE("~MidiIO unregistring ports"); - jack_port_unregister( jack->getJackClientPointer(), jackInputPort ); - jack_port_unregister( jack->getJackClientPointer(), jackOutputPort ); + jack->unregisterMidiIO( this ); + + //LUPPP_NOTE("~MidiIO unregistring ports"); + jack_port_unregister( jack->getJackClientPointer(), jackInputPort ); + jack_port_unregister( jack->getJackClientPointer(), jackOutputPort ); } void MidiIO::writeMidi( unsigned char* data ) { - void* portBuffer = jack_port_get_buffer( jackOutputPort, jack->getBuffersize() ); - - unsigned char* buffer = jack_midi_event_reserve( portBuffer, 0, 3); - if( buffer == 0 ) - { - return; - } - else - { - //memcpy( buffer, data, sizeof(unsigned char)*3 ); - buffer[0] = data[0]; - buffer[1] = data[1]; - buffer[2] = data[2]; - } - + void* portBuffer = jack_port_get_buffer( jackOutputPort, jack->getBuffersize() ); + + unsigned char* buffer = jack_midi_event_reserve( portBuffer, 0, 3); + if( buffer == 0 ) { + return; + } else { + //memcpy( buffer, data, sizeof(unsigned char)*3 ); + buffer[0] = data[0]; + buffer[1] = data[1]; + buffer[2] = data[2]; + } + } int MidiIO::registerMidiPorts(std::string name) { - if( !jack ) - { - LUPPP_ERROR("Attempted register of controller, JACK not instantiated yet!"); - return LUPPP_RETURN_ERROR; - } - - jack_client_t* c = jack->getJackClientPointer(); - - // register the JACK MIDI ports - stringstream i; - i << name << " in"; - jackInputPort = jack_port_register( c, - i.str().c_str(), - JACK_DEFAULT_MIDI_TYPE, - JackPortIsInput, - 0 ); - stringstream o; - o << name << " out"; - jackOutputPort = jack_port_register( c, - o.str().c_str(), - JACK_DEFAULT_MIDI_TYPE, - JackPortIsOutput, - 0 ); - - if ( jackInputPort && jackOutputPort ) - { - //LUPPP_NOTE("%i, %i", jackInputPort, jackOutputPort ); - portsRegistered = true; - return LUPPP_RETURN_OK; - } - else - { - LUPPP_ERROR("Error registering JACK ports" ); - return LUPPP_RETURN_ERROR; - } + if( !jack ) { + LUPPP_ERROR("Attempted register of controller, JACK not instantiated yet!"); + return LUPPP_RETURN_ERROR; + } + + jack_client_t* c = jack->getJackClientPointer(); + + // register the JACK MIDI ports + stringstream i; + i << name << " in"; + jackInputPort = jack_port_register( c, + i.str().c_str(), + JACK_DEFAULT_MIDI_TYPE, + JackPortIsInput, + 0 ); + stringstream o; + o << name << " out"; + jackOutputPort = jack_port_register( c, + o.str().c_str(), + JACK_DEFAULT_MIDI_TYPE, + JackPortIsOutput, + 0 ); + + if ( jackInputPort && jackOutputPort ) { + //LUPPP_NOTE("%i, %i", jackInputPort, jackOutputPort ); + portsRegistered = true; + return LUPPP_RETURN_OK; + } else { + LUPPP_ERROR("Error registering JACK ports" ); + return LUPPP_RETURN_ERROR; + } } void MidiIO::initBuffers(int nframes) { - if ( !portsRegistered ) - return; - - // clear the output buffer - void* outputBuffer= (void*) jack_port_get_buffer( jackOutputPort, nframes ); - jack_midi_clear_buffer( outputBuffer ); + if ( !portsRegistered ) + return; + + // clear the output buffer + void* outputBuffer= (void*) jack_port_get_buffer( jackOutputPort, nframes ); + jack_midi_clear_buffer( outputBuffer ); } void MidiIO::process(int nframes) { - if ( !portsRegistered ) - return; - - // get port buffers and setup - void* inputBuffer = (void*) jack_port_get_buffer( jackInputPort, nframes ); - - jack_midi_event_t event; - int index = 0; - int event_count = (int) jack_midi_get_event_count( inputBuffer ); - while ( index < event_count ) - { - jack_midi_event_get(&event, inputBuffer, index); - midi( (unsigned char*) &event.buffer[0] ); - //printf( "MIDI %i %i %i\n", int(event.buffer[0]), int(event.buffer[1]), int(event.buffer[2]) ); - index++; - } - + if ( !portsRegistered ) + return; + + // get port buffers and setup + void* inputBuffer = (void*) jack_port_get_buffer( jackInputPort, nframes ); + + jack_midi_event_t event; + int index = 0; + int event_count = (int) jack_midi_get_event_count( inputBuffer ); + while ( index < event_count ) { + jack_midi_event_get(&event, inputBuffer, index); + midi( (unsigned char*) &event.buffer[0] ); + //printf( "MIDI %i %i %i\n", int(event.buffer[0]), int(event.buffer[1]), int(event.buffer[2]) ); + index++; + } + } diff --git a/src/observer/midi.hxx b/src/observer/midi.hxx index 4310ee4..9fb3e65 100644 --- a/src/observer/midi.hxx +++ b/src/observer/midi.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -32,32 +32,32 @@ extern Jack* jack; **/ class MidiIO { - public: - MidiIO(); - virtual ~MidiIO(); - - /// name string to show in UI - virtual std::string getName() = 0; - - /// gets / clears MIDI buffers - void initBuffers(int nframes); - - /// gets called each process() in JACK - void process(int nframes); - - /// called by the subclass to create MIDI ports - int registerMidiPorts(std::string name); - - virtual void midi(unsigned char* /*data*/){}; - - void writeMidi( unsigned char* /*data*/ ); - - private: - bool portsRegistered; - // there are jack_port_t* registered ports - jack_port_t* jackInputPort; - jack_port_t* jackOutputPort; - +public: + MidiIO(); + virtual ~MidiIO(); + + /// name string to show in UI + virtual std::string getName() = 0; + + /// gets / clears MIDI buffers + void initBuffers(int nframes); + + /// gets called each process() in JACK + void process(int nframes); + + /// called by the subclass to create MIDI ports + int registerMidiPorts(std::string name); + + virtual void midi(unsigned char* /*data*/) {}; + + void writeMidi( unsigned char* /*data*/ ); + +private: + bool portsRegistered; + // there are jack_port_t* registered ports + jack_port_t* jackInputPort; + jack_port_t* jackOutputPort; + }; #endif // LUPPP_MIDI_IO_H diff --git a/src/observer/time.cxx b/src/observer/time.cxx index 9e8ea58..a0d7c7c 100644 --- a/src/observer/time.cxx +++ b/src/observer/time.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -25,6 +25,6 @@ extern Jack* jack; TimeObserver::TimeObserver() { - jack->getTimeManager()->registerObserver( this ); + jack->getTimeManager()->registerObserver( this ); } diff --git a/src/observer/time.hxx b/src/observer/time.hxx index 6b17a1b..13f5023 100644 --- a/src/observer/time.hxx +++ b/src/observer/time.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -23,23 +23,23 @@ class TimeObserver { - public: - /// registers with TimeManager - TimeObserver(); - virtual ~TimeObserver(){}; - - virtual void setFpb(int fpb){}; - - //Reset any internal set of this object regarding time. Don't reset/delete any buffers!! - //This is not to be confused with Stately::reset() - virtual void resetTimeState(){}; - - virtual void bar(){}; - - virtual void beat(){}; - - virtual void tapTempo(bool b){}; - +public: + /// registers with TimeManager + TimeObserver(); + virtual ~TimeObserver() {}; + + virtual void setFpb(int fpb) {}; + + //Reset any internal set of this object regarding time. Don't reset/delete any buffers!! + //This is not to be confused with Stately::reset() + virtual void resetTimeState() {}; + + virtual void bar() {}; + + virtual void beat() {}; + + virtual void tapTempo(bool b) {}; + }; #endif // LUPPP_TIME_OBSERVER_H diff --git a/src/state/state.cxx b/src/state/state.cxx index 3f4ffb0..f4071db 100644 --- a/src/state/state.cxx +++ b/src/state/state.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -34,38 +34,36 @@ State::State() void State::registerStately(Stately* s) { - statelys.push_back( s ); + statelys.push_back( s ); } void State::save() { - for( unsigned int i = 0; i < statelys.size(); i++) - { - statelys.at(i)->save(); - } + for( unsigned int i = 0; i < statelys.size(); i++) { + statelys.at(i)->save(); + } } void State::reset() { - for( unsigned int i = 0; i < statelys.size(); i++) - { - statelys.at(i)->reset(); - } - - jack->getGridLogic()->updateState(); + for( unsigned int i = 0; i < statelys.size(); i++) { + statelys.at(i)->reset(); + } + + jack->getGridLogic()->updateState(); } void State::finish() { - // trigger the GUI to write the metadata to disk, as each component of the - // engine is done saving - - EventStateSaveFinish e; - writeToGuiRingbuffer( &e ); - + // trigger the GUI to write the metadata to disk, as each component of the + // engine is done saving + + EventStateSaveFinish e; + writeToGuiRingbuffer( &e ); + } int State::getNumStatelys() { - return statelys.size(); + return statelys.size(); } diff --git a/src/state/state.hxx b/src/state/state.hxx index ea4becd..7782fa7 100644 --- a/src/state/state.hxx +++ b/src/state/state.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -29,24 +29,24 @@ **/ class State { - public: - State(); - - /// called to initiate a save on all Statelys - void save(); - - /// called to initiate a reset on all Statelys - void reset(); - - /// called when each part is finished, and we can flush the metadata to disk - void finish(); - - void registerStately(Stately* s); - - int getNumStatelys(); - - private: - std::vector statelys; +public: + State(); + + /// called to initiate a save on all Statelys + void save(); + + /// called to initiate a reset on all Statelys + void reset(); + + /// called when each part is finished, and we can flush the metadata to disk + void finish(); + + void registerStately(Stately* s); + + int getNumStatelys(); + +private: + std::vector statelys; }; #endif // LUPPP_STATE_H diff --git a/src/state/stately.cxx b/src/state/stately.cxx index d77c2a7..6f3ce20 100644 --- a/src/state/stately.cxx +++ b/src/state/stately.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -29,7 +29,7 @@ int Stately::saveErrors = 0; Stately::Stately() { - jack->getState()->registerStately( this ); + jack->getState()->registerStately( this ); } @@ -43,34 +43,32 @@ void Stately::save() void Stately::checkCompletedSave() { - if ( (saveSuccess + saveErrors) >= jack->getState()->getNumStatelys() ) - { - jack->getState()->finish(); - - if ( saveErrors ) - { - // send message to UI to be printed, noting # of clips unsaved due to errors - char buf[50]; - sprintf( buf, "Saved with %i clips !saved due to errors", saveErrors); - EventGuiPrint e( buf ); - writeToGuiRingbuffer( &e ); - } - - // reset in case of another save before quit - saveErrors = 0; - saveSuccess = 0; - } + if ( (saveSuccess + saveErrors) >= jack->getState()->getNumStatelys() ) { + jack->getState()->finish(); + + if ( saveErrors ) { + // send message to UI to be printed, noting # of clips unsaved due to errors + char buf[50]; + sprintf( buf, "Saved with %i clips !saved due to errors", saveErrors); + EventGuiPrint e( buf ); + writeToGuiRingbuffer( &e ); + } + + // reset in case of another save before quit + saveErrors = 0; + saveSuccess = 0; + } } void Stately::success() { - saveSuccess++; - checkCompletedSave(); + saveSuccess++; + checkCompletedSave(); } void Stately::error(const char* errorString) { - // CRITICAL FIXME: add error handling code, noting an error occured, perhaps prompt user? - saveErrors++; - checkCompletedSave(); + // CRITICAL FIXME: add error handling code, noting an error occured, perhaps prompt user? + saveErrors++; + checkCompletedSave(); } diff --git a/src/state/stately.hxx b/src/state/stately.hxx index eb337a5..2bd48e5 100644 --- a/src/state/stately.hxx +++ b/src/state/stately.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -21,40 +21,40 @@ /** Stately * This class is inherited from by all classes that have state. - * + * * save() should be overriden if the object needs to save its state * reset() should be overriden if the object can clear its state - * + * * The flexibility allows eg LooperClips to request buffers to tranfser audio - * data into the GUI thread for disk serialization, and scales for future + * data into the GUI thread for disk serialization, and scales for future * classes which also need to request memory in order to save in a RT safe way. **/ class Stately { - public: - Stately(); - - /// this function being called resets the state of the instance to blank - virtual void reset(); - - /// this function is called when the user initiates a save action - virtual void save(); - - /// this function *must* be called by each sub-class when it is *finished* - /// a successful save action. Once each Stately is done, the final save is OK-ed. - static void success(); - - /// this function notes that a stately could *not* successfully save: buffer - /// size mismatch in LooperClip for example. - static void error(const char* errorString); - - private: - /// holds the amount of successful / error-full saves. Used by success() - /// and error() - static int saveSuccess; - static int saveErrors; - - static void checkCompletedSave(); +public: + Stately(); + + /// this function being called resets the state of the instance to blank + virtual void reset(); + + /// this function is called when the user initiates a save action + virtual void save(); + + /// this function *must* be called by each sub-class when it is *finished* + /// a successful save action. Once each Stately is done, the final save is OK-ed. + static void success(); + + /// this function notes that a stately could *not* successfully save: buffer + /// size mismatch in LooperClip for example. + static void error(const char* errorString); + +private: + /// holds the amount of successful / error-full saves. Used by success() + /// and error() + static int saveSuccess; + static int saveErrors; + + static void checkCompletedSave(); }; #endif // LUPPP_STATELY_H diff --git a/src/tests/diskreadertest.cxx b/src/tests/diskreadertest.cxx index 7aa6238..330efba 100644 --- a/src/tests/diskreadertest.cxx +++ b/src/tests/diskreadertest.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -32,21 +32,21 @@ extern bool testsPassed; int DiskReader::runTests() { - QUnit::UnitTest qunit( QUnit::normal ); - - // set the session path to /tmp for test writing - - string path = "/tmp"; - string session = "testSession"; - - //AudioBuffer ab(440); - //gui->getDiskWriter()->initialize(path, session); - - QUNIT_IS_TRUE( gui->getDiskReader()->loadSample( 0, 0,"/tmp/lupppTestMaterial/beat.wav" ) == LUPPP_RETURN_OK ); - - QUNIT_IS_TRUE( gui->getDiskReader()->readSession("/tmp/lupppTestMaterial/lupppTest" ) == LUPPP_RETURN_OK ); - - return qunit.errors(); + QUnit::UnitTest qunit( QUnit::normal ); + + // set the session path to /tmp for test writing + + string path = "/tmp"; + string session = "testSession"; + + //AudioBuffer ab(440); + //gui->getDiskWriter()->initialize(path, session); + + QUNIT_IS_TRUE( gui->getDiskReader()->loadSample( 0, 0,"/tmp/lupppTestMaterial/beat.wav" ) == LUPPP_RETURN_OK ); + + QUNIT_IS_TRUE( gui->getDiskReader()->readSession("/tmp/lupppTestMaterial/lupppTest" ) == LUPPP_RETURN_OK ); + + return qunit.errors(); } #endif diff --git a/src/tests/diskwritertest.cxx b/src/tests/diskwritertest.cxx index 90cc4d4..100196e 100644 --- a/src/tests/diskwritertest.cxx +++ b/src/tests/diskwritertest.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -35,51 +35,51 @@ extern bool testsPassed; int DiskWriter::runTests() { - QUnit::UnitTest qunit( QUnit::normal ); - - // set the session path to /tmp for test writing - - string path = "/tmp"; - string session = "testSession"; - - AudioBuffer ab(440); - gui->getDiskWriter()->initialize(path, session); - - QUNIT_IS_TRUE( gui->getDiskWriter()->writeAudioBuffer(0, 0, &ab) == LUPPP_RETURN_OK ); - QUNIT_IS_TRUE( gui->getDiskWriter()->writeSession() == LUPPP_RETURN_OK ); - - QUNIT_IS_TRUE( strcmp( gui->getDiskWriter()->getLastSavePath().c_str(), path.c_str() ) == 0 ); - QUNIT_IS_TRUE( strcmp( gui->getDiskWriter()->getLastSaveName().c_str(), session.c_str() ) == 0 ); - - /** write controller test: - * This test ensures that when writing a GenericMIDI* controller to disk the - * data is correct. A dummy controller instance is setup, and then written to - * disk. - **/ - int waste = 0; - GenericMIDI* dummy = new GenericMIDI( waste, "dummy" ); - std::string name = "dummy name"; - std::string author = "dummy author"; - std::string link = "www.dummylink.com"; - - int d = gui->getDiskWriter()->writeControllerFile( dummy ); - QUNIT_IS_TRUE( d == LUPPP_RETURN_OK ); - - dummy->setupBinding( Event::TRACK_VOLUME, 176, 7, 0, 0, 0, 0 ); - dummy->setupBinding( Event::GRID_LAUNCH_SCENE, 144, 60, 0, 2, 0, 0 ); - - int d1 = gui->getDiskWriter()->writeControllerFile( dummy ); - QUNIT_IS_TRUE( d1 == LUPPP_RETURN_OK ); - - /// test dynamic cast, null, and invalid Controller* type - int r1 = gui->getDiskWriter()->writeControllerFile( 0 ); - QUNIT_IS_TRUE( r1 == LUPPP_RETURN_ERROR ); - - Controller* non = new NonSeq(); - int r2 = gui->getDiskWriter()->writeControllerFile( non); - QUNIT_IS_TRUE( r2 == LUPPP_RETURN_ERROR ); - - return qunit.errors(); + QUnit::UnitTest qunit( QUnit::normal ); + + // set the session path to /tmp for test writing + + string path = "/tmp"; + string session = "testSession"; + + AudioBuffer ab(440); + gui->getDiskWriter()->initialize(path, session); + + QUNIT_IS_TRUE( gui->getDiskWriter()->writeAudioBuffer(0, 0, &ab) == LUPPP_RETURN_OK ); + QUNIT_IS_TRUE( gui->getDiskWriter()->writeSession() == LUPPP_RETURN_OK ); + + QUNIT_IS_TRUE( strcmp( gui->getDiskWriter()->getLastSavePath().c_str(), path.c_str() ) == 0 ); + QUNIT_IS_TRUE( strcmp( gui->getDiskWriter()->getLastSaveName().c_str(), session.c_str() ) == 0 ); + + /** write controller test: + * This test ensures that when writing a GenericMIDI* controller to disk the + * data is correct. A dummy controller instance is setup, and then written to + * disk. + **/ + int waste = 0; + GenericMIDI* dummy = new GenericMIDI( waste, "dummy" ); + std::string name = "dummy name"; + std::string author = "dummy author"; + std::string link = "www.dummylink.com"; + + int d = gui->getDiskWriter()->writeControllerFile( dummy ); + QUNIT_IS_TRUE( d == LUPPP_RETURN_OK ); + + dummy->setupBinding( Event::TRACK_VOLUME, 176, 7, 0, 0, 0, 0 ); + dummy->setupBinding( Event::GRID_LAUNCH_SCENE, 144, 60, 0, 2, 0, 0 ); + + int d1 = gui->getDiskWriter()->writeControllerFile( dummy ); + QUNIT_IS_TRUE( d1 == LUPPP_RETURN_OK ); + + /// test dynamic cast, null, and invalid Controller* type + int r1 = gui->getDiskWriter()->writeControllerFile( 0 ); + QUNIT_IS_TRUE( r1 == LUPPP_RETURN_ERROR ); + + Controller* non = new NonSeq(); + int r2 = gui->getDiskWriter()->writeControllerFile( non); + QUNIT_IS_TRUE( r2 == LUPPP_RETURN_ERROR ); + + return qunit.errors(); } #endif diff --git a/src/tests/goptionstest.cxx b/src/tests/goptionstest.cxx index d2fdd12..8e802c4 100644 --- a/src/tests/goptionstest.cxx +++ b/src/tests/goptionstest.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -26,14 +26,14 @@ int OptionsWindow::runTests() { - QUnit::UnitTest qunit( QUnit::normal, true ); - - OptionsWindow opts; - //opts.show(); - //Fl::run(); - - //QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == s ); - return 0; + QUnit::UnitTest qunit( QUnit::normal, true ); + + OptionsWindow opts; + //opts.show(); + //Fl::run(); + + //QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == s ); + return 0; } #endif // BUILD_TESTS diff --git a/src/tests/gridlogictests.cxx b/src/tests/gridlogictests.cxx index c219778..18d3452 100644 --- a/src/tests/gridlogictests.cxx +++ b/src/tests/gridlogictests.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -32,124 +32,124 @@ extern Jack* jack; int GridLogic::runTests() { - QUnit::UnitTest qunit( QUnit::normal, true ); - int t = 0; - int s = 0; - LooperClip* lc = jack->getLooper( t )->getClip( s ); - - // "pretty" prints the state of the clip - //LUPPP_NOTE("%s", GridLogic::StateString[ lc->getState() ] ); - - /// SCENE LAUNCH - lc->init(); - jack->getGridLogic()->launchScene( s ); - QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == s ); - - /// QUEUE s1, then launch s2, s1 - int launchScene = s + 1; - lc->init(); - lc->setState( true, false, false, true, false, false ); // loaded + qplay - LUPPP_NOTE("state before = %s", GridLogic::StateString[ lc->getState() ] ); - jack->getGridLogic()->launchScene( launchScene ); // launch different clip - - QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == launchScene ); - LUPPP_NOTE("state after launch before bar = %s", GridLogic::StateString[ lc->getState() ] ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED ); - - jack->getGridLogic()->bar(); - - LUPPP_NOTE("state after bar = %s", GridLogic::StateString[ lc->getState() ] ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED ); - - /// s1 playing, then launch s2, s1 - lc->init(); - lc->setState( true, true, false, false, false, false ); // playing - //LUPPP_NOTE("state before = %s", GridLogic::StateString[ lc->getState() ] ); - jack->getGridLogic()->launchScene( launchScene ); // launch different clip - QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == launchScene ); - //LUPPP_NOTE("state after before bar = %s", GridLogic::StateString[ lc->getState() ] ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED ); - jack->getGridLogic()->bar(); - //LUPPP_NOTE("state after bar = %s", GridLogic::StateString[ lc->getState() ] ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED ); - - - /// PRESS PAD - // empty -> recording - lc->init(); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_EMPTY ); - jack->getGridLogic()->pressed( t, s ); - jack->getGridLogic()->released( t, s ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORD_QUEUED ); - jack->getGridLogic()->bar(); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORDING ); - - float buffer[64]; - lc->record(64, &buffer[0], &buffer[0]); - - // recording -> playing - jack->getGridLogic()->pressed( t, s ); - jack->getGridLogic()->released( t, s ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED ); - jack->getGridLogic()->bar(); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING ); - // playing -> stopped - jack->getGridLogic()->pressed( t, s ); - jack->getGridLogic()->released( t, s ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED ); - jack->getGridLogic()->bar(); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED ); - // stopped -> playing - jack->getGridLogic()->pressed( t, s ); - jack->getGridLogic()->released( t, s ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED ); - jack->getGridLogic()->bar(); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING ); - - - /// DOUBLE PRESS PAD - // empty -> recordQ -> empty - lc->init(); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_EMPTY ); - jack->getGridLogic()->pressed( t, s ); - jack->getGridLogic()->released( t, s ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORD_QUEUED ); - jack->getGridLogic()->pressed( t, s ); - jack->getGridLogic()->released( t, s ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_EMPTY ); - lc->bar(); - - // recording -> playing -> stopped - lc->setState( true, false, true, false, false, false ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORDING ); - jack->getGridLogic()->pressed( t, s ); - jack->getGridLogic()->released( t, s ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED ); - jack->getGridLogic()->pressed( t, s ); - jack->getGridLogic()->released( t, s ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED ); - lc->bar(); - - // stopped -> playing -> stopped - lc->setState( true, false, false, false, false, false ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED ); - jack->getGridLogic()->pressed( t, s ); - jack->getGridLogic()->released( t, s ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED ); - jack->getGridLogic()->pressed( t, s ); - jack->getGridLogic()->released( t, s ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED ); - - // stopped -> playing - lc->setState( true, true, false, false, false, false ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING ); - jack->getGridLogic()->pressed( t, s ); - jack->getGridLogic()->released( t, s ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED ); - jack->getGridLogic()->pressed( t, s ); - jack->getGridLogic()->released( t, s ); - QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING ); - return qunit.errors(); + QUnit::UnitTest qunit( QUnit::normal, true ); + int t = 0; + int s = 0; + LooperClip* lc = jack->getLooper( t )->getClip( s ); + + // "pretty" prints the state of the clip + //LUPPP_NOTE("%s", GridLogic::StateString[ lc->getState() ] ); + + /// SCENE LAUNCH + lc->init(); + jack->getGridLogic()->launchScene( s ); + QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == s ); + + /// QUEUE s1, then launch s2, s1 + int launchScene = s + 1; + lc->init(); + lc->setState( true, false, false, true, false, false ); // loaded + qplay + LUPPP_NOTE("state before = %s", GridLogic::StateString[ lc->getState() ] ); + jack->getGridLogic()->launchScene( launchScene ); // launch different clip + + QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == launchScene ); + LUPPP_NOTE("state after launch before bar = %s", GridLogic::StateString[ lc->getState() ] ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED ); + + jack->getGridLogic()->bar(); + + LUPPP_NOTE("state after bar = %s", GridLogic::StateString[ lc->getState() ] ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED ); + + /// s1 playing, then launch s2, s1 + lc->init(); + lc->setState( true, true, false, false, false, false ); // playing + //LUPPP_NOTE("state before = %s", GridLogic::StateString[ lc->getState() ] ); + jack->getGridLogic()->launchScene( launchScene ); // launch different clip + QUNIT_IS_TRUE( jack->getGridLogic()->getLaunchedScene() == launchScene ); + //LUPPP_NOTE("state after before bar = %s", GridLogic::StateString[ lc->getState() ] ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED ); + jack->getGridLogic()->bar(); + //LUPPP_NOTE("state after bar = %s", GridLogic::StateString[ lc->getState() ] ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED ); + + + /// PRESS PAD + // empty -> recording + lc->init(); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_EMPTY ); + jack->getGridLogic()->pressed( t, s ); + jack->getGridLogic()->released( t, s ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORD_QUEUED ); + jack->getGridLogic()->bar(); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORDING ); + + float buffer[64]; + lc->record(64, &buffer[0], &buffer[0]); + + // recording -> playing + jack->getGridLogic()->pressed( t, s ); + jack->getGridLogic()->released( t, s ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED ); + jack->getGridLogic()->bar(); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING ); + // playing -> stopped + jack->getGridLogic()->pressed( t, s ); + jack->getGridLogic()->released( t, s ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED ); + jack->getGridLogic()->bar(); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED ); + // stopped -> playing + jack->getGridLogic()->pressed( t, s ); + jack->getGridLogic()->released( t, s ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED ); + jack->getGridLogic()->bar(); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING ); + + + /// DOUBLE PRESS PAD + // empty -> recordQ -> empty + lc->init(); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_EMPTY ); + jack->getGridLogic()->pressed( t, s ); + jack->getGridLogic()->released( t, s ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORD_QUEUED ); + jack->getGridLogic()->pressed( t, s ); + jack->getGridLogic()->released( t, s ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_EMPTY ); + lc->bar(); + + // recording -> playing -> stopped + lc->setState( true, false, true, false, false, false ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_RECORDING ); + jack->getGridLogic()->pressed( t, s ); + jack->getGridLogic()->released( t, s ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED ); + jack->getGridLogic()->pressed( t, s ); + jack->getGridLogic()->released( t, s ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED ); + lc->bar(); + + // stopped -> playing -> stopped + lc->setState( true, false, false, false, false, false ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOPPED ); + jack->getGridLogic()->pressed( t, s ); + jack->getGridLogic()->released( t, s ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAY_QUEUED ); + jack->getGridLogic()->pressed( t, s ); + jack->getGridLogic()->released( t, s ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED ); + + // stopped -> playing + lc->setState( true, true, false, false, false, false ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING ); + jack->getGridLogic()->pressed( t, s ); + jack->getGridLogic()->released( t, s ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_STOP_QUEUED ); + jack->getGridLogic()->pressed( t, s ); + jack->getGridLogic()->released( t, s ); + QUNIT_IS_TRUE( lc->getState() == GridLogic::STATE_PLAYING ); + return qunit.errors(); } #endif // BUILD_TESTS diff --git a/src/timemanager.cxx b/src/timemanager.cxx index edb9786..1a262d3 100644 --- a/src/timemanager.cxx +++ b/src/timemanager.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -33,259 +33,241 @@ extern Jack* jack; using namespace std; TimeManager::TimeManager(): - transportState( TRANSPORT_ROLLING ), - observers() + transportState( TRANSPORT_ROLLING ), + observers() { - samplerate = jack->getSamplerate(); - // 120 BPM default - fpb = samplerate / 2; - - //Counter for current bar/beat - barCounter = 0; - beatCounter = 0; - - previousBeat = 0; - - //In process() we want to immediately process bar(), beat() of all observers - // thats why beatFrameCountdowngetSamplerate(); + // 120 BPM default + fpb = samplerate / 2; + + //Counter for current bar/beat + barCounter = 0; + beatCounter = 0; + + previousBeat = 0; + + //In process() we want to immediately process bar(), beat() of all observers + // thats why beatFrameCountdownresetTimeState(); - */ + setFpb( samplerate / bpm * 60 ); + barCounter = 0; + beatCounter = 0; + beatFrameCountdown = -1; + /* + for(int i=0;iresetTimeState(); + */ } void TimeManager::setBpmZeroOne(float b) { - setBpm( b * 160 + 60 ); // 60 - 220 + setBpm( b * 160 + 60 ); // 60 - 220 } void TimeManager::setFpb(float f) { - fpb = f; - int bpm = ( samplerate * 60) / f; - - char buffer [50]; - sprintf (buffer, "TM, setFpb() %i, bpm = %i", int(f), int(bpm) ); - EventGuiPrint e( buffer ); - writeToGuiRingbuffer( &e ); - - EventTimeBPM e2( bpm ); - writeToGuiRingbuffer( &e2 ); - - for(uint i = 0; i < observers.size(); i++) - { - observers.at(i)->setFpb(fpb); - } + fpb = f; + int bpm = ( samplerate * 60) / f; + + char buffer [50]; + sprintf (buffer, "TM, setFpb() %i, bpm = %i", int(f), int(bpm) ); + EventGuiPrint e( buffer ); + writeToGuiRingbuffer( &e ); + + EventTimeBPM e2( bpm ); + writeToGuiRingbuffer( &e2 ); + + for(uint i = 0; i < observers.size(); i++) { + observers.at(i)->setFpb(fpb); + } } void TimeManager::registerObserver(TimeObserver* o) { - //LUPPP_NOTE("%s","registerObserver()"); - observers.push_back(o); - o->setFpb( fpb ); - - int bpm = ( samplerate * 60) / fpb; - EventTimeBPM e2( bpm ); - writeToGuiRingbuffer( &e2 ); + //LUPPP_NOTE("%s","registerObserver()"); + observers.push_back(o); + o->setFpb( fpb ); + + int bpm = ( samplerate * 60) / fpb; + EventTimeBPM e2( bpm ); + writeToGuiRingbuffer( &e2 ); } void TimeManager::tap() { - // reset tap tempo to "first tap" if more than 5 secs elapsed since last tap - if ( tapTempo[0] < totalFrameCounter - samplerate * 5 ) - { - tapTempoPos = 0; - } - - if ( tapTempoPos < 3 ) - { - tapTempo[tapTempoPos] = totalFrameCounter; - tapTempoPos++; - } - else - { - // calculate frames per tap - int tapFpb1 = tapTempo[1] - tapTempo[0]; - int tapFpb2 = tapTempo[2] - tapTempo[1]; - int tapFpb3 = totalFrameCounter - tapTempo[2]; // last tap, until now - - int average = (tapFpb1 + tapFpb2 + tapFpb3) / 3; + // reset tap tempo to "first tap" if more than 5 secs elapsed since last tap + if ( tapTempo[0] < totalFrameCounter - samplerate * 5 ) { + tapTempoPos = 0; + } - if( average < 13000 ) - { - char buffer [50]; - sprintf (buffer, "TM, tap() average too slow! quitting"); - EventGuiPrint e( buffer ); - writeToGuiRingbuffer( &e ); - return; - } - - char buffer [50]; - sprintf (buffer, "TM, tap() average = %i", average ); - EventGuiPrint e( buffer ); - writeToGuiRingbuffer( &e ); - + if ( tapTempoPos < 3 ) { + tapTempo[tapTempoPos] = totalFrameCounter; + tapTempoPos++; + } else { + // calculate frames per tap + int tapFpb1 = tapTempo[1] - tapTempo[0]; + int tapFpb2 = tapTempo[2] - tapTempo[1]; + int tapFpb3 = totalFrameCounter - tapTempo[2]; // last tap, until now - setFpb(average); - - // reset, so next 3 taps restart process - tapTempoPos = 0; - } + int average = (tapFpb1 + tapFpb2 + tapFpb3) / 3; + + if( average < 13000 ) { + char buffer [50]; + sprintf (buffer, "TM, tap() average too slow! quitting"); + EventGuiPrint e( buffer ); + writeToGuiRingbuffer( &e ); + return; + } + + char buffer [50]; + sprintf (buffer, "TM, tap() average = %i", average ); + EventGuiPrint e( buffer ); + writeToGuiRingbuffer( &e ); + + + setFpb(average); + + // reset, so next 3 taps restart process + tapTempoPos = 0; + } } int TimeManager::getNframesToBeat() { - // FIXME - return -1; //beatFrameCountdown; + // FIXME + return -1; //beatFrameCountdown; } void TimeManager::setTransportState( TRANSPORT_STATE s ) { - transportState = s; - if(transportState == TRANSPORT_STOPPED) - jack->transportRolling(false); - else - { - jack->transportRolling(true); - barCounter = 0; - beatCounter = 0; - beatFrameCountdown = -1; - for(int i=0;iresetTimeState(); - } + transportState = s; + if(transportState == TRANSPORT_STOPPED) + jack->transportRolling(false); + else { + jack->transportRolling(true); + barCounter = 0; + beatCounter = 0; + beatFrameCountdown = -1; + for(int i=0; iresetTimeState(); + } } void TimeManager::process(Buffers* buffers) { - // time signature? - //buffers->transportPosition->beats_per_bar = 4; - //buffers->transportPosition->beat_type = 4; - - if ( transportState == TRANSPORT_STOPPED ) - { - return; - } - - int nframes = buffers->nframes; - + // time signature? + //buffers->transportPosition->beats_per_bar = 4; + //buffers->transportPosition->beat_type = 4; + + if ( transportState == TRANSPORT_STOPPED ) { + return; + } + + int nframes = buffers->nframes; - - if ( beatFrameCountdown < nframes ) - { - //length of beat is not multiple of nframes, so need to process last frames of last beat *before* setting next beat - //then set new beat (get the queued actions: play, rec etc) - // then process first frames *after* new beat - int before=(beatCounter*fpb)%nframes; - int after=nframes-before; - - if ( before < nframes && after <= nframes && before + after == nframes ) - { - char buffer [50]; + + + if ( beatFrameCountdown < nframes ) { + //length of beat is not multiple of nframes, so need to process last frames of last beat *before* setting next beat + //then set new beat (get the queued actions: play, rec etc) + // then process first frames *after* new beat + int before=(beatCounter*fpb)%nframes; + int after=nframes-before; + + if ( before < nframes && after <= nframes && before + after == nframes ) { + char buffer [50]; // sprintf (buffer, "Timing OK: before %i, after %i, b+a %i", before, after, before+after ); // EventGuiPrint e2( buffer ); // writeToGuiRingbuffer( &e2 ); - - } - else - { - char buffer [50]; - sprintf (buffer, "Timing Error: before: %i, after %i", before, after ); - EventGuiPrint e2( buffer ); - writeToGuiRingbuffer( &e2 ); - } - - // process before beat: - if(before) - jack->processFrames( before ); - - // handle beat: - // inform observers of new beat FIRST - for(uint i = 0; i < observers.size(); i++) - { - observers.at(i)->beat(); - } - - if ( beatCounter % 4 == 0 ) - { - // inform observers of new bar SECOND - for(uint i = 0; i < observers.size(); i++) - { - observers.at(i)->bar(); - } - barCounter++; - //beatCounter=0; - } - - // process after - // we need to clear internal buffers in order to write *after* frames to them - jack->clearInternalBuffers(nframes); - if(after) - jack->processFrames( after ); - // write new beat to UI (bar info currently not used) - EventTimeBarBeat e( barCounter, beatCounter ); - writeToGuiRingbuffer( &e ); - - - - beatFrameCountdown = fpb-after; - beatCounter++; - } - else - { - jack->processFrames( nframes ); - beatFrameCountdown -= nframes; + } else { + char buffer [50]; + sprintf (buffer, "Timing Error: before: %i, after %i", before, after ); + EventGuiPrint e2( buffer ); + writeToGuiRingbuffer( &e2 ); + } - } + // process before beat: + if(before) + jack->processFrames( before ); - totalFrameCounter += nframes; - - // write BPM / transport info to JACK - int bpm = ( samplerate * 60) / fpb; - if ( buffers->transportPosition ) - { - buffers->transportPosition->valid = (jack_position_bits_t)(JackPositionBBT | JackTransportPosition); - - buffers->transportPosition->bar = beatCounter / 4 + 1;// bars 1-based - buffers->transportPosition->beat = (beatCounter % 4) + 1; // beats 1-4 - - float part = float( fpb-beatFrameCountdown) / fpb; - buffers->transportPosition->tick = part > 1.0f? 0.9999*1920 : part*1920; - - buffers->transportPosition->frame = totalFrameCounter; - - buffers->transportPosition->ticks_per_beat = 1920; - buffers->transportPosition->beats_per_bar = 4; - - buffers->transportPosition->beats_per_minute = bpm; - } + // handle beat: + // inform observers of new beat FIRST + for(uint i = 0; i < observers.size(); i++) { + observers.at(i)->beat(); + } + + if ( beatCounter % 4 == 0 ) { + // inform observers of new bar SECOND + for(uint i = 0; i < observers.size(); i++) { + observers.at(i)->bar(); + } + barCounter++; + //beatCounter=0; + } + + // process after + // we need to clear internal buffers in order to write *after* frames to them + jack->clearInternalBuffers(nframes); + if(after) + jack->processFrames( after ); + + // write new beat to UI (bar info currently not used) + EventTimeBarBeat e( barCounter, beatCounter ); + writeToGuiRingbuffer( &e ); + + + + beatFrameCountdown = fpb-after; + beatCounter++; + } else { + jack->processFrames( nframes ); + beatFrameCountdown -= nframes; + + } + + totalFrameCounter += nframes; + + // write BPM / transport info to JACK + int bpm = ( samplerate * 60) / fpb; + if ( buffers->transportPosition ) { + buffers->transportPosition->valid = (jack_position_bits_t)(JackPositionBBT | JackTransportPosition); + + buffers->transportPosition->bar = beatCounter / 4 + 1;// bars 1-based + buffers->transportPosition->beat = (beatCounter % 4) + 1; // beats 1-4 + + float part = float( fpb-beatFrameCountdown) / fpb; + buffers->transportPosition->tick = part > 1.0f? 0.9999*1920 : part*1920; + + buffers->transportPosition->frame = totalFrameCounter; + + buffers->transportPosition->ticks_per_beat = 1920; + buffers->transportPosition->beats_per_bar = 4; + + buffers->transportPosition->beats_per_minute = bpm; + } } diff --git a/src/timemanager.hxx b/src/timemanager.hxx index a2b2275..f946fc5 100644 --- a/src/timemanager.hxx +++ b/src/timemanager.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -32,57 +32,57 @@ using namespace std; class TimeManager { - public: - TimeManager(); - - int getFpb(); - void setBpm(float bpm); - void setBpmZeroOne(float bpm); - void setFpb(float f); - - /// add a component to be updated for time events - void registerObserver(TimeObserver* o); - - /// call this when a tempo-tap occurs - void tap(); - - /// called to process buffers->nframes samples. If a beat is present, this - /// is handled gracefully, first calling process up to the beat, then doing - /// a beat() event on all TimeObservers, and processing the remaining samples - void process(Buffers* buffers); - - /// returns the number of samples till beat if a beat exists in this process - /// Otherwise returns nframes - int getNframesToBeat(); - - /// TRANSPORT_STATE is defined in transport.hxx - void setTransportState( TRANSPORT_STATE s ); - - private: - int samplerate; - - /// the "state" of the transport: rolling or stopped - TRANSPORT_STATE transportState; - - /// number of frames per beat - int fpb; - - /// holds the number of frames processed - long long totalFrameCounter; - - /// frame number of the last beat - long previousBeat; - - long beatFrameCountdown; - - /// counts bars / beats processed - int barCounter; - int beatCounter; - - int tapTempoPos; - long long tapTempo[3]; - - std::vector observers; +public: + TimeManager(); + + int getFpb(); + void setBpm(float bpm); + void setBpmZeroOne(float bpm); + void setFpb(float f); + + /// add a component to be updated for time events + void registerObserver(TimeObserver* o); + + /// call this when a tempo-tap occurs + void tap(); + + /// called to process buffers->nframes samples. If a beat is present, this + /// is handled gracefully, first calling process up to the beat, then doing + /// a beat() event on all TimeObservers, and processing the remaining samples + void process(Buffers* buffers); + + /// returns the number of samples till beat if a beat exists in this process + /// Otherwise returns nframes + int getNframesToBeat(); + + /// TRANSPORT_STATE is defined in transport.hxx + void setTransportState( TRANSPORT_STATE s ); + +private: + int samplerate; + + /// the "state" of the transport: rolling or stopped + TRANSPORT_STATE transportState; + + /// number of frames per beat + int fpb; + + /// holds the number of frames processed + long long totalFrameCounter; + + /// frame number of the last beat + long previousBeat; + + long beatFrameCountdown; + + /// counts bars / beats processed + int barCounter; + int beatCounter; + + int tapTempoPos; + long long tapTempo[3]; + + std::vector observers; }; #endif // LUPPP_TIME_H diff --git a/src/trackoutput.cxx b/src/trackoutput.cxx index b9fe8f7..cd1d2ed 100644 --- a/src/trackoutput.cxx +++ b/src/trackoutput.cxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -22,149 +22,145 @@ extern Jack* jack; TrackOutput::TrackOutput(int t, AudioProcessor* ap) : - AudioProcessor(), - track(t), - _recordArm(false), - previousInChain(ap) + AudioProcessor(), + track(t), + _recordArm(false), + previousInChain(ap) { - // UI update - uiUpdateConstant = jack->getSamplerate() / 30; - uiUpdateCounter = jack->getSamplerate() / 30; - - dbMeter = new DBMeter( jack->getSamplerate() ); - - _toMaster = 0.8; - _toMasterLag = 0.8; - _toMasterDiff = 0; - _toReverb = 0.0; - _toSidechain = 0.0; - _toPostSidechain = 0.0; - - _toPostfaderActive = 0; - _toKeyActive = 0; - _toXSideActive = true; + // UI update + uiUpdateConstant = jack->getSamplerate() / 30; + uiUpdateCounter = jack->getSamplerate() / 30; + + dbMeter = new DBMeter( jack->getSamplerate() ); + + _toMaster = 0.8; + _toMasterLag = 0.8; + _toMasterDiff = 0; + _toReverb = 0.0; + _toSidechain = 0.0; + _toPostSidechain = 0.0; + + _toPostfaderActive = 0; + _toKeyActive = 0; + _toXSideActive = true; } void TrackOutput::setMaster(float value) { - if(value < 0.01) - value = 0.f; - _toMaster = value; - _toMasterDiff=_toMaster-_toMasterLag; + if(value < 0.01) + value = 0.f; + _toMaster = value; + _toMasterDiff=_toMaster-_toMasterLag; } float TrackOutput::getMaster() { - return _toMaster; + return _toMaster; } bool TrackOutput::recordArm() { - return _recordArm; + return _recordArm; } void TrackOutput::recordArm(bool r) { - _recordArm = r; + _recordArm = r; } void TrackOutput::setSendActive( int send, bool a ) { - switch( send ) - { - case SEND_POSTFADER: - _toPostfaderActive = a; - break; - case SEND_KEY: - _toKeyActive = a; - break; - //case SEND_XSIDE: - // _toXSideActive = a; - default: - break; - } + switch( send ) { + case SEND_POSTFADER: + _toPostfaderActive = a; + break; + case SEND_KEY: + _toKeyActive = a; + break; + //case SEND_XSIDE: + // _toXSideActive = a; + default: + break; + } } void TrackOutput::setSend( int send, float value ) { - switch( send ) - { - case SEND_POSTFADER: - _toReverb = value; - break; - case SEND_KEY: - // setSendActive() handles on/off for this send - //_toSidechain = value; - break; - case SEND_XSIDE: - _toPostSidechain = value; - break; - } + switch( send ) { + case SEND_POSTFADER: + _toReverb = value; + break; + case SEND_KEY: + // setSendActive() handles on/off for this send + //_toSidechain = value; + break; + case SEND_XSIDE: + _toPostSidechain = value; + break; + } } void TrackOutput::process(unsigned int nframes, Buffers* buffers) { - //compute master volume lag; - if(fabs(_toMaster-_toMasterLag)>=fabs(_toMasterDiff/100.0)) - _toMasterLag+=_toMasterDiff/10.0; - // get & zero track buffer - float* trackBuffer = buffers->audio[Buffers::RETURN_TRACK_0 + track]; - memset( trackBuffer, 0, sizeof(float)*nframes ); - - // call process() up the chain - previousInChain->process( nframes, buffers ); - - // run the meter - dbMeter->process( nframes, trackBuffer, trackBuffer ); - - if (uiUpdateCounter > uiUpdateConstant ) - { - float l = dbMeter->getLeftDB() * _toMasterLag; - float r = dbMeter->getRightDB() * _toMasterLag; - EventTrackSignalLevel e( track, l, r ); - writeToGuiRingbuffer( &e ); - uiUpdateCounter = 0; - } - - uiUpdateCounter += nframes; - - // copy audio data into reverb / sidechain / master buffers - float* reverb = buffers->audio[Buffers::SEND]; - float* sidechain = buffers->audio[Buffers::SIDECHAIN_KEY]; - float* postSidechain = buffers->audio[Buffers::SIDECHAIN_SIGNAL]; - - float* masterL = buffers->audio[Buffers::MASTER_OUT_L]; - float* masterR = buffers->audio[Buffers::MASTER_OUT_R]; + //compute master volume lag; + if(fabs(_toMaster-_toMasterLag)>=fabs(_toMasterDiff/100.0)) + _toMasterLag+=_toMasterDiff/10.0; + // get & zero track buffer + float* trackBuffer = buffers->audio[Buffers::RETURN_TRACK_0 + track]; + memset( trackBuffer, 0, sizeof(float)*nframes ); + + // call process() up the chain + previousInChain->process( nframes, buffers ); + + // run the meter + dbMeter->process( nframes, trackBuffer, trackBuffer ); + + if (uiUpdateCounter > uiUpdateConstant ) { + float l = dbMeter->getLeftDB() * _toMasterLag; + float r = dbMeter->getRightDB() * _toMasterLag; + EventTrackSignalLevel e( track, l, r ); + writeToGuiRingbuffer( &e ); + uiUpdateCounter = 0; + } + + uiUpdateCounter += nframes; + + // copy audio data into reverb / sidechain / master buffers + float* reverb = buffers->audio[Buffers::SEND]; + float* sidechain = buffers->audio[Buffers::SIDECHAIN_KEY]; + float* postSidechain = buffers->audio[Buffers::SIDECHAIN_SIGNAL]; + + float* masterL = buffers->audio[Buffers::MASTER_OUT_L]; + float* masterR = buffers->audio[Buffers::MASTER_OUT_R]; - float* jackoutput = buffers->audio[Buffers::JACK_TRACK_0+track]; - - for(unsigned int i = 0; i < nframes; i++) - { - // * master for "post-fader" sends - float tmp = trackBuffer[i]; - - // post-sidechain *moves* signal between "before/after" ducking, not add! - masterL[i] += tmp * _toMasterLag * (1-_toPostSidechain); - masterR[i] += tmp * _toMasterLag * (1-_toPostSidechain); - if(jackoutput) - jackoutput[i] = tmp * _toMasterLag * (1-_toPostSidechain); - if ( _toPostfaderActive ) - reverb[i] += tmp * _toReverb * _toMasterLag; - - if ( _toXSideActive ) - postSidechain[i] += tmp * _toPostSidechain * _toMasterLag; - - // turning down an element in the mix should *NOT* influence sidechaining - if ( _toKeyActive ) - sidechain[i] += tmp; - - } + float* jackoutput = buffers->audio[Buffers::JACK_TRACK_0+track]; + + for(unsigned int i = 0; i < nframes; i++) { + // * master for "post-fader" sends + float tmp = trackBuffer[i]; + + // post-sidechain *moves* signal between "before/after" ducking, not add! + masterL[i] += tmp * _toMasterLag * (1-_toPostSidechain); + masterR[i] += tmp * _toMasterLag * (1-_toPostSidechain); + if(jackoutput) + jackoutput[i] = tmp * _toMasterLag * (1-_toPostSidechain); + if ( _toPostfaderActive ) + reverb[i] += tmp * _toReverb * _toMasterLag; + + if ( _toXSideActive ) + postSidechain[i] += tmp * _toPostSidechain * _toMasterLag; + + // turning down an element in the mix should *NOT* influence sidechaining + if ( _toKeyActive ) + sidechain[i] += tmp; + + } } TrackOutput::~TrackOutput() { - delete dbMeter; + delete dbMeter; } diff --git a/src/trackoutput.hxx b/src/trackoutput.hxx index a4382bb..f7e81d3 100644 --- a/src/trackoutput.hxx +++ b/src/trackoutput.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -35,52 +35,52 @@ **/ class TrackOutput : public AudioProcessor { - public: - TrackOutput(int t, AudioProcessor* ap); - - /// set main mix, 0-1 - void setMaster(float value); - - float getMaster(); - - bool recordArm(); - void recordArm(bool r); - - /// set send - void setSend( int send, float value ); - void setSendActive( int send, bool active ); - - /// copies the track output to master buffer, sidechain & post-side buffer - void process(unsigned int nframes, Buffers* buffers); - - ~TrackOutput(); - - private: - int track; - - bool _recordArm; - /// _toMasterLag is a volume that lags behind _toMaster when setMaster() is called - /// This prohibits audible jumps when rapidly changing the volume - float _toMaster; - float _toMasterLag; - float _toMasterDiff; +public: + TrackOutput(int t, AudioProcessor* ap); + + /// set main mix, 0-1 + void setMaster(float value); + + float getMaster(); + + bool recordArm(); + void recordArm(bool r); + + /// set send + void setSend( int send, float value ); + void setSendActive( int send, bool active ); + + /// copies the track output to master buffer, sidechain & post-side buffer + void process(unsigned int nframes, Buffers* buffers); + + ~TrackOutput(); + +private: + int track; + + bool _recordArm; + /// _toMasterLag is a volume that lags behind _toMaster when setMaster() is called + /// This prohibits audible jumps when rapidly changing the volume + float _toMaster; + float _toMasterLag; + float _toMasterDiff; + + float _toReverb; + float _toSidechain; + float _toPostSidechain; + + bool _toPostfaderActive; + bool _toKeyActive; + bool _toXSideActive; + + /// Pointer to "previous" processor: the graph is backwards + AudioProcessor* previousInChain; + + // Metering variables + long uiUpdateCounter; + long uiUpdateConstant; + DBMeter* dbMeter; - float _toReverb; - float _toSidechain; - float _toPostSidechain; - - bool _toPostfaderActive; - bool _toKeyActive; - bool _toXSideActive; - - /// Pointer to "previous" processor: the graph is backwards - AudioProcessor* previousInChain; - - // Metering variables - long uiUpdateCounter; - long uiUpdateConstant; - DBMeter* dbMeter; - }; #endif // LUPPP_TRACK_OUTPUT_H diff --git a/src/transport.hxx b/src/transport.hxx index f95e5d9..6dda345 100644 --- a/src/transport.hxx +++ b/src/transport.hxx @@ -1,17 +1,17 @@ /* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -19,10 +19,9 @@ #ifndef LUPPP_TRANSPORT_H #define LUPPP_TRANSPORT_H -enum TRANSPORT_STATE -{ - TRANSPORT_STOPPED = 0, - TRANSPORT_ROLLING, +enum TRANSPORT_STATE { + TRANSPORT_STOPPED = 0, + TRANSPORT_ROLLING, }; #endif