1 /*
2 * Schism Tracker - a cross-platform Impulse Tracker clone
3 * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4 * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5 * copyright (c) 2009 Storlek & Mrs. Brisby
6 * copyright (c) 2010-2012 Storlek
7 * URL: http://schismtracker.org/
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 /* This is getting almost as disturbing as the pattern editor. */
25
26 #include "headers.h"
27 #include "it.h"
28 #include "page.h"
29 #include "song.h"
30 #include "dmoz.h"
31 #include "video.h"
32
33 #include <sys/stat.h>
34
35 /* --------------------------------------------------------------------- */
36 /* just one global variable... */
37
38 int instrument_list_subpage = PAGE_INSTRUMENT_LIST_GENERAL;
39
40 /* --------------------------------------------------------------------- */
41 /* ... but tons o' ugly statics */
42
43 static struct widget widgets_general[18];
44 static struct widget widgets_volume[17];
45 static struct widget widgets_panning[19];
46 static struct widget widgets_pitch[20];
47
48 /* rastops for envelope */
49 static struct vgamem_overlay env_overlay = {
50 32, 18, 65, 25,
51 NULL, 0, 0, 0
52 };
53
54 /* toggled when pressing "," on the note table's sample field
55 * more of a boolean than a bit mask -delt.
56 */
57 static int note_sample_mask = 1;
58
get_page_widgets(void)59 static struct widget *get_page_widgets(void)
60 {
61 switch (instrument_list_subpage) {
62 case PAGE_INSTRUMENT_LIST_GENERAL:
63 return widgets_general;
64 case PAGE_INSTRUMENT_LIST_VOLUME:
65 return widgets_volume;
66 case PAGE_INSTRUMENT_LIST_PANNING:
67 return widgets_panning;
68 case PAGE_INSTRUMENT_LIST_PITCH:
69 return widgets_pitch;
70 };
71 return widgets_general;
72 }
73
74 static const int subpage_switches_group[5] = { 1, 2, 3, 4, -1 };
75 static const int nna_group[5] = { 6, 7, 8, 9, -1 };
76 static const int dct_group[5] = { 10, 11, 12, 13, -1 };
77 static const int dca_group[4] = { 14, 15, 16, -1 };
78
79 static const char *const pitch_envelope_states[] = { "Off", "On Pitch", "On Filter", NULL };
80
81 static int top_instrument = 1;
82 static int current_instrument = 1;
83 static int _altswap_lastvis = 99; // for alt-down instrument-swapping
84 static int instrument_cursor_pos = 25; /* "play" mode */
85
86 static int note_trans_top_line = 0;
87 static int note_trans_sel_line = 0;
88
89 static int note_trans_cursor_pos = 0;
90
91 /* shared by all the numentries on a page
92 * (0 = volume, 1 = panning, 2 = pitch) */
93 static int numentry_cursor_pos[3] = { 0 };
94
95 static int current_node_vol = 0;
96 static int current_node_pan = 0;
97 static int current_node_pitch = 0;
98
99 static int envelope_edit_mode = 0;
100 static int envelope_mouse_edit = 0;
101 static int envelope_tick_limit = 0;
102
103 static void set_subpage(int page);
104
105 /* playback */
106 static int last_note = 61; /* C-5 */
107
108 /* strange saved envelopes */
109 static song_envelope_t saved_env[10];
110 static unsigned int flags[10] = {0};
111
112 /* --------------------------------------------------------------------------------------------------------- */
113
save_envelope(int slot,song_envelope_t * e,unsigned int sec)114 static void save_envelope(int slot, song_envelope_t *e, unsigned int sec)
115 {
116 song_instrument_t *ins;
117
118 slot = ((unsigned)slot)%10;
119
120 ins = song_get_instrument(current_instrument);
121 memcpy(&saved_env[slot], e, sizeof(song_envelope_t));
122
123 switch (sec) {
124 case ENV_VOLUME:
125 flags[slot] = ins->flags & (ENV_VOLUME|ENV_VOLSUSTAIN|ENV_VOLLOOP|ENV_VOLCARRY);
126 break;
127 case ENV_PANNING:
128 flags[slot] =
129 ((ins->flags & ENV_PANNING) ? ENV_VOLUME : 0)
130 | ((ins->flags & ENV_PANSUSTAIN) ? ENV_VOLSUSTAIN : 0)
131 | ((ins->flags & ENV_PANLOOP) ? ENV_VOLLOOP : 0)
132 | ((ins->flags & ENV_PANCARRY) ? ENV_VOLCARRY : 0)
133 | (ins->flags & ENV_SETPANNING);
134 break;
135 case ENV_PITCH:
136 flags[slot] =
137 ((ins->flags & ENV_PITCH) ? ENV_VOLUME : 0)
138 | ((ins->flags & ENV_PITCHSUSTAIN) ? ENV_VOLSUSTAIN : 0)
139 | ((ins->flags & ENV_PITCHLOOP) ? ENV_VOLLOOP : 0)
140 | ((ins->flags & ENV_PITCHCARRY) ? ENV_VOLCARRY : 0)
141 | (ins->flags & ENV_FILTER);
142 break;
143 };
144 }
restore_envelope(int slot,song_envelope_t * e,unsigned int sec)145 static void restore_envelope(int slot, song_envelope_t *e, unsigned int sec)
146 {
147 song_instrument_t *ins;
148
149 song_lock_audio();
150
151 slot = ((unsigned)slot)%10;
152
153 ins = song_get_instrument(current_instrument);
154 memcpy(e, &saved_env[slot], sizeof(song_envelope_t));
155
156 switch (sec) {
157 case ENV_VOLUME:
158 ins->flags &= ~(ENV_VOLUME|ENV_VOLSUSTAIN|ENV_VOLLOOP|ENV_VOLCARRY);
159 ins->flags |= (flags[slot] & (ENV_VOLUME|ENV_VOLSUSTAIN|ENV_VOLLOOP|ENV_VOLCARRY));
160 break;
161
162 case ENV_PANNING:
163 ins->flags &= ~(ENV_PANNING|ENV_PANSUSTAIN|ENV_PANLOOP|ENV_PANCARRY|ENV_SETPANNING);
164 if (flags[slot] & ENV_VOLUME) ins->flags |= ENV_PANNING;
165 if (flags[slot] & ENV_VOLSUSTAIN) ins->flags |= ENV_PANSUSTAIN;
166 if (flags[slot] & ENV_VOLLOOP) ins->flags |= ENV_PANLOOP;
167 if (flags[slot] & ENV_VOLCARRY) ins->flags |= ENV_PANCARRY;
168 ins->flags |= (flags[slot] & ENV_SETPANNING);
169 break;
170
171 case ENV_PITCH:
172 ins->flags &= ~(ENV_PITCH|ENV_PITCHSUSTAIN|ENV_PITCHLOOP|ENV_PITCHCARRY|ENV_FILTER);
173 if (flags[slot] & ENV_VOLUME) ins->flags |= ENV_PITCH;
174 if (flags[slot] & ENV_VOLSUSTAIN) ins->flags |= ENV_PITCHSUSTAIN;
175 if (flags[slot] & ENV_VOLLOOP) ins->flags |= ENV_PITCHLOOP;
176 if (flags[slot] & ENV_VOLCARRY) ins->flags |= ENV_PITCHCARRY;
177 ins->flags |= (flags[slot] & ENV_FILTER);
178 break;
179
180 };
181
182 song_unlock_audio();
183
184 status.flags |= SONG_NEEDS_SAVE;
185 }
186
187
188
189 /* --------------------------------------------------------------------------------------------------------- */
190
191 static void instrument_list_draw_list(void);
192
193 /* --------------------------------------------------------------------------------------------------------- */
_last_vis_inst(void)194 static int _last_vis_inst(void)
195 {
196 int i, j, n;
197
198 n = 99;
199 j = 0;
200 /* 65 is first visible sample on last page */
201 for (i = 65; i < MAX_INSTRUMENTS; i++) {
202 if (!csf_instrument_is_empty(current_song->instruments[i])) {
203 j = i;
204 }
205 }
206 while ((j + 34) > n)
207 n += 34;
208 return MIN(n, MAX_INSTRUMENTS - 1);
209 }
210 /* the actual list */
211
instrument_list_reposition(void)212 static void instrument_list_reposition(void)
213 {
214 if (current_instrument < top_instrument) {
215 top_instrument = current_instrument;
216 if (top_instrument < 1) {
217 top_instrument = 1;
218 }
219 } else if (current_instrument > top_instrument + 34) {
220 top_instrument = current_instrument - 34;
221 }
222 }
223
instrument_get_current(void)224 int instrument_get_current(void)
225 {
226 return current_instrument;
227 }
228
instrument_set(int n)229 void instrument_set(int n)
230 {
231 int new_ins = n;
232 song_instrument_t *ins;
233
234 if (page_is_instrument_list(status.current_page)) {
235 new_ins = CLAMP(n, 1, _last_vis_inst());
236 } else {
237 new_ins = CLAMP(n, 0, _last_vis_inst());
238 }
239
240 if (current_instrument == new_ins)
241 return;
242
243 envelope_edit_mode = 0;
244 current_instrument = new_ins;
245 instrument_list_reposition();
246
247 ins = song_get_instrument(current_instrument);
248
249 current_node_vol = ins->vol_env.nodes ? CLAMP(current_node_vol, 0, ins->vol_env.nodes - 1) : 0;
250 current_node_pan = ins->pan_env.nodes ? CLAMP(current_node_vol, 0, ins->pan_env.nodes - 1) : 0;
251 current_node_pitch = ins->pitch_env.nodes ? CLAMP(current_node_vol, 0, ins->pan_env.nodes - 1) : 0;
252
253 status.flags |= NEED_UPDATE;
254 }
255
instrument_synchronize_to_sample(void)256 void instrument_synchronize_to_sample(void)
257 {
258 song_instrument_t *ins;
259 int sample = sample_get_current();
260 int n, pos;
261
262 /* 1. if the instrument with the same number as the current sample
263 * has the sample in its sample_map, change to that instrument. */
264 ins = song_get_instrument(sample);
265 for (pos = 0; pos < 120; pos++) {
266 if ((int)(ins->sample_map[pos]) == sample) {
267 instrument_set(sample);
268 return;
269 }
270 }
271
272 /* 2. look through the instrument list for the first instrument
273 * that uses the selected sample. */
274 for (n = 1; n < 100; n++) {
275 if (n == sample)
276 continue;
277 ins = song_get_instrument(n);
278 for (pos = 0; pos < 120; pos++) {
279 if ((int)(ins->sample_map[pos]) == sample) {
280 instrument_set(n);
281 return;
282 }
283 }
284 }
285
286 /* 3. if no instruments are using the sample, just change to the
287 * same-numbered instrument. */
288 instrument_set(sample);
289 }
290
291 /* --------------------------------------------------------------------- */
292
instrument_list_add_char(int c)293 static int instrument_list_add_char(int c)
294 {
295 song_instrument_t *ins;
296
297 if (c < 32)
298 return 0;
299 ins = song_get_instrument(current_instrument);
300 text_add_char(ins->name, c, &instrument_cursor_pos, 25);
301 if (instrument_cursor_pos == 25)
302 instrument_cursor_pos--;
303
304 get_page_widgets()->accept_text = (instrument_cursor_pos == 25 ? 0 : 1);
305 status.flags |= NEED_UPDATE;
306 status.flags |= SONG_NEEDS_SAVE;
307 return 1;
308 }
309
instrument_list_delete_char(void)310 static void instrument_list_delete_char(void)
311 {
312 song_instrument_t *ins = song_get_instrument(current_instrument);
313 text_delete_char(ins->name, &instrument_cursor_pos, 25);
314
315 get_page_widgets()->accept_text = (instrument_cursor_pos == 25 ? 0 : 1);
316 status.flags |= NEED_UPDATE;
317 status.flags |= SONG_NEEDS_SAVE;
318 }
319
instrument_list_delete_next_char(void)320 static void instrument_list_delete_next_char(void)
321 {
322 song_instrument_t *ins = song_get_instrument(current_instrument);
323 text_delete_next_char(ins->name, &instrument_cursor_pos, 25);
324
325 get_page_widgets()->accept_text = (instrument_cursor_pos == 25 ? 0 : 1);
326 status.flags |= NEED_UPDATE;
327 status.flags |= SONG_NEEDS_SAVE;
328 }
329
clear_instrument_text(void)330 static void clear_instrument_text(void)
331 {
332 song_instrument_t *ins = song_get_instrument(current_instrument);
333
334 memset(ins->filename, 0, 14);
335 memset(ins->name, 0, 26);
336 if (instrument_cursor_pos != 25)
337 instrument_cursor_pos = 0;
338
339 get_page_widgets()->accept_text = (instrument_cursor_pos == 25 ? 0 : 1);
340 status.flags |= NEED_UPDATE;
341 status.flags |= SONG_NEEDS_SAVE;
342 }
343
344 /* --------------------------------------------------------------------- */
345
do_swap_instrument(int n)346 static void do_swap_instrument(int n)
347 {
348 if (n >= 1 && n <= _last_vis_inst()) {
349 song_swap_instruments(current_instrument, n);
350 }
351 }
352
do_exchange_instrument(int n)353 static void do_exchange_instrument(int n)
354 {
355 if (n >= 1 && n <= _last_vis_inst()) {
356 song_exchange_instruments(current_instrument, n);
357 }
358 }
359
do_copy_instrument(int n)360 static void do_copy_instrument(int n)
361 {
362 if (n >= 1 && n <= _last_vis_inst()) {
363 song_copy_instrument(current_instrument, n);
364 }
365 }
366
do_replace_instrument(int n)367 static void do_replace_instrument(int n)
368 {
369 if (n >= 1 && n <= _last_vis_inst()) {
370 song_replace_instrument(current_instrument, n);
371 }
372 }
373
374 /* --------------------------------------------------------------------- */
375
instrument_list_draw_list(void)376 static void instrument_list_draw_list(void)
377 {
378 int pos, n;
379 song_instrument_t *ins;
380 int selected = (ACTIVE_PAGE.selected_widget == 0);
381 int is_current;
382 int ss, cl = 0, cr = 0;
383 int is_playing[MAX_INSTRUMENTS];
384 char buf[4];
385
386 ss = -1;
387
388 song_get_playing_instruments(is_playing);
389
390 for (pos = 0, n = top_instrument; pos < 35; pos++, n++) {
391 ins = song_get_instrument(n);
392 is_current = (n == current_instrument);
393
394 if (ins->played)
395 draw_char(is_playing[n] > 1 ? 183 : 173, 1, 13 + pos, is_playing[n] ? 3 : 1, 2);
396
397 draw_text(num99tostr(n, buf), 2, 13 + pos, 0, 2);
398 if (instrument_cursor_pos < 25) {
399 /* it's in edit mode */
400 if (is_current) {
401 draw_text_len(ins->name, 25, 5, 13 + pos, 6, 14);
402 if (selected) {
403 draw_char(ins->name[instrument_cursor_pos],
404 5 + instrument_cursor_pos,
405 13 + pos, 0, 3);
406 }
407 } else {
408 draw_text_len(ins->name, 25, 5, 13 + pos, 6, 0);
409 }
410 } else {
411 draw_text_len(ins->name, 25, 5, 13 + pos,
412 ((is_current && selected) ? 0 : 6),
413 (is_current ? (selected ? 3 : 14) : 0));
414 }
415 if (ss == n) {
416 draw_text_len(ins->name + cl, (cr-cl)+1,
417 5 + cl, 13 + pos,
418 (is_current ? 3 : 11), 8);
419 }
420 }
421 }
422
instrument_list_handle_key_on_list(struct key_event * k)423 static int instrument_list_handle_key_on_list(struct key_event * k)
424 {
425 int new_ins = current_instrument;
426
427 if (k->state == KEY_PRESS && k->mouse != MOUSE_NONE && k->y >= 13 && k->y <= 47 && k->x >= 5 && k->x <= 30) {
428 if (k->mouse == MOUSE_CLICK) {
429 new_ins = (k->y - 13) + top_instrument;
430 if (instrument_cursor_pos < 25)
431 instrument_cursor_pos = MIN(k->x - 5, 24);
432 status.flags |= NEED_UPDATE;
433 } else if (k->mouse == MOUSE_DBLCLICK) {
434 /* this doesn't seem to work, but I think it'd be
435 more useful if double click switched to edit mode */
436 if (instrument_cursor_pos < 25) {
437 instrument_cursor_pos = 25;
438 get_page_widgets()->accept_text = 0;
439 } else {
440 set_page(PAGE_LOAD_INSTRUMENT);
441 }
442 status.flags |= NEED_UPDATE;
443 return 1;
444
445 } else if (k->mouse == MOUSE_SCROLL_UP) {
446 top_instrument -= MOUSE_SCROLL_LINES;
447 if (top_instrument < 1) top_instrument = 1;
448 status.flags |= NEED_UPDATE;
449 return 1;
450 } else if (k->mouse == MOUSE_SCROLL_DOWN) {
451 top_instrument += MOUSE_SCROLL_LINES;
452 if (top_instrument > (_last_vis_inst()-34)) top_instrument = _last_vis_inst()-34;
453 status.flags |= NEED_UPDATE;
454 return 1;
455 }
456 } else {
457 switch (k->sym) {
458 case SDLK_UP:
459 if (k->state == KEY_RELEASE)
460 return 0;
461 if (k->mod & KMOD_ALT) {
462 if (current_instrument > 1) {
463 new_ins = current_instrument - 1;
464 song_swap_instruments(current_instrument, new_ins);
465 }
466 } else if (!NO_MODIFIER(k->mod)) {
467 return 0;
468 } else {
469 new_ins--;
470 }
471 break;
472 case SDLK_DOWN:
473 if (k->state == KEY_RELEASE)
474 return 0;
475 if (k->mod & KMOD_ALT) {
476 // restrict position to the "old" value of _last_vis_inst()
477 // (this is entirely for aesthetic reasons)
478 if (status.last_keysym != SDLK_DOWN && !k->is_repeat)
479 _altswap_lastvis = _last_vis_inst();
480 if (current_instrument < _altswap_lastvis) {
481 new_ins = current_instrument + 1;
482 song_swap_instruments(current_instrument, new_ins);
483 }
484 } else if (!NO_MODIFIER(k->mod)) {
485 return 0;
486 } else {
487 new_ins++;
488 }
489 break;
490 case SDLK_PAGEUP:
491 if (k->state == KEY_RELEASE)
492 return 0;
493 if (k->mod & KMOD_CTRL)
494 new_ins = 1;
495 else
496 new_ins -= 16;
497 break;
498 case SDLK_PAGEDOWN:
499 if (k->state == KEY_RELEASE)
500 return 0;
501 if (k->mod & KMOD_CTRL)
502 new_ins = _last_vis_inst();
503 else
504 new_ins += 16;
505 break;
506 case SDLK_HOME:
507 if (k->state == KEY_RELEASE)
508 return 0;
509 if (!NO_MODIFIER(k->mod))
510 return 0;
511 if (instrument_cursor_pos < 25) {
512 instrument_cursor_pos = 0;
513 get_page_widgets()->accept_text = 1;
514 status.flags |= NEED_UPDATE;
515 }
516 return 1;
517 case SDLK_END:
518 if (k->state == KEY_RELEASE)
519 return 0;
520 if (!NO_MODIFIER(k->mod))
521 return 0;
522 if (instrument_cursor_pos < 24) {
523 instrument_cursor_pos = 24;
524 get_page_widgets()->accept_text = 1;
525 status.flags |= NEED_UPDATE;
526 }
527 return 1;
528 case SDLK_LEFT:
529 if (k->state == KEY_RELEASE)
530 return 0;
531 if (!NO_MODIFIER(k->mod))
532 return 0;
533 if (instrument_cursor_pos < 25 && instrument_cursor_pos > 0) {
534 instrument_cursor_pos--;
535 get_page_widgets()->accept_text = 1;
536 status.flags |= NEED_UPDATE;
537 }
538 return 1;
539 case SDLK_RIGHT:
540 if (k->state == KEY_RELEASE)
541 return 0;
542 if (!NO_MODIFIER(k->mod))
543 return 0;
544 if (instrument_cursor_pos == 25) {
545 get_page_widgets()->accept_text = 0;
546 change_focus_to(1);
547 } else if (instrument_cursor_pos < 24) {
548 get_page_widgets()->accept_text = 1;
549 instrument_cursor_pos++;
550 status.flags |= NEED_UPDATE;
551 }
552 return 1;
553 case SDLK_RETURN:
554 if (k->state == KEY_PRESS)
555 return 0;
556 if (instrument_cursor_pos < 25) {
557 instrument_cursor_pos = 25;
558 get_page_widgets()->accept_text = 0;
559 status.flags |= NEED_UPDATE;
560 } else {
561 get_page_widgets()->accept_text = 1;
562 set_page(PAGE_LOAD_INSTRUMENT);
563 }
564 return 1;
565 case SDLK_ESCAPE:
566 if ((k->mod & KMOD_SHIFT) || instrument_cursor_pos < 25) {
567 if (k->state == KEY_RELEASE)
568 return 1;
569 instrument_cursor_pos = 25;
570 get_page_widgets()->accept_text = 0;
571 status.flags |= NEED_UPDATE;
572 return 1;
573 }
574 return 0;
575 case SDLK_BACKSPACE:
576 if (k->state == KEY_RELEASE)
577 return 0;
578 if (instrument_cursor_pos == 25)
579 return 0;
580 if ((k->mod & (KMOD_CTRL | KMOD_ALT)) == 0)
581 instrument_list_delete_char();
582 else if (k->mod & KMOD_CTRL)
583 instrument_list_add_char(127);
584 return 1;
585 case SDLK_INSERT:
586 if (k->state == KEY_RELEASE)
587 return 0;
588 if (k->mod & KMOD_ALT) {
589 song_insert_instrument_slot(current_instrument);
590 status.flags |= NEED_UPDATE;
591 return 1;
592 }
593 return 0;
594 case SDLK_DELETE:
595 if (k->state == KEY_RELEASE)
596 return 0;
597 if (k->mod & KMOD_ALT) {
598 song_remove_instrument_slot(current_instrument);
599 status.flags |= NEED_UPDATE;
600 return 1;
601 } else if ((k->mod & KMOD_CTRL) == 0) {
602 if (instrument_cursor_pos == 25)
603 return 0;
604 instrument_list_delete_next_char();
605 return 1;
606 }
607 return 0;
608 default:
609 if (k->state == KEY_RELEASE)
610 return 0;
611 if (k->mod & KMOD_ALT) {
612 if (k->sym == SDLK_c) {
613 clear_instrument_text();
614 return 1;
615 }
616 } else if ((k->mod & KMOD_CTRL) == 0) {
617 if (!k->unicode) return 0;
618 if (instrument_cursor_pos < 25) {
619 return instrument_list_add_char(k->unicode);
620 } else if (k->sym == SDLK_SPACE) {
621 instrument_cursor_pos = 0;
622 get_page_widgets()->accept_text = 0;
623 status.flags |= NEED_UPDATE;
624 memused_songchanged();
625 return 1;
626 }
627 }
628 return 0;
629 };
630 }
631
632 new_ins = CLAMP(new_ins, 1, _last_vis_inst());
633 if (new_ins != current_instrument) {
634 instrument_set(new_ins);
635 status.flags |= NEED_UPDATE;
636 memused_songchanged();
637 }
638
639 return 1;
640 }
641
642 /* --------------------------------------------------------------------- */
643 /* note translation table */
644
note_trans_reposition(void)645 static void note_trans_reposition(void)
646 {
647 if (note_trans_sel_line < note_trans_top_line) {
648 note_trans_top_line = note_trans_sel_line;
649 } else if (note_trans_sel_line > note_trans_top_line + 31) {
650 note_trans_top_line = note_trans_sel_line - 31;
651 }
652 }
653
note_trans_draw(void)654 static void note_trans_draw(void)
655 {
656 int pos, n;
657 int is_selected = (ACTIVE_PAGE.selected_widget == 5);
658 int bg, sel_bg = (is_selected ? 14 : 0);
659 song_instrument_t *ins = song_get_instrument(current_instrument);
660 char buf[4];
661
662 for (pos = 0, n = note_trans_top_line; pos < 32; pos++, n++) {
663 bg = ((n == note_trans_sel_line) ? sel_bg : 0);
664
665 /* invalid notes are translated to themselves (and yes, this edits the actual instrument) */
666 if (ins->note_map[n] < 1 || ins->note_map[n] > 120)
667 ins->note_map[n] = n + 1;
668
669 draw_text(get_note_string(n + 1, buf), 32, 16 + pos, 2, bg);
670 draw_char(168, 35, 16 + pos, 2, bg);
671 draw_text(get_note_string(ins->note_map[n], buf), 36, 16 + pos, 2, bg);
672 if (is_selected && n == note_trans_sel_line) {
673 if (note_trans_cursor_pos == 0)
674 draw_char(buf[0], 36, 16 + pos, 0, 3);
675 else if (note_trans_cursor_pos == 1)
676 draw_char(buf[2], 38, 16 + pos, 0, 3);
677 }
678 draw_char(0, 39, 16 + pos, 2, bg);
679 if (ins->sample_map[n]) {
680 num99tostr(ins->sample_map[n], buf);
681 } else {
682 buf[0] = buf[1] = 173;
683 buf[2] = 0;
684 }
685 draw_text(buf, 40, 16 + pos, 2, bg);
686 if (is_selected && n == note_trans_sel_line) {
687 if (note_trans_cursor_pos == 2)
688 draw_char(buf[0], 40, 16 + pos, 0, 3);
689 else if (note_trans_cursor_pos == 3)
690 draw_char(buf[1], 41, 16 + pos, 0, 3);
691 }
692 }
693
694 /* draw the little mask thingy at the bottom. Could optimize this.... -delt.
695 Sure can! This could share the same track-view functions that the
696 pattern editor ought to be using. -Storlek */
697 if (is_selected && !(status.flags & CLASSIC_MODE)) {
698 switch (note_trans_cursor_pos) {
699 case 0:
700 draw_char(171, 36, 48, 3, 2);
701 draw_char(171, 37, 48, 3, 2);
702 draw_char(169, 38, 48, 3, 2);
703 if (note_sample_mask) {
704 draw_char(169, 40, 48, 3, 2);
705 draw_char(169, 41, 48, 3, 2);
706 }
707 break;
708 case 1:
709 draw_char(169, 38, 48, 3, 2);
710 if (note_sample_mask) {
711 draw_char(170, 40, 48, 3, 2);
712 draw_char(170, 41, 48, 3, 2);
713 }
714 break;
715 case 2:
716 case 3:
717 draw_char(note_sample_mask ? 171 : 169, 40, 48, 3, 2);
718 draw_char(note_sample_mask ? 171 : 169, 41, 48, 3, 2);
719 break;
720 };
721 }
722 }
723
instrument_note_trans_transpose(song_instrument_t * ins,int dir)724 static void instrument_note_trans_transpose(song_instrument_t *ins, int dir)
725 {
726 int i;
727 for (i = 0; i < 120; i++) {
728 ins->note_map[i] = CLAMP(ins->note_map[i]+dir, 1, 120);
729 }
730 }
731
instrument_note_trans_insert(song_instrument_t * ins,int pos)732 static void instrument_note_trans_insert(song_instrument_t *ins, int pos)
733 {
734 int i;
735 for (i = 119; i > pos; i--) {
736 ins->note_map[i] = ins->note_map[i-1];
737 ins->sample_map[i] = ins->sample_map[i-1];
738 }
739 if (pos) {
740 ins->note_map[pos] = ins->note_map[pos-1]+1;
741 } else {
742 ins->note_map[0] = 1;
743 }
744 }
745
instrument_note_trans_delete(song_instrument_t * ins,int pos)746 static void instrument_note_trans_delete(song_instrument_t *ins, int pos)
747 {
748 int i;
749 for (i = pos; i < 120; i++) {
750 ins->note_map[i] = ins->note_map[i+1];
751 ins->sample_map[i] = ins->sample_map[i+1];
752 }
753 ins->note_map[119] = ins->note_map[118]+1;
754 }
755
note_trans_handle_key(struct key_event * k)756 static int note_trans_handle_key(struct key_event * k)
757 {
758 int prev_line = note_trans_sel_line;
759 int new_line = prev_line;
760 int prev_pos = note_trans_cursor_pos;
761 int new_pos = prev_pos;
762 song_instrument_t *ins = song_get_instrument(current_instrument);
763 int c, n;
764
765 if (k->mouse == MOUSE_CLICK && k->mouse_button == MOUSE_BUTTON_MIDDLE) {
766 if (k->state == KEY_RELEASE)
767 status.flags |= CLIPPY_PASTE_SELECTION;
768 return 1;
769 } else if (k->mouse == MOUSE_SCROLL_UP || k->mouse == MOUSE_SCROLL_DOWN) {
770 if (k->state == KEY_PRESS) {
771 note_trans_top_line += (k->mouse == MOUSE_SCROLL_UP) ? -3 : 3;
772 note_trans_top_line = CLAMP(note_trans_top_line, 0, 119 - 31);
773 status.flags |= NEED_UPDATE;
774 }
775 return 1;
776 } else if (k->mouse != MOUSE_NONE) {
777 if (k->x >= 32 && k->x <= 41 && k->y >= 16 && k->y <= 47) {
778 new_line = note_trans_top_line + k->y - 16;
779 if (new_line == prev_line) {
780 switch (k->x - 36) {
781 case 2:
782 new_pos = 1;
783 break;
784 case 4:
785 new_pos = 2;
786 break;
787 case 5:
788 new_pos = 3;
789 break;
790 default:
791 new_pos = 0;
792 break;
793 };
794 }
795 }
796 } else if (k->mod & KMOD_ALT) {
797 if (k->state == KEY_RELEASE)
798 return 0;
799 switch (k->sym) {
800 case SDLK_UP:
801 instrument_note_trans_transpose(ins, 1);
802 break;
803 case SDLK_DOWN:
804 instrument_note_trans_transpose(ins, -1);
805 break;
806 case SDLK_INSERT:
807 instrument_note_trans_insert(ins, note_trans_sel_line);
808 break;
809 case SDLK_DELETE:
810 instrument_note_trans_delete(ins, note_trans_sel_line);
811 break;
812 case SDLK_n:
813 n = note_trans_sel_line - 1; // the line to copy *from*
814 if (n < 0 || ins->note_map[n] == NOTE_LAST)
815 break;
816 ins->note_map[note_trans_sel_line] = ins->note_map[n] + 1;
817 ins->sample_map[note_trans_sel_line] = ins->sample_map[n];
818 new_line++;
819 break;
820 case SDLK_p:
821 n = note_trans_sel_line + 1; // the line to copy *from*
822 if (n > (NOTE_LAST - NOTE_FIRST) || ins->note_map[n] == NOTE_FIRST)
823 break;
824 ins->note_map[note_trans_sel_line] = ins->note_map[n] - 1;
825 ins->sample_map[note_trans_sel_line] = ins->sample_map[n];
826 new_line--;
827 break;
828 case SDLK_a:
829 c = sample_get_current();
830 for (n = 0; n < (NOTE_LAST - NOTE_FIRST + 1); n++)
831 ins->sample_map[n] = c;
832 if (k->mod & KMOD_SHIFT) {
833 // Copy the name too.
834 memcpy(ins->name, current_song->samples[c].name, 32);
835 }
836 break;
837 default:
838 return 0;
839 }
840 } else {
841 switch (k->sym) {
842 case SDLK_UP:
843 if (k->state == KEY_RELEASE)
844 return 0;
845 if (k->mod & KMOD_CTRL)
846 sample_set(sample_get_current () - 1);
847 if (!NO_MODIFIER(k->mod))
848 return 0;
849 if (--new_line < 0) {
850 change_focus_to(1);
851 return 1;
852 }
853 break;
854 case SDLK_DOWN:
855 if (k->state == KEY_RELEASE)
856 return 0;
857 if (k->mod & KMOD_CTRL)
858 sample_set(sample_get_current () + 1);
859 if (!NO_MODIFIER(k->mod))
860 return 0;
861 new_line++;
862 break;
863 case SDLK_PAGEUP:
864 if (k->state == KEY_RELEASE)
865 return 0;
866 if (k->mod & KMOD_CTRL) {
867 instrument_set(current_instrument - 1);
868 return 1;
869 }
870 new_line -= 16;
871 break;
872 case SDLK_PAGEDOWN:
873 if (k->state == KEY_RELEASE)
874 return 0;
875 if (k->mod & KMOD_CTRL) {
876 instrument_set(current_instrument + 1);
877 return 1;
878 }
879 new_line += 16;
880 break;
881 case SDLK_HOME:
882 if (k->state == KEY_RELEASE)
883 return 0;
884 if (!NO_MODIFIER(k->mod))
885 return 0;
886 new_line = 0;
887 break;
888 case SDLK_END:
889 if (k->state == KEY_RELEASE)
890 return 0;
891 if (!NO_MODIFIER(k->mod))
892 return 0;
893 new_line = 119;
894 break;
895 case SDLK_LEFT:
896 if (k->state == KEY_RELEASE)
897 return 0;
898 if (!NO_MODIFIER(k->mod))
899 return 0;
900 new_pos--;
901 break;
902 case SDLK_RIGHT:
903 if (k->state == KEY_RELEASE)
904 return 0;
905 if (!NO_MODIFIER(k->mod))
906 return 0;
907 new_pos++;
908 break;
909 case SDLK_RETURN:
910 if (k->state == KEY_PRESS)
911 return 0;
912 if (!NO_MODIFIER(k->mod))
913 return 0;
914 sample_set(ins->sample_map[note_trans_sel_line]);
915 get_page_widgets()->accept_text = (instrument_cursor_pos == 25 ? 0 : 1);
916 return 1;
917 case SDLK_LESS:
918 case SDLK_SEMICOLON:
919 case SDLK_COLON:
920 if (k->state == KEY_RELEASE)
921 return 0;
922 sample_set(sample_get_current() - 1);
923 return 1;
924 case SDLK_GREATER:
925 case SDLK_QUOTE:
926 case SDLK_QUOTEDBL:
927 if (k->state == KEY_RELEASE)
928 return 0;
929 sample_set(sample_get_current() + 1);
930 return 1;
931
932 default:
933 if (k->state == KEY_RELEASE)
934 return 0;
935 switch (note_trans_cursor_pos) {
936 case 0: /* note */
937 n = kbd_get_note(k);
938 if (!NOTE_IS_NOTE(n))
939 return 0;
940 ins->note_map[note_trans_sel_line] = n;
941 if (note_sample_mask || (status.flags & CLASSIC_MODE))
942 ins->sample_map[note_trans_sel_line] = sample_get_current();
943 new_line++;
944 break;
945 case 1: /* octave */
946 c = kbd_char_to_hex(k);
947 if (c < 0 || c > 9) return 0;
948 n = ins->note_map[note_trans_sel_line];
949 n = ((n - 1) % 12) + (12 * c) + 1;
950 ins->note_map[note_trans_sel_line] = n;
951 new_line++;
952 break;
953
954 /* Made it possible to enter H to R letters
955 on 1st digit for expanded sample slots. -delt. */
956
957 case 2: /* instrument, first digit */
958 case 3: /* instrument, second digit */
959 if (k->sym == SDLK_SPACE) {
960 ins->sample_map[note_trans_sel_line] =
961 sample_get_current();
962 new_line++;
963 break;
964 }
965
966 if ((k->sym == SDLK_PERIOD && NO_MODIFIER(k->mod)) || k->sym == SDLK_DELETE) {
967 ins->sample_map[note_trans_sel_line] = 0;
968 new_line += (k->sym == SDLK_PERIOD) ? 1 : 0;
969 break;
970 }
971 if (k->sym == SDLK_COMMA && NO_MODIFIER(k->mod)) {
972 note_sample_mask = note_sample_mask ? 0 : 1;
973 break;
974 }
975
976 n = ins->sample_map[note_trans_sel_line];
977 if (note_trans_cursor_pos == 2) {
978 c = kbd_char_to_99(k);
979 if (c < 0) return 0;
980 n = (c * 10) + (n % 10);
981 new_pos++;
982 } else {
983 c = kbd_char_to_hex(k);
984 if (c < 0 || c > 9) return 0;
985 n = ((n / 10) * 10) + c;
986 new_pos--;
987 new_line++;
988 }
989 n = MIN(n, MAX_SAMPLES - 1);
990 ins->sample_map[note_trans_sel_line] = n;
991 sample_set(n);
992 break;
993 }
994 break;
995 }
996 }
997
998 new_line = CLAMP(new_line, 0, 119);
999 note_trans_cursor_pos = CLAMP(new_pos, 0, 3);
1000 if (new_line != prev_line) {
1001 note_trans_sel_line = new_line;
1002 note_trans_reposition();
1003 }
1004
1005 /* this causes unneeded redraws in some cases... oh well :P */
1006 status.flags |= NEED_UPDATE;
1007 return 1;
1008 }
1009
1010 /* --------------------------------------------------------------------------------------------------------- */
1011 /* envelope helper functions */
1012
_env_draw_axes(int middle)1013 static void _env_draw_axes(int middle)
1014 {
1015 int n, y = middle ? 31 : 62;
1016 for (n = 0; n < 64; n += 2)
1017 vgamem_ovl_drawpixel(&env_overlay, 3, n, 12);
1018 for (n = 0; n < 256; n += 2)
1019 vgamem_ovl_drawpixel(&env_overlay, 1 + n, y, 12);
1020 }
1021
_env_draw_node(int x,int y,int on)1022 static void _env_draw_node(int x, int y, int on)
1023 {
1024 int c = (status.flags & CLASSIC_MODE) ? 12 : 5;
1025
1026 vgamem_ovl_drawpixel(&env_overlay, x - 1, y - 1, c);
1027 vgamem_ovl_drawpixel(&env_overlay, x - 1, y, c);
1028 vgamem_ovl_drawpixel(&env_overlay, x - 1, y + 1, c);
1029
1030 vgamem_ovl_drawpixel(&env_overlay, x, y - 1, c);
1031 vgamem_ovl_drawpixel(&env_overlay, x, y, c);
1032 vgamem_ovl_drawpixel(&env_overlay, x, y + 1, c);
1033
1034 vgamem_ovl_drawpixel(&env_overlay, x + 1, y - 1,c);
1035 vgamem_ovl_drawpixel(&env_overlay, x + 1, y,c);
1036 vgamem_ovl_drawpixel(&env_overlay, x + 1, y + 1,c);
1037
1038 if (on) {
1039 vgamem_ovl_drawpixel(&env_overlay, x - 3, y - 1,c);
1040 vgamem_ovl_drawpixel(&env_overlay, x - 3, y,c);
1041 vgamem_ovl_drawpixel(&env_overlay, x - 3, y + 1,c);
1042
1043 vgamem_ovl_drawpixel(&env_overlay, x + 3, y - 1,c);
1044 vgamem_ovl_drawpixel(&env_overlay, x + 3, y,c);
1045 vgamem_ovl_drawpixel(&env_overlay, x + 3, y + 1,c);
1046 }
1047 }
1048
_env_draw_loop(int xs,int xe,int sustain)1049 static void _env_draw_loop(int xs, int xe, int sustain)
1050 {
1051 int y = 0;
1052 int c = (status.flags & CLASSIC_MODE) ? 12 : 3;
1053
1054 if (sustain) {
1055 while (y < 62) {
1056 /* unrolled once */
1057 vgamem_ovl_drawpixel(&env_overlay, xs, y, c);
1058 vgamem_ovl_drawpixel(&env_overlay, xe, y, c); y++;
1059 vgamem_ovl_drawpixel(&env_overlay, xs, y, 0);
1060 vgamem_ovl_drawpixel(&env_overlay, xe, y, 0); y++;
1061 vgamem_ovl_drawpixel(&env_overlay, xs, y, c);
1062 vgamem_ovl_drawpixel(&env_overlay, xe, y, c); y++;
1063 vgamem_ovl_drawpixel(&env_overlay, xs, y, 0);
1064 vgamem_ovl_drawpixel(&env_overlay, xe, y, 0); y++;
1065 }
1066 } else {
1067 while (y < 62) {
1068 vgamem_ovl_drawpixel(&env_overlay, xs, y, 0);
1069 vgamem_ovl_drawpixel(&env_overlay, xe, y, 0); y++;
1070 vgamem_ovl_drawpixel(&env_overlay, xs, y, c);
1071 vgamem_ovl_drawpixel(&env_overlay, xe, y, c); y++;
1072 vgamem_ovl_drawpixel(&env_overlay, xs, y, c);
1073 vgamem_ovl_drawpixel(&env_overlay, xe, y, c); y++;
1074 vgamem_ovl_drawpixel(&env_overlay, xs, y, 0);
1075 vgamem_ovl_drawpixel(&env_overlay, xe, y, 0); y++;
1076 }
1077 }
1078 }
1079
_env_draw(const song_envelope_t * env,int middle,int current_node,int env_on,int loop_on,int sustain_on,int env_num)1080 static void _env_draw(const song_envelope_t *env, int middle, int current_node,
1081 int env_on, int loop_on, int sustain_on, int env_num)
1082 {
1083 song_voice_t *channel;
1084 unsigned int *channel_list;
1085 char buf[16];
1086 unsigned int envpos[3];
1087 int x, y, n, m, c;
1088 int last_x = 0, last_y = 0;
1089 int max_ticks = 50;
1090
1091 while (env->ticks[env->nodes - 1] >= max_ticks)
1092 max_ticks *= 2;
1093
1094 vgamem_ovl_clear(&env_overlay, 0);
1095
1096 /* draw the axis lines */
1097 _env_draw_axes(middle);
1098
1099 for (n = 0; n < env->nodes; n++) {
1100 x = 4 + env->ticks[n] * 256 / max_ticks;
1101
1102 /* 65 values are being crammed into 62 pixels => have to lose three pixels somewhere.
1103 * This is where IT compromises -- I don't quite get how the lines are drawn, though,
1104 * because it changes for each value... (apart from drawing 63 and 64 the same way) */
1105 y = env->values[n];
1106 if (y > 63) y--;
1107 if (y > 42) y--;
1108 if (y > 21) y--;
1109 y = 62 - y;
1110
1111 _env_draw_node(x, y, n == current_node);
1112
1113 if (last_x)
1114 vgamem_ovl_drawline(&env_overlay,
1115 last_x, last_y, x, y, 12);
1116
1117 last_x = x;
1118 last_y = y;
1119 }
1120
1121 if (sustain_on)
1122 _env_draw_loop(4 + env->ticks[env->sustain_start] * 256 / max_ticks,
1123 4 + env->ticks[env->sustain_end] * 256 / max_ticks, 1);
1124 if (loop_on)
1125 _env_draw_loop(4 + env->ticks[env->loop_start] * 256 / max_ticks,
1126 4 + env->ticks[env->loop_end] * 256 / max_ticks, 0);
1127
1128 if (env_on) {
1129 max_ticks = env->ticks[env->nodes-1];
1130 m = max_ticks ? song_get_mix_state(&channel_list) : 0;
1131 while (m--) {
1132 channel = song_get_mix_channel(channel_list[m]);
1133 if (channel->ptr_instrument != song_get_instrument(current_instrument))
1134 continue;
1135
1136 envpos[0] = channel->vol_env_position;
1137 envpos[1] = channel->pan_env_position;
1138 envpos[2] = channel->pitch_env_position;
1139
1140 x = 4 + (envpos[env_num] * (last_x-4) / max_ticks);
1141 if (x > last_x)
1142 x = last_x;
1143 c = (status.flags & CLASSIC_MODE)
1144 ? 12
1145 : ((channel->flags & (CHN_KEYOFF | CHN_NOTEFADE)) ? 8 : 6);
1146 for (y = 0; y < 62; y++)
1147 vgamem_ovl_drawpixel(&env_overlay, x, y, c);
1148 }
1149 }
1150
1151 draw_fill_chars(65, 18, 76, 25, 0);
1152 vgamem_ovl_apply(&env_overlay);
1153
1154 sprintf(buf, "Node %d/%d", current_node, env->nodes);
1155 draw_text(buf, 66, 19, 2, 0);
1156 sprintf(buf, "Tick %d", env->ticks[current_node]);
1157 draw_text(buf, 66, 21, 2, 0);
1158 sprintf(buf, "Value %d", (int)(env->values[current_node] - (middle ? 32 : 0)));
1159 draw_text(buf, 66, 23, 2, 0);
1160 }
1161
1162 /* return: the new current node */
_env_node_add(song_envelope_t * env,int current_node,int override_tick,int override_value)1163 static int _env_node_add(song_envelope_t *env, int current_node, int override_tick, int override_value)
1164 {
1165 int newtick, newvalue;
1166
1167 status.flags |= SONG_NEEDS_SAVE;
1168
1169 if (env->nodes > 24 || current_node == env->nodes - 1)
1170 return current_node;
1171
1172 newtick = (env->ticks[current_node] + env->ticks[current_node + 1]) / 2;
1173 newvalue = (env->values[current_node] + env->values[current_node + 1]) / 2;
1174 if (override_tick > -1 && override_value > -1) {
1175 newtick = override_tick;
1176 newvalue = override_value;
1177 } else if (newtick == env->ticks[current_node] || newtick == env->ticks[current_node + 1]) {
1178 printf("Not enough room!\n");
1179 return current_node;
1180 }
1181
1182 env->nodes++;
1183 memmove(env->ticks + current_node + 1, env->ticks + current_node,
1184 (env->nodes - current_node - 1) * sizeof(env->ticks[0]));
1185 memmove(env->values + current_node + 1, env->values + current_node,
1186 (env->nodes - current_node - 1) * sizeof(env->values[0]));
1187 env->ticks[current_node + 1] = newtick;
1188 env->values[current_node + 1] = newvalue;
1189 if (env->loop_end > current_node) env->loop_end++;
1190 if (env->loop_start > current_node) env->loop_start++;
1191 if (env->sustain_end > current_node) env->sustain_end++;
1192 if (env->sustain_start > current_node) env->sustain_start++;
1193
1194 return current_node;
1195 }
1196
1197 /* return: the new current node */
_env_node_remove(song_envelope_t * env,int current_node)1198 static int _env_node_remove(song_envelope_t *env, int current_node)
1199 {
1200 status.flags |= SONG_NEEDS_SAVE;
1201
1202 if (current_node == 0 || env->nodes < 3)
1203 return current_node;
1204
1205 memmove(env->ticks + current_node, env->ticks + current_node + 1,
1206 (env->nodes - current_node - 1) * sizeof(env->ticks[0]));
1207 memmove(env->values + current_node, env->values + current_node + 1,
1208 (env->nodes - current_node - 1) * sizeof(env->values[0]));
1209 env->nodes--;
1210
1211 if (env->loop_start >= env->nodes)
1212 env->loop_start = env->nodes - 1;
1213 else if (env->loop_start > current_node)
1214 env->loop_start--;
1215 if (env->loop_end >= env->nodes)
1216 env->loop_end = env->nodes - 1;
1217 else if (env->loop_end > current_node)
1218 env->loop_end--;
1219 if (env->sustain_start >= env->nodes)
1220 env->sustain_start = env->nodes - 1;
1221 else if (env->sustain_start > current_node)
1222 env->sustain_start--;
1223 if (env->sustain_end >= env->nodes)
1224 env->sustain_end = env->nodes - 1;
1225 else if (env->sustain_end > current_node)
1226 env->sustain_end--;
1227 if (current_node >= env->nodes)
1228 current_node = env->nodes - 1;
1229
1230 return current_node;
1231 }
1232
do_pre_loop_cut(void * ign)1233 static void do_pre_loop_cut(void *ign)
1234 {
1235 song_envelope_t *env = (song_envelope_t *)ign;
1236 unsigned int bt;
1237 int i;
1238 bt = env->ticks[env->loop_start];
1239 for (i = env->loop_start; i < 32; i++) {
1240 env->ticks[i - env->loop_start] = env->ticks[i] - bt;
1241 env->values[i - env->loop_start] = env->values[i];
1242 }
1243 env->nodes -= env->loop_start;
1244 if (env->sustain_start > env->loop_start) {
1245 env->sustain_start -= env->loop_start;
1246 } else {
1247 env->sustain_start = 0;
1248 }
1249 if (env->sustain_end > env->loop_start) {
1250 env->sustain_end -= env->loop_start;
1251 } else {
1252 env->sustain_end = 0;
1253 }
1254 if (env->loop_end > env->loop_start) {
1255 env->loop_end -= env->loop_start;
1256 } else {
1257 env->loop_end = 0;
1258 }
1259 env->loop_start = 0;
1260 if (env->loop_start > env->loop_end)
1261 env->loop_end = env->loop_start;
1262 if (env->sustain_start > env->sustain_end)
1263 env->sustain_end = env->sustain_start;
1264 status.flags |= NEED_UPDATE;
1265 }
1266
do_post_loop_cut(void * ign)1267 static void do_post_loop_cut(void *ign)
1268 {
1269 song_envelope_t *env = (song_envelope_t *)ign;
1270 env->nodes = env->loop_end+1;
1271 }
1272
1273
env_resize(song_envelope_t * env,int ticks)1274 static void env_resize(song_envelope_t *env, int ticks)
1275 {
1276 int old = env->ticks[env->nodes - 1];
1277 int n, t;
1278
1279 if (ticks > 9999)
1280 ticks = 9999;
1281 for (n = 1; n < env->nodes; n++) {
1282 t = env->ticks[n] * ticks / old;
1283 env->ticks[n] = MAX(t, env->ticks[n - 1] + 1);
1284 }
1285 status.flags |= NEED_UPDATE;
1286 }
1287
1288
1289 static struct widget env_resize_widgets[2];
1290 static int env_resize_cursor;
1291
do_env_resize(void * data)1292 static void do_env_resize(void *data)
1293 {
1294 env_resize((song_envelope_t *) data, env_resize_widgets[0].d.numentry.value);
1295 }
1296
env_resize_draw_const(void)1297 static void env_resize_draw_const(void)
1298 {
1299 draw_text("Resize Envelope", 34, 24, 3, 2);
1300 draw_text("New Length", 31, 27, 0, 2);
1301 draw_box(41, 26, 49, 28, BOX_THICK | BOX_INNER | BOX_INSET);
1302 }
1303
env_resize_dialog(song_envelope_t * env)1304 static void env_resize_dialog(song_envelope_t *env)
1305 {
1306 struct dialog *dialog;
1307
1308 env_resize_cursor = 0;
1309 create_numentry(env_resize_widgets + 0, 42, 27, 7, 0, 1, 1, NULL, 0, 9999, &env_resize_cursor);
1310 env_resize_widgets[0].d.numentry.value = env->ticks[env->nodes - 1];
1311 create_button(env_resize_widgets + 1, 36, 30, 6, 0, 1, 1, 1, 1, dialog_cancel_NULL, "Cancel", 1);
1312 dialog = dialog_create_custom(26, 22, 29, 11, env_resize_widgets, 2, 0, env_resize_draw_const, env);
1313 dialog->action_yes = do_env_resize;
1314 }
1315
1316
1317
1318 static struct widget env_adsr_widgets[4];
1319 static int env_adsr_cursor = 0;
1320
do_env_adsr(void * data)1321 static void do_env_adsr(void *data)
1322 {
1323 // FIXME | move env flags into the envelope itself, where they should be in the first place.
1324 // FIXME | then this nonsense can go away.
1325 song_instrument_t *ins = (song_instrument_t *) data;
1326 song_envelope_t *env = &ins->vol_env;
1327 int a = env_adsr_widgets[0].d.thumbbar.value;
1328 int d = env_adsr_widgets[1].d.thumbbar.value;
1329 int s = env_adsr_widgets[2].d.thumbbar.value;
1330 int r = env_adsr_widgets[3].d.thumbbar.value;
1331 int v1 = MAX(a, a * a / 16);
1332 int v2 = MAX(v1 + d * d / 16, v1 + d);
1333 int v3 = MAX(v2 + r * r / 4, v2 + r);
1334 int n = 0;
1335
1336 if (a) {
1337 env->ticks[n] = 0;
1338 env->values[n++] = 0;
1339 }
1340 if (d) {
1341 env->ticks[n] = v1;
1342 env->values[n++] = 64;
1343 }
1344 env->sustain_start = env->sustain_end = n;
1345 env->ticks[n] = v2;
1346 env->values[n++] = s / 2;
1347 env->ticks[n] = v3;
1348 env->values[n++] = 0;
1349 env->nodes = n;
1350 for (n = 0; n < env->nodes - 1; n++)
1351 if (env->ticks[n] >= env->ticks[n + 1])
1352 env->ticks[n + 1] = env->ticks[n] + 1;
1353 ins->flags |= ENV_VOLSUSTAIN | ENV_VOLUME; // arghhhhh
1354 }
1355
env_adsr_draw_const(void)1356 static void env_adsr_draw_const(void)
1357 {
1358 draw_text("Envelope Generator", 32, 22, 0, 2);
1359 draw_text("Attack", 27, 24, 0, 2);
1360 draw_text("Decay", 28, 25, 0, 2);
1361 draw_text("Sustain", 26, 26, 0, 2);
1362 draw_text("Release", 26, 27, 0, 2);
1363
1364 draw_box(33, 23, 51, 28, BOX_THICK | BOX_INNER | BOX_INSET);
1365 }
1366
env_adsr_dialog(UNUSED song_envelope_t * env)1367 static void env_adsr_dialog(UNUSED song_envelope_t *env)
1368 {
1369 struct dialog *dialog;
1370 song_instrument_t *ins = song_get_instrument(current_instrument); // ARGHHH
1371
1372 env_adsr_cursor = 0;
1373 create_thumbbar(env_adsr_widgets + 0, 34, 24, 17, 4, 1, 4, NULL, 0, 128);
1374 create_thumbbar(env_adsr_widgets + 1, 34, 25, 17, 0, 2, 4, NULL, 0, 128);
1375 create_thumbbar(env_adsr_widgets + 2, 34, 26, 17, 1, 3, 4, NULL, 0, 128);
1376 create_thumbbar(env_adsr_widgets + 3, 34, 27, 17, 2, 4, 4, NULL, 0, 128);
1377 create_button(env_adsr_widgets + 4, 36, 30, 6, 3, 0, 4, 4, 0, dialog_cancel_NULL, "Cancel", 1);
1378
1379 dialog = dialog_create_custom(25, 21, 31, 12, env_adsr_widgets, 5, 0, env_adsr_draw_const, ins);
1380 dialog->action_yes = do_env_adsr;
1381 }
1382
1383
1384
1385
1386 /* the return value here is actually a bitmask:
1387 r & 1 => the key was handled
1388 r & 2 => the envelope changed (i.e., it should be enabled) */
_env_handle_key_viewmode(struct key_event * k,song_envelope_t * env,int * current_node,unsigned int sec)1389 static int _env_handle_key_viewmode(struct key_event *k, song_envelope_t *env, int *current_node, unsigned int sec)
1390 {
1391 int new_node = *current_node;
1392 int n;
1393
1394 switch (k->sym) {
1395 case SDLK_UP:
1396 if (k->state == KEY_RELEASE)
1397 return 0;
1398 change_focus_to(1);
1399 return 1;
1400 case SDLK_DOWN:
1401 if (k->state == KEY_RELEASE)
1402 return 0;
1403 change_focus_to(6);
1404 return 1;
1405 case SDLK_LEFT:
1406 if (k->state == KEY_RELEASE)
1407 return 0;
1408 if (!NO_MODIFIER(k->mod))
1409 return 0;
1410 new_node--;
1411 break;
1412 case SDLK_RIGHT:
1413 if (k->state == KEY_RELEASE)
1414 return 0;
1415 if (!NO_MODIFIER(k->mod))
1416 return 0;
1417 new_node++;
1418 break;
1419 case SDLK_INSERT:
1420 if (k->state == KEY_RELEASE)
1421 return 0;
1422 if (!NO_MODIFIER(k->mod))
1423 return 0;
1424 *current_node = _env_node_add(env, *current_node, -1, -1);
1425 status.flags |= NEED_UPDATE;
1426 return 1 | 2;
1427 case SDLK_DELETE:
1428 if (k->state == KEY_RELEASE)
1429 return 0;
1430 if (!NO_MODIFIER(k->mod))
1431 return 0;
1432 *current_node = _env_node_remove(env, *current_node);
1433 status.flags |= NEED_UPDATE;
1434 return 1 | 2;
1435 case SDLK_SPACE:
1436 if (k->state == KEY_RELEASE)
1437 return 0;
1438 if (!NO_MODIFIER(k->mod))
1439 return 0;
1440 song_keyup(KEYJAZZ_NOINST, current_instrument, last_note);
1441 song_keydown(KEYJAZZ_NOINST, current_instrument, last_note, 64, KEYJAZZ_CHAN_CURRENT);
1442 return 1;
1443 case SDLK_RETURN:
1444 if (k->state == KEY_PRESS)
1445 return 0;
1446 if (!NO_MODIFIER(k->mod))
1447 return 0;
1448 envelope_edit_mode = 1;
1449 status.flags |= NEED_UPDATE;
1450 return 1 | 2;
1451 case SDLK_l:
1452 if (k->state == KEY_PRESS)
1453 return 0;
1454 if (!(k->mod & KMOD_ALT)) return 0;
1455 if (env->loop_end < (env->nodes-1)) {
1456 dialog_create(DIALOG_OK_CANCEL, "Cut envelope?", do_post_loop_cut, NULL, 1, env);
1457 return 1;
1458 }
1459 return 0;
1460 case SDLK_b:
1461 if (k->state == KEY_PRESS)
1462 return 0;
1463 if (!(k->mod & KMOD_ALT)) return 0;
1464 if (env->loop_start > 0) {
1465 dialog_create(DIALOG_OK_CANCEL, "Cut envelope?", do_pre_loop_cut, NULL, 1, env);
1466 return 1;
1467 }
1468 return 0;
1469
1470 // F/G for key symmetry with pattern double/halve block
1471 // E for symmetry with sample resize
1472 case SDLK_f:
1473 if (k->state == KEY_PRESS)
1474 return 0;
1475 if (!(k->mod & KMOD_ALT)) return 0;
1476 env_resize(env, env->ticks[env->nodes - 1] * 2);
1477 return 1;
1478 case SDLK_g:
1479 if (k->state == KEY_PRESS)
1480 return 0;
1481 if (!(k->mod & KMOD_ALT)) return 0;
1482 env_resize(env, env->ticks[env->nodes - 1] / 2);
1483 return 1;
1484 case SDLK_e:
1485 if (k->state == KEY_PRESS)
1486 return 0;
1487 if (!(k->mod & KMOD_ALT)) return 0;
1488 env_resize_dialog(env);
1489 return 1;
1490
1491 case SDLK_z:
1492 if (k->state == KEY_PRESS)
1493 return 0;
1494 if (!(k->mod & KMOD_ALT)) return 0;
1495 env_adsr_dialog(env);
1496 return 1;
1497
1498 default:
1499 if (k->state == KEY_PRESS)
1500 return 0;
1501
1502 n = numeric_key_event(k, 0);
1503 if (n > -1) {
1504 if (k->mod & (KMOD_ALT | KMOD_CTRL)) {
1505 save_envelope(n, env, sec);
1506 status_text_flash("Envelope copied into slot %d", n);
1507 } else if (k->mod & KMOD_SHIFT) {
1508 restore_envelope(n, env, sec);
1509 if (!(status.flags & CLASSIC_MODE))
1510 status_text_flash("Pasted envelope from slot %d", n);
1511 }
1512 return 1;
1513 }
1514 return 0;
1515 }
1516
1517 new_node = CLAMP(new_node, 0, env->nodes - 1);
1518 if (*current_node != new_node) {
1519 *current_node = new_node;
1520 status.flags |= NEED_UPDATE;
1521 }
1522
1523 return 1;
1524 }
1525
1526 /* mouse handling routines for envelope */
_env_handle_mouse(struct key_event * k,song_envelope_t * env,int * current_node)1527 static int _env_handle_mouse(struct key_event *k, song_envelope_t *env, int *current_node)
1528 {
1529 int x, y, i;
1530 int max_ticks = 50;
1531
1532 if (k->mouse != MOUSE_CLICK) return 0;
1533
1534 if (k->state == KEY_RELEASE) {
1535 /* mouse release */
1536 if (envelope_mouse_edit) {
1537 if (current_node && *current_node) {
1538 for (i = 0; i < env->nodes-1; i++) {
1539 if (*current_node == i) continue;
1540 if (env->ticks[ *current_node ] == env->ticks[i]
1541 && env->values[ *current_node ] == env->values[i]) {
1542 status_text_flash("Removed node %d", (int)(*current_node));
1543 status.flags |= SONG_NEEDS_SAVE;
1544
1545 *current_node = _env_node_remove(env, *current_node);
1546 break;
1547 }
1548 }
1549
1550 }
1551 status.flags |= NEED_UPDATE;
1552 }
1553 memused_songchanged();
1554 envelope_mouse_edit = 0;
1555 return 1;
1556 }
1557
1558 while (env->ticks[env->nodes - 1] >= max_ticks)
1559 max_ticks *= 2;
1560
1561 if (envelope_mouse_edit) {
1562 if (k->fx < 259)
1563 x = 0;
1564 else
1565 x = (k->fx - 259) * max_ticks / 256;
1566 y = 64 - (k->fy - 144);
1567 if (y > 63) y++;
1568 if (y > 42) y++;
1569 if (y > 21) y++;
1570 if (y > 64) y = 64;
1571 if (y < 0) y = 0;
1572
1573 if (*current_node && env->ticks[ (*current_node)-1 ] >= x) {
1574 x = env->ticks[ (*current_node)-1 ]+1;
1575 }
1576 if (*current_node < (env->nodes-1)) {
1577 if (env->ticks[ (*current_node)+1 ] <= x) {
1578 x = env->ticks[ (*current_node)+1 ]-1;
1579 }
1580 }
1581 if (env->ticks[*current_node] == x && env->ticks[*current_node] == y) {
1582 return 1;
1583 }
1584 if (x < 0) x = 0;
1585 if (x > envelope_tick_limit) x = envelope_tick_limit;
1586 if (x > 9999) x = 9999;
1587 if (*current_node) env->ticks[ *current_node ] = x;
1588 env->values[ *current_node ] = y;
1589 status.flags |= SONG_NEEDS_SAVE;
1590 status.flags |= NEED_UPDATE;
1591 } else {
1592 int n;
1593 int dist, dx, dy;
1594 int best_dist = 0;
1595 int best_dist_node;
1596
1597 best_dist_node = -1;
1598
1599 if (k->x < 32 || k->y < 18 || k->x > 32+45 || k->y > 18+8)
1600 return 0;
1601
1602 for (n = 0; n < env->nodes; n++) {
1603 x = 259 + env->ticks[n] * 256 / max_ticks;
1604 y = env->values[n];
1605 if (y > 63) y--;
1606 if (y > 42) y--;
1607 if (y > 21) y--;
1608 y = 206 - y;
1609
1610 dx = abs(x - (int) k->fx);
1611 dy = abs(y - (int) k->fy);
1612 dist = i_sqrt((dx*dx)+(dy*dy));
1613 if (best_dist_node == -1 || dist < best_dist) {
1614 if (dist <= 5) {
1615 best_dist = dist;
1616 best_dist_node = n;
1617 }
1618 }
1619 }
1620 if (best_dist_node == -1) {
1621 x = (k->fx - 259) * max_ticks / 256;
1622 y = 64 - (k->fy - 144);
1623 if (y > 63) y++;
1624 if (y > 42) y++;
1625 if (y > 21) y++;
1626 if (y > 64) y = 64;
1627 if (y < 0) y = 0;
1628 if (x > 0 && x < max_ticks) {
1629 *current_node = 0;
1630 for (i = 1; i < env->nodes; i++) {
1631 /* something too close */
1632 if (env->ticks[i] <= x) *current_node = i;
1633 if (abs(env->ticks[i] - x) < 2) return 0;
1634 }
1635 best_dist_node = (_env_node_add(env, *current_node, x, y))+1;
1636 status_text_flash("Created node %d", best_dist_node);
1637 }
1638 if (best_dist_node == -1) return 0;
1639 }
1640
1641 envelope_tick_limit = env->ticks[env->nodes - 1] * 2;
1642 envelope_mouse_edit = 1;
1643 *current_node = best_dist_node;
1644 status.flags |= SONG_NEEDS_SAVE;
1645 status.flags |= NEED_UPDATE;
1646 return 1;
1647 }
1648 return 0;
1649 }
1650
1651
1652
1653 /* - this function is only ever called when the envelope is in edit mode
1654 - envelope_edit_mode is only ever assigned a true value once, in _env_handle_key_viewmode.
1655 - when _env_handle_key_viewmode enables envelope_edit_mode, it indicates in its return value
1656 that the envelope should be enabled.
1657 - therefore, the envelope will always be enabled when this function is called, so there is
1658 no reason to indicate a change in the envelope here. */
_env_handle_key_editmode(struct key_event * k,song_envelope_t * env,int * current_node)1659 static int _env_handle_key_editmode(struct key_event *k, song_envelope_t *env, int *current_node)
1660 {
1661 int new_node = *current_node, new_tick = env->ticks[*current_node],
1662 new_value = env->values[*current_node];
1663
1664 /* TODO: when does adding/removing a node alter loop points? */
1665
1666 switch (k->sym) {
1667 case SDLK_UP:
1668 if (k->state == KEY_RELEASE)
1669 return 0;
1670 if (k->mod & KMOD_ALT)
1671 new_value += 16;
1672 else
1673 new_value++;
1674 break;
1675 case SDLK_DOWN:
1676 if (k->state == KEY_RELEASE)
1677 return 0;
1678 if (k->mod & KMOD_ALT)
1679 new_value -= 16;
1680 else
1681 new_value--;
1682 break;
1683 case SDLK_PAGEUP:
1684 if (k->state == KEY_RELEASE)
1685 return 0;
1686 if (!NO_MODIFIER(k->mod))
1687 return 0;
1688 new_value += 16;
1689 break;
1690 case SDLK_PAGEDOWN:
1691 if (k->state == KEY_RELEASE)
1692 return 0;
1693 if (!NO_MODIFIER(k->mod))
1694 return 0;
1695 new_value -= 16;
1696 break;
1697 case SDLK_LEFT:
1698 if (k->state == KEY_RELEASE)
1699 return 1;
1700 if (k->mod & KMOD_CTRL)
1701 new_node--;
1702 else if (k->mod & KMOD_ALT)
1703 new_tick -= 16;
1704 else
1705 new_tick--;
1706 break;
1707 case SDLK_RIGHT:
1708 if (k->state == KEY_RELEASE)
1709 return 1;
1710 if (k->mod & KMOD_CTRL)
1711 new_node++;
1712 else if (k->mod & KMOD_ALT)
1713 new_tick += 16;
1714 else
1715 new_tick++;
1716 break;
1717 case SDLK_TAB:
1718 if (k->state == KEY_RELEASE)
1719 return 0;
1720 if (k->mod & KMOD_SHIFT)
1721 new_tick -= 16;
1722 else
1723 new_tick += 16;
1724 break;
1725 case SDLK_HOME:
1726 if (k->state == KEY_RELEASE)
1727 return 0;
1728 if (!NO_MODIFIER(k->mod))
1729 return 0;
1730 new_tick = 0;
1731 break;
1732 case SDLK_END:
1733 if (k->state == KEY_RELEASE)
1734 return 0;
1735 if (!NO_MODIFIER(k->mod))
1736 return 0;
1737 new_tick = 10000;
1738 break;
1739 case SDLK_INSERT:
1740 if (k->state == KEY_RELEASE)
1741 return 0;
1742 if (!NO_MODIFIER(k->mod))
1743 return 0;
1744 *current_node = _env_node_add(env, *current_node, -1, -1);
1745 status.flags |= NEED_UPDATE;
1746 return 1;
1747 case SDLK_DELETE:
1748 if (k->state == KEY_RELEASE)
1749 return 0;
1750 if (!NO_MODIFIER(k->mod))
1751 return 0;
1752 *current_node = _env_node_remove(env, *current_node);
1753 status.flags |= NEED_UPDATE;
1754 return 1;
1755 case SDLK_SPACE:
1756 if (k->state == KEY_RELEASE)
1757 return 0;
1758 if (!NO_MODIFIER(k->mod))
1759 return 0;
1760 song_keyup(KEYJAZZ_NOINST, current_instrument, last_note);
1761 song_keydown(KEYJAZZ_NOINST, current_instrument, last_note, 64, KEYJAZZ_CHAN_CURRENT);
1762 return 1;
1763 case SDLK_RETURN:
1764 if (k->state == KEY_PRESS)
1765 return 0;
1766 if (!NO_MODIFIER(k->mod))
1767 return 0;
1768 envelope_edit_mode = 0;
1769 memused_songchanged();
1770 status.flags |= NEED_UPDATE;
1771 break;
1772 default:
1773 return 0;
1774 }
1775
1776 new_node = CLAMP(new_node, 0, env->nodes - 1);
1777 if (new_node != *current_node) {
1778 status.flags |= NEED_UPDATE;
1779 *current_node = new_node;
1780 return 1;
1781 }
1782
1783 new_tick = (new_node == 0) ? 0 : CLAMP(new_tick,
1784 env->ticks[new_node - 1] + 1,
1785 ((new_node == env->nodes - 1)
1786 ? 10000 : env->ticks[new_node + 1]) - 1);
1787 if (new_tick != env->ticks[new_node]) {
1788 env->ticks[*current_node] = new_tick;
1789 status.flags |= SONG_NEEDS_SAVE;
1790 status.flags |= NEED_UPDATE;
1791 return 1;
1792 }
1793 new_value = CLAMP(new_value, 0, 64);
1794
1795 if (new_value != (int)env->values[new_node]) {
1796 env->values[*current_node] = (unsigned int)new_value;
1797 status.flags |= SONG_NEEDS_SAVE;
1798 status.flags |= NEED_UPDATE;
1799 return 1;
1800 }
1801
1802 return 1;
1803 }
1804
1805 /* --------------------------------------------------------------------------------------------------------- */
1806 /* envelope stuff (draw()'s and handle_key()'s) */
1807
_draw_env_label(const char * env_name,int is_selected)1808 static void _draw_env_label(const char *env_name, int is_selected)
1809 {
1810 int pos = 33;
1811
1812 pos += draw_text(env_name, pos, 16, is_selected ? 3 : 0, 2);
1813 pos += draw_text(" Envelope", pos, 16, is_selected ? 3 : 0, 2);
1814 if (envelope_edit_mode || envelope_mouse_edit)
1815 draw_text(" (Edit)", pos, 16, is_selected ? 3 : 0, 2);
1816 }
1817
volume_envelope_draw(void)1818 static void volume_envelope_draw(void)
1819 {
1820 int is_selected = (ACTIVE_PAGE.selected_widget == 5);
1821 song_instrument_t *ins = song_get_instrument(current_instrument);
1822
1823 _draw_env_label("Volume", is_selected);
1824 _env_draw(&ins->vol_env, 0, current_node_vol,
1825 ins->flags & ENV_VOLUME,
1826 ins->flags & ENV_VOLLOOP, ins->flags & ENV_VOLSUSTAIN, 0);
1827 }
1828
panning_envelope_draw(void)1829 static void panning_envelope_draw(void)
1830 {
1831 int is_selected = (ACTIVE_PAGE.selected_widget == 5);
1832 song_instrument_t *ins = song_get_instrument(current_instrument);
1833
1834 _draw_env_label("Panning", is_selected);
1835 _env_draw(&ins->pan_env, 1, current_node_pan,
1836 ins->flags & ENV_PANNING,
1837 ins->flags & ENV_PANLOOP, ins->flags & ENV_PANSUSTAIN, 1);
1838 }
1839
pitch_envelope_draw(void)1840 static void pitch_envelope_draw(void)
1841 {
1842 int is_selected = (ACTIVE_PAGE.selected_widget == 5);
1843 song_instrument_t *ins = song_get_instrument(current_instrument);
1844
1845 _draw_env_label("Frequency", is_selected);
1846 _env_draw(&ins->pitch_env, (ins->flags & ENV_FILTER) ? 0 : 1, current_node_pitch,
1847 ins->flags & (ENV_PITCH|ENV_FILTER),
1848 ins->flags & ENV_PITCHLOOP, ins->flags & ENV_PITCHSUSTAIN, 2);
1849 }
1850
volume_envelope_handle_key(struct key_event * k)1851 static int volume_envelope_handle_key(struct key_event * k)
1852 {
1853 song_instrument_t *ins = song_get_instrument(current_instrument);
1854 int r;
1855
1856 if (_env_handle_mouse(k, &ins->vol_env, ¤t_node_vol)) {
1857 ins->flags |= ENV_VOLUME;
1858 return 1;
1859 }
1860 if (envelope_edit_mode)
1861 r = _env_handle_key_editmode(k, &ins->vol_env, ¤t_node_vol);
1862 else
1863 r = _env_handle_key_viewmode(k, &ins->vol_env, ¤t_node_vol, ENV_VOLUME);
1864 if (r & 2) {
1865 r ^= 2;
1866 ins->flags |= ENV_VOLUME;
1867 }
1868 return r;
1869 }
1870
panning_envelope_handle_key(struct key_event * k)1871 static int panning_envelope_handle_key(struct key_event * k)
1872 {
1873 song_instrument_t *ins = song_get_instrument(current_instrument);
1874 int r;
1875
1876 if (_env_handle_mouse(k, &ins->pan_env, ¤t_node_pan)) {
1877 ins->flags |= ENV_PANNING;
1878 return 1;
1879 }
1880
1881 if (envelope_edit_mode)
1882 r = _env_handle_key_editmode(k, &ins->pan_env, ¤t_node_pan);
1883 else
1884 r = _env_handle_key_viewmode(k, &ins->pan_env, ¤t_node_pan, ENV_PANNING);
1885 if (r & 2) {
1886 r ^= 2;
1887 ins->flags |= ENV_PANNING;
1888 }
1889 return r;
1890 }
1891
pitch_envelope_handle_key(struct key_event * k)1892 static int pitch_envelope_handle_key(struct key_event * k)
1893 {
1894 song_instrument_t *ins = song_get_instrument(current_instrument);
1895 int r;
1896
1897 if (_env_handle_mouse(k, &ins->pitch_env, ¤t_node_pitch)) {
1898 ins->flags |= ENV_PITCH;
1899 return 1;
1900 }
1901 if (envelope_edit_mode)
1902 r = _env_handle_key_editmode(k, &ins->pitch_env, ¤t_node_pitch);
1903 else
1904 r = _env_handle_key_viewmode(k, &ins->pitch_env, ¤t_node_pitch, ENV_PITCH);
1905 if (r & 2) {
1906 r ^= 2;
1907 ins->flags |= ENV_PITCH;
1908 }
1909 return r;
1910 }
1911
1912 /* --------------------------------------------------------------------------------------------------------- */
1913 /* pitch-pan center */
1914
pitch_pan_center_handle_key(struct key_event * k)1915 static int pitch_pan_center_handle_key(struct key_event *k)
1916 {
1917 song_instrument_t *ins = song_get_instrument(current_instrument);
1918 int ppc = ins->pitch_pan_center;
1919
1920 if (k->state == KEY_RELEASE)
1921 return 0;
1922 switch (k->sym) {
1923 case SDLK_LEFT:
1924 if (!NO_MODIFIER(k->mod))
1925 return 0;
1926 ppc--;
1927 break;
1928 case SDLK_RIGHT:
1929 if (!NO_MODIFIER(k->mod))
1930 return 0;
1931 ppc++;
1932 break;
1933 default:
1934 if ((k->mod & (KMOD_CTRL | KMOD_ALT)) == 0) {
1935 ppc = kbd_get_note(k);
1936 if (ppc < 1 || ppc > 120)
1937 return 0;
1938 ppc--;
1939 break;
1940 }
1941 return 0;
1942 }
1943 if ((unsigned int)ppc != ins->pitch_pan_center
1944 && ppc >= 0 && ppc < 120) {
1945 ins->pitch_pan_center = (unsigned int)ppc;
1946 status.flags |= NEED_UPDATE;
1947 }
1948 return 1;
1949 }
1950
pitch_pan_center_draw(void)1951 static void pitch_pan_center_draw(void)
1952 {
1953 char buf[4];
1954 int selected = (ACTIVE_PAGE.selected_widget == 16);
1955 song_instrument_t *ins = song_get_instrument(current_instrument);
1956
1957 draw_text(get_note_string(ins->pitch_pan_center + 1, buf), 54, 45, selected ? 3 : 2, 0);
1958 }
1959
1960 /* --------------------------------------------------------------------------------------------------------- */
1961 /* default key handler (for instrument changing on pgup/pgdn) */
1962
do_ins_save(void * p)1963 static void do_ins_save(void *p)
1964 {
1965 char *ptr = (char *)p;
1966 if (song_save_instrument(current_instrument, ptr))
1967 status_text_flash("Instrument saved (instrument %d)", current_instrument);
1968 else
1969 status_text_flash("Error: Instrument %d NOT saved! (No Filename?)", current_instrument);
1970 free(ptr);
1971 }
1972
instrument_save(void)1973 static void instrument_save(void)
1974 {
1975 song_instrument_t *ins = song_get_instrument(current_instrument);
1976 char *ptr = (char *) dmoz_path_concat(cfg_dir_instruments, ins->filename);
1977 struct stat buf;
1978
1979 if (stat(ptr, &buf) == 0) {
1980 if (S_ISDIR(buf.st_mode)) {
1981 status_text_flash("%s is a directory", ins->filename);
1982 return;
1983 } else if (S_ISREG(buf.st_mode)) {
1984 dialog_create(DIALOG_OK_CANCEL,
1985 "Overwrite file?", do_ins_save,
1986 free, 1, ptr);
1987 return;
1988 } else {
1989 status_text_flash("%s is not a regular file", ins->filename);
1990 return;
1991 }
1992 }
1993 if (song_save_instrument(current_instrument, ptr))
1994 status_text_flash("Instrument saved (instrument %d)", current_instrument);
1995 else
1996 status_text_flash("Error: Instrument %d NOT saved! (No Filename?)", current_instrument);
1997 free(ptr);
1998 }
1999
do_delete_inst(UNUSED void * ign)2000 static void do_delete_inst(UNUSED void *ign)
2001 {
2002 song_delete_instrument(current_instrument, 0);
2003 }
2004
do_delete_inst_preserve(UNUSED void * ign)2005 static void do_delete_inst_preserve(UNUSED void *ign)
2006 {
2007 song_delete_instrument(current_instrument, 1);
2008 }
2009
instrument_list_handle_alt_key(struct key_event * k)2010 static void instrument_list_handle_alt_key(struct key_event *k)
2011 {
2012 /* song_instrument_t *ins = song_get_instrument(current_instrument); */
2013
2014 if (k->state == KEY_RELEASE)
2015 return;
2016 switch (k->sym) {
2017 case SDLK_n:
2018 song_toggle_multichannel_mode();
2019 return;
2020 case SDLK_o:
2021 instrument_save();
2022 return;
2023 case SDLK_r:
2024 smpprompt_create("Replace instrument with:", "Instrument", do_replace_instrument);
2025 return;
2026 case SDLK_s:
2027 // extra space to align the text like IT
2028 smpprompt_create("Swap instrument with: ", "Instrument", do_swap_instrument);
2029 return;
2030 case SDLK_x:
2031 smpprompt_create("Exchange instrument with:", "Instrument", do_exchange_instrument);
2032 return;
2033 case SDLK_p:
2034 smpprompt_create("Copy instrument:", "Instrument", do_copy_instrument);
2035 return;
2036 case SDLK_w:
2037 song_wipe_instrument(current_instrument);
2038 break;
2039 case SDLK_d:
2040 if (k->mod & KMOD_SHIFT) {
2041 dialog_create(DIALOG_OK_CANCEL,
2042 "Delete Instrument? (preserve shared samples)",
2043 do_delete_inst_preserve, NULL, 1, NULL);
2044 } else {
2045 dialog_create(DIALOG_OK_CANCEL,
2046 "Delete Instrument?",
2047 do_delete_inst, NULL, 1, NULL);
2048 }
2049 return;
2050 default:
2051 return;
2052 }
2053
2054 status.flags |= NEED_UPDATE;
2055 }
2056
instrument_list_pre_handle_key(struct key_event * k)2057 static int instrument_list_pre_handle_key(struct key_event * k)
2058 {
2059 // Only handle plain F4 key when no dialog is active.
2060 if (status.dialog_type != DIALOG_NONE || k->sym != SDLK_F4 || (k->mod & (KMOD_CTRL | KMOD_ALT)))
2061 return 0;
2062 if (k->state == KEY_RELEASE)
2063 return 1;
2064
2065 if (song_is_instrument_mode()) {
2066 int csamp = sample_get_current();
2067 sample_synchronize_to_instrument();
2068 if (csamp != sample_get_current())
2069 return 0;
2070 }
2071
2072 if (k->mod & KMOD_SHIFT) {
2073 switch (status.current_page) {
2074 default:
2075 case PAGE_INSTRUMENT_LIST_VOLUME: set_subpage(PAGE_INSTRUMENT_LIST_GENERAL); break;
2076 case PAGE_INSTRUMENT_LIST_PANNING: set_subpage(PAGE_INSTRUMENT_LIST_VOLUME); break;
2077 case PAGE_INSTRUMENT_LIST_PITCH: set_subpage(PAGE_INSTRUMENT_LIST_PANNING); break;
2078 case PAGE_INSTRUMENT_LIST_GENERAL: set_subpage(PAGE_INSTRUMENT_LIST_PITCH); break;
2079 }
2080 } else {
2081 switch (status.current_page) {
2082 default:
2083 case PAGE_INSTRUMENT_LIST_PITCH: set_subpage(PAGE_INSTRUMENT_LIST_GENERAL); break;
2084 case PAGE_INSTRUMENT_LIST_GENERAL: set_subpage(PAGE_INSTRUMENT_LIST_VOLUME); break;
2085 case PAGE_INSTRUMENT_LIST_VOLUME: set_subpage(PAGE_INSTRUMENT_LIST_PANNING); break;
2086 case PAGE_INSTRUMENT_LIST_PANNING: set_subpage(PAGE_INSTRUMENT_LIST_PITCH); break;
2087 }
2088 }
2089 return 1;
2090 }
instrument_list_handle_key(struct key_event * k)2091 static void instrument_list_handle_key(struct key_event * k)
2092 {
2093 switch (k->sym) {
2094 case SDLK_COMMA:
2095 if (NO_MODIFIER(k->mod)) {
2096 if (!(status.flags & CLASSIC_MODE)
2097 && ACTIVE_PAGE.selected_widget == 5) return;
2098 }
2099 case SDLK_LESS:
2100 if (k->state == KEY_RELEASE)
2101 return;
2102 song_change_current_play_channel(-1, 0);
2103 return;
2104 case SDLK_PERIOD:
2105 if (NO_MODIFIER(k->mod)) {
2106 if (!(status.flags & CLASSIC_MODE)
2107 && ACTIVE_PAGE.selected_widget == 5) return;
2108 }
2109 case SDLK_GREATER:
2110 if (k->state == KEY_RELEASE)
2111 return;
2112 song_change_current_play_channel(1, 0);
2113 return;
2114
2115 case SDLK_PAGEUP:
2116 if (k->state == KEY_RELEASE)
2117 return;
2118 instrument_set(current_instrument - 1);
2119 break;
2120 case SDLK_PAGEDOWN:
2121 if (k->state == KEY_RELEASE)
2122 return;
2123 instrument_set(current_instrument + 1);
2124 break;
2125 case SDLK_ESCAPE:
2126 if ((k->mod & KMOD_SHIFT) || instrument_cursor_pos < 25) {
2127 if (k->state == KEY_RELEASE)
2128 return;
2129 instrument_cursor_pos = 25;
2130 get_page_widgets()->accept_text = 0;
2131 change_focus_to(0);
2132 status.flags |= NEED_UPDATE;
2133 return;
2134 }
2135 return;
2136 default:
2137 if (k->mod & (KMOD_ALT)) {
2138 instrument_list_handle_alt_key(k);
2139 } else {
2140 int n, v;
2141
2142 if (k->midi_note > -1) {
2143 n = k->midi_note;
2144 if (k->midi_volume > -1) {
2145 v = k->midi_volume / 2;
2146 } else {
2147 v = 64;
2148 }
2149 } else {
2150 v = 64;
2151 n = kbd_get_note(k);
2152 if (n <= 0 || n > 120)
2153 return;
2154 }
2155
2156 if (k->state == KEY_RELEASE) {
2157 song_keyup(0, current_instrument, n);
2158 status.last_keysym = 0;
2159 } else if (!k->is_repeat) {
2160 song_keydown(KEYJAZZ_NOINST, current_instrument, n, v, KEYJAZZ_CHAN_CURRENT);
2161 }
2162 last_note = n;
2163 }
2164 return;
2165 }
2166 }
2167
2168 /* --------------------------------------------------------------------- */
2169
set_subpage(int page)2170 static void set_subpage(int page)
2171 {
2172 int widget = ACTIVE_PAGE.selected_widget;
2173 int b = 1;
2174 switch (page) {
2175 case PAGE_INSTRUMENT_LIST_GENERAL: b = 1; break;
2176 case PAGE_INSTRUMENT_LIST_VOLUME: b = 2; break;
2177 case PAGE_INSTRUMENT_LIST_PANNING: b = 3; break;
2178 case PAGE_INSTRUMENT_LIST_PITCH: b = 4; break;
2179 default: return;
2180 };
2181 togglebutton_set(pages[page].widgets, b, 0);
2182 set_page(page);
2183 if (widget >= ACTIVE_PAGE.total_widgets)
2184 widget = ACTIVE_PAGE.total_widgets - 1;
2185 ACTIVE_PAGE.selected_widget = widget;
2186 instrument_list_subpage = page;
2187 status.flags |= NEED_UPDATE;
2188 }
2189
change_subpage(void)2190 static void change_subpage(void)
2191 {
2192 int widget = ACTIVE_PAGE.selected_widget;
2193 int p[] = {
2194 PAGE_INSTRUMENT_LIST_GENERAL,
2195 PAGE_INSTRUMENT_LIST_VOLUME,
2196 PAGE_INSTRUMENT_LIST_PANNING,
2197 PAGE_INSTRUMENT_LIST_PITCH,
2198 };
2199 set_subpage(p[CLAMP(widget - 1, 0, 3)]);
2200 }
2201
2202 /* --------------------------------------------------------------------- */
2203 /* predraw hooks... */
2204
instrument_list_general_predraw_hook(void)2205 static void instrument_list_general_predraw_hook(void)
2206 {
2207 song_instrument_t *ins = song_get_instrument(current_instrument);
2208
2209 togglebutton_set(widgets_general, 6 + (ins->nna % 4), 0);
2210 togglebutton_set(widgets_general, 10 + (ins->dct % 4), 0);
2211 togglebutton_set(widgets_general, 14 + (ins->dca % 3), 0);
2212
2213 widgets_general[17].d.textentry.text = ins->filename;
2214 }
2215
instrument_list_volume_predraw_hook(void)2216 static void instrument_list_volume_predraw_hook(void)
2217 {
2218 song_instrument_t *ins = song_get_instrument(current_instrument);
2219
2220 widgets_volume[6].d.toggle.state = !!(ins->flags & ENV_VOLUME);
2221 widgets_volume[7].d.toggle.state = !!(ins->flags & ENV_VOLCARRY);
2222 widgets_volume[8].d.toggle.state = !!(ins->flags & ENV_VOLLOOP);
2223 widgets_volume[11].d.toggle.state = !!(ins->flags & ENV_VOLSUSTAIN);
2224
2225 /* FIXME: this is the wrong place for this.
2226 ... and it's probably not even right -- how does Impulse Tracker handle loop constraints?
2227 See below for panning/pitch envelopes; same deal there. */
2228 if (ins->vol_env.loop_start > ins->vol_env.loop_end)
2229 ins->vol_env.loop_end = ins->vol_env.loop_start;
2230 if (ins->vol_env.sustain_start > ins->vol_env.sustain_end)
2231 ins->vol_env.sustain_end = ins->vol_env.sustain_start;
2232
2233 widgets_volume[9].d.numentry.max = ins->vol_env.nodes - 1;
2234 widgets_volume[10].d.numentry.max = ins->vol_env.nodes - 1;
2235 widgets_volume[12].d.numentry.max = ins->vol_env.nodes - 1;
2236 widgets_volume[13].d.numentry.max = ins->vol_env.nodes - 1;
2237
2238 widgets_volume[9].d.numentry.value = ins->vol_env.loop_start;
2239 widgets_volume[10].d.numentry.value = ins->vol_env.loop_end;
2240 widgets_volume[12].d.numentry.value = ins->vol_env.sustain_start;
2241 widgets_volume[13].d.numentry.value = ins->vol_env.sustain_end;
2242
2243 /* current_song hack: shifting values all over the place here, ugh */
2244 widgets_volume[14].d.thumbbar.value = ins->global_volume;
2245 widgets_volume[15].d.thumbbar.value = ins->fadeout >> 5;
2246 widgets_volume[16].d.thumbbar.value = ins->vol_swing;
2247 }
2248
instrument_list_panning_predraw_hook(void)2249 static void instrument_list_panning_predraw_hook(void)
2250 {
2251 song_instrument_t *ins = song_get_instrument(current_instrument);
2252
2253 widgets_panning[6].d.toggle.state = !!(ins->flags & ENV_PANNING);
2254 widgets_panning[7].d.toggle.state = !!(ins->flags & ENV_PANCARRY);
2255 widgets_panning[8].d.toggle.state = !!(ins->flags & ENV_PANLOOP);
2256 widgets_panning[11].d.toggle.state = !!(ins->flags & ENV_PANSUSTAIN);
2257
2258 if (ins->pan_env.loop_start > ins->pan_env.loop_end)
2259 ins->pan_env.loop_end = ins->pan_env.loop_start;
2260 if (ins->pan_env.sustain_start > ins->pan_env.sustain_end)
2261 ins->pan_env.sustain_end = ins->pan_env.sustain_start;
2262
2263 widgets_panning[9].d.numentry.max = ins->pan_env.nodes - 1;
2264 widgets_panning[10].d.numentry.max = ins->pan_env.nodes - 1;
2265 widgets_panning[12].d.numentry.max = ins->pan_env.nodes - 1;
2266 widgets_panning[13].d.numentry.max = ins->pan_env.nodes - 1;
2267
2268 widgets_panning[9].d.numentry.value = ins->pan_env.loop_start;
2269 widgets_panning[10].d.numentry.value = ins->pan_env.loop_end;
2270 widgets_panning[12].d.numentry.value = ins->pan_env.sustain_start;
2271 widgets_panning[13].d.numentry.value = ins->pan_env.sustain_end;
2272
2273 widgets_panning[14].d.toggle.state = !!(ins->flags & ENV_SETPANNING);
2274 widgets_panning[15].d.thumbbar.value = ins->panning >> 2;
2275 /* (widgets_panning[16] is the pitch-pan center) */
2276 widgets_panning[17].d.thumbbar.value = ins->pitch_pan_separation;
2277 widgets_panning[18].d.thumbbar.value = ins->pan_swing;
2278 }
2279
instrument_list_pitch_predraw_hook(void)2280 static void instrument_list_pitch_predraw_hook(void)
2281 {
2282 song_instrument_t *ins = song_get_instrument(current_instrument);
2283
2284 widgets_pitch[6].d.menutoggle.state = ((ins->flags & ENV_PITCH)
2285 ? ((ins->flags & ENV_FILTER)
2286 ? 2 : 1) : 0);
2287 widgets_pitch[7].d.toggle.state = !!(ins->flags & ENV_PITCHCARRY);
2288 widgets_pitch[8].d.toggle.state = !!(ins->flags & ENV_PITCHLOOP);
2289 widgets_pitch[11].d.toggle.state = !!(ins->flags & ENV_PITCHSUSTAIN);
2290
2291 if (ins->pitch_env.loop_start > ins->pitch_env.loop_end)
2292 ins->pitch_env.loop_end = ins->pitch_env.loop_start;
2293 if (ins->pitch_env.sustain_start > ins->pitch_env.sustain_end)
2294 ins->pitch_env.sustain_end = ins->pitch_env.sustain_start;
2295
2296 widgets_pitch[9].d.numentry.max = ins->pitch_env.nodes - 1;
2297 widgets_pitch[10].d.numentry.max = ins->pitch_env.nodes - 1;
2298 widgets_pitch[12].d.numentry.max = ins->pitch_env.nodes - 1;
2299 widgets_pitch[13].d.numentry.max = ins->pitch_env.nodes - 1;
2300
2301 widgets_pitch[9].d.numentry.value = ins->pitch_env.loop_start;
2302 widgets_pitch[10].d.numentry.value = ins->pitch_env.loop_end;
2303 widgets_pitch[12].d.numentry.value = ins->pitch_env.sustain_start;
2304 widgets_pitch[13].d.numentry.value = ins->pitch_env.sustain_end;
2305
2306 if (ins->ifc & 0x80)
2307 widgets_pitch[14].d.thumbbar.value = ins->ifc & 0x7f;
2308 else
2309 widgets_pitch[14].d.thumbbar.value = -1;
2310 if (ins->ifr & 0x80)
2311 widgets_pitch[15].d.thumbbar.value = ins->ifr & 0x7f;
2312 else
2313 widgets_pitch[15].d.thumbbar.value = -1;
2314
2315 /* printf("ins%02d: ch%04d pgm%04d bank%06d drum%04d\n", current_instrument,
2316 ins->midi_channel, ins->midi_program, ins->midi_bank, ins->midi_drum_key); */
2317 widgets_pitch[16].d.bitset.value = ins->midi_channel_mask;
2318 widgets_pitch[17].d.thumbbar.value = (signed char) ins->midi_program;
2319 widgets_pitch[18].d.thumbbar.value = (signed char) (ins->midi_bank & 0xff);
2320 widgets_pitch[19].d.thumbbar.value = (signed char) (ins->midi_bank >> 8);
2321 /* what is midi_drum_key for? */
2322 }
2323
2324 /* --------------------------------------------------------------------- */
2325 /* update values in song */
2326
instrument_list_general_update_values(void)2327 static void instrument_list_general_update_values(void)
2328 {
2329 song_instrument_t *ins = song_get_instrument(current_instrument);
2330
2331 status.flags |= SONG_NEEDS_SAVE;
2332 for (ins->nna = 4; ins->nna--;)
2333 if (widgets_general[ins->nna + 6].d.togglebutton.state)
2334 break;
2335 for (ins->dct = 4; ins->dct--;)
2336 if (widgets_general[ins->dct + 10].d.togglebutton.state)
2337 break;
2338 for (ins->dca = 3; ins->dca--;)
2339 if (widgets_general[ins->dca + 14].d.togglebutton.state)
2340 break;
2341 }
2342
update_filename(void)2343 static void update_filename(void)
2344 {
2345 status.flags |= SONG_NEEDS_SAVE;
2346 }
2347
2348 #define CHECK_SET(a,b,c) if (a != b) { a = b; c; }
2349
instrument_list_volume_update_values(void)2350 static void instrument_list_volume_update_values(void)
2351 {
2352 song_instrument_t *ins = song_get_instrument(current_instrument);
2353
2354 status.flags |= SONG_NEEDS_SAVE;
2355 ins->flags &= ~(ENV_VOLUME | ENV_VOLCARRY | ENV_VOLLOOP | ENV_VOLSUSTAIN);
2356 if (widgets_volume[6].d.toggle.state)
2357 ins->flags |= ENV_VOLUME;
2358 if (widgets_volume[7].d.toggle.state)
2359 ins->flags |= ENV_VOLCARRY;
2360 if (widgets_volume[8].d.toggle.state)
2361 ins->flags |= ENV_VOLLOOP;
2362 if (widgets_volume[11].d.toggle.state)
2363 ins->flags |= ENV_VOLSUSTAIN;
2364
2365 CHECK_SET(ins->vol_env.loop_start, widgets_volume[9].d.numentry.value,
2366 ins->flags |= ENV_VOLLOOP);
2367 CHECK_SET(ins->vol_env.loop_end, widgets_volume[10].d.numentry.value,
2368 ins->flags |= ENV_VOLLOOP);
2369 CHECK_SET(ins->vol_env.sustain_start, widgets_volume[12].d.numentry.value,
2370 ins->flags |= ENV_VOLSUSTAIN);
2371 CHECK_SET(ins->vol_env.sustain_end, widgets_volume[13].d.numentry.value,
2372 ins->flags |= ENV_VOLSUSTAIN);
2373
2374 /* more ugly shifts */
2375 ins->global_volume = widgets_volume[14].d.thumbbar.value;
2376 ins->fadeout = widgets_volume[15].d.thumbbar.value << 5;
2377 ins->vol_swing = widgets_volume[16].d.thumbbar.value;
2378
2379 song_update_playing_instrument(current_instrument);
2380 }
2381
instrument_list_panning_update_values(void)2382 static void instrument_list_panning_update_values(void)
2383 {
2384 song_instrument_t *ins = song_get_instrument(current_instrument);
2385 int n;
2386
2387 status.flags |= SONG_NEEDS_SAVE;
2388 ins->flags &= ~(ENV_PANNING | ENV_PANCARRY | ENV_PANLOOP | ENV_PANSUSTAIN | ENV_SETPANNING);
2389 if (widgets_panning[6].d.toggle.state)
2390 ins->flags |= ENV_PANNING;
2391 if (widgets_panning[7].d.toggle.state)
2392 ins->flags |= ENV_PANCARRY;
2393 if (widgets_panning[8].d.toggle.state)
2394 ins->flags |= ENV_PANLOOP;
2395 if (widgets_panning[11].d.toggle.state)
2396 ins->flags |= ENV_PANSUSTAIN;
2397 if (widgets_panning[14].d.toggle.state)
2398 ins->flags |= ENV_SETPANNING;
2399
2400 CHECK_SET(ins->pan_env.loop_start, widgets_panning[9].d.numentry.value,
2401 ins->flags |= ENV_PANLOOP);
2402 CHECK_SET(ins->pan_env.loop_end, widgets_panning[10].d.numentry.value,
2403 ins->flags |= ENV_PANLOOP);
2404 CHECK_SET(ins->pan_env.sustain_start, widgets_panning[12].d.numentry.value,
2405 ins->flags |= ENV_PANSUSTAIN);
2406 CHECK_SET(ins->pan_env.sustain_end, widgets_panning[13].d.numentry.value,
2407 ins->flags |= ENV_PANSUSTAIN);
2408
2409 n = widgets_panning[15].d.thumbbar.value << 2;
2410 if (ins->panning != (unsigned int)n) {
2411 ins->panning = (unsigned int)n;
2412 ins->flags |= ENV_SETPANNING;
2413 }
2414 /* (widgets_panning[16] is the pitch-pan center) */
2415 ins->pitch_pan_separation = widgets_panning[17].d.thumbbar.value;
2416 ins->pan_swing = widgets_panning[18].d.thumbbar.value;
2417
2418 song_update_playing_instrument(current_instrument);
2419 }
2420
instrument_list_pitch_update_values(void)2421 static void instrument_list_pitch_update_values(void)
2422 {
2423 song_instrument_t *ins = song_get_instrument(current_instrument);
2424
2425 status.flags |= SONG_NEEDS_SAVE;
2426 ins->flags &= ~(ENV_PITCH | ENV_PITCHCARRY | ENV_PITCHLOOP | ENV_PITCHSUSTAIN | ENV_FILTER);
2427
2428 switch (widgets_pitch[6].d.menutoggle.state) {
2429 case 2: ins->flags |= ENV_FILTER;
2430 case 1: ins->flags |= ENV_PITCH;
2431 }
2432
2433 if (widgets_pitch[6].d.menutoggle.state)
2434 ins->flags |= ENV_PITCH;
2435 if (widgets_pitch[7].d.toggle.state)
2436 ins->flags |= ENV_PITCHCARRY;
2437 if (widgets_pitch[8].d.toggle.state)
2438 ins->flags |= ENV_PITCHLOOP;
2439 if (widgets_pitch[11].d.toggle.state)
2440 ins->flags |= ENV_PITCHSUSTAIN;
2441
2442 CHECK_SET(ins->pitch_env.loop_start, widgets_pitch[9].d.numentry.value,
2443 ins->flags |= ENV_PITCHLOOP);
2444 CHECK_SET(ins->pitch_env.loop_end, widgets_pitch[10].d.numentry.value,
2445 ins->flags |= ENV_PITCHLOOP);
2446 CHECK_SET(ins->pitch_env.sustain_start, widgets_pitch[12].d.numentry.value,
2447 ins->flags |= ENV_PITCHSUSTAIN);
2448 CHECK_SET(ins->pitch_env.sustain_end, widgets_pitch[13].d.numentry.value,
2449 ins->flags |= ENV_PITCHSUSTAIN);
2450 if (widgets_pitch[14].d.thumbbar.value > -1) {
2451 ins->ifc = widgets_pitch[14].d.thumbbar.value | 0x80;
2452 } else {
2453 ins->ifc = 0x7f;
2454 }
2455 if (widgets_pitch[15].d.thumbbar.value > -1) {
2456 ins->ifr = widgets_pitch[15].d.thumbbar.value | 0x80;
2457 } else {
2458 ins->ifr = 0x7f;
2459 }
2460 ins->midi_channel_mask = widgets_pitch[16].d.bitset.value;
2461 ins->midi_program = widgets_pitch[17].d.thumbbar.value;
2462 ins->midi_bank = ((widgets_pitch[19].d.thumbbar.value << 8)
2463 | (widgets_pitch[18].d.thumbbar.value & 0xff));
2464
2465 song_update_playing_instrument(current_instrument);
2466 }
2467
2468 /* --------------------------------------------------------------------- */
2469 /* draw_const functions */
2470
instrument_list_draw_const(void)2471 static void instrument_list_draw_const(void)
2472 {
2473 draw_box(4, 12, 30, 48, BOX_THICK | BOX_INNER | BOX_INSET);
2474 }
2475
instrument_list_general_draw_const(void)2476 static void instrument_list_general_draw_const(void)
2477 {
2478 int n;
2479
2480 instrument_list_draw_const();
2481
2482 draw_box(31, 15, 42, 48, BOX_THICK | BOX_INNER | BOX_INSET);
2483
2484 /* Kind of a hack, and not really useful, but... :) */
2485 if (status.flags & CLASSIC_MODE) {
2486 draw_box(55, 46, 73, 48, BOX_THICK | BOX_INNER | BOX_INSET);
2487 draw_text(" ", 69, 47, 1, 0);
2488 } else {
2489 draw_box(55, 46, 69, 48, BOX_THICK | BOX_INNER | BOX_INSET);
2490 }
2491
2492 draw_text("New Note Action", 54, 17, 0, 2);
2493 draw_text("Duplicate Check Type & Action", 47, 32, 0, 2);
2494 draw_text("Filename", 47, 47, 0, 2);
2495
2496 for (n = 0; n < 35; n++) {
2497 draw_char(134, 44 + n, 15, 0, 2);
2498 draw_char(134, 44 + n, 30, 0, 2);
2499 draw_char(154, 44 + n, 45, 0, 2);
2500 }
2501 }
2502
instrument_list_volume_draw_const(void)2503 static void instrument_list_volume_draw_const(void)
2504 {
2505 instrument_list_draw_const();
2506
2507 draw_fill_chars(57, 28, 62, 29, 0);
2508 draw_fill_chars(57, 32, 62, 34, 0);
2509 draw_fill_chars(57, 37, 62, 39, 0);
2510
2511 draw_box(31, 17, 77, 26, BOX_THICK | BOX_INNER | BOX_INSET);
2512 draw_box(53, 27, 63, 30, BOX_THICK | BOX_INNER | BOX_INSET);
2513 draw_box(53, 31, 63, 35, BOX_THICK | BOX_INNER | BOX_INSET);
2514 draw_box(53, 36, 63, 40, BOX_THICK | BOX_INNER | BOX_INSET);
2515 draw_box(53, 41, 71, 44, BOX_THICK | BOX_INNER | BOX_INSET);
2516 draw_box(53, 45, 71, 47, BOX_THICK | BOX_INNER | BOX_INSET);
2517
2518 draw_text("Volume Envelope", 38, 28, 0, 2);
2519 draw_text("Carry", 48, 29, 0, 2);
2520 draw_text("Envelope Loop", 40, 32, 0, 2);
2521 draw_text("Loop Begin", 43, 33, 0, 2);
2522 draw_text("Loop End", 45, 34, 0, 2);
2523 draw_text("Sustain Loop", 41, 37, 0, 2);
2524 draw_text("SusLoop Begin", 40, 38, 0, 2);
2525 draw_text("SusLoop End", 42, 39, 0, 2);
2526 draw_text("Global Volume", 40, 42, 0, 2);
2527 draw_text("Fadeout", 46, 43, 0, 2);
2528 draw_text("Volume Swing %", 39, 46, 0, 2);
2529 }
2530
instrument_list_panning_draw_const(void)2531 static void instrument_list_panning_draw_const(void)
2532 {
2533 instrument_list_draw_const();
2534
2535 draw_fill_chars(57, 28, 62, 29, 0);
2536 draw_fill_chars(57, 32, 62, 34, 0);
2537 draw_fill_chars(57, 37, 62, 39, 0);
2538 draw_fill_chars(57, 42, 62, 45, 0);
2539
2540 draw_box(31, 17, 77, 26, BOX_THICK | BOX_INNER | BOX_INSET);
2541 draw_box(53, 27, 63, 30, BOX_THICK | BOX_INNER | BOX_INSET);
2542 draw_box(53, 31, 63, 35, BOX_THICK | BOX_INNER | BOX_INSET);
2543 draw_box(53, 36, 63, 40, BOX_THICK | BOX_INNER | BOX_INSET);
2544 draw_box(53, 41, 63, 48, BOX_THICK | BOX_INNER | BOX_INSET);
2545
2546 draw_text("Panning Envelope", 37, 28, 0, 2);
2547 draw_text("Carry", 48, 29, 0, 2);
2548 draw_text("Envelope Loop", 40, 32, 0, 2);
2549 draw_text("Loop Begin", 43, 33, 0, 2);
2550 draw_text("Loop End", 45, 34, 0, 2);
2551 draw_text("Sustain Loop", 41, 37, 0, 2);
2552 draw_text("SusLoop Begin", 40, 38, 0, 2);
2553 draw_text("SusLoop End", 42, 39, 0, 2);
2554 draw_text("Default Pan", 42, 42, 0, 2);
2555 draw_text("Pan Value", 44, 43, 0, 2);
2556 draw_text("Pitch-Pan Center", 37, 45, 0, 2);
2557 draw_text("Pitch-Pan Separation", 33, 46, 0, 2);
2558 if (status.flags & CLASSIC_MODE) {
2559 /* Hmm. The 's' in swing isn't capitalised. ;) */
2560 draw_text("Pan swing", 44, 47, 0, 2);
2561 } else {
2562 draw_text("Pan Swing", 44, 47, 0, 2);
2563 }
2564
2565 draw_text("\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a", 54, 44, 2, 0);
2566 }
2567
instrument_list_pitch_draw_const(void)2568 static void instrument_list_pitch_draw_const(void)
2569 {
2570 instrument_list_draw_const();
2571
2572 draw_fill_chars(57, 28, 62, 29, 0);
2573 draw_fill_chars(57, 32, 62, 34, 0);
2574 draw_fill_chars(57, 37, 62, 39, 0);
2575
2576 draw_box(31, 17, 77, 26, BOX_THICK | BOX_INNER | BOX_INSET);
2577 draw_box(53, 27, 63, 30, BOX_THICK | BOX_INNER | BOX_INSET);
2578 draw_box(53, 31, 63, 35, BOX_THICK | BOX_INNER | BOX_INSET);
2579 draw_box(53, 36, 63, 40, BOX_THICK | BOX_INNER | BOX_INSET);
2580 draw_box(53, 41, 71, 48, BOX_THICK | BOX_INNER | BOX_INSET);
2581
2582 draw_text("Frequency Envelope", 35, 28, 0, 2);
2583 draw_text("Carry", 48, 29, 0, 2);
2584 draw_text("Envelope Loop", 40, 32, 0, 2);
2585 draw_text("Loop Begin", 43, 33, 0, 2);
2586 draw_text("Loop End", 45, 34, 0, 2);
2587 draw_text("Sustain Loop", 41, 37, 0, 2);
2588 draw_text("SusLoop Begin", 40, 38, 0, 2);
2589 draw_text("SusLoop End", 42, 39, 0, 2);
2590 draw_text("Default Cutoff", 36, 42, 0, 2);
2591 draw_text("Default Resonance", 36, 43, 0, 2);
2592 draw_text("MIDI Channels", 36, 44, 0, 2);
2593 draw_text("MIDI Program", 36, 45, 0, 2);
2594 draw_text("MIDI Bank Low", 36, 46, 0, 2);
2595 draw_text("MIDI Bank High", 36, 47, 0, 2);
2596 }
2597
2598 /* --------------------------------------------------------------------- */
2599 /* load_page functions */
2600
_load_page_common(struct page * page,struct widget * page_widgets)2601 static void _load_page_common(struct page *page, struct widget *page_widgets)
2602 {
2603 int i;
2604
2605 memset(saved_env, 0, sizeof(saved_env));
2606 for (i = 0; i < 10; i++) {
2607 saved_env[i].nodes = 2;
2608 saved_env[i].ticks[0] = 0;
2609 saved_env[i].ticks[1] = 100;
2610 saved_env[i].values[0] = 32;
2611 saved_env[i].values[1] = 32;
2612 }
2613 vgamem_ovl_alloc(&env_overlay);
2614
2615 page->title = "Instrument List (F4)";
2616 page->pre_handle_key = instrument_list_pre_handle_key;
2617 page->handle_key = instrument_list_handle_key;
2618 page->widgets = page_widgets;
2619 page->help_index = HELP_INSTRUMENT_LIST;
2620 page->set_page = instrument_list_reposition;
2621
2622 /* the first five widgets are the same for all four pages. */
2623
2624 /* 0 = instrument list */
2625 create_other(page_widgets + 0, 1, instrument_list_handle_key_on_list, instrument_list_draw_list);
2626 page_widgets[0].accept_text = (instrument_cursor_pos == 25 ? 0 : 1);
2627 page_widgets[0].x = 5;
2628 page_widgets[0].y = 13;
2629 page_widgets[0].width = 24;
2630 page_widgets[0].height = 34;
2631
2632 /* 1-4 = subpage switches */
2633 create_togglebutton(page_widgets + 1, 32, 13, 7, 1, 5, 0, 2, 2, change_subpage, "General",
2634 1, subpage_switches_group);
2635 create_togglebutton(page_widgets + 2, 44, 13, 7, 2, 5, 1, 3, 3, change_subpage, "Volume",
2636 1, subpage_switches_group);
2637 create_togglebutton(page_widgets + 3, 56, 13, 7, 3, 5, 2, 4, 4, change_subpage, "Panning",
2638 1, subpage_switches_group);
2639 create_togglebutton(page_widgets + 4, 68, 13, 7, 4, 5, 3, 0, 0, change_subpage, "Pitch",
2640 2, subpage_switches_group);
2641 }
2642
instrument_list_general_load_page(struct page * page)2643 void instrument_list_general_load_page(struct page *page)
2644 {
2645 _load_page_common(page, widgets_general);
2646
2647 page->draw_const = instrument_list_general_draw_const;
2648 page->predraw_hook = instrument_list_general_predraw_hook;
2649 page->total_widgets = 18;
2650
2651 /* special case stuff */
2652 widgets_general[1].d.togglebutton.state = 1;
2653 widgets_general[2].next.down = widgets_general[3].next.down = widgets_general[4].next.down = 6;
2654
2655 /* 5 = note trans table */
2656 create_other(widgets_general + 5, 6, note_trans_handle_key, note_trans_draw);
2657 widgets_general[5].x = 32;
2658 widgets_general[5].y = 16;
2659 widgets_general[5].width = 9;
2660 widgets_general[5].height = 31;
2661
2662 /* 6-9 = nna toggles */
2663 create_togglebutton(widgets_general + 6, 46, 19, 29, 2, 7, 5, 0, 0,
2664 instrument_list_general_update_values,
2665 "Note Cut", 2, nna_group);
2666 create_togglebutton(widgets_general + 7, 46, 22, 29, 6, 8, 5, 0, 0,
2667 instrument_list_general_update_values,
2668 "Continue", 2, nna_group);
2669 create_togglebutton(widgets_general + 8, 46, 25, 29, 7, 9, 5, 0, 0,
2670 instrument_list_general_update_values,
2671 "Note Off", 2, nna_group);
2672 create_togglebutton(widgets_general + 9, 46, 28, 29, 8, 10, 5, 0, 0,
2673 instrument_list_general_update_values,
2674 "Note Fade", 2, nna_group);
2675
2676 /* 10-13 = dct toggles */
2677 create_togglebutton(widgets_general + 10, 46, 34, 12, 9, 11, 5, 14,
2678 14, instrument_list_general_update_values,
2679 "Disabled", 2, dct_group);
2680 create_togglebutton(widgets_general + 11, 46, 37, 12, 10, 12, 5, 15,
2681 15, instrument_list_general_update_values,
2682 "Note", 2, dct_group);
2683 create_togglebutton(widgets_general + 12, 46, 40, 12, 11, 13, 5, 16,
2684 16, instrument_list_general_update_values,
2685 "Sample", 2, dct_group);
2686 create_togglebutton(widgets_general + 13, 46, 43, 12, 12, 17, 5, 13,
2687 13, instrument_list_general_update_values,
2688 "Instrument", 2, dct_group);
2689 /* 14-16 = dca toggles */
2690 create_togglebutton(widgets_general + 14, 62, 34, 13, 9, 15, 10, 0,
2691 0, instrument_list_general_update_values,
2692 "Note Cut", 2, dca_group);
2693 create_togglebutton(widgets_general + 15, 62, 37, 13, 14, 16, 11, 0,
2694 0, instrument_list_general_update_values,
2695 "Note Off", 2, dca_group);
2696 create_togglebutton(widgets_general + 16, 62, 40, 13, 15, 17, 12, 0,
2697 0, instrument_list_general_update_values,
2698 "Note Fade", 2, dca_group);
2699 /* 17 = filename */
2700 /* impulse tracker has a 17-char-wide box for the filename for
2701 * some reason, though it still limits the actual text to 12
2702 * characters. go figure... */
2703 create_textentry(widgets_general + 17, 56, 47, 13, 13, 17, 0, update_filename,
2704 NULL, 12);
2705 }
2706
_fixup_mouse_instpage_volume(struct key_event * k)2707 static int _fixup_mouse_instpage_volume(struct key_event *k)
2708 {
2709 song_instrument_t *ins = song_get_instrument(current_instrument);
2710 if (envelope_mouse_edit && ins) {
2711 if (_env_handle_mouse(k, &ins->vol_env, ¤t_node_vol)) {
2712 ins->flags |= ENV_VOLUME;
2713 return 1;
2714 }
2715 }
2716 if ((k->sym == SDLK_l || k->sym == SDLK_b) && (k->mod & KMOD_ALT)) {
2717 return _env_handle_key_viewmode(k, &ins->vol_env, ¤t_node_vol, ENV_VOLUME);
2718 }
2719 return instrument_list_pre_handle_key(k);
2720 }
2721
instrument_list_volume_load_page(struct page * page)2722 void instrument_list_volume_load_page(struct page *page)
2723 {
2724 _load_page_common(page, widgets_volume);
2725
2726 page->pre_handle_key = _fixup_mouse_instpage_volume;
2727 page->draw_const = instrument_list_volume_draw_const;
2728 page->predraw_hook = instrument_list_volume_predraw_hook;
2729 page->total_widgets = 17;
2730
2731 /* 5 = volume envelope */
2732 create_other(widgets_volume + 5, 0, volume_envelope_handle_key, volume_envelope_draw);
2733 widgets_volume[5].x = 32;
2734 widgets_volume[5].y = 18;
2735 widgets_volume[5].width = 45;
2736 widgets_volume[5].height = 8;
2737
2738 /* 6-7 = envelope switches */
2739 create_toggle(widgets_volume + 6, 54, 28, 5, 7, 0, 0, 0,
2740 instrument_list_volume_update_values);
2741 create_toggle(widgets_volume + 7, 54, 29, 6, 8, 0, 0, 0,
2742 instrument_list_volume_update_values);
2743
2744 /* 8-10 envelope loop settings */
2745 create_toggle(widgets_volume + 8, 54, 32, 7, 9, 0, 0, 0,
2746 instrument_list_volume_update_values);
2747 create_numentry(widgets_volume + 9, 54, 33, 3, 8, 10, 0,
2748 instrument_list_volume_update_values, 0, 1,
2749 numentry_cursor_pos + 0);
2750 create_numentry(widgets_volume + 10, 54, 34, 3, 9, 11, 0,
2751 instrument_list_volume_update_values, 0, 1,
2752 numentry_cursor_pos + 0);
2753
2754 /* 11-13 = susloop settings */
2755 create_toggle(widgets_volume + 11, 54, 37, 10, 12, 0, 0, 0,
2756 instrument_list_volume_update_values);
2757 create_numentry(widgets_volume + 12, 54, 38, 3, 11, 13, 0,
2758 instrument_list_volume_update_values, 0, 1,
2759 numentry_cursor_pos + 0);
2760 create_numentry(widgets_volume + 13, 54, 39, 3, 12, 14, 0,
2761 instrument_list_volume_update_values, 0, 1,
2762 numentry_cursor_pos + 0);
2763
2764 /* 14-16 = volume thumbbars */
2765 create_thumbbar(widgets_volume + 14, 54, 42, 17, 13, 15, 0,
2766 instrument_list_volume_update_values, 0, 128);
2767 create_thumbbar(widgets_volume + 15, 54, 43, 17, 14, 16, 0,
2768 instrument_list_volume_update_values, 0, 256);
2769 create_thumbbar(widgets_volume + 16, 54, 46, 17, 15, 16, 0,
2770 instrument_list_volume_update_values, 0, 100);
2771 }
2772
_fixup_mouse_instpage_panning(struct key_event * k)2773 static int _fixup_mouse_instpage_panning(struct key_event *k)
2774 {
2775 song_instrument_t *ins = song_get_instrument(current_instrument);
2776 if (envelope_mouse_edit && ins) {
2777 if (_env_handle_mouse(k, &ins->pan_env, ¤t_node_pan)) {
2778 ins->flags |= ENV_PANNING;
2779 return 1;
2780 }
2781 }
2782 if ((k->sym == SDLK_l || k->sym == SDLK_b) && (k->mod & KMOD_ALT)) {
2783 return _env_handle_key_viewmode(k, &ins->pan_env, ¤t_node_pan, ENV_PANNING);
2784 }
2785 return instrument_list_pre_handle_key(k);
2786 }
instrument_list_panning_load_page(struct page * page)2787 void instrument_list_panning_load_page(struct page *page)
2788 {
2789 _load_page_common(page, widgets_panning);
2790
2791 page->pre_handle_key = _fixup_mouse_instpage_panning;
2792 page->draw_const = instrument_list_panning_draw_const;
2793 page->predraw_hook = instrument_list_panning_predraw_hook;
2794 page->total_widgets = 19;
2795
2796 /* 5 = panning envelope */
2797 create_other(widgets_panning + 5, 0, panning_envelope_handle_key, panning_envelope_draw);
2798 widgets_panning[5].x = 32;
2799 widgets_panning[5].y = 18;
2800 widgets_panning[5].width = 45;
2801 widgets_panning[5].height = 8;
2802
2803 /* 6-7 = envelope switches */
2804 create_toggle(widgets_panning + 6, 54, 28, 5, 7, 0, 0, 0,
2805 instrument_list_panning_update_values);
2806 create_toggle(widgets_panning + 7, 54, 29, 6, 8, 0, 0, 0,
2807 instrument_list_panning_update_values);
2808
2809 /* 8-10 envelope loop settings */
2810 create_toggle(widgets_panning + 8, 54, 32, 7, 9, 0, 0, 0,
2811 instrument_list_panning_update_values);
2812 create_numentry(widgets_panning + 9, 54, 33, 3, 8, 10, 0,
2813 instrument_list_panning_update_values, 0, 1,
2814 numentry_cursor_pos + 1);
2815 create_numentry(widgets_panning + 10, 54, 34, 3, 9, 11, 0,
2816 instrument_list_panning_update_values, 0, 1,
2817 numentry_cursor_pos + 1);
2818
2819 /* 11-13 = susloop settings */
2820 create_toggle(widgets_panning + 11, 54, 37, 10, 12, 0, 0, 0,
2821 instrument_list_panning_update_values);
2822 create_numentry(widgets_panning + 12, 54, 38, 3, 11, 13, 0,
2823 instrument_list_panning_update_values, 0, 1,
2824 numentry_cursor_pos + 1);
2825 create_numentry(widgets_panning + 13, 54, 39, 3, 12, 14, 0,
2826 instrument_list_panning_update_values, 0, 1,
2827 numentry_cursor_pos + 1);
2828
2829 /* 14-15 = default panning */
2830 create_toggle(widgets_panning + 14, 54, 42, 13, 15, 0, 0, 0,
2831 instrument_list_panning_update_values);
2832 create_thumbbar(widgets_panning + 15, 54, 43, 9, 14, 16, 0,
2833 instrument_list_panning_update_values, 0, 64);
2834
2835 /* 16 = pitch-pan center */
2836 create_other(widgets_panning + 16, 0, pitch_pan_center_handle_key, pitch_pan_center_draw);
2837 widgets_panning[16].next.up = 15;
2838 widgets_panning[16].next.down = 17;
2839
2840 /* 17-18 = other panning stuff */
2841 create_thumbbar(widgets_panning + 17, 54, 46, 9, 16, 18, 0,
2842 instrument_list_panning_update_values, -32, 32);
2843 create_thumbbar(widgets_panning + 18, 54, 47, 9, 17, 18, 0,
2844 instrument_list_panning_update_values, 0, 64);
2845 }
2846
_fixup_mouse_instpage_pitch(struct key_event * k)2847 static int _fixup_mouse_instpage_pitch(struct key_event *k)
2848 {
2849 song_instrument_t *ins = song_get_instrument(current_instrument);
2850 if (envelope_mouse_edit && ins) {
2851 if (_env_handle_mouse(k, &ins->pitch_env, ¤t_node_pitch)) {
2852 ins->flags |= ENV_PITCH;
2853 return 1;
2854 }
2855 }
2856 if ((k->sym == SDLK_l || k->sym == SDLK_b) && (k->mod & KMOD_ALT)) {
2857 return _env_handle_key_viewmode(k, &ins->pitch_env, ¤t_node_pitch, ENV_PITCH);
2858 }
2859 return instrument_list_pre_handle_key(k);
2860 }
instrument_list_pitch_load_page(struct page * page)2861 void instrument_list_pitch_load_page(struct page *page)
2862 {
2863 static int midi_channel_selection_cursor_position = 0;
2864
2865 _load_page_common(page, widgets_pitch);
2866
2867 page->pre_handle_key = _fixup_mouse_instpage_pitch;
2868 page->draw_const = instrument_list_pitch_draw_const;
2869 page->predraw_hook = instrument_list_pitch_predraw_hook;
2870 page->total_widgets = 20;
2871
2872 /* 5 = pitch envelope */
2873 create_other(widgets_pitch + 5, 0, pitch_envelope_handle_key, pitch_envelope_draw);
2874 widgets_pitch[5].x = 32;
2875 widgets_pitch[5].y = 18;
2876 widgets_pitch[5].width = 45;
2877 widgets_pitch[5].height = 8;
2878
2879 /* 6-7 = envelope switches */
2880 create_menutoggle(widgets_pitch + 6, 54, 28, 5, 7, 0, 0, 0,
2881 instrument_list_pitch_update_values, pitch_envelope_states);
2882 create_toggle(widgets_pitch + 7, 54, 29, 6, 8, 0, 0, 0,
2883 instrument_list_pitch_update_values);
2884
2885 /* 8-10 envelope loop settings */
2886 create_toggle(widgets_pitch + 8, 54, 32, 7, 9, 0, 0, 0,
2887 instrument_list_pitch_update_values);
2888 create_numentry(widgets_pitch + 9, 54, 33, 3, 8, 10, 0,
2889 instrument_list_pitch_update_values, 0, 1,
2890 numentry_cursor_pos + 2);
2891 create_numentry(widgets_pitch + 10, 54, 34, 3, 9, 11, 0,
2892 instrument_list_pitch_update_values, 0, 1,
2893 numentry_cursor_pos + 2);
2894
2895 /* 11-13 = susloop settings */
2896 create_toggle(widgets_pitch + 11, 54, 37, 10, 12, 0, 0, 0,
2897 instrument_list_pitch_update_values);
2898 create_numentry(widgets_pitch + 12, 54, 38, 3, 11, 13, 0,
2899 instrument_list_pitch_update_values, 0, 1,
2900 numentry_cursor_pos + 2);
2901 create_numentry(widgets_pitch + 13, 54, 39, 3, 12, 14, 0,
2902 instrument_list_pitch_update_values, 0, 1,
2903 numentry_cursor_pos + 2);
2904
2905 /* 14-15 = filter cutoff/resonance */
2906 create_thumbbar(widgets_pitch + 14, 54, 42, 17, 13, 15, 0,
2907 instrument_list_pitch_update_values, -1, 127);
2908 create_thumbbar(widgets_pitch + 15, 54, 43, 17, 14, 16, 0,
2909 instrument_list_pitch_update_values, -1, 127);
2910 widgets_pitch[14].d.thumbbar.text_at_min = "Off";
2911 widgets_pitch[15].d.thumbbar.text_at_min = "Off";
2912
2913 /* 16-19 = midi crap */
2914 create_bitset(widgets_pitch + 16, 54, 44, 17, 15, 17, 0,
2915 instrument_list_pitch_update_values,
2916 17,
2917 " 1 2 3 4 5 6 7 8 9P\0""111213141516M\0",
2918 ".\0.\0.\0.\0.\0.\0.\0.\0.\0p\0.\0.\0.\0.\0.\0.\0m\0",
2919 &midi_channel_selection_cursor_position
2920 );
2921 widgets_pitch[16].d.bitset.activation_keys =
2922 "123456789pabcdefm";
2923
2924 create_thumbbar(widgets_pitch + 17, 54, 45, 17, 16, 18, 0,
2925 instrument_list_pitch_update_values, -1, 127);
2926 create_thumbbar(widgets_pitch + 18, 54, 46, 17, 17, 19, 0,
2927 instrument_list_pitch_update_values, -1, 127);
2928 create_thumbbar(widgets_pitch + 19, 54, 47, 17, 18, 19, 0,
2929 instrument_list_pitch_update_values, -1, 127);
2930 widgets_pitch[17].d.thumbbar.text_at_min = "Off";
2931 widgets_pitch[18].d.thumbbar.text_at_min = "Off";
2932 widgets_pitch[19].d.thumbbar.text_at_min = "Off";
2933 }
2934
2935