aboutsummaryrefslogtreecommitdiffstats
path: root/src/clipboard.c
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-04-23 15:48:59 +0200
committerBad Diode <bd@badd10de.dev>2023-04-23 15:48:59 +0200
commitff6e784e7c5ebe223666c6c631305397ad358289 (patch)
tree0f87823d48366a6beb8d36d7eea5dc33663d7abd /src/clipboard.c
parentdeb9c48fbd3dc5854de4ae3a04dc999029c10ae0 (diff)
downloadstepper-ff6e784e7c5ebe223666c6c631305397ad358289.tar.gz
stepper-ff6e784e7c5ebe223666c6c631305397ad358289.zip
Start decoupling of rendering from update passes
Diffstat (limited to 'src/clipboard.c')
-rw-r--r--src/clipboard.c319
1 files changed, 319 insertions, 0 deletions
diff --git a/src/clipboard.c b/src/clipboard.c
new file mode 100644
index 0000000..7491d4b
--- /dev/null
+++ b/src/clipboard.c
@@ -0,0 +1,319 @@
1void clipboard_paste(void);
2void clipboard_copy(void);
3
4typedef enum ClipboardType {
5 CLIP_EMPTY,
6 CLIP_TRIG,
7 CLIP_PARAM_CH1,
8 CLIP_PARAM_CH2,
9 CLIP_PARAM_CH3,
10 CLIP_PARAM_CH4,
11 CLIP_PATTERN,
12 CLIP_CHANNEL,
13} ClipboardType;
14
15typedef struct Clipboard {
16 ClipboardType type;
17 u8 src_pat;
18 u8 src_chan;
19 u8 src_trig;
20} Clipboard;
21
22static Clipboard clipboard = {CLIP_EMPTY, 0, 0, 0};
23
24void
25clipboard_paste(void) {
26 Pattern *pat_dst = &patterns[pattern_selection_loc];
27 Pattern *pat_src = &patterns[clipboard.src_pat];
28
29 if (input_handler == handle_trigger_selection) {
30 if (clipboard.type == CLIP_TRIG) {
31 // Copy notes or parameters when applicable.
32 switch (clipboard.src_chan) {
33 case 0: {
34 switch (channel_selection_loc) {
35 case 0: {
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];
38 } break;
39 case 1: {
40 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 } break;
43 case 2: {
44 pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig];
45 } break;
46 case 3: {
47 pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig];
48 } break;
49 }
50 } break;
51 case 1: {
52 switch (channel_selection_loc) {
53 case 0: {
54 pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig];
55 pat_dst->ch1.params[trig_selection_loc].env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume;
56 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;
58 pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle;
59 } break;
60 case 1: {
61 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];
63 } break;
64 case 2: {
65 pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig];
66 } break;
67 case 3: {
68 pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig];
69 } break;
70 }
71 } break;
72 case 2: {
73 switch (channel_selection_loc) {
74 case 0: {
75 pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig];
76 } break;
77 case 1: {
78 pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig];
79 } break;
80 case 2: {
81 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];
83 } break;
84 case 3: {
85 pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig];
86 } break;
87 }
88 } break;
89 case 3: {
90 switch (channel_selection_loc) {
91 case 0: {
92 pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig];
93 } break;
94 case 1: {
95 pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig];
96 } break;
97 case 2: {
98 pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig];
99 } break;
100 case 3: {
101 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];
103 } break;
104 }
105 } break;
106 }
107 }
108 // Only paste the params for the respective trigger.
109 if (clipboard.type == CLIP_PARAM_CH1) {
110 switch (channel_selection_loc) {
111 case 0: {
112 pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig];
113 } break;
114 case 1: {
115 pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig];
116 } break;
117 }
118 }
119 if (clipboard.type == CLIP_PARAM_CH2) {
120 switch (channel_selection_loc) {
121 case 0: {
122 pat_dst->ch1.params[trig_selection_loc].env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume;
123 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;
125 pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle;
126 } break;
127 case 1: {
128 pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig];
129 } break;
130 }
131 }
132 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];
134 }
135 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];
137 }
138 draw_triggers();
139 draw_parameters();
140 } 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];
142 draw_parameters();
143 } 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;
145 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;
147 pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle;
148 draw_parameters();
149 } 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];
151 draw_parameters();
152 } 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];
154 draw_parameters();
155 } 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];
157 draw_parameters();
158 } 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];
160 draw_parameters();
161 } else if (input_handler == handle_channel_selection && clipboard.type == CLIP_CHANNEL) {
162 // Copy notes from a different channel OR notes and parameters
163 // from a different pattern.
164 if (clipboard.src_chan == channel_selection_loc) {
165 switch (clipboard.src_chan) {
166 case 0: { pat_dst->ch1 = pat_src->ch1; } break;
167 case 1: { pat_dst->ch2 = pat_src->ch2; } break;
168 case 2: { pat_dst->ch3 = pat_src->ch3; } break;
169 case 3: { pat_dst->ch4 = pat_src->ch4; } break;
170 }
171 } else {
172 switch (clipboard.src_chan) {
173 case 0: {
174 switch (channel_selection_loc) {
175 case 0: {
176 for (size_t i = 0; i < 16; i++) {
177 pat_dst->ch1.notes[i] = pat_src->ch1.notes[i];
178 }
179 } break;
180 case 1: {
181 for (size_t i = 0; i < 16; i++) {
182 pat_dst->ch2.notes[i] = pat_src->ch1.notes[i];
183 }
184 } break;
185 case 2: {
186 for (size_t i = 0; i < 16; i++) {
187 pat_dst->ch3.notes[i] = pat_src->ch1.notes[i];
188 }
189 } break;
190 case 3: {
191 for (size_t i = 0; i < 16; i++) {
192 pat_dst->ch4.notes[i] = pat_src->ch1.notes[i];
193 }
194 } break;
195 }
196 } break;
197 case 1: {
198 switch (channel_selection_loc) {
199 case 0: {
200 for (size_t i = 0; i < 16; i++) {
201 pat_dst->ch1.notes[i] = pat_src->ch2.notes[i];
202 }
203 } break;
204 case 1: {
205 for (size_t i = 0; i < 16; i++) {
206 pat_dst->ch2.notes[i] = pat_src->ch2.notes[i];
207 }
208 } break;
209 case 2: {
210 for (size_t i = 0; i < 16; i++) {
211 pat_dst->ch3.notes[i] = pat_src->ch2.notes[i];
212 }
213 } break;
214 case 3: {
215 for (size_t i = 0; i < 16; i++) {
216 pat_dst->ch4.notes[i] = pat_src->ch2.notes[i];
217 }
218 } break;
219 }
220 } break;
221 case 2: {
222 switch (channel_selection_loc) {
223 case 0: {
224 for (size_t i = 0; i < 16; i++) {
225 pat_dst->ch1.notes[i] = pat_src->ch3.notes[i];
226 }
227 } break;
228 case 1: {
229 for (size_t i = 0; i < 16; i++) {
230 pat_dst->ch2.notes[i] = pat_src->ch3.notes[i];
231 }
232 } break;
233 case 2: {
234 for (size_t i = 0; i < 16; i++) {
235 pat_dst->ch3.notes[i] = pat_src->ch3.notes[i];
236 }
237 } break;
238 case 3: {
239 for (size_t i = 0; i < 16; i++) {
240 pat_dst->ch4.notes[i] = pat_src->ch3.notes[i];
241 }
242 } break;
243 }
244 } break;
245 case 3: {
246 switch (channel_selection_loc) {
247 case 0: {
248 for (size_t i = 0; i < 16; i++) {
249 pat_dst->ch1.notes[i] = pat_src->ch4.notes[i];
250 }
251 } break;
252 case 1: {
253 for (size_t i = 0; i < 16; i++) {
254 pat_dst->ch2.notes[i] = pat_src->ch4.notes[i];
255 }
256 } break;
257 case 2: {
258 for (size_t i = 0; i < 16; i++) {
259 pat_dst->ch3.notes[i] = pat_src->ch4.notes[i];
260 }
261 } break;
262 case 3: {
263 for (size_t i = 0; i < 16; i++) {
264 pat_dst->ch4.notes[i] = pat_src->ch4.notes[i];
265 }
266 } break;
267 }
268 } break;
269 }
270 }
271 draw_channels();
272 draw_triggers();
273 } else if (input_handler == handle_pattern_selection && clipboard.type == CLIP_PATTERN) {
274 // Copy an entire pattern.
275 if (pattern_selection_loc != clipboard.src_pat) {
276 *pat_dst = *pat_src;
277 draw_channels();
278 draw_triggers();
279 }
280 }
281}
282
283void
284clipboard_copy(void) {
285 if (input_handler == handle_trigger_selection) {
286 clipboard.type = CLIP_TRIG;
287 clipboard.src_pat = pattern_selection_loc;
288 clipboard.src_chan = channel_selection_loc;
289 clipboard.src_trig = trig_selection_loc;
290 } else if (input_handler == handle_param_selection_sq1) {
291 clipboard.type = CLIP_PARAM_CH1;
292 clipboard.src_pat = pattern_selection_loc;
293 clipboard.src_chan = channel_selection_loc;
294 clipboard.src_trig = trig_selection_loc;
295 } else if (input_handler == handle_param_selection_sq2) {
296 clipboard.type = CLIP_PARAM_CH2;
297 clipboard.src_pat = pattern_selection_loc;
298 clipboard.src_chan = channel_selection_loc;
299 clipboard.src_trig = trig_selection_loc;
300 } else if (input_handler == handle_param_selection_wave) {
301 clipboard.type = CLIP_PARAM_CH3;
302 clipboard.src_pat = pattern_selection_loc;
303 clipboard.src_chan = channel_selection_loc;
304 clipboard.src_trig = trig_selection_loc;
305 } else if (input_handler == handle_param_selection_noise) {
306 clipboard.type = CLIP_PARAM_CH4;
307 clipboard.src_pat = pattern_selection_loc;
308 clipboard.src_chan = channel_selection_loc;
309 clipboard.src_trig = trig_selection_loc;
310 } else if (input_handler == handle_channel_selection) {
311 clipboard.type = CLIP_CHANNEL;
312 clipboard.src_pat = pattern_selection_loc;
313 clipboard.src_chan = channel_selection_loc;
314 } else if (input_handler == handle_pattern_selection) {
315 clipboard.type = CLIP_PATTERN;
316 clipboard.src_pat = pattern_selection_loc;
317 }
318}
319