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