Support for dual APC40s
[SugarCubes.git] / _Presets.pde
CommitLineData
e0794d3a
MS
1interface PresetListener {
2 public void onPresetLoaded(Preset preset);
3 public void onPresetDirty(Preset preset);
4 public void onPresetStored(Preset preset);
1f974cbc 5 public void onPresetUnloaded();
e0794d3a
MS
6}
7
c1d777c9 8class PresetManager implements LXParameter.Listener {
e0794d3a
MS
9
10 public static final int NUM_PRESETS = 8;
11 public static final String FILENAME = "data/presets.txt";
12 public static final String DELIMITER = "\t";
13
14 private final Preset[] presets = new Preset[NUM_PRESETS];
15 private final List<PresetListener> listeners = new ArrayList<PresetListener>();
16
c1d777c9
MS
17 private Preset loadedPreset = null;
18 private LXPattern loadedPattern = null;
e0794d3a
MS
19
20 PresetManager() {
21 for (int i = 0; i < presets.length; ++i) {
22 presets[i] = new Preset(this, i);
23 }
24 String[] values = loadStrings(FILENAME);
25 if (values == null) {
26 write();
27 } else {
28 int i = 0;
29 for (String serialized : values) {
30 presets[i++].load(serialized);
31 if (i >= NUM_PRESETS) {
32 break;
33 }
34 }
35 }
1f974cbc
MS
36 for (Engine.Deck deck : lx.engine.getDecks()) {
37 deck.addListener(new Engine.AbstractListener() {
38 public void patternDidChange(Engine.Deck deck, LXPattern pattern) {
39 if (midiEngine.getFocusedDeck() == deck) {
40 if (pattern != loadedPattern) {
41 onPresetDirty();
42 }
43 }
44 }
45 });
46 }
47 }
48
49 public void setMidiEngine(MidiEngine midiEngine) {
50 midiEngine.addListener(new MidiEngineListener() {
51 public void onFocusedDeck(int deckIndex) {
52 loadedPreset = null;
53 for (PresetListener listener : listeners) {
54 listener.onPresetUnloaded();
55 }
56 }
57 });
e0794d3a
MS
58 }
59
60 public void addListener(PresetListener listener) {
61 listeners.add(listener);
62 }
63
a1396b9e
MS
64 public void dirty(LXPattern pattern) {
65 if (loadedPattern == pattern) {
66 onPresetDirty();
67 }
68 }
69
e0794d3a
MS
70 public void select(int index) {
71 presets[index].select();
72 }
73
74 public void store(int index) {
75 presets[index].store(midiEngine.getFocusedPattern());
1f974cbc
MS
76 for (PresetListener listener : listeners) {
77 listener.onPresetStored(presets[index]);
78 }
c1d777c9 79 select(index);
e0794d3a
MS
80 }
81
82 public void onPresetLoaded(Preset preset, LXPattern pattern) {
c1d777c9
MS
83 if (loadedPattern != pattern) {
84 if (loadedPattern != null) {
85 for (LXParameter p : loadedPattern.getParameters()) {
86 ((LXListenableParameter) p).removeListener(this);
87 }
88 }
89 }
e0794d3a
MS
90 for (PresetListener listener : listeners) {
91 listener.onPresetLoaded(preset);
c1d777c9
MS
92 }
93 loadedPreset = preset;
94 loadedPattern = pattern;
95 for (LXParameter p : loadedPattern.getParameters()) {
96 ((LXListenableParameter) p).addListener(this);
97 }
98 }
99
1f974cbc 100 private void onPresetDirty() {
66067e53
MS
101 if (loadedPreset != null) {
102 for (PresetListener listener : listeners) {
103 listener.onPresetDirty(loadedPreset);
104 }
e0794d3a
MS
105 }
106 }
107
1f974cbc
MS
108 public void onParameterChanged(LXParameter p) {
109 onPresetDirty();
110 }
111
e0794d3a
MS
112 public void write() {
113 String[] lines = new String[NUM_PRESETS];
114 int i = 0;
115 for (Preset preset : presets) {
116 lines[i++] = preset.serialize();
117 }
118 saveStrings(FILENAME, lines);
119 }
120}
121
122class Preset {
123
124 final PresetManager manager;
125 final int index;
126
127 String className;
128 final Map<String, Float> parameters = new HashMap<String, Float>();
129
130 Preset(PresetManager manager, int index) {
131 this.manager = manager;
132 this.index = index;
133 }
134
135 public void load(String serialized) {
136 className = null;
137 parameters.clear();
138 try {
139 String[] parts = serialized.split(PresetManager.DELIMITER);
140 className = parts[0];
141 int i = 1;
142 while (i < parts.length - 1) {
143 parameters.put(parts[i], Float.parseFloat(parts[i+1]));
144 i += 2;
145 }
146 } catch (Exception x) {
147 className = null;
148 parameters.clear();
149 }
150 }
151
152 public String serialize() {
153 if (className == null) {
154 return "null";
155 }
156 String val = className + PresetManager.DELIMITER;
157 for (String pKey : parameters.keySet()) {
158 val += pKey + PresetManager.DELIMITER + parameters.get(pKey) + PresetManager.DELIMITER;
159 }
160 return val;
161 }
162
163 public void store(LXPattern pattern) {
164 className = null;
165 parameters.clear();
166 className = pattern.getClass().getName();
167 for (LXParameter p : pattern.getParameters()) {
168 parameters.put(p.getLabel(), p.getValuef());
169 }
a1396b9e
MS
170 if (pattern instanceof DPat) {
171 DPat dpattern = (DPat) pattern;
172 for (DBool bool : dpattern.bools) {
173 parameters.put(bool.tag, bool.b ? 1.f : 0.f);
174 }
175 for (Pick pick : dpattern.picks) {
176 parameters.put(pick.tag, pick.CurRow + pick.CurCol/100.f);
177 }
178 }
e0794d3a
MS
179 manager.write();
180 }
181
182 public void select() {
183 Engine.Deck deck = midiEngine.getFocusedDeck();
184 for (LXPattern pattern : deck.getPatterns()) {
185 if (pattern.getClass().getName().equals(className)) {
186 for (String pLabel : parameters.keySet()) {
187 for (LXParameter p : pattern.getParameters()) {
188 if (p.getLabel().equals(pLabel)) {
189 p.setValue(parameters.get(pLabel));
190 }
191 }
a1396b9e
MS
192 if (pattern instanceof DPat) {
193 DPat dpattern = (DPat) pattern;
194 for (DBool bool : dpattern.bools) {
195 if (bool.tag.equals(pLabel)) {
196 bool.set(bool.row, bool.col, parameters.get(pLabel) > 0);
197 }
198 }
199 for (Pick pick : dpattern.picks) {
200 if (pick.tag.equals(pLabel)) {
201 float f = parameters.get(pLabel);
202 pick.set((int) floor(f), (int) round((f%1)*100.));
203 }
204 }
205 }
e0794d3a
MS
206 }
207 deck.goPattern(pattern);
a1396b9e
MS
208 if (pattern instanceof DPat) {
209 ((DPat)pattern).updateLights();
210 }
e0794d3a
MS
211 manager.onPresetLoaded(this, pattern);
212 break;
213 }
214 }
215 }
216}
217