├── 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 | 
11 |
12 |
13 |
14 | ## Screenshots
15 |
16 | 
17 | 
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 |
--------------------------------------------------------------------------------