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