aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-07-12 18:24:46 +0200
committerBad Diode <bd@badd10de.dev>2023-07-12 18:24:46 +0200
commit20b1b448b7a1c8e22cb2e0f2d6294533f7a220af (patch)
treee9a6c30530ec6d222e778d83f6f6bca49d0ca378
parentd2be261b88753c3e0fdeb7588057aa3f1648ead5 (diff)
downloadstepper-20b1b448b7a1c8e22cb2e0f2d6294533f7a220af.tar.gz
stepper-20b1b448b7a1c8e22cb2e0f2d6294533f7a220af.zip
Add a notification system and use it for save/copy/paste events
-rw-r--r--src/clipboard.c61
-rw-r--r--src/drawing.c26
-rw-r--r--src/globals.c11
-rw-r--r--src/main.c6
-rw-r--r--src/sequencer.c25
5 files changed, 127 insertions, 2 deletions
diff --git a/src/clipboard.c b/src/clipboard.c
index eba28ae..edb9b31 100644
--- a/src/clipboard.c
+++ b/src/clipboard.c
@@ -35,16 +35,20 @@ clipboard_paste(void) {
35 case 0: { 35 case 0: {
36 pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; 36 pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig];
37 pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; 37 pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig];
38 send_notif("PASTED NOTE & PARAMS");
38 } break; 39 } break;
39 case 1: { 40 case 1: {
40 pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; 41 pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig];
41 pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; 42 pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig];
43 send_notif("PASTED NOTE & PARAMS");
42 } break; 44 } break;
43 case 2: { 45 case 2: {
44 pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; 46 pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig];
47 send_notif("PASTED NOTE");
45 } break; 48 } break;
46 case 3: { 49 case 3: {
47 pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; 50 pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig];
51 send_notif("PASTED NOTE");
48 } break; 52 } break;
49 } 53 }
50 } break; 54 } break;
@@ -56,16 +60,20 @@ clipboard_paste(void) {
56 pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; 60 pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time;
57 pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; 61 pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction;
58 pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; 62 pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle;
63 send_notif("PASTED NOTE & PARAMS");
59 } break; 64 } break;
60 case 1: { 65 case 1: {
61 pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; 66 pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig];
62 pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; 67 pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig];
68 send_notif("PASTED NOTE & PARAMS");
63 } break; 69 } break;
64 case 2: { 70 case 2: {
65 pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; 71 pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig];
72 send_notif("PASTED NOTE");
66 } break; 73 } break;
67 case 3: { 74 case 3: {
68 pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; 75 pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig];
76 send_notif("PASTED NOTE");
69 } break; 77 } break;
70 } 78 }
71 } break; 79 } break;
@@ -73,16 +81,20 @@ clipboard_paste(void) {
73 switch (channel_selection_loc) { 81 switch (channel_selection_loc) {
74 case 0: { 82 case 0: {
75 pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; 83 pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig];
84 send_notif("PASTED NOTE");
76 } break; 85 } break;
77 case 1: { 86 case 1: {
78 pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; 87 pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig];
88 send_notif("PASTED NOTE");
79 } break; 89 } break;
80 case 2: { 90 case 2: {
81 pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; 91 pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig];
82 pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; 92 pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig];
93 send_notif("PASTED NOTE & PARAMS");
83 } break; 94 } break;
84 case 3: { 95 case 3: {
85 pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; 96 pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig];
97 send_notif("PASTED NOTE");
86 } break; 98 } break;
87 } 99 }
88 } break; 100 } break;
@@ -90,16 +102,20 @@ clipboard_paste(void) {
90 switch (channel_selection_loc) { 102 switch (channel_selection_loc) {
91 case 0: { 103 case 0: {
92 pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; 104 pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig];
105 send_notif("PASTED NOTE");
93 } break; 106 } break;
94 case 1: { 107 case 1: {
95 pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; 108 pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig];
109 send_notif("PASTED NOTE");
96 } break; 110 } break;
97 case 2: { 111 case 2: {
98 pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; 112 pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig];
113 send_notif("PASTED NOTE");
99 } break; 114 } break;
100 case 3: { 115 case 3: {
101 pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; 116 pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig];
102 pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig]; 117 pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig];
118 send_notif("PASTED NOTE & PARAMS");
103 } break; 119 } break;
104 } 120 }
105 } break; 121 } break;
@@ -110,9 +126,11 @@ clipboard_paste(void) {
110 switch (channel_selection_loc) { 126 switch (channel_selection_loc) {
111 case 0: { 127 case 0: {
112 pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; 128 pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig];
129 send_notif("PASTED PARAMS");
113 } break; 130 } break;
114 case 1: { 131 case 1: {
115 pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; 132 pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig];
133 send_notif("PASTED PARAMS");
116 } break; 134 } break;
117 } 135 }
118 } 136 }
@@ -123,40 +141,50 @@ clipboard_paste(void) {
123 pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; 141 pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time;
124 pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; 142 pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction;
125 pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; 143 pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle;
144 send_notif("PASTED PARAMS");
126 } break; 145 } break;
127 case 1: { 146 case 1: {
128 pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; 147 pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig];
148 send_notif("PASTED PARAMS");
129 } break; 149 } break;
130 } 150 }
131 } 151 }
132 if (clipboard.type == CLIP_PARAM_CH3 && channel_selection_loc == clipboard.src_chan) { 152 if (clipboard.type == CLIP_PARAM_CH3 && channel_selection_loc == clipboard.src_chan) {
133 pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; 153 pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig];
154 send_notif("PASTED PARAMS");
134 } 155 }
135 if (clipboard.type == CLIP_PARAM_CH4 && channel_selection_loc == clipboard.src_chan) { 156 if (clipboard.type == CLIP_PARAM_CH4 && channel_selection_loc == clipboard.src_chan) {
136 pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig]; 157 pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig];
158 send_notif("PASTED PARAMS");
137 } 159 }
138 draw_triggers(); 160 draw_triggers();
139 draw_parameters(); 161 draw_parameters();
140 } else if (input_handler == handle_param_selection_sq1 && clipboard.type == CLIP_PARAM_CH1) { 162 } else if (input_handler == handle_param_selection_sq1 && clipboard.type == CLIP_PARAM_CH1) {
141 pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; 163 pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig];
164 send_notif("PASTED PARAMS");
142 draw_parameters(); 165 draw_parameters();
143 } else if (input_handler == handle_param_selection_sq1 && clipboard.type == CLIP_PARAM_CH2) { 166 } else if (input_handler == handle_param_selection_sq1 && clipboard.type == CLIP_PARAM_CH2) {
144 pat_dst->ch1.params[trig_selection_loc].env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume; 167 pat_dst->ch1.params[trig_selection_loc].env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume;
145 pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; 168 pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time;
146 pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; 169 pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction;
147 pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; 170 pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle;
171 send_notif("PASTED PARAMS");
148 draw_parameters(); 172 draw_parameters();
149 } else if (input_handler == handle_param_selection_sq2 && clipboard.type == CLIP_PARAM_CH2) { 173 } else if (input_handler == handle_param_selection_sq2 && clipboard.type == CLIP_PARAM_CH2) {
150 pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; 174 pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig];
175 send_notif("PASTED PARAMS");
151 draw_parameters(); 176 draw_parameters();
152 } else if (input_handler == handle_param_selection_sq2 && clipboard.type == CLIP_PARAM_CH1) { 177 } else if (input_handler == handle_param_selection_sq2 && clipboard.type == CLIP_PARAM_CH1) {
153 pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; 178 pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig];
179 send_notif("PASTED PARAMS");
154 draw_parameters(); 180 draw_parameters();
155 } else if (input_handler == handle_param_selection_wave && clipboard.type == CLIP_PARAM_CH3) { 181 } else if (input_handler == handle_param_selection_wave && clipboard.type == CLIP_PARAM_CH3) {
156 pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; 182 pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig];
183 send_notif("PASTED PARAMS");
157 draw_parameters(); 184 draw_parameters();
158 } else if (input_handler == handle_param_selection_noise && clipboard.type == CLIP_PARAM_CH4) { 185 } else if (input_handler == handle_param_selection_noise && clipboard.type == CLIP_PARAM_CH4) {
159 pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig]; 186 pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig];
187 send_notif("PASTED PARAMS");
160 draw_parameters(); 188 draw_parameters();
161 } else if (input_handler == handle_channel_selection && clipboard.type == CLIP_CHANNEL) { 189 } else if (input_handler == handle_channel_selection && clipboard.type == CLIP_CHANNEL) {
162 // Copy notes from a different channel OR notes and parameters 190 // Copy notes from a different channel OR notes and parameters
@@ -168,6 +196,7 @@ clipboard_paste(void) {
168 case 2: { pat_dst->ch3 = pat_src->ch3; } break; 196 case 2: { pat_dst->ch3 = pat_src->ch3; } break;
169 case 3: { pat_dst->ch4 = pat_src->ch4; } break; 197 case 3: { pat_dst->ch4 = pat_src->ch4; } break;
170 } 198 }
199 send_notif("PASTED NOTES & PARAMS");
171 } else { 200 } else {
172 switch (clipboard.src_chan) { 201 switch (clipboard.src_chan) {
173 case 0: { 202 case 0: {
@@ -177,22 +206,26 @@ clipboard_paste(void) {
177 pat_dst->ch1.notes[i] = pat_src->ch1.notes[i]; 206 pat_dst->ch1.notes[i] = pat_src->ch1.notes[i];
178 pat_dst->ch1.params[i] = pat_src->ch1.params[i]; 207 pat_dst->ch1.params[i] = pat_src->ch1.params[i];
179 } 208 }
209 send_notif("PASTED NOTES & PARAMS");
180 } break; 210 } break;
181 case 1: { 211 case 1: {
182 for (size_t i = 0; i < 16; i++) { 212 for (size_t i = 0; i < 16; i++) {
183 pat_dst->ch2.notes[i] = pat_src->ch1.notes[i]; 213 pat_dst->ch2.notes[i] = pat_src->ch1.notes[i];
184 pat_dst->ch2.params[i] = pat_src->ch1.params[i]; 214 pat_dst->ch2.params[i] = pat_src->ch1.params[i];
185 } 215 }
216 send_notif("PASTED NOTES & PARAMS");
186 } break; 217 } break;
187 case 2: { 218 case 2: {
188 for (size_t i = 0; i < 16; i++) { 219 for (size_t i = 0; i < 16; i++) {
189 pat_dst->ch3.notes[i] = pat_src->ch1.notes[i]; 220 pat_dst->ch3.notes[i] = pat_src->ch1.notes[i];
190 } 221 }
222 send_notif("PASTED NOTES");
191 } break; 223 } break;
192 case 3: { 224 case 3: {
193 for (size_t i = 0; i < 16; i++) { 225 for (size_t i = 0; i < 16; i++) {
194 pat_dst->ch4.notes[i] = pat_src->ch1.notes[i]; 226 pat_dst->ch4.notes[i] = pat_src->ch1.notes[i];
195 } 227 }
228 send_notif("PASTED NOTES");
196 } break; 229 } break;
197 } 230 }
198 } break; 231 } break;
@@ -206,22 +239,26 @@ clipboard_paste(void) {
206 pat_dst->ch1.params[i].env_direction = pat_src->ch2.params[i].env_direction; 239 pat_dst->ch1.params[i].env_direction = pat_src->ch2.params[i].env_direction;
207 pat_dst->ch1.params[i].duty_cycle = pat_src->ch2.params[i].duty_cycle; 240 pat_dst->ch1.params[i].duty_cycle = pat_src->ch2.params[i].duty_cycle;
208 } 241 }
242 send_notif("PASTED NOTES & PARAMS");
209 } break; 243 } break;
210 case 1: { 244 case 1: {
211 for (size_t i = 0; i < 16; i++) { 245 for (size_t i = 0; i < 16; i++) {
212 pat_dst->ch2.notes[i] = pat_src->ch2.notes[i]; 246 pat_dst->ch2.notes[i] = pat_src->ch2.notes[i];
213 pat_dst->ch2.params[i] = pat_src->ch2.params[i]; 247 pat_dst->ch2.params[i] = pat_src->ch2.params[i];
214 } 248 }
249 send_notif("PASTED NOTES & PARAMS");
215 } break; 250 } break;
216 case 2: { 251 case 2: {
217 for (size_t i = 0; i < 16; i++) { 252 for (size_t i = 0; i < 16; i++) {
218 pat_dst->ch3.notes[i] = pat_src->ch2.notes[i]; 253 pat_dst->ch3.notes[i] = pat_src->ch2.notes[i];
219 } 254 }
255 send_notif("PASTED NOTES");
220 } break; 256 } break;
221 case 3: { 257 case 3: {
222 for (size_t i = 0; i < 16; i++) { 258 for (size_t i = 0; i < 16; i++) {
223 pat_dst->ch4.notes[i] = pat_src->ch2.notes[i]; 259 pat_dst->ch4.notes[i] = pat_src->ch2.notes[i];
224 } 260 }
261 send_notif("PASTED NOTES");
225 } break; 262 } break;
226 } 263 }
227 } break; 264 } break;
@@ -231,22 +268,26 @@ clipboard_paste(void) {
231 for (size_t i = 0; i < 16; i++) { 268 for (size_t i = 0; i < 16; i++) {
232 pat_dst->ch1.notes[i] = pat_src->ch3.notes[i]; 269 pat_dst->ch1.notes[i] = pat_src->ch3.notes[i];
233 } 270 }
271 send_notif("PASTED NOTES");
234 } break; 272 } break;
235 case 1: { 273 case 1: {
236 for (size_t i = 0; i < 16; i++) { 274 for (size_t i = 0; i < 16; i++) {
237 pat_dst->ch2.notes[i] = pat_src->ch3.notes[i]; 275 pat_dst->ch2.notes[i] = pat_src->ch3.notes[i];
238 } 276 }
277 send_notif("PASTED NOTES");
239 } break; 278 } break;
240 case 2: { 279 case 2: {
241 for (size_t i = 0; i < 16; i++) { 280 for (size_t i = 0; i < 16; i++) {
242 pat_dst->ch3.notes[i] = pat_src->ch3.notes[i]; 281 pat_dst->ch3.notes[i] = pat_src->ch3.notes[i];
243 pat_dst->ch3.params[i] = pat_src->ch3.params[i]; 282 pat_dst->ch3.params[i] = pat_src->ch3.params[i];
244 } 283 }
284 send_notif("PASTED NOTES & PARAMS");
245 } break; 285 } break;
246 case 3: { 286 case 3: {
247 for (size_t i = 0; i < 16; i++) { 287 for (size_t i = 0; i < 16; i++) {
248 pat_dst->ch4.notes[i] = pat_src->ch3.notes[i]; 288 pat_dst->ch4.notes[i] = pat_src->ch3.notes[i];
249 } 289 }
290 send_notif("PASTED NOTES");
250 } break; 291 } break;
251 } 292 }
252 } break; 293 } break;
@@ -256,22 +297,26 @@ clipboard_paste(void) {
256 for (size_t i = 0; i < 16; i++) { 297 for (size_t i = 0; i < 16; i++) {
257 pat_dst->ch1.notes[i] = pat_src->ch4.notes[i]; 298 pat_dst->ch1.notes[i] = pat_src->ch4.notes[i];
258 } 299 }
300 send_notif("PASTED NOTES");
259 } break; 301 } break;
260 case 1: { 302 case 1: {
261 for (size_t i = 0; i < 16; i++) { 303 for (size_t i = 0; i < 16; i++) {
262 pat_dst->ch2.notes[i] = pat_src->ch4.notes[i]; 304 pat_dst->ch2.notes[i] = pat_src->ch4.notes[i];
263 } 305 }
306 send_notif("PASTED NOTES");
264 } break; 307 } break;
265 case 2: { 308 case 2: {
266 for (size_t i = 0; i < 16; i++) { 309 for (size_t i = 0; i < 16; i++) {
267 pat_dst->ch3.notes[i] = pat_src->ch4.notes[i]; 310 pat_dst->ch3.notes[i] = pat_src->ch4.notes[i];
268 } 311 }
312 send_notif("PASTED NOTES");
269 } break; 313 } break;
270 case 3: { 314 case 3: {
271 for (size_t i = 0; i < 16; i++) { 315 for (size_t i = 0; i < 16; i++) {
272 pat_dst->ch4.notes[i] = pat_src->ch4.notes[i]; 316 pat_dst->ch4.notes[i] = pat_src->ch4.notes[i];
273 pat_dst->ch4.params[i] = pat_src->ch4.params[i]; 317 pat_dst->ch4.params[i] = pat_src->ch4.params[i];
274 } 318 }
319 send_notif("PASTED NOTES & PARAMS");
275 } break; 320 } break;
276 } 321 }
277 } break; 322 } break;
@@ -290,6 +335,7 @@ clipboard_paste(void) {
290 for (size_t i = 0; i < 16; i++) { 335 for (size_t i = 0; i < 16; i++) {
291 pat_dst->ch1.params[i] = pat_src->ch1.params[clipboard.src_trig]; 336 pat_dst->ch1.params[i] = pat_src->ch1.params[clipboard.src_trig];
292 } 337 }
338 send_notif("PASTED PARAMS");
293 } 339 }
294 if (clipboard.src_chan == 1) { 340 if (clipboard.src_chan == 1) {
295 ch1_params.env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume; 341 ch1_params.env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume;
@@ -302,6 +348,7 @@ clipboard_paste(void) {
302 pat_dst->ch1.params[i].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; 348 pat_dst->ch1.params[i].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction;
303 pat_dst->ch1.params[i].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; 349 pat_dst->ch1.params[i].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle;
304 } 350 }
351 send_notif("PASTED PARAMS");
305 } 352 }
306 } 353 }
307 } break; 354 } break;
@@ -314,12 +361,14 @@ clipboard_paste(void) {
314 for (size_t i = 0; i < 16; i++) { 361 for (size_t i = 0; i < 16; i++) {
315 pat_dst->ch2.params[i] = pat_src->ch1.params[clipboard.src_trig]; 362 pat_dst->ch2.params[i] = pat_src->ch1.params[clipboard.src_trig];
316 } 363 }
364 send_notif("PASTED PARAMS");
317 } 365 }
318 if (clipboard.src_chan == 1) { 366 if (clipboard.src_chan == 1) {
319 ch2_params = pat_src->ch2.params[clipboard.src_trig]; 367 ch2_params = pat_src->ch2.params[clipboard.src_trig];
320 for (size_t i = 0; i < 16; i++) { 368 for (size_t i = 0; i < 16; i++) {
321 pat_dst->ch2.params[i] = pat_src->ch2.params[clipboard.src_trig]; 369 pat_dst->ch2.params[i] = pat_src->ch2.params[clipboard.src_trig];
322 } 370 }
371 send_notif("PASTED PARAMS");
323 } 372 }
324 } 373 }
325 } break; 374 } break;
@@ -332,6 +381,7 @@ clipboard_paste(void) {
332 for (size_t i = 0; i < 16; i++) { 381 for (size_t i = 0; i < 16; i++) {
333 pat_dst->ch3.params[i] = pat_src->ch3.params[clipboard.src_trig]; 382 pat_dst->ch3.params[i] = pat_src->ch3.params[clipboard.src_trig];
334 } 383 }
384 send_notif("PASTED PARAMS");
335 } 385 }
336 } break; 386 } break;
337 case 3: { 387 case 3: {
@@ -343,6 +393,7 @@ clipboard_paste(void) {
343 for (size_t i = 0; i < 16; i++) { 393 for (size_t i = 0; i < 16; i++) {
344 pat_dst->ch4.params[i] = pat_src->ch4.params[clipboard.src_trig]; 394 pat_dst->ch4.params[i] = pat_src->ch4.params[clipboard.src_trig];
345 } 395 }
396 send_notif("PASTED PARAMS");
346 } 397 }
347 } break; 398 } break;
348 } 399 }
@@ -352,10 +403,13 @@ clipboard_paste(void) {
352 *pat_dst = *pat_src; 403 *pat_dst = *pat_src;
353 draw_channels(); 404 draw_channels();
354 draw_triggers(); 405 draw_triggers();
406 send_notif("PASTED PATTERN");
355 } 407 }
356 } 408 }
357} 409}
358 410
411void send_notif(char *msg);
412
359void 413void
360clipboard_copy(void) { 414clipboard_copy(void) {
361 if (input_handler == handle_trigger_selection) { 415 if (input_handler == handle_trigger_selection) {
@@ -363,33 +417,40 @@ clipboard_copy(void) {
363 clipboard.src_pat = pattern_selection_loc; 417 clipboard.src_pat = pattern_selection_loc;
364 clipboard.src_chan = channel_selection_loc; 418 clipboard.src_chan = channel_selection_loc;
365 clipboard.src_trig = trig_selection_loc; 419 clipboard.src_trig = trig_selection_loc;
420 send_notif("COPIED TRIGGER");
366 } else if (input_handler == handle_param_selection_sq1) { 421 } else if (input_handler == handle_param_selection_sq1) {
367 clipboard.type = CLIP_PARAM_CH1; 422 clipboard.type = CLIP_PARAM_CH1;
368 clipboard.src_pat = pattern_selection_loc; 423 clipboard.src_pat = pattern_selection_loc;
369 clipboard.src_chan = channel_selection_loc; 424 clipboard.src_chan = channel_selection_loc;
370 clipboard.src_trig = trig_selection_loc; 425 clipboard.src_trig = trig_selection_loc;
426 send_notif("COPIED CH1 PARAMS");
371 } else if (input_handler == handle_param_selection_sq2) { 427 } else if (input_handler == handle_param_selection_sq2) {
372 clipboard.type = CLIP_PARAM_CH2; 428 clipboard.type = CLIP_PARAM_CH2;
373 clipboard.src_pat = pattern_selection_loc; 429 clipboard.src_pat = pattern_selection_loc;
374 clipboard.src_chan = channel_selection_loc; 430 clipboard.src_chan = channel_selection_loc;
375 clipboard.src_trig = trig_selection_loc; 431 clipboard.src_trig = trig_selection_loc;
432 send_notif("COPIED CH2 PARAMS");
376 } else if (input_handler == handle_param_selection_wave) { 433 } else if (input_handler == handle_param_selection_wave) {
377 clipboard.type = CLIP_PARAM_CH3; 434 clipboard.type = CLIP_PARAM_CH3;
378 clipboard.src_pat = pattern_selection_loc; 435 clipboard.src_pat = pattern_selection_loc;
379 clipboard.src_chan = channel_selection_loc; 436 clipboard.src_chan = channel_selection_loc;
380 clipboard.src_trig = trig_selection_loc; 437 clipboard.src_trig = trig_selection_loc;
438 send_notif("COPIED CH3 PARAMS");
381 } else if (input_handler == handle_param_selection_noise) { 439 } else if (input_handler == handle_param_selection_noise) {
382 clipboard.type = CLIP_PARAM_CH4; 440 clipboard.type = CLIP_PARAM_CH4;
383 clipboard.src_pat = pattern_selection_loc; 441 clipboard.src_pat = pattern_selection_loc;
384 clipboard.src_chan = channel_selection_loc; 442 clipboard.src_chan = channel_selection_loc;
385 clipboard.src_trig = trig_selection_loc; 443 clipboard.src_trig = trig_selection_loc;
444 send_notif("COPIED CH4 PARAMS");
386 } else if (input_handler == handle_channel_selection) { 445 } else if (input_handler == handle_channel_selection) {
387 clipboard.type = CLIP_CHANNEL; 446 clipboard.type = CLIP_CHANNEL;
388 clipboard.src_pat = pattern_selection_loc; 447 clipboard.src_pat = pattern_selection_loc;
389 clipboard.src_chan = channel_selection_loc; 448 clipboard.src_chan = channel_selection_loc;
449 send_notif("COPIED CHANNEL");
390 } else if (input_handler == handle_pattern_selection) { 450 } else if (input_handler == handle_pattern_selection) {
391 clipboard.type = CLIP_PATTERN; 451 clipboard.type = CLIP_PATTERN;
392 clipboard.src_pat = pattern_selection_loc; 452 clipboard.src_pat = pattern_selection_loc;
453 send_notif("COPIED PATTERN");
393 } 454 }
394} 455}
395 456
diff --git a/src/drawing.c b/src/drawing.c
index 3e00e17..b488ed1 100644
--- a/src/drawing.c
+++ b/src/drawing.c
@@ -1246,6 +1246,30 @@ draw_notif_bar() {
1246 u8 x1 = PARAMS_START_X + PARAMS_W; 1246 u8 x1 = PARAMS_START_X + PARAMS_W;
1247 u8 y1 = y0 + 10; 1247 u8 y1 = y0 + 10;
1248 u8 color = COL_FG; 1248 u8 color = COL_FG;
1249 draw_filled_rect(x0, y0, x1, y1, COL_BG);
1249 draw_rect(x0, y0, x1, y1, color); 1250 draw_rect(x0, y0, x1, y1, color);
1250 txt_drawf_small("HELLO WORLD!", x0 + 2, y0 + 1, color); 1251 if (notif.time > 0) {
1252 char msg[32] = {0};
1253 if (notif.time <= 32) {
1254 for (size_t i = 0; i < notif.time; i++) {
1255 msg[i] = notif.msg[i + 32 - notif.time];
1256 }
1257 } else {
1258 for (size_t i = 0; i < 32; i++) {
1259 msg[i] = notif.msg[i];
1260 }
1261 }
1262 txt_drawf_small(msg, x0 + 2, y0 + 1, color);
1263 } else {
1264 // if (notif.time > -16) {
1265 // notif.time--;
1266 // return;
1267 // }
1268 // TODO: More context dependent messages? Use instructions?
1269 if (play_status == 0) {
1270 txt_drawf_small("STOPPED", x0 + 2, y0 + 1, color);
1271 } else {
1272 txt_drawf_small("PLAYING", x0 + 2, y0 + 1, color);
1273 }
1274 }
1251} 1275}
diff --git a/src/globals.c b/src/globals.c
index 2f4d32d..c2e2ee2 100644
--- a/src/globals.c
+++ b/src/globals.c
@@ -120,3 +120,14 @@ typedef enum Scene {
120 120
121static Scene scene = SCENE_SEQUENCER; 121static Scene scene = SCENE_SEQUENCER;
122static Scene next_scene = SCENE_SEQUENCER; 122static Scene next_scene = SCENE_SEQUENCER;
123
124typedef struct Notification {
125 // We can only fit 31 characters on the notification bar at the moment.
126 // Leaving an extra character for \0.
127 char msg[32];
128 s16 time;
129} Notification;
130
131static Notification notif = {0};
132
133#define NOTIF_TIME (80 + 32)
diff --git a/src/main.c b/src/main.c
index 5c7d6ed..2e78b3c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -13,7 +13,7 @@ WITH REGARD TO THIS SOFTWARE.
13// 13//
14// UI tweaks. 14// UI tweaks.
15// - Add custom user themes 15// - Add custom user themes
16// - Notification support for feedback when doing some operations 16// + Notification support for feedback when doing some operations
17// (copying/pasting) 17// (copying/pasting)
18// - Animations for cursor movement/current step highlight. (A fade out maybe?) 18// - Animations for cursor movement/current step highlight. (A fade out maybe?)
19// - Add panning support. 19// - Add panning support.
@@ -28,6 +28,7 @@ WITH REGARD TO THIS SOFTWARE.
28// - Loop? 28// - Loop?
29// - Undo/Redo. 29// - Undo/Redo.
30// - Select + up/down to queue the next pattern as we move to it? 30// - Select + up/down to queue the next pattern as we move to it?
31// - Option to show help on the notification bar?
31// 32//
32// Advanced 33// Advanced
33// - Add tap tempo for BPM. 34// - Add tap tempo for BPM.
@@ -172,6 +173,9 @@ update(void) {
172 if (audio_sync_click) { 173 if (audio_sync_click) {
173 play_click(); 174 play_click();
174 } 175 }
176 if (notif.time > 0) {
177 notif.time--;
178 }
175} 179}
176 180
177int 181int
diff --git a/src/sequencer.c b/src/sequencer.c
index 5120805..a22c219 100644
--- a/src/sequencer.c
+++ b/src/sequencer.c
@@ -999,11 +999,36 @@ handle_trigger_selection(void) {
999} 999}
1000 1000
1001void 1001void
1002send_notif(char *msg) {
1003 if (msg == NULL) {
1004 return;
1005 }
1006
1007 char buf[32] = {0};
1008 size_t n_chars = 0;
1009 for (size_t i = 0; i < 32; i++) {
1010 if (*msg == '\0') {
1011 break;
1012 }
1013 buf[i] = *msg++;
1014 n_chars++;
1015 }
1016 if (n_chars == 0) {
1017 return;
1018 }
1019 notif.time = NOTIF_TIME;
1020 for (size_t i = 0; i < 32; i++) {
1021 notif.msg[i] = buf[i];
1022 }
1023}
1024
1025void
1002handle_sequencer_input(void) { 1026handle_sequencer_input(void) {
1003 if (key_tap(KEY_START)) { 1027 if (key_tap(KEY_START)) {
1004 if (key_hold(KEY_SELECT)) { 1028 if (key_hold(KEY_SELECT)) {
1005 save_bank(current_bank); 1029 save_bank(current_bank);
1006 save_metadata(); 1030 save_metadata();
1031 send_notif("SAVED BANK");
1007 return; 1032 return;
1008 } 1033 }
1009 // Stop the sequencer or start playing from the beginning. 1034 // Stop the sequencer or start playing from the beginning.