Rev 1675 | Rev 1751 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
134 | tk | 1 | // $Id: seq_ui.c 1713 2013-03-16 21:36:06Z tk $ |
2 | /* |
||
3 | * User Interface Routines |
||
4 | * |
||
5 | * ========================================================================== |
||
6 | * |
||
7 | * Copyright (C) 2008 Thorsten Klose (tk@midibox.org) |
||
8 | * Licensed for personal non-commercial use only. |
||
9 | * All other rights reserved. |
||
10 | * |
||
11 | * ========================================================================== |
||
12 | */ |
||
13 | |||
14 | ///////////////////////////////////////////////////////////////////////////// |
||
15 | // Include files |
||
16 | ///////////////////////////////////////////////////////////////////////////// |
||
17 | |||
272 | tk | 18 | // with this switch, seq_ui.h/seq_ui_pages.inc will create local variables |
19 | #define SEQ_UI_PAGES_INC_LOCAL_VARS 1 |
||
20 | |||
134 | tk | 21 | #include <mios32.h> |
299 | tk | 22 | #include <string.h> |
690 | tk | 23 | #include <blm.h> |
464 | tk | 24 | #include <blm_x.h> |
190 | tk | 25 | #include <seq_midi_out.h> |
26 | #include <seq_bpm.h> |
||
134 | tk | 27 | |
290 | tk | 28 | #include "tasks.h" |
134 | tk | 29 | #include "seq_ui.h" |
728 | tk | 30 | #include "seq_lcd.h" |
31 | #include "seq_lcd_logo.h" |
||
492 | tk | 32 | #include "seq_hwcfg.h" |
134 | tk | 33 | #include "seq_lcd.h" |
34 | #include "seq_led.h" |
||
186 | tk | 35 | #include "seq_midply.h" |
1527 | tk | 36 | #include "seq_mixer.h" |
134 | tk | 37 | #include "seq_core.h" |
399 | tk | 38 | #include "seq_song.h" |
333 | tk | 39 | #include "seq_par.h" |
178 | tk | 40 | #include "seq_layer.h" |
184 | tk | 41 | #include "seq_cc.h" |
1313 | tk | 42 | #include "seq_record.h" |
785 | tk | 43 | #include "seq_midi_sysex.h" |
1336 | tk | 44 | #include "seq_midi_port.h" |
1020 | tk | 45 | #include "seq_blm.h" |
1261 | tk | 46 | |
47 | #include "file.h" |
||
299 | tk | 48 | #include "seq_file.h" |
1281 | tk | 49 | #include "seq_file_t.h" |
690 | tk | 50 | #include "seq_file_hw.h" |
134 | tk | 51 | |
52 | |||
53 | ///////////////////////////////////////////////////////////////////////////// |
||
54 | // Global variables |
||
55 | ///////////////////////////////////////////////////////////////////////////// |
||
56 | |||
159 | tk | 57 | u8 seq_ui_display_update_req; |
58 | u8 seq_ui_display_init_req; |
||
134 | tk | 59 | |
167 | tk | 60 | seq_ui_button_state_t seq_ui_button_state; |
61 | |||
134 | tk | 62 | u8 ui_selected_group; |
484 | tk | 63 | u16 ui_selected_tracks; |
134 | tk | 64 | u8 ui_selected_par_layer; |
65 | u8 ui_selected_trg_layer; |
||
328 | tk | 66 | u8 ui_selected_instrument; |
134 | tk | 67 | u8 ui_selected_step_view; |
68 | u8 ui_selected_step; |
||
168 | tk | 69 | u8 ui_selected_item; |
1319 | tk | 70 | u16 ui_selected_gp_buttons; |
134 | tk | 71 | |
168 | tk | 72 | u8 ui_selected_item; |
134 | tk | 73 | |
240 | tk | 74 | u16 ui_hold_msg_ctr; |
75 | |||
206 | tk | 76 | seq_ui_page_t ui_page; |
272 | tk | 77 | seq_ui_page_t ui_selected_page; |
600 | tk | 78 | seq_ui_page_t ui_stepview_prev_page; |
79 | seq_ui_page_t ui_trglayer_prev_page; |
||
80 | seq_ui_page_t ui_parlayer_prev_page; |
||
206 | tk | 81 | |
173 | tk | 82 | volatile u8 ui_cursor_flash; |
740 | tk | 83 | volatile u8 ui_cursor_flash_overrun_ctr; |
173 | tk | 84 | u16 ui_cursor_flash_ctr; |
134 | tk | 85 | |
316 | tk | 86 | u8 ui_edit_name_cursor; |
87 | u8 ui_edit_preset_num_category; |
||
88 | u8 ui_edit_preset_num_label; |
||
729 | tk | 89 | u8 ui_edit_preset_num_drum; |
316 | tk | 90 | |
193 | tk | 91 | u8 ui_seq_pause; |
92 | |||
1421 | tk | 93 | u8 ui_song_edit_pos; |
94 | |||
634 | tk | 95 | u8 seq_ui_backup_req; |
740 | tk | 96 | u8 seq_ui_format_req; |
974 | tk | 97 | u8 seq_ui_saveall_req; |
625 | tk | 98 | |
1713 | tk | 99 | u8 seq_ui_sent_cc_track; |
100 | |||
744 | tk | 101 | // to display directories via SEQ_UI_SelectListItem() and SEQ_LCD_PrintList() -- see seq_ui_sysex.c as example |
746 | tk | 102 | char ui_global_dir_list[80]; |
634 | tk | 103 | |
1203 | tk | 104 | seq_ui_bookmark_t seq_ui_bookmarks[SEQ_UI_BOOKMARKS_NUM]; |
744 | tk | 105 | |
1349 | tk | 106 | |
134 | tk | 107 | ///////////////////////////////////////////////////////////////////////////// |
108 | // Local variables |
||
109 | ///////////////////////////////////////////////////////////////////////////// |
||
110 | |||
168 | tk | 111 | static s32 (*ui_button_callback)(seq_ui_button_t button, s32 depressed); |
112 | static s32 (*ui_encoder_callback)(seq_ui_encoder_t encoder, s32 incrementer); |
||
173 | tk | 113 | static s32 (*ui_led_callback)(u16 *gp_leds); |
167 | tk | 114 | static s32 (*ui_lcd_callback)(u8 high_prio); |
352 | tk | 115 | static s32 (*ui_exit_callback)(void); |
752 | tk | 116 | static s32 (*ui_delayed_action_callback)(u32 parameter); |
117 | static u32 ui_delayed_action_parameter; |
||
167 | tk | 118 | |
168 | tk | 119 | static u16 ui_gp_leds; |
167 | tk | 120 | |
1040 | tk | 121 | #define UI_MSG_MAX_CHAR 31 |
596 | tk | 122 | static char ui_msg[2][UI_MSG_MAX_CHAR]; |
123 | static u16 ui_msg_ctr; |
||
124 | static seq_ui_msg_type_t ui_msg_type; |
||
299 | tk | 125 | |
740 | tk | 126 | static u16 ui_delayed_action_ctr; |
299 | tk | 127 | |
1203 | tk | 128 | static seq_ui_page_t ui_page_before_bookmark; |
752 | tk | 129 | |
1454 | midilab | 130 | mios32_sys_time_t seq_play_timer; |
752 | tk | 131 | |
1713 | tk | 132 | |
134 | tk | 133 | ///////////////////////////////////////////////////////////////////////////// |
1713 | tk | 134 | // Prototypes |
135 | ///////////////////////////////////////////////////////////////////////////// |
||
136 | static s32 SEQ_UI_Button_StepViewInc(s32 depressed); |
||
137 | static s32 SEQ_UI_Button_StepViewDec(s32 depressed); |
||
138 | |||
139 | |||
140 | ///////////////////////////////////////////////////////////////////////////// |
||
134 | tk | 141 | // Initialisation |
142 | ///////////////////////////////////////////////////////////////////////////// |
||
143 | s32 SEQ_UI_Init(u32 mode) |
||
144 | { |
||
626 | tk | 145 | int i; |
146 | // clear all LEDs |
||
147 | for(i=0; i<SEQ_LED_NUM_SR; ++i) |
||
148 | SEQ_LED_SRSet(i, 0x00); |
||
149 | |||
134 | tk | 150 | // init selection variables |
151 | ui_selected_group = 0; |
||
152 | ui_selected_tracks = (1 << 0); |
||
153 | ui_selected_par_layer = 0; |
||
154 | ui_selected_trg_layer = 0; |
||
328 | tk | 155 | ui_selected_instrument = 0; |
134 | tk | 156 | ui_selected_step_view = 0; |
157 | ui_selected_step = 0; |
||
168 | tk | 158 | ui_selected_item = 0; |
1319 | tk | 159 | ui_selected_gp_buttons = 0; |
134 | tk | 160 | |
240 | tk | 161 | ui_hold_msg_ctr = 0; |
596 | tk | 162 | ui_msg_ctr = 0; |
740 | tk | 163 | ui_delayed_action_ctr = 0; |
240 | tk | 164 | |
740 | tk | 165 | ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0; |
173 | tk | 166 | ui_cursor_flash = 0; |
168 | tk | 167 | |
167 | tk | 168 | seq_ui_button_state.ALL = 0; |
169 | |||
193 | tk | 170 | ui_seq_pause = 0; |
171 | |||
1421 | tk | 172 | ui_song_edit_pos = 0; |
173 | |||
134 | tk | 174 | // visible GP pattern |
175 | ui_gp_leds = 0x0000; |
||
176 | |||
634 | tk | 177 | // misc |
178 | seq_ui_backup_req = 0; |
||
740 | tk | 179 | seq_ui_format_req = 0; |
974 | tk | 180 | seq_ui_saveall_req = 0; |
634 | tk | 181 | |
1713 | tk | 182 | seq_ui_sent_cc_track = 0xff; // invalidate |
183 | |||
167 | tk | 184 | // change to edit page |
185 | ui_page = SEQ_UI_PAGE_NONE; |
||
186 | SEQ_UI_PageSet(SEQ_UI_PAGE_EDIT); |
||
134 | tk | 187 | |
1203 | tk | 188 | // finally init bookmarks |
189 | ui_page_before_bookmark = SEQ_UI_PAGE_EDIT; |
||
190 | for(i=0; i<SEQ_UI_BOOKMARKS_NUM; ++i) { |
||
191 | char buffer[10]; |
||
192 | seq_ui_bookmark_t *bm = (seq_ui_bookmark_t *)&seq_ui_bookmarks[i]; |
||
596 | tk | 193 | |
1203 | tk | 194 | sprintf(buffer, "BM%2d ", i+1); |
195 | memcpy((char *)bm->name, buffer, 6); |
||
196 | bm->enable.ALL = ~0; |
||
197 | bm->flags.LOCKED = 0; |
||
198 | SEQ_UI_Bookmark_Store(i); |
||
199 | } |
||
200 | |||
134 | tk | 201 | return 0; // no error |
202 | } |
||
203 | |||
204 | |||
205 | ///////////////////////////////////////////////////////////////////////////// |
||
178 | tk | 206 | // Inits the speed mode of all encoders |
207 | // Auto mode should be used whenever: |
||
208 | // - the edit screen is entered |
||
209 | // - the group is changed |
||
210 | // - a track is changed |
||
211 | // - a layer is changed |
||
212 | ///////////////////////////////////////////////////////////////////////////// |
||
213 | s32 SEQ_UI_InitEncSpeed(u32 auto_config) |
||
214 | { |
||
215 | mios32_enc_config_t enc_config; |
||
216 | |||
217 | if( auto_config ) { |
||
513 | tk | 218 | |
219 | if( !seq_hwcfg_enc.auto_fast ) |
||
220 | return 0; // auto mode not enabled - ignore auto reconfiguration request |
||
221 | |||
333 | tk | 222 | switch( SEQ_PAR_AssignmentGet(SEQ_UI_VisibleTrackGet(), ui_selected_par_layer) ) { |
223 | case SEQ_PAR_Type_Velocity: |
||
224 | case SEQ_PAR_Type_Length: |
||
225 | case SEQ_PAR_Type_CC: |
||
226 | case SEQ_PAR_Type_PitchBend: |
||
227 | case SEQ_PAR_Type_Probability: |
||
228 | case SEQ_PAR_Type_Delay: |
||
1422 | tk | 229 | case SEQ_PAR_Type_ProgramChange: |
1420 | tk | 230 | seq_ui_button_state.FAST_ENCODERS = 1; |
231 | break; |
||
178 | tk | 232 | |
233 | default: |
||
1420 | tk | 234 | seq_ui_button_state.FAST_ENCODERS = 0; |
178 | tk | 235 | } |
236 | } |
||
237 | |||
238 | // change for datawheel and GP encoders |
||
239 | int enc; |
||
1341 | tk | 240 | for(enc=0; enc<SEQ_HWCFG_NUM_ENCODERS; ++enc) { |
178 | tk | 241 | enc_config = MIOS32_ENC_ConfigGet(enc); |
1121 | tk | 242 | enc_config.cfg.speed = (seq_ui_button_state.FAST_ENCODERS || seq_ui_button_state.FAST2_ENCODERS) ? FAST : NORMAL; |
1341 | tk | 243 | enc_config.cfg.speed_par = |
244 | (enc == 0) ? seq_hwcfg_enc.datawheel_fast_speed |
||
245 | : (enc == 17) ? seq_hwcfg_enc.bpm_fast_speed |
||
246 | : seq_hwcfg_enc.gp_fast_speed; |
||
178 | tk | 247 | MIOS32_ENC_ConfigSet(enc, enc_config); |
248 | } |
||
249 | |||
250 | return 0; // no error |
||
251 | } |
||
252 | |||
253 | |||
254 | ///////////////////////////////////////////////////////////////////////////// |
||
167 | tk | 255 | // Various installation routines for menu page LCD handlers |
256 | ///////////////////////////////////////////////////////////////////////////// |
||
168 | tk | 257 | s32 SEQ_UI_InstallButtonCallback(void *callback) |
167 | tk | 258 | { |
168 | tk | 259 | ui_button_callback = callback; |
167 | tk | 260 | return 0; // no error |
261 | } |
||
262 | |||
168 | tk | 263 | s32 SEQ_UI_InstallEncoderCallback(void *callback) |
167 | tk | 264 | { |
168 | tk | 265 | ui_encoder_callback = callback; |
167 | tk | 266 | return 0; // no error |
267 | } |
||
268 | |||
168 | tk | 269 | s32 SEQ_UI_InstallLEDCallback(void *callback) |
167 | tk | 270 | { |
168 | tk | 271 | ui_led_callback = callback; |
167 | tk | 272 | return 0; // no error |
273 | } |
||
274 | |||
168 | tk | 275 | s32 SEQ_UI_InstallLCDCallback(void *callback) |
167 | tk | 276 | { |
277 | ui_lcd_callback = callback; |
||
278 | return 0; // no error |
||
279 | } |
||
280 | |||
352 | tk | 281 | s32 SEQ_UI_InstallExitCallback(void *callback) |
282 | { |
||
283 | ui_exit_callback = callback; |
||
284 | return 0; // no error |
||
285 | } |
||
167 | tk | 286 | |
352 | tk | 287 | |
752 | tk | 288 | s32 SEQ_UI_InstallDelayedActionCallback(void *callback, u16 delay_mS, u32 parameter) |
740 | tk | 289 | { |
752 | tk | 290 | // must be atomic |
291 | MIOS32_IRQ_Disable(); |
||
292 | ui_delayed_action_parameter = parameter; |
||
740 | tk | 293 | ui_delayed_action_callback = callback; |
752 | tk | 294 | ui_delayed_action_ctr = delay_mS; |
295 | MIOS32_IRQ_Enable(); |
||
740 | tk | 296 | |
297 | return 0; // no error |
||
298 | } |
||
299 | |||
300 | s32 SEQ_UI_UnInstallDelayedActionCallback(void *callback) |
||
301 | { |
||
752 | tk | 302 | // must be atomic |
303 | MIOS32_IRQ_Disable(); |
||
740 | tk | 304 | if( ui_delayed_action_callback == callback ) |
305 | ui_delayed_action_callback = 0; |
||
752 | tk | 306 | MIOS32_IRQ_Enable(); |
307 | |||
740 | tk | 308 | return 0; // no error |
309 | } |
||
310 | |||
311 | |||
167 | tk | 312 | ///////////////////////////////////////////////////////////////////////////// |
313 | // Change the menu page |
||
314 | ///////////////////////////////////////////////////////////////////////////// |
||
315 | s32 SEQ_UI_PageSet(seq_ui_page_t page) |
||
316 | { |
||
317 | if( page != ui_page ) { |
||
352 | tk | 318 | |
319 | // call page exit callback |
||
320 | if( ui_exit_callback != NULL ) |
||
321 | ui_exit_callback(); |
||
322 | |||
167 | tk | 323 | // disable hooks of previous page and request re-initialisation |
318 | tk | 324 | portENTER_CRITICAL(); |
167 | tk | 325 | ui_page = page; |
168 | tk | 326 | ui_button_callback = NULL; |
327 | ui_encoder_callback = NULL; |
||
328 | ui_led_callback = NULL; |
||
167 | tk | 329 | ui_lcd_callback = NULL; |
352 | tk | 330 | ui_exit_callback = NULL; |
740 | tk | 331 | ui_delayed_action_callback = NULL; |
318 | tk | 332 | portEXIT_CRITICAL(); |
167 | tk | 333 | |
1420 | tk | 334 | // always disable ALL button when changing page |
335 | seq_ui_button_state.CHANGE_ALL_STEPS_SAME_VALUE = 0; |
||
336 | seq_ui_button_state.CHANGE_ALL_STEPS = 0; |
||
337 | |||
167 | tk | 338 | // request display initialisation |
339 | seq_ui_display_init_req = 1; |
||
340 | } |
||
173 | tk | 341 | |
306 | tk | 342 | // for MENU button: |
1024 | tk | 343 | if( seq_hwcfg_button_beh.menu ) |
344 | seq_ui_button_state.MENU_PRESSED = 0; // MENU page selection finished |
||
1420 | tk | 345 | |
306 | tk | 346 | // first page has been selected - display new screen |
347 | seq_ui_button_state.MENU_FIRST_PAGE_SELECTED = 1; |
||
348 | |||
272 | tk | 349 | // for SEQ_UI_MENU which is accessible with EXIT button |
350 | // remember the current selectable page |
||
351 | if( ui_page >= SEQ_UI_FIRST_MENU_SELECTION_PAGE ) |
||
352 | ui_selected_page = ui_page; |
||
353 | |||
184 | tk | 354 | return 0; // no error |
167 | tk | 355 | } |
356 | |||
357 | |||
358 | ///////////////////////////////////////////////////////////////////////////// |
||
272 | tk | 359 | // Returns name of menu page (18 characters) |
360 | ///////////////////////////////////////////////////////////////////////////// |
||
361 | char *SEQ_UI_PageNameGet(seq_ui_page_t page) |
||
362 | { |
||
690 | tk | 363 | return (char *)ui_menu_pages[page].name; |
272 | tk | 364 | } |
365 | |||
366 | |||
367 | ///////////////////////////////////////////////////////////////////////////// |
||
1527 | tk | 368 | // Local help functions for copy/paste/clear/undo operations |
369 | ///////////////////////////////////////////////////////////////////////////// |
||
370 | static void SEQ_UI_Msg_Track(char *line2) |
||
371 | { |
||
372 | char buffer[20]; |
||
373 | u8 visible_track = SEQ_UI_VisibleTrackGet(); |
||
374 | sprintf(buffer, "Track G%dT%d", 1 + (visible_track / 4), 1 + (visible_track % 4)); |
||
375 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, buffer, line2); |
||
376 | } |
||
377 | |||
378 | static void SEQ_UI_Msg_MixerMap(char *line2) |
||
379 | { |
||
380 | char buffer[20]; |
||
381 | sprintf(buffer, "Mixer Map #%d", SEQ_MIXER_NumGet()+1); |
||
382 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, buffer, line2); |
||
383 | } |
||
384 | |||
385 | static void SEQ_UI_Msg_SongPos(char *line2) |
||
386 | { |
||
387 | char buffer[20]; |
||
388 | sprintf(buffer, "Song Position %c%d", 'A' + (ui_song_edit_pos >> 3), (ui_song_edit_pos&7)+1); |
||
389 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, buffer, line2); |
||
390 | } |
||
391 | |||
392 | |||
393 | ///////////////////////////////////////////////////////////////////////////// |
||
134 | tk | 394 | // Dedicated button functions |
395 | // Mapped to physical buttons in SEQ_UI_Button_Handler() |
||
396 | // Will also be mapped to MIDI keys later (for MIDI remote function) |
||
397 | ///////////////////////////////////////////////////////////////////////////// |
||
398 | static s32 SEQ_UI_Button_GP(s32 depressed, u32 gp) |
||
399 | { |
||
1044 | tk | 400 | // in MENU page: overrule GP buttons as long as MENU button is pressed/active |
1675 | tk | 401 | if( seq_ui_button_state.MENU_PRESSED || seq_hwcfg_blm.gp_always_select_menu_page ) { |
306 | tk | 402 | if( depressed ) return -1; |
403 | SEQ_UI_PageSet(ui_shortcut_menu_pages[gp]); |
||
404 | } else { |
||
1319 | tk | 405 | if( depressed ) |
406 | ui_selected_gp_buttons &= ~(1 << gp); |
||
407 | else |
||
408 | ui_selected_gp_buttons |= (1 << gp); |
||
409 | |||
306 | tk | 410 | // forward to menu page |
740 | tk | 411 | if( ui_button_callback != NULL ) { |
306 | tk | 412 | ui_button_callback(gp, depressed); |
740 | tk | 413 | ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0; |
414 | } |
||
306 | tk | 415 | } |
134 | tk | 416 | |
417 | return 0; // no error |
||
418 | } |
||
419 | |||
420 | static s32 SEQ_UI_Button_Left(s32 depressed) |
||
421 | { |
||
168 | tk | 422 | // forward to menu page |
740 | tk | 423 | if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL ) { |
168 | tk | 424 | ui_button_callback(SEQ_UI_BUTTON_Left, depressed); |
740 | tk | 425 | ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0; |
426 | } |
||
134 | tk | 427 | |
428 | return 0; // no error |
||
429 | } |
||
430 | |||
431 | static s32 SEQ_UI_Button_Right(s32 depressed) |
||
432 | { |
||
168 | tk | 433 | // forward to menu page |
740 | tk | 434 | if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL ) { |
168 | tk | 435 | ui_button_callback(SEQ_UI_BUTTON_Right, depressed); |
740 | tk | 436 | ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0; |
437 | } |
||
134 | tk | 438 | |
439 | return 0; // no error |
||
440 | } |
||
441 | |||
168 | tk | 442 | static s32 SEQ_UI_Button_Down(s32 depressed) |
443 | { |
||
240 | tk | 444 | seq_ui_button_state.DOWN = depressed ? 0 : 1; |
445 | |||
168 | tk | 446 | // forward to menu page |
740 | tk | 447 | if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL ) { |
168 | tk | 448 | ui_button_callback(SEQ_UI_BUTTON_Down, depressed); |
740 | tk | 449 | ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0; |
450 | } |
||
168 | tk | 451 | |
452 | return 0; // no error |
||
453 | } |
||
454 | |||
455 | static s32 SEQ_UI_Button_Up(s32 depressed) |
||
456 | { |
||
240 | tk | 457 | seq_ui_button_state.UP = depressed ? 0 : 1; |
458 | |||
168 | tk | 459 | // forward to menu page |
740 | tk | 460 | if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL ) { |
168 | tk | 461 | ui_button_callback(SEQ_UI_BUTTON_Up, depressed); |
740 | tk | 462 | ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0; |
463 | } |
||
168 | tk | 464 | |
465 | return 0; // no error |
||
466 | } |
||
467 | |||
1068 | tk | 468 | s32 SEQ_UI_Button_Stop(s32 depressed) |
134 | tk | 469 | { |
470 | if( depressed ) return -1; // ignore when button depressed |
||
471 | |||
159 | tk | 472 | // if sequencer running: stop it |
473 | // if sequencer already stopped: reset song position |
||
1206 | tk | 474 | if( SEQ_BPM_IsRunning() ) { |
475 | #if 0 |
||
476 | // TK: maybe to complicated to understand: STOP sequencer in slave mode if stop button pressed twice |
||
477 | u8 enable_slaveclk_mute = !SEQ_BPM_IsMaster() && seq_core_slaveclk_mute != SEQ_CORE_SLAVECLK_MUTE_Enabled; |
||
478 | #else |
||
479 | // always mute tracks, never stop sequencer (can only be done from external) |
||
480 | u8 enable_slaveclk_mute = !SEQ_BPM_IsMaster(); |
||
481 | #endif |
||
482 | if( enable_slaveclk_mute ) { |
||
483 | seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Enabled; |
||
484 | } else { |
||
485 | seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off; |
||
486 | SEQ_BPM_Stop(); |
||
487 | } |
||
488 | } else { |
||
489 | seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off; |
||
1145 | tk | 490 | SEQ_SONG_Reset(0); |
491 | SEQ_CORE_Reset(0); |
||
759 | tk | 492 | SEQ_MIDPLY_Reset(); |
493 | } |
||
159 | tk | 494 | |
1454 | midilab | 495 | seq_play_timer.seconds = 0; |
496 | |||
134 | tk | 497 | return 0; // no error |
498 | } |
||
499 | |||
500 | static s32 SEQ_UI_Button_Pause(s32 depressed) |
||
501 | { |
||
502 | if( depressed ) return -1; // ignore when button depressed |
||
503 | |||
1206 | tk | 504 | // if in auto mode and BPM generator is not clocked in slave mode: |
193 | tk | 505 | // change to master mode |
506 | SEQ_BPM_CheckAutoMaster(); |
||
159 | tk | 507 | |
1206 | tk | 508 | // toggle pause |
193 | tk | 509 | ui_seq_pause ^= 1; |
510 | |||
511 | // execute stop/continue depending on new mode |
||
1206 | tk | 512 | MIOS32_IRQ_Disable(); |
513 | if( ui_seq_pause ) { |
||
514 | if( !SEQ_BPM_IsMaster() ) { |
||
515 | seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Enabled; |
||
516 | } else { |
||
517 | SEQ_BPM_Stop(); |
||
518 | } |
||
519 | } else { |
||
520 | if( !SEQ_BPM_IsMaster() ) { |
||
521 | seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off; |
||
522 | } |
||
193 | tk | 523 | |
1206 | tk | 524 | if( !SEQ_BPM_IsRunning() ) |
525 | SEQ_BPM_Cont(); |
||
526 | } |
||
527 | MIOS32_IRQ_Enable(); |
||
528 | |||
134 | tk | 529 | return 0; // no error |
530 | } |
||
531 | |||
1068 | tk | 532 | s32 SEQ_UI_Button_Play(s32 depressed) |
134 | tk | 533 | { |
534 | if( depressed ) return -1; // ignore when button depressed |
||
535 | |||
1090 | tk | 536 | // if MENU button pressed -> tap tempo |
537 | if( seq_ui_button_state.MENU_PRESSED ) |
||
538 | return SEQ_UI_BPM_TapTempo(); |
||
539 | |||
1206 | tk | 540 | // if in auto mode and BPM generator is not clocked in slave mode: |
186 | tk | 541 | // change to master mode |
542 | SEQ_BPM_CheckAutoMaster(); |
||
543 | |||
1206 | tk | 544 | // slave mode and tracks muted: enable on next measure |
545 | if( !SEQ_BPM_IsMaster() && SEQ_BPM_IsRunning() ) { |
||
546 | if( seq_core_slaveclk_mute != SEQ_CORE_SLAVECLK_MUTE_Off ) |
||
547 | seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_OffOnNextMeasure; |
||
548 | // TK: note - in difference to master mode pressing PLAY twice won't reset the sequencer! |
||
549 | } else { |
||
193 | tk | 550 | #if 0 |
1206 | tk | 551 | // if sequencer running: restart it |
552 | // if sequencer stopped: continue at last song position |
||
553 | if( SEQ_BPM_IsRunning() ) |
||
554 | SEQ_BPM_Start(); |
||
555 | else |
||
556 | SEQ_BPM_Cont(); |
||
557 | #else |
||
558 | // always restart sequencer |
||
559 | seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off; |
||
193 | tk | 560 | SEQ_BPM_Start(); |
186 | tk | 561 | #endif |
1206 | tk | 562 | } |
159 | tk | 563 | |
1454 | midilab | 564 | seq_play_timer = MIOS32_SYS_TimeGet(); |
565 | |||
134 | tk | 566 | return 0; // no error |
567 | } |
||
568 | |||
569 | static s32 SEQ_UI_Button_Rew(s32 depressed) |
||
570 | { |
||
240 | tk | 571 | seq_ui_button_state.REW = depressed ? 0 : 1; |
572 | |||
134 | tk | 573 | if( depressed ) return -1; // ignore when button depressed |
574 | |||
607 | tk | 575 | if( SEQ_SONG_ActiveGet() ) { |
576 | portENTER_CRITICAL(); |
||
577 | SEQ_SONG_Rew(); |
||
578 | portEXIT_CRITICAL(); |
||
1713 | tk | 579 | } else { |
580 | //SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "We are not", "in Song Mode!"); |
||
581 | SEQ_UI_Button_StepViewDec(depressed); |
||
582 | } |
||
607 | tk | 583 | |
134 | tk | 584 | return 0; // no error |
585 | } |
||
586 | |||
587 | static s32 SEQ_UI_Button_Fwd(s32 depressed) |
||
588 | { |
||
240 | tk | 589 | seq_ui_button_state.FWD = depressed ? 0 : 1; |
590 | |||
134 | tk | 591 | if( depressed ) return -1; // ignore when button depressed |
592 | |||
607 | tk | 593 | if( SEQ_SONG_ActiveGet() ) { |
594 | portENTER_CRITICAL(); |
||
595 | SEQ_SONG_Fwd(); |
||
596 | portEXIT_CRITICAL(); |
||
1713 | tk | 597 | } else { |
598 | //SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "We are not", "in Song Mode!"); |
||
599 | SEQ_UI_Button_StepViewInc(depressed); |
||
600 | } |
||
607 | tk | 601 | |
134 | tk | 602 | return 0; // no error |
603 | } |
||
604 | |||
596 | tk | 605 | static s32 SEQ_UI_Button_Loop(s32 depressed) |
606 | { |
||
607 | if( seq_hwcfg_button_beh.loop ) { |
||
608 | // toggle mode |
||
609 | if( depressed ) return -1; // ignore when button depressed |
||
610 | // should be atomic |
||
611 | portENTER_CRITICAL(); |
||
612 | seq_core_state.LOOP ^= 1; |
||
613 | } else { |
||
614 | // should be atomic |
||
615 | portENTER_CRITICAL(); |
||
616 | // set mode |
||
617 | seq_core_state.LOOP = depressed ? 0 : 1; |
||
618 | } |
||
619 | portEXIT_CRITICAL(); |
||
620 | |||
621 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Loop Mode", seq_core_state.LOOP ? " on" : " off"); |
||
622 | |||
623 | return 0; // no error |
||
624 | } |
||
625 | |||
951 | tk | 626 | static s32 SEQ_UI_Button_Follow(s32 depressed) |
627 | { |
||
628 | if( seq_hwcfg_button_beh.follow ) { |
||
629 | // toggle mode |
||
630 | if( depressed ) return -1; // ignore when button depressed |
||
631 | // should be atomic |
||
632 | portENTER_CRITICAL(); |
||
633 | seq_core_state.FOLLOW ^= 1; |
||
634 | } else { |
||
635 | // should be atomic |
||
636 | portENTER_CRITICAL(); |
||
637 | // set mode |
||
638 | seq_core_state.FOLLOW = depressed ? 0 : 1; |
||
639 | } |
||
640 | portEXIT_CRITICAL(); |
||
641 | |||
642 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Follow Mode", seq_core_state.FOLLOW ? " on" : " off"); |
||
643 | |||
644 | return 0; // no error |
||
645 | } |
||
646 | |||
596 | tk | 647 | static s32 SEQ_UI_Button_Scrub(s32 depressed) |
648 | { |
||
649 | // double function: -> Loop if menu button pressed |
||
650 | if( seq_ui_button_state.MENU_PRESSED ) |
||
651 | return SEQ_UI_Button_Loop(depressed); |
||
652 | |||
653 | if( seq_hwcfg_button_beh.scrub ) { |
||
654 | // toggle mode |
||
655 | if( depressed ) return -1; // ignore when button depressed |
||
656 | seq_ui_button_state.SCRUB ^= 1; |
||
657 | } else { |
||
658 | // set mode |
||
659 | seq_ui_button_state.SCRUB = depressed ? 0 : 1; |
||
660 | } |
||
661 | |||
662 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Scrub Mode", seq_ui_button_state.SCRUB ? " on" : " off"); |
||
663 | |||
664 | return 0; // no error |
||
665 | } |
||
666 | |||
513 | tk | 667 | static s32 SEQ_UI_Button_TempoPreset(s32 depressed) |
134 | tk | 668 | { |
513 | tk | 669 | static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE; |
240 | tk | 670 | |
513 | tk | 671 | if( seq_hwcfg_button_beh.tempo_preset ) { |
672 | if( depressed ) return -1; // ignore when button depressed |
||
678 | tk | 673 | if( !seq_ui_button_state.TEMPO_PRESET ) // due to page change: button going to be set, clear other toggle buttons |
674 | seq_ui_button_state.PAGE_CHANGE_BUTTON_FLAGS = 0; |
||
513 | tk | 675 | seq_ui_button_state.TEMPO_PRESET ^= 1; // toggle TEMPO_PRESET pressed (will also be released once GP button has been pressed) |
676 | } else { |
||
677 | // set mode |
||
678 | seq_ui_button_state.TEMPO_PRESET = depressed ? 0 : 1; |
||
679 | } |
||
134 | tk | 680 | |
513 | tk | 681 | if( seq_ui_button_state.TEMPO_PRESET ) { |
682 | prev_page = ui_page; |
||
683 | SEQ_UI_PageSet(SEQ_UI_PAGE_BPM_PRESETS); |
||
684 | } else { |
||
524 | tk | 685 | if( ui_page == SEQ_UI_PAGE_BPM_PRESETS ) |
686 | SEQ_UI_PageSet(prev_page); |
||
513 | tk | 687 | } |
240 | tk | 688 | |
134 | tk | 689 | return 0; // no error |
690 | } |
||
691 | |||
513 | tk | 692 | static s32 SEQ_UI_Button_TapTempo(s32 depressed) |
134 | tk | 693 | { |
513 | tk | 694 | seq_ui_button_state.TAP_TEMPO = depressed ? 0 : 1; |
240 | tk | 695 | |
134 | tk | 696 | if( depressed ) return -1; // ignore when button depressed |
697 | |||
1142 | tk | 698 | return SEQ_UI_BPM_TapTempo(); |
134 | tk | 699 | } |
700 | |||
524 | tk | 701 | static s32 SEQ_UI_Button_ExtRestart(s32 depressed) |
134 | tk | 702 | { |
703 | if( depressed ) return -1; // ignore when button depressed |
||
704 | |||
596 | tk | 705 | // should be atomic |
524 | tk | 706 | portENTER_CRITICAL(); |
707 | seq_core_state.EXT_RESTART_REQ = 1; |
||
708 | portEXIT_CRITICAL(); |
||
709 | |||
596 | tk | 710 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "External Restart", "requested"); |
711 | |||
134 | tk | 712 | return 0; // no error |
713 | } |
||
714 | |||
596 | tk | 715 | static s32 SEQ_UI_Button_Metronome(s32 depressed) |
716 | { |
||
717 | // double function: -> ExtRestart if menu button pressed |
||
718 | if( seq_ui_button_state.MENU_PRESSED ) |
||
719 | return SEQ_UI_Button_ExtRestart(depressed); |
||
720 | |||
721 | if( seq_hwcfg_button_beh.metronome ) { |
||
722 | // toggle mode |
||
723 | if( depressed ) return -1; // ignore when button depressed |
||
724 | // should be atomic |
||
725 | portENTER_CRITICAL(); |
||
726 | seq_core_state.METRONOME ^= 1; |
||
727 | } else { |
||
728 | // should be atomic |
||
729 | portENTER_CRITICAL(); |
||
730 | // set mode |
||
731 | seq_core_state.METRONOME = depressed ? 0 : 1; |
||
732 | } |
||
733 | portEXIT_CRITICAL(); |
||
734 | |||
735 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Metronome", seq_core_state.METRONOME ? " on" : " off"); |
||
736 | |||
599 | tk | 737 | #if 0 |
738 | // metronome button can be used to trigger pattern file fixes |
||
739 | if( !depressed ) |
||
740 | SEQ_PATTERN_FixAll(); |
||
741 | #endif |
||
742 | |||
596 | tk | 743 | return 0; // no error |
744 | } |
||
745 | |||
630 | tk | 746 | static s32 SEQ_UI_Button_Record(s32 depressed) |
747 | { |
||
748 | if( depressed ) return -1; // ignore when button depressed |
||
749 | |||
1219 | tk | 750 | // change to record page |
630 | tk | 751 | SEQ_UI_PageSet(SEQ_UI_PAGE_TRKREC); |
752 | |||
753 | return 0; // no error |
||
754 | } |
||
755 | |||
1219 | tk | 756 | static s32 SEQ_UI_Button_Live(s32 depressed) |
757 | { |
||
758 | if( depressed ) return -1; // ignore when button depressed |
||
759 | |||
760 | // change to live page |
||
761 | SEQ_UI_PageSet(SEQ_UI_PAGE_TRKLIVE); |
||
762 | |||
763 | return 0; // no error |
||
764 | } |
||
765 | |||
134 | tk | 766 | static s32 SEQ_UI_Button_Utility(s32 depressed) |
767 | { |
||
768 | if( depressed ) return -1; // ignore when button depressed |
||
769 | |||
240 | tk | 770 | // change to utility page |
771 | SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL); |
||
772 | |||
134 | tk | 773 | return 0; // no error |
774 | } |
||
775 | |||
1281 | tk | 776 | static s32 SEQ_UI_Button_MultiCopy(s32 depressed) |
777 | { |
||
778 | if( depressed ) return 1; |
||
779 | |||
780 | s32 status = 0; |
||
781 | char path[30]; |
||
782 | |||
783 | // create directory if it doesn't exist |
||
784 | strcpy(path, "/PRESETS"); |
||
785 | MUTEX_SDCARD_TAKE; |
||
786 | status = FILE_MakeDir(path); |
||
787 | status = FILE_DirExists(path); |
||
788 | MUTEX_SDCARD_GIVE; |
||
789 | |||
790 | if( status < 0 ) { |
||
791 | SEQ_UI_SDCardErrMsg(2000, status); |
||
792 | return -3; |
||
793 | } |
||
794 | |||
795 | if( status == 0 ) { |
||
796 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "/PRESETS directory", "cannot be created!"); |
||
797 | return -4; |
||
798 | } |
||
799 | |||
800 | // copy all selected patterns to preset directory |
||
801 | u8 track, track_id; |
||
802 | for(track=0, track_id=0; track<SEQ_CORE_NUM_TRACKS; ++track) { |
||
803 | if( ui_selected_tracks & (1 << track) ) { |
||
804 | ++track_id; |
||
805 | sprintf(path, "/PRESETS/COPY%d.v4t", track_id); |
||
806 | |||
807 | char str[30]; |
||
808 | sprintf(str, "Exporting G%dT%d to:", (track/4)+1, (track%4)+1); |
||
809 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, str, path); |
||
810 | |||
811 | MUTEX_SDCARD_TAKE; |
||
1282 | tk | 812 | status=SEQ_FILE_T_Write(path, track); |
1281 | tk | 813 | MUTEX_SDCARD_GIVE; |
814 | |||
815 | if( status < 0 ) { |
||
816 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "Error during Export!", "see MIOS Terminal!"); |
||
817 | return -6; |
||
818 | } |
||
819 | } |
||
820 | } |
||
821 | |||
822 | if( !track_id ) { |
||
823 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "No Track selected", "for Multi-Copy!"); |
||
824 | } |
||
825 | |||
826 | return 0; // no error |
||
827 | } |
||
828 | |||
134 | tk | 829 | static s32 SEQ_UI_Button_Copy(s32 depressed) |
830 | { |
||
240 | tk | 831 | static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE; |
134 | tk | 832 | |
240 | tk | 833 | seq_ui_button_state.COPY = depressed ? 0 : 1; |
834 | |||
1281 | tk | 835 | if( seq_ui_button_state.MENU_PRESSED ) { |
836 | return SEQ_UI_Button_MultiCopy(depressed); |
||
837 | } |
||
838 | |||
280 | tk | 839 | if( ui_page == SEQ_UI_PAGE_MIXER ) { |
840 | if( depressed ) return -1; |
||
841 | SEQ_UI_MIXER_Copy(); |
||
1527 | tk | 842 | SEQ_UI_Msg_MixerMap("copied"); |
280 | tk | 843 | return 1; |
729 | tk | 844 | } else if( ui_page == SEQ_UI_PAGE_SONG ) { |
845 | if( depressed ) return -1; |
||
846 | SEQ_UI_SONG_Copy(); |
||
1527 | tk | 847 | SEQ_UI_Msg_SongPos("copied"); |
729 | tk | 848 | return 1; |
280 | tk | 849 | } else { |
850 | if( !depressed ) { |
||
851 | prev_page = ui_page; |
||
852 | SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL); |
||
853 | } |
||
240 | tk | 854 | |
280 | tk | 855 | s32 status = SEQ_UI_UTIL_CopyButton(depressed); |
240 | tk | 856 | |
596 | tk | 857 | if( depressed ) { |
858 | if( prev_page != SEQ_UI_PAGE_UTIL ) |
||
859 | SEQ_UI_PageSet(prev_page); |
||
240 | tk | 860 | |
1527 | tk | 861 | SEQ_UI_Msg_Track("copied"); |
596 | tk | 862 | } |
863 | |||
280 | tk | 864 | return status; |
865 | } |
||
134 | tk | 866 | } |
867 | |||
1281 | tk | 868 | static s32 SEQ_UI_Button_MultiPaste(s32 depressed) |
869 | { |
||
870 | if( depressed ) return 1; |
||
871 | |||
872 | s32 status = 0; |
||
873 | char path[30]; |
||
874 | |||
875 | // paste multi copy presets into selected tracks |
||
876 | u8 track, track_id; |
||
877 | for(track=0, track_id=0; track<SEQ_CORE_NUM_TRACKS; ++track) { |
||
878 | if( ui_selected_tracks & (1 << track) ) { |
||
879 | ++track_id; |
||
880 | sprintf(path, "/PRESETS/COPY%d.v4t", track_id); |
||
881 | |||
882 | char str[30]; |
||
883 | sprintf(str, "Importing to G%dT%d:", (track/4)+1, (track%4)+1); |
||
884 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, str, path); |
||
885 | |||
886 | // mute track to avoid random effects while loading the file |
||
887 | MIOS32_IRQ_Disable(); // this operation should be atomic! |
||
888 | u8 muted = seq_core_trk_muted & (1 << track); |
||
889 | if( !muted ) |
||
890 | seq_core_trk_muted |= (1 << track); |
||
891 | MIOS32_IRQ_Enable(); |
||
892 | |||
893 | static seq_file_t_import_flags_t import_flags; |
||
894 | import_flags.ALL = 0xff; |
||
895 | |||
896 | // read file |
||
897 | MUTEX_SDCARD_TAKE; |
||
898 | status = SEQ_FILE_T_Read(path, track, import_flags); |
||
899 | MUTEX_SDCARD_GIVE; |
||
900 | |||
901 | // unmute track if it wasn't muted before |
||
902 | MIOS32_IRQ_Disable(); // this operation should be atomic! |
||
903 | if( !muted ) |
||
904 | seq_core_trk_muted &= ~(1 << track); |
||
905 | MIOS32_IRQ_Enable(); |
||
906 | |||
907 | if( status == FILE_ERR_OPEN_READ ) { |
||
908 | char str[30]; |
||
909 | sprintf(str, "File for G%dT%d missing:", (track/4)+1, (track%4)+1); |
||
910 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, str, path); |
||
911 | } else if( status < 0 ) { |
||
912 | SEQ_UI_SDCardErrMsg(2000, status); |
||
913 | } else { |
||
914 | sprintf(str, "Imported to G%dT%d:", (track/4)+1, (track%4)+1); |
||
915 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, str, path); |
||
916 | } |
||
917 | } |
||
918 | } |
||
919 | |||
920 | if( !track_id ) { |
||
921 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "No Track selected", "for Multi-Paste!"); |
||
922 | } |
||
923 | |||
924 | return 0; // no error |
||
925 | } |
||
926 | |||
134 | tk | 927 | static s32 SEQ_UI_Button_Paste(s32 depressed) |
928 | { |
||
240 | tk | 929 | static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE; |
134 | tk | 930 | |
240 | tk | 931 | seq_ui_button_state.PASTE = depressed ? 0 : 1; |
932 | |||
1281 | tk | 933 | if( seq_ui_button_state.MENU_PRESSED ) { |
934 | return SEQ_UI_Button_MultiPaste(depressed); |
||
935 | } |
||
936 | |||
280 | tk | 937 | if( ui_page == SEQ_UI_PAGE_MIXER ) { |
938 | if( depressed ) return -1; |
||
939 | SEQ_UI_MIXER_Paste(); |
||
1527 | tk | 940 | SEQ_UI_Msg_MixerMap("pasted"); |
280 | tk | 941 | return 1; |
729 | tk | 942 | } else if( ui_page == SEQ_UI_PAGE_SONG ) { |
943 | if( depressed ) return -1; |
||
944 | SEQ_UI_SONG_Paste(); |
||
1527 | tk | 945 | SEQ_UI_Msg_SongPos("pasted"); |
729 | tk | 946 | return 1; |
280 | tk | 947 | } else { |
948 | if( !depressed ) { |
||
949 | prev_page = ui_page; |
||
950 | SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL); |
||
951 | } |
||
240 | tk | 952 | |
280 | tk | 953 | s32 status = SEQ_UI_UTIL_PasteButton(depressed); |
240 | tk | 954 | |
596 | tk | 955 | if( depressed ) { |
956 | if( prev_page != SEQ_UI_PAGE_UTIL ) |
||
957 | SEQ_UI_PageSet(prev_page); |
||
240 | tk | 958 | |
1527 | tk | 959 | SEQ_UI_Msg_Track("pasted"); |
596 | tk | 960 | } |
961 | |||
280 | tk | 962 | return status; |
963 | } |
||
134 | tk | 964 | } |
965 | |||
740 | tk | 966 | |
967 | // callback function for delayed Clear Mixer function |
||
752 | tk | 968 | static void SEQ_UI_Button_Clear_Mixer(u32 dummy) |
740 | tk | 969 | { |
970 | SEQ_UI_MIXER_Clear(); |
||
1527 | tk | 971 | SEQ_UI_Msg_MixerMap("cleared"); |
740 | tk | 972 | } |
973 | |||
974 | // callback function for delayed Clear SongPos function |
||
752 | tk | 975 | static void SEQ_UI_Button_Clear_SongPos(u32 dummy) |
740 | tk | 976 | { |
977 | SEQ_UI_SONG_Clear(); |
||
1527 | tk | 978 | SEQ_UI_Msg_SongPos("cleared"); |
740 | tk | 979 | } |
980 | |||
981 | // callback function for clear track |
||
752 | tk | 982 | static void SEQ_UI_Button_Clear_Track(u32 dummy) |
740 | tk | 983 | { |
984 | SEQ_UI_UTIL_ClearButton(0); // button pressed |
||
985 | SEQ_UI_UTIL_ClearButton(1); // button depressed |
||
1527 | tk | 986 | SEQ_UI_Msg_Track("cleared"); |
740 | tk | 987 | } |
988 | |||
134 | tk | 989 | static s32 SEQ_UI_Button_Clear(s32 depressed) |
990 | { |
||
1523 | tk | 991 | #if 0 |
992 | u32 clear_delay = 2000; |
||
993 | #else |
||
994 | u32 clear_delay = 50; // TK: I prefer a much faster clear |
||
995 | #endif |
||
240 | tk | 996 | seq_ui_button_state.CLEAR = depressed ? 0 : 1; |
280 | tk | 997 | |
998 | if( ui_page == SEQ_UI_PAGE_MIXER ) { |
||
740 | tk | 999 | if( depressed ) |
1000 | SEQ_UI_UnInstallDelayedActionCallback(SEQ_UI_Button_Clear_Mixer); |
||
752 | tk | 1001 | else { |
1523 | tk | 1002 | SEQ_UI_InstallDelayedActionCallback(SEQ_UI_Button_Clear_Mixer, clear_delay, 0); |
1003 | SEQ_UI_Msg(SEQ_UI_MSG_DELAYED_ACTION, clear_delay+1, "", "to clear Mixer Map"); |
||
752 | tk | 1004 | } |
729 | tk | 1005 | return 1; |
1006 | } else if( ui_page == SEQ_UI_PAGE_SONG ) { |
||
740 | tk | 1007 | if( depressed ) |
1008 | SEQ_UI_UnInstallDelayedActionCallback(SEQ_UI_Button_Clear_SongPos); |
||
752 | tk | 1009 | else { |
1523 | tk | 1010 | SEQ_UI_InstallDelayedActionCallback(SEQ_UI_Button_Clear_SongPos, clear_delay, 0); |
1011 | SEQ_UI_Msg(SEQ_UI_MSG_DELAYED_ACTION, clear_delay+1, "", "to clear SongPos"); |
||
752 | tk | 1012 | } |
729 | tk | 1013 | return 1; |
1014 | } else { |
||
740 | tk | 1015 | if( depressed ) |
1016 | SEQ_UI_UnInstallDelayedActionCallback(SEQ_UI_Button_Clear_Track); |
||
752 | tk | 1017 | else { |
1523 | tk | 1018 | SEQ_UI_InstallDelayedActionCallback(SEQ_UI_Button_Clear_Track, clear_delay, 0); |
1019 | SEQ_UI_Msg(SEQ_UI_MSG_DELAYED_ACTION, clear_delay+1, "", "to clear Track"); |
||
752 | tk | 1020 | } |
280 | tk | 1021 | return 1; |
1022 | } |
||
134 | tk | 1023 | } |
1024 | |||
1014 | tk | 1025 | |
1026 | static s32 SEQ_UI_Button_Undo(s32 depressed) |
||
1027 | { |
||
1028 | static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE; |
||
1029 | |||
1030 | seq_ui_button_state.UNDO = depressed ? 0 : 1; |
||
1031 | |||
1032 | if( ui_page == SEQ_UI_PAGE_MIXER ) { |
||
1033 | if( depressed ) return -1; |
||
1034 | SEQ_UI_MIXER_Undo(); |
||
1527 | tk | 1035 | SEQ_UI_Msg_MixerMap("Undo applied"); |
1014 | tk | 1036 | return 1; |
1037 | } else { |
||
1038 | if( !depressed ) { |
||
1039 | prev_page = ui_page; |
||
1040 | SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL); |
||
1041 | } |
||
1042 | |||
1043 | s32 status = SEQ_UI_UTIL_UndoButton(depressed); |
||
1044 | |||
1045 | if( depressed ) { |
||
1046 | if( prev_page != SEQ_UI_PAGE_UTIL ) |
||
1047 | SEQ_UI_PageSet(prev_page); |
||
1048 | |||
1527 | tk | 1049 | SEQ_UI_Msg_Track("Undo applied"); |
1014 | tk | 1050 | } |
1051 | |||
1052 | return status; |
||
1053 | } |
||
1054 | } |
||
1055 | |||
1056 | |||
134 | tk | 1057 | static s32 SEQ_UI_Button_Menu(s32 depressed) |
1058 | { |
||
513 | tk | 1059 | if( seq_hwcfg_button_beh.menu ) { |
1060 | // toggle mode |
||
1061 | if( depressed ) return -1; // ignore when button depressed |
||
1062 | seq_ui_button_state.MENU_FIRST_PAGE_SELECTED = 0; |
||
678 | tk | 1063 | if( !seq_ui_button_state.MENU_PRESSED ) // due to page change: button going to be set, clear other toggle buttons |
1064 | seq_ui_button_state.PAGE_CHANGE_BUTTON_FLAGS = 0; |
||
513 | tk | 1065 | seq_ui_button_state.MENU_PRESSED ^= 1; // toggle MENU pressed (will also be released once GP button has been pressed) |
1066 | } else { |
||
1067 | // set mode |
||
1068 | seq_ui_button_state.MENU_FIRST_PAGE_SELECTED = 0; |
||
1069 | seq_ui_button_state.MENU_PRESSED = depressed ? 0 : 1; |
||
1070 | } |
||
134 | tk | 1071 | |
1072 | return 0; // no error |
||
1073 | } |
||
1074 | |||
1203 | tk | 1075 | |
1076 | static s32 SEQ_UI_Button_Bookmark(s32 depressed) |
||
1077 | { |
||
1078 | if( seq_hwcfg_button_beh.bookmark ) { |
||
1079 | if( depressed ) return -1; // ignore when button depressed |
||
1080 | if( !seq_ui_button_state.BOOKMARK ) // due to page change: button going to be set, clear other toggle buttons |
||
1081 | seq_ui_button_state.PAGE_CHANGE_BUTTON_FLAGS = 0; |
||
1082 | #if 0 |
||
1083 | seq_ui_button_state.BOOKMARK ^= 1; // toggle BOOKMARK pressed (will also be released once GP button has been pressed) |
||
1084 | #else |
||
1085 | seq_ui_button_state.BOOKMARK = 1; // seems that it's better *not* to toggle! |
||
1086 | #endif |
||
1087 | } else { |
||
1088 | // set mode |
||
1089 | seq_ui_button_state.BOOKMARK = depressed ? 0 : 1; |
||
1090 | } |
||
1091 | |||
1092 | if( seq_ui_button_state.BOOKMARK ) { |
||
1093 | if( ui_page != SEQ_UI_PAGE_BOOKMARKS ) |
||
1094 | ui_page_before_bookmark = ui_page; |
||
1095 | SEQ_UI_PageSet(SEQ_UI_PAGE_BOOKMARKS); |
||
1096 | } else { |
||
1097 | if( ui_page == SEQ_UI_PAGE_BOOKMARKS ) |
||
1098 | SEQ_UI_PageSet(ui_page_before_bookmark); |
||
1099 | } |
||
1100 | |||
1101 | return 0; // no error |
||
1102 | } |
||
1103 | |||
1104 | |||
1205 | tk | 1105 | static s32 SEQ_UI_Button_DirectBookmark(s32 depressed, u32 bookmark_button) |
1106 | { |
||
1107 | if( !depressed ) |
||
1108 | ui_page_before_bookmark = ui_page; |
||
1109 | |||
1110 | return SEQ_UI_BOOKMARKS_Button_Handler(bookmark_button, depressed); |
||
1111 | } |
||
1112 | |||
1113 | |||
134 | tk | 1114 | static s32 SEQ_UI_Button_Select(s32 depressed) |
1115 | { |
||
1203 | tk | 1116 | // double function: -> Bookmark if menu button pressed |
1117 | if( seq_ui_button_state.MENU_PRESSED ) |
||
1118 | return SEQ_UI_Button_Bookmark(depressed); |
||
1119 | |||
168 | tk | 1120 | // forward to menu page |
591 | tk | 1121 | if( !seq_ui_button_state.MENU_PRESSED ) { |
1122 | seq_ui_button_state.SELECT_PRESSED = depressed ? 0 : 1; |
||
740 | tk | 1123 | if( ui_button_callback != NULL ) { |
591 | tk | 1124 | ui_button_callback(SEQ_UI_BUTTON_Select, depressed); |
740 | tk | 1125 | ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0; |
1126 | } |
||
591 | tk | 1127 | } |
134 | tk | 1128 | |
1129 | return 0; // no error |
||
1130 | } |
||
1131 | |||
1132 | static s32 SEQ_UI_Button_Exit(s32 depressed) |
||
1133 | { |
||
951 | tk | 1134 | // double function: -> Follow if menu button pressed |
1135 | if( seq_ui_button_state.MENU_PRESSED ) |
||
1136 | return SEQ_UI_Button_Follow(depressed); |
||
1137 | |||
272 | tk | 1138 | if( depressed ) return -1; // ignore when button depressed |
1139 | |||
1140 | u8 prev_ui_page = ui_page; |
||
1141 | |||
168 | tk | 1142 | // forward to menu page |
1123 | tk | 1143 | if( ui_button_callback != NULL ) { |
1144 | if( ui_button_callback(SEQ_UI_BUTTON_Exit, depressed) >= 1 ) |
||
1145 | return 1; // page has already handled exit button |
||
740 | tk | 1146 | ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0; |
1147 | } |
||
134 | tk | 1148 | |
167 | tk | 1149 | // release all button states |
984 | tk | 1150 | // seq_ui_button_state.ALL = 0; |
1151 | // clashes with SOLO/ALL/etc. |
||
167 | tk | 1152 | |
272 | tk | 1153 | // enter menu page if we were not there before |
1154 | if( prev_ui_page != SEQ_UI_PAGE_MENU ) |
||
1155 | SEQ_UI_PageSet(SEQ_UI_PAGE_MENU); |
||
1156 | |||
134 | tk | 1157 | return 0; // no error |
1158 | } |
||
1159 | |||
1160 | static s32 SEQ_UI_Button_Edit(s32 depressed) |
||
1161 | { |
||
741 | tk | 1162 | seq_ui_button_state.EDIT_PRESSED = depressed ? 0 : 1; |
591 | tk | 1163 | |
167 | tk | 1164 | // change to edit page |
1350 | tk | 1165 | if( !depressed ) { |
1166 | SEQ_UI_PageSet(SEQ_UI_PAGE_EDIT); |
||
167 | tk | 1167 | |
1350 | tk | 1168 | // set/clear encoder fast function if required |
1169 | SEQ_UI_InitEncSpeed(1); // auto config |
||
1170 | } |
||
178 | tk | 1171 | |
1350 | tk | 1172 | // EDIT button notification to button callback |
1173 | // currently only used in EDIT page itself! |
||
1174 | if( depressed && ui_page != SEQ_UI_PAGE_EDIT ) |
||
1175 | return -1; |
||
1176 | |||
1177 | if( ui_button_callback != NULL ) { |
||
1178 | ui_button_callback(SEQ_UI_BUTTON_Edit, depressed); |
||
1179 | ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0; |
||
1180 | } |
||
1181 | |||
134 | tk | 1182 | return 0; // no error |
1183 | } |
||
1184 | |||
1185 | static s32 SEQ_UI_Button_Mute(s32 depressed) |
||
1186 | { |
||
591 | tk | 1187 | seq_ui_button_state.MUTE_PRESSED = depressed ? 0 : 1; |
1188 | |||
134 | tk | 1189 | if( depressed ) return -1; // ignore when button depressed |
1190 | |||
184 | tk | 1191 | SEQ_UI_PageSet(SEQ_UI_PAGE_MUTE); |
1192 | |||
134 | tk | 1193 | return 0; // no error |
1194 | } |
||
1195 | |||
1196 | static s32 SEQ_UI_Button_Pattern(s32 depressed) |
||
1197 | { |
||
591 | tk | 1198 | seq_ui_button_state.PATTERN_PRESSED = depressed ? 0 : 1; |
1199 | |||
134 | tk | 1200 | if( depressed ) return -1; // ignore when button depressed |
1201 | |||
184 | tk | 1202 | SEQ_UI_PageSet(SEQ_UI_PAGE_PATTERN); |
1203 | |||
134 | tk | 1204 | return 0; // no error |
1205 | } |
||
1206 | |||
1454 | midilab | 1207 | static s32 SEQ_UI_Button_Pattern_Remix(s32 depressed) |
1208 | { |
||
1209 | |||
1210 | if ( ui_page == SEQ_UI_PAGE_PATTERN_RMX ) { |
||
1211 | // to avoid race conditions using the same button(any other way of solving that?) |
||
1212 | vTaskDelay(60); |
||
1213 | // a trick to use the same button with 2 functionalitys |
||
1214 | ui_button_callback(SEQ_UI_BUTTON_Edit, depressed); |
||
1215 | } else { |
||
1216 | SEQ_UI_PageSet(SEQ_UI_PAGE_PATTERN_RMX); |
||
1217 | } |
||
1218 | |||
1219 | return 0; // no error |
||
1220 | |||
1221 | } |
||
1222 | |||
134 | tk | 1223 | static s32 SEQ_UI_Button_Song(s32 depressed) |
1224 | { |
||
591 | tk | 1225 | seq_ui_button_state.SONG_PRESSED = depressed ? 0 : 1; |
1226 | |||
134 | tk | 1227 | if( depressed ) return -1; // ignore when button depressed |
1228 | |||
399 | tk | 1229 | SEQ_UI_PageSet(SEQ_UI_PAGE_SONG); |
1230 | |||
134 | tk | 1231 | return 0; // no error |
1232 | } |
||
1233 | |||
1234 | static s32 SEQ_UI_Button_Solo(s32 depressed) |
||
1235 | { |
||
513 | tk | 1236 | if( seq_hwcfg_button_beh.solo ) { |
1237 | // toggle mode |
||
1238 | if( depressed ) return -1; // ignore when button depressed |
||
1239 | seq_ui_button_state.SOLO ^= 1; |
||
1240 | } else { |
||
1241 | // set mode |
||
1242 | seq_ui_button_state.SOLO = depressed ? 0 : 1; |
||
1243 | } |
||
134 | tk | 1244 | |
1245 | return 0; // no error |
||
1246 | } |
||
1247 | |||
1248 | static s32 SEQ_UI_Button_Fast(s32 depressed) |
||
1249 | { |
||
513 | tk | 1250 | if( seq_hwcfg_button_beh.fast ) { |
1251 | // toggle mode |
||
1252 | if( depressed ) return -1; // ignore when button depressed |
||
1253 | seq_ui_button_state.FAST_ENCODERS ^= 1; |
||
1254 | } else { |
||
1255 | // set mode |
||
1256 | seq_ui_button_state.FAST_ENCODERS = depressed ? 0 : 1; |
||
1257 | } |
||
134 | tk | 1258 | |
178 | tk | 1259 | SEQ_UI_InitEncSpeed(0); // no auto config |
1260 | |||
134 | tk | 1261 | return 0; // no error |
1262 | } |
||
1263 | |||
1121 | tk | 1264 | static s32 SEQ_UI_Button_Fast2(s32 depressed) |
1265 | { |
||
1266 | if( seq_hwcfg_button_beh.fast2 ) { |
||
1267 | // toggle mode |
||
1268 | if( depressed ) return -1; // ignore when button depressed |
||
1269 | seq_ui_button_state.FAST2_ENCODERS ^= 1; |
||
1270 | } else { |
||
1271 | // set mode |
||
1272 | seq_ui_button_state.FAST2_ENCODERS = depressed ? 0 : 1; |
||
1273 | } |
||
1274 | |||
1275 | SEQ_UI_InitEncSpeed(0); // no auto config |
||
1276 | |||
1277 | return 0; // no error |
||
1278 | } |
||
1279 | |||
134 | tk | 1280 | static s32 SEQ_UI_Button_All(s32 depressed) |
1281 | { |
||
178 | tk | 1282 | seq_ui_button_state.CHANGE_ALL_STEPS_SAME_VALUE = depressed ? 0 : 1; |
134 | tk | 1283 | |
513 | tk | 1284 | if( seq_hwcfg_button_beh.all ) { |
1285 | // toggle mode |
||
1286 | if( depressed ) return -1; |
||
1287 | seq_ui_button_state.CHANGE_ALL_STEPS ^= 1; |
||
1288 | } else { |
||
1289 | // set mode |
||
1290 | seq_ui_button_state.CHANGE_ALL_STEPS = depressed ? 0 : 1; |
||
1291 | } |
||
178 | tk | 1292 | |
134 | tk | 1293 | return 0; // no error |
1294 | } |
||
1295 | |||
1296 | static s32 SEQ_UI_Button_StepView(s32 depressed) |
||
1297 | { |
||
600 | tk | 1298 | // static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE; |
1299 | // also used by seq_ui_stepsel |
||
1300 | |||
513 | tk | 1301 | if( seq_hwcfg_button_beh.step_view ) { |
1302 | if( depressed ) return -1; // ignore when button depressed |
||
678 | tk | 1303 | if( !seq_ui_button_state.STEP_VIEW ) // due to page change: button going to be set, clear other toggle buttons |
1304 | seq_ui_button_state.PAGE_CHANGE_BUTTON_FLAGS = 0; |
||
513 | tk | 1305 | seq_ui_button_state.STEP_VIEW ^= 1; // toggle STEP_VIEW pressed (will also be released once GP button has been pressed) |
1306 | } else { |
||
1307 | // set mode |
||
1308 | seq_ui_button_state.STEP_VIEW = depressed ? 0 : 1; |
||
1309 | } |
||
134 | tk | 1310 | |
513 | tk | 1311 | if( seq_ui_button_state.STEP_VIEW ) { |
600 | tk | 1312 | ui_stepview_prev_page = ui_page; |
303 | tk | 1313 | SEQ_UI_PageSet(SEQ_UI_PAGE_STEPSEL); |
1314 | } else { |
||
524 | tk | 1315 | if( ui_page == SEQ_UI_PAGE_STEPSEL ) |
600 | tk | 1316 | SEQ_UI_PageSet(ui_stepview_prev_page); |
303 | tk | 1317 | } |
134 | tk | 1318 | |
1319 | return 0; // no error |
||
1320 | } |
||
1321 | |||
1713 | tk | 1322 | static s32 SEQ_UI_Button_StepViewInc(s32 depressed) |
1323 | { |
||
1324 | if( depressed ) return -1; // ignore when button depressed |
||
1325 | |||
1326 | u8 visible_track = SEQ_UI_VisibleTrackGet(); |
||
1327 | int num_steps = SEQ_TRG_NumStepsGet(visible_track); |
||
1328 | |||
1329 | int new_step_view = ui_selected_step_view + 1; |
||
1330 | if( (16*new_step_view) < num_steps ) { |
||
1331 | // select new step view |
||
1332 | ui_selected_step_view = new_step_view; |
||
1333 | |||
1334 | // select step within view |
||
1335 | ui_selected_step = (ui_selected_step_view << 4) | (ui_selected_step & 0xf); |
||
1336 | } |
||
1337 | |||
1338 | char buffer[20]; |
||
1339 | sprintf(buffer, "%d-%d", ui_selected_step_view*16 + 1, ui_selected_step_view*16 + 16); |
||
1340 | SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "Step View", buffer); |
||
1341 | |||
1342 | return 0; // no error |
||
1343 | } |
||
1344 | |||
1345 | static s32 SEQ_UI_Button_StepViewDec(s32 depressed) |
||
1346 | { |
||
1347 | if( depressed ) return -1; // ignore when button depressed |
||
1348 | |||
1349 | int new_step_view = ui_selected_step_view - 1; |
||
1350 | if( new_step_view >= 0 ) { |
||
1351 | // select new step view |
||
1352 | ui_selected_step_view = new_step_view; |
||
1353 | |||
1354 | // select step within view |
||
1355 | ui_selected_step = (ui_selected_step_view << 4) | (ui_selected_step & 0xf); |
||
1356 | } |
||
1357 | |||
1358 | char buffer[20]; |
||
1359 | sprintf(buffer, "%d-%d", ui_selected_step_view*16 + 1, ui_selected_step_view*16 + 16); |
||
1360 | SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "Step View", buffer); |
||
1361 | |||
1362 | return 0; // no error |
||
1363 | } |
||
1364 | |||
513 | tk | 1365 | static s32 SEQ_UI_Button_TrackSel(s32 depressed) |
134 | tk | 1366 | { |
513 | tk | 1367 | static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE; |
134 | tk | 1368 | |
513 | tk | 1369 | if( seq_hwcfg_button_beh.track_sel ) { |
1370 | if( depressed ) return -1; // ignore when button depressed |
||
678 | tk | 1371 | if( !seq_ui_button_state.TRACK_SEL ) // due to page change: button going to be set, clear other toggle buttons |
1372 | seq_ui_button_state.PAGE_CHANGE_BUTTON_FLAGS = 0; |
||
513 | tk | 1373 | seq_ui_button_state.TRACK_SEL ^= 1; // toggle TRACKSEL status (will also be released once GP button has been pressed) |
1374 | } else { |
||
1375 | seq_ui_button_state.TRACK_SEL = depressed ? 0 : 1; |
||
1376 | } |
||
1377 | |||
1378 | if( seq_ui_button_state.TRACK_SEL ) { |
||
1379 | prev_page = ui_page; |
||
1380 | SEQ_UI_PageSet(SEQ_UI_PAGE_TRACKSEL); |
||
1381 | } else { |
||
524 | tk | 1382 | if( ui_page == SEQ_UI_PAGE_TRACKSEL ) |
1383 | SEQ_UI_PageSet(prev_page); |
||
513 | tk | 1384 | } |
1385 | |||
134 | tk | 1386 | return 0; // no error |
1387 | } |
||
1388 | |||
987 | tk | 1389 | static s32 SEQ_UI_Button_Group(s32 depressed, u32 group) |
1390 | { |
||
1391 | if( depressed ) return -1; // ignore when button depressed |
||
1392 | |||
1393 | if( group >= 4 ) return -2; // max. 4 group buttons |
||
1394 | |||
1395 | // in song page: track and group buttons are used to select the cursor position |
||
1396 | if( ui_page == SEQ_UI_PAGE_SONG ) { |
||
1397 | ui_selected_item = 3 + group; |
||
1398 | return 0; |
||
1399 | } |
||
1400 | |||
1401 | // if group has changed: |
||
1402 | if( group != ui_selected_group ) { |
||
1403 | // get current track selection |
||
1404 | u16 old_tracks = ui_selected_tracks >> (4*ui_selected_group); |
||
1405 | |||
1406 | // select new group |
||
1407 | ui_selected_group = group; |
||
1408 | |||
1409 | // take over old track selection |
||
1410 | ui_selected_tracks = old_tracks << (4*ui_selected_group); |
||
1411 | } |
||
1412 | |||
1413 | // set/clear encoder fast function if required |
||
1414 | SEQ_UI_InitEncSpeed(1); // auto config |
||
1415 | |||
1416 | return 0; // no error |
||
1417 | } |
||
1418 | |||
484 | tk | 1419 | static s32 SEQ_UI_Button_Track(s32 depressed, u32 track_button) |
134 | tk | 1420 | { |
484 | tk | 1421 | static u8 button_state = 0x0f; // all 4 buttons depressed |
134 | tk | 1422 | |
484 | tk | 1423 | if( track_button >= 4 ) return -2; // max. 4 track buttons |
134 | tk | 1424 | |
484 | tk | 1425 | if( depressed ) { |
1426 | button_state |= (1 << track_button); |
||
1427 | return 0; // no error |
||
1428 | } |
||
134 | tk | 1429 | |
484 | tk | 1430 | button_state &= ~(1 << track_button); |
1431 | |||
987 | tk | 1432 | // in pattern and song page: use track buttons as group buttons |
1433 | if( ui_page == SEQ_UI_PAGE_PATTERN || ui_page == SEQ_UI_PAGE_SONG ) { |
||
1434 | return SEQ_UI_Button_Group(depressed, track_button); |
||
1435 | } |
||
1436 | |||
484 | tk | 1437 | if( button_state == (~(1 << track_button) & 0xf) ) { |
1438 | // if only one select button pressed: radio-button function (1 of 4) |
||
1439 | ui_selected_tracks = 1 << (track_button + 4*ui_selected_group); |
||
1440 | } else { |
||
1441 | // if more than one select button pressed: toggle function (4 of 4) |
||
1442 | ui_selected_tracks ^= 1 << (track_button + 4*ui_selected_group); |
||
1443 | } |
||
1444 | |||
178 | tk | 1445 | // set/clear encoder fast function if required |
1446 | SEQ_UI_InitEncSpeed(1); // auto config |
||
1447 | |||
134 | tk | 1448 | return 0; // no error |
1449 | } |
||
1450 | |||
1146 | tk | 1451 | static s32 SEQ_UI_Button_DirectTrack(s32 depressed, u32 track_button) |
1452 | { |
||
1453 | static u16 button_state = 0xffff; // all 16 buttons depressed |
||
1454 | |||
1455 | if( track_button >= 16 ) return -2; // max. 16 direct track buttons |
||
1456 | |||
1457 | if( depressed ) { |
||
1458 | button_state |= (1 << track_button); |
||
1459 | return 0; // no error |
||
1460 | } |
||
1461 | |||
1462 | button_state &= ~(1 << track_button); |
||
1463 | |||
1464 | if( button_state == (~(1 << track_button) & 0xffff) ) { |
||
1465 | // if only one select button pressed: radio-button function (1 of 16) |
||
1466 | ui_selected_tracks = 1 << track_button; |
||
1488 | tk | 1467 | ui_selected_group = track_button / 4; |
1146 | tk | 1468 | } else { |
1469 | // if more than one select button pressed: toggle function (16 of 16) |
||
1470 | ui_selected_tracks ^= 1 << track_button; |
||
1471 | } |
||
1472 | |||
1473 | // set/clear encoder fast function if required |
||
1474 | SEQ_UI_InitEncSpeed(1); // auto config |
||
1475 | |||
1476 | return 0; // no error |
||
1477 | } |
||
1478 | |||
513 | tk | 1479 | static s32 SEQ_UI_Button_ParLayerSel(s32 depressed) |
1480 | { |
||
600 | tk | 1481 | // static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE; |
1482 | // also used by seq_ui_parsel.c |
||
513 | tk | 1483 | |
1484 | if( seq_hwcfg_button_beh.par_layer ) { |
||
1485 | if( depressed ) return -1; // ignore when button depressed |
||
678 | tk | 1486 | if( !seq_ui_button_state.PAR_LAYER_SEL ) // due to page change: button going to be set, clear other toggle buttons |
1487 | seq_ui_button_state.PAGE_CHANGE_BUTTON_FLAGS = 0; |
||
513 | tk | 1488 | seq_ui_button_state.PAR_LAYER_SEL ^= 1; // toggle PARSEL status (will also be released once GP button has been pressed) |
1489 | } else { |
||
1490 | seq_ui_button_state.PAR_LAYER_SEL = depressed ? 0 : 1; |
||
1491 | } |
||
1492 | |||
1493 | if( seq_ui_button_state.PAR_LAYER_SEL ) { |
||
600 | tk | 1494 | ui_parlayer_prev_page = ui_page; |
513 | tk | 1495 | SEQ_UI_PageSet(SEQ_UI_PAGE_PARSEL); |
1496 | } else { |
||
524 | tk | 1497 | if( ui_page == SEQ_UI_PAGE_PARSEL ) |
600 | tk | 1498 | SEQ_UI_PageSet(ui_parlayer_prev_page); |
513 | tk | 1499 | } |
1500 | |||
1501 | // set/clear encoder fast function if required |
||
1502 | SEQ_UI_InitEncSpeed(1); // auto config |
||
1503 | |||
1504 | return 0; // no error |
||
1505 | } |
||
1506 | |||
134 | tk | 1507 | static s32 SEQ_UI_Button_ParLayer(s32 depressed, u32 par_layer) |
1508 | { |
||
1117 | tk | 1509 | static u8 layer_c_pressed = 0; |
784 | tk | 1510 | |
134 | tk | 1511 | if( par_layer >= 3 ) return -2; // max. 3 parlayer buttons |
1512 | |||
1205 | tk | 1513 | u8 visible_track = SEQ_UI_VisibleTrackGet(); |
1514 | u8 num_p_layers = SEQ_PAR_NumLayersGet(visible_track); |
||
1515 | |||
987 | tk | 1516 | // in song page: parameter layer buttons are used to select the cursor position |
1517 | if( ui_page == SEQ_UI_PAGE_SONG ) { |
||
1518 | ui_selected_item = par_layer; |
||
1519 | return 0; |
||
1520 | } |
||
1521 | |||
1205 | tk | 1522 | // drum mode in edit page: print parameter layer as long as button is pressed |
1523 | if( ui_page == SEQ_UI_PAGE_EDIT ) { |
||
1524 | u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE); |
||
1525 | if( event_mode == SEQ_EVENT_MODE_Drum ) { |
||
1526 | ui_hold_msg_ctr = depressed ? 0 : ~0; // show value for at least 65 seconds... enough? |
||
1527 | } |
||
1528 | } |
||
134 | tk | 1529 | |
784 | tk | 1530 | // holding Layer C button allows to increment/decrement layer with A/B button |
1531 | if( par_layer == 2 ) |
||
1532 | layer_c_pressed = !depressed; |
||
1533 | |||
1534 | if( layer_c_pressed && par_layer == 0 ) { |
||
333 | tk | 1535 | if( depressed ) return -1; // ignore when button depressed |
784 | tk | 1536 | // increment layer |
1537 | if( ++ui_selected_par_layer >= num_p_layers ) |
||
1538 | ui_selected_par_layer = 0; |
||
1539 | } else if( layer_c_pressed && par_layer == 1 ) { |
||
333 | tk | 1540 | if( depressed ) return -1; // ignore when button depressed |
784 | tk | 1541 | // decrement layer |
1542 | if( ui_selected_par_layer == 0 ) |
||
1543 | ui_selected_par_layer = num_p_layers - 1; |
||
333 | tk | 1544 | else |
784 | tk | 1545 | --ui_selected_par_layer; |
333 | tk | 1546 | } else { |
784 | tk | 1547 | if( num_p_layers <= 3 ) { |
1548 | // 3 layers: direct selection with LayerA/B/C button |
||
333 | tk | 1549 | if( depressed ) return -1; // ignore when button depressed |
784 | tk | 1550 | if( par_layer >= num_p_layers ) { |
1551 | char str1[21]; |
||
1552 | sprintf(str1, "Parameter Layer %c", 'A'+par_layer); |
||
1553 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, str1, "not available!"); |
||
1554 | } else { |
||
1555 | seq_ui_button_state.PAR_LAYER_SEL = 0; |
||
1556 | ui_selected_par_layer = par_layer; |
||
1557 | } |
||
1558 | } else if( num_p_layers <= 4 ) { |
||
1559 | // 4 layers: LayerC Button toggles between C and D |
||
1560 | if( depressed ) return -1; // ignore when button depressed |
||
333 | tk | 1561 | seq_ui_button_state.PAR_LAYER_SEL = 0; |
784 | tk | 1562 | if( par_layer == 2 ) |
1563 | ui_selected_par_layer = (ui_selected_par_layer == 2) ? 3 : 2; |
||
1564 | else |
||
1565 | ui_selected_par_layer = par_layer; |
||
333 | tk | 1566 | } else { |
784 | tk | 1567 | // >4 layers: LayerA/B button selects directly, Layer C button enters layer selection page |
1568 | if( par_layer <= 1 ) { |
||
1569 | if( depressed ) return -1; // ignore when button depressed |
||
1570 | seq_ui_button_state.PAR_LAYER_SEL = 0; |
||
1571 | ui_selected_par_layer = par_layer; |
||
1572 | } else { |
||
1573 | return SEQ_UI_Button_ParLayerSel(depressed); |
||
1574 | } |
||
333 | tk | 1575 | } |
1576 | } |
||
1577 | |||
178 | tk | 1578 | // set/clear encoder fast function if required |
1579 | SEQ_UI_InitEncSpeed(1); // auto config |
||
1580 | |||
134 | tk | 1581 | return 0; // no error |
1582 | } |
||
1583 | |||
513 | tk | 1584 | static s32 SEQ_UI_Button_TrgLayerSel(s32 depressed) |
1585 | { |
||
600 | tk | 1586 | // static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE; |
1587 | // also used by seq_ui_trgsel.c |
||
513 | tk | 1588 | |
1589 | if( seq_hwcfg_button_beh.trg_layer ) { |
||
1590 | if( depressed ) return -1; // ignore when button depressed |
||
678 | tk | 1591 | if( !seq_ui_button_state.TRG_LAYER_SEL ) // due to page change: button going to be set, clear other toggle buttons |
1592 | seq_ui_button_state.PAGE_CHANGE_BUTTON_FLAGS = 0; |
||
513 | tk | 1593 | seq_ui_button_state.TRG_LAYER_SEL ^= 1; // toggle TRGSEL status (will also be released once GP button has been pressed) |
1594 | } else { |
||
1595 | seq_ui_button_state.TRG_LAYER_SEL = depressed ? 0 : 1; |
||
1596 | } |
||
1597 | |||
1598 | if( seq_ui_button_state.TRG_LAYER_SEL ) { |
||
600 | tk | 1599 | ui_trglayer_prev_page = ui_page; |
513 | tk | 1600 | SEQ_UI_PageSet(SEQ_UI_PAGE_TRGSEL); |
1601 | } else { |
||
524 | tk | 1602 | if( ui_page == SEQ_UI_PAGE_TRGSEL ) |
600 | tk | 1603 | SEQ_UI_PageSet(ui_trglayer_prev_page); |
513 | tk | 1604 | } |
1605 | |||
1606 | return 0; // no error |
||
1607 | } |
||
1608 | |||
134 | tk | 1609 | static s32 SEQ_UI_Button_TrgLayer(s32 depressed, u32 trg_layer) |
1610 | { |
||
1117 | tk | 1611 | static u8 layer_c_pressed = 0; |
784 | tk | 1612 | |
134 | tk | 1613 | if( trg_layer >= 3 ) return -2; // max. 3 trglayer buttons |
1614 | |||
326 | tk | 1615 | u8 visible_track = SEQ_UI_VisibleTrackGet(); |
1616 | u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE); |
||
1617 | u8 num_t_layers = SEQ_TRG_NumLayersGet(visible_track); |
||
134 | tk | 1618 | |
1205 | tk | 1619 | // drum mode in edit page: ensure that trigger layer is print again |
1620 | if( ui_page == SEQ_UI_PAGE_EDIT ) { |
||
1621 | u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE); |
||
1622 | if( event_mode == SEQ_EVENT_MODE_Drum ) { |
||
1623 | if( !depressed ) |
||
1624 | ui_hold_msg_ctr = 0; |
||
1625 | } |
||
1626 | } |
||
1627 | |||
784 | tk | 1628 | // holding Layer C button allows to increment/decrement layer with A/B button |
1629 | if( trg_layer == 2 ) |
||
1630 | layer_c_pressed = !depressed; |
||
1631 | |||
1632 | if( layer_c_pressed && trg_layer == 0 ) { |
||
326 | tk | 1633 | if( depressed ) return -1; // ignore when button depressed |
784 | tk | 1634 | // increment layer |
1635 | if( ++ui_selected_trg_layer >= num_t_layers ) |
||
1636 | ui_selected_trg_layer = 0; |
||
1637 | } else if( layer_c_pressed && trg_layer == 1 ) { |
||
326 | tk | 1638 | if( depressed ) return -1; // ignore when button depressed |
784 | tk | 1639 | // decrement layer |
1640 | if( ui_selected_trg_layer == 0 ) |
||
1641 | ui_selected_trg_layer = num_t_layers - 1; |
||
326 | tk | 1642 | else |
784 | tk | 1643 | --ui_selected_trg_layer; |
326 | tk | 1644 | } else { |
784 | tk | 1645 | if( event_mode != SEQ_EVENT_MODE_Drum && num_t_layers <= 3 ) { |
1646 | // 3 layers: direct selection with LayerA/B/C button |
||
326 | tk | 1647 | if( depressed ) return -1; // ignore when button depressed |
784 | tk | 1648 | if( trg_layer >= num_t_layers ) { |
1649 | char str1[21]; |
||
1650 | sprintf(str1, "Trigger Layer %c", 'A'+trg_layer); |
||
1651 | SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, str1, "not available!"); |
||
1652 | } else { |
||
1653 | seq_ui_button_state.TRG_LAYER_SEL = 0; |
||
1654 | ui_selected_trg_layer = trg_layer; |
||
1655 | } |
||
1656 | } else if( event_mode != SEQ_EVENT_MODE_Drum && num_t_layers <= 4 ) { |
||
1657 | // 4 layers: LayerC Button toggles between C and D |
||
1658 | if( depressed ) return -1; // ignore when button depressed |
||
328 | tk | 1659 | seq_ui_button_state.TRG_LAYER_SEL = 0; |
784 | tk | 1660 | if( trg_layer == 2 ) |
1661 | ui_selected_trg_layer = (ui_selected_trg_layer == 2) ? 3 : 2; |
||
1662 | else |
||
1663 | ui_selected_trg_layer = trg_layer; |
||
326 | tk | 1664 | } else { |
784 | tk | 1665 | // >4 layers or drum mode: LayerA/B button selects directly, Layer C button enters trigger selection page |
1666 | // also used for drum tracks |
||
1667 | if( trg_layer <= 1 ) { |
||
1668 | if( depressed ) return -1; // ignore when button depressed |
||
1669 | seq_ui_button_state.TRG_LAYER_SEL = 0; |
||
1670 | ui_selected_trg_layer = trg_layer; |
||
1671 | } else { |
||
1672 | return SEQ_UI_Button_TrgLayerSel(depressed); |
||
1673 | } |
||
326 | tk | 1674 | } |
1675 | } |
||
1676 | |||
134 | tk | 1677 | return 0; // no error |
1678 | } |
||
1679 | |||
1680 | |||
1119 | tk | 1681 | static s32 SEQ_UI_Button_Mixer(s32 depressed) |
544 | tk | 1682 | { |
1683 | if( depressed ) return -1; // ignore when button depressed |
||
134 | tk | 1684 | |
1119 | tk | 1685 | SEQ_UI_PageSet(SEQ_UI_PAGE_MIXER); |
544 | tk | 1686 | |
1687 | return 0; // no error |
||
1688 | } |
||
1689 | |||
1119 | tk | 1690 | static s32 SEQ_UI_Button_TrackMode(s32 depressed) |
544 | tk | 1691 | { |
1692 | if( depressed ) return -1; // ignore when button depressed |
||
1693 | |||
1119 | tk | 1694 | SEQ_UI_PageSet(SEQ_UI_PAGE_TRKMODE); |
544 | tk | 1695 | |
1696 | return 0; // no error |
||
1697 | } |
||
1698 | |||
1119 | tk | 1699 | static s32 SEQ_UI_Button_TrackGroove(s32 depressed) |
544 | tk | 1700 | { |
1701 | if( depressed ) return -1; // ignore when button depressed |
||
1702 | |||
1119 | tk | 1703 | SEQ_UI_PageSet(SEQ_UI_PAGE_TRKGRV); |
1704 | |||
1705 | return 0; // no error |
||
1706 | } |
||
1707 | |||
1708 | static s32 SEQ_UI_Button_TrackLength(s32 depressed) |
||
1709 | { |
||
1710 | if( depressed ) return -1; // ignore when button depressed |
||
1711 | |||
1712 | SEQ_UI_PageSet(SEQ_UI_PAGE_TRKLEN); |
||
1713 | |||
1714 | return 0; // no error |
||
1715 | } |
||
1716 | |||
1717 | static s32 SEQ_UI_Button_TrackDirection(s32 depressed) |
||
1718 | { |
||
1719 | if( depressed ) return -1; // ignore when button depressed |
||
1720 | |||
1721 | SEQ_UI_PageSet(SEQ_UI_PAGE_TRKDIR); |
||
1722 | |||
1723 | return 0; // no error |
||
1724 | } |
||
1725 | |||
1726 | static s32 SEQ_UI_Button_TrackMorph(s32 depressed) |
||
1727 | { |
||
1728 | if( depressed ) return -1; // ignore when button depressed |
||
1729 | |||
1730 | SEQ_UI_PageSet(SEQ_UI_PAGE_TRKMORPH); |
||
1731 | |||
1732 | return 0; // no error |
||
1733 | } |
||
1734 | |||
1735 | static s32 SEQ_UI_Button_TrackTranspose(s32 depressed) |
||
1736 | { |
||
1737 | if( depressed ) return -1; // ignore when button depressed |
||
1738 | |||
544 | tk | 1739 | SEQ_UI_PageSet(SEQ_UI_PAGE_TRKTRAN); |
1740 | |||
1741 | return 0; // no error |
||
1742 | } |
||
1743 | |||
1744 | |||
742 | tk | 1745 | // only used by keyboard remote function |
1746 | static s32 SEQ_UI_Button_ToggleGate(s32 depressed) |
||
1747 | { |
||
1748 | if( depressed ) return -1; // ignore when button depressed |
||
544 | tk | 1749 | |
742 | tk | 1750 | u8 visible_track = SEQ_UI_VisibleTrackGet(); |
1751 | u8 gate = SEQ_TRG_GateGet(visible_track, ui_selected_step, ui_selected_instrument) ? 0 : 1; |
||
1752 | SEQ_TRG_GateSet(visible_track, ui_selected_step, ui_selected_instrument, gate); |
||
544 | tk | 1753 | |
742 | tk | 1754 | return 0; // no error |
1755 | } |
||
1756 | |||
1349 | tk | 1757 | static s32 SEQ_UI_Button_FootSwitch(s32 depressed) |
1758 | { |
||
1759 | // static variables (only used here, therefore local) |
||
1760 | static u32 fs_time_control = 0; // timestamp of last operation |
||
1761 | static u8 fs_mode = 0; // mode |
||
742 | tk | 1762 | |
1349 | tk | 1763 | // this is used as a constant value |
1764 | u32 fs_time_delay = 1000; // mS - should this be configurable? |
||
742 | tk | 1765 | |
1349 | tk | 1766 | |
1767 | // PUNCH_IN, PUNCH_OUT and Delete track data control |
||
1768 | if( !depressed ) { |
||
1769 | if( ( fs_time_control > (seq_core_timestamp_ms - fs_time_delay) ) && ( fs_time_control != 0 ) ) |
||
1770 | { |
||
1771 | // that confirms the delete function |
||
1772 | fs_mode = 1; // delete |
||
1773 | } else { |
||
1774 | // start time in count |
||
1775 | fs_time_control = seq_core_timestamp_ms; |
||
1776 | } |
||
1777 | } else { |
||
1778 | // if time pressed is less than fs_time_delay miliseconds, we got a possible delete function activation |
||
1779 | if( fs_time_control > (seq_core_timestamp_ms - fs_time_delay) ) |
||
1780 | { |
||
1781 | switch( fs_mode ) { |
||
1782 | case 1: { // delete |
||
1783 | SEQ_UI_Button_Clear_Track(0); |
||
1784 | fs_mode = 0; // back to normal mode, later we would increment the value |
||
1785 | } break; |
||
1786 | default: |
||
1787 | fs_mode = 0; // for the case that an invalid mode is selected |
||
1788 | } |
||
1789 | |||
1790 | fs_time_control = seq_core_timestamp_ms; |
||
1791 | } |
||
1792 | } |
||
1793 | |||
1794 | if( depressed ) { |
||
1795 | // disable recording |
||
1796 | seq_record_state.ENABLED = 0; |
||
1797 | } else { |
||
1798 | // enable recording |
||
1799 | seq_record_state.ENABLED = 1; |
||
1800 | seq_record_state.ARMED_TRACKS = ui_selected_tracks; // not used yet, just preparation for future changes |
||
1801 | } |
||
1802 | |||
1803 | return 0; // no error |
||
1804 | } |
||
1805 | |||
1806 | |||
134 | tk | 1807 | ///////////////////////////////////////////////////////////////////////////// |
1808 | // Button handler |
||
1809 | ///////////////////////////////////////////////////////////////////////////// |
||
1810 | s32 SEQ_UI_Button_Handler(u32 pin, u32 pin_value) |
||
1811 | { |
||
492 | tk | 1812 | int i; |
1813 | |||
625 | tk | 1814 | // send MIDI event in remote mode and exit |
1316 | tk | 1815 | if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT ) |
625 | tk | 1816 | return SEQ_MIDI_SYSEX_REMOTE_Client_SendButton(pin, pin_value); |
1817 | |||
1044 | tk | 1818 | // ignore as long as hardware config hasn't been read |
496 | tk | 1819 | if( !SEQ_FILE_HW_ConfigLocked() ) |
1820 | return -1; |
||
1821 | |||
740 | tk | 1822 | // ignore during a backup or format is created |
1823 | if( seq_ui_backup_req || seq_ui_format_req ) |
||
634 | tk | 1824 | return -1; |
1825 | |||
328 | tk | 1826 | // ensure that selections are matching with track constraints |
1827 | SEQ_UI_CheckSelections(); |
||
1828 | |||
492 | tk | 1829 | // request display update |
1830 | seq_ui_display_update_req = 1; |
||
134 | tk | 1831 | |
596 | tk | 1832 | // stop current message if (new) button has been pressed |
1833 | if( pin_value == 0 ) |
||
1834 | SEQ_UI_MsgStop(); |
||
134 | tk | 1835 | |
596 | tk | 1836 | |
492 | tk | 1837 | // MEMO: we could also use a jump table with references to the functions |
1838 | // here, but this "spagetthi code" simplifies the configuration and |
||
1839 | // the resulting ASM doesn't look that bad! |
||
168 | tk | 1840 | |
492 | tk | 1841 | for(i=0; i<SEQ_HWCFG_NUM_GP; ++i) |
1842 | if( pin == seq_hwcfg_button.gp[i] ) |
||
1843 | return SEQ_UI_Button_GP(pin_value, i); |
||
134 | tk | 1844 | |
492 | tk | 1845 | for(i=0; i<SEQ_HWCFG_NUM_TRACK; ++i) |
1846 | if( pin == seq_hwcfg_button.track[i] ) |
||
1847 | return SEQ_UI_Button_Track(pin_value, i); |
||
1146 | tk | 1848 | |
1849 | for(i=0; i<SEQ_HWCFG_NUM_DIRECT_TRACK; ++i) |
||
1850 | if( pin == seq_hwcfg_button.direct_track[i] ) |
||
1851 | return SEQ_UI_Button_DirectTrack(pin_value, i); |
||
1852 | |||
1205 | tk | 1853 | for(i=0; i<SEQ_HWCFG_NUM_DIRECT_BOOKMARK; ++i) |
1854 | if( pin == seq_hwcfg_button.direct_bookmark[i] ) |
||
1855 | return SEQ_UI_Button_DirectBookmark(pin_value, i); |
||
1856 | |||
513 | tk | 1857 | if( pin == seq_hwcfg_button.track_sel ) |
1858 | return SEQ_UI_Button_TrackSel(pin_value); |
||
134 | tk | 1859 | |
492 | tk | 1860 | for(i=0; i<SEQ_HWCFG_NUM_GROUP; ++i) |
1861 | if( pin == seq_hwcfg_button.group[i] ) |
||
1862 | return SEQ_UI_Button_Group(pin_value, i); |
||
134 | tk | 1863 | |
492 | tk | 1864 | for(i=0; i<SEQ_HWCFG_NUM_PAR_LAYER; ++i) |
1865 | if( pin == seq_hwcfg_button.par_layer[i] ) |
||
1866 | return SEQ_UI_Button_ParLayer(pin_value, i); |
||
513 | tk | 1867 | if( pin == seq_hwcfg_button.par_layer_sel ) |
1868 | return SEQ_UI_Button_ParLayerSel(pin_value); |
||
134 | tk | 1869 | |
492 | tk | 1870 | for(i=0; i<SEQ_HWCFG_NUM_TRG_LAYER; ++i) |
1871 | if( pin == seq_hwcfg_button.trg_layer[i] ) |
||
1872 | return SEQ_UI_Button_TrgLayer(pin_value, i); |
||
513 | tk | 1873 | if( pin == seq_hwcfg_button.trg_layer_sel ) |
1874 | return SEQ_UI_Button_TrgLayerSel(pin_value); |
||
134 | tk | 1875 | |
492 | tk | 1876 | if( pin == seq_hwcfg_button.left ) |
1877 | return SEQ_UI_Button_Left(pin_value); |
||
1878 | if( pin == seq_hwcfg_button.right ) |
||
1879 | return SEQ_UI_Button_Right(pin_value); |
||
1880 | if( pin == seq_hwcfg_button.down ) |
||
1881 | return SEQ_UI_Button_Down(pin_value); |
||
1882 | if( pin == seq_hwcfg_button.up ) |
||
1883 | return SEQ_UI_Button_Up(pin_value); |
||
134 | tk | 1884 | |
492 | tk | 1885 | if( pin == seq_hwcfg_button.scrub ) |
1886 | return SEQ_UI_Button_Scrub(pin_value); |
||
1887 | if( pin == seq_hwcfg_button.metronome ) |
||
1888 | return SEQ_UI_Button_Metronome(pin_value); |
||
134 | tk | 1889 | |
630 | tk | 1890 | if( pin == seq_hwcfg_button.record ) |
1891 | return SEQ_UI_Button_Record(pin_value); |
||
1219 | tk | 1892 | if( pin == seq_hwcfg_button.live ) |
1893 | return SEQ_UI_Button_Live(pin_value); |
||
630 | tk | 1894 | |
492 | tk | 1895 | if( pin == seq_hwcfg_button.stop ) |
1896 | return SEQ_UI_Button_Stop(pin_value); |
||
1897 | if( pin == seq_hwcfg_button.pause ) |
||
1898 | return SEQ_UI_Button_Pause(pin_value); |
||
1899 | if( pin == seq_hwcfg_button.play ) |
||
1900 | return SEQ_UI_Button_Play(pin_value); |
||
1901 | if( pin == seq_hwcfg_button.rew ) |
||
1902 | return SEQ_UI_Button_Rew(pin_value); |
||
1903 | if( pin == seq_hwcfg_button.fwd ) |
||
1904 | return SEQ_UI_Button_Fwd(pin_value); |
||
596 | tk | 1905 | if( pin == seq_hwcfg_button.loop ) |
1906 | return SEQ_UI_Button_Loop(pin_value); |
||
973 | tk | 1907 | if( pin == seq_hwcfg_button.follow ) |
1908 | return SEQ_UI_Button_Follow(pin_value); |
||
134 | tk | 1909 | |
492 | tk | 1910 | if( pin == seq_hwcfg_button.utility ) |
1911 | return SEQ_UI_Button_Utility(pin_value); |
||
1912 | if( pin == seq_hwcfg_button.copy ) |
||
1913 | return SEQ_UI_Button_Copy(pin_value); |
||
1914 | if( pin == seq_hwcfg_button.paste ) |
||
1915 | return SEQ_UI_Button_Paste(pin_value); |
||
1916 | if( pin == seq_hwcfg_button.clear ) |
||
1917 | return SEQ_UI_Button_Clear(pin_value); |
||
1014 | tk | 1918 | if( pin == seq_hwcfg_button.undo ) |
1919 | return SEQ_UI_Button_Undo(pin_value); |
||
134 | tk | 1920 | |
492 | tk | 1921 | if( pin == seq_hwcfg_button.menu ) |
1922 | return SEQ_UI_Button_Menu(pin_value); |
||
1203 | tk | 1923 | if( pin == seq_hwcfg_button.bookmark ) |
1924 | return SEQ_UI_Button_Bookmark(pin_value); |
||
492 | tk | 1925 | if( pin == seq_hwcfg_button.select ) |
1926 | return SEQ_UI_Button_Select(pin_value); |
||
1927 | if( pin == seq_hwcfg_button.exit ) |
||
1928 | return SEQ_UI_Button_Exit(pin_value); |
||
134 | tk | 1929 | |
513 | tk | 1930 | if( pin == seq_hwcfg_button.tap_tempo ) |
1931 | return SEQ_UI_Button_TapTempo(pin_value); |
||
1932 | if( pin == seq_hwcfg_button.tempo_preset ) |
||
1933 | return SEQ_UI_Button_TempoPreset(pin_value); |
||
524 | tk | 1934 | if( pin == seq_hwcfg_button.ext_restart ) |
1935 | return SEQ_UI_Button_ExtRestart(pin_value); |
||
134 | tk | 1936 | |
492 | tk | 1937 | if( pin == seq_hwcfg_button.edit ) |
1938 | return SEQ_UI_Button_Edit(pin_value); |
||
1939 | if( pin == seq_hwcfg_button.mute ) |
||
1940 | return SEQ_UI_Button_Mute(pin_value); |
||
1941 | if( pin == seq_hwcfg_button.pattern ) |
||
1942 | return SEQ_UI_Button_Pattern(pin_value); |
||
1943 | if( pin == seq_hwcfg_button.song ) |
||
1944 | return SEQ_UI_Button_Song(pin_value); |
||
134 | tk | 1945 | |
492 | tk | 1946 | if( pin == seq_hwcfg_button.solo ) |
1947 | return SEQ_UI_Button_Solo(pin_value); |
||
1948 | if( pin == seq_hwcfg_button.fast ) |
||
1949 | return SEQ_UI_Button_Fast(pin_value); |
||
1121 | tk | 1950 | if( pin == seq_hwcfg_button.fast2 ) |
1951 | return SEQ_UI_Button_Fast2(pin_value); |
||
492 | tk | 1952 | if( pin == seq_hwcfg_button.all ) |
1953 | return SEQ_UI_Button_All(pin_value); |
||
134 | tk | 1954 | |
492 | tk | 1955 | if( pin == seq_hwcfg_button.step_view ) |
1956 | return SEQ_UI_Button_StepView(pin_value); |
||
134 | tk | 1957 | |
544 | tk | 1958 | if( pin == seq_hwcfg_button.mixer ) |
1959 | return SEQ_UI_Button_Mixer(pin_value); |
||
1960 | |||
1119 | tk | 1961 | if( pin == seq_hwcfg_button.track_mode ) |
1962 | return SEQ_UI_Button_TrackMode(pin_value); |
||
1963 | if( pin == seq_hwcfg_button.track_groove ) |
||
1964 | return SEQ_UI_Button_TrackGroove(pin_value); |
||
1965 | if( pin == seq_hwcfg_button.track_length ) |
||
1966 | return SEQ_UI_Button_TrackLength(pin_value); |
||
1967 | if( pin == seq_hwcfg_button.track_direction ) |
||
1968 | return SEQ_UI_Button_TrackDirection(pin_value); |
||
1969 | if( pin == seq_hwcfg_button.track_morph ) |
||
1970 | return SEQ_UI_Button_TrackMorph(pin_value); |
||
1971 | if( pin == seq_hwcfg_button.track_transpose ) |
||
1972 | return SEQ_UI_Button_TrackTranspose(pin_value); |
||
1349 | tk | 1973 | if( pin == seq_hwcfg_button.footswitch ) |
1974 | return SEQ_UI_Button_FootSwitch(pin_value); |
||
1454 | midilab | 1975 | if( pin == seq_hwcfg_button.pattern_remix ) |
1976 | return SEQ_UI_Button_Pattern_Remix(pin_value); |
||
625 | tk | 1977 | // always print debugging message |
1978 | #if 1 |
||
1081 | tk | 1979 | MUTEX_MIDIOUT_TAKE; |
1980 | DEBUG_MSG("[SEQ_UI_Button_Handler] Button SR:%d, Pin:%d not mapped, it has been %s.\n", |
||
1981 | (pin >> 3) + 1, |
||
1982 | pin & 7, |
||
1983 | pin_value ? "depressed" : "pressed"); |
||
1984 | MUTEX_MIDIOUT_GIVE; |
||
625 | tk | 1985 | #endif |
1986 | |||
492 | tk | 1987 | return -1; // button not mapped |
134 | tk | 1988 | } |
1989 | |||
1990 | |||
1991 | ///////////////////////////////////////////////////////////////////////////// |
||
524 | tk | 1992 | // BLM Button handler |
1993 | ///////////////////////////////////////////////////////////////////////////// |
||
1994 | s32 SEQ_UI_BLM_Button_Handler(u32 row, u32 pin, u32 pin_value) |
||
1995 | { |
||
625 | tk | 1996 | // send MIDI event in remote mode and exit |
1316 | tk | 1997 | if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT ) |
625 | tk | 1998 | return SEQ_MIDI_SYSEX_REMOTE_Client_Send_BLM_Button(row, pin, pin_value); |
1999 | |||
1044 | tk | 2000 | // ignore as long as hardware config hasn't been read |
524 | tk | 2001 | if( !SEQ_FILE_HW_ConfigLocked() ) |
2002 | return -1; |
||
2003 | |||
740 | tk | 2004 | // ignore during a backup or format is created |
2005 | if( seq_ui_backup_req || seq_ui_format_req ) |
||
634 | tk | 2006 | return -1; |
2007 | |||
524 | tk | 2008 | if( row >= SEQ_CORE_NUM_TRACKS_PER_GROUP ) |
2009 | return -1; // more than 4 tracks not supported (yet) - could be done in this function w/o much effort |
||
2010 | |||
2011 | if( pin >= 16 ) |
||
2012 | return -1; // more than 16 step buttons not supported (yet) - could be done by selecting the step view |
||
2013 | |||
2014 | // select track depending on row |
||
2015 | ui_selected_tracks = 1 << (row + 4*ui_selected_group); |
||
2016 | |||
2017 | // ensure that selections are matching with track constraints |
||
2018 | SEQ_UI_CheckSelections(); |
||
2019 | |||
2020 | // request display update |
||
2021 | seq_ui_display_update_req = 1; |
||
2022 | |||
2023 | // emulate general purpose button |
||
758 | tk | 2024 | if( seq_hwcfg_blm.buttons_no_ui ) { |
763 | tk | 2025 | s32 status = SEQ_UI_EDIT_Button_Handler(pin, pin_value); |
758 | tk | 2026 | ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0; |
2027 | return status; |
||
763 | tk | 2028 | } |
2029 | |||
2030 | return SEQ_UI_Button_GP(pin_value, pin); // no error, pin_value and pin are swapped for this function due to consistency reasons |
||
524 | tk | 2031 | } |
2032 | |||
2033 | |||
2034 | ///////////////////////////////////////////////////////////////////////////// |
||
134 | tk | 2035 | // Encoder handler |
2036 | ///////////////////////////////////////////////////////////////////////////// |
||
2037 | s32 SEQ_UI_Encoder_Handler(u32 encoder, s32 incrementer) |
||
2038 | { |
||
625 | tk | 2039 | // send MIDI event in remote mode and exit |
1316 | tk | 2040 | if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT ) |
625 | tk | 2041 | return SEQ_MIDI_SYSEX_REMOTE_Client_SendEncoder(encoder, incrementer); |
2042 | |||
1044 | tk | 2043 | // ignore as long as hardware config hasn't been read |
496 | tk | 2044 | if( !SEQ_FILE_HW_ConfigLocked() ) |
2045 | return -1; |
||
2046 | |||
740 | tk | 2047 | // ignore during a backup or format is created |
2048 | if( seq_ui_backup_req || seq_ui_format_req ) |
||
634 | tk | 2049 | return -1; |
2050 | |||
1341 | tk | 2051 | if( encoder >= SEQ_HWCFG_NUM_ENCODERS ) |
134 | tk | 2052 | return -1; // encoder doesn't exist |
2053 | |||
328 | tk | 2054 | // ensure that selections are matching with track constraints |
2055 | SEQ_UI_CheckSelections(); |
||
2056 | |||
596 | tk | 2057 | // stop current message |
2058 | SEQ_UI_MsgStop(); |
||
2059 | |||
134 | tk | 2060 | // limit incrementer |
2061 | if( incrementer > 3 ) |
||
2062 | incrementer = 3; |
||
2063 | else if( incrementer < -3 ) |
||
2064 | incrementer = -3; |
||
2065 | |||
1341 | tk | 2066 | // encoder 17 increments BPM |
2067 | if( encoder == 17 ) { |
||
2068 | u16 value = (u16)(seq_core_bpm_preset_tempo[seq_core_bpm_preset_num]*10); |
||
2069 | if( SEQ_UI_Var16_Inc(&value, 25, 3000, incrementer) ) { // at 384ppqn, the minimum BPM rate is ca. 2.5 |
||
2070 | // set new BPM |
||
2071 | seq_core_bpm_preset_tempo[seq_core_bpm_preset_num] = (float)value/10.0; |
||
2072 | SEQ_CORE_BPM_Update(seq_core_bpm_preset_tempo[seq_core_bpm_preset_num], seq_core_bpm_preset_ramp[seq_core_bpm_preset_num]); |
||
2073 | //store_file_required = 1; |
||
2074 | seq_ui_display_update_req = 1; |
||
2075 | } |
||
2076 | return 0; |
||
2077 | } |
||
2078 | |||
607 | tk | 2079 | if( seq_ui_button_state.SCRUB && encoder == 0 ) { |
2080 | // if sequencer isn't already running, continue it (don't restart) |
||
2081 | if( !SEQ_BPM_IsRunning() ) |
||
2082 | SEQ_BPM_Cont(); |
||
2083 | ui_seq_pause = 0; // clear pause mode |
||
1278 | tk | 2084 | |
607 | tk | 2085 | // Scrub sequence back or forth |
2086 | portENTER_CRITICAL(); // should be atomic |
||
2087 | SEQ_CORE_Scrub(incrementer); |
||
2088 | portEXIT_CRITICAL(); |
||
2089 | } else if( !seq_ui_button_state.MENU_PRESSED && ui_encoder_callback != NULL ) { |
||
173 | tk | 2090 | ui_encoder_callback((encoder == 0) ? SEQ_UI_ENCODER_Datawheel : (encoder-1), incrementer); |
740 | tk | 2091 | ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0; // ensure that value is visible when it has been changed |
134 | tk | 2092 | } |
2093 | |||
2094 | // request display update |
||
159 | tk | 2095 | seq_ui_display_update_req = 1; |
134 | tk | 2096 | |
2097 | return 0; // no error |
||
2098 | } |
||
2099 | |||
2100 | |||
353 | tk | 2101 | |
134 | tk | 2102 | ///////////////////////////////////////////////////////////////////////////// |
626 | tk | 2103 | // Receives a MIDI package from APP_NotifyReceivedEvent (-> app.c) |
2104 | ///////////////////////////////////////////////////////////////////////////// |
||
2105 | s32 SEQ_UI_REMOTE_MIDI_Receive(mios32_midi_port_t port, mios32_midi_package_t midi_package) |
||
2106 | { |
||
2107 | #if 1 |
||
2108 | // check for active remote mode |
||
1316 | tk | 2109 | if( seq_midi_sysex_remote_active_mode != SEQ_MIDI_SYSEX_REMOTE_MODE_SERVER ) |
626 | tk | 2110 | return 0; // no error |
2111 | #endif |
||
2112 | |||
1316 | tk | 2113 | if( (seq_midi_sysex_remote_port == DEFAULT && seq_midi_sysex_remote_active_port != port) || |
2114 | (seq_midi_sysex_remote_port != DEFAULT && port != seq_midi_sysex_remote_port) ) |
||
626 | tk | 2115 | return 0; // wrong port |
2116 | |||
2117 | // for easier parsing: convert Note Off -> Note On with velocity 0 |
||
2118 | if( midi_package.event == NoteOff ) { |
||
2119 | midi_package.event = NoteOn; |
||
2120 | midi_package.velocity = 0; |
||
2121 | } |
||
2122 | |||
2123 | switch( midi_package.event ) { |
||
2124 | case NoteOn: { |
||
2125 | switch( midi_package.chn ) { |
||
2126 | case Chn1: |
||
2127 | SEQ_UI_Button_Handler(midi_package.note + 0x00, midi_package.velocity ? 0 : 1); |
||
2128 | break; |
||
2129 | case Chn2: |
||
2130 | SEQ_UI_Button_Handler(midi_package.note + 0x80, midi_package.velocity ? 0 : 1); |
||
2131 | break; |
||
2132 | case Chn3: |
||
2133 | SEQ_UI_BLM_Button_Handler(midi_package.note >> 5, midi_package.note & 0x1f, midi_package.velocity ? 0 : 1); |
||
2134 | break; |
||
2135 | } |
||
2136 | } break; |
||
2137 | |||
2138 | case CC: { |
||
2139 | if( midi_package.cc_number >= 15 && midi_package.cc_number <= 31 ) |
||
2140 | SEQ_UI_Encoder_Handler(midi_package.cc_number-15, (int)midi_package.value - 0x40); |
||
2141 | } break; |
||
2142 | } |
||
2143 | |||
632 | tk | 2144 | return 1; // MIDI event has been taken for remote function -> don't forward to router/MIDI event parser |
626 | tk | 2145 | } |
2146 | |||
2147 | |||
2148 | ///////////////////////////////////////////////////////////////////////////// |
||
741 | tk | 2149 | // MIDI Remote Keyboard Function (called from SEQ_MIDI_IN) |
2150 | ///////////////////////////////////////////////////////////////////////////// |
||
742 | tk | 2151 | s32 SEQ_UI_REMOTE_MIDI_Keyboard(u8 key, u8 depressed) |
741 | tk | 2152 | { |
742 | tk | 2153 | #if 0 |
1316 | tk | 2154 | MIOS32_MIDI_SendDebugMessage("SEQ_MIDI_SYSEX_REMOTE_MIDI_Keyboard(%d, %d)\n", key, depressed); |
741 | tk | 2155 | #endif |
742 | tk | 2156 | |
2157 | switch( key ) { |
||
2158 | case 0x24: // C-2 |
||
2159 | return SEQ_UI_Button_GP(depressed, 0); |
||
2160 | case 0x25: // C#2 |
||
2161 | return SEQ_UI_Button_Track(depressed, 0); |
||
2162 | case 0x26: // D-2 |
||
2163 | return SEQ_UI_Button_GP(depressed, 1); |
||
2164 | case 0x27: // D#2 |
||
2165 | return SEQ_UI_Button_Track(depressed, 1); |
||
2166 | case 0x28: // E-2 |
||
2167 | return SEQ_UI_Button_GP(depressed, 2); |
||
2168 | case 0x29: // F-2 |
||
2169 | return SEQ_UI_Button_GP(depressed, 3); |
||
2170 | case 0x2a: // F#2 |
||
2171 | return SEQ_UI_Button_Track(depressed, 2); |
||
2172 | case 0x2b: // G-2 |
||
2173 | return SEQ_UI_Button_GP(depressed, 4); |
||
2174 | case 0x2c: // G#2 |
||
2175 | return SEQ_UI_Button_Track(depressed, 3); |
||
2176 | case 0x2d: // A-2 |
||
2177 | return SEQ_UI_Button_GP(depressed, 5); |
||
2178 | case 0x2e: // A#2 |
||
2179 | return SEQ_UI_Button_ParLayer(depressed, 0); |
||
2180 | case 0x2f: // B-2 |
||
2181 | return SEQ_UI_Button_GP(depressed, 6); |
||
2182 | |||
2183 | case 0x30: // C-3 |
||
2184 | return SEQ_UI_Button_GP(depressed, 7); |
||
2185 | case 0x31: // C#3 |
||
2186 | return SEQ_UI_Button_ParLayer(depressed, 1); |
||
2187 | case 0x32: // D-3 |
||
2188 | return SEQ_UI_Button_GP(depressed, 8); |
||
2189 | case 0x33: // D#3 |
||
2190 | return SEQ_UI_Button_ParLayer(depressed, 2); |
||
2191 | case 0x34: // E-3 |
||
2192 | return SEQ_UI_Button_GP(depressed, 9); |
||
2193 | case 0x35: // F-3 |
||
2194 | return SEQ_UI_Button_GP(depressed, 10); |
||
2195 | case 0x36: // F#3 |
||
2196 | return SEQ_UI_Button_TrgLayer(depressed, 0); |
||
2197 | case 0x37: // G-3 |
||
2198 | return SEQ_UI_Button_GP(depressed, 11); |
||
2199 | case 0x38: // G#3 |
||
2200 | return SEQ_UI_Button_TrgLayer(depressed, 1); |
||
2201 | case 0x39: // A-3 |
||
2202 | return SEQ_UI_Button_GP(depressed, 12); |
||
2203 | case 0x3a: // A#3 |
||
2204 | return SEQ_UI_Button_TrgLayer(depressed, 2); |
||
2205 | case 0x3b: // B-3 |
||
2206 | return SEQ_UI_Button_GP(depressed, 13); |
||
2207 | |||
2208 | case 0x3c: // C-4 |
||
2209 | return SEQ_UI_Button_GP(depressed, 14); |
||
2210 | case 0x3d: // C#4 |
||
2211 | return SEQ_UI_Button_Group(depressed, 0); |
||
2212 | case 0x3e: // D-4 |
||
2213 | return SEQ_UI_Button_GP(depressed, 15); |
||
2214 | case 0x3f: // D#4 |
||
2215 | return SEQ_UI_Button_Group(depressed, 1); |
||
2216 | case 0x40: // E-4 |
||
2217 | return 0; // ignore |
||
2218 | case 0x41: // F-4 |
||
2219 | return SEQ_UI_Button_StepView(depressed); |
||
2220 | case 0x42: // F#4 |
||
2221 | return SEQ_UI_Button_Group(depressed, 1); |
||
2222 | case 0x43: // G-4 |
||
2223 | return 0; // ignore |
||
2224 | case 0x44: // G#4 |
||
2225 | return SEQ_UI_Button_Group(depressed, 2); |
||
2226 | case 0x45: // A-4 |
||
2227 | return SEQ_UI_Button_Left(depressed); |
||
2228 | case 0x46: // A#4 |
||
2229 | return SEQ_UI_Button_ToggleGate(depressed); |
||
2230 | case 0x47: // B-4 |
||
2231 | return SEQ_UI_Button_Right(depressed); |
||
2232 | |||
2233 | case 0x48: // C-5 |
||
2234 | return SEQ_UI_Button_Edit(depressed); |
||
2235 | case 0x49: // C#5 |
||
2236 | return SEQ_UI_Button_Solo(depressed); |
||
2237 | case 0x4a: // D-5 |
||
2238 | return SEQ_UI_Button_Mute(depressed); |
||
2239 | case 0x4b: // D#5 |
||
2240 | return SEQ_UI_Button_All(depressed); |
||
2241 | case 0x4c: // E-5 |
||
2242 | return SEQ_UI_Button_Pattern(depressed); |
||
2243 | case 0x4d: // F-5 |
||
2244 | return SEQ_UI_Button_Song(depressed); |
||
2245 | case 0x4e: // F#5 |
||
2246 | return SEQ_UI_Button_Fast(depressed); |
||
2247 | case 0x4f: // G-5 |
||
2248 | return SEQ_UI_Button_Metronome(depressed); |
||
2249 | case 0x50: // G#5 |
||
2250 | return SEQ_UI_Button_ExtRestart(depressed); |
||
2251 | case 0x51: // A-5 |
||
2252 | return SEQ_UI_Button_ParLayerSel(depressed); |
||
2253 | case 0x52: // A#5 |
||
2254 | return SEQ_UI_Button_TrackSel(depressed); |
||
2255 | case 0x53: // B-5 |
||
2256 | return SEQ_UI_Button_Stop(depressed); |
||
2257 | |||
2258 | case 0x54: // C-6 |
||
2259 | return SEQ_UI_Button_Play(depressed); |
||
2260 | case 0x55: // C#6 |
||
2261 | return SEQ_UI_Button_Pause(depressed); |
||
2262 | case 0x56: // D-6 |
||
2263 | return SEQ_UI_Button_Rew(depressed); |
||
2264 | case 0x57: // D#6 |
||
2265 | return SEQ_UI_Button_Fwd(depressed); |
||
2266 | case 0x58: // E-6 |
||
2267 | return SEQ_UI_Button_Utility(depressed); |
||
2268 | case 0x59: // F-6 |
||
2269 | return SEQ_UI_Button_TempoPreset(depressed); |
||
2270 | case 0x5a: // F#6 |
||
2271 | return 0; // ignore |
||
2272 | case 0x5b: // G-6 |
||
2273 | return SEQ_UI_Button_Menu(depressed); |
||
2274 | case 0x5c: // G#6 |
||
2275 | return SEQ_UI_Button_Select(depressed); |
||
2276 | case 0x5d: // A-6 |
||
2277 | return SEQ_UI_Button_Exit(depressed); |
||
2278 | case 0x5e: // A#6 |
||
2279 | return SEQ_UI_Button_Down(depressed); |
||
2280 | case 0x5f: // B-6 |
||
2281 | return SEQ_UI_Button_Up(depressed); |
||
2282 | } |
||
2283 | |||
741 | tk | 2284 | return 0; // no error |
2285 | } |
||
2286 | |||
2287 | |||
2288 | ///////////////////////////////////////////////////////////////////////////// |
||
134 | tk | 2289 | // Update LCD messages |
2290 | // Usually called from background task |
||
2291 | ///////////////////////////////////////////////////////////////////////////// |
||
2292 | s32 SEQ_UI_LCD_Handler(void) |
||
2293 | { |
||
728 | tk | 2294 | static u8 boot_animation_wait_ctr = 0; |
2295 | static u8 boot_animation_lcd_pos = 0; |
||
2296 | |||
625 | tk | 2297 | // special handling in remote client mode |
1316 | tk | 2298 | if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT ) |
625 | tk | 2299 | return SEQ_UI_LCD_Update(); |
2300 | |||
159 | tk | 2301 | if( seq_ui_display_init_req ) { |
2302 | seq_ui_display_init_req = 0; // clear request |
||
134 | tk | 2303 | |
278 | tk | 2304 | // clear force update of LCD |
2305 | SEQ_LCD_Clear(); |
||
2306 | SEQ_LCD_Update(1); |
||
134 | tk | 2307 | |
168 | tk | 2308 | // select first menu item |
2309 | ui_selected_item = 0; |
||
2310 | |||
167 | tk | 2311 | // call init function of current page |
272 | tk | 2312 | if( ui_menu_pages[ui_page].init_callback != NULL ) |
2313 | ui_menu_pages[ui_page].init_callback(0); // mode |
||
134 | tk | 2314 | |
2315 | // request display update |
||
159 | tk | 2316 | seq_ui_display_update_req = 1; |
134 | tk | 2317 | } |
2318 | |||
1044 | tk | 2319 | // print boot screen as long as hardware config hasn't been read |
496 | tk | 2320 | if( !SEQ_FILE_HW_ConfigLocked() ) { |
728 | tk | 2321 | if( boot_animation_lcd_pos < (40-3) ) { |
2322 | if( ++boot_animation_wait_ctr >= 75 ) { |
||
2323 | boot_animation_wait_ctr = 0; |
||
637 | tk | 2324 | |
728 | tk | 2325 | if( boot_animation_lcd_pos == 0 ) { |
2326 | SEQ_LCD_Clear(); |
||
2327 | SEQ_LCD_CursorSet(0, 0); |
||
2328 | SEQ_LCD_PrintString(MIOS32_LCD_BOOT_MSG_LINE1 " " MIOS32_LCD_BOOT_MSG_LINE2); |
||
2329 | SEQ_LCD_CursorSet(0, 1); |
||
2330 | SEQ_LCD_PrintString("Searching for SD Card..."); |
||
2331 | } |
||
2332 | |||
2333 | // logo is print on second LCD |
||
2334 | SEQ_LCD_LOGO_Print(boot_animation_lcd_pos++); |
||
2335 | } |
||
2336 | } |
||
740 | tk | 2337 | } else if( seq_ui_backup_req || seq_ui_format_req ) { |
634 | tk | 2338 | SEQ_LCD_Clear(); |
2339 | SEQ_LCD_CursorSet(0, 0); |
||
740 | tk | 2340 | // <--------------------------------------> |
2341 | // 0123456789012345678901234567890123456789 |
||
2342 | if( seq_ui_backup_req ) |
||
959 | tk | 2343 | SEQ_LCD_PrintString("Copy Files - be patient!!!"); |
740 | tk | 2344 | else if( seq_ui_format_req ) |
959 | tk | 2345 | SEQ_LCD_PrintString("Creating Files - be patient!!!"); |
740 | tk | 2346 | else |
2347 | SEQ_LCD_PrintString("Don't know what I'm doing! :-/"); |
||
637 | tk | 2348 | |
2349 | if( seq_file_backup_notification != NULL ) { |
||
2350 | int i; |
||
2351 | |||
2352 | SEQ_LCD_CursorSet(0, 1); |
||
959 | tk | 2353 | SEQ_LCD_PrintFormattedString("Creating %s", seq_file_backup_notification); |
637 | tk | 2354 | |
2355 | SEQ_LCD_CursorSet(40+3, 0); |
||
2356 | SEQ_LCD_PrintString("Total: ["); |
||
2357 | for(i=0; i<20; ++i) |
||
2358 | SEQ_LCD_PrintChar((i>(seq_file_backup_percentage/5)) ? ' ' : '#'); |
||
2359 | SEQ_LCD_PrintFormattedString("] %3d%%", seq_file_backup_percentage); |
||
2360 | |||
2361 | SEQ_LCD_CursorSet(40+3, 1); |
||
2362 | SEQ_LCD_PrintString("File: ["); |
||
2363 | for(i=0; i<20; ++i) |
||
1261 | tk | 2364 | SEQ_LCD_PrintChar((i>(file_copy_percentage/5)) ? ' ' : '#'); |
2365 | SEQ_LCD_PrintFormattedString("] %3d%%", file_copy_percentage); |
||
637 | tk | 2366 | } |
2367 | |||
496 | tk | 2368 | } else if( seq_ui_button_state.MENU_PRESSED && !seq_ui_button_state.MENU_FIRST_PAGE_SELECTED ) { |
2369 | SEQ_LCD_CursorSet(0, 0); |
||
2370 | // <--------------------------------------> |
||
2371 | // 0123456789012345678901234567890123456789 |
||
306 | tk | 2372 | SEQ_LCD_PrintString("Menu Shortcuts:"); |
2373 | SEQ_LCD_PrintSpaces(25 + 40); |
||
2374 | SEQ_LCD_CursorSet(0, 1); |
||
2375 | SEQ_LCD_PrintString(UI_SHORTCUT_STR); // defined in seq_ui_pages.inc |
||
2376 | } else { |
||
2377 | // perform high priority LCD update request |
||
2378 | if( ui_lcd_callback != NULL ) |
||
2379 | ui_lcd_callback(1); // high_prio |
||
167 | tk | 2380 | |
306 | tk | 2381 | // perform low priority LCD update request if requested |
2382 | if( seq_ui_display_update_req ) { |
||
2383 | seq_ui_display_update_req = 0; // clear request |
||
328 | tk | 2384 | |
2385 | // ensure that selections are matching with track constraints |
||
2386 | SEQ_UI_CheckSelections(); |
||
2387 | |||
306 | tk | 2388 | if( ui_lcd_callback != NULL ) |
2389 | ui_lcd_callback(0); // no high_prio |
||
2390 | } |
||
134 | tk | 2391 | } |
2392 | |||
353 | tk | 2393 | // transfer all changed characters to LCD |
2394 | SEQ_UI_LCD_Update(); |
||
2395 | |||
2396 | return 0; // no error |
||
2397 | } |
||
2398 | |||
2399 | |||
2400 | ///////////////////////////////////////////////////////////////////////////// |
||
2401 | // Called from SEQ_UI_LCD_Handler(), but optionally also from other tasks |
||
2402 | // to update the LCD screen immediately |
||
2403 | ///////////////////////////////////////////////////////////////////////////// |
||
1117 | tk | 2404 | // for newer GCC versions it's important to declare constant arrays outside a function |
2405 | // 00112233 |
||
2406 | static const char animation_l_arrows[2*4+1] = " >>>> "; |
||
2407 | // 00112233 |
||
2408 | static const char animation_r_arrows[2*4+1] = " < << <"; |
||
2409 | // 00112233 |
||
2410 | static const char animation_l_brackets[2*4+1] = " )))) "; |
||
2411 | // 00112233 |
||
2412 | static const char animation_r_brackets[2*4+1] = " ( (( ("; |
||
2413 | // 00112233 |
||
2414 | static const char animation_l_stars[2*4+1] = " **** "; |
||
2415 | // 00112233 |
||
2416 | static const char animation_r_stars[2*4+1] = " * ** *"; |
||
353 | tk | 2417 | s32 SEQ_UI_LCD_Update(void) |
2418 | { |
||
625 | tk | 2419 | // special handling in remote client mode |
1316 | tk | 2420 | if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT ) { |
626 | tk | 2421 | MIOS32_IRQ_Disable(); |
1316 | tk | 2422 | u8 force = seq_midi_sysex_remote_force_lcd_update; |
2423 | seq_midi_sysex_remote_force_lcd_update = 0; |
||
626 | tk | 2424 | MIOS32_IRQ_Enable(); |
2425 | return SEQ_LCD_Update(force); |
||
625 | tk | 2426 | } |
2427 | |||
596 | tk | 2428 | // if UI message active: copy over the text |
2429 | if( ui_msg_ctr ) { |
||
774 | tk | 2430 | char *animation_l_ptr; |
2431 | char *animation_r_ptr; |
||
596 | tk | 2432 | u8 msg_x = 0; |
2433 | u8 right_aligned = 0; |
||
740 | tk | 2434 | u8 disable_message = 0; |
299 | tk | 2435 | |
596 | tk | 2436 | switch( ui_msg_type ) { |
2437 | case SEQ_UI_MSG_SDCARD: { |
||
1117 | tk | 2438 | animation_l_ptr = (char *)animation_l_arrows; |
2439 | animation_r_ptr = (char *)animation_r_arrows; |
||
596 | tk | 2440 | msg_x = 0; // MEMO: print such important information at first LCD for the case the user hasn't connected the second LCD yet |
2441 | right_aligned = 0; |
||
2442 | } break; |
||
2443 | |||
756 | tk | 2444 | case SEQ_UI_MSG_DELAYED_ACTION: |
2445 | case SEQ_UI_MSG_DELAYED_ACTION_R: { |
||
1117 | tk | 2446 | animation_l_ptr = (char *)animation_l_brackets; |
2447 | animation_r_ptr = (char *)animation_r_brackets; |
||
756 | tk | 2448 | if( ui_msg_type == SEQ_UI_MSG_DELAYED_ACTION_R ) { |
2449 | msg_x = 40; // right LCD |
||
2450 | right_aligned = 0; |
||
2451 | } else { |
||
2452 | msg_x = 39; // left LCD |
||
2453 | right_aligned = 1; |
||
2454 | } |
||
740 | tk | 2455 | |
2456 | if( ui_delayed_action_callback == NULL ) { |
||
2457 | disable_message = 1; // button has been depressed before delay |
||
2458 | } else { |
||
2459 | int seconds = (ui_delayed_action_ctr / 1000) + 1; |
||
2460 | if( seconds == 1 ) |
||
2461 | sprintf(ui_msg[0], "Hold for 1 second "); |
||
2462 | else |
||
2463 | sprintf(ui_msg[0], "Hold for %d seconds", seconds); |
||
2464 | } |
||
2465 | } break; |
||
2466 | |||
741 | tk | 2467 | case SEQ_UI_MSG_USER_R: { |
1117 | tk | 2468 | animation_l_ptr = (char *)animation_l_stars; |
2469 | animation_r_ptr = (char *)animation_r_stars; |
||
741 | tk | 2470 | msg_x = 40; // right display |
2471 | right_aligned = 0; |
||
2472 | } break; |
||
2473 | |||
596 | tk | 2474 | default: { |
1117 | tk | 2475 | animation_l_ptr = (char *)animation_l_stars; |
2476 | animation_r_ptr = (char *)animation_r_stars; |
||
596 | tk | 2477 | msg_x = 39; |
2478 | right_aligned = 1; |
||
2479 | } break; |
||
2480 | |||
2481 | } |
||
2482 | |||
740 | tk | 2483 | if( !disable_message ) { |
2484 | int anum = (ui_msg_ctr % 1000) / 250; |
||
596 | tk | 2485 | |
740 | tk | 2486 | int len[2]; |
2487 | len[0] = strlen((char *)ui_msg[0]); |
||
2488 | len[1] = strlen((char *)ui_msg[1]); |
||
2489 | int len_max = len[0]; |
||
2490 | if( len[1] > len_max ) |
||
2491 | len_max = len[1]; |
||
596 | tk | 2492 | |
740 | tk | 2493 | if( right_aligned ) |
2494 | msg_x -= (9 + len_max); |
||
596 | tk | 2495 | |
740 | tk | 2496 | int line; |
2497 | for(line=0; line<2; ++line) { |
||
2498 | SEQ_LCD_CursorSet(msg_x, line); |
||
596 | tk | 2499 | |
740 | tk | 2500 | // ensure that both lines are padded with same number of spaces |
2501 | int end_pos = len[line]; |
||
2502 | while( end_pos < len_max ) |
||
2503 | ui_msg[line][end_pos++] = ' '; |
||
2504 | ui_msg[line][end_pos] = 0; |
||
2505 | |||
2506 | SEQ_LCD_PrintFormattedString(" %c%c| %s |%c%c ", |
||
2507 | *(animation_l_ptr + 2*anum + 0), *(animation_l_ptr + 2*anum + 1), |
||
2508 | (char *)ui_msg[line], |
||
2509 | *(animation_r_ptr + 2*anum + 0), *(animation_r_ptr + 2*anum + 1)); |
||
2510 | } |
||
299 | tk | 2511 | } |
2512 | } |
||
2513 | |||
637 | tk | 2514 | // MSD USB notification at right corner if not in Disk page |
2515 | // to warn user that USB MIDI is disabled and seq performance is bad now! |
||
638 | tk | 2516 | if( (TASK_MSD_EnableGet() > 0) && ui_page != SEQ_UI_PAGE_DISK ) { |
637 | tk | 2517 | SEQ_LCD_CursorSet(80-11, 0); |
2518 | if( ui_cursor_flash ) SEQ_LCD_PrintSpaces(13); else SEQ_LCD_PrintString(" [MSD USB] "); |
||
2519 | SEQ_LCD_CursorSet(80-11, 1); |
||
2520 | char str[5]; |
||
2521 | TASK_MSD_FlagStrGet(str); |
||
2522 | if( ui_cursor_flash ) SEQ_LCD_PrintSpaces(13); else SEQ_LCD_PrintFormattedString(" [ %s ] ", str); |
||
2523 | } |
||
596 | tk | 2524 | |
278 | tk | 2525 | // transfer all changed characters to LCD |
353 | tk | 2526 | // SEQ_LCD_Update provides a MUTEX handling to allow updates from different tasks |
2527 | return SEQ_LCD_Update(0); |
||
134 | tk | 2528 | } |
2529 | |||
2530 | |||
2531 | ///////////////////////////////////////////////////////////////////////////// |
||
2532 | // Update all LEDs |
||
2533 | // Usually called from background task |
||
2534 | ///////////////////////////////////////////////////////////////////////////// |
||
2535 | s32 SEQ_UI_LED_Handler(void) |
||
2536 | { |
||
626 | tk | 2537 | static u8 remote_led_sr[SEQ_LED_NUM_SR]; |
2538 | |||
625 | tk | 2539 | // ignore in remote client mode |
1316 | tk | 2540 | if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT ) |
625 | tk | 2541 | return 0; // no error |
2542 | |||
1044 | tk | 2543 | // ignore as long as hardware config hasn't been read |
496 | tk | 2544 | if( !SEQ_FILE_HW_ConfigLocked() ) |
2545 | return -1; |
||
2546 | |||
134 | tk | 2547 | // track LEDs |
987 | tk | 2548 | // in pattern page: track buttons are used as group buttons |
2549 | if( ui_page == SEQ_UI_PAGE_PATTERN ) { |
||
2550 | SEQ_LED_PinSet(seq_hwcfg_led.track[0], (ui_selected_group == 0)); |
||
2551 | SEQ_LED_PinSet(seq_hwcfg_led.track[1], (ui_selected_group == 1)); |
||
2552 | SEQ_LED_PinSet(seq_hwcfg_led.track[2], (ui_selected_group == 2)); |
||
2553 | SEQ_LED_PinSet(seq_hwcfg_led.track[3], (ui_selected_group == 3)); |
||
2554 | } else if( ui_page == SEQ_UI_PAGE_SONG ) { |
||
2555 | // in song page: track and group buttons are used to select the cursor position |
||
2556 | SEQ_LED_PinSet(seq_hwcfg_led.track[0], (ui_selected_item == 3)); |
||
2557 | SEQ_LED_PinSet(seq_hwcfg_led.track[1], (ui_selected_item == 4)); |
||
2558 | SEQ_LED_PinSet(seq_hwcfg_led.track[2], (ui_selected_item == 5)); |
||
2559 | SEQ_LED_PinSet(seq_hwcfg_led.track[3], (ui_selected_item == 6)); |
||
2560 | } else { |
||
2561 | u8 selected_tracks = ui_selected_tracks >> (4*ui_selected_group); |
||
2562 | SEQ_LED_PinSet(seq_hwcfg_led.track[0], (selected_tracks & (1 << 0))); |
||
2563 | SEQ_LED_PinSet(seq_hwcfg_led.track[1], (selected_tracks & (1 << 1))); |
||
2564 | SEQ_LED_PinSet(seq_hwcfg_led.track[2], (selected_tracks & (1 << 2))); |
||
2565 | SEQ_LED_PinSet(seq_hwcfg_led.track[3], (selected_tracks & (1 << 3))); |
||
2566 | } |
||
2567 | |||
678 | tk | 2568 | SEQ_LED_PinSet(seq_hwcfg_led.track_sel, ui_page == SEQ_UI_PAGE_TRACKSEL); |
134 | tk | 2569 | |
2570 | // parameter layer LEDs |
||
987 | tk | 2571 | // in song page: layer buttons are used to select the cursor position |
2572 | if( ui_page == SEQ_UI_PAGE_SONG ) { |
||
2573 | SEQ_LED_PinSet(seq_hwcfg_led.par_layer[0], ui_selected_item == 0); |
||
2574 | SEQ_LED_PinSet(seq_hwcfg_led.par_layer[1], ui_selected_item == 1); |
||
2575 | SEQ_LED_PinSet(seq_hwcfg_led.par_layer[2], ui_selected_item == 2); |
||
2576 | } else { |
||
2577 | SEQ_LED_PinSet(seq_hwcfg_led.par_layer[0], (ui_selected_par_layer == 0)); |
||
2578 | SEQ_LED_PinSet(seq_hwcfg_led.par_layer[1], (ui_selected_par_layer == 1)); |
||
2579 | SEQ_LED_PinSet(seq_hwcfg_led.par_layer[2], (ui_selected_par_layer >= 2) || seq_ui_button_state.PAR_LAYER_SEL); |
||
2580 | } |
||
678 | tk | 2581 | SEQ_LED_PinSet(seq_hwcfg_led.par_layer_sel, ui_page == SEQ_UI_PAGE_PARSEL); |
134 | tk | 2582 | |
2583 | // group LEDs |
||
987 | tk | 2584 | // in song page: track and group buttons are used to select the cursor position |
2585 | if( ui_page == SEQ_UI_PAGE_SONG ) { |
||
2586 | SEQ_LED_PinSet(seq_hwcfg_led.group[0], (ui_selected_item == 3)); |
||
2587 | SEQ_LED_PinSet(seq_hwcfg_led.group[1], (ui_selected_item == 4)); |
||
2588 | SEQ_LED_PinSet(seq_hwcfg_led.group[2], (ui_selected_item == 5)); |
||
2589 | SEQ_LED_PinSet(seq_hwcfg_led.group[3], (ui_selected_item == 6)); |
||
2590 | } else { |
||
2591 | SEQ_LED_PinSet(seq_hwcfg_led.group[0], (ui_selected_group == 0)); |
||
2592 | SEQ_LED_PinSet(seq_hwcfg_led.group[1], (ui_selected_group == 1)); |
||
2593 | SEQ_LED_PinSet(seq_hwcfg_led.group[2], (ui_selected_group == 2)); |
||
2594 | SEQ_LED_PinSet(seq_hwcfg_led.group[3], (ui_selected_group == 3)); |
||
2595 | } |
||
134 | tk | 2596 | |
2597 | // trigger layer LEDs |
||
492 | tk | 2598 | SEQ_LED_PinSet(seq_hwcfg_led.trg_layer[0], (ui_selected_trg_layer == 0)); |
2599 | SEQ_LED_PinSet(seq_hwcfg_led.trg_layer[1], (ui_selected_trg_layer == 1)); |
||
2600 | SEQ_LED_PinSet(seq_hwcfg_led.trg_layer[2], (ui_selected_trg_layer >= 2) || seq_ui_button_state.TRG_LAYER_SEL); |
||
678 | tk | 2601 | SEQ_LED_PinSet(seq_hwcfg_led.trg_layer_sel, ui_page == SEQ_UI_PAGE_TRGSEL); |
134 | tk | 2602 | |
2603 | // remaining LEDs |
||
492 | tk | 2604 | SEQ_LED_PinSet(seq_hwcfg_led.edit, ui_page == SEQ_UI_PAGE_EDIT); |
2605 | SEQ_LED_PinSet(seq_hwcfg_led.mute, ui_page == SEQ_UI_PAGE_MUTE); |
||
2606 | SEQ_LED_PinSet(seq_hwcfg_led.pattern, ui_page == SEQ_UI_PAGE_PATTERN); |
||
399 | tk | 2607 | if( SEQ_SONG_ActiveGet() ) |
492 | tk | 2608 | SEQ_LED_PinSet(seq_hwcfg_led.song, 1); |
399 | tk | 2609 | else |
492 | tk | 2610 | SEQ_LED_PinSet(seq_hwcfg_led.song, ui_cursor_flash ? 0 : (ui_page == SEQ_UI_PAGE_SONG)); |
743 | tk | 2611 | SEQ_LED_PinSet(seq_hwcfg_led.mixer, ui_page == SEQ_UI_PAGE_MIXER); |
1119 | tk | 2612 | |
2613 | SEQ_LED_PinSet(seq_hwcfg_led.track_mode, ui_page == SEQ_UI_PAGE_TRKMODE); |
||
2614 | SEQ_LED_PinSet(seq_hwcfg_led.track_groove, ui_page == SEQ_UI_PAGE_TRKGRV); |
||
2615 | SEQ_LED_PinSet(seq_hwcfg_led.track_length, ui_page == SEQ_UI_PAGE_TRKLEN); |
||
2616 | SEQ_LED_PinSet(seq_hwcfg_led.track_direction, ui_page == SEQ_UI_PAGE_TRKDIR); |
||
2617 | SEQ_LED_PinSet(seq_hwcfg_led.track_morph, ui_page == SEQ_UI_PAGE_TRKMORPH); |
||
2618 | SEQ_LED_PinSet(seq_hwcfg_led.track_transpose, ui_page == SEQ_UI_PAGE_TRKTRAN); |
||
134 | tk | 2619 | |
492 | tk | 2620 | SEQ_LED_PinSet(seq_hwcfg_led.solo, seq_ui_button_state.SOLO); |
2621 | SEQ_LED_PinSet(seq_hwcfg_led.fast, seq_ui_button_state.FAST_ENCODERS); |
||
1121 | tk | 2622 | SEQ_LED_PinSet(seq_hwcfg_led.fast2, seq_ui_button_state.FAST2_ENCODERS); |
492 | tk | 2623 | SEQ_LED_PinSet(seq_hwcfg_led.all, seq_ui_button_state.CHANGE_ALL_STEPS); |
134 | tk | 2624 | |
1206 | tk | 2625 | u8 seq_running = SEQ_BPM_IsRunning() && (!seq_core_slaveclk_mute || ((seq_core_state.ref_step & 3) == 0)); |
2626 | // note: no bug: we added check for ref_step&3 for flashing the LEDs to give a sign of activity in slave mode with slaveclk_muted |
||
2627 | SEQ_LED_PinSet(seq_hwcfg_led.play, seq_running); |
||
2628 | SEQ_LED_PinSet(seq_hwcfg_led.stop, !seq_running && !ui_seq_pause); |
||
2629 | SEQ_LED_PinSet(seq_hwcfg_led.pause, ui_seq_pause && (!seq_core_slaveclk_mute || ui_cursor_flash)); |
||
240 | tk | 2630 | |
492 | tk | 2631 | SEQ_LED_PinSet(seq_hwcfg_led.rew, seq_ui_button_state.REW); |
2632 | SEQ_LED_PinSet(seq_hwcfg_led.fwd, seq_ui_button_state.FWD); |
||
596 | tk | 2633 | |
2634 | SEQ_LED_PinSet(seq_hwcfg_led.loop, seq_core_state.LOOP); |
||
951 | tk | 2635 | SEQ_LED_PinSet(seq_hwcfg_led.follow, seq_core_state.FOLLOW); |
134 | tk | 2636 | |
678 | tk | 2637 | SEQ_LED_PinSet(seq_hwcfg_led.step_view, ui_page == SEQ_UI_PAGE_STEPSEL); |
134 | tk | 2638 | |
591 | tk | 2639 | SEQ_LED_PinSet(seq_hwcfg_led.select, seq_ui_button_state.SELECT_PRESSED); |
492 | tk | 2640 | SEQ_LED_PinSet(seq_hwcfg_led.menu, seq_ui_button_state.MENU_PRESSED); |
1203 | tk | 2641 | SEQ_LED_PinSet(seq_hwcfg_led.bookmark, ui_page == SEQ_UI_PAGE_BOOKMARKS); |
134 | tk | 2642 | |
596 | tk | 2643 | // handle double functions |
2644 | if( seq_ui_button_state.MENU_PRESSED ) { |
||
2645 | SEQ_LED_PinSet(seq_hwcfg_led.scrub, seq_core_state.LOOP); |
||
951 | tk | 2646 | SEQ_LED_PinSet(seq_hwcfg_led.exit, seq_core_state.FOLLOW); |
596 | tk | 2647 | SEQ_LED_PinSet(seq_hwcfg_led.metronome, seq_core_state.EXT_RESTART_REQ); |
2648 | } else { |
||
2649 | SEQ_LED_PinSet(seq_hwcfg_led.scrub, seq_ui_button_state.SCRUB); |
||
951 | tk | 2650 | SEQ_LED_PinSet(seq_hwcfg_led.exit, ui_page == SEQ_UI_PAGE_MENU); |
596 | tk | 2651 | SEQ_LED_PinSet(seq_hwcfg_led.metronome, seq_core_state.METRONOME); |
2652 | } |
||
2653 | |||
1313 | tk | 2654 | SEQ_LED_PinSet(seq_hwcfg_led.record, seq_record_state.ENABLED); |