├── screenshot1.JPG ├── screenshot2.JPG ├── ofxStepSequencer.gif ├── 1_example_ofxStepSequencer ├── addons.make ├── bin │ └── data │ │ ├── ofxBeatClock │ │ ├── settings │ │ │ ├── AppSettings.xml │ │ │ ├── MidiInputPort_Settings.xml │ │ │ └── BeatClock_Settings.xml │ │ ├── sounds │ │ │ ├── click1.wav │ │ │ ├── click2.wav │ │ │ └── tapBell.wav │ │ └── fonts │ │ │ └── telegrama_render.otf │ │ ├── assets │ │ └── fonts │ │ │ └── telegrama_render.otf │ │ ├── ofxStepSequencer │ │ ├── presetsControl.xml │ │ ├── fonts │ │ │ └── telegrama_render.otf │ │ ├── settings.xml │ │ └── presets │ │ │ ├── stepSequencer_preset_-2.json │ │ │ ├── stepSequencer_preset_0.json │ │ │ ├── stepSequencer_preset_1.json │ │ │ ├── stepSequencer_preset_2.json │ │ │ ├── stepSequencer_preset_3.json │ │ │ ├── stepSequencer_preset_4.json │ │ │ ├── stepSequencer_preset_5.json │ │ │ ├── stepSequencer_preset_6.json │ │ │ └── stepSequencer_preset_7.json │ │ ├── ofxWindowApp │ │ └── AppWindow.json │ │ └── theme │ │ └── theme_bleurgh.json └── src │ ├── main.cpp │ ├── ofApp.h │ └── ofApp.cpp ├── gitIgnoreUpdate.ps1 ├── libs ├── ofxPresetDataGrid │ ├── README.md │ └── src │ │ ├── DataGrid.h │ │ ├── DataGrid.cpp │ │ ├── ofxPresetDataGrid.h │ │ └── ofxPresetDataGrid.cpp └── ofxSequencer │ ├── src │ ├── ofxSequencerBpm.h │ ├── ofxSequencerBpm.cpp │ ├── ofxSequencer.h │ └── ofxSequencer.cpp │ └── README.md ├── license.md ├── README.md ├── src ├── ofxStepSequencer.h └── ofxStepSequencer.cpp └── .gitignore /screenshot1.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moebiussurfing/ofxStepSequencer/HEAD/screenshot1.JPG -------------------------------------------------------------------------------- /screenshot2.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moebiussurfing/ofxStepSequencer/HEAD/screenshot2.JPG -------------------------------------------------------------------------------- /ofxStepSequencer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moebiussurfing/ofxStepSequencer/HEAD/ofxStepSequencer.gif -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/addons.make: -------------------------------------------------------------------------------- 1 | ofxBeatClock 2 | ofxDawMetro 3 | ofxGui 4 | ofxGuiExtended2 5 | ofxJsonUtils 6 | ofxMidi 7 | ofxSerializer 8 | ofxStepSequencer 9 | ofxWindowApp 10 | -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxBeatClock/settings/AppSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1 4 | 0.5 5 | 6 | -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxBeatClock/sounds/click1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moebiussurfing/ofxStepSequencer/HEAD/1_example_ofxStepSequencer/bin/data/ofxBeatClock/sounds/click1.wav -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxBeatClock/sounds/click2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moebiussurfing/ofxStepSequencer/HEAD/1_example_ofxStepSequencer/bin/data/ofxBeatClock/sounds/click2.wav -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxBeatClock/sounds/tapBell.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moebiussurfing/ofxStepSequencer/HEAD/1_example_ofxStepSequencer/bin/data/ofxBeatClock/sounds/tapBell.wav -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/assets/fonts/telegrama_render.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moebiussurfing/ofxStepSequencer/HEAD/1_example_ofxStepSequencer/bin/data/assets/fonts/telegrama_render.otf -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxBeatClock/settings/MidiInputPort_Settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 0 4 | 5 | -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxStepSequencer/presetsControl.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1 4 | 1 5 | 1 6 | 7 | -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxBeatClock/fonts/telegrama_render.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moebiussurfing/ofxStepSequencer/HEAD/1_example_ofxStepSequencer/bin/data/ofxBeatClock/fonts/telegrama_render.otf -------------------------------------------------------------------------------- /gitIgnoreUpdate.ps1: -------------------------------------------------------------------------------- 1 | 2 | # rm all files 3 | git rm -r --cached . 4 | # add all files as per new .gitignore 5 | git add . 6 | # now, commit for new .gitignore to apply 7 | git commit -m ".gitignore is now working" 8 | -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxStepSequencer/fonts/telegrama_render.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moebiussurfing/ofxStepSequencer/HEAD/1_example_ofxStepSequencer/bin/data/ofxStepSequencer/fonts/telegrama_render.otf -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | //======================================================================== 4 | int main(){ 5 | ofSetupOpenGL(1000, 1065, OF_WINDOW); 6 | ofRunApp(new ofApp()); 7 | } 8 | -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxBeatClock/settings/BeatClock_Settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1 4 | 91.4634 5 | 1 6 | 0 7 | 1 8 | 1 9 | 10 | -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxStepSequencer/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 91.4634 4 | 0 5 | 2 6 | 1 7 | 1 8 | 1 9 | 0 10 | 11 | -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxWindowApp/AppWindow.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "position": { 4 | "x": 409.0, 5 | "y": 92.0 6 | }, 7 | "size": { 8 | "height": 878, 9 | "width": 949 10 | }, 11 | "window_mode": "OF_WINDOW" 12 | }, 13 | { 14 | "extra_settings": { 15 | "debug": "0", 16 | "performance": "1", 17 | "targetFps": "60.5", 18 | "vsync": "0" 19 | } 20 | } 21 | ] -------------------------------------------------------------------------------- /libs/ofxPresetDataGrid/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## ofxPresetDataGrid 3 | 4 | This is an addon helper based on https://github.com/npisanti/ofxGuiPresetSelector. 5 | 6 | Created to handle presets into my other addon: 7 | 8 | https://github.com/moebiussurfing/ofxStepSequencer. 9 | 10 | Thanks a lot to @npisanti, Nicola Pisanti, MIT License 2016. 11 | 12 | Changes by MoebiusSurfing in this fork: 13 | 14 | + switched preset management from ofxGui panels to a custom data type used for my ofxStepSequencer. 15 | 16 | + switched from ofxGui/ofxGuiPanel to ofxGuiExtended. 17 | 18 | 19 | ## Required addons: 20 | 21 | * ofxJsonUtils 22 | * ofxGuiExtended2. 23 | 24 | 25 | Added a custom class: "DataGrid.h / .cpp". 26 | It's a two dimentions bool array grid matrix step-sequencer-like: 27 | 28 | >int grid [NUM_SEQ_NOTES][NUM_SEQ_BEATS]; 29 | 30 | -------------------------------------------------------------------------------- /libs/ofxPresetDataGrid/src/DataGrid.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by moebiussurfing on 5/15/19. 3 | // 4 | 5 | #pragma once 6 | 7 | #include "ofMain.h" 8 | #include "ofxJsonUtils.h" 9 | 10 | #define NUM_SEQ_NOTES 12//max & fixed size 11 | #define NUM_SEQ_BEATS 16//max & fixed size 12 | 13 | 14 | class DataGrid { 15 | 16 | public: 17 | DataGrid(); 18 | 19 | std::string name; 20 | int id; 21 | 22 | void setup(int nNotes, int nBeats);///for custom grid sizes 23 | int NumSeqNotes = 12; 24 | int NumSeqBeats = 16; 25 | 26 | //- 27 | 28 | // DATA 29 | 30 | vector < vector > grid; 31 | // int grid[NUM_SEQ_NOTES][NUM_SEQ_BEATS]; 32 | 33 | //- 34 | 35 | void save_JSON(string path); 36 | void load_JSON(string path); 37 | 38 | void dump_grid(); 39 | void randomize_grid(); 40 | 41 | string subTag; 42 | 43 | void setName(std::string name); 44 | std::string getName() const; 45 | }; 46 | 47 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | The code in this repository is available under the [MIT License](https://secure.wikimedia.org/wikipedia/en/wiki/Mit_license). 2 | 3 | Copyright (c) [Date] [Author Name] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /libs/ofxSequencer/src/ofxSequencerBpm.h: -------------------------------------------------------------------------------- 1 | // Based on ofxBpm by mirrorboy 2 | 3 | #pragma once 4 | #include "ofMain.h" 5 | #include "ofThread.h" 6 | 7 | class ofxSequencerBpm : private ofThread 8 | { 9 | public: 10 | const float OFX_BPM_MAX = 300.0; 11 | const float OFX_BPM_DEFAULT = 120.0; 12 | const float OFX_BPM_MIN = 1.; 13 | const int OFX_BPM_TICK = 960; 14 | 15 | explicit ofxSequencerBpm(float bpm = 120.0, int beatPerBar = 4); 16 | 17 | void start(); 18 | void stop(); 19 | void reset(); 20 | 21 | void setBpm(float bpm); 22 | float getBpm() const; 23 | 24 | void setBeatPerBar(int beatPerBar); 25 | 26 | bool isPlaying() const; 27 | 28 | ofEvent beatEvent; 29 | 30 | private: 31 | void threadedFunction(); 32 | 33 | float _bpm; 34 | bool _isTick; 35 | bool _isPlaying; 36 | int _countOfTick; 37 | long _totalTime; 38 | long _durationOfTick; 39 | long _remainderOfTick; 40 | 41 | float _preTime; 42 | int _beatPerBar; 43 | 44 | inline int getCountOfTick() const; 45 | }; 46 | 47 | //init 48 | //const float ofxSequencerBpm::OFX_BPM_MAX = 300. ; 49 | //const float ofxSequencerBpm::OFX_BPM_DEFAULT = 120.; 50 | //const float ofxSequencerBpm::OFX_BPM_MIN = 1.; 51 | //const int ofxSequencerBpm::OFX_BPM_TICK = 960; 52 | 53 | -------------------------------------------------------------------------------- /libs/ofxSequencer/README.md: -------------------------------------------------------------------------------- 1 | # ofxSequencer 2 | 3 | [FORK] addon for OpenFrameworks for creating an auto-updating sequencer. a couple of features: 4 | 5 | ## MODIFICATIONS: 6 | - I made this fork to use into: https://github.com/moebiussurfing/ofxStepSequencer. Feel free to check for it! 7 | - Added some methods to get and set values from the grid to store/load presets. 8 | - It only handles bool types. 9 | - A lot of improvements could be made because of my C++ skills absence. It has been hard for me to add these features. I am sure that my changes are not well done or could be better done. Sorry! 10 | 11 | ## TODO: 12 | - Allow resize pattern step sizes and note amount. (Now is 12 notes and 16 beats) 13 | - Improve ofxSequencer integration. I used a lot of workarounds to avoid all my big-skills-limitations. Any help is welcome! 14 | - Add not only bang/bool types like int or float as the original ofxSequencer can handle. Any collaboration on this will be welcome! 15 | 16 | //------------------------------------------------------------------------------------------------------------ 17 | 18 | - can be discrete (all cells 1 or 0) or continuously valued. 19 | - interacts with the mouse. drag the mouse over a cell to change the value, or click it to snap to 0/1 20 | - updates automatically, in its own thread, sends notifier to your app (based on ofxBpm) 21 | 22 | requires [ofxBpm](https://github.com/mirrorboy714/ofxBpm). -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | #include "ofxStepSequencer.h" 6 | 7 | //uncomment if you added this addon to handle window settings 8 | //#define USE_ofxWindowApp 9 | #ifdef USE_ofxWindowApp 10 | #include "ofxWindowApp.h" 11 | #endif 12 | 13 | //TODO: 14 | //adding variable grid size (notes & steps) feature 15 | #define NUM_SEQ_NOTES 12//max & fixed size 16 | #define NUM_SEQ_BEATS 16//max & fixed size 17 | 18 | class ofApp : public ofBaseApp { 19 | 20 | public: 21 | 22 | #ifdef USE_ofxWindowApp 23 | ofxWindowApp windowApp; 24 | #endif 25 | 26 | void setup(); 27 | void update(); 28 | void draw(); 29 | void exit(); 30 | void keyPressed(int key); 31 | 32 | //-- 33 | 34 | ofxStepSequencer SEQ; 35 | void SEQ_Gui_Customize(); 36 | 37 | //-- 38 | 39 | ofxGui gui_Panel_Notes; 40 | ofxGuiContainer* gui_Notes; 41 | 42 | //-- 43 | 44 | //local receivers in ofApp, bool params to receive states triggered from the running sequencer 45 | ofParameter notes_params[NUM_SEQ_NOTES]; 46 | 47 | //CALLBACKS MODE A 48 | void Changed_SEQ_NOTES(ofAbstractParameter& e); 49 | //callback listener for inside class ofxStepSequencer 50 | //this callback is required to receive the sequencer states when playing, 51 | //and to receive to the target bool params 52 | 53 | //CALLBACKS MODE B 54 | //ofParameterGroup notes_paramsGroup; 55 | //void Changed_notes_paramsGroup(ofAbstractParameter &e); 56 | //this callback should be required if we want to control target params from user mouse clicks too, 57 | //not only from sequencer addon when playing. 58 | //if you don't add this callback, the user clicks to the target notes will not be catched. 59 | 60 | //- 61 | }; 62 | -------------------------------------------------------------------------------- /libs/ofxSequencer/src/ofxSequencerBpm.cpp: -------------------------------------------------------------------------------- 1 | // Based on ofxBpm by mirrorboy 2 | 3 | 4 | #include "ofxSequencerBpm.h" 5 | #include "ofMain.h" 6 | 7 | ofxSequencerBpm::ofxSequencerBpm(float bpm,int beatPerBar):_beatPerBar(beatPerBar) 8 | { 9 | _isPlaying = false; 10 | _isTick = false; 11 | setBpm(bpm); 12 | }; 13 | 14 | 15 | void ofxSequencerBpm::start() 16 | { 17 | stop(); 18 | _isPlaying = true; 19 | reset(); 20 | //startThread(true, false); // blocking, verbose 21 | startThread(); 22 | } 23 | 24 | void ofxSequencerBpm::stop() 25 | { 26 | waitForThread(true); 27 | _isPlaying = false; 28 | } 29 | 30 | void ofxSequencerBpm::reset() 31 | { 32 | if( lock() ) 33 | { 34 | _remainderOfTick = 0; 35 | _countOfTick = -1; 36 | _preTime = ofGetElapsedTimeMicros(); 37 | _totalTime = 0; 38 | unlock(); 39 | } 40 | } 41 | 42 | 43 | void ofxSequencerBpm::threadedFunction() 44 | { 45 | while(isThreadRunning() != 0 ) 46 | { 47 | if(lock()) 48 | { 49 | if(_isPlaying == true) 50 | { 51 | long nowTime = ofGetElapsedTimeMicros(); 52 | long deltaTime = nowTime - _preTime; 53 | _preTime = nowTime; 54 | 55 | if(_totalTime + _remainderOfTick >= _durationOfTick) 56 | { 57 | if((_countOfTick % (OFX_BPM_TICK / _beatPerBar)) == 0) { 58 | ofNotifyEvent(beatEvent); 59 | } 60 | _remainderOfTick = (_totalTime + _remainderOfTick) % _durationOfTick; 61 | _totalTime = 0.; 62 | _isTick = true; 63 | 64 | _countOfTick++; 65 | _countOfTick %= OFX_BPM_TICK; 66 | } 67 | else{ 68 | _isTick = false; 69 | } 70 | _totalTime += deltaTime; 71 | 72 | unlock(); 73 | yield(); 74 | } 75 | } 76 | } 77 | } 78 | 79 | void ofxSequencerBpm::setBeatPerBar(int beatPerBar) 80 | { 81 | if(lock()) 82 | { 83 | _beatPerBar = beatPerBar; 84 | unlock(); 85 | } 86 | } 87 | 88 | void ofxSequencerBpm::setBpm(float bpm) 89 | { 90 | if(lock()) 91 | { 92 | if(bpm < OFX_BPM_MIN){ 93 | _bpm = OFX_BPM_MIN; 94 | } 95 | else if(bpm >= OFX_BPM_MAX){ 96 | _bpm = OFX_BPM_MAX; 97 | } 98 | else { 99 | _bpm = bpm; 100 | } 101 | 102 | _durationOfTick = 60. * 1000. * 1000. / (bpm * (OFX_BPM_TICK >> 2)); 103 | unlock(); 104 | } 105 | } 106 | 107 | float ofxSequencerBpm::getBpm() const 108 | { 109 | return _bpm; 110 | } 111 | 112 | bool ofxSequencerBpm::isPlaying() const 113 | { 114 | return _isPlaying; 115 | } 116 | -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/theme/theme_bleurgh.json: -------------------------------------------------------------------------------- 1 | { 2 | "bleurgh": { 3 | "base": { 4 | "background-color": "rgba(0,0,0,0.3)", 5 | "fill-color": "rgba(64,64,64,0.8)", 6 | "border-width": 1, 7 | "padding": 0, 8 | "border-color": "rgba(0,0,0,0.4)", 9 | "margin": 2, 10 | "text-color": "rgba(255,255,255,0.8)", 11 | "text-padding": 5, 12 | "font-family": "assets/fonts/telegrama_render.otf", 13 | "font-size": 8, 14 | "align-content": "center", 15 | "justify-content": "space-around", 16 | "width": "100%" 17 | }, 18 | 19 | "panel": { 20 | "show-header": true, 21 | "background-color": "rgba(0,0,0,0.3)", 22 | "width": 200 23 | }, 24 | 25 | "group": { 26 | "background-color": "rgba(0,0,0,0.2)", 27 | "padding": 0, 28 | "margin": 0, 29 | "margin-bottom": 1, 30 | "align-content": "space-between", 31 | "flex-direction": "row", 32 | "flex-wrap": "wrap", 33 | "width": 200 34 | }, 35 | 36 | "group-header": { 37 | "height": 20, 38 | "margin": 0, 39 | "background-color": "rgba(0,0,0,0.2)", 40 | "text-color": "rgba(255,255,255,1)", 41 | "width": 200 42 | }, 43 | 44 | "slider": { 45 | "fill-color": "rgba(64,64,64,0.8)", 46 | "height": 20, 47 | "precision": 3, 48 | "padding": 0, 49 | "width": "100%", 50 | "border-radius": 1 51 | }, 52 | 53 | "toggle": { 54 | "height": 24, 55 | "background-color": "rgba(64,64,64,0.3)", 56 | "border-color": "rgba(32,32,32,0.4)", 57 | "fill-color": "rgba(128,128,128,0.7)", 58 | "type": "radio", 59 | "border-width": 1 60 | }, 61 | 62 | "button": { 63 | "fill-color": "rgba(128,128,128,0.8)", 64 | "background-color": "rgba(64,64,64,0.4)", 65 | "type": "fullsize" 66 | }, 67 | 68 | "label": { 69 | "text-color": "rgba(255,255,255,0.7)", 70 | "border-color": "transparent" 71 | }, 72 | 73 | "graphics": { 74 | "background-color": "rgba(0,0,0,0.4)" 75 | }, 76 | 77 | "value-plotter": { 78 | "fill-color": "rgba(64,64,64,1)", 79 | "height": 20, 80 | "precision": 3 81 | }, 82 | 83 | "function-plotter": { 84 | "fill-color": "rgba(64,64,64,1)", 85 | "precision": 3 86 | }, 87 | 88 | "tabs": { 89 | "border-color": "rgba(32,32,32,0.4)", 90 | "fill-color": "rgba(64,64,64,0.8)", 91 | "height": 10, 92 | "padding": 10 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ofxStepSequencer 2 | 3 | openFrameworks addon as a basic (bang) step-sequencer manager. Includes tap tempo, internal clock and external MIDI sync with pattern presets manager. 4 | Mainly based on ofxSequencer from @genekogan, ofxMidi from @danomatika and ofxDawMetro from @castovoid among others. 5 | 6 | 7 | 8 | ## Screencast 9 | 10 | ![Alt text](/ofxStepSequencer.gif?raw=true "ofxStepSequencer.gif") 11 | 12 | 13 | 14 | ## Screenshots 15 | 16 | ![Alt text](/screenshot1.JPG?raw=true "screenshot1") 17 | ![Alt text](/screenshot2.JPG?raw=true "screenshot2") 18 | 19 | 20 | 21 | ## Usage 22 | 23 | Create the example project or your own with OF ProjectGenerator as usual. 24 | 25 | Recommended to look at the example. 26 | 27 | 28 | 29 | ```c++ 30 | ofApp.h: 31 | 32 | #include "ofxStepSequencer.h" 33 | 34 | ofxStepSequencer SEQ; 35 | 36 | //local notes_params to receive bang/bools trigged from sequencer 37 | ofParameter notes_params[NUM_SEQ_NOTES]; 38 | 39 | //callback listener 40 | void Changed_SEQ_NOTES(ofAbstractParameter& e); 41 | 42 | //-- 43 | 44 | ofApp.cpp: 45 | 46 | //setup() 47 | SEQ.setup(); 48 | 49 | //callbacks 50 | ofAddListener(SEQ.TARGET_NOTES_paramsGroup.parameterChangedE(), this, &ofApp::Changed_SEQ_NOTES); 51 | 52 | //- 53 | 54 | //update() 55 | SEQ.update(); 56 | 57 | //- 58 | 59 | //draw() 60 | SEQ.draw(); 61 | SEQ.draw_CLOCK(); 62 | 63 | //- 64 | 65 | //callback receiver from sequencer 66 | void ofApp::Changed_SEQ_NOTES(ofAbstractParameter& e) 67 | { 68 | ... 69 | } 70 | ``` 71 | 72 | 73 | 74 | ## Features 75 | 76 | - Internal beat-clock and external midi clock sync. (check ofxBeatClock info) 77 | - Preset manager with 8 patterns presets. 78 | - Helper tool to clone selected preset to the other next presets of your kit. 79 | - Use ctrl + mouse-click to clone preset to the clicked preset position. 80 | - Helper tools to randomize patterns and clone one bar to all other 3. 81 | - API methods to toggle hide/show gui and some others. Please check into the addon to know more. 82 | 83 | 84 | ## Requeriments 85 | 86 | https://github.com/moebiussurfing/ofxBeatClock 87 | https://github.com/danomatika/ofxMidi 88 | https://github.com/castovoid/ofxDawMetro 89 | https://github.com/2bbb/ofxJsonUtils 90 | https://github.com/moebiussurfing/ofxGuiExtended2 (fork) 91 | 92 | Included on the example but not mandatory: 93 | Optional to handle window settings between sessions: 94 | https://github.com/moebiussurfing/ofxWindowApp 95 | 96 | 97 | 98 | ## Tested systems 99 | 100 | - OF 0.11 101 | - Visual Studio 2017 102 | - macOS / HighSierra 103 | 104 | 105 | 106 | ## About 107 | 108 | An addon by MoebiusSurfing, 2020. 109 | Kind of beta state but I decided to make it public. Please post issues or problems to solve that I'll reply. 110 | Thanks to developers of all the other addons used, of course. 111 | Specially: 112 | @genekogan for https://github.com/genekogan/ofxSequencer 113 | @npisanti for https://github.com/npisanti/ofxGuiPresetSelector 114 | @castovoid for https://github.com/castovoid/ofxDawMetro 115 | @frauzufall for https://github.com/frauzufall/ofxGuiExtended 116 | @transat for GUI theme 117 | 118 | 119 | 120 | ## TODO: 121 | 122 | - Repair BUG original from ofxSequencer where sometimes mouse-clicks are ignored. Any help is welcome! 123 | - Allow resize pattern step sizes and note amount. (Now is fixed to 12 notes and 16 beats) 124 | - Improve ofxSequencer integration. I used a lot of workarounds to avoid all my big-skills-limitations. Any help is welcome! 125 | - Add not only bang/bool types like int or float as the original ofxSequencer can handle. Any help is welcome! 126 | - Some OSC in/out control. 127 | - Repair little BUG that create some rare xml files into presets folder. 128 | 129 | 130 |
131 | 132 | **PLEASE FEEL FREE TO ADD MODIFICATIONS OR FEATURES AND TO SEND ME ISSUES/PULL REQUESTS. THANKS!** -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxStepSequencer/presets/stepSequencer_preset_-2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "row0": [ 4 | 0, 5 | 0, 6 | 0, 7 | 0, 8 | 0, 9 | 0, 10 | 0, 11 | 0, 12 | 0, 13 | 0, 14 | 0, 15 | 0, 16 | 0, 17 | 0, 18 | 0, 19 | 0 20 | ] 21 | }, 22 | { 23 | "row1": [ 24 | 0, 25 | 0, 26 | 0, 27 | 0, 28 | 0, 29 | 0, 30 | 0, 31 | 0, 32 | 0, 33 | 0, 34 | 0, 35 | 0, 36 | 0, 37 | 0, 38 | 0, 39 | 0 40 | ] 41 | }, 42 | { 43 | "row2": [ 44 | 0, 45 | 0, 46 | 0, 47 | 0, 48 | 0, 49 | 0, 50 | 0, 51 | 0, 52 | 0, 53 | 0, 54 | 0, 55 | 0, 56 | 0, 57 | 0, 58 | 0, 59 | 0 60 | ] 61 | }, 62 | { 63 | "row3": [ 64 | 0, 65 | 0, 66 | 0, 67 | 0, 68 | 0, 69 | 0, 70 | 0, 71 | 0, 72 | 0, 73 | 0, 74 | 0, 75 | 0, 76 | 0, 77 | 0, 78 | 0, 79 | 0 80 | ] 81 | }, 82 | { 83 | "row4": [ 84 | 0, 85 | 0, 86 | 0, 87 | 0, 88 | 0, 89 | 0, 90 | 0, 91 | 0, 92 | 0, 93 | 0, 94 | 0, 95 | 0, 96 | 0, 97 | 0, 98 | 0, 99 | 0 100 | ] 101 | }, 102 | { 103 | "row5": [ 104 | 0, 105 | 0, 106 | 0, 107 | 0, 108 | 0, 109 | 0, 110 | 0, 111 | 0, 112 | 0, 113 | 0, 114 | 0, 115 | 0, 116 | 0, 117 | 0, 118 | 0, 119 | 0 120 | ] 121 | }, 122 | { 123 | "row6": [ 124 | 0, 125 | 0, 126 | 0, 127 | 0, 128 | 0, 129 | 0, 130 | 0, 131 | 0, 132 | 0, 133 | 0, 134 | 0, 135 | 0, 136 | 0, 137 | 0, 138 | 0, 139 | 0 140 | ] 141 | }, 142 | { 143 | "row7": [ 144 | 0, 145 | 0, 146 | 0, 147 | 0, 148 | 0, 149 | 0, 150 | 0, 151 | 0, 152 | 0, 153 | 0, 154 | 0, 155 | 0, 156 | 0, 157 | 0, 158 | 0, 159 | 0 160 | ] 161 | }, 162 | { 163 | "row8": [ 164 | 0, 165 | 0, 166 | 0, 167 | 0, 168 | 0, 169 | 0, 170 | 0, 171 | 0, 172 | 0, 173 | 0, 174 | 0, 175 | 0, 176 | 0, 177 | 0, 178 | 0, 179 | 0 180 | ] 181 | }, 182 | { 183 | "row9": [ 184 | 0, 185 | 0, 186 | 0, 187 | 0, 188 | 0, 189 | 0, 190 | 0, 191 | 0, 192 | 0, 193 | 0, 194 | 0, 195 | 0, 196 | 0, 197 | 0, 198 | 0, 199 | 0 200 | ] 201 | }, 202 | { 203 | "row10": [ 204 | 0, 205 | 0, 206 | 0, 207 | 0, 208 | 0, 209 | 0, 210 | 0, 211 | 0, 212 | 0, 213 | 0, 214 | 0, 215 | 0, 216 | 0, 217 | 0, 218 | 0, 219 | 0 220 | ] 221 | }, 222 | { 223 | "row11": [ 224 | 0, 225 | 0, 226 | 0, 227 | 0, 228 | 0, 229 | 0, 230 | 0, 231 | 0, 232 | 0, 233 | 0, 234 | 0, 235 | 0, 236 | 0, 237 | 0, 238 | 0, 239 | 0 240 | ] 241 | } 242 | ] -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxStepSequencer/presets/stepSequencer_preset_0.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "row0": [ 4 | 1, 5 | 0, 6 | 0, 7 | 0, 8 | 0, 9 | 0, 10 | 0, 11 | 0, 12 | 1, 13 | 0, 14 | 0, 15 | 0, 16 | 0, 17 | 0, 18 | 0, 19 | 0 20 | ] 21 | }, 22 | { 23 | "row1": [ 24 | 0, 25 | 0, 26 | 0, 27 | 0, 28 | 1, 29 | 0, 30 | 0, 31 | 0, 32 | 0, 33 | 0, 34 | 0, 35 | 0, 36 | 0, 37 | 0, 38 | 0, 39 | 0 40 | ] 41 | }, 42 | { 43 | "row2": [ 44 | 0, 45 | 0, 46 | 0, 47 | 0, 48 | 0, 49 | 0, 50 | 0, 51 | 0, 52 | 0, 53 | 0, 54 | 0, 55 | 0, 56 | 1, 57 | 0, 58 | 1, 59 | 0 60 | ] 61 | }, 62 | { 63 | "row3": [ 64 | 0, 65 | 0, 66 | 0, 67 | 0, 68 | 0, 69 | 0, 70 | 0, 71 | 0, 72 | 0, 73 | 0, 74 | 0, 75 | 0, 76 | 0, 77 | 0, 78 | 0, 79 | 0 80 | ] 81 | }, 82 | { 83 | "row4": [ 84 | 0, 85 | 0, 86 | 0, 87 | 0, 88 | 0, 89 | 0, 90 | 0, 91 | 0, 92 | 0, 93 | 0, 94 | 0, 95 | 0, 96 | 0, 97 | 0, 98 | 0, 99 | 0 100 | ] 101 | }, 102 | { 103 | "row5": [ 104 | 0, 105 | 0, 106 | 0, 107 | 0, 108 | 0, 109 | 0, 110 | 0, 111 | 0, 112 | 0, 113 | 0, 114 | 0, 115 | 0, 116 | 0, 117 | 0, 118 | 0, 119 | 0 120 | ] 121 | }, 122 | { 123 | "row6": [ 124 | 0, 125 | 0, 126 | 0, 127 | 0, 128 | 0, 129 | 0, 130 | 0, 131 | 0, 132 | 0, 133 | 0, 134 | 0, 135 | 0, 136 | 0, 137 | 0, 138 | 0, 139 | 0 140 | ] 141 | }, 142 | { 143 | "row7": [ 144 | 0, 145 | 0, 146 | 0, 147 | 0, 148 | 0, 149 | 0, 150 | 0, 151 | 0, 152 | 0, 153 | 0, 154 | 0, 155 | 0, 156 | 0, 157 | 0, 158 | 0, 159 | 0 160 | ] 161 | }, 162 | { 163 | "row8": [ 164 | 0, 165 | 0, 166 | 0, 167 | 0, 168 | 0, 169 | 0, 170 | 0, 171 | 0, 172 | 0, 173 | 0, 174 | 0, 175 | 0, 176 | 0, 177 | 0, 178 | 0, 179 | 0 180 | ] 181 | }, 182 | { 183 | "row9": [ 184 | 0, 185 | 0, 186 | 0, 187 | 0, 188 | 0, 189 | 0, 190 | 0, 191 | 0, 192 | 0, 193 | 0, 194 | 0, 195 | 0, 196 | 0, 197 | 0, 198 | 0, 199 | 0 200 | ] 201 | }, 202 | { 203 | "row10": [ 204 | 0, 205 | 0, 206 | 0, 207 | 0, 208 | 0, 209 | 0, 210 | 0, 211 | 0, 212 | 0, 213 | 0, 214 | 0, 215 | 0, 216 | 0, 217 | 0, 218 | 0, 219 | 0 220 | ] 221 | }, 222 | { 223 | "row11": [ 224 | 0, 225 | 0, 226 | 0, 227 | 0, 228 | 0, 229 | 0, 230 | 0, 231 | 0, 232 | 0, 233 | 0, 234 | 0, 235 | 0, 236 | 0, 237 | 0, 238 | 0, 239 | 0 240 | ] 241 | } 242 | ] -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxStepSequencer/presets/stepSequencer_preset_1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "row0": [ 4 | 0, 5 | 0, 6 | 0, 7 | 0, 8 | 0, 9 | 0, 10 | 1, 11 | 0, 12 | 0, 13 | 0, 14 | 0, 15 | 0, 16 | 0, 17 | 0, 18 | 1, 19 | 0 20 | ] 21 | }, 22 | { 23 | "row1": [ 24 | 1, 25 | 0, 26 | 0, 27 | 0, 28 | 0, 29 | 0, 30 | 0, 31 | 0, 32 | 0, 33 | 0, 34 | 0, 35 | 0, 36 | 0, 37 | 0, 38 | 0, 39 | 0 40 | ] 41 | }, 42 | { 43 | "row2": [ 44 | 1, 45 | 0, 46 | 0, 47 | 0, 48 | 0, 49 | 1, 50 | 0, 51 | 0, 52 | 0, 53 | 0, 54 | 0, 55 | 0, 56 | 0, 57 | 1, 58 | 0, 59 | 1 60 | ] 61 | }, 62 | { 63 | "row3": [ 64 | 0, 65 | 0, 66 | 0, 67 | 0, 68 | 0, 69 | 0, 70 | 0, 71 | 0, 72 | 0, 73 | 0, 74 | 0, 75 | 1, 76 | 1, 77 | 0, 78 | 0, 79 | 0 80 | ] 81 | }, 82 | { 83 | "row4": [ 84 | 0, 85 | 0, 86 | 0, 87 | 1, 88 | 0, 89 | 0, 90 | 1, 91 | 1, 92 | 0, 93 | 0, 94 | 0, 95 | 0, 96 | 1, 97 | 0, 98 | 0, 99 | 0 100 | ] 101 | }, 102 | { 103 | "row5": [ 104 | 1, 105 | 1, 106 | 0, 107 | 0, 108 | 0, 109 | 0, 110 | 0, 111 | 0, 112 | 0, 113 | 0, 114 | 0, 115 | 1, 116 | 0, 117 | 0, 118 | 0, 119 | 0 120 | ] 121 | }, 122 | { 123 | "row6": [ 124 | 1, 125 | 0, 126 | 1, 127 | 0, 128 | 0, 129 | 0, 130 | 0, 131 | 0, 132 | 0, 133 | 1, 134 | 0, 135 | 0, 136 | 0, 137 | 0, 138 | 0, 139 | 1 140 | ] 141 | }, 142 | { 143 | "row7": [ 144 | 0, 145 | 0, 146 | 0, 147 | 0, 148 | 0, 149 | 0, 150 | 0, 151 | 0, 152 | 0, 153 | 0, 154 | 0, 155 | 0, 156 | 0, 157 | 0, 158 | 0, 159 | 0 160 | ] 161 | }, 162 | { 163 | "row8": [ 164 | 0, 165 | 0, 166 | 0, 167 | 0, 168 | 1, 169 | 0, 170 | 0, 171 | 1, 172 | 0, 173 | 1, 174 | 1, 175 | 0, 176 | 0, 177 | 0, 178 | 0, 179 | 0 180 | ] 181 | }, 182 | { 183 | "row9": [ 184 | 0, 185 | 0, 186 | 0, 187 | 0, 188 | 1, 189 | 0, 190 | 0, 191 | 0, 192 | 0, 193 | 0, 194 | 0, 195 | 0, 196 | 0, 197 | 0, 198 | 1, 199 | 0 200 | ] 201 | }, 202 | { 203 | "row10": [ 204 | 0, 205 | 0, 206 | 0, 207 | 0, 208 | 0, 209 | 0, 210 | 0, 211 | 0, 212 | 0, 213 | 0, 214 | 0, 215 | 0, 216 | 0, 217 | 0, 218 | 0, 219 | 0 220 | ] 221 | }, 222 | { 223 | "row11": [ 224 | 0, 225 | 0, 226 | 0, 227 | 0, 228 | 0, 229 | 0, 230 | 1, 231 | 0, 232 | 0, 233 | 0, 234 | 0, 235 | 0, 236 | 0, 237 | 0, 238 | 0, 239 | 0 240 | ] 241 | } 242 | ] -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxStepSequencer/presets/stepSequencer_preset_2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "row0": [ 4 | 0, 5 | 0, 6 | 1, 7 | 0, 8 | 1, 9 | 0, 10 | 0, 11 | 0, 12 | 0, 13 | 0, 14 | 0, 15 | 0, 16 | 0, 17 | 0, 18 | 0, 19 | 0 20 | ] 21 | }, 22 | { 23 | "row1": [ 24 | 0, 25 | 0, 26 | 0, 27 | 0, 28 | 0, 29 | 0, 30 | 0, 31 | 1, 32 | 0, 33 | 0, 34 | 0, 35 | 1, 36 | 0, 37 | 0, 38 | 0, 39 | 0 40 | ] 41 | }, 42 | { 43 | "row2": [ 44 | 0, 45 | 1, 46 | 0, 47 | 0, 48 | 1, 49 | 0, 50 | 0, 51 | 0, 52 | 0, 53 | 0, 54 | 0, 55 | 0, 56 | 1, 57 | 0, 58 | 0, 59 | 0 60 | ] 61 | }, 62 | { 63 | "row3": [ 64 | 0, 65 | 1, 66 | 0, 67 | 0, 68 | 0, 69 | 1, 70 | 0, 71 | 1, 72 | 0, 73 | 0, 74 | 0, 75 | 0, 76 | 0, 77 | 1, 78 | 0, 79 | 0 80 | ] 81 | }, 82 | { 83 | "row4": [ 84 | 0, 85 | 0, 86 | 0, 87 | 0, 88 | 0, 89 | 0, 90 | 1, 91 | 0, 92 | 0, 93 | 0, 94 | 0, 95 | 0, 96 | 0, 97 | 0, 98 | 1, 99 | 0 100 | ] 101 | }, 102 | { 103 | "row5": [ 104 | 0, 105 | 0, 106 | 1, 107 | 1, 108 | 0, 109 | 0, 110 | 0, 111 | 1, 112 | 0, 113 | 0, 114 | 0, 115 | 0, 116 | 0, 117 | 0, 118 | 0, 119 | 0 120 | ] 121 | }, 122 | { 123 | "row6": [ 124 | 0, 125 | 1, 126 | 0, 127 | 0, 128 | 0, 129 | 0, 130 | 0, 131 | 0, 132 | 1, 133 | 0, 134 | 0, 135 | 0, 136 | 1, 137 | 0, 138 | 0, 139 | 0 140 | ] 141 | }, 142 | { 143 | "row7": [ 144 | 1, 145 | 0, 146 | 1, 147 | 0, 148 | 1, 149 | 0, 150 | 0, 151 | 0, 152 | 0, 153 | 0, 154 | 1, 155 | 0, 156 | 0, 157 | 1, 158 | 0, 159 | 0 160 | ] 161 | }, 162 | { 163 | "row8": [ 164 | 0, 165 | 0, 166 | 0, 167 | 1, 168 | 0, 169 | 1, 170 | 0, 171 | 1, 172 | 0, 173 | 0, 174 | 0, 175 | 1, 176 | 0, 177 | 0, 178 | 1, 179 | 1 180 | ] 181 | }, 182 | { 183 | "row9": [ 184 | 0, 185 | 0, 186 | 1, 187 | 0, 188 | 0, 189 | 0, 190 | 0, 191 | 0, 192 | 0, 193 | 1, 194 | 0, 195 | 0, 196 | 0, 197 | 0, 198 | 0, 199 | 0 200 | ] 201 | }, 202 | { 203 | "row10": [ 204 | 0, 205 | 0, 206 | 1, 207 | 0, 208 | 0, 209 | 1, 210 | 0, 211 | 1, 212 | 0, 213 | 0, 214 | 1, 215 | 1, 216 | 0, 217 | 0, 218 | 0, 219 | 1 220 | ] 221 | }, 222 | { 223 | "row11": [ 224 | 0, 225 | 0, 226 | 0, 227 | 0, 228 | 0, 229 | 0, 230 | 0, 231 | 1, 232 | 0, 233 | 0, 234 | 0, 235 | 0, 236 | 0, 237 | 1, 238 | 0, 239 | 0 240 | ] 241 | } 242 | ] -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxStepSequencer/presets/stepSequencer_preset_3.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "row0": [ 4 | 0, 5 | 0, 6 | 1, 7 | 1, 8 | 0, 9 | 0, 10 | 1, 11 | 1, 12 | 0, 13 | 0, 14 | 1, 15 | 1, 16 | 0, 17 | 0, 18 | 1, 19 | 1 20 | ] 21 | }, 22 | { 23 | "row1": [ 24 | 0, 25 | 0, 26 | 1, 27 | 0, 28 | 0, 29 | 0, 30 | 1, 31 | 0, 32 | 0, 33 | 0, 34 | 1, 35 | 0, 36 | 0, 37 | 0, 38 | 1, 39 | 0 40 | ] 41 | }, 42 | { 43 | "row2": [ 44 | 0, 45 | 0, 46 | 0, 47 | 0, 48 | 0, 49 | 0, 50 | 0, 51 | 0, 52 | 0, 53 | 0, 54 | 0, 55 | 0, 56 | 0, 57 | 0, 58 | 0, 59 | 0 60 | ] 61 | }, 62 | { 63 | "row3": [ 64 | 0, 65 | 1, 66 | 0, 67 | 0, 68 | 0, 69 | 1, 70 | 0, 71 | 0, 72 | 0, 73 | 1, 74 | 0, 75 | 0, 76 | 0, 77 | 1, 78 | 0, 79 | 0 80 | ] 81 | }, 82 | { 83 | "row4": [ 84 | 0, 85 | 0, 86 | 1, 87 | 0, 88 | 0, 89 | 0, 90 | 1, 91 | 0, 92 | 0, 93 | 0, 94 | 1, 95 | 0, 96 | 0, 97 | 0, 98 | 1, 99 | 0 100 | ] 101 | }, 102 | { 103 | "row5": [ 104 | 0, 105 | 0, 106 | 0, 107 | 0, 108 | 0, 109 | 0, 110 | 0, 111 | 0, 112 | 0, 113 | 0, 114 | 0, 115 | 0, 116 | 0, 117 | 0, 118 | 0, 119 | 0 120 | ] 121 | }, 122 | { 123 | "row6": [ 124 | 0, 125 | 1, 126 | 0, 127 | 0, 128 | 0, 129 | 1, 130 | 0, 131 | 0, 132 | 0, 133 | 1, 134 | 0, 135 | 0, 136 | 0, 137 | 1, 138 | 0, 139 | 0 140 | ] 141 | }, 142 | { 143 | "row7": [ 144 | 0, 145 | 0, 146 | 0, 147 | 0, 148 | 0, 149 | 0, 150 | 0, 151 | 0, 152 | 0, 153 | 0, 154 | 0, 155 | 0, 156 | 0, 157 | 0, 158 | 0, 159 | 0 160 | ] 161 | }, 162 | { 163 | "row8": [ 164 | 1, 165 | 0, 166 | 0, 167 | 0, 168 | 1, 169 | 0, 170 | 0, 171 | 0, 172 | 1, 173 | 0, 174 | 0, 175 | 0, 176 | 1, 177 | 0, 178 | 0, 179 | 0 180 | ] 181 | }, 182 | { 183 | "row9": [ 184 | 0, 185 | 0, 186 | 0, 187 | 1, 188 | 0, 189 | 0, 190 | 0, 191 | 1, 192 | 0, 193 | 0, 194 | 0, 195 | 1, 196 | 0, 197 | 0, 198 | 0, 199 | 1 200 | ] 201 | }, 202 | { 203 | "row10": [ 204 | 0, 205 | 1, 206 | 0, 207 | 0, 208 | 0, 209 | 1, 210 | 0, 211 | 0, 212 | 0, 213 | 1, 214 | 0, 215 | 0, 216 | 0, 217 | 1, 218 | 0, 219 | 0 220 | ] 221 | }, 222 | { 223 | "row11": [ 224 | 1, 225 | 0, 226 | 1, 227 | 0, 228 | 1, 229 | 0, 230 | 1, 231 | 0, 232 | 1, 233 | 0, 234 | 1, 235 | 0, 236 | 1, 237 | 0, 238 | 1, 239 | 0 240 | ] 241 | } 242 | ] -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxStepSequencer/presets/stepSequencer_preset_4.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "row0": [ 4 | 0, 5 | 1, 6 | 0, 7 | 0, 8 | 0, 9 | 1, 10 | 0, 11 | 0, 12 | 0, 13 | 1, 14 | 0, 15 | 0, 16 | 0, 17 | 1, 18 | 0, 19 | 0 20 | ] 21 | }, 22 | { 23 | "row1": [ 24 | 0, 25 | 0, 26 | 0, 27 | 0, 28 | 0, 29 | 0, 30 | 0, 31 | 0, 32 | 0, 33 | 0, 34 | 0, 35 | 0, 36 | 0, 37 | 0, 38 | 0, 39 | 0 40 | ] 41 | }, 42 | { 43 | "row2": [ 44 | 0, 45 | 0, 46 | 0, 47 | 0, 48 | 0, 49 | 0, 50 | 0, 51 | 0, 52 | 0, 53 | 0, 54 | 0, 55 | 0, 56 | 0, 57 | 0, 58 | 0, 59 | 0 60 | ] 61 | }, 62 | { 63 | "row3": [ 64 | 0, 65 | 1, 66 | 0, 67 | 0, 68 | 0, 69 | 1, 70 | 0, 71 | 0, 72 | 0, 73 | 1, 74 | 0, 75 | 0, 76 | 0, 77 | 1, 78 | 0, 79 | 0 80 | ] 81 | }, 82 | { 83 | "row4": [ 84 | 0, 85 | 0, 86 | 0, 87 | 0, 88 | 0, 89 | 0, 90 | 0, 91 | 0, 92 | 0, 93 | 0, 94 | 0, 95 | 0, 96 | 0, 97 | 0, 98 | 0, 99 | 0 100 | ] 101 | }, 102 | { 103 | "row5": [ 104 | 0, 105 | 1, 106 | 0, 107 | 0, 108 | 0, 109 | 1, 110 | 0, 111 | 0, 112 | 0, 113 | 1, 114 | 0, 115 | 0, 116 | 0, 117 | 1, 118 | 0, 119 | 0 120 | ] 121 | }, 122 | { 123 | "row6": [ 124 | 0, 125 | 0, 126 | 0, 127 | 0, 128 | 0, 129 | 0, 130 | 0, 131 | 0, 132 | 0, 133 | 0, 134 | 0, 135 | 0, 136 | 0, 137 | 0, 138 | 0, 139 | 0 140 | ] 141 | }, 142 | { 143 | "row7": [ 144 | 0, 145 | 0, 146 | 0, 147 | 1, 148 | 0, 149 | 0, 150 | 0, 151 | 1, 152 | 0, 153 | 0, 154 | 0, 155 | 1, 156 | 0, 157 | 0, 158 | 0, 159 | 1 160 | ] 161 | }, 162 | { 163 | "row8": [ 164 | 0, 165 | 0, 166 | 0, 167 | 0, 168 | 0, 169 | 0, 170 | 0, 171 | 0, 172 | 0, 173 | 0, 174 | 0, 175 | 0, 176 | 0, 177 | 0, 178 | 0, 179 | 0 180 | ] 181 | }, 182 | { 183 | "row9": [ 184 | 1, 185 | 0, 186 | 0, 187 | 0, 188 | 1, 189 | 0, 190 | 0, 191 | 0, 192 | 1, 193 | 0, 194 | 0, 195 | 0, 196 | 1, 197 | 0, 198 | 0, 199 | 0 200 | ] 201 | }, 202 | { 203 | "row10": [ 204 | 0, 205 | 0, 206 | 0, 207 | 1, 208 | 0, 209 | 0, 210 | 0, 211 | 1, 212 | 0, 213 | 0, 214 | 0, 215 | 1, 216 | 0, 217 | 0, 218 | 0, 219 | 1 220 | ] 221 | }, 222 | { 223 | "row11": [ 224 | 0, 225 | 0, 226 | 0, 227 | 0, 228 | 0, 229 | 0, 230 | 0, 231 | 0, 232 | 0, 233 | 0, 234 | 0, 235 | 0, 236 | 0, 237 | 0, 238 | 0, 239 | 0 240 | ] 241 | } 242 | ] -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxStepSequencer/presets/stepSequencer_preset_5.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "row0": [ 4 | 0, 5 | 0, 6 | 0, 7 | 0, 8 | 0, 9 | 0, 10 | 0, 11 | 0, 12 | 0, 13 | 0, 14 | 0, 15 | 0, 16 | 0, 17 | 0, 18 | 0, 19 | 0 20 | ] 21 | }, 22 | { 23 | "row1": [ 24 | 0, 25 | 0, 26 | 1, 27 | 0, 28 | 0, 29 | 0, 30 | 1, 31 | 0, 32 | 0, 33 | 0, 34 | 1, 35 | 0, 36 | 0, 37 | 0, 38 | 1, 39 | 0 40 | ] 41 | }, 42 | { 43 | "row2": [ 44 | 0, 45 | 0, 46 | 0, 47 | 1, 48 | 0, 49 | 0, 50 | 0, 51 | 1, 52 | 0, 53 | 0, 54 | 0, 55 | 1, 56 | 0, 57 | 0, 58 | 0, 59 | 1 60 | ] 61 | }, 62 | { 63 | "row3": [ 64 | 0, 65 | 0, 66 | 1, 67 | 0, 68 | 0, 69 | 0, 70 | 1, 71 | 0, 72 | 0, 73 | 0, 74 | 1, 75 | 0, 76 | 0, 77 | 0, 78 | 1, 79 | 0 80 | ] 81 | }, 82 | { 83 | "row4": [ 84 | 0, 85 | 0, 86 | 0, 87 | 0, 88 | 0, 89 | 0, 90 | 0, 91 | 0, 92 | 0, 93 | 0, 94 | 0, 95 | 0, 96 | 0, 97 | 0, 98 | 0, 99 | 0 100 | ] 101 | }, 102 | { 103 | "row5": [ 104 | 1, 105 | 0, 106 | 0, 107 | 0, 108 | 1, 109 | 0, 110 | 0, 111 | 0, 112 | 1, 113 | 0, 114 | 0, 115 | 0, 116 | 1, 117 | 0, 118 | 0, 119 | 0 120 | ] 121 | }, 122 | { 123 | "row6": [ 124 | 0, 125 | 0, 126 | 0, 127 | 0, 128 | 0, 129 | 0, 130 | 0, 131 | 0, 132 | 0, 133 | 0, 134 | 0, 135 | 0, 136 | 0, 137 | 0, 138 | 0, 139 | 0 140 | ] 141 | }, 142 | { 143 | "row7": [ 144 | 0, 145 | 0, 146 | 0, 147 | 0, 148 | 0, 149 | 0, 150 | 0, 151 | 0, 152 | 0, 153 | 0, 154 | 0, 155 | 0, 156 | 0, 157 | 0, 158 | 0, 159 | 0 160 | ] 161 | }, 162 | { 163 | "row8": [ 164 | 1, 165 | 0, 166 | 0, 167 | 0, 168 | 1, 169 | 0, 170 | 0, 171 | 0, 172 | 1, 173 | 0, 174 | 0, 175 | 0, 176 | 1, 177 | 0, 178 | 0, 179 | 0 180 | ] 181 | }, 182 | { 183 | "row9": [ 184 | 0, 185 | 0, 186 | 0, 187 | 0, 188 | 0, 189 | 0, 190 | 0, 191 | 0, 192 | 0, 193 | 0, 194 | 0, 195 | 0, 196 | 0, 197 | 0, 198 | 0, 199 | 0 200 | ] 201 | }, 202 | { 203 | "row10": [ 204 | 0, 205 | 0, 206 | 1, 207 | 0, 208 | 0, 209 | 0, 210 | 1, 211 | 0, 212 | 0, 213 | 0, 214 | 1, 215 | 0, 216 | 0, 217 | 0, 218 | 1, 219 | 0 220 | ] 221 | }, 222 | { 223 | "row11": [ 224 | 1, 225 | 1, 226 | 0, 227 | 1, 228 | 1, 229 | 1, 230 | 0, 231 | 1, 232 | 1, 233 | 1, 234 | 0, 235 | 1, 236 | 1, 237 | 1, 238 | 0, 239 | 1 240 | ] 241 | } 242 | ] -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxStepSequencer/presets/stepSequencer_preset_6.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "row0": [ 4 | 0, 5 | 1, 6 | 1, 7 | 0, 8 | 0, 9 | 1, 10 | 1, 11 | 0, 12 | 0, 13 | 1, 14 | 1, 15 | 0, 16 | 0, 17 | 1, 18 | 1, 19 | 0 20 | ] 21 | }, 22 | { 23 | "row1": [ 24 | 0, 25 | 0, 26 | 0, 27 | 0, 28 | 0, 29 | 0, 30 | 0, 31 | 0, 32 | 0, 33 | 0, 34 | 0, 35 | 0, 36 | 0, 37 | 0, 38 | 0, 39 | 0 40 | ] 41 | }, 42 | { 43 | "row2": [ 44 | 1, 45 | 0, 46 | 1, 47 | 0, 48 | 1, 49 | 0, 50 | 1, 51 | 0, 52 | 1, 53 | 0, 54 | 1, 55 | 0, 56 | 1, 57 | 0, 58 | 1, 59 | 0 60 | ] 61 | }, 62 | { 63 | "row3": [ 64 | 0, 65 | 0, 66 | 0, 67 | 0, 68 | 0, 69 | 0, 70 | 0, 71 | 0, 72 | 0, 73 | 0, 74 | 0, 75 | 0, 76 | 0, 77 | 0, 78 | 0, 79 | 0 80 | ] 81 | }, 82 | { 83 | "row4": [ 84 | 0, 85 | 0, 86 | 1, 87 | 0, 88 | 0, 89 | 0, 90 | 1, 91 | 0, 92 | 0, 93 | 0, 94 | 1, 95 | 0, 96 | 0, 97 | 0, 98 | 1, 99 | 0 100 | ] 101 | }, 102 | { 103 | "row5": [ 104 | 0, 105 | 0, 106 | 0, 107 | 1, 108 | 0, 109 | 0, 110 | 0, 111 | 1, 112 | 0, 113 | 0, 114 | 0, 115 | 1, 116 | 0, 117 | 0, 118 | 0, 119 | 1 120 | ] 121 | }, 122 | { 123 | "row6": [ 124 | 0, 125 | 0, 126 | 1, 127 | 0, 128 | 0, 129 | 0, 130 | 1, 131 | 0, 132 | 0, 133 | 0, 134 | 1, 135 | 0, 136 | 0, 137 | 0, 138 | 1, 139 | 0 140 | ] 141 | }, 142 | { 143 | "row7": [ 144 | 1, 145 | 0, 146 | 1, 147 | 0, 148 | 1, 149 | 0, 150 | 1, 151 | 0, 152 | 1, 153 | 0, 154 | 1, 155 | 0, 156 | 1, 157 | 0, 158 | 1, 159 | 0 160 | ] 161 | }, 162 | { 163 | "row8": [ 164 | 0, 165 | 0, 166 | 0, 167 | 0, 168 | 0, 169 | 0, 170 | 0, 171 | 0, 172 | 0, 173 | 0, 174 | 0, 175 | 0, 176 | 0, 177 | 0, 178 | 0, 179 | 0 180 | ] 181 | }, 182 | { 183 | "row9": [ 184 | 0, 185 | 1, 186 | 0, 187 | 0, 188 | 0, 189 | 1, 190 | 0, 191 | 0, 192 | 0, 193 | 1, 194 | 0, 195 | 0, 196 | 0, 197 | 1, 198 | 0, 199 | 0 200 | ] 201 | }, 202 | { 203 | "row10": [ 204 | 0, 205 | 0, 206 | 0, 207 | 0, 208 | 0, 209 | 0, 210 | 0, 211 | 0, 212 | 0, 213 | 0, 214 | 0, 215 | 0, 216 | 0, 217 | 0, 218 | 0, 219 | 0 220 | ] 221 | }, 222 | { 223 | "row11": [ 224 | 0, 225 | 1, 226 | 0, 227 | 0, 228 | 0, 229 | 1, 230 | 0, 231 | 0, 232 | 0, 233 | 1, 234 | 0, 235 | 0, 236 | 0, 237 | 1, 238 | 0, 239 | 0 240 | ] 241 | } 242 | ] -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/bin/data/ofxStepSequencer/presets/stepSequencer_preset_7.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "row0": [ 4 | 0, 5 | 1, 6 | 0, 7 | 0, 8 | 0, 9 | 0, 10 | 0, 11 | 0, 12 | 1, 13 | 0, 14 | 0, 15 | 0, 16 | 1, 17 | 0, 18 | 1, 19 | 0 20 | ] 21 | }, 22 | { 23 | "row1": [ 24 | 0, 25 | 0, 26 | 0, 27 | 0, 28 | 0, 29 | 0, 30 | 0, 31 | 0, 32 | 0, 33 | 0, 34 | 0, 35 | 0, 36 | 0, 37 | 0, 38 | 0, 39 | 0 40 | ] 41 | }, 42 | { 43 | "row2": [ 44 | 0, 45 | 0, 46 | 0, 47 | 0, 48 | 1, 49 | 0, 50 | 0, 51 | 0, 52 | 0, 53 | 1, 54 | 0, 55 | 0, 56 | 0, 57 | 0, 58 | 0, 59 | 0 60 | ] 61 | }, 62 | { 63 | "row3": [ 64 | 0, 65 | 1, 66 | 0, 67 | 1, 68 | 0, 69 | 1, 70 | 0, 71 | 1, 72 | 0, 73 | 0, 74 | 0, 75 | 1, 76 | 0, 77 | 0, 78 | 0, 79 | 1 80 | ] 81 | }, 82 | { 83 | "row4": [ 84 | 0, 85 | 0, 86 | 0, 87 | 0, 88 | 1, 89 | 0, 90 | 0, 91 | 0, 92 | 0, 93 | 0, 94 | 0, 95 | 1, 96 | 0, 97 | 0, 98 | 0, 99 | 1 100 | ] 101 | }, 102 | { 103 | "row5": [ 104 | 0, 105 | 0, 106 | 0, 107 | 0, 108 | 0, 109 | 0, 110 | 0, 111 | 0, 112 | 1, 113 | 1, 114 | 0, 115 | 0, 116 | 1, 117 | 0, 118 | 0, 119 | 1 120 | ] 121 | }, 122 | { 123 | "row6": [ 124 | 0, 125 | 0, 126 | 1, 127 | 1, 128 | 0, 129 | 1, 130 | 0, 131 | 1, 132 | 0, 133 | 0, 134 | 0, 135 | 0, 136 | 0, 137 | 1, 138 | 1, 139 | 1 140 | ] 141 | }, 142 | { 143 | "row7": [ 144 | 0, 145 | 0, 146 | 0, 147 | 1, 148 | 1, 149 | 0, 150 | 0, 151 | 0, 152 | 0, 153 | 0, 154 | 0, 155 | 1, 156 | 1, 157 | 0, 158 | 1, 159 | 1 160 | ] 161 | }, 162 | { 163 | "row8": [ 164 | 0, 165 | 0, 166 | 1, 167 | 1, 168 | 0, 169 | 0, 170 | 0, 171 | 0, 172 | 0, 173 | 1, 174 | 1, 175 | 0, 176 | 0, 177 | 1, 178 | 0, 179 | 0 180 | ] 181 | }, 182 | { 183 | "row9": [ 184 | 0, 185 | 0, 186 | 0, 187 | 0, 188 | 0, 189 | 0, 190 | 0, 191 | 0, 192 | 0, 193 | 1, 194 | 1, 195 | 0, 196 | 0, 197 | 0, 198 | 0, 199 | 0 200 | ] 201 | }, 202 | { 203 | "row10": [ 204 | 0, 205 | 0, 206 | 0, 207 | 0, 208 | 0, 209 | 1, 210 | 0, 211 | 1, 212 | 0, 213 | 0, 214 | 0, 215 | 0, 216 | 0, 217 | 1, 218 | 0, 219 | 0 220 | ] 221 | }, 222 | { 223 | "row11": [ 224 | 0, 225 | 0, 226 | 0, 227 | 0, 228 | 0, 229 | 0, 230 | 1, 231 | 0, 232 | 0, 233 | 0, 234 | 0, 235 | 0, 236 | 0, 237 | 0, 238 | 0, 239 | 0 240 | ] 241 | } 242 | ] -------------------------------------------------------------------------------- /libs/ofxPresetDataGrid/src/DataGrid.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by moebiussurfing on 5/15/19. 3 | // 4 | 5 | #include "DataGrid.h" 6 | 7 | DataGrid::DataGrid() 8 | { 9 | ofSetLogLevel("DataGrid", OF_LOG_NOTICE); 10 | 11 | ofLogVerbose("DataGrid") << "CONSTRUCTOR"; 12 | name = ""; 13 | id = 0; 14 | subTag = "row";//text tag for any row (aka subjson) into json file 15 | 16 | //- 17 | 18 | // init data vector 19 | 20 | grid.resize(NUM_SEQ_NOTES); 21 | 22 | for(int i=0 ; i < grid.size() ; i++) 23 | { 24 | grid[i].resize(NUM_SEQ_BEATS); 25 | 26 | for(int j=0 ; j < grid[i].size() ; j++) //init 27 | { 28 | grid[i][j] = 0; 29 | } 30 | } 31 | } 32 | 33 | //------------------------------------------------ 34 | void DataGrid::setup(int nNotes, int nBeats)///for custom grid sizes 35 | { 36 | //init data vector 37 | grid.clear(); 38 | grid.resize(nNotes); 39 | 40 | for (int i = 0; i < grid.size(); i++) 41 | { 42 | grid[i].resize(nBeats); 43 | 44 | for (int j = 0; j < grid[i].size(); j++) //init 45 | { 46 | grid[i][j] = 0; 47 | } 48 | } 49 | } 50 | 51 | //------------------------------------------------ 52 | void DataGrid::setName(const std::string _name){ 53 | name = _name; 54 | } 55 | 56 | //------------------------------------------------ 57 | std::string DataGrid::getName() const { 58 | return name; 59 | } 60 | 61 | //------------------------------------------------ 62 | void DataGrid::save_JSON(string path) 63 | { 64 | ofLogNotice("DataGrid") << "save_JSON"; 65 | 66 | ofJson JSON_row;//temp row(note) json for the slow mode parser 67 | ofJson JSON_grid; 68 | 69 | //- 70 | 71 | // A. slow mode with tags 72 | 73 | // TODO: should define data vector with open size.. 74 | 75 | // create one json for each row aka note: 76 | for (int note = 0; note < NUM_SEQ_NOTES; note++) 77 | { 78 | string name = subTag + ofToString(note); 79 | 80 | // JSON_row = ofxJsonUtils::create( kv( grid[note] ) ); 81 | JSON_row = ofxJsonUtils::create( name, grid[note] ); 82 | 83 | ofLogVerbose("DataGrid") << "DUMP: " + name + " " << JSON_row.dump(); 84 | 85 | //- 86 | 87 | JSON_grid.push_back(JSON_row); 88 | } 89 | 90 | //- 91 | 92 | // B. fast mode vector without tags 93 | // JSON_grid = ofxJsonUtils::create( kv( grid ) ); 94 | 95 | //- 96 | 97 | ofSavePrettyJson(path, JSON_grid); 98 | } 99 | 100 | 101 | //------------------------------------------------ 102 | void DataGrid::dump_grid() 103 | { 104 | ofLogNotice("DataGrid") << "dump_grid"; 105 | 106 | for (int note = 0; note < NUM_SEQ_NOTES; note++) { 107 | 108 | string str; 109 | for (int s = 0; s < NUM_SEQ_BEATS ; s++) 110 | { 111 | str += ofToString( grid[note][s] ) + " "; 112 | } 113 | ofLogVerbose("DataGrid") << "NOTE: " << note << " BEATS: " + str; 114 | } 115 | } 116 | 117 | //------------------------------------------------ 118 | void DataGrid::randomize_grid() { 119 | 120 | ofLogNotice("DataGrid") << "randomize_grid"; 121 | 122 | //- 123 | 124 | // id = 1; 125 | // name = "grid_" + ofToString(id) + ".json"; 126 | 127 | //- 128 | 129 | // random initiate 130 | 131 | string str; 132 | 133 | // TODO: should define data vector with open size.. 134 | 135 | for( size_t n = 0; n < NUM_SEQ_NOTES; n++ ) 136 | { 137 | //ofLogVerbose("DataGrid") << subTag + ofToString(n ) + " -- "; 138 | // cout << subTag << n << " -- "; 139 | 140 | for( size_t b = 0; b < NUM_SEQ_BEATS; b++ ) 141 | { 142 | int iState = (int) ofRandom(0, 2); 143 | 144 | // cout << "b" << b << ":" <> js; 168 | ofLogVerbose("DataGrid") << " > DUMP GRID: "; 169 | 170 | int n = 0; 171 | for (auto &js_Row: js) { 172 | if (!js_Row.empty()) { 173 | string js_Tag = subTag + ofToString(n); 174 | ofLogVerbose("DataGrid") << "subJSON:" + js_Tag + ": " << js_Row.dump(); 175 | 176 | std::vector steps = js_Row[js_Tag]; 177 | //load json array to vector 178 | int b = 0; 179 | for (auto i : steps) { 180 | grid[n][b] = i; 181 | b++; 182 | } 183 | n++; 184 | } 185 | } 186 | } 187 | 188 | //- 189 | 190 | // fast mode do not works. maybe because using array not vectors.. 191 | 192 | // ofJson js = ofxJsonUtils::loadFromFile(path); 193 | // ofLogNotice("DataGrid") << "DUMP GRID: " << js.dump(); 194 | // ofxJsonUtils::load( json, kv( grid[][] ) ); 195 | 196 | //- 197 | } 198 | -------------------------------------------------------------------------------- /libs/ofxPresetDataGrid/src/ofxPresetDataGrid.h: -------------------------------------------------------------------------------- 1 | 2 | //ofxPresetDataGrid.h 3 | //original addon by Nicola Pisanti, MIT License, 2016 4 | // 5 | //changes and customized by moebiussurfing: 6 | // 7 | //LOG: 8 | //+ switched from ofxGui to ofxGuiExtended 9 | //+ switched preset management from ofxGuiPanel to ofParametersGroup 10 | //+ added custom DATA class DataGrid 11 | //+ integrated to ofxStepSequencer 12 | //+ added control gui panel: slider selector, cloner, save 13 | // 14 | //TODO: 15 | //+ could make tween when changing params 16 | //+ save full kit of presets to avoid blocking main thread when switching presets 17 | //because json loadings 18 | //+ use pointers between classes (ofxSequencer) to share the data struct 19 | //from DataGrid class, 20 | //ofxStepSequencer, or wherever is used ... almost done. but maybe should add listeners 21 | //re players when preset are loaded/saved.. 22 | 23 | #pragma once 24 | 25 | #include "ofMain.h" 26 | #include "ofxGuiExtended2.h" 27 | 28 | #include "DataGrid.h" 29 | 30 | #define NUM_OF_PRESETS 8 31 | 32 | class ofxPresetDataGrid { 33 | 34 | public: 35 | 36 | bool DISABLE_CALLBACKS = false; 37 | 38 | ofxPresetDataGrid(); 39 | ~ofxPresetDataGrid(); 40 | 41 | //- 42 | 43 | string path_Global = "ofxStepSequencer"; 44 | string pathControl = "presetsControl.xml"; 45 | 46 | //- 47 | 48 | //add a gui for preset saving 49 | void add( DataGrid & grid, int numPresets=8 ); 50 | //adds and activate key switch 51 | void add( DataGrid & grid, initializer_list keysList ); 52 | 53 | //- 54 | 55 | //save to a preset 56 | void save( int presetIndex, int guiIndex=0 ); 57 | void save( int presetIndex, string guiName ); 58 | 59 | //loads an already saved preset 60 | void load( int presetIndex, int guiIndex=0 ); 61 | void load( int presetIndex, string guiName ); 62 | 63 | //get the last loaded preset 64 | int getPresetIndex( int guiIndex ) const; 65 | int getPresetIndex( string guiName ) const; 66 | 67 | //set the key you have to hold for saving, default is OF_KEY_CONTROL 68 | void setModeKey( int key ); 69 | 70 | //- 71 | 72 | //API 73 | 74 | //set graphics position 75 | //cellsize is the size of each preset button 76 | void setPosition_ClickerPanel( int x, int y, int cellSize ); 77 | 78 | //- 79 | 80 | //draw some info, when the gui is drawn you can also click on the button to change / save presets 81 | void draw(); 82 | void draw( int x, int y, int cellSize ); 83 | 84 | //- 85 | 86 | //DELAYED LOADING 87 | 88 | //if you set it to true the preset will be loaded only when you call (false is the default behavior) 89 | void setDelayedLoading( bool active ); 90 | //make preset change effective when setDelayedLoading() is set to true 91 | void delayedUpdate(); 92 | //if setDelayedLoading() is set to true stages a load action 93 | void delayedLoad( int presetIndex, int guiIndex=0 ); 94 | void delayedLoad( int presetIndex, string guiName ); 95 | 96 | //switch on or off the control with the keys 97 | void toggleKeysControl( bool active ); 98 | 99 | //- 100 | 101 | //TODO: easy listener temp solution for ofxStepSequencer integration 102 | ofParameter DONE_load; 103 | ofParameter DONE_save; 104 | 105 | //- 106 | 107 | private: 108 | 109 | int getGuiIndex(string name ) const; 110 | string presetName( string guiName, int presetIndex ); 111 | 112 | //- 113 | 114 | //DATA 115 | 116 | //B. custom DataGrid class 117 | vector grids; 118 | 119 | //- 120 | 121 | vector lastIndices; 122 | vector presets; 123 | 124 | void addKeysListeners(); 125 | void keyPressed( ofKeyEventArgs& eventArgs); 126 | void keyReleased( ofKeyEventArgs& eventArgs ); 127 | 128 | bool bKeys; 129 | vector> keys; 130 | bool keysNotActivated; 131 | int modeKey; 132 | bool bKeySave; 133 | 134 | int x; 135 | int y; 136 | int cellSize; 137 | 138 | bool lastMouseButtonState; 139 | void mousePressed( int x, int y ); 140 | 141 | bool bDelayedLoading; 142 | vector newIndices; 143 | 144 | //- 145 | 146 | ofTrueTypeFont myFont; 147 | string myTTF;//gui font for all gui theme 148 | int sizeTTF; 149 | 150 | //- 151 | 152 | public: 153 | 154 | //GUI 155 | 156 | ofJson confCont, confItem, confItem_toggle, confItem_Big, confItem_Fat; 157 | void setup_Gui(); 158 | void Changed_Params(ofAbstractParameter &e); 159 | 160 | //- 161 | 162 | //control panel to selec presets, clone, save.. 163 | ofxGui gui; 164 | ofParameterGroup params; 165 | ofxGuiGroup2 * group; 166 | 167 | ofParameter PRESET_selected; 168 | int PRESET_selected_PRE = -1; 169 | ofParameter bSave; 170 | ofParameter bAutoSave; 171 | ofParameter bAutoLoad; 172 | ofParameter bCloneToRight; 173 | void doCloneRight(int patternNum); 174 | void doSave(int patternNum); 175 | int num_presets; 176 | 177 | //- 178 | 179 | void load_ControlSettings(); 180 | void save_ControlSettings(); 181 | 182 | //- 183 | 184 | //API 185 | 186 | void set_GUI_position(int x, int y); 187 | void setVisible_Gui(bool visible); 188 | void setVisible_ClickerPanel(bool visible); 189 | void set_pathKit_Folder(string folder); 190 | string pathKitFolder = "myKit";//default kit folder to store patterns 191 | 192 | //- 193 | 194 | bool SHOW_Gui; 195 | bool SHOW_ClickPanel; 196 | bool ENABLE_shortcuts = true; 197 | 198 | int gui_w; 199 | int gui_slider_h; 200 | int gui_slider_big_h; 201 | int gui_button_h; 202 | 203 | //-- 204 | }; 205 | -------------------------------------------------------------------------------- /1_example_ofxStepSequencer/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | //-------------------------------------------------------------- 4 | void ofApp::setup() 5 | { 6 | ofSetBackgroundColor(48); 7 | ofSetLogLevel("ofApp", OF_LOG_NOTICE); 8 | 9 | #ifdef USE_ofxWindowApp 10 | windowApp.setSettingsFps(60);//onlty required on first use, before xml is present 11 | #else 12 | ofSetFrameRate(60); 13 | ofSetVerticalSync(true); 14 | #endif 15 | 16 | //------------------------------------------------------ 17 | 18 | //STEP SEQUENCER 19 | SEQ.setup(); 20 | SEQ_Gui_Customize(); 21 | 22 | //------------------------------------------------------ 23 | 24 | //LOCAL TARGET NOTES PARAMS (toggle bools) & GUI MONITOR 25 | 26 | //optional customize 27 | ofJson confg_Cont = 28 | { 29 | {"width", 40} 30 | }; 31 | ofJson confg_Button = 32 | { 33 | {"type", "fullsize"}, 34 | {"text-align", "right"}, 35 | {"height", 21}, 36 | //{"width", 100}, 37 | //{"text-align", "center"}, 38 | }; 39 | 40 | gui_Notes = gui_Panel_Notes.addContainer(); 41 | gui_Notes->setName("LOCAL NOTES"); 42 | gui_Notes->setConfig(confg_Cont); 43 | 44 | //notes_paramsGroup.setName("NOTES PARAMS");//CALLBACKS MODE B 45 | 46 | //-- 47 | 48 | //ofApp local params. bool/toggles target receivers from sequencer 49 | for (int col = 0; col < NUM_SEQ_NOTES; col++) 50 | { 51 | //define param 52 | string nStr = ofToString(col + 1); 53 | notes_params[col].set(nStr, false); 54 | 55 | //add param to gui panel 56 | gui_Notes->add(notes_params[col]); 57 | //notes_paramsGroup.add(notes_params[col]);//CALLBACKS MODE B 58 | 59 | //customize added button 60 | gui_Notes->getControl(nStr)->setConfig(confg_Button); 61 | } 62 | 63 | //layout and theme 64 | gui_Notes->setPosition(880, 10); 65 | gui_Notes->loadTheme("theme/theme_bleurgh.json"); 66 | 67 | //-- 68 | 69 | //CALLBACKS MODE A: 70 | //listener to directly check inside class ofxStepSequencer and receive states 71 | ofAddListener(SEQ.TARGET_NOTES_paramsGroup.parameterChangedE(), this, &ofApp::Changed_SEQ_NOTES); 72 | 73 | //-- 74 | 75 | ////CALLBACKS MODE B: 76 | ////listener for local ofApp toggle param variables 77 | //ofAddListener(notes_paramsGroup.parameterChangedE(), this, &ofApp::Changed_notes_paramsGroup); 78 | 79 | //-- 80 | } 81 | 82 | //-------------------------------------------------------------- 83 | void ofApp::SEQ_Gui_Customize() 84 | { 85 | //optional customize layout 86 | 87 | //THEME 88 | int grid_w = 400; 89 | SEQ.setPosition_GridSequencer(465, 10, grid_w, 0); 90 | SEQ.setPosition_Gui(220, 5); 91 | 92 | //BEAT CLOCK TRANSPORT 93 | SEQ.setPosition_BeatClock(5, 5); 94 | 95 | int squares_w = 200; 96 | int ball_radius = 30; 97 | int px = 5; 98 | int py = 5; 99 | //SEQ.setPosition_CLOCK_Gui(px, py, squares_w);//main gui. titled as 'ofxStepSequencer' 100 | //SEQ.setPosition_CLOCK_Squares(px, py + 630, squares_w);//beat squares 101 | //SEQ.setPosition_CLOCK_Ball(px + squares_w * 0.5 - ball_radius, py + 830, ball_radius);//beat ball for visual feedback 102 | 103 | //PRESET MANAGER 104 | SEQ.presetsManager.set_GUI_position(465, 350 + grid_w / 9 + 10);//gui titled as 'SEQ PATTERNS' 105 | SEQ.presetsManager.setPosition_ClickerPanel(465, 350, grid_w / 9);//mouse clicker preset selector 106 | SEQ.presetsManager.setVisible_ClickerPanel(true);//show 107 | SEQ.presetsManager.setVisible_Gui(true);//show 108 | 109 | //- 110 | 111 | //TODO: customize data folder. startup buggy.. 112 | //SEQ.presetsManager.set_pathKit_Folder("patterns/kit_1"); 113 | 114 | //load last GRID settings 115 | //path = "SEQ_default.json"; 116 | //SEQ.load_JSON(path); 117 | } 118 | 119 | //-------------------------------------------------------------- 120 | void ofApp::update() 121 | { 122 | SEQ.update(); 123 | } 124 | 125 | //-------------------------------------------------------------- 126 | void ofApp::draw() 127 | { 128 | SEQ.draw();//grid sequencer 129 | SEQ.draw_CLOCK();//visual feedback: beat ball, beat squares and text info 130 | } 131 | 132 | //-------------------------------------------------------------- 133 | void ofApp::exit() 134 | { 135 | //save current preset steps 136 | //SEQ.save_JSON(path); 137 | 138 | SEQ.exit(); 139 | ofRemoveListener(SEQ.TARGET_NOTES_paramsGroup.parameterChangedE(), this, &ofApp::Changed_SEQ_NOTES); 140 | } 141 | 142 | //-------------------------------------------------------------- 143 | void ofApp::keyPressed(int key) 144 | { 145 | switch (key) 146 | { 147 | 148 | //transport control 149 | case ' ': 150 | { 151 | SEQ.togglePlayStop(); 152 | } 153 | break; 154 | 155 | case OF_KEY_LEFT: 156 | SEQ.sequencer.stepBack(); 157 | break; 158 | 159 | case OF_KEY_RIGHT: 160 | SEQ.sequencer.advance(); 161 | break; 162 | 163 | #ifdef USE_OFXBEATCLOCK 164 | case 't': 165 | SEQ.beatClock.tap_Trig(); 166 | break; 167 | #endif 168 | 169 | //helpers 170 | case ',': 171 | SEQ.randomize(); 172 | break; 173 | 174 | case '.': 175 | SEQ.clear(); 176 | break; 177 | 178 | default: 179 | break; 180 | } 181 | } 182 | 183 | //-------------------------------------------------------------- 184 | //CALLBACKS MODE A: 185 | //listener to check inside class ofxStepSequencer 186 | void ofApp::Changed_SEQ_NOTES(ofAbstractParameter& e) 187 | { 188 | string name = e.getName(); 189 | int noteNum = ofToInt(name); 190 | bool state = false; 191 | 192 | if (e.type() == typeid(ofParameter).name()) 193 | { 194 | ofParameter p = e.cast(); 195 | state = p; 196 | ofLogVerbose("ofApp") << "Changed_SEQ_NOTES: " << name << (p ? " ON" : " OFF"); 197 | 198 | notes_params[noteNum] = state; 199 | 200 | //- 201 | 202 | //here you can trig midi notes_params i.e. 203 | //pd.sendNoteOn(midiChan, noteFirst + noteNum, (int)state?127:0); 204 | } 205 | } 206 | 207 | ////-------------------------------------------------------------- 208 | ////CALLBACKS MODE B: 209 | ////listener for local ofApp toggle param variables 210 | //void ofApp::Changed_notes_paramsGroup(ofAbstractParameter &e) 211 | //{ 212 | // string name = e.getName(); 213 | // int noteNum = ofToInt(name); 214 | // bool state = false; 215 | // 216 | // if (e.type() == typeid(ofParameter).name()) 217 | // { 218 | // ofParameter p = e.cast(); 219 | // state = p; 220 | // ofLogVerbose("ofApp") << "Changed_notes_paramsGroup " << name << (p ? " ON" : " OFF"); 221 | // } 222 | //} 223 | -------------------------------------------------------------------------------- /src/ofxStepSequencer.h: -------------------------------------------------------------------------------- 1 | ///TODO: 2 | 3 | ///+ helper to shift steps left rigth up down 4 | ///+ variable pattern beat and note sizes 5 | ///+ improve performance using fbo to only refesh when grid preview changes 6 | 7 | ///+ ofxBeatClock 8 | ///+ add callback to play toggle linking 9 | ///+ group all bpm's into one 10 | ///+ add buffer clock besides timer 11 | ///+ re sync trig 12 | 13 | ///+ monitor too (cell blinks) triggered notes from outside (OSC/API) to the grid cells 14 | ///+ helpers to set widgets/panels layout 15 | 16 | //---------------------------------------------------------- 17 | 18 | #pragma once 19 | 20 | #include "ofMain.h" 21 | 22 | #include "ofxGuiExtended2.h" 23 | #include "ofxJsonUtils.h" 24 | #include "ofxSequencer.h" 25 | 26 | #define USE_OFXBEATCLOCK 27 | //comment to disable and use internal ofxSequencer / ofxBpm clock tick timer instead of ofxBeatClock 28 | //default mode (uncommented) will use ofxBeatClock for clock tick timer 29 | 30 | #ifdef USE_OFXBEATCLOCK 31 | #include "ofxBeatClock.h" 32 | #endif 33 | 34 | #define NUM_SEQ_NOTES 12//max & fixed size 35 | #define NUM_SEQ_BEATS 16//max & fixed size 36 | 37 | #define BPM_INIT 120 38 | #define BARS_INIT 4 39 | 40 | #ifndef USE_OFXBEATCLOCK 41 | #define USE_OFXSEQUENCER_TRANSPORT 42 | //to use ofxSequencer clock by ofxBPM 43 | //comment to use my own ofxBeatClock clock system. This one is called INTERNAL and based in timers too, so it could drop and be inestable sometimes. Also it has MIDI IN CLOCK mode as EXTERNAL clock. 44 | #endif 45 | 46 | #include "DataGrid.h" 47 | #include "ofxPresetDataGrid.h" 48 | 49 | //- 50 | 51 | class ofxStepSequencer 52 | { 53 | 54 | public: 55 | 56 | void resetClock() 57 | { 58 | if (isPlaying) 59 | { 60 | beatClock.reset_ClockValues(); 61 | beatClock.start(); 62 | } 63 | }; 64 | 65 | //debug cols and transport 66 | bool DEBUG_state = false; 67 | 68 | ofxStepSequencer() {} 69 | ~ofxStepSequencer() {} 70 | 71 | //- 72 | 73 | void setup(); 74 | void update(); 75 | void draw(); 76 | void exit(); 77 | 78 | void setup_gui(); 79 | void draw_CLOCK(); 80 | 81 | //- 82 | 83 | //TODO: 84 | ///for custom grid sizes 85 | void setup(int nNotes, int nBeats); 86 | 87 | private: 88 | int NumSeqNotes = 12; 89 | int NumSeqBeats = 16; 90 | 91 | //- 92 | 93 | ofParameter loopBar; 94 | ofParameter numBars; 95 | ofParameter startBar; 96 | 97 | public: 98 | void setLoopBarMode(bool b) 99 | { 100 | loopBar = b; 101 | } 102 | void setNumBarMode(int i) 103 | { 104 | numBars = i; 105 | } 106 | void setStartBar(int i) 107 | { 108 | startBar = i; 109 | } 110 | 111 | //- 112 | 113 | //API 114 | 115 | public: 116 | 117 | void setPosition_GridSequencer(int x, int y, int width, int heigh); 118 | void setPosition_Gui(int x, int y); 119 | 120 | #ifdef USE_OFXBEATCLOCK 121 | void setPosition_BeatClock(int x, int y);//main global position setter 122 | //optional to customize 123 | void setPosition_CLOCK_Gui(int x, int y, int w); 124 | void setPosition_CLOCK_Squares(int x, int y, int w); 125 | void setPosition_CLOCK_Ball(int x, int y, int w); 126 | //bool bBallAutoPos = true; 127 | //void setPosition_CLOCK_Ball_Auto(bool b) 128 | //{ 129 | // bBallAutoPos = b; 130 | //} 131 | float getHeight_GridSequencer() 132 | { 133 | return seqH; 134 | } 135 | float getWidth_GridSequencer() 136 | { 137 | return seqW; 138 | } 139 | glm::vec2 getPosition_GridSequencer() 140 | { 141 | return (glm::vec2(seqX, seqY)); 142 | } 143 | #endif 144 | 145 | bool getPlayState(); 146 | 147 | void setPlayState(bool state); 148 | void togglePlayStop(); 149 | 150 | void randomize(); 151 | void clear(); 152 | 153 | private: 154 | void random(int noteFrom, int numNotes, float prob);//num TARGET_NOTES_params, 2 = 50% 155 | void cloneFromBar(int selBar); 156 | bool SHOW_Gui = true; 157 | 158 | public: 159 | void set_SHOW_Gui(bool state); 160 | 161 | //apply settings for font in all gui panels together 162 | void set_GuiAll_Settings(ofJson js); 163 | 164 | //- 165 | 166 | //SEQUENCER 167 | 168 | public: 169 | 170 | ofxSequencer sequencer; 171 | 172 | //- 173 | 174 | //TARGET (NOTES TRIGGERS) OF SEQUENCER DATA 175 | 176 | public: 177 | 178 | ofParameter TARGET_NOTES_params[NUM_SEQ_NOTES];//state of each note/row 179 | //TODO: BUG: add step 0 180 | //ofParameter TARGET_NOTES_params[NUM_SEQ_NOTES+1];//state of each note/row 181 | 182 | ofParameterGroup TARGET_NOTES_paramsGroup; 183 | 184 | //TODO: change only bool mode to int or floats too 185 | //ofParameter step0_row[NUM_SEQ_NOTES];//state of each note/row 186 | 187 | //- 188 | 189 | //method to use from outside 190 | void setGRID_square(int note, int beat, bool state);//to the store array 191 | 192 | //- 193 | 194 | //get values to GRID from sequencer class, like clicked cells, (not only from randomized or cloned by ofxStepSequencer, that they are alreay stored) 195 | void GRID_getFrom_Sequencer(); 196 | 197 | //TODO: make functionm to refresh when listens preset manager changes.. 198 | //void GRID_set_Sequencer_From_DATA_class(); 199 | 200 | void setGRID_visible(bool b) 201 | { 202 | //sequencer.setVisible(b); 203 | SHOW_Grid = b; 204 | }; 205 | 206 | //-- 207 | 208 | private: 209 | 210 | bool DISABLE_CALLBACKS = false; 211 | 212 | string path_Global = "ofxStepSequencer"; 213 | string path_Settings = "settings.xml"; 214 | 215 | ofParameter SHOW_beatClock; 216 | ofParameter SHOW_presetsManager; 217 | ofParameter SHOW_Grid; 218 | 219 | //- 220 | 221 | private: 222 | 223 | //JSON settings: 224 | 225 | struct JSON_grid_Row //one row note 226 | { 227 | //init NUM_SEQ_BEATS = 16 228 | //TODO: allow variable lenghts row/col 229 | //TODO: allow ofxJsonUtils mode... easy parsers 230 | std::vector steps{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 231 | }; 232 | 233 | void save_JSON(string path); 234 | void load_JSON(string path); 235 | 236 | bool ENABLE_autoSaveLoad = false;//disable auto save load 237 | string path_def; 238 | 239 | //---- 240 | 241 | //to trig from inside the class 242 | //void Changed_SEQ_NOTES(ofAbstractParameter& e); 243 | 244 | //- 245 | 246 | //GUI AND PARAMETERS 247 | 248 | ofxGui gui_SEQ; 249 | 250 | ofxGuiGroup2* group_HelperTools; 251 | ofParameterGroup params_HelperTools; 252 | ofParameter random_trig; 253 | ofParameter randomProb; 254 | ofParameter noteFrom; 255 | ofParameter numNotes; 256 | ofParameter clear_trig; 257 | ofParameter clone_trig; 258 | ofParameter clone_fromBar; 259 | 260 | ofxGuiGroup2* group_Transport; 261 | ofParameterGroup params_Transport; 262 | ofParameter isPlaying = false; 263 | ofParameter play_trig; 264 | ofParameter bpm; 265 | 266 | void Changed_Params(ofAbstractParameter& e); 267 | 268 | //- 269 | 270 | //GUI & GRID THEME FONT 271 | 272 | string myTTF;//gui font path 273 | int sizeTTF; 274 | ofTrueTypeFont myFont; 275 | int fontSize; 276 | 277 | //- 278 | 279 | //DEBUG FONT 280 | 281 | int ttfSize; 282 | ofTrueTypeFont ttfType; 283 | 284 | //- 285 | 286 | //SEQUENCER GRID POSITION AND SIZE: 287 | 288 | int seqW; 289 | int seqH; 290 | int seqX; 291 | int seqY; 292 | int seqBoxSize; 293 | 294 | //----- 295 | 296 | //TODO: fbo to improve redraw performance.. 297 | //TODO: maybe should mix both SEQ and ofxSequencer together, drawings too 298 | 299 | ofFbo fbo; 300 | bool toRedraw; 301 | void redraw(); 302 | bool useFbo; 303 | //ofFbo fboNotes; 304 | 305 | //-- 306 | 307 | //BPM CLOCK 308 | 309 | #ifdef USE_OFXBEATCLOCK 310 | public: 311 | ofxBeatClock beatClock; 312 | void Changed_BPM_beat_current(int & value); 313 | void Changed_BeatClock_BPM(float & value); 314 | #endif 315 | 316 | private: 317 | //choice between internal ofxSequencer clock vs ofxBeatClock clocker 318 | bool ENABLE_ofxBeatClock_MODE; 319 | 320 | //-- 321 | 322 | public: 323 | ofxPresetDataGrid presetsManager; 324 | 325 | //-- 326 | 327 | public: 328 | //TODO: 329 | //public callbacks. easy listeners 330 | void Changed_DONE_load(bool & DONE_load); 331 | void Changed_DONE_save(bool & DONE_save); 332 | 333 | //-- 334 | 335 | private: 336 | //DATA custom class 337 | DataGrid myDataGrid; 338 | 339 | //-- 340 | }; 341 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ######################### 2 | # general patterns 3 | ######################### 4 | 5 | ##------------------------------- 6 | 7 | ## can exclude some sttings files 8 | 9 | #*.XML 10 | #*.xml 11 | #*.JSON 12 | #*.json 13 | 14 | #*/bin/* 15 | #!*/bin/data/ 16 | #[Bb]in/ 17 | 18 | # for bin folder in root 19 | #/bin/* 20 | #!/bin/data/ 21 | 22 | ##------------------------------- 23 | 24 | docs/html 25 | docs/tagfile.xml 26 | 27 | [Bb]uild/ 28 | [Oo]bj/ 29 | *.o 30 | [Dd]ebug*/ 31 | [Rr]elease*/ 32 | *.mode* 33 | *.app/ 34 | *.pyc 35 | .svn/ 36 | 37 | ######################### 38 | # IDE 39 | ######################### 40 | 41 | # VS2017 42 | *.vcxproj 43 | *.vcxproj.* 44 | icon.rc 45 | *.vs 46 | *.vs/ 47 | *.vs/* 48 | *.vs/ 49 | *.sln 50 | *.filters 51 | *.user 52 | *.exp 53 | 54 | #vs2017 55 | *.sln 56 | *.vcxproj 57 | *.vcxproj.filters 58 | *.vcxproj.user 59 | icon.rc 60 | *.vs/* 61 | 62 | ##------------------------------- 63 | 64 | # XCode 65 | *.xcodeproj 66 | *.pbxuser 67 | *.perspective 68 | *.perspectivev3 69 | *.mode1v3 70 | *.mode2v3 71 | #XCode 4 72 | xcuserdata 73 | *.xcworkspace 74 | *.xcodeproj/project.pbxproj 75 | *.xcodeproj/xcshareddata/xcschemes/ 76 | 77 | # AppCode 78 | *.idea 79 | *.idea/ 80 | *.idea/* 81 | *.idea/ 82 | */.idea/workspace.xml 83 | 84 | # Code::Blocks 85 | *.depend 86 | *.layout 87 | *.cbTemp 88 | 89 | # Visual Studio 90 | *.sdf 91 | *.opensdf 92 | *.suo 93 | *.pdb 94 | *.ilk 95 | *.aps 96 | ipch/ 97 | 98 | # Eclipse 99 | .metadata 100 | local.properties 101 | .externalToolBuilders 102 | 103 | # Codelite 104 | *.session 105 | *.tags 106 | *.workspace.* 107 | 108 | ######################### 109 | # operating system 110 | ######################### 111 | 112 | # Linux 113 | *~ 114 | # KDE 115 | .directory 116 | .AppleDouble 117 | 118 | # OSX 119 | .DS_Store 120 | *.swp 121 | *~.nib 122 | # Thumbnails 123 | ._* 124 | 125 | # Windows 126 | # Windows image file caches 127 | Thumbs.db 128 | # Folder config file 129 | Desktop.ini 130 | 131 | #Android 132 | .csettings 133 | 134 | ######################### 135 | # packages 136 | ######################### 137 | 138 | # it's better to unpack these files and commit the raw source 139 | # git has its own built in compression methods 140 | *.7z 141 | *.dmg 142 | *.gz 143 | *.iso 144 | *.jar 145 | *.rar 146 | *.tar 147 | *.zip 148 | 149 | # Logs and databases 150 | *.log 151 | *.sql 152 | *.sqlite 153 | 154 | 155 | ##------------------------------- 156 | 157 | ## more c++ patterns 158 | ## https://github.com/github/gitignore/blob/master/C%2B%2B.gitignore 159 | 160 | # Prerequisites 161 | *.d 162 | 163 | # Compiled Object files 164 | *.slo 165 | *.lo 166 | *.o 167 | *.obj 168 | 169 | # Precompiled Headers 170 | *.gch 171 | *.pch 172 | 173 | # Compiled Dynamic libraries 174 | *.so 175 | *.dylib 176 | *.dll 177 | 178 | # Fortran module files 179 | *.mod 180 | *.smod 181 | 182 | # Compiled Static libraries 183 | *.lai 184 | *.la 185 | *.a 186 | *.lib 187 | 188 | # Executables 189 | *.exe 190 | *.out 191 | *.app 192 | 193 | 194 | ##----------------------------------------------------------------- 195 | 196 | ## more VS patterns 197 | ## https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 198 | 199 | 200 | ## Ignore Visual Studio temporary files, build results, and 201 | ## files generated by popular Visual Studio add-ons. 202 | ## 203 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 204 | 205 | # User-specific files 206 | *.rsuser 207 | *.suo 208 | *.user 209 | *.userosscache 210 | *.sln.docstates 211 | 212 | # User-specific files (MonoDevelop/Xamarin Studio) 213 | *.userprefs 214 | 215 | # Mono auto generated files 216 | mono_crash.* 217 | 218 | # Build results 219 | [Dd]ebug/ 220 | [Dd]ebugPublic/ 221 | [Rr]elease/ 222 | [Rr]eleases/ 223 | x64/ 224 | x86/ 225 | [Aa][Rr][Mm]/ 226 | [Aa][Rr][Mm]64/ 227 | bld/ 228 | #[Bb]in/ 229 | [Oo]bj/ 230 | [Ll]og/ 231 | [Ll]ogs/ 232 | 233 | # Visual Studio 2015/2017 cache/options directory 234 | .vs/ 235 | # Uncomment if you have tasks that create the project's static files in wwwroot 236 | #wwwroot/ 237 | 238 | # Visual Studio 2017 auto generated files 239 | Generated\ Files/ 240 | 241 | # MSTest test Results 242 | [Tt]est[Rr]esult*/ 243 | [Bb]uild[Ll]og.* 244 | 245 | # NUnit 246 | *.VisualState.xml 247 | TestResult.xml 248 | nunit-*.xml 249 | 250 | # Build Results of an ATL Project 251 | [Dd]ebugPS/ 252 | [Rr]eleasePS/ 253 | dlldata.c 254 | 255 | # Benchmark Results 256 | BenchmarkDotNet.Artifacts/ 257 | 258 | # .NET Core 259 | project.lock.json 260 | project.fragment.lock.json 261 | artifacts/ 262 | 263 | # StyleCop 264 | StyleCopReport.xml 265 | 266 | # Files built by Visual Studio 267 | *_i.c 268 | *_p.c 269 | *_h.h 270 | *.ilk 271 | *.meta 272 | *.obj 273 | *.iobj 274 | *.pch 275 | *.pdb 276 | *.ipdb 277 | *.pgc 278 | *.pgd 279 | *.rsp 280 | *.sbr 281 | *.tlb 282 | *.tli 283 | *.tlh 284 | *.tmp 285 | *.tmp_proj 286 | *_wpftmp.csproj 287 | *.log 288 | *.vspscc 289 | *.vssscc 290 | .builds 291 | *.pidb 292 | *.svclog 293 | *.scc 294 | 295 | # Chutzpah Test files 296 | _Chutzpah* 297 | 298 | # Visual C++ cache files 299 | ipch/ 300 | *.aps 301 | *.ncb 302 | *.opendb 303 | *.opensdf 304 | *.sdf 305 | *.cachefile 306 | *.VC.db 307 | *.VC.VC.opendb 308 | 309 | # Visual Studio profiler 310 | *.psess 311 | *.vsp 312 | *.vspx 313 | *.sap 314 | 315 | # Visual Studio Trace Files 316 | *.e2e 317 | 318 | # TFS 2012 Local Workspace 319 | $tf/ 320 | 321 | # Guidance Automation Toolkit 322 | *.gpState 323 | 324 | # ReSharper is a .NET coding add-in 325 | _ReSharper*/ 326 | *.[Rr]e[Ss]harper 327 | *.DotSettings.user 328 | 329 | # TeamCity is a build add-in 330 | _TeamCity* 331 | 332 | # DotCover is a Code Coverage Tool 333 | *.dotCover 334 | 335 | # AxoCover is a Code Coverage Tool 336 | .axoCover/* 337 | !.axoCover/settings.json 338 | 339 | # Coverlet is a free, cross platform Code Coverage Tool 340 | coverage*[.json, .xml, .info] 341 | 342 | # Visual Studio code coverage results 343 | *.coverage 344 | *.coveragexml 345 | 346 | # NCrunch 347 | _NCrunch_* 348 | .*crunch*.local.xml 349 | nCrunchTemp_* 350 | 351 | # MightyMoose 352 | *.mm.* 353 | AutoTest.Net/ 354 | 355 | # Web workbench (sass) 356 | .sass-cache/ 357 | 358 | # Installshield output folder 359 | [Ee]xpress/ 360 | 361 | # DocProject is a documentation generator add-in 362 | DocProject/buildhelp/ 363 | DocProject/Help/*.HxT 364 | DocProject/Help/*.HxC 365 | DocProject/Help/*.hhc 366 | DocProject/Help/*.hhk 367 | DocProject/Help/*.hhp 368 | DocProject/Help/Html2 369 | DocProject/Help/html 370 | 371 | # Click-Once directory 372 | publish/ 373 | 374 | # Publish Web Output 375 | *.[Pp]ublish.xml 376 | *.azurePubxml 377 | # Note: Comment the next line if you want to checkin your web deploy settings, 378 | # but database connection strings (with potential passwords) will be unencrypted 379 | *.pubxml 380 | *.publishproj 381 | 382 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 383 | # checkin your Azure Web App publish settings, but sensitive information contained 384 | # in these scripts will be unencrypted 385 | PublishScripts/ 386 | 387 | # NuGet Packages 388 | *.nupkg 389 | # NuGet Symbol Packages 390 | *.snupkg 391 | # The packages folder can be ignored because of Package Restore 392 | **/[Pp]ackages/* 393 | # except build/, which is used as an MSBuild target. 394 | !**/[Pp]ackages/build/ 395 | # Uncomment if necessary however generally it will be regenerated when needed 396 | #!**/[Pp]ackages/repositories.config 397 | # NuGet v3's project.json files produces more ignorable files 398 | *.nuget.props 399 | *.nuget.targets 400 | 401 | # Microsoft Azure Build Output 402 | csx/ 403 | *.build.csdef 404 | 405 | # Microsoft Azure Emulator 406 | ecf/ 407 | rcf/ 408 | 409 | # Windows Store app package directories and files 410 | AppPackages/ 411 | BundleArtifacts/ 412 | Package.StoreAssociation.xml 413 | _pkginfo.txt 414 | *.appx 415 | *.appxbundle 416 | *.appxupload 417 | 418 | # Visual Studio cache files 419 | # files ending in .cache can be ignored 420 | *.[Cc]ache 421 | # but keep track of directories ending in .cache 422 | !?*.[Cc]ache/ 423 | 424 | # Others 425 | ClientBin/ 426 | ~$* 427 | *~ 428 | *.dbmdl 429 | *.dbproj.schemaview 430 | *.jfm 431 | *.pfx 432 | *.publishsettings 433 | orleans.codegen.cs 434 | 435 | # Including strong name files can present a security risk 436 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 437 | #*.snk 438 | 439 | # Since there are multiple workflows, uncomment next line to ignore bower_components 440 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 441 | #bower_components/ 442 | 443 | # RIA/Silverlight projects 444 | Generated_Code/ 445 | 446 | # Backup & report files from converting an old project file 447 | # to a newer Visual Studio version. Backup files are not needed, 448 | # because we have git ;-) 449 | _UpgradeReport_Files/ 450 | Backup*/ 451 | UpgradeLog*.XML 452 | UpgradeLog*.htm 453 | ServiceFabricBackup/ 454 | *.rptproj.bak 455 | 456 | # SQL Server files 457 | *.mdf 458 | *.ldf 459 | *.ndf 460 | 461 | # Business Intelligence projects 462 | *.rdl.data 463 | *.bim.layout 464 | *.bim_*.settings 465 | *.rptproj.rsuser 466 | *- [Bb]ackup.rdl 467 | *- [Bb]ackup ([0-9]).rdl 468 | *- [Bb]ackup ([0-9][0-9]).rdl 469 | 470 | # Microsoft Fakes 471 | FakesAssemblies/ 472 | 473 | # GhostDoc plugin setting file 474 | *.GhostDoc.xml 475 | 476 | # Node.js Tools for Visual Studio 477 | .ntvs_analysis.dat 478 | node_modules/ 479 | 480 | # Visual Studio 6 build log 481 | *.plg 482 | 483 | # Visual Studio 6 workspace options file 484 | *.opt 485 | 486 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 487 | *.vbw 488 | 489 | # Visual Studio LightSwitch build output 490 | **/*.HTMLClient/GeneratedArtifacts 491 | **/*.DesktopClient/GeneratedArtifacts 492 | **/*.DesktopClient/ModelManifest.xml 493 | **/*.Server/GeneratedArtifacts 494 | **/*.Server/ModelManifest.xml 495 | _Pvt_Extensions 496 | 497 | # Paket dependency manager 498 | .paket/paket.exe 499 | paket-files/ 500 | 501 | # FAKE - F# Make 502 | .fake/ 503 | 504 | # CodeRush personal settings 505 | .cr/personal 506 | 507 | # Python Tools for Visual Studio (PTVS) 508 | __pycache__/ 509 | *.pyc 510 | 511 | # Cake - Uncomment if you are using it 512 | # tools/** 513 | # !tools/packages.config 514 | 515 | # Tabs Studio 516 | *.tss 517 | 518 | # Telerik's JustMock configuration file 519 | *.jmconfig 520 | 521 | # BizTalk build output 522 | *.btp.cs 523 | *.btm.cs 524 | *.odx.cs 525 | *.xsd.cs 526 | 527 | # OpenCover UI analysis results 528 | OpenCover/ 529 | 530 | # Azure Stream Analytics local run output 531 | ASALocalRun/ 532 | 533 | # MSBuild Binary and Structured Log 534 | *.binlog 535 | 536 | # NVidia Nsight GPU debugger configuration file 537 | *.nvuser 538 | 539 | # MFractors (Xamarin productivity tool) working folder 540 | .mfractor/ 541 | 542 | # Local History for Visual Studio 543 | .localhistory/ 544 | 545 | # BeatPulse healthcheck temp database 546 | healthchecksdb 547 | 548 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 549 | MigrationBackup/ 550 | 551 | # Ionide (cross platform F# VS Code tools) working folder 552 | .ionide/ -------------------------------------------------------------------------------- /libs/ofxSequencer/src/ofxSequencer.h: -------------------------------------------------------------------------------- 1 | 2 | ///------------------------------------------------------------- 3 | ///addon modified from the original from: 4 | ///https://github.com/genekogan/ofxSequencer 5 | /// 6 | ///TODO: BUG: starting skips step 0... A standby state or step 0 (col -1) should be defined, to jump there when sequencer is stoped. Then, when staring, should jump to step 1 (col = 0) 7 | ///shoul be added a new standby -1 step to columns.. 8 | ///------------------------------------------------------------- 9 | 10 | ///TODO: BUG: massive overlap on startup ofOrganelle 11 | ///should debug: [notice ] ofxSequencer: set_GridFromSequencer 12 | ///] ofxSequencer: store_Row_Values: c: 14 = 0 13 | ///[verbose] ofxSequencer: store_Row_Values: c: 15 = 0 14 | 15 | #pragma once 16 | 17 | #include "ofMain.h" 18 | #include "ofxSequencerBpm.h" 19 | 20 | //#define NUM_SEQ_NOTES 12//max & fixed size 21 | //#define NUM_SEQ_BEATS 16//max & fixed size 22 | 23 | //-- 24 | 25 | //T ofxSequencerRowBase 26 | 27 | struct ofxSequencerRowBase 28 | { 29 | ofxSequencerRowBase(int cols); 30 | 31 | virtual string getName() 32 | { 33 | string name; return name; 34 | } 35 | 36 | template T getMin(); 37 | template T getMax(); 38 | 39 | template T getValue();//my getter 40 | 41 | template void setValue(int idx, T value); 42 | 43 | bool getValue_Cell(int idx);//works? 44 | 45 | //TODO: 46 | virtual void resetParam() { } 47 | 48 | virtual void update(int column) { } 49 | virtual void update(float cursor) { } 50 | virtual void randomize() { } 51 | 52 | virtual void mousePressed(int col, int x, int y) { } 53 | virtual void mouseDragged(int col, int y) { } 54 | virtual void mouseReleased(int col) { } 55 | 56 | virtual void draw(int col, int cellWidth, int cellHeight) { } 57 | 58 | int cols; 59 | 60 | //- 61 | 62 | //API 63 | 64 | virtual void store_Row_Values() { } 65 | 66 | //DATA 67 | 68 | vector grid_Rows; 69 | 70 | };//ofxSequencerRowBase 71 | 72 | //------------------ 73 | 74 | //T ofxSequencerRow 75 | 76 | template 77 | struct ofxSequencerRow : public ofxSequencerRowBase 78 | { 79 | ofxSequencerRow(ofParameter * parameter, int cols); 80 | 81 | string getName() 82 | { 83 | return parameter->getName(); 84 | } 85 | 86 | T getMin() 87 | { 88 | return parameter->getMin(); 89 | } 90 | 91 | T getMax() 92 | { 93 | return parameter->getMax(); 94 | } 95 | 96 | T getValue() 97 | { 98 | return parameter->getValue(); 99 | } 100 | 101 | void setValue(int idx, T value) 102 | { 103 | values[idx] = value; 104 | } 105 | 106 | bool getValue_Cell(int idx)//works 107 | { 108 | bool myVal = (bool) values[idx]; 109 | ofLogVerbose("ofxSequencer") << "- getValue_Cell(idx) : " << myVal; 110 | //return parameter->getMax(); 111 | return myVal;//bool 112 | } 113 | 114 | //- 115 | 116 | bool get_CellValue(int idx) 117 | { 118 | bool myVal = (bool) values[idx]; 119 | //ofLogVerbose("ofxSequencer") << "get_CellValue[idx] : " << myVal; 120 | return myVal; 121 | }; 122 | 123 | //TODO: 124 | void resetParam(); 125 | 126 | void update(int column); 127 | void update(float cursor); 128 | 129 | void randomize(); 130 | void store_Row_Values(); 131 | 132 | void mousePressed(int col, int x, int y); 133 | void mouseDragged(int col, int y); 134 | void mouseReleased(int col); 135 | void draw(int col, int cellWidth, int cellHeight); 136 | 137 | //- 138 | 139 | ofParameter * parameter; 140 | vector values; 141 | T pValue; 142 | ofPoint pMouse; 143 | 144 | //- 145 | 146 | }; //ofxSequencerRow 147 | 148 | //------------------ 149 | 150 | //creator row with columns 151 | 152 | template 153 | ofxSequencerRow::ofxSequencerRow(ofParameter * parameter, int cols) : ofxSequencerRowBase(cols) 154 | { 155 | this->parameter = parameter; 156 | for (int c=0; cget()); 159 | 160 | //-- 161 | 162 | //init row grid_Rows values vector 163 | grid_Rows.push_back( (bool) ( parameter->get() ) ); 164 | 165 | //-- 166 | } 167 | } //ofxSequencerRow 168 | 169 | //------------------ 170 | 171 | //TODO: 172 | //workaround to reset bool param only. 173 | //should upgrade to use with other types using min or zero/false 174 | template 175 | void ofxSequencerRow::resetParam() 176 | { 177 | *parameter = false; 178 | } 179 | 180 | //-- 181 | 182 | //update row parameter in current column 183 | 184 | template 185 | void ofxSequencerRow::update(int column) 186 | { 187 | *parameter = values[column]; 188 | } 189 | 190 | //------------------ 191 | 192 | //update row parameter by cursor 193 | 194 | template 195 | void ofxSequencerRow::update(float cursor) 196 | { 197 | *parameter = ofLerp(values[(int) floor(cursor)], values[(int) ceil(cursor) % values.size()], cursor - floor(cursor)); 198 | } 199 | 200 | //------------------ 201 | 202 | //randomize all columns (steps) in the row 203 | 204 | template 205 | void ofxSequencerRow::randomize() 206 | { 207 | for (int i = 0; i < values.size(); i++) { 208 | values[i] = ofRandom(parameter->getMin(), parameter->getMax()); 209 | 210 | //-- 211 | 212 | //TODO: add to grid_Rows too 213 | grid_Rows[i] = (bool) values[i]; 214 | } 215 | } 216 | 217 | //------------------ 218 | 219 | //read (from cells) and store all row columns values (steps) in bool vector grid_Rows 220 | 221 | template 222 | void ofxSequencerRow::store_Row_Values() 223 | { 224 | for (int c = 0; c < values.size(); c++) 225 | { 226 | //TODO: cell is float.. 227 | 228 | bool myVal; 229 | myVal = (bool) get_CellValue(c);//myVal = parameter->get(); 230 | 231 | ofLogVerbose("ofxSequencer") << "store_Row_Values: c: " << c << " = " << myVal; 232 | 233 | //store in row 234 | grid_Rows[c] = myVal; 235 | } 236 | } 237 | 238 | //------------------ 239 | 240 | //mouse handlers 241 | 242 | template 243 | void ofxSequencerRow::mousePressed(int col, int x, int y) 244 | { 245 | pMouse.set(x, y); 246 | pValue = values[col]; 247 | } 248 | 249 | template 250 | void ofxSequencerRow::mouseDragged(int col, int y) 251 | { 252 | 253 | } 254 | 255 | template<> 256 | inline void ofxSequencerRow::mouseDragged(int col, int y) 257 | { 258 | values[col] = ofClamp(pValue - 0.01 * (y - pMouse.y) * (parameter->getMax() - parameter->getMin()), parameter->getMin(), parameter->getMax()); 259 | } 260 | 261 | template<> 262 | inline void ofxSequencerRow::mouseDragged(int col, int y) 263 | { 264 | values[col] = ofClamp(pValue - 0.01 * (y - pMouse.y) * (parameter->getMax() - parameter->getMin()), parameter->getMin(), parameter->getMax()); 265 | } 266 | 267 | //------------------ 268 | 269 | //drawing functions 270 | 271 | template 272 | void ofxSequencerRow::draw(int col, int cellWidth, int cellHeight) 273 | { 274 | float rectMult = 1.0 / (parameter->getMax() - parameter->getMin()); 275 | ofDrawRectangle(0, 0, 276 | cellWidth * rectMult * (values[col] - parameter->getMin()), 277 | cellHeight * rectMult * (values[col] - parameter->getMin())); 278 | } 279 | 280 | template<> 281 | inline void ofxSequencerRow::draw(int col, int cellWidth, int cellHeight) 282 | { 283 | if (values[col]) 284 | { 285 | ofDrawRectangle(0, 0, cellWidth, cellHeight); 286 | } 287 | } 288 | 289 | //------------------ 290 | 291 | //mouse handlers 292 | 293 | template 294 | void ofxSequencerRow::mouseReleased(int col) 295 | { 296 | if (values[col] > 0.5 * (parameter->getMin() + parameter->getMax())){ 297 | values[col] = parameter->getMin(); 298 | } 299 | else { 300 | values[col] = parameter->getMax(); 301 | } 302 | } 303 | 304 | //------------------ 305 | 306 | template<> 307 | inline void ofxSequencerRow::mouseReleased(int col) 308 | { 309 | values[col] = 1.0 - values[col]; 310 | } 311 | 312 | //------------------ 313 | 314 | //rowBase getters 315 | 316 | template T ofxSequencerRowBase::getMin() 317 | { 318 | return dynamic_cast&>(*this).getMin(); 319 | } 320 | 321 | template T ofxSequencerRowBase::getMax() 322 | { 323 | return dynamic_cast&>(*this).getMax(); 324 | } 325 | 326 | template T ofxSequencerRowBase::getValue() 327 | { 328 | return dynamic_cast&>(*this).getValue(); 329 | } 330 | 331 | //------------------ 332 | 333 | //class methods 334 | 335 | class ofxSequencer 336 | { 337 | public: 338 | ofxSequencer(); 339 | ~ofxSequencer(); 340 | 341 | void setup(int cols, int beatsPerMinute=120, int beatsPerBar=4); 342 | void setBpm(int beatsPerMinute, int beatsPerBar=4); 343 | void setSmooth(bool smooth) {this->smooth = smooth;} 344 | 345 | int getBpm() {return beatsPerMinute;} 346 | bool getSmooth() {return smooth;} 347 | 348 | //-- 349 | 350 | template 351 | void addRow(ofParameter * parameter); 352 | 353 | //-- 354 | 355 | //TODO: BUG: play starts from step 1 instead of from 0 like expected! 356 | 357 | void start(); 358 | 359 | void advance(); 360 | 361 | //TODO: added transport methods 362 | //TODO: loop, one trig, loop and back... 363 | 364 | void stepBack(); 365 | 366 | void stop(); 367 | void reset(); 368 | void randomize(); 369 | 370 | //-- 371 | 372 | void set_GridFromSequencer(); 373 | void set_SequencerFromGrid(); 374 | 375 | void DEBUG_All_GRID();//show store GRID vector 376 | 377 | //-- 378 | 379 | void update(); 380 | void draw(); 381 | 382 | void setPosition(int x, int y, int width, int height); 383 | 384 | //TODO: 385 | void setVisible(bool visible); 386 | bool isVisible() { 387 | return bIsVisible; 388 | }; 389 | bool bIsVisible = true; 390 | //void toggleVisible(); 391 | 392 | void setMouseActive(bool active); 393 | 394 | //-- 395 | 396 | template 397 | void setValue(int r, int c, T value) { 398 | ((ofxSequencerRow*) rows[r])->setValue(c, value); 399 | toRedraw = true; 400 | } 401 | 402 | //-- 403 | 404 | template 405 | bool get_Value(int r, int c) { 406 | bool myValue = ((ofxSequencerRow*) rows[r])->get_Value(c); 407 | 408 | ofLogVerbose("ofxSequencer") << "-- get_Value " << "r:" << r << " c:" << c << " get_Value:" << myValue; 409 | return myValue; 410 | } 411 | 412 | int getColumn() {return column;} 413 | vector & getRows() {return rows;} 414 | 415 | //-- 416 | 417 | ofEvent beatEvent; 418 | 419 | //-- 420 | 421 | //made public.. 422 | float cursor; 423 | int column; 424 | 425 | //-- 426 | 427 | //SEQUENCER DATA 428 | 429 | //DATA GRID STORAGE. DUPLICATED FROM ORIGINAL CLASS. 430 | 431 | vector < vector > grid;//all cols in all rows 432 | 433 | //TODO: take care with this grid cause is bool not int! 434 | 435 | //------------------ 436 | 437 | private: 438 | 439 | void play(void); 440 | void redraw(); 441 | 442 | //- 443 | 444 | void mousePressed(ofMouseEventArgs &evt); 445 | void mouseDragged(ofMouseEventArgs &evt); 446 | void mouseReleased(ofMouseEventArgs &evt); 447 | 448 | //- 449 | 450 | vector rows; 451 | 452 | //- 453 | 454 | //float cursor;//go to public 455 | //int column; 456 | 457 | int beatsPerMinute; 458 | int bpmInterval; 459 | int bpmTime; 460 | bool smooth; 461 | ofxSequencerBpm bpm; 462 | 463 | //- 464 | 465 | int cols; 466 | int x, y, width, height; 467 | float cellWidth, cellHeight; 468 | 469 | ofPoint mCell; 470 | bool draggingCell; 471 | int draggingFrames; 472 | 473 | ofFbo fbo; 474 | bool toRedraw; 475 | 476 | //-- 477 | // 478 | // ofParameter loopBar; 479 | // ofParameter numBars; 480 | // ofParameter startBar; 481 | // 482 | //public: 483 | // void setLoopBarMode(bool b) 484 | // { 485 | // loopBar = b; 486 | // } 487 | // void setNumBarMode(int i) 488 | // { 489 | // numBars = i; 490 | // } 491 | // void setStartBar(int i) 492 | // { 493 | // startBar = i; 494 | // } 495 | }; 496 | 497 | //------------------ 498 | 499 | template 500 | void ofxSequencer::addRow(ofParameter * parameter) 501 | { 502 | ofxSequencerRow *newRow = new ofxSequencerRow(parameter, cols); 503 | rows.push_back(newRow); 504 | toRedraw = true; 505 | 506 | //-- 507 | 508 | //erase all bools cols for any rows (?) 509 | 510 | vector myBools; 511 | 512 | for (int c = 0 ; c < cols; c++) 513 | { 514 | bool defState = false; 515 | myBools.push_back(defState);//define cell 516 | } 517 | 518 | grid.push_back(myBools); //create row 519 | } 520 | 521 | //------------------ 522 | 523 | -------------------------------------------------------------------------------- /libs/ofxSequencer/src/ofxSequencer.cpp: -------------------------------------------------------------------------------- 1 | #include "ofxSequencer.h" 2 | 3 | //------------------------------------------------------------------- 4 | ofxSequencerRowBase::ofxSequencerRowBase(int cols) 5 | { 6 | this->cols = cols; 7 | } 8 | 9 | //------------------------------------------------------------------- 10 | ofxSequencer::ofxSequencer() 11 | { 12 | toRedraw = true; 13 | } 14 | 15 | //------------------------------------------------------------------- 16 | ofxSequencer::~ofxSequencer() 17 | { 18 | stop(); 19 | } 20 | 21 | //------------------------------------------------------------------- 22 | void ofxSequencer::setup(int cols, int beatsPerMinute, int beatsPerBar) 23 | { 24 | ofLogNotice("ofxSequencer") << __FUNCTION__; 25 | ofSetLogLevel(OF_LOG_NOTICE); 26 | 27 | //TODO: BUG: add step 0 28 | 29 | //total num cols 30 | this->cols = cols; 31 | //this->cols = cols + 1;//total num cols 32 | 33 | setBpm(beatsPerMinute, beatsPerBar); 34 | setMouseActive(true); 35 | setPosition(0, 0, 24 * cols, 96); 36 | 37 | //-- 38 | 39 | ////TODO: 40 | //BUG: add step 0 41 | //for (int r = 0; r < NUM_SEQ_NOTES; r++) 42 | //{ 43 | // this->setValue(r, 0, false); 44 | //} 45 | 46 | //- 47 | 48 | //TODO: 49 | //maybe should change from vector to array fixed size mode.. 50 | //maybe to use pointers too 51 | ////resize and erase bools grid. 12 rows and 16 cols 52 | //for (int r = 0; r < 12; r++) 53 | //{ 54 | // vector myBools; 55 | // for (int c = 0 ; c < 16; c++) 56 | // { 57 | // myBools.push_back(false); 58 | // } 59 | // GRID_values.push_back(myBools);//create row 60 | //} 61 | 62 | //-- 63 | 64 | reset();//to reset beat to -1 65 | } 66 | 67 | //------------------------------------------------------------------- 68 | void ofxSequencer::setBpm(int beatsPerMinute, int beatsPerBar) 69 | { 70 | ofLogNotice("ofxSequencer") << __FUNCTION__; 71 | this->beatsPerMinute = beatsPerMinute; 72 | bpm.setBpm(beatsPerMinute); 73 | bpm.setBeatPerBar(beatsPerBar); 74 | bpmInterval = 60000.0 / beatsPerMinute; 75 | } 76 | 77 | //------------------------------------------------------------------- 78 | void ofxSequencer::start() 79 | { 80 | ofLogNotice("ofxSequencer") << __FUNCTION__; 81 | ofAddListener(bpm.beatEvent, this, &ofxSequencer::play); 82 | bpm.start(); 83 | } 84 | 85 | //------------------------------------------------------------------- 86 | void ofxSequencer::stop() 87 | { 88 | ofLogNotice("ofxSequencer") << __FUNCTION__; 89 | ofRemoveListener(bpm.beatEvent, this, &ofxSequencer::play); 90 | bpm.stop(); 91 | } 92 | 93 | //------------------------------------------------------------------- 94 | void ofxSequencer::reset() 95 | { 96 | ofLogNotice("ofxSequencer") << __FUNCTION__; 97 | bpm.reset(); 98 | //column = 0; 99 | 100 | //TODO: BUG: add step 0 101 | column = -1; 102 | 103 | //TODO: 104 | //workaround to disable all toggles when stopped 105 | //could add a last step with all params disabled? 106 | for (int r = 0; r < rows.size(); r++) 107 | { 108 | rows[r]->resetParam(); 109 | 110 | //rows[r]->update(0); 111 | //rows[r]->update(this->cols-1); 112 | //rows[r]->update(cols);//this works on macOS but crashes on Windows 113 | } 114 | } 115 | 116 | //------------------------------------------------------------------- 117 | void ofxSequencer::randomize() 118 | { 119 | for (int r = 0; r < rows.size(); r++) 120 | { 121 | rows[r]->randomize(); 122 | } 123 | toRedraw = true; 124 | } 125 | 126 | //------------------------------------------------------------------- 127 | void ofxSequencer::DEBUG_All_GRID() 128 | { 129 | //dump grid matrix values 130 | 131 | ofLogNotice("ofxSequencer") << "DEBUG_All_GRID"; 132 | 133 | bool myVal; 134 | for (int r = 0; r < rows.size(); r++) 135 | { 136 | ofLogVerbose("ofxSequencer") << "--- row " << r; 137 | 138 | for (int c = 0; c < cols; c++) 139 | //for (int c = 0; c < cols-1; c++) 140 | { 141 | myVal = grid[r][c]; 142 | 143 | ofLogVerbose("ofxSequencer") << "- col " << c << " " << myVal; 144 | } 145 | } 146 | ofLogVerbose("ofxSequencer") << "-------------------------------------------"; 147 | } 148 | 149 | //------------------------------------------------------------------- 150 | void ofxSequencer::set_GridFromSequencer() 151 | { 152 | //get values from internal draw parameters to data grid vector ? 153 | 154 | ofLogNotice("ofxSequencer") << "set_GridFromSequencer"; 155 | 156 | for (int r = 0; r < rows.size(); r++) 157 | { 158 | ofLogVerbose("ofxSequencer") << "--- row " << r; 159 | 160 | //TODO: ?? 161 | //save every row columns values on his object.. ?? 162 | rows[r]->store_Row_Values();//working 163 | 164 | //- 165 | 166 | for (int c = 0; c < cols; c++) 167 | //for (int c = 0; c < cols-1; c++) 168 | { 169 | //ofLogVerbose("ofxSequencer") << "r:" << r << " c:" << c; 170 | 171 | bool myVal; 172 | myVal = rows[r]->grid_Rows[c];//test after move to base 173 | 174 | grid[r][c] = myVal; 175 | } 176 | ofLogVerbose("ofxSequencer") << "----------------------------"; 177 | } 178 | } 179 | 180 | //------------------------------------------------ 181 | void ofxSequencer::set_SequencerFromGrid() 182 | { 183 | ofLogNotice("ofxSequencer") << "set_SequencerFromGrid"; 184 | 185 | //put sequencer draw parameters values (bool) from grid vector (bool) ! 186 | 187 | for (int n = 0; n < rows.size(); n++) 188 | { 189 | string str; 190 | 191 | ofLogVerbose("ofxSequencer") << "row:" << n; 192 | 193 | for (int b = 0; b < cols; b++) 194 | //for (int b = 0; b < cols-1; b++) 195 | { 196 | //SEQUENCER CLASS 197 | 198 | //set value to sequencer grid squares 199 | 200 | bool state = grid[n][b]; 201 | str += ofToString(state) + " "; 202 | 203 | setValue(n, b, state); 204 | 205 | //- 206 | } 207 | 208 | ofLogVerbose("ofxSequencer") << str; 209 | } 210 | } 211 | 212 | //------------------------------------------------------------------- 213 | void ofxSequencer::play(void) 214 | { 215 | ofLogNotice("ofxSequencer") << __FUNCTION__; 216 | advance(); 217 | } 218 | 219 | //------------------------------------------------------------------- 220 | void ofxSequencer::advance() 221 | { 222 | column = (column + 1) % cols; 223 | //TODO: BUG: add step 0 224 | //column = (column + 1) % (cols-1); 225 | 226 | if (smooth) 227 | { 228 | bpmTime = ofGetElapsedTimeMillis(); 229 | cursor = column; 230 | for (auto r : rows) 231 | { 232 | r->update(cursor); 233 | } 234 | } 235 | else 236 | { 237 | for (auto r : rows) 238 | { 239 | r->update(column); 240 | } 241 | } 242 | 243 | ofNotifyEvent(beatEvent, column, this); 244 | } 245 | 246 | //------------------------------------------------------------------- 247 | void ofxSequencer::stepBack() 248 | { 249 | column = (column - 1);//% cols; 250 | if (column < 0) 251 | column = 0; 252 | 253 | if (smooth) 254 | { 255 | bpmTime = ofGetElapsedTimeMillis(); 256 | cursor = column; 257 | for (auto r : rows) 258 | { 259 | r->update(cursor); 260 | } 261 | } 262 | else 263 | { 264 | for (auto r : rows) 265 | { 266 | r->update(column); 267 | } 268 | } 269 | 270 | ofNotifyEvent(beatEvent, column, this); 271 | } 272 | 273 | //------------------------------------------------------------------- 274 | 275 | //MOUSE HANDLERS: 276 | 277 | //------------------------------------------------------------------- 278 | void ofxSequencer::setMouseActive(bool active) 279 | { 280 | if (active) 281 | { 282 | //ofAddListener(ofEvents().mousePressed, this, &ofxSequencer::mousePressed); 283 | //ofAddListener(ofEvents().mouseReleased, this, &ofxSequencer::mouseReleased); 284 | //ofAddListener(ofEvents().mouseDragged, this, &ofxSequencer::mouseDragged); 285 | //TODO: 286 | //trying workaround to solve mouse bugs.. 287 | //mouse clicks are ignored sometimes.. 288 | ofAddListener(ofEvents().mousePressed, this, &ofxSequencer::mousePressed, OF_EVENT_ORDER_AFTER_APP); 289 | ofAddListener(ofEvents().mouseReleased, this, &ofxSequencer::mouseReleased, OF_EVENT_ORDER_AFTER_APP); 290 | ofAddListener(ofEvents().mouseDragged, this, &ofxSequencer::mouseDragged, OF_EVENT_ORDER_AFTER_APP); 291 | 292 | } 293 | else 294 | { 295 | ofRemoveListener(ofEvents().mousePressed, this, &ofxSequencer::mousePressed, OF_EVENT_ORDER_AFTER_APP); 296 | ofRemoveListener(ofEvents().mouseReleased, this, &ofxSequencer::mouseReleased, OF_EVENT_ORDER_AFTER_APP); 297 | ofRemoveListener(ofEvents().mouseDragged, this, &ofxSequencer::mouseDragged, OF_EVENT_ORDER_AFTER_APP); 298 | } 299 | } 300 | 301 | //------------------------------------------------------------------- 302 | void ofxSequencer::mousePressed(ofMouseEventArgs &evt) 303 | { 304 | ofRectangle seqRect(x, y, width, height); 305 | if (seqRect.inside(evt.x, evt.y)) 306 | { 307 | mCell.set(floor((evt.x - x) / cellWidth), 308 | floor((evt.y - y) / cellHeight)); 309 | rows[mCell.y]->mousePressed(mCell.x, evt.x, evt.y); 310 | draggingCell = true; 311 | 312 | ofLogVerbose("ofxSequencer") << "< pressed: mCell x " << mCell.x; 313 | ofLogVerbose("ofxSequencer") << "< pressed: mCell y " << mCell.y; 314 | } 315 | } 316 | 317 | //------------------------------------------------------------------- 318 | void ofxSequencer::mouseDragged(ofMouseEventArgs &evt) 319 | { 320 | if (draggingCell) 321 | { 322 | rows[mCell.y]->mouseDragged(mCell.x, ofGetMouseY()); 323 | draggingFrames++; 324 | toRedraw = true; 325 | } 326 | } 327 | 328 | //------------------------------------------------------------------- 329 | void ofxSequencer::mouseReleased(ofMouseEventArgs &evt) 330 | { 331 | if (draggingCell && draggingFrames == 0) 332 | { 333 | rows[mCell.y]->mouseReleased(mCell.x); 334 | 335 | ofLogVerbose("ofxSequencer") << "< released: mCell x " << mCell.x; 336 | ofLogVerbose("ofxSequencer") << "< released: mCell y " << mCell.y; 337 | } 338 | else 339 | { 340 | draggingFrames = 0; 341 | } 342 | draggingCell = false; 343 | toRedraw = true; 344 | } 345 | 346 | //------------------------------------------------------------------- 347 | void ofxSequencer::setPosition(int x, int y, int width, int height) 348 | { 349 | this->x = x; 350 | this->y = y; 351 | this->width = width; 352 | this->height = height; 353 | fbo.allocate(width, height); 354 | fbo.begin(); 355 | ofClear(0, 0); 356 | fbo.end(); 357 | toRedraw = true; 358 | } 359 | 360 | //------------------------------------------------------------------- 361 | void ofxSequencer::setVisible(bool visible) 362 | { 363 | bIsVisible = visible; 364 | } 365 | 366 | //------------------------------------------------------------------- 367 | void ofxSequencer::update() 368 | { 369 | if (smooth && bpm.isPlaying()) 370 | { 371 | cursor = column + (float)(ofGetElapsedTimeMillis() - bpmTime) / bpmInterval; 372 | for (auto r : rows) 373 | { 374 | r->update(cursor); 375 | } 376 | } 377 | } 378 | 379 | //------------------------------------------------------------------- 380 | void ofxSequencer::draw() 381 | { 382 | if (bIsVisible) 383 | { 384 | //update drawing only if grid changed to improve performance 385 | if (toRedraw) 386 | { 387 | redraw(); 388 | toRedraw = false; 389 | } 390 | 391 | ofPushMatrix(); 392 | ofPushStyle(); 393 | 394 | //draw grid fbo 395 | ofTranslate(x, y); 396 | ofSetColor(255); 397 | fbo.draw(0, 0, width, height); 398 | 399 | ofSetRectMode(OF_RECTMODE_CORNER); 400 | //ofSetLineWidth(4); 401 | ofSetLineWidth(2); 402 | ofNoFill(); 403 | 404 | //vertical bar line on current player position/column 405 | if (bpm.isPlaying() && smooth) 406 | { 407 | float t = cursor - floor(cursor); 408 | ofSetColor(255, 0, 0, 255 * (1 - t)); 409 | ofDrawRectangle(cellWidth * column, 0, cellWidth, height); 410 | ofSetColor(255, 0, 0, 255 * t); 411 | ofDrawRectangle(cellWidth * ((column + 1) % cols), 0, cellWidth, height); 412 | //ofDrawRectangle(cellWidth * ((column + 1) % (cols-1)), 0, cellWidth, height); 413 | } 414 | else if (column != -1) 415 | { 416 | //ofSetColor(255, 0, 0); 417 | ////lines only 418 | //ofNoFill(); 419 | //ofSetColor(ofColor::white); 420 | //ofDrawRectangle(cellWidth * column, 0, cellWidth, height); 421 | 422 | //filled bar with alpha 423 | ofFill(); 424 | int grey = 255; 425 | int a = 64; 426 | ofColor c; 427 | c.set(grey); 428 | ofSetColor(c.r, c.g, c.b, a); 429 | ofDrawRectangle(cellWidth * column, 0, cellWidth, height); 430 | } 431 | 432 | ofPopStyle(); 433 | ofPopMatrix(); 434 | 435 | ////debug 436 | //ofSetColor(ofColor::white); 437 | //ofDrawBitmapString(ofToString(column), 800, 800); 438 | ////if (column == 4) column = 0; 439 | } 440 | } 441 | 442 | //------------------------------------------------------------------- 443 | void ofxSequencer::redraw() 444 | { 445 | //every cell size 446 | cellWidth = (float)width / cols; 447 | //cellWidth = (float) width / (cols-1); 448 | cellHeight = (float)height / rows.size(); 449 | 450 | //- 451 | 452 | fbo.begin(); 453 | ofPushMatrix(); 454 | ofPushStyle(); 455 | 456 | //- 457 | 458 | ofSetColor(0); 459 | ofFill(); 460 | ofDrawRectangle(0, 0, width + 120, height); 461 | ofSetColor(255); 462 | ofSetRectMode(OF_RECTMODE_CENTER); 463 | ofTranslate(0.5 * cellWidth, 0.5 * cellHeight); 464 | 465 | //draw every cell name to the left 466 | for (int r = 0; r < rows.size(); r++) 467 | { 468 | ofSetColor(255); 469 | //for (int c = 0; c < cols-1; c++) 470 | for (int c = 0; c < cols; c++) 471 | { 472 | rows[r]->draw(c, cellWidth, cellHeight); 473 | ofTranslate(cellWidth, 0); 474 | } 475 | ofTranslate(-cols * cellWidth, cellHeight); 476 | //ofSetColor(0, 200, 0); 477 | ofSetColor(ofColor::white); 478 | 479 | //text label 480 | ofDrawBitmapString(rows[r]->getName(), -20 - 0.5 * cellWidth + 2, -cellHeight + 8); 481 | } 482 | 483 | //lines 484 | ofTranslate(-0.5 * cellWidth, (-0.5 - rows.size()) * cellHeight); 485 | ofSetColor(100); 486 | ofSetLineWidth(1); 487 | for (int r = 1; r < rows.size(); r++) 488 | { 489 | ofDrawLine(0, r * cellHeight, width, r * cellHeight); 490 | } 491 | for (int c = 1; c < cols; c++) 492 | { 493 | //for (int c=1; c", false); 57 | params.add(bSave); 58 | params.add(bAutoLoad); 59 | params.add(bAutoSave); 60 | params.add(bCloneToRight); 61 | 62 | ofAddListener(params.parameterChangedE(), this, &ofxPresetDataGrid::Changed_Params); 63 | 64 | //---- 65 | 66 | //startup 67 | 68 | PRESET_selected_PRE = -1; 69 | 70 | DISABLE_CALLBACKS = false; 71 | 72 | //---- 73 | } 74 | 75 | //------------------------------------------------ 76 | ofxPresetDataGrid::~ofxPresetDataGrid() 77 | { 78 | save_ControlSettings(); 79 | 80 | ofRemoveListener(params.parameterChangedE(), this, &ofxPresetDataGrid::Changed_Params); 81 | } 82 | 83 | //------------------------------------------------ 84 | int ofxPresetDataGrid::getGuiIndex(string name) const { 85 | 86 | for (size_t i = 0; i < grids.size(); ++i) 87 | { 88 | string myName = grids[i]->getName(); 89 | if (myName == name) { 90 | return i; 91 | } 92 | return -1; 93 | } 94 | } 95 | 96 | //------------------------------------------------ 97 | string ofxPresetDataGrid::presetName(string guiName, int presetIndex) 98 | { 99 | string folder; 100 | folder = "/"; //without subfolder. must ends with "/" 101 | //folder = "/patterns/"; //using subfolder 102 | 103 | return (folder + guiName + "_preset_" + ofToString(presetIndex) + ".json"); 104 | } 105 | 106 | //------------------------------------------------ 107 | void ofxPresetDataGrid::add(DataGrid & grid, int numPresets) 108 | { 109 | //add a gui for preset saving 110 | 111 | grids.push_back(&grid); 112 | 113 | lastIndices.push_back(0); 114 | newIndices.push_back(0); 115 | presets.push_back(numPresets); 116 | 117 | //- 118 | 119 | num_presets = numPresets; 120 | (group->getIntSlider("PRESETS"))->setMax(num_presets); 121 | } 122 | 123 | //------------------------------------------------ 124 | void ofxPresetDataGrid::add(DataGrid & grid, initializer_list keysList) 125 | { 126 | add(grid, keysList.size()); 127 | 128 | keys.resize(grids.size()); 129 | int i = grids.size() - 1; 130 | 131 | keys[i].reserve(keysList.size()); 132 | 133 | for (const int & key : keysList) keys[i].push_back(key); 134 | 135 | if (keysNotActivated) 136 | addKeysListeners(); 137 | } 138 | 139 | //------------------------------------------------ 140 | void ofxPresetDataGrid::save(int presetIndex, int guiIndex) 141 | { 142 | if (guiIndex >= 0 && guiIndex < (int)grids.size()) 143 | { 144 | ofLogNotice("ofxPresetDataGrid") << "DONE_save"; 145 | DONE_save = true; 146 | //will make in SEQ: get sequencer state before saving in preset manager 147 | //GRID_getFrom_Sequencer(); 148 | 149 | //- 150 | 151 | std::string n = presetName(grids[guiIndex]->getName(), presetIndex); 152 | 153 | ofLogNotice("ofxPresetDataGrid") << "save(presetIndex, guiIndex): " << presetIndex << ", " << guiIndex; 154 | ofLogNotice("ofxPresetDataGrid") << "grids[guiIndex]->getName(): " << grids[guiIndex]->getName(); 155 | ofLogNotice("ofxPresetDataGrid") << "n: " << n; 156 | 157 | grids[guiIndex]->save_JSON(pathKitFolder + "/" + n); 158 | } 159 | } 160 | 161 | //------------------------------------------------ 162 | void ofxPresetDataGrid::save(int presetIndex, string guiName) 163 | { 164 | int guiIndex = getGuiIndex(guiName); 165 | 166 | if (guiIndex >= 0 && guiIndex < (int)grids.size()) 167 | { 168 | ofLogNotice("ofxPresetDataGrid") << "DONE_save"; 169 | DONE_save = true; 170 | //will make in SEQ: get sequencer state before saving in preset manager 171 | //GRID_getFrom_Sequencer(); 172 | 173 | //- 174 | 175 | ofLogNotice("ofxPresetDataGrid") << "save( presetIndex, guiName): " << presetIndex << ", " << guiName; 176 | ofLogNotice("ofxPresetDataGrid") << "guiIndex = getGuiIndex(guiName): " << guiIndex; 177 | 178 | string n = presetName(guiName, presetIndex); 179 | 180 | grids[guiIndex]->save_JSON(pathKitFolder + "/" + n); 181 | } 182 | } 183 | 184 | //------------------------------------------------ 185 | void ofxPresetDataGrid::load(int presetIndex, int guiIndex) 186 | { 187 | if (guiIndex >= 0 && guiIndex < (int)grids.size()) 188 | { 189 | ofLogNotice("ofxPresetDataGrid") << "load(presetIndex, guiIndex): " << presetIndex << ", " << guiIndex; 190 | 191 | string str = presetName(grids[guiIndex]->getName(), presetIndex); 192 | grids[guiIndex]->load_JSON(pathKitFolder + "/" + str); 193 | 194 | lastIndices[guiIndex] = presetIndex; 195 | 196 | //grids[guiIndex]->dump_grid(); 197 | 198 | //- 199 | 200 | ofLogNotice("ofxPresetDataGrid") << "DONE_load"; 201 | DONE_load = true; 202 | } 203 | } 204 | 205 | //------------------------------------------------ 206 | void ofxPresetDataGrid::load(int presetIndex, string guiName) 207 | { 208 | int guiIndex = getGuiIndex(guiName); 209 | 210 | if (guiIndex >= 0 && guiIndex < (int)grids.size()) { 211 | 212 | ofLogNotice("ofxPresetDataGrid") << "load(presetIndex, guiName): " << presetIndex << ", " << guiName; 213 | 214 | string n = presetName(guiName, presetIndex); 215 | grids[guiIndex]->load_JSON(pathKitFolder + "/" + n); 216 | 217 | lastIndices[guiIndex] = presetIndex; 218 | 219 | //- 220 | 221 | ofLogNotice("ofxPresetDataGrid") << "DONE_load"; 222 | DONE_load = true; 223 | } 224 | } 225 | 226 | //------------------------------------------------ 227 | int ofxPresetDataGrid::getPresetIndex(int guiIndex) const 228 | { 229 | if (guiIndex > 0 && guiIndex < (int)grids.size()) { 230 | return lastIndices[guiIndex]; 231 | } 232 | else { 233 | return -1; 234 | } 235 | } 236 | 237 | //------------------------------------------------ 238 | int ofxPresetDataGrid::getPresetIndex(string guiName)const 239 | { 240 | int guiIndex = getGuiIndex(guiName); 241 | 242 | if (guiIndex > 0 && guiIndex < (int)grids.size()) 243 | { 244 | return lastIndices[guiIndex]; 245 | } 246 | else 247 | { 248 | return -1; 249 | } 250 | } 251 | 252 | //------------------------------------------------ 253 | void ofxPresetDataGrid::setModeKey(int key) 254 | { 255 | modeKey = key; 256 | } 257 | 258 | //---------------------------------------------------------------- 259 | void ofxPresetDataGrid::keyPressed(ofKeyEventArgs& eventArgs) 260 | { 261 | if (bKeys && ENABLE_shortcuts) 262 | { 263 | const int & key = eventArgs.key; 264 | 265 | if (key == modeKey) 266 | { 267 | bKeySave = true; 268 | return; 269 | } 270 | 271 | for (size_t i = 0; i < keys.size(); ++i) 272 | { 273 | for (size_t k = 0; k < keys[i].size(); ++k) 274 | { 275 | if (key == keys[i][k]) 276 | { 277 | if (bKeySave) 278 | { 279 | save(k, i); 280 | } 281 | else 282 | { 283 | if (bDelayedLoading) 284 | { 285 | //newIndices[i] = k; 286 | //ofLogNotice("ofxPresetDataGrid") << "newIndices[i] = k;" << k << ", " << i; 287 | //PRESET_selected = 1 + k; 288 | } 289 | else 290 | { 291 | //load( k, i ); 292 | //ofLogNotice("ofxPresetDataGrid") << "load( k, i ):" << k << ", " << i; 293 | 294 | PRESET_selected = 1 + k;//first row/gui only 295 | } 296 | } 297 | return; 298 | } 299 | } 300 | } 301 | } 302 | } 303 | 304 | //------------------------------------------------ 305 | void ofxPresetDataGrid::keyReleased(ofKeyEventArgs& eventArgs) 306 | { 307 | if (eventArgs.key == modeKey && ENABLE_shortcuts) bKeySave = false; 308 | } 309 | 310 | //------------------------------------------------ 311 | void ofxPresetDataGrid::addKeysListeners() 312 | { 313 | ofAddListener(ofEvents().keyPressed, this, &ofxPresetDataGrid::keyPressed); 314 | ofAddListener(ofEvents().keyReleased, this, &ofxPresetDataGrid::keyReleased); 315 | keysNotActivated = false; 316 | bKeys = true; 317 | } 318 | 319 | //------------------------------------------------ 320 | void ofxPresetDataGrid::setPosition_ClickerPanel(int x, int y, int cellSize) 321 | { 322 | this->x = x; 323 | this->y = y; 324 | this->cellSize = cellSize; 325 | } 326 | 327 | //------------------------------------------------ 328 | void ofxPresetDataGrid::draw(int x, int y, int cellSize) 329 | { 330 | setPosition_ClickerPanel(x, y, cellSize); 331 | draw(); 332 | } 333 | 334 | //--------------------------------------------------------------------- 335 | void ofxPresetDataGrid::draw() 336 | { 337 | if (SHOW_ClickPanel) 338 | { 339 | if (!lastMouseButtonState && ofGetMousePressed()) 340 | { 341 | mousePressed(ofGetMouseX(), ofGetMouseY()); 342 | } 343 | lastMouseButtonState = ofGetMousePressed(); 344 | 345 | ofPushMatrix(); 346 | ofPushStyle(); 347 | 348 | ofSetLineWidth(1.0f); 349 | ofSetColor(ofColor::white); 350 | ofNoFill(); 351 | ofTranslate(x, y); 352 | 353 | for (size_t i = 0; i < keys.size(); ++i) 354 | { 355 | size_t k = 0; 356 | for (; k < keys[i].size(); ++k) 357 | { 358 | ofDrawRectangle(cellSize * k, cellSize * i, cellSize, cellSize); 359 | 360 | if (!myFont.isLoaded()) 361 | ofDrawBitmapString(ofToString((char)keys[i][k]), cellSize*k + 8, cellSize*i + 18); 362 | else 363 | myFont.drawString(ofToString((char)keys[i][k]), 364 | cellSize * k + 0.5f * cellSize - 0.25f * sizeTTF, 365 | cellSize * i + 0.5f * cellSize + 0.5f * sizeTTF); 366 | 367 | if (lastIndices[i] == k) ofDrawRectangle(cellSize * k + 4, cellSize * i + 4, cellSize - 8, cellSize - 8); 368 | } 369 | for (; k < presets[i]; ++k) 370 | { 371 | ofDrawRectangle(cellSize * k, cellSize * i, cellSize, cellSize); 372 | if (lastIndices[i] == k) ofDrawRectangle(cellSize * k + 4, cellSize * i + 4, cellSize - 8, cellSize - 8); 373 | } 374 | 375 | //save button 376 | ofDrawRectangle(cellSize * k, cellSize * i, cellSize, cellSize); 377 | 378 | //label 379 | if (!myFont.isLoaded()) 380 | ofDrawBitmapString("SAVE", cellSize*k + 10, cellSize*i + 18); 381 | else 382 | myFont.drawString("SAVE", cellSize * k + sizeTTF - 2, cellSize * i + cellSize * 0.5f + 0.5 * sizeTTF); 383 | 384 | k++; 385 | 386 | //- 387 | 388 | //kit name 389 | //ofDrawBitmapString( grids[i]->getName(), cellSize*k+8, cellSize*i+18 ); 390 | 391 | //- 392 | } 393 | 394 | ofPopStyle(); 395 | ofPopMatrix(); 396 | } 397 | } 398 | 399 | //----------------------------------------------------- 400 | void ofxPresetDataGrid::mousePressed(int x, int y) 401 | { 402 | x -= this->x; 403 | y -= this->y; 404 | 405 | int xIndex = x / cellSize; 406 | int yIndex = y / cellSize; 407 | 408 | xIndex = (x > 0) ? xIndex : -1; 409 | yIndex = (y > 0) ? yIndex : -1; 410 | 411 | //if (xIndex != -1 && yIndex != -1) 412 | // ofLogNotice("ofxPresetDataGrid") << "mousePressed - xIndex, yIndex: " << xIndex << ", " << yIndex; 413 | 414 | //- 415 | 416 | //custom DataGrid class 417 | 418 | if (yIndex >= 0 && yIndex < (int)grids.size()) 419 | { 420 | //row buttons, preset selctors 421 | if (xIndex >= 0 && xIndex < presets[yIndex]) 422 | { 423 | //load 424 | if (bDelayedLoading) 425 | { 426 | // newIndices[yIndex] = xIndex; 427 | // ofLogNotice("ofxPresetDataGrid") << "newIndices[yIndex] = xIndex:" << yIndex << " = " << xIndex; 428 | } 429 | else 430 | { 431 | // load( xIndex, yIndex); 432 | // ofLogNotice("ofxPresetDataGrid") << "load( xIndex, yIndex):" << xIndex << ", " << yIndex; 433 | 434 | PRESET_selected = 1 + xIndex; 435 | } 436 | } 437 | 438 | //last button (save button) 439 | else if (xIndex == presets[yIndex]) 440 | { 441 | ofLogNotice("ofxPresetDataGrid") << "saveButton: ( lastIndices[yIndex], yIndex ): " << lastIndices[yIndex] << ", " << yIndex; 442 | 443 | //save 444 | 445 | //save( lastIndices[yIndex], yIndex ); 446 | 447 | ////save( k, i);//this is from keyPressed 448 | ////PRESET_selected = 1 + yIndex; 449 | 450 | doSave(lastIndices[yIndex]); 451 | } 452 | } 453 | 454 | //- 455 | } 456 | 457 | //------------------------------------------------ 458 | void ofxPresetDataGrid::setDelayedLoading(bool active) 459 | { 460 | bDelayedLoading = active; 461 | } 462 | 463 | //------------------------------------------------ 464 | void ofxPresetDataGrid::delayedLoad(int presetIndex, int guiIndex) 465 | { 466 | if (guiIndex >= 0 && guiIndex < (int)grids.size()) 467 | { 468 | newIndices[guiIndex] = presetIndex; 469 | } 470 | } 471 | 472 | //------------------------------------------------ 473 | void ofxPresetDataGrid::delayedLoad(int presetIndex, string guiName) 474 | { 475 | int guiIndex = getGuiIndex(guiName); 476 | 477 | if (guiIndex >= 0 && guiIndex < (int)grids.size()) 478 | { 479 | newIndices[guiIndex] = presetIndex; 480 | } 481 | } 482 | 483 | //------------------------------------------------ 484 | void ofxPresetDataGrid::delayedUpdate() 485 | { 486 | for (size_t i = 0; i < grids.size(); ++i) 487 | { 488 | if (newIndices[i] != lastIndices[i]) 489 | { 490 | load(newIndices[i], i); 491 | } 492 | } 493 | } 494 | 495 | //------------------------------------------------ 496 | void ofxPresetDataGrid::toggleKeysControl(bool active) 497 | { 498 | bKeys = active; 499 | } 500 | 501 | //-- 502 | 503 | //PRESET GUI MANAGER 504 | 505 | //------------------------------------------------ 506 | void ofxPresetDataGrid::Changed_Params(ofAbstractParameter &e) 507 | { 508 | if (!DISABLE_CALLBACKS) 509 | { 510 | string name = e.getName(); 511 | 512 | ofLogNotice("ofxPresetDataGrid") << "Changed_Params '" << name << "': " << e; 513 | 514 | if (name == "SAVE" && (bSave)) { 515 | ofLogNotice("ofxPresetDataGrid") << "SAVE: " << e; 516 | doSave(PRESET_selected - 1); 517 | } 518 | 519 | else if (name == "CLONE >" && (bCloneToRight)) 520 | { 521 | ofLogNotice("ofxPresetDataGrid") << "CLONE >: " << e; 522 | doCloneRight(PRESET_selected - 1); 523 | } 524 | 525 | else if (name == "PRESETS" && (PRESET_selected != PRESET_selected_PRE)) 526 | { 527 | ofLogNotice("ofxPresetDataGrid") << "Changed PRESET_selected: " << e; 528 | 529 | //load 530 | if (bDelayedLoading)//TODO: not implemented 531 | { 532 | ofLogNotice("ofxPresetDataGrid") << "bDelayedLoading: " << bDelayedLoading; 533 | 534 | //byKey 535 | //newIndices[i] = k; 536 | //ofLogNotice("ofxPresetDataGrid") << "newIndices[i] = k;" << k << ", " << i; 537 | 538 | //byMousePressed 539 | //ofLogNotice("ofxPresetDataGrid") << "newIndices[yIndex] = xIndex:" << yIndex << " = " << xIndex; 540 | } 541 | 542 | else 543 | { 544 | //byKey 545 | // load( k, i ); 546 | // ofLogNotice("ofxPresetDataGrid") << "load( k, i ):" << k << ", " << i; 547 | 548 | //byMousePressed 549 | // load( xIndex, yIndex); 550 | // ofLogNotice("ofxPresetDataGrid") << "load( xIndex, yIndex):" << xIndex << ", " << yIndex; 551 | 552 | //- 553 | 554 | if (bAutoSave) 555 | { 556 | ofLogNotice("ofxPresetDataGrid") << "AUTO SAVE: " << e; 557 | doSave(PRESET_selected_PRE - 1); 558 | 559 | //DONE_save = true;//get sequencer state before saving in preset manager 560 | //save(lastIndices[PRESET_selected_PRE], 0);//save on back from ofxStepSequencerlistener 561 | } 562 | 563 | //- 564 | 565 | PRESET_selected_PRE = PRESET_selected; 566 | int xIndex = PRESET_selected - 1; 567 | int yIndex = 0; 568 | //this should handle when using multiple kits together 569 | //yIndex = ? 570 | 571 | //- 572 | 573 | if (bAutoLoad) 574 | { 575 | load(xIndex, yIndex); 576 | ofLogNotice("ofxPresetDataGrid") << "load( xIndex, yIndex): " << xIndex << ", " << yIndex; 577 | 578 | DONE_load = true;//TODO: to refresh in SEQ sequencer from grid.. 579 | } 580 | else 581 | { 582 | lastIndices[yIndex] = xIndex;//this is to move clicker selector 583 | ofLogNotice("ofxPresetDataGrid") << "lastIndices[yIndex]: " << xIndex; 584 | ofLogNotice("ofxPresetDataGrid") << "bAutoLoad: " << bAutoLoad; 585 | } 586 | } 587 | } 588 | } 589 | } 590 | 591 | //-- 592 | 593 | //GUI CONTROL PANEL 594 | 595 | //------------------------------------------------ 596 | void ofxPresetDataGrid::setup_Gui() 597 | { 598 | gui_w = 200; 599 | gui_slider_h = 16; 600 | gui_slider_big_h = 18; 601 | gui_button_h = 22; 602 | 603 | //- 604 | 605 | //container 606 | confCont = 607 | { 608 | //{"direction", "vertical"}, 609 | //{"width", gui_w}, 610 | //{"padding", 0}, 611 | //{"margin", 0}, 612 | }; 613 | 614 | //toggle 615 | confItem_toggle = 616 | { 617 | //{"height", gui_slider_h}, 618 | }; 619 | 620 | //sliders & button 621 | confItem = 622 | { 623 | //{"type", "fullsize"}, 624 | //{"height", gui_slider_h}, 625 | }; 626 | 627 | //big sliders 628 | confItem_Big = 629 | { 630 | //{"type", "fullsize"}, 631 | //{"height", gui_slider_big_h}, 632 | }; 633 | 634 | //big buttons 635 | confItem_Fat = 636 | { 637 | //{"type", "fullsize"}, 638 | //{"height", gui_button_h}, 639 | //{"text-align", "center"}, 640 | }; 641 | 642 | //- 643 | 644 | //customize panel name to class mode 645 | 646 | string name_Panel; 647 | name_Panel = "SEQ PATTERNS"; 648 | 649 | group = gui.addGroup(name_Panel);//, confCont); 650 | group->add(PRESET_selected);//, confItem_Big); 651 | group->add(bSave);//, confItem_toggle); 652 | group->add(bAutoLoad);//, confItem_toggle); 653 | group->add(bAutoSave);//, confItem_toggle); 654 | group->add(bCloneToRight);//, confItem_toggle); 655 | 656 | //- 657 | 658 | group->setPosition(600, 550); 659 | 660 | //TODO: 661 | group->loadTheme("theme/theme_bleurgh.json"); 662 | group->minimize(); 663 | } 664 | 665 | //------------------------------------------------ 666 | void ofxPresetDataGrid::set_GUI_position(int x, int y) 667 | { 668 | group->setPosition(x, y); 669 | } 670 | 671 | //------------------------------------------------ 672 | void ofxPresetDataGrid::setVisible_Gui(bool visible) 673 | { 674 | SHOW_Gui = visible; 675 | gui.getVisible().set(SHOW_Gui); 676 | } 677 | 678 | //------------------------------------------------ 679 | void ofxPresetDataGrid::setVisible_ClickerPanel(bool visible) 680 | { 681 | SHOW_ClickPanel = visible; 682 | } 683 | 684 | //------------------------------------------------ 685 | void ofxPresetDataGrid::load_ControlSettings() 686 | { 687 | ofXml settings; 688 | settings.load(path_Global + "/" + pathControl); 689 | ofDeserialize(settings, params); 690 | 691 | ofLogNotice("ofxPresetDataGrid") << "load_ControlSettings > PRESET_selected: " << PRESET_selected; 692 | } 693 | 694 | //------------------------------------------------ 695 | void ofxPresetDataGrid::save_ControlSettings() 696 | { 697 | ofXml settings; 698 | ofSerialize(settings, params); 699 | settings.save(path_Global + "/" + pathControl); 700 | } 701 | 702 | //------------------------------------------------ 703 | void ofxPresetDataGrid::set_pathKit_Folder(string folder) 704 | { 705 | pathKitFolder = folder; 706 | } 707 | 708 | //------------------------------------------------ 709 | void ofxPresetDataGrid::doCloneRight(int patternNum) 710 | { 711 | ofLogNotice("ofxPresetDataGrid") << "doCloneRight: patternNum: " << patternNum; 712 | for (int i = patternNum + 1; i < num_presets; i++) 713 | { 714 | save(i, 0);//only 1 row (gui) / data content 715 | } 716 | } 717 | 718 | //------------------------------------------------ 719 | void ofxPresetDataGrid::doSave(int patternNum) 720 | { 721 | ofLogNotice("ofxPresetDataGrid") << "doSave: patternNum: " << patternNum; 722 | save(patternNum, 0);//only 1 row (gui) / data content 723 | } 724 | -------------------------------------------------------------------------------- /src/ofxStepSequencer.cpp: -------------------------------------------------------------------------------- 1 | #include "ofxStepSequencer.h" 2 | 3 | //TODO: 4 | //adding variable grid size (notes & steps) feature 5 | 6 | //-------------------------------------------------------------- 7 | void ofxStepSequencer::setup(int _NUM_SEQ_BEATS, int _NUM_SEQ_NOTES) 8 | { 9 | ofSetLogLevel("ofxStepSequencer", OF_LOG_NOTICE); 10 | ofSetLogLevel("ofxSequencer", OF_LOG_NOTICE); 11 | 12 | //- 13 | 14 | #ifdef USE_OFXBEATCLOCK 15 | ENABLE_ofxBeatClock_MODE = true; 16 | #else 17 | ENABLE_ofxBeatClock_MODE = false; 18 | #endif 19 | 20 | //- 21 | 22 | //1. SEQUENCER CLASS 23 | 24 | //ofxSequencer object 25 | 26 | sequencer.setup(_NUM_SEQ_BEATS, BPM_INIT, BARS_INIT); 27 | 28 | //TODO: BUG: add step 0 29 | 30 | //-- 31 | 32 | //2. SEQ GRID 33 | 34 | TARGET_NOTES_paramsGroup.setName("sequencer TARGET_NOTES_params"); 35 | 36 | for (int row = 0; row < _NUM_SEQ_NOTES; row++) 37 | { 38 | //target vars 39 | TARGET_NOTES_params[row].set(ofToString(row), false); 40 | TARGET_NOTES_paramsGroup.add(TARGET_NOTES_params[row]); 41 | 42 | //- 43 | 44 | //grid sequencer 45 | sequencer.addRow(&TARGET_NOTES_params[row]); 46 | } 47 | 48 | //TODO: BUG: add step 0 49 | //sequencer.addRow(& TARGET_NOTES_params[NUM_SEQ_NOTES] ); 50 | 51 | //to trig from inside the class 52 | //ofAddListener(TARGET_NOTES_paramsGroup.parameterChangedE(), this, &ofxStepSequencer::Changed_SEQ_NOTES); 53 | 54 | //-- 55 | 56 | clear();//erase all grid vector and ofxSequencer data grid 57 | 58 | //- 59 | 60 | //default grid position and sizes (if setPosition not called..) 61 | 62 | seqH = 200; 63 | seqBoxSize = seqH / _NUM_SEQ_NOTES; 64 | seqW = seqBoxSize * _NUM_SEQ_BEATS; 65 | seqX = 550; 66 | seqY = 500; 67 | sequencer.setPosition(seqX, seqY, seqW, seqH); 68 | 69 | //- 70 | 71 | //GUI 72 | 73 | setup_gui(); 74 | 75 | //- 76 | 77 | //FBO IMPROVE DRAW PERFORMANCE 78 | 79 | //TODO: 80 | //do the draw on refresh only code.. 81 | useFbo = false; 82 | fbo.allocate(seqW, seqH); 83 | fbo.begin(); 84 | ofClear(0, 0); 85 | fbo.end(); 86 | //toRedraw = true; 87 | toRedraw = useFbo; 88 | 89 | //- 90 | 91 | //GRID NUMBERS FONT DRAW 92 | 93 | string f1; 94 | fontSize = 8; 95 | f1 = path_Global + "/fonts/telegrama_render.otf"; 96 | 97 | myFont.load(f1, fontSize, true, true); 98 | myFont.setLineHeight(fontSize); 99 | 100 | //- 101 | 102 | //DEBUG FONT 103 | 104 | string f2; 105 | ttfSize = 7; 106 | f2 = path_Global + "/fonts/telegrama_render.otf"; 107 | ttfType.load(f2, ttfSize, true, true); 108 | ttfType.setLineHeight(ttfSize); 109 | 110 | //-- 111 | 112 | //TODO: 113 | //GRID states auto save load 114 | if (ENABLE_autoSaveLoad) 115 | { 116 | string path_def = "SEQ_defaultPattern.json"; 117 | load_JSON(path_def); 118 | } 119 | 120 | //-- 121 | 122 | #ifdef USE_OFXBEATCLOCK 123 | 124 | //BPM CLOCKER 125 | 126 | beatClock.setup(); 127 | 128 | //- 129 | 130 | //DEFAULT POSITIONS 131 | //int squares_w = 200; 132 | //int ball_radius = 30; 133 | //int px = 5; 134 | //int py= 5; 135 | //setPosition_CLOCK_Gui( px, py, squares_w ) ; 136 | //setPosition_CLOCK_Squares( px, py + 605, squares_w); 137 | //setPosition_CLOCK_Ball(px + squares_w * 0.5 - ball_radius, py + 760, ball_radius); 138 | 139 | //- 140 | 141 | //get beat ticks events from outside the class 142 | beatClock.Beat_current.addListener(this, &ofxStepSequencer::Changed_BPM_beat_current); 143 | 144 | //check changes on beatClock bpm 145 | beatClock.BPM_Global.addListener(this, &ofxStepSequencer::Changed_BeatClock_BPM); 146 | 147 | #endif 148 | 149 | //-- 150 | 151 | //PRESET MANAGER 152 | 153 | //GUI 154 | 155 | presetsManager.setup_Gui(); 156 | presetsManager.set_pathKit_Folder("ofxStepSequencer/presets"); 157 | myDataGrid.setName("stepSequencer"); 158 | presetsManager.add(myDataGrid, { '1', '2', '3', '4', '5', '6', '7', '8' }); 159 | 160 | //- 161 | 162 | //TODO: easy listener temp solution to trig when save/load is done 163 | //then will load refresh grid sequencer states 164 | 165 | presetsManager.DONE_save.addListener(this, &ofxStepSequencer::Changed_DONE_save); 166 | presetsManager.DONE_load.addListener(this, &ofxStepSequencer::Changed_DONE_load); 167 | 168 | //- 169 | 170 | //STARTUP INIT 171 | 172 | presetsManager.load_ControlSettings();//this loads selected preset number and gui state 173 | 174 | //- 175 | 176 | //trick to solve auto load fail because the sorting of xml autoSave after preset selector tag 177 | presetsManager.PRESET_selected_PRE = -1; 178 | ofLogNotice("ofxStepSequencer") << "PRESET_selected:" << presetsManager.PRESET_selected; 179 | presetsManager.PRESET_selected = presetsManager.PRESET_selected; 180 | 181 | //--- 182 | 183 | //DEFAULT STARUP SETTINGS 184 | 185 | presetsManager.set_GUI_position(450, 450);//default 186 | presetsManager.setPosition_ClickerPanel(450, 550, 40);//default 187 | presetsManager.setVisible_ClickerPanel(true);//default 188 | presetsManager.setVisible_Gui(true);//default 189 | 190 | //presetsManager.setDelayedLoading(true); 191 | 192 | //-- 193 | 194 | //load settings 195 | ofXml settings; 196 | settings.load(path_Global + "/" + path_Settings); 197 | ofDeserialize(settings, params_Transport); 198 | 199 | //-- 200 | } 201 | 202 | //-------------------------------------------------------------- 203 | void ofxStepSequencer::setup() 204 | { 205 | setup((int)NUM_SEQ_BEATS, (int)NUM_SEQ_NOTES); 206 | } 207 | 208 | //--------------------------- 209 | void ofxStepSequencer::set_SHOW_Gui(bool state) 210 | { 211 | SHOW_Gui = state; 212 | gui_SEQ.getVisible().set(SHOW_Gui); 213 | 214 | presetsManager.setVisible_Gui(SHOW_Gui); 215 | 216 | //sequencer.setVisible(SHOW_Gui); 217 | } 218 | 219 | //--------------------------- 220 | void ofxStepSequencer::setup_gui() 221 | { 222 | //- 223 | 224 | //THEME 225 | 226 | ofJson confg_Sliders = 227 | { 228 | {"height", 40} 229 | }; 230 | ofJson confg_BigBut = 231 | { 232 | {"type", "fullsize"}, 233 | {"text-align", "center"}, 234 | {"height", 40}, 235 | }; 236 | //ofJson conf_Cont = 237 | //{ 238 | // //{"direction", "vertical"}, 239 | //}; 240 | //ofJson confg_Sliders = 241 | //{ 242 | // //{"show-header", false}, 243 | // //{"height", 18}, 244 | //}; 245 | 246 | //- 247 | 248 | //SEQUENCER CONTROLLER: 249 | 250 | //1. control 251 | 252 | params_HelperTools.setName("SEQ HELPER TOOLS"); 253 | params_HelperTools.add(random_trig.set("RANDOM NOTES", false)); 254 | params_HelperTools.add(noteFrom.set("FROM", 0, 0, NUM_SEQ_NOTES - 1)); 255 | params_HelperTools.add(numNotes.set("MAX AMOUNT", NUM_SEQ_NOTES, 1, NUM_SEQ_NOTES)); 256 | params_HelperTools.add(randomProb.set("PROB", 0.1f, 0, 10)); 257 | params_HelperTools.add(clone_trig.set("CLONE BARS", false)); 258 | params_HelperTools.add(clone_fromBar.set("FROM BAR", 1, 1, 4)); 259 | params_HelperTools.add(clear_trig.set("CLEAR ALL", false)); 260 | 261 | group_HelperTools = gui_SEQ.addGroup(params_HelperTools); 262 | 263 | //custom settings 264 | group_HelperTools->minimize(); 265 | //group_HelperTools->setConfig(conf_Cont); 266 | //(group_HelperTools->getIntSlider("FROM"))->setConfig(confg_Sliders); 267 | //(group_HelperTools->getIntSlider("MAX AMOUNT"))->setConfig(confg_Sliders); 268 | //(group_HelperTools->getFloatSlider("PROB"))->setConfig(confg_Sliders); 269 | (group_HelperTools->getFloatSlider("PROB"))->setPrecision(1); 270 | //(group_HelperTools->getIntSlider("FROM BAR"))->setConfig(confg_Sliders); 271 | 272 | //- 273 | 274 | //2. transport 275 | 276 | params_Transport.setName("ofxStepSequencer"); 277 | params_Transport.add(play_trig.set("PLAY", false)); 278 | params_Transport.add(bpm.set("BPM", 120.0f, 30.0f, 400.0f)); 279 | params_Transport.add(loopBar.set("LOOP BAR", false)); 280 | params_Transport.add(startBar.set("startBar", 1, 1, 4)); 281 | params_Transport.add(numBars.set("numBars", 4, 1, 4)); 282 | params_Transport.add(SHOW_Grid.set("SHOW GRID", true)); 283 | params_Transport.add(SHOW_beatClock.set("SHOW BEAT-CLOCK", true)); 284 | params_Transport.add(SHOW_presetsManager.set("SHOW PRESETS", true)); 285 | 286 | play_trig.setSerializable(false); 287 | 288 | //#ifdef USE_OFXSEQUENCER_TRANSPORT 289 | group_Transport = gui_SEQ.addGroup(params_Transport); 290 | //group_Transport->setConfig(conf_Cont);//disable custom individual settings.. 291 | (group_Transport->getToggle("PLAY"))->setConfig(confg_BigBut); 292 | (group_Transport->getFloatSlider("BPM"))->setPrecision(2); 293 | (group_Transport->getFloatSlider("BPM"))->setConfig(confg_Sliders); 294 | //#endif 295 | 296 | //- 297 | 298 | //default positions 299 | group_Transport->setPosition(ofPoint(400, 5)); 300 | group_HelperTools->setPosition(ofPoint(400, 600)); 301 | 302 | //- 303 | 304 | //custom theme 305 | group_Transport->loadTheme("theme/theme_bleurgh.json"); 306 | group_HelperTools->loadTheme("theme/theme_bleurgh.json"); 307 | 308 | //- 309 | 310 | //listeners 311 | 312 | ofAddListener(params_HelperTools.parameterChangedE(), this, &ofxStepSequencer::Changed_Params); 313 | ofAddListener(params_Transport.parameterChangedE(), this, &ofxStepSequencer::Changed_Params); 314 | 315 | //-- 316 | 317 | //set visible 318 | set_SHOW_Gui(SHOW_Gui);//by default 319 | } 320 | 321 | //------------------------------------ 322 | void ofxStepSequencer::update() 323 | { 324 | //ofxSequencer 325 | sequencer.update(); 326 | 327 | if (useFbo) 328 | toRedraw = true; 329 | 330 | //- 331 | 332 | #ifdef USE_OFXBEATCLOCK 333 | beatClock.update(); 334 | 335 | ////TODO: 336 | ////should use the beatClock play toggle and bpm params directly 337 | 338 | ////not working..it blocks clock 339 | ////workflow to link addons states 340 | //if (beatClock.getInternalClockMode()) 341 | // bpm = beatClock.get_BPM(); 342 | 343 | //if (beatClock.isPlaying()) 344 | //{ 345 | 346 | //} 347 | #endif 348 | 349 | 350 | } 351 | 352 | //-- 353 | 354 | //-------------------------------------- 355 | void ofxStepSequencer::setPosition_GridSequencer(int x, int y, int w, int h) 356 | { 357 | //sequencer grid 358 | 359 | //size could be defined with w or h. 360 | //pass one of them to 0 to get squares sizes 361 | 362 | //- 363 | 364 | seqX = x; 365 | seqY = y; 366 | 367 | if (w == 0) 368 | { 369 | seqH = h; 370 | seqBoxSize = seqH / NUM_SEQ_NOTES;//will be used to draw squares or number TARGET_NOTES_params 371 | seqW = seqBoxSize * NUM_SEQ_BEATS; 372 | } 373 | else if (h == 0) 374 | { 375 | seqW = w; 376 | seqBoxSize = seqW / NUM_SEQ_BEATS;//will be used to draw squares or number TARGET_NOTES_params 377 | seqH = seqBoxSize * NUM_SEQ_NOTES; 378 | } 379 | else 380 | { 381 | seqW = w; 382 | seqH = h; 383 | } 384 | 385 | //- 386 | 387 | sequencer.setPosition(seqX, seqY, seqW, seqH); 388 | 389 | //- 390 | 391 | if (useFbo) 392 | { 393 | fbo.allocate(seqW, seqH); 394 | fbo.begin(); 395 | ofClear(0, 0); 396 | fbo.end(); 397 | toRedraw = true; 398 | } 399 | 400 | //- 401 | } 402 | 403 | //-------------------------------------- 404 | void ofxStepSequencer::setPosition_Gui(int x, int y) 405 | { 406 | //sequencer gui 407 | group_Transport->setPosition(ofPoint(x, y)); 408 | float h = group_Transport->getHeight(); 409 | group_HelperTools->setPosition(ofPoint(x, y + h)); 410 | 411 | //#ifdef USE_OFXSEQUENCER_TRANSPORT 412 | // group_Transport->setPosition(ofPoint(x, y)); 413 | //#else 414 | // group_HelperTools->setPosition(ofPoint(x, y)); 415 | //#endif 416 | } 417 | 418 | #ifdef USE_OFXBEATCLOCK 419 | 420 | //-------------------------------------- 421 | void ofxStepSequencer::setPosition_BeatClock(int x, int y) 422 | { 423 | beatClock.setPosition_GuiGlobal(x, y); 424 | } 425 | 426 | //-------------------------------------- 427 | void ofxStepSequencer::setPosition_CLOCK_Gui(int x, int y, int w) 428 | { 429 | beatClock.setPosition_GuiPanel(x, y, w); 430 | } 431 | 432 | //-------------------------------------- 433 | void ofxStepSequencer::setPosition_CLOCK_Squares(int x, int y, int w) 434 | { 435 | beatClock.setPosition_BeatBoxes(x, y, w); 436 | } 437 | 438 | //-------------------------------------- 439 | void ofxStepSequencer::setPosition_CLOCK_Ball(int x, int y, int w) 440 | { 441 | beatClock.setPosition_BeatBall(x, y, w); 442 | } 443 | 444 | #endif 445 | 446 | //------------------------------------ 447 | void ofxStepSequencer::redraw() 448 | { 449 | //TODO: move all draw into ofxSequencer 450 | 451 | fbo.begin(); 452 | //ofClear(0, 0); 453 | 454 | //- 455 | 456 | //square border 457 | 458 | ofSetColor(ofColor::white); 459 | ofSetLineWidth(1); 460 | ofNoFill(); 461 | 462 | //ofDrawRectangle(-1, -1, seqWidth+1, seqHeigh+1); 463 | ofDrawRectangle(1, 1, seqW - 1, seqH - 1); 464 | 465 | //bar lines 466 | 467 | ofSetLineWidth(2);//vertical bar lines 468 | ofDrawLine(seqW / 4, 0, seqW / 4, seqH); 469 | ofDrawLine(seqW / 2, 0, seqW / 2, seqH); 470 | ofDrawLine(seqW * 3 / 4, 0, seqW * 3 / 4, seqH); 471 | 472 | //erase all bars 473 | 474 | ofSetColor(ofColor::black); 475 | ofFill(); 476 | ofDrawRectangle(0, 0, seqW, seqH); 477 | 478 | //fill selected bar 479 | 480 | int xBar, yBar, wBar, hBar; 481 | wBar = seqW / 4; 482 | xBar = wBar * (clone_fromBar - 1);//selected bar 483 | yBar = 0; 484 | hBar = seqH; 485 | 486 | ofColor c; 487 | c.set(ofColor::white); 488 | int alpha = 24; 489 | ofSetColor(c.r, c.g, c.b, alpha); 490 | ofFill(); 491 | ofDrawRectangle(xBar, yBar, wBar, hBar); 492 | 493 | //- 494 | 495 | //note numbers 496 | 497 | float row_h = seqH / (float)(NUM_SEQ_NOTES);//size h of any row line 498 | int padX = 0; 499 | int padY = 5; 500 | int charW = 23; 501 | int x, y; 502 | 503 | //note labels 504 | for (int i = 0; i < NUM_SEQ_NOTES; i++) 505 | { 506 | if (i < 9) 507 | padX = 7;//justify right 508 | else 509 | padX = 0; 510 | 511 | x = charW + padX; 512 | y = (i * row_h) + padY + row_h * 0.5; 513 | 514 | ofSetColor(ofColor::white); 515 | 516 | if (TARGET_NOTES_params[i] == true) 517 | { 518 | ofFill(); 519 | ofSetColor(ofColor::white); 520 | int pad = 0; 521 | if (i < 9) 522 | { 523 | pad = 8; 524 | } 525 | 526 | //square on active TARGET_NOTES_params 527 | ofDrawRectangle(x - 1 - pad, y - 11, 18, 12); 528 | ofNoFill(); 529 | ofSetColor(ofColor::black); 530 | } 531 | 532 | //text number TARGET_NOTES_params 533 | myFont.drawString(ofToString(i + 1), x, y); 534 | } 535 | 536 | //- 537 | 538 | fbo.end(); 539 | } 540 | 541 | //------------------------------------ 542 | void ofxStepSequencer::draw_CLOCK() 543 | { 544 | #ifdef USE_OFXBEATCLOCK 545 | beatClock.draw(); 546 | #endif 547 | } 548 | 549 | //------------------------------------ 550 | void ofxStepSequencer::draw()//draw sequencer grid 551 | { 552 | if (SHOW_Grid) 553 | { 554 | //-- 555 | 556 | ofPushStyle(); 557 | 558 | //- 559 | 560 | //sequencer grid 561 | 562 | sequencer.draw(); 563 | 564 | //- 565 | 566 | if (useFbo) 567 | { 568 | if (toRedraw) 569 | { 570 | redraw(); 571 | toRedraw = false; 572 | } 573 | 574 | fbo.draw(seqX, seqY, seqW, seqH); 575 | } 576 | 577 | else 578 | { 579 | //1. square border 580 | 581 | ofSetColor(ofColor::white); 582 | ofSetLineWidth(1); 583 | ofNoFill(); 584 | ofDrawRectangle(seqX - 1, seqY - 1, seqW + 1, seqH + 1); 585 | 586 | //- 587 | 588 | //2. the 3 bar vertical lines (between 4 bars dividers) 589 | 590 | ofSetLineWidth(2);//vertical bar lines 591 | ofDrawLine(seqX + seqW / 4, seqY, seqX + seqW / 4, seqY + seqH); 592 | ofDrawLine(seqX + seqW / 2, seqY, seqX + seqW / 2, seqY + seqH); 593 | ofDrawLine(seqX + seqW * 3 / 4, seqY, seqX + seqW * 3 / 4, seqY + seqH); 594 | 595 | //- 596 | 597 | //3.1 selected current player bar/position transparent rectangle 598 | 599 | int xBar, yBar, wBar, hBar; 600 | wBar = seqW / 4; 601 | xBar = seqX + wBar * (clone_fromBar - 1);//selected bar 602 | yBar = seqY; 603 | hBar = seqH; 604 | 605 | ofColor c; 606 | c.set(ofColor::white); 607 | int alpha = 24; 608 | ofSetColor(c.r, c.g, c.b, alpha); 609 | ofFill(); 610 | ofDrawRectangle(xBar, yBar, wBar, hBar); 611 | 612 | //- 613 | 614 | if (loopBar) 615 | { 616 | //3.2 make darken the bar out of the defined bar loop 617 | 618 | alpha = 192; 619 | int widthLoop; 620 | c.set(8); 621 | ofSetColor(c.r, c.g, c.b, alpha); 622 | 623 | //right rectangle 624 | xBar = seqX + wBar * (startBar - 1 + numBars);//from end 625 | //int limitBars = ; 626 | if (startBar + numBars <= 4) 627 | { 628 | widthLoop = wBar * (4 - (startBar - 1 + numBars)); 629 | ofDrawRectangle(xBar, yBar, widthLoop, hBar); 630 | } 631 | 632 | //left rectangle 633 | if (startBar > 1) 634 | { 635 | xBar = seqX;//first to start 636 | widthLoop = wBar * (startBar - 1); 637 | ofDrawRectangle(xBar, yBar, widthLoop, hBar); 638 | } 639 | } 640 | 641 | //- 642 | 643 | //4. margin note numbers 644 | 645 | float row_h = seqH / (float)(NUM_SEQ_NOTES);//size h of any row line 646 | int padX = 0; 647 | int padY = 5; 648 | int charW = 23; 649 | int x, y; 650 | 651 | for (int i = 0; i < NUM_SEQ_NOTES; i++) 652 | { 653 | if (i < 9) 654 | padX = 7;//justify right 655 | else 656 | padX = 0; 657 | 658 | x = seqX - charW + padX; 659 | y = seqY + (i * row_h) + padY + row_h * 0.5; 660 | 661 | ofSetColor(ofColor::white); 662 | 663 | if (TARGET_NOTES_params[i] == true) 664 | { 665 | ofFill(); 666 | ofSetColor(ofColor::white); 667 | int pad = 0; 668 | if (i < 9) 669 | { 670 | pad = 8; 671 | } 672 | 673 | //square on active TARGET_NOTES_params 674 | ofDrawRectangle(x - 1 - pad, y - 11, 18, 12); 675 | ofNoFill(); 676 | ofSetColor(ofColor::black); 677 | } 678 | 679 | //text number TARGET_NOTES_params 680 | myFont.drawString(ofToString(i + 1), x, y); 681 | } 682 | } 683 | 684 | //- 685 | 686 | ofPopStyle(); 687 | 688 | //--------------------------------------------------------// 689 | 690 | //DEBUG: 691 | 692 | if (DEBUG_state) 693 | { 694 | //text number TARGET_NOTES_params 695 | int linesH = 10; 696 | int maxLines = 6; 697 | int x = ofGetWidth() - 200; 698 | int y = ofGetHeight() - (linesH * maxLines); 699 | string myString; 700 | int numLine = 0; 701 | 702 | myString = "sequencer.column " + ofToString(sequencer.column); 703 | ttfType.drawString(myString, x, y + linesH * numLine++); 704 | 705 | myString = "sequencer.getColumn() " + ofToString(sequencer.getColumn()); 706 | ttfType.drawString(myString, x, y + linesH * numLine++); 707 | 708 | myString = "sequencer.cursor " + ofToString(sequencer.cursor); 709 | ttfType.drawString(myString, x, y + linesH * numLine++); 710 | 711 | myString = "sequencer.getBpm() " + ofToString(sequencer.getBpm()); 712 | ttfType.drawString(myString, x, y + linesH * numLine++); 713 | } 714 | } 715 | 716 | //--------------------------------------------------------// 717 | 718 | //TODO: could split this drawer whith his own function.. 719 | presetsManager.draw();//draw clicker panel 720 | 721 | //draw_CLOCK(); 722 | } 723 | 724 | //------------------------------------------------ 725 | void ofxStepSequencer::random(int noteFrom, int numNotes, float prob) 726 | { 727 | ofLogNotice("ofxStepSequencer") << "SEQ random:"; 728 | 729 | ////TODO: could add random merge without erase at first 730 | //clear();//erase all grid 731 | 732 | for (int n = noteFrom; n < (noteFrom + numNotes) && n < NUM_SEQ_NOTES; n++) 733 | { 734 | for (int b = 0; b < NUM_SEQ_BEATS; b++) 735 | { 736 | //1. SEQ GRID 737 | 738 | float myRandom = ofRandom(10); 739 | 740 | bool rndB = false; 741 | if (myRandom < randomProb) 742 | rndB = true; 743 | 744 | if (rndB) 745 | myDataGrid.grid[n][b] = 1; 746 | else 747 | myDataGrid.grid[n][b] = 0; 748 | 749 | //- 750 | 751 | //2. SEQUENCER CLASS 752 | 753 | //ofLogVerbose("ofxStepSequencer") << "note:" << n << " beat:" << b << " state:" << ( rndB ? "ON":"OFF" ); 754 | 755 | //set value to sequencer 756 | sequencer.setValue(n, b, rndB); 757 | 758 | //sequencer.set_GridFromSequencer();//TODO: added.. reduces performance.. 759 | //grid squares 760 | 761 | //- 762 | } 763 | } 764 | } 765 | 766 | //------------------------------------------------ 767 | void ofxStepSequencer::clear() 768 | { 769 | //erase all grid vector and ofxSequencer data grid 770 | 771 | ofLogNotice("ofxStepSequencer") << "clear:"; 772 | 773 | bool bState = false; 774 | 775 | for (int row = 0; row < NUM_SEQ_NOTES; row++) 776 | { 777 | for (int col = 0; col < NUM_SEQ_BEATS; col++) 778 | { 779 | //1. GRID SEQ 780 | 781 | myDataGrid.grid[row][col] = bState; 782 | 783 | //- 784 | 785 | //2. SEQUENCER CLASS 786 | 787 | sequencer.setValue(row, col, bState); 788 | //sequencer.set_GridFromSequencer();//TODO: added.. 789 | } 790 | } 791 | } 792 | 793 | //------------------------------------------------ 794 | void ofxStepSequencer::cloneFromBar(int selBar) 795 | { 796 | //-- 797 | 798 | //refresh states before cloning, just in case grid cells are modified by mouse clicks. 799 | 800 | //get values to GRID from sequencer class, like clicked cells, (not only from randomized or cloned by ofxStepSequencer, that they are alreay stored) 801 | 802 | GRID_getFrom_Sequencer(); 803 | 804 | //-- 805 | 806 | ofLogNotice("ofxStepSequencer") << "SEQ cloneFromBar: " << selBar; 807 | 808 | bool GRID_stepsBar[NUM_SEQ_NOTES][4];//fixed 4 steps per bar 809 | 810 | //- 811 | 812 | //1. prepare only selected states from selected bar (from all 12 TARGET_NOTES_params / 16 steps) 813 | 814 | for (int row = 0; row < NUM_SEQ_NOTES; row++) 815 | { 816 | ofLogVerbose("ofxStepSequencer") << " > BAR STEPS FROM NOTE " << row << ":"; 817 | ofLogVerbose("ofxStepSequencer") << " "; 818 | 819 | for (int col = 0; col < 4; col++) 820 | { 821 | int step_inBar = col + (selBar * 4); 822 | 823 | GRID_stepsBar[row][col] = myDataGrid.grid[row][step_inBar]; 824 | 825 | ofLogVerbose("ofxStepSequencer") << " " << GRID_stepsBar[row][col]; 826 | } 827 | ofLogVerbose("ofxStepSequencer") << endl; 828 | } 829 | 830 | //- 831 | 832 | //2. fill the other 3 bars with cloned steps from bar selected 833 | 834 | for (int n = 0; n < NUM_SEQ_NOTES; n++) 835 | { 836 | ofLogVerbose("ofxStepSequencer") << "FILL BAR STEPS FROM NOTE " << n << ":"; 837 | for (int b = 0; b < NUM_SEQ_BEATS; b++) 838 | { 839 | int numBar = b / 4; 840 | bool startsBar = (b % 4 == 0); 841 | 842 | //- 843 | 844 | if (numBar == selBar) 845 | { 846 | //do not touch selected origin bar 847 | ofLogVerbose("ofxStepSequencer") << " > step: " << b << " is selected bar. no touch"; 848 | } 849 | else 850 | { 851 | ofLogVerbose("ofxStepSequencer") << " > step: " << b << " is bar " << numBar 852 | << (startsBar ? (" and starts the bar " + ofToString(numBar)) : " "); 853 | 854 | int relative_Bar = b % 4; 855 | 856 | //fill grid squares: 857 | bool bState; 858 | bState = GRID_stepsBar[n][relative_Bar]; 859 | 860 | //- 861 | 862 | if (bState) 863 | myDataGrid.grid[n][b] = 1; 864 | else 865 | myDataGrid.grid[n][b] = 0; 866 | 867 | //TODO: should use a main method to modify both sequencer/gird on class 868 | sequencer.setValue(n, b, bState); 869 | //sequencer.set_GridFromSequencer();//TODO: added. outperforms 870 | } 871 | } 872 | } 873 | } 874 | 875 | //-------------------------------------------------------------- 876 | void ofxStepSequencer::Changed_Params(ofAbstractParameter &e) //patch change 877 | { 878 | if (!DISABLE_CALLBACKS) 879 | { 880 | string name = e.getName(); 881 | ofLogNotice("ofxStepSequencer") << "Changed_Params '" << name << "': " << e; 882 | 883 | if (name == "PLAY") 884 | { 885 | if (play_trig) 886 | setPlayState(true); 887 | else 888 | setPlayState(false); 889 | } 890 | else if (name == "RANDOM NOTES") 891 | { 892 | if (random_trig) 893 | { 894 | random_trig = false; 895 | random(noteFrom, numNotes, randomProb); 896 | } 897 | } 898 | else if (name == "PROB") 899 | { 900 | random(noteFrom, numNotes, randomProb); 901 | } 902 | else if (name == "FROM") 903 | { 904 | random(noteFrom, numNotes, randomProb); 905 | } 906 | else if (name == "MAX AMOUNT") 907 | { 908 | random(noteFrom, numNotes, randomProb); 909 | } 910 | else if (name == "CLEAR ALL") 911 | { 912 | if (clear_trig) 913 | { 914 | clear_trig = false; 915 | clear(); 916 | } 917 | } 918 | else if (name == "BPM") 919 | { 920 | #ifndef USE_OFXBEATCLOCK 921 | sequencer.setBpm(bpm); 922 | #else 923 | beatClock.setBpm_ClockInternal(bpm); 924 | #endif 925 | } 926 | 927 | #ifdef USE_OFXBEATCLOCK 928 | else if (name == "SHOW BEAT-CLOCK") 929 | { 930 | beatClock.setVisible_GuiPanel(SHOW_beatClock); 931 | beatClock.setVisible_BeatBall(SHOW_beatClock); 932 | } 933 | #endif 934 | else if (name == "CLONE BARS") 935 | { 936 | if (clone_trig) 937 | { 938 | cloneFromBar(clone_fromBar - 1);//to use 1-4 not 0 939 | clone_trig = false; 940 | } 941 | } 942 | else if (name == "FROM BAR") 943 | { 944 | //sequencer. 945 | } 946 | else if (name == "SHOW PRESETS") 947 | { 948 | presetsManager.setVisible_Gui(SHOW_presetsManager); 949 | presetsManager.setVisible_ClickerPanel(SHOW_presetsManager); 950 | } 951 | 952 | //- 953 | 954 | //variable bar duration 955 | else if (name == "startBar" && loopBar) 956 | { 957 | sequencer.reset(); 958 | sequencer.column = ((startBar - 1) * 4); 959 | //sequencer.setStartBar(startBar); 960 | } 961 | else if (name == "numBars" && loopBar) 962 | { 963 | //sequencer.setNumBarMode(numBars); 964 | } 965 | else if (name == "LOOP BAR") 966 | { 967 | if (!loopBar) 968 | { 969 | //sequencer.stop(); 970 | //sequencer.reset(); 971 | //resetClock(); 972 | } 973 | else 974 | { 975 | //sequencer.stop(); 976 | sequencer.column = ((startBar - 1) * 4) - 1;//-1 to avoid bug 977 | //resetClock(); 978 | } 979 | //sequencer.setLoopBarMode(loopBar); 980 | } 981 | 982 | } 983 | } 984 | 985 | //------------------------------------------------ 986 | void ofxStepSequencer::setPlayState(bool _state) 987 | { 988 | if (_state)//play 989 | { 990 | if (ENABLE_ofxBeatClock_MODE) 991 | { 992 | #ifdef USE_OFXBEATCLOCK 993 | ////force beatClock to ofxSeq user gui clock 994 | //if (beatClock.getInternalClockModeState()) 995 | //{ 996 | // beatClock.set_DAW_bpm(bpm.get()); 997 | //} 998 | 999 | //TODO: 1000 | if (loopBar) 1001 | { 1002 | //sequencer.reset(); 1003 | sequencer.column = ((startBar - 1) * 4) - 1;//-1 to avoid bug 1004 | } 1005 | 1006 | //sequencer.column = 0; 1007 | beatClock.start(); 1008 | #endif 1009 | } 1010 | else 1011 | { 1012 | //ofxSequencer clocker 1013 | sequencer.start(); 1014 | } 1015 | 1016 | isPlaying = true; 1017 | } 1018 | else if (!_state)//stop 1019 | { 1020 | if (ENABLE_ofxBeatClock_MODE) 1021 | { 1022 | 1023 | #ifdef USE_OFXBEATCLOCK 1024 | beatClock.stop(); 1025 | #endif 1026 | //- 1027 | 1028 | sequencer.stop(); 1029 | sequencer.reset(); 1030 | 1031 | //TODO: 1032 | if (loopBar) 1033 | { 1034 | //sequencer.reset(); 1035 | sequencer.column = ((startBar - 1) * 4) - 1;//-1 to avoid bug 1036 | } 1037 | //else 1038 | //{ 1039 | // sequencer.column = -1;//? 1040 | //} 1041 | ofLogNotice("ofxStepSequencer") << "sequencer.column = " << sequencer.column; 1042 | } 1043 | else 1044 | { 1045 | //ofxSequencer clocker 1046 | sequencer.stop(); 1047 | sequencer.reset(); 1048 | } 1049 | 1050 | isPlaying = false; 1051 | } 1052 | } 1053 | 1054 | //------------------------------------------------ 1055 | void ofxStepSequencer::randomize() 1056 | { 1057 | random(noteFrom, numNotes, randomProb); 1058 | } 1059 | 1060 | //------------------------------------------------ 1061 | bool ofxStepSequencer::getPlayState() 1062 | { 1063 | return play_trig.get(); 1064 | } 1065 | 1066 | //------------------------------------------------ 1067 | void ofxStepSequencer::togglePlayStop() 1068 | { 1069 | play_trig = !play_trig; 1070 | 1071 | //DISABLE_CALLBACKS = true; 1072 | //bool b = !play_trig.get(); 1073 | //DISABLE_CALLBACKS = false; 1074 | //play_trig = b; 1075 | } 1076 | 1077 | //------------------------------------------------ 1078 | void ofxStepSequencer::exit() 1079 | { 1080 | #ifdef USE_OFXBEATCLOCK 1081 | beatClock.exit(); 1082 | 1083 | //get beat ticks events from outside the class 1084 | beatClock.Beat_current.removeListener(this, &ofxStepSequencer::Changed_BPM_beat_current); 1085 | 1086 | //check changes on beatClock bpm 1087 | beatClock.BPM_Global.removeListener(this, &ofxStepSequencer::Changed_BeatClock_BPM); 1088 | #endif 1089 | 1090 | //- 1091 | 1092 | //remove listeners 1093 | 1094 | ofRemoveListener(params_HelperTools.parameterChangedE(), this, &ofxStepSequencer::Changed_Params); 1095 | ofRemoveListener(params_Transport.parameterChangedE(), this, &ofxStepSequencer::Changed_Params); 1096 | 1097 | //- 1098 | 1099 | //TODO: easy listener temp solution to trig when save/load is done 1100 | //then will load refresh grid sequencer states 1101 | 1102 | presetsManager.DONE_save.removeListener(this, &ofxStepSequencer::Changed_DONE_save); 1103 | presetsManager.DONE_load.removeListener(this, &ofxStepSequencer::Changed_DONE_load); 1104 | 1105 | //- 1106 | 1107 | //to trig from inside the class 1108 | //ofRemoveListener(TARGET_NOTES_paramsGroup.parameterChangedE(), this, &ofxStepSequencer::Changed_SEQ_NOTES); 1109 | 1110 | //-- 1111 | 1112 | if (ENABLE_autoSaveLoad) 1113 | { 1114 | save_JSON(path_def); 1115 | } 1116 | 1117 | //-- 1118 | 1119 | //save settings 1120 | ofXml settings; 1121 | ofSerialize(settings, params_Transport); 1122 | settings.save(path_Global + "/" + path_Settings); 1123 | } 1124 | 1125 | //------------------------------------------------ 1126 | void ofxStepSequencer::GRID_getFrom_Sequencer() 1127 | { 1128 | //TODO: should improve updating all sequencer class together (values params and grids) 1129 | 1130 | ofLogNotice("ofxStepSequencer") << "GRID_getFrom_Sequencer"; 1131 | 1132 | //-- 1133 | 1134 | //get values to local grid from sequencer class, 1135 | //like clicked cells, (not only from randomized or cloned by ofxStepSequencer, that they are alreay stored) 1136 | 1137 | //TODO: both are required? should be in other places too ? like when clicking cells.. 1138 | 1139 | //1 get sequencer grid from sequencer draw parameters (just in case) 1140 | //TODO: should improve mirroring both sequencer stored data (values/grid) 1141 | 1142 | sequencer.set_GridFromSequencer(); 1143 | 1144 | //- 1145 | 1146 | //2 put from sequencer grid into local grid 1147 | 1148 | //TODO: could be from sequence grid instead 1149 | 1150 | //for (int r = 0; r < NUM_SEQ_NOTES; r++) 1151 | for (int r = 0; r < sequencer.grid.size(); r++) 1152 | { 1153 | ofLogVerbose("ofxStepSequencer") << "--- NOTE " << r; 1154 | 1155 | for (int c = 0; c < sequencer.grid[r].size(); c++) 1156 | { 1157 | bool myVal; 1158 | 1159 | //- 1160 | 1161 | //TODO: dont know why must invert c <-> r 1162 | myVal = sequencer.grid[r][c]; 1163 | 1164 | //- 1165 | 1166 | ofLogVerbose("ofxStepSequencer") << "BEAT " << c << " : " << myVal; 1167 | 1168 | int myInt; 1169 | if (myVal == true) 1170 | { 1171 | myInt = 1; 1172 | } 1173 | else 1174 | { 1175 | myInt = 0; 1176 | } 1177 | 1178 | //- 1179 | 1180 | myDataGrid.grid[r][c] = myInt; 1181 | 1182 | //- 1183 | } 1184 | ofLogVerbose("ofxStepSequencer") << "----------------------------"; 1185 | } 1186 | } 1187 | 1188 | //------------------------------------------------ 1189 | void ofxStepSequencer::save_JSON(string path) 1190 | { 1191 | //-- 1192 | 1193 | //get values to GRID from sequencer class, like clicked cells, (not only from randomized or cloned by ofxStepSequencer, that they are alreay stored) 1194 | 1195 | GRID_getFrom_Sequencer(); 1196 | 1197 | //-- 1198 | 1199 | //save from GRID 1200 | 1201 | ofLogNotice("ofxStepSequencer") << "StepSEQ save_JSON"; 1202 | 1203 | JSON_grid_Row myRow; //note row 1204 | 1205 | ofJson json_ROW_Note_Steps; 1206 | ofJson json_GRID_Full_Rows_Steps; 1207 | 1208 | for (int note = 0; note < NUM_SEQ_NOTES; note++) 1209 | { 1210 | //create one json for each note: 1211 | 1212 | string name = "note_" + ofToString(note); 1213 | 1214 | for (int beatStep = 0; beatStep < NUM_SEQ_BEATS; beatStep++) 1215 | { 1216 | //store grid sequencer states to json's temp struct 1217 | 1218 | myRow.steps[beatStep] = myDataGrid.grid[note][beatStep]; 1219 | } 1220 | 1221 | json_ROW_Note_Steps = ofxJsonUtils::create(name, myRow.steps); 1222 | 1223 | ofLogVerbose("ofxStepSequencer") << "> DUMP: " + name + " " << json_ROW_Note_Steps.dump(); 1224 | 1225 | //- 1226 | 1227 | json_GRID_Full_Rows_Steps.push_back(json_ROW_Note_Steps); 1228 | //append note(s) json(s) to grid's json 1229 | } 1230 | 1231 | //- 1232 | 1233 | ofSavePrettyJson(path, json_GRID_Full_Rows_Steps); 1234 | 1235 | //- 1236 | } 1237 | 1238 | //------------------------------------------------ 1239 | void ofxStepSequencer::load_JSON(string path) 1240 | { 1241 | ofLogNotice("ofxStepSequencer") << "SEQ StepSEQ load_JSON"; 1242 | 1243 | ofJson js; 1244 | ofFile file(path); 1245 | if (file.exists()) 1246 | { 1247 | file >> js; 1248 | int n = 0; 1249 | 1250 | ofLogVerbose("ofxStepSequencer") << " > DUMP NOTE STEPS STATES"; 1251 | 1252 | for (auto &jsNote : js) 1253 | { 1254 | if (!jsNote.empty()) 1255 | { 1256 | string jTag = "note_" + ofToString(n); 1257 | 1258 | ofLogVerbose("ofxStepSequencer") << " > " + jTag + " " << jsNote.dump(); 1259 | 1260 | std::vector steps = jsNote[jTag]; 1261 | //load json array to vector 1262 | 1263 | int b = 0; 1264 | for (auto i : steps) 1265 | { 1266 | myDataGrid.grid[n][b] = i; 1267 | 1268 | b++; 1269 | } 1270 | 1271 | //- 1272 | 1273 | //debug: 1274 | 1275 | string debugLine; 1276 | for (int s = 0; s < NUM_SEQ_BEATS; s++) 1277 | { 1278 | debugLine += ofToString(myDataGrid.grid[n][s]) + " "; 1279 | } 1280 | ofLogVerbose("ofxStepSequencer") << " > GRID : " + debugLine; 1281 | 1282 | //- 1283 | 1284 | n++; 1285 | } 1286 | } 1287 | 1288 | //-- 1289 | 1290 | //load sequencer grid: 1291 | 1292 | //go through each grid square 1293 | for (int n = 0; n < NUM_SEQ_NOTES; n++) 1294 | { 1295 | for (int b = 0; b < NUM_SEQ_BEATS; b++) 1296 | { 1297 | //set value to sequencer grid square 1298 | sequencer.setValue(n, b, myDataGrid.grid[n][b]); 1299 | sequencer.set_GridFromSequencer();//TODO: added 1300 | } 1301 | } 1302 | } 1303 | } 1304 | 1305 | //------------------------------------------------ 1306 | void ofxStepSequencer::setGRID_square(int note, int beat, bool state) 1307 | { 1308 | //set value to ofxSequencer class 1309 | sequencer.setValue(note, beat, state); 1310 | 1311 | //TODO: should update sequencer grid together wuith an API 1312 | sequencer.set_GridFromSequencer(); 1313 | 1314 | //- 1315 | 1316 | //set to local ofxStepSequencer storage 1317 | 1318 | myDataGrid.grid[note][beat] = state; 1319 | 1320 | //- 1321 | } 1322 | 1323 | #ifdef USE_OFXBEATCLOCK 1324 | 1325 | //-------------------------------------------------------------- 1326 | void ofxStepSequencer::Changed_BeatClock_BPM(float & value) 1327 | { 1328 | ofLogVerbose("ofxStepSequencer") << "Changed_BeatClock_BPM: " << value; 1329 | 1330 | bpm = value; 1331 | } 1332 | 1333 | //-------------------------------------------------------------- 1334 | void ofxStepSequencer::Changed_BPM_beat_current(int &value) 1335 | { 1336 | ofLogVerbose("ofxStepSequencer") << "Changed_BPM_beat_current: " << value; 1337 | 1338 | if (ENABLE_ofxBeatClock_MODE) 1339 | { 1340 | //TODO: 1341 | //add variable pattern duration 1342 | //limited bar 1343 | int limit = ((startBar - 1) * 4) + (numBars * 4 - 1); 1344 | if (limit > 16) 1345 | limit = 15; 1346 | 1347 | if (sequencer.getColumn() >= limit && loopBar) 1348 | { 1349 | sequencer.column = (startBar - 1) * 4; 1350 | //sequencer.column = 0; 1351 | //sequencer.stop(); 1352 | //sequencer.start(); 1353 | } 1354 | else//still remains bars 1355 | { 1356 | sequencer.advance(); 1357 | } 1358 | } 1359 | } 1360 | 1361 | #endif 1362 | 1363 | //TODO: easy listener temp solution 1364 | //-------------------------------------------------------------- 1365 | void ofxStepSequencer::Changed_DONE_save(bool &DONE_save) 1366 | { 1367 | ofLogNotice("ofxStepSequencer") << "Changed_DONE_save: " << ofToString(DONE_save ? "TRUE" : "FALSE"); 1368 | 1369 | if (presetsManager.DONE_save) 1370 | { 1371 | presetsManager.DONE_save = false; 1372 | 1373 | GRID_getFrom_Sequencer();//get sequencer state before saving in preset manager 1374 | } 1375 | } 1376 | 1377 | //-------------------------------------------------------------- 1378 | void ofxStepSequencer::Changed_DONE_load(bool &DONE_load) 1379 | { 1380 | ofLogNotice("ofxStepSequencer") << "Changed_DONE_load: " << ofToString(DONE_load ? "TRUE" : "FALSE"); 1381 | 1382 | //load local grid into sequencer: 1383 | 1384 | if (presetsManager.DONE_load) 1385 | { 1386 | presetsManager.DONE_load = false; 1387 | 1388 | //- 1389 | 1390 | //1. put local grid to sequencer grid: 1391 | 1392 | // ofLogNotice("ofxStepSequencer") << "ofxSequencer size rows:" << sequencer.grid.size(); 1393 | for (int i = 0; i < sequencer.grid.size(); i++) 1394 | { 1395 | // ofLogNotice("ofxStepSequencer") << "ofxSequencer size cols:" << sequencer.grid[i].size() ; 1396 | for (int j = 0; j < sequencer.grid[i].size(); j++) 1397 | { 1398 | sequencer.grid[i][j] = (bool)myDataGrid.grid[i][j]; 1399 | } 1400 | } 1401 | 1402 | //- 1403 | 1404 | //2. refresh from sequencer grid to draw params 1405 | 1406 | sequencer.set_SequencerFromGrid(); 1407 | 1408 | //- 1409 | } 1410 | } 1411 | 1412 | //------------------------------------------------ 1413 | void ofxStepSequencer::set_GuiAll_Settings(ofJson js) 1414 | { 1415 | gui_SEQ.setConfig(js); 1416 | 1417 | #ifdef USE_OFXBEATCLOCK 1418 | //take care if USE_OFXBEATCLOCK is enabled inside class header.. 1419 | beatClock.gui.setConfig(js);//..then should not set this config 1420 | #endif 1421 | 1422 | presetsManager.gui.setConfig(js); 1423 | } 1424 | 1425 | //------------------------------------------------ 1426 | //to trig from inside the class 1427 | //void ofxStepSequencer::Changed_SEQ_NOTES(ofAbstractParameter& e) 1428 | //{ 1429 | // string name = e.getName(); 1430 | // ofLogVerbose("ofxStepSequencer") << "Changed_SEQ_NOTES " << name << ": " << e; 1431 | // 1432 | // int noteNum = ofToInt(name); 1433 | // bool state = false; 1434 | // 1435 | // if(e.type() == typeid(ofParameter).name()) 1436 | // { 1437 | // ofParameter p = e.cast(); 1438 | // state = p; 1439 | // ofLogNotice("ofxStepSequencer") << "Changed_SEQ_NOTES: " << name << (p ? " ON":" OFF"); 1440 | // 1441 | // //TARGET_NOTES_params [noteNum] = state; 1442 | // //pd.sendNoteOn(midiChan, noteFirst + noteNum, (int)state?127:0); 1443 | // } 1444 | //} 1445 | --------------------------------------------------------------------------------