Subversion Repositories svn.mios32

Rev

Rev 327 | Rev 333 | 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 328 2009-01-30 21:21:05Z 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>
134 tk 23
#include <blm8x8.h>
190 tk 24
#include <seq_midi_out.h>
25
#include <seq_bpm.h>
134 tk 26
 
290 tk 27
#include "tasks.h"
134 tk 28
#include "seq_ui.h"
29
#include "seq_lcd.h"
30
#include "seq_led.h"
186 tk 31
#include "seq_midply.h"
134 tk 32
#include "seq_core.h"
178 tk 33
#include "seq_layer.h"
184 tk 34
#include "seq_cc.h"
299 tk 35
#include "seq_file.h"
248 tk 36
#include "seq_file_b.h"
280 tk 37
#include "seq_file_m.h"
134 tk 38
 
39
 
40
/////////////////////////////////////////////////////////////////////////////
41
// Global variables
42
/////////////////////////////////////////////////////////////////////////////
43
 
159 tk 44
u8 seq_ui_display_update_req;
45
u8 seq_ui_display_init_req;
134 tk 46
 
167 tk 47
seq_ui_button_state_t seq_ui_button_state;
48
 
134 tk 49
u8 ui_selected_group;
50
u8 ui_selected_tracks;
51
u8 ui_selected_par_layer;
52
u8 ui_selected_trg_layer;
328 tk 53
u8 ui_selected_instrument;
134 tk 54
u8 ui_selected_step_view;
55
u8 ui_selected_step;
168 tk 56
u8 ui_selected_item;
134 tk 57
 
168 tk 58
u8 ui_selected_item;
134 tk 59
 
240 tk 60
u16 ui_hold_msg_ctr;
61
 
206 tk 62
seq_ui_page_t ui_page;
272 tk 63
seq_ui_page_t ui_selected_page;
303 tk 64
seq_ui_page_t ui_stepview_prev_page;
326 tk 65
seq_ui_page_t ui_trglayer_prev_page;
66
seq_ui_page_t ui_parlayer_prev_page;
206 tk 67
 
173 tk 68
volatile u8 ui_cursor_flash;
69
u16 ui_cursor_flash_ctr;
134 tk 70
 
316 tk 71
char ui_edit_name[21];
72
u8 ui_edit_name_cursor;
73
u8 ui_edit_preset_num_category;
74
u8 ui_edit_preset_num_label;
75
 
193 tk 76
u8 ui_seq_pause;
77
 
78
 
134 tk 79
/////////////////////////////////////////////////////////////////////////////
80
// Local variables
81
/////////////////////////////////////////////////////////////////////////////
82
 
168 tk 83
static s32 (*ui_button_callback)(seq_ui_button_t button, s32 depressed);
84
static s32 (*ui_encoder_callback)(seq_ui_encoder_t encoder, s32 incrementer);
173 tk 85
static s32 (*ui_led_callback)(u16 *gp_leds);
167 tk 86
static s32 (*ui_lcd_callback)(u8 high_prio);
87
 
168 tk 88
static u16 ui_gp_leds;
167 tk 89
 
168 tk 90
 
299 tk 91
#define SDCARD_MSG_MAX_CHAR 21
92
static char sdcard_msg[2][SDCARD_MSG_MAX_CHAR];
93
static u16 sdcard_msg_ctr;
94
 
95
 
96
 
134 tk 97
/////////////////////////////////////////////////////////////////////////////
98
// Initialisation
99
/////////////////////////////////////////////////////////////////////////////
100
s32 SEQ_UI_Init(u32 mode)
101
{
102
  // init selection variables
103
  ui_selected_group = 0;
104
  ui_selected_tracks = (1 << 0);
105
  ui_selected_par_layer = 0;
106
  ui_selected_trg_layer = 0;
328 tk 107
  ui_selected_instrument = 0;
134 tk 108
  ui_selected_step_view = 0;
109
  ui_selected_step = 0;
168 tk 110
  ui_selected_item = 0;
134 tk 111
 
240 tk 112
  ui_hold_msg_ctr = 0;
299 tk 113
  sdcard_msg_ctr = 0;
240 tk 114
 
168 tk 115
  ui_cursor_flash_ctr = 0;
173 tk 116
  ui_cursor_flash = 0;
168 tk 117
 
167 tk 118
  seq_ui_button_state.ALL = 0;
119
 
193 tk 120
  ui_seq_pause = 0;
121
 
134 tk 122
  // visible GP pattern
123
  ui_gp_leds = 0x0000;
124
 
167 tk 125
  // change to edit page
126
  ui_page = SEQ_UI_PAGE_NONE;
127
  SEQ_UI_PageSet(SEQ_UI_PAGE_EDIT);
134 tk 128
 
129
  return 0; // no error
130
}
131
 
132
 
133
/////////////////////////////////////////////////////////////////////////////
178 tk 134
// Inits the speed mode of all encoders
135
// Auto mode should be used whenever:
136
//    - the edit screen is entered
137
//    - the group is changed
138
//    - a track is changed
139
//    - a layer is changed
140
/////////////////////////////////////////////////////////////////////////////
141
s32 SEQ_UI_InitEncSpeed(u32 auto_config)
142
{
143
  mios32_enc_config_t enc_config;
144
 
145
  if( auto_config ) {
146
#if DEFAULT_AUTO_FAST_BUTTON
147
    switch( SEQ_LAYER_GetVControlType(SEQ_UI_VisibleTrackGet(), ui_selected_par_layer) ) {
148
      case SEQ_LAYER_ControlType_Velocity:
323 tk 149
      case SEQ_LAYER_ControlType_Chord_Velocity:
178 tk 150
      case SEQ_LAYER_ControlType_CC:
328 tk 151
      case SEQ_LAYER_ControlType_Length:
178 tk 152
    seq_ui_button_state.FAST_ENCODERS = 1;
153
    break;
154
 
155
      default:
156
    seq_ui_button_state.FAST_ENCODERS = 0;
157
    }
158
#else
159
    // auto mode not enabled - ignore auto reconfiguration request
160
    return 0;
161
#endif
162
  }
163
 
164
  // change for datawheel and GP encoders
165
  int enc;
166
  for(enc=0; enc<17; ++enc) {
167
    enc_config = MIOS32_ENC_ConfigGet(enc);
168
    enc_config.cfg.speed = seq_ui_button_state.FAST_ENCODERS ? FAST : NORMAL;
169
    enc_config.cfg.speed_par = (enc == 0) ? DEFAULT_DATAWHEEL_SPEED_VALUE : DEFAULT_ENC_SPEED_VALUE;
170
    MIOS32_ENC_ConfigSet(enc, enc_config);
171
  }
172
 
173
  return 0; // no error
174
}
175
 
176
 
177
/////////////////////////////////////////////////////////////////////////////
167 tk 178
// Various installation routines for menu page LCD handlers
179
/////////////////////////////////////////////////////////////////////////////
168 tk 180
s32 SEQ_UI_InstallButtonCallback(void *callback)
167 tk 181
{
168 tk 182
  ui_button_callback = callback;
167 tk 183
  return 0; // no error
184
}
185
 
168 tk 186
s32 SEQ_UI_InstallEncoderCallback(void *callback)
167 tk 187
{
168 tk 188
  ui_encoder_callback = callback;
167 tk 189
  return 0; // no error
190
}
191
 
168 tk 192
s32 SEQ_UI_InstallLEDCallback(void *callback)
167 tk 193
{
168 tk 194
  ui_led_callback = callback;
167 tk 195
  return 0; // no error
196
}
197
 
168 tk 198
s32 SEQ_UI_InstallLCDCallback(void *callback)
167 tk 199
{
200
  ui_lcd_callback = callback;
201
  return 0; // no error
202
}
203
 
204
 
205
/////////////////////////////////////////////////////////////////////////////
206
// Change the menu page
207
/////////////////////////////////////////////////////////////////////////////
208
s32 SEQ_UI_PageSet(seq_ui_page_t page)
209
{
210
  if( page != ui_page ) {
211
    // disable hooks of previous page and request re-initialisation
318 tk 212
    portENTER_CRITICAL();
167 tk 213
    ui_page = page;
168 tk 214
    ui_button_callback = NULL;
215
    ui_encoder_callback = NULL;
216
    ui_led_callback = NULL;
167 tk 217
    ui_lcd_callback = NULL;
318 tk 218
    portEXIT_CRITICAL();
167 tk 219
 
178 tk 220
#if DEFAULT_BEHAVIOUR_BUTTON_MENU
168 tk 221
    seq_ui_button_state.MENU_PRESSED = 0; // MENU page selection finished
167 tk 222
#endif
223
 
224
    // request display initialisation
225
    seq_ui_display_init_req = 1;
226
  }
173 tk 227
 
306 tk 228
  // for MENU button:
229
  // first page has been selected - display new screen
230
  seq_ui_button_state.MENU_FIRST_PAGE_SELECTED = 1;
231
 
272 tk 232
  // for SEQ_UI_MENU which is accessible with EXIT button
233
  // remember the current selectable page
234
  if( ui_page >= SEQ_UI_FIRST_MENU_SELECTION_PAGE )
235
    ui_selected_page = ui_page;
236
 
184 tk 237
  return 0; // no error
167 tk 238
}
239
 
240
 
241
/////////////////////////////////////////////////////////////////////////////
272 tk 242
// Returns name of menu page (18 characters)
243
/////////////////////////////////////////////////////////////////////////////
244
char *SEQ_UI_PageNameGet(seq_ui_page_t page)
245
{
246
  return ui_menu_pages[page].name;
247
}
248
 
249
 
250
/////////////////////////////////////////////////////////////////////////////
134 tk 251
// Dedicated button functions
252
// Mapped to physical buttons in SEQ_UI_Button_Handler()
253
// Will also be mapped to MIDI keys later (for MIDI remote function)
254
/////////////////////////////////////////////////////////////////////////////
255
static s32 SEQ_UI_Button_GP(s32 depressed, u32 gp)
256
{
306 tk 257
  // in MENU page: overrule GP buttons so long MENU button is pressed/active
258
  if( seq_ui_button_state.MENU_PRESSED ) {
259
    if( depressed ) return -1;
260
    SEQ_UI_PageSet(ui_shortcut_menu_pages[gp]);
261
  } else {
262
    // forward to menu page
263
    if( ui_button_callback != NULL )
264
      ui_button_callback(gp, depressed);
265
    ui_cursor_flash_ctr = 0;
266
  }
134 tk 267
 
268
  return 0; // no error
269
}
270
 
271
static s32 SEQ_UI_Button_Left(s32 depressed)
272
{
168 tk 273
  // forward to menu page
306 tk 274
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 275
    ui_button_callback(SEQ_UI_BUTTON_Left, depressed);
173 tk 276
  ui_cursor_flash_ctr = 0;
134 tk 277
 
278
  return 0; // no error
279
}
280
 
281
static s32 SEQ_UI_Button_Right(s32 depressed)
282
{
168 tk 283
  // forward to menu page
306 tk 284
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 285
    ui_button_callback(SEQ_UI_BUTTON_Right, depressed);
173 tk 286
  ui_cursor_flash_ctr = 0;
134 tk 287
 
288
  return 0; // no error
289
}
290
 
168 tk 291
static s32 SEQ_UI_Button_Down(s32 depressed)
292
{
240 tk 293
  seq_ui_button_state.DOWN = depressed ? 0 : 1;
294
 
168 tk 295
  // forward to menu page
306 tk 296
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 297
    ui_button_callback(SEQ_UI_BUTTON_Down, depressed);
173 tk 298
  ui_cursor_flash_ctr = 0;
168 tk 299
 
300
  return 0; // no error
301
}
302
 
303
static s32 SEQ_UI_Button_Up(s32 depressed)
304
{
240 tk 305
  seq_ui_button_state.UP = depressed ? 0 : 1;
306
 
168 tk 307
  // forward to menu page
306 tk 308
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 309
    ui_button_callback(SEQ_UI_BUTTON_Up, depressed);
173 tk 310
  ui_cursor_flash_ctr = 0;
168 tk 311
 
312
  return 0; // no error
313
}
314
 
134 tk 315
static s32 SEQ_UI_Button_Scrub(s32 depressed)
316
{
178 tk 317
#if DEFAULT_BEHAVIOUR_BUTTON_SCRUB
318
  // toggle mode
134 tk 319
  if( depressed ) return -1; // ignore when button depressed
178 tk 320
  seq_ui_button_state.SCRUB ^= 1;
137 tk 321
#else
178 tk 322
  // set mode
323
  seq_ui_button_state.SCRUB = depressed ? 0 : 1;
137 tk 324
#endif
325
 
134 tk 326
  return 0; // no error
327
}
328
 
329
static s32 SEQ_UI_Button_Metronome(s32 depressed)
330
{
178 tk 331
#if DEFAULT_BEHAVIOUR_BUTTON_METRON
332
  // toggle mode
134 tk 333
  if( depressed ) return -1; // ignore when button depressed
178 tk 334
  seq_ui_button_state.METRONOME ^= 1;
290 tk 335
 
248 tk 336
#if 1
290 tk 337
  MUTEX_SDCARD_TAKE;
280 tk 338
 
328 tk 339
#if 1
249 tk 340
  u8 bank;
341
  for(bank=0; bank<SEQ_FILE_B_NUM_BANKS; ++bank) {
342
    SEQ_FILE_B_Create(bank);
343
    SEQ_FILE_B_Open(bank);
344
  }
280 tk 345
#else
346
    SEQ_FILE_M_Create();
347
    SEQ_FILE_M_Open();
348
#endif
349
 
290 tk 350
  MUTEX_SDCARD_GIVE;
248 tk 351
#endif
352
 
137 tk 353
#else
178 tk 354
  // set mode
355
  seq_ui_button_state.METRONOME = depressed ? 0 : 1;
137 tk 356
#endif
134 tk 357
 
358
  return 0; // no error
359
}
360
 
361
static s32 SEQ_UI_Button_Stop(s32 depressed)
362
{
363
  if( depressed ) return -1; // ignore when button depressed
364
 
159 tk 365
  // if sequencer running: stop it
366
  // if sequencer already stopped: reset song position
186 tk 367
#if MID_PLAYER_TEST
193 tk 368
  if( SEQ_BPM_IsRunning() )
369
    SEQ_BPM_Stop();
186 tk 370
  else
371
    SEQ_MIDPLY_Reset();
372
#else
193 tk 373
  if( SEQ_BPM_IsRunning() )
374
    SEQ_BPM_Stop();
159 tk 375
  else
376
    SEQ_CORE_Reset();
186 tk 377
#endif
159 tk 378
 
134 tk 379
  return 0; // no error
380
}
381
 
382
static s32 SEQ_UI_Button_Pause(s32 depressed)
383
{
384
  if( depressed ) return -1; // ignore when button depressed
385
 
193 tk 386
  // if in auto mode and BPM generator is clocked in slave mode:
387
  // change to master mode
388
  SEQ_BPM_CheckAutoMaster();
159 tk 389
 
193 tk 390
  // toggle pause mode
391
  ui_seq_pause ^= 1;
392
 
393
  // execute stop/continue depending on new mode
394
  if( ui_seq_pause )
395
    SEQ_BPM_Stop();
396
  else
397
    SEQ_BPM_Cont();
398
 
134 tk 399
  return 0; // no error
400
}
401
 
402
static s32 SEQ_UI_Button_Play(s32 depressed)
403
{
404
  if( depressed ) return -1; // ignore when button depressed
405
 
186 tk 406
  // if in auto mode and BPM generator is clocked in slave mode:
407
  // change to master mode
408
  SEQ_BPM_CheckAutoMaster();
409
 
193 tk 410
#if 0
411
  // if sequencer running: restart it
412
  // if sequencer stopped: continue at last song position
413
  if( SEQ_BPM_IsRunning() )
414
    SEQ_BPM_Start();
415
  else
416
    SEQ_BPM_Cont();
186 tk 417
#else
193 tk 418
  // always restart sequencer
419
  SEQ_BPM_Start();
186 tk 420
#endif
159 tk 421
 
134 tk 422
  return 0; // no error
423
}
424
 
425
static s32 SEQ_UI_Button_Rew(s32 depressed)
426
{
240 tk 427
  seq_ui_button_state.REW = depressed ? 0 : 1;
428
 
134 tk 429
  if( depressed ) return -1; // ignore when button depressed
430
 
431
  return 0; // no error
432
}
433
 
434
static s32 SEQ_UI_Button_Fwd(s32 depressed)
435
{
240 tk 436
  seq_ui_button_state.FWD = depressed ? 0 : 1;
437
 
134 tk 438
  if( depressed ) return -1; // ignore when button depressed
439
 
440
  return 0; // no error
441
}
442
 
443
static s32 SEQ_UI_Button_F1(s32 depressed)
444
{
240 tk 445
  seq_ui_button_state.F1 = depressed ? 0 : 1;
446
 
134 tk 447
  if( depressed ) return -1; // ignore when button depressed
448
 
240 tk 449
  // change to utility page
450
  SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL);
451
 
134 tk 452
  return 0; // no error
453
}
454
 
455
static s32 SEQ_UI_Button_F2(s32 depressed)
456
{
240 tk 457
  seq_ui_button_state.F2 = depressed ? 0 : 1;
458
 
134 tk 459
  if( depressed ) return -1; // ignore when button depressed
460
 
461
  return 0; // no error
462
}
463
 
464
static s32 SEQ_UI_Button_F3(s32 depressed)
465
{
240 tk 466
  seq_ui_button_state.F3 = depressed ? 0 : 1;
467
 
134 tk 468
  if( depressed ) return -1; // ignore when button depressed
469
 
470
  return 0; // no error
471
}
472
 
473
static s32 SEQ_UI_Button_F4(s32 depressed)
474
{
240 tk 475
  seq_ui_button_state.F4 = depressed ? 0 : 1;
476
 
134 tk 477
  if( depressed ) return -1; // ignore when button depressed
478
 
479
  return 0; // no error
480
}
481
 
482
static s32 SEQ_UI_Button_Utility(s32 depressed)
483
{
484
  if( depressed ) return -1; // ignore when button depressed
485
 
240 tk 486
  // change to utility page
487
  SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL);
488
 
134 tk 489
  return 0; // no error
490
}
491
 
492
static s32 SEQ_UI_Button_Copy(s32 depressed)
493
{
240 tk 494
  static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE;
134 tk 495
 
240 tk 496
  seq_ui_button_state.COPY = depressed ? 0 : 1;
497
 
280 tk 498
  if( ui_page == SEQ_UI_PAGE_MIXER ) {
499
    if( depressed ) return -1;
500
    SEQ_UI_MIXER_Copy();
501
    return 1;
502
  } else {
503
    if( !depressed ) {
504
      prev_page = ui_page;
505
      SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL);
506
    }
240 tk 507
 
280 tk 508
    s32 status = SEQ_UI_UTIL_CopyButton(depressed);
240 tk 509
 
280 tk 510
    if( depressed )
511
      SEQ_UI_PageSet(prev_page);
240 tk 512
 
280 tk 513
    return status;
514
  }
134 tk 515
}
516
 
517
static s32 SEQ_UI_Button_Paste(s32 depressed)
518
{
240 tk 519
  static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE;
134 tk 520
 
240 tk 521
  seq_ui_button_state.PASTE = depressed ? 0 : 1;
522
 
280 tk 523
  if( ui_page == SEQ_UI_PAGE_MIXER ) {
524
    if( depressed ) return -1;
525
    SEQ_UI_MIXER_Paste();
526
    return 1;
527
  } else {
528
    if( !depressed ) {
529
      prev_page = ui_page;
530
      SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL);
531
    }
240 tk 532
 
280 tk 533
    s32 status = SEQ_UI_UTIL_PasteButton(depressed);
240 tk 534
 
280 tk 535
    if( depressed )
536
      SEQ_UI_PageSet(prev_page);
240 tk 537
 
280 tk 538
    return status;
539
  }
134 tk 540
}
541
 
542
static s32 SEQ_UI_Button_Clear(s32 depressed)
543
{
240 tk 544
  seq_ui_button_state.CLEAR = depressed ? 0 : 1;
280 tk 545
 
546
  if( ui_page == SEQ_UI_PAGE_MIXER ) {
547
    if( depressed ) return -1;
548
    SEQ_UI_MIXER_Clear();
549
    return 1;
550
  } else {
551
    return SEQ_UI_UTIL_ClearButton(depressed);
552
  }
134 tk 553
}
554
 
555
static s32 SEQ_UI_Button_Menu(s32 depressed)
556
{
167 tk 557
  // TODO: define generic #define for this button behaviour
178 tk 558
#if DEFAULT_BEHAVIOUR_BUTTON_MENU
559
  // toggle mode
134 tk 560
  if( depressed ) return -1; // ignore when button depressed
306 tk 561
  seq_ui_button_state.MENU_FIRST_PAGE_SELECTED = 0;
167 tk 562
  seq_ui_button_state.MENU_PRESSED ^= 1; // toggle MENU pressed (will also be released once GP button has been pressed)
563
#else
178 tk 564
  // set mode
306 tk 565
  seq_ui_button_state.MENU_FIRST_PAGE_SELECTED = 0;
167 tk 566
  seq_ui_button_state.MENU_PRESSED = depressed ? 0 : 1;
567
#endif
134 tk 568
 
569
  return 0; // no error
570
}
571
 
572
static s32 SEQ_UI_Button_Select(s32 depressed)
573
{
168 tk 574
  // forward to menu page
306 tk 575
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 576
    ui_button_callback(SEQ_UI_BUTTON_Select, depressed);
173 tk 577
  ui_cursor_flash_ctr = 0;
134 tk 578
 
579
  return 0; // no error
580
}
581
 
582
static s32 SEQ_UI_Button_Exit(s32 depressed)
583
{
272 tk 584
  if( depressed ) return -1; // ignore when button depressed
585
 
586
  u8 prev_ui_page = ui_page;
587
 
168 tk 588
  // forward to menu page
306 tk 589
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 590
    ui_button_callback(SEQ_UI_BUTTON_Exit, depressed);
173 tk 591
  ui_cursor_flash_ctr = 0;
134 tk 592
 
167 tk 593
  // release all button states
594
  seq_ui_button_state.ALL = 0;
595
 
272 tk 596
  // enter menu page if we were not there before
597
  if( prev_ui_page != SEQ_UI_PAGE_MENU )
598
    SEQ_UI_PageSet(SEQ_UI_PAGE_MENU);
599
 
134 tk 600
  return 0; // no error
601
}
602
 
603
static s32 SEQ_UI_Button_Edit(s32 depressed)
604
{
605
  if( depressed ) return -1; // ignore when button depressed
606
 
167 tk 607
  // change to edit page
608
  SEQ_UI_PageSet(SEQ_UI_PAGE_EDIT);
609
 
178 tk 610
  // set/clear encoder fast function if required
611
  SEQ_UI_InitEncSpeed(1); // auto config
612
 
134 tk 613
  return 0; // no error
614
}
615
 
616
static s32 SEQ_UI_Button_Mute(s32 depressed)
617
{
618
  if( depressed ) return -1; // ignore when button depressed
619
 
184 tk 620
  SEQ_UI_PageSet(SEQ_UI_PAGE_MUTE);
621
 
134 tk 622
  return 0; // no error
623
}
624
 
625
static s32 SEQ_UI_Button_Pattern(s32 depressed)
626
{
627
  if( depressed ) return -1; // ignore when button depressed
628
 
184 tk 629
  SEQ_UI_PageSet(SEQ_UI_PAGE_PATTERN);
630
 
134 tk 631
  return 0; // no error
632
}
633
 
634
static s32 SEQ_UI_Button_Song(s32 depressed)
635
{
636
  if( depressed ) return -1; // ignore when button depressed
637
 
638
  return 0; // no error
639
}
640
 
641
static s32 SEQ_UI_Button_Solo(s32 depressed)
642
{
178 tk 643
#if DEFAULT_BEHAVIOUR_BUTTON_ALL
644
  // toggle mode
134 tk 645
  if( depressed ) return -1; // ignore when button depressed
178 tk 646
  seq_ui_button_state.SOLO ^= 1;
647
#else
648
  // set mode
649
  seq_ui_button_state.SOLO = depressed ? 0 : 1;
650
#endif
134 tk 651
 
652
  return 0; // no error
653
}
654
 
655
static s32 SEQ_UI_Button_Fast(s32 depressed)
656
{
178 tk 657
#if DEFAULT_BEHAVIOUR_BUTTON_FAST
658
  // toggle mode
134 tk 659
  if( depressed ) return -1; // ignore when button depressed
178 tk 660
  seq_ui_button_state.FAST_ENCODERS ^= 1;
661
#else
662
  // set mode
663
  seq_ui_button_state.FAST_ENCODERS = depressed ? 0 : 1;
664
#endif
134 tk 665
 
178 tk 666
  SEQ_UI_InitEncSpeed(0); // no auto config
667
 
134 tk 668
  return 0; // no error
669
}
670
 
671
static s32 SEQ_UI_Button_All(s32 depressed)
672
{
178 tk 673
  seq_ui_button_state.CHANGE_ALL_STEPS_SAME_VALUE = depressed ? 0 : 1;
134 tk 674
 
178 tk 675
#if DEFAULT_BEHAVIOUR_BUTTON_ALL
676
  // toggle mode
677
  if( depressed ) return -1;
678
  seq_ui_button_state.CHANGE_ALL_STEPS ^= 1;
679
#else
680
  // set mode
681
  seq_ui_button_state.CHANGE_ALL_STEPS = depressed ? 0 : 1;
682
#endif
683
 
134 tk 684
  return 0; // no error
685
}
686
 
687
static s32 SEQ_UI_Button_StepView(s32 depressed)
688
{
326 tk 689
 
303 tk 690
#if DEFAULT_BEHAVIOUR_BUTTON_STEPVIEW
134 tk 691
  if( depressed ) return -1; // ignore when button depressed
303 tk 692
  seq_ui_button_state.STEPVIEW ^= 1; // toggle STEPVIEW pressed (will also be released once GP button has been pressed)
693
#else
694
  // set mode
695
  seq_ui_button_state.STEPVIEW = depressed ? 0 : 1;
696
#endif
134 tk 697
 
303 tk 698
  if( seq_ui_button_state.STEPVIEW ) {
699
    ui_stepview_prev_page = ui_page;
700
    SEQ_UI_PageSet(SEQ_UI_PAGE_STEPSEL);
701
  } else {
702
    SEQ_UI_PageSet(ui_stepview_prev_page);
703
  }
134 tk 704
 
705
  return 0; // no error
706
}
707
 
708
static s32 SEQ_UI_Button_TapTempo(s32 depressed)
709
{
710
  if( depressed ) return -1; // ignore when button depressed
711
 
712
  return 0; // no error
713
}
714
 
715
static s32 SEQ_UI_Button_Track(s32 depressed, u32 track)
716
{
717
  if( depressed ) return -1; // ignore when button depressed
718
 
719
  if( track >= 4 ) return -2; // max. 4 track buttons
720
 
721
  ui_selected_tracks = (1 << track); // TODO: multi-selections!
722
 
178 tk 723
  // set/clear encoder fast function if required
724
  SEQ_UI_InitEncSpeed(1); // auto config
725
 
134 tk 726
  return 0; // no error
727
}
728
 
729
static s32 SEQ_UI_Button_Group(s32 depressed, u32 group)
730
{
731
  if( depressed ) return -1; // ignore when button depressed
732
 
733
  if( group >= 4 ) return -2; // max. 4 group buttons
734
 
735
  ui_selected_group = group;
736
 
178 tk 737
  // set/clear encoder fast function if required
738
  SEQ_UI_InitEncSpeed(1); // auto config
739
 
134 tk 740
  return 0; // no error
741
}
742
 
743
static s32 SEQ_UI_Button_ParLayer(s32 depressed, u32 par_layer)
744
{
745
  if( depressed ) return -1; // ignore when button depressed
746
 
747
  if( par_layer >= 3 ) return -2; // max. 3 parlayer buttons
748
 
749
  ui_selected_par_layer = par_layer;
750
 
178 tk 751
  // set/clear encoder fast function if required
752
  SEQ_UI_InitEncSpeed(1); // auto config
753
 
134 tk 754
  return 0; // no error
755
}
756
 
757
static s32 SEQ_UI_Button_TrgLayer(s32 depressed, u32 trg_layer)
758
{
759
  if( trg_layer >= 3 ) return -2; // max. 3 trglayer buttons
760
 
326 tk 761
  u8 visible_track = SEQ_UI_VisibleTrackGet();
762
  u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);
763
  u8 num_t_layers = SEQ_TRG_NumLayersGet(visible_track);
134 tk 764
 
328 tk 765
  if( event_mode != SEQ_EVENT_MODE_Drum && num_t_layers <= 3 ) {
326 tk 766
    // 3 layers: direct selection with LayerA/B/C button
767
    if( depressed ) return -1; // ignore when button depressed
768
    seq_ui_button_state.TRG_LAYER_SEL = 0;
769
    ui_selected_trg_layer = trg_layer;
328 tk 770
  } else if( event_mode != SEQ_EVENT_MODE_Drum && num_t_layers <= 4 ) {
326 tk 771
    // 4 layers: LayerC Button toggles between C and D
772
    if( depressed ) return -1; // ignore when button depressed
773
    seq_ui_button_state.TRG_LAYER_SEL = 0;
774
    if( trg_layer == 3 )
775
      ui_selected_trg_layer = (ui_selected_trg_layer == 3) ? 4 : 3;
776
    else
777
      ui_selected_trg_layer = trg_layer;
778
  } else {
328 tk 779
    // >4 layers or drum mode: LayerA/B button selects directly, Layer C button enters trigger assignment screen
326 tk 780
    // also used for drum tracks
781
    if( trg_layer <= 1 ) {
782
      if( depressed ) return -1; // ignore when button depressed
328 tk 783
      seq_ui_button_state.TRG_LAYER_SEL = 0;
784
      ui_selected_trg_layer = trg_layer;
326 tk 785
    } else {
786
#if DEFAULT_BEHAVIOUR_BUTTON_TRG_LAYER
787
      if( depressed ) return -1; // ignore when button depressed
788
      seq_ui_button_state.TRG_LAYER_SEL ^= 1; // toggle TRGSEL status (will also be released once GP button has been pressed)
789
#else
790
      // set mode
791
      seq_ui_button_state.TRG_LAYER_SEL = depressed ? 0 : 1;
792
#endif
793
 
794
      if( seq_ui_button_state.TRG_LAYER_SEL ) {
795
    ui_trglayer_prev_page = ui_page;
796
    SEQ_UI_PageSet(SEQ_UI_PAGE_TRGSEL);
797
      } else {
798
    SEQ_UI_PageSet(ui_trglayer_prev_page);
799
      }
800
    }
801
  }
802
 
134 tk 803
  return 0; // no error
804
}
805
 
806
 
807
 
808
/////////////////////////////////////////////////////////////////////////////
809
// Button handler
810
/////////////////////////////////////////////////////////////////////////////
811
s32 SEQ_UI_Button_Handler(u32 pin, u32 pin_value)
812
{
328 tk 813
  // ensure that selections are matching with track constraints
814
  SEQ_UI_CheckSelections();
815
 
134 tk 816
  switch( pin ) {
168 tk 817
#if BUTTON_GP1 != BUTTON_DISABLED
134 tk 818
    case BUTTON_GP1:   SEQ_UI_Button_GP(pin_value, 0); break;
819
#endif
168 tk 820
#if BUTTON_GP2 != BUTTON_DISABLED
134 tk 821
    case BUTTON_GP2:   SEQ_UI_Button_GP(pin_value, 1); break;
822
#endif
168 tk 823
#if BUTTON_GP3 != BUTTON_DISABLED
134 tk 824
    case BUTTON_GP3:   SEQ_UI_Button_GP(pin_value, 2); break;
825
#endif
168 tk 826
#if BUTTON_GP4 != BUTTON_DISABLED
134 tk 827
    case BUTTON_GP4:   SEQ_UI_Button_GP(pin_value, 3); break;
828
#endif
168 tk 829
#if BUTTON_GP5 != BUTTON_DISABLED
134 tk 830
    case BUTTON_GP5:   SEQ_UI_Button_GP(pin_value, 4); break;
831
#endif
168 tk 832
#if BUTTON_GP6 != BUTTON_DISABLED
134 tk 833
    case BUTTON_GP6:   SEQ_UI_Button_GP(pin_value, 5); break;
834
#endif
168 tk 835
#if BUTTON_GP7 != BUTTON_DISABLED
134 tk 836
    case BUTTON_GP7:   SEQ_UI_Button_GP(pin_value, 6); break;
837
#endif
168 tk 838
#if BUTTON_GP8 != BUTTON_DISABLED
134 tk 839
    case BUTTON_GP8:   SEQ_UI_Button_GP(pin_value, 7); break;
840
#endif
168 tk 841
#if BUTTON_GP9 != BUTTON_DISABLED
134 tk 842
    case BUTTON_GP9:   SEQ_UI_Button_GP(pin_value, 8); break;
843
#endif
168 tk 844
#if BUTTON_GP10 != BUTTON_DISABLED
134 tk 845
    case BUTTON_GP10:  SEQ_UI_Button_GP(pin_value, 9); break;
846
#endif
168 tk 847
#if BUTTON_GP11 != BUTTON_DISABLED
134 tk 848
    case BUTTON_GP11:  SEQ_UI_Button_GP(pin_value, 10); break;
849
#endif
168 tk 850
#if BUTTON_GP12 != BUTTON_DISABLED
134 tk 851
    case BUTTON_GP12:  SEQ_UI_Button_GP(pin_value, 11); break;
852
#endif
168 tk 853
#if BUTTON_GP13 != BUTTON_DISABLED
134 tk 854
    case BUTTON_GP13:  SEQ_UI_Button_GP(pin_value, 12); break;
855
#endif
168 tk 856
#if BUTTON_GP14 != BUTTON_DISABLED
134 tk 857
    case BUTTON_GP14:  SEQ_UI_Button_GP(pin_value, 13); break;
858
#endif
168 tk 859
#if BUTTON_GP15 != BUTTON_DISABLED
134 tk 860
    case BUTTON_GP15:  SEQ_UI_Button_GP(pin_value, 14); break;
861
#endif
168 tk 862
#if BUTTON_GP16 != BUTTON_DISABLED
134 tk 863
    case BUTTON_GP16:  SEQ_UI_Button_GP(pin_value, 15); break;
864
#endif
865
 
168 tk 866
#if BUTTON_LEFT != BUTTON_DISABLED
134 tk 867
    case BUTTON_LEFT:  SEQ_UI_Button_Left(pin_value); break;
868
#endif
168 tk 869
#if BUTTON_RIGHT != BUTTON_DISABLED
134 tk 870
    case BUTTON_RIGHT: SEQ_UI_Button_Right(pin_value); break;
871
#endif
872
 
168 tk 873
#if BUTTON_DOWN != BUTTON_DISABLED
874
    case BUTTON_DOWN:  SEQ_UI_Button_Down(pin_value); break;
875
#endif
876
#if BUTTON_UP != BUTTON_DISABLED
877
    case BUTTON_UP:    SEQ_UI_Button_Up(pin_value); break;
878
#endif
879
 
880
#if BUTTON_SCRUB != BUTTON_DISABLED
134 tk 881
    case BUTTON_SCRUB: SEQ_UI_Button_Scrub(pin_value); break;
882
#endif
168 tk 883
#if BUTTON_METRONOME != BUTTON_DISABLED
134 tk 884
    case BUTTON_METRONOME: SEQ_UI_Button_Metronome(pin_value); break;
885
#endif
886
 
168 tk 887
#if BUTTON_STOP != BUTTON_DISABLED
134 tk 888
    case BUTTON_STOP:  SEQ_UI_Button_Stop(pin_value); break;
889
#endif
168 tk 890
#if BUTTON_PAUSE != BUTTON_DISABLED
134 tk 891
    case BUTTON_PAUSE: SEQ_UI_Button_Pause(pin_value); break;
892
#endif
168 tk 893
#if BUTTON_PLAY != BUTTON_DISABLED
134 tk 894
    case BUTTON_PLAY:  SEQ_UI_Button_Play(pin_value); break;
895
#endif
168 tk 896
#if BUTTON_REW != BUTTON_DISABLED
134 tk 897
    case BUTTON_REW:   SEQ_UI_Button_Rew(pin_value); break;
898
#endif
168 tk 899
#if BUTTON_FWD != BUTTON_DISABLED
134 tk 900
    case BUTTON_FWD:   SEQ_UI_Button_Fwd(pin_value); break;
901
#endif
902
 
168 tk 903
#if BUTTON_F1 != BUTTON_DISABLED
134 tk 904
    case BUTTON_F1:    SEQ_UI_Button_F1(pin_value); break;
905
#endif
168 tk 906
#if BUTTON_F2 != BUTTON_DISABLED
134 tk 907
    case BUTTON_F2:    SEQ_UI_Button_F2(pin_value); break;
908
#endif
168 tk 909
#if BUTTON_F3 != BUTTON_DISABLED
134 tk 910
    case BUTTON_F3:    SEQ_UI_Button_F3(pin_value); break;
911
#endif
168 tk 912
#if BUTTON_F4 != BUTTON_DISABLED
134 tk 913
    case BUTTON_F4:    SEQ_UI_Button_F4(pin_value); break;
914
#endif
915
 
168 tk 916
#if BUTTON_UTILITY != BUTTON_DISABLED
134 tk 917
    case BUTTON_UTILITY: SEQ_UI_Button_Utility(pin_value); break;
918
#endif
168 tk 919
#if BUTTON_COPY != BUTTON_DISABLED
134 tk 920
    case BUTTON_COPY:  SEQ_UI_Button_Copy(pin_value); break;
921
#endif
168 tk 922
#if BUTTON_PASTE != BUTTON_DISABLED
134 tk 923
    case BUTTON_PASTE: SEQ_UI_Button_Paste(pin_value); break;
924
#endif
168 tk 925
#if BUTTON_CLEAR != BUTTON_DISABLED
134 tk 926
    case BUTTON_CLEAR: SEQ_UI_Button_Clear(pin_value); break;
927
#endif
928
 
168 tk 929
#if BUTTON_MENU != BUTTON_DISABLED
134 tk 930
    case BUTTON_MENU:  SEQ_UI_Button_Menu(pin_value); break;
931
#endif
168 tk 932
#if BUTTON_SELECT != BUTTON_DISABLED
134 tk 933
    case BUTTON_SELECT:SEQ_UI_Button_Select(pin_value); break;
934
#endif
168 tk 935
#if BUTTON_EXIT != BUTTON_DISABLED
134 tk 936
    case BUTTON_EXIT:  SEQ_UI_Button_Exit(pin_value); break;
937
#endif
938
 
168 tk 939
#if BUTTON_TRACK1 != BUTTON_DISABLED
134 tk 940
    case BUTTON_TRACK1: SEQ_UI_Button_Track(pin_value, 0); break;
941
#endif
168 tk 942
#if BUTTON_TRACK2 != BUTTON_DISABLED
134 tk 943
    case BUTTON_TRACK2: SEQ_UI_Button_Track(pin_value, 1); break;
944
#endif
168 tk 945
#if BUTTON_TRACK3 != BUTTON_DISABLED
134 tk 946
    case BUTTON_TRACK3: SEQ_UI_Button_Track(pin_value, 2); break;
947
#endif
168 tk 948
#if BUTTON_TRACK4 != BUTTON_DISABLED
134 tk 949
    case BUTTON_TRACK4: SEQ_UI_Button_Track(pin_value, 3); break;
950
#endif
951
 
168 tk 952
#if BUTTON_PAR_LAYER_A != BUTTON_DISABLED
134 tk 953
    case BUTTON_PAR_LAYER_A: SEQ_UI_Button_ParLayer(pin_value, 0); break;
954
#endif
168 tk 955
#if BUTTON_PAR_LAYER_B != BUTTON_DISABLED
134 tk 956
    case BUTTON_PAR_LAYER_B: SEQ_UI_Button_ParLayer(pin_value, 1); break;
957
#endif
168 tk 958
#if BUTTON_PAR_LAYER_C != BUTTON_DISABLED
134 tk 959
    case BUTTON_PAR_LAYER_C: SEQ_UI_Button_ParLayer(pin_value, 2); break;
960
#endif
961
 
168 tk 962
#if BUTTON_EDIT != BUTTON_DISABLED
134 tk 963
    case BUTTON_EDIT:   SEQ_UI_Button_Edit(pin_value); break;
964
#endif
168 tk 965
#if BUTTON_MUTE != BUTTON_DISABLED
134 tk 966
    case BUTTON_MUTE:   SEQ_UI_Button_Mute(pin_value); break;
967
#endif
168 tk 968
#if BUTTON_PATTERN != BUTTON_DISABLED
134 tk 969
    case BUTTON_PATTERN:SEQ_UI_Button_Pattern(pin_value); break;
970
#endif
168 tk 971
#if BUTTON_SONG != BUTTON_DISABLED
134 tk 972
    case BUTTON_SONG:   SEQ_UI_Button_Song(pin_value); break;
973
#endif
974
 
168 tk 975
#if BUTTON_SOLO != BUTTON_DISABLED
134 tk 976
    case BUTTON_SOLO:   SEQ_UI_Button_Solo(pin_value); break;
977
#endif
168 tk 978
#if BUTTON_FAST != BUTTON_DISABLED
134 tk 979
    case BUTTON_FAST:   SEQ_UI_Button_Fast(pin_value); break;
980
#endif
168 tk 981
#if BUTTON_ALL != BUTTON_DISABLED
134 tk 982
    case BUTTON_ALL:    SEQ_UI_Button_All(pin_value); break;
983
#endif
984
 
168 tk 985
#if BUTTON_GROUP1 != BUTTON_DISABLED
134 tk 986
    case BUTTON_GROUP1: SEQ_UI_Button_Group(pin_value, 0); break;
987
#endif
168 tk 988
#if BUTTON_GROUP2 != BUTTON_DISABLED
134 tk 989
    case BUTTON_GROUP2: SEQ_UI_Button_Group(pin_value, 1); break;
990
#endif
168 tk 991
#if BUTTON_GROUP3 != BUTTON_DISABLED
134 tk 992
    case BUTTON_GROUP3: SEQ_UI_Button_Group(pin_value, 2); break;
993
#endif
168 tk 994
#if BUTTON_GROUP4 != BUTTON_DISABLED
134 tk 995
    case BUTTON_GROUP4: SEQ_UI_Button_Group(pin_value, 3); break;
996
#endif
997
 
168 tk 998
#if BUTTON_TRG_LAYER_A != BUTTON_DISABLED
134 tk 999
    case BUTTON_TRG_LAYER_A: SEQ_UI_Button_TrgLayer(pin_value, 0); break;
1000
#endif
168 tk 1001
#if BUTTON_TRG_LAYER_B != BUTTON_DISABLED
134 tk 1002
    case BUTTON_TRG_LAYER_B: SEQ_UI_Button_TrgLayer(pin_value, 1); break;
1003
#endif
168 tk 1004
#if BUTTON_TRG_LAYER_C != BUTTON_DISABLED
134 tk 1005
    case BUTTON_TRG_LAYER_C: SEQ_UI_Button_TrgLayer(pin_value, 2); break;
1006
#endif
1007
 
168 tk 1008
#if BUTTON_STEP_VIEW != BUTTON_DISABLED
134 tk 1009
    case BUTTON_STEP_VIEW: SEQ_UI_Button_StepView(pin_value); break;
1010
#endif
1011
 
168 tk 1012
#if BUTTON_TAP_TEMPO != BUTTON_DISABLED
134 tk 1013
    case BUTTON_TAP_TEMPO:   SEQ_UI_Button_TapTempo(pin_value); break;
1014
#endif
1015
 
1016
    default:
1017
      return -1; // button function not mapped to physical button
1018
  }
1019
 
1020
  // request display update
159 tk 1021
  seq_ui_display_update_req = 1;
134 tk 1022
 
1023
  return 0; // no error
1024
}
1025
 
1026
 
1027
/////////////////////////////////////////////////////////////////////////////
1028
// Encoder handler
1029
/////////////////////////////////////////////////////////////////////////////
1030
s32 SEQ_UI_Encoder_Handler(u32 encoder, s32 incrementer)
1031
{
1032
  if( encoder > 16 )
1033
    return -1; // encoder doesn't exist
1034
 
328 tk 1035
  // ensure that selections are matching with track constraints
1036
  SEQ_UI_CheckSelections();
1037
 
134 tk 1038
  // limit incrementer
1039
  if( incrementer > 3 )
1040
    incrementer = 3;
1041
  else if( incrementer < -3 )
1042
    incrementer = -3;
1043
 
306 tk 1044
  if( !seq_ui_button_state.MENU_PRESSED && ui_encoder_callback != NULL ) {
173 tk 1045
    ui_encoder_callback((encoder == 0) ? SEQ_UI_ENCODER_Datawheel : (encoder-1), incrementer);
1046
    ui_cursor_flash_ctr = 0; // ensure that value is visible when it has been changed
134 tk 1047
  }
1048
 
1049
  // request display update
159 tk 1050
  seq_ui_display_update_req = 1;
134 tk 1051
 
1052
  return 0; // no error
1053
}
1054
 
1055
 
1056
/////////////////////////////////////////////////////////////////////////////
1057
// Update LCD messages
1058
// Usually called from background task
1059
/////////////////////////////////////////////////////////////////////////////
1060
s32 SEQ_UI_LCD_Handler(void)
1061
{
159 tk 1062
  if( seq_ui_display_init_req ) {
1063
    seq_ui_display_init_req = 0; // clear request
134 tk 1064
 
278 tk 1065
    // clear force update of LCD
1066
    SEQ_LCD_Clear();
1067
    SEQ_LCD_Update(1);
134 tk 1068
 
168 tk 1069
    // select first menu item
1070
    ui_selected_item = 0;
1071
 
167 tk 1072
    // call init function of current page
272 tk 1073
    if( ui_menu_pages[ui_page].init_callback != NULL )
1074
      ui_menu_pages[ui_page].init_callback(0); // mode
134 tk 1075
 
1076
    // request display update
159 tk 1077
    seq_ui_display_update_req = 1;
134 tk 1078
  }
1079
 
306 tk 1080
  // in MENU page: overrule LCD output so long MENU button is pressed/active
1081
  if( seq_ui_button_state.MENU_PRESSED && !seq_ui_button_state.MENU_FIRST_PAGE_SELECTED ) {
1082
    SEQ_LCD_CursorSet(0, 0);
1083
    //                      <-------------------------------------->
1084
    //                      0123456789012345678901234567890123456789
1085
    SEQ_LCD_PrintString("Menu Shortcuts:");
1086
    SEQ_LCD_PrintSpaces(25 + 40);
1087
    SEQ_LCD_CursorSet(0, 1);
1088
    SEQ_LCD_PrintString(UI_SHORTCUT_STR); // defined in seq_ui_pages.inc
1089
  } else {
1090
    // perform high priority LCD update request
1091
    if( ui_lcd_callback != NULL )
1092
      ui_lcd_callback(1); // high_prio
167 tk 1093
 
306 tk 1094
    // perform low priority LCD update request if requested
1095
    if( seq_ui_display_update_req ) {
1096
      seq_ui_display_update_req = 0; // clear request
328 tk 1097
 
1098
      // ensure that selections are matching with track constraints
1099
      SEQ_UI_CheckSelections();
1100
 
306 tk 1101
      if( ui_lcd_callback != NULL )
1102
    ui_lcd_callback(0); // no high_prio
1103
    }
134 tk 1104
  }
1105
 
299 tk 1106
  // if SD card message active: copy over the text
1107
  if( sdcard_msg_ctr ) {
1108
    const char animation_l[4][3] = {
1109
      "  ", " >", ">>", "> " };
1110
    const char animation_r[4][3] = {
1111
      "  ", "< ", "<<", " <" };
1112
    int anum = (sdcard_msg_ctr % 1000) / 250;
1113
 
1114
    int line;
1115
    for(line=0; line<2; ++line) {
1116
      SEQ_LCD_CursorSet(40, line);
1117
      SEQ_LCD_PrintFormattedString(" %s| %-20s |%s ",
1118
                   (char *)animation_l[anum],
1119
                   (char *)sdcard_msg[line],
1120
                   (char *)animation_r[anum]);
1121
    }
1122
  }
1123
 
278 tk 1124
  // transfer all changed characters to LCD
1125
  SEQ_LCD_Update(0);
159 tk 1126
 
134 tk 1127
  return 0; // no error
1128
}
1129
 
1130
 
1131
 
1132
/////////////////////////////////////////////////////////////////////////////
1133
// Update all LEDs
1134
// Usually called from background task
1135
/////////////////////////////////////////////////////////////////////////////
1136
s32 SEQ_UI_LED_Handler(void)
1137
{
326 tk 1138
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1139
  u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);
1140
 
134 tk 1141
  // track LEDs
167 tk 1142
  SEQ_LED_PinSet(LED_TRACK1, (ui_selected_tracks & (1 << 0)));
1143
  SEQ_LED_PinSet(LED_TRACK2, (ui_selected_tracks & (1 << 1)));
1144
  SEQ_LED_PinSet(LED_TRACK3, (ui_selected_tracks & (1 << 2)));
1145
  SEQ_LED_PinSet(LED_TRACK4, (ui_selected_tracks & (1 << 3)));
134 tk 1146
 
1147
  // parameter layer LEDs
167 tk 1148
  SEQ_LED_PinSet(LED_PAR_LAYER_A, (ui_selected_par_layer == 0));
1149
  SEQ_LED_PinSet(LED_PAR_LAYER_B, (ui_selected_par_layer == 1));
326 tk 1150
  SEQ_LED_PinSet(LED_PAR_LAYER_C, (ui_selected_par_layer >= 2) || seq_ui_button_state.PAR_LAYER_SEL);
134 tk 1151
 
1152
  // group LEDs
167 tk 1153
  SEQ_LED_PinSet(LED_GROUP1, (ui_selected_group == 0));
1154
  SEQ_LED_PinSet(LED_GROUP2, (ui_selected_group == 1));
1155
  SEQ_LED_PinSet(LED_GROUP3, (ui_selected_group == 2));
1156
  SEQ_LED_PinSet(LED_GROUP4, (ui_selected_group == 3));
134 tk 1157
 
1158
  // trigger layer LEDs
328 tk 1159
  SEQ_LED_PinSet(LED_TRG_LAYER_A, (ui_selected_trg_layer == 0));
1160
  SEQ_LED_PinSet(LED_TRG_LAYER_B, (ui_selected_trg_layer == 1));
1161
  SEQ_LED_PinSet(LED_TRG_LAYER_C, (ui_selected_trg_layer >= 2) || seq_ui_button_state.TRG_LAYER_SEL);
134 tk 1162
 
1163
  // remaining LEDs
167 tk 1164
  SEQ_LED_PinSet(LED_EDIT, ui_page == SEQ_UI_PAGE_EDIT);
184 tk 1165
  SEQ_LED_PinSet(LED_MUTE, ui_page == SEQ_UI_PAGE_MUTE);
1166
  SEQ_LED_PinSet(LED_PATTERN, ui_page == SEQ_UI_PAGE_PATTERN);
134 tk 1167
  SEQ_LED_PinSet(LED_SONG, 0);
1168
 
178 tk 1169
  SEQ_LED_PinSet(LED_SOLO, seq_ui_button_state.SOLO);
1170
  SEQ_LED_PinSet(LED_FAST, seq_ui_button_state.FAST_ENCODERS);
1171
  SEQ_LED_PinSet(LED_ALL, seq_ui_button_state.CHANGE_ALL_STEPS);
134 tk 1172
 
193 tk 1173
  SEQ_LED_PinSet(LED_PLAY, SEQ_BPM_IsRunning());
1174
  SEQ_LED_PinSet(LED_STOP, !SEQ_BPM_IsRunning() && !ui_seq_pause);
1175
  SEQ_LED_PinSet(LED_PAUSE, ui_seq_pause);
240 tk 1176
 
1177
  SEQ_LED_PinSet(LED_REW, seq_ui_button_state.REW);
1178
  SEQ_LED_PinSet(LED_FWD, seq_ui_button_state.FWD);
134 tk 1179
 
303 tk 1180
  SEQ_LED_PinSet(LED_STEPVIEW, seq_ui_button_state.STEPVIEW);
134 tk 1181
 
167 tk 1182
  SEQ_LED_PinSet(LED_MENU, seq_ui_button_state.MENU_PRESSED);
178 tk 1183
  SEQ_LED_PinSet(LED_SCRUB, seq_ui_button_state.SCRUB);
1184
  SEQ_LED_PinSet(LED_METRONOME, seq_ui_button_state.METRONOME);
134 tk 1185
 
240 tk 1186
  SEQ_LED_PinSet(LED_UTILITY, ui_page == SEQ_UI_PAGE_UTIL);
1187
  SEQ_LED_PinSet(LED_COPY, seq_ui_button_state.COPY);
1188
  SEQ_LED_PinSet(LED_PASTE, seq_ui_button_state.PASTE);
1189
  SEQ_LED_PinSet(LED_CLEAR, seq_ui_button_state.CLEAR);
1190
 
1191
  SEQ_LED_PinSet(LED_F1, seq_ui_button_state.F1);
1192
  SEQ_LED_PinSet(LED_F2, seq_ui_button_state.F2);
1193
  SEQ_LED_PinSet(LED_F3, seq_ui_button_state.F3);
1194
  SEQ_LED_PinSet(LED_F4, seq_ui_button_state.F4);
1195
 
1196
  SEQ_LED_PinSet(LED_DOWN, seq_ui_button_state.DOWN);
1197
  SEQ_LED_PinSet(LED_UP, seq_ui_button_state.UP);
1198
 
167 tk 1199
 
306 tk 1200
  // in MENU page: overrule GP LEDs so long MENU button is pressed/active
1201
  if( seq_ui_button_state.MENU_PRESSED ) {
1202
    if( ui_cursor_flash ) // if flashing flag active: no LED flag set
1203
      ui_gp_leds = 0x0000;
1204
    else {
1205
      int i;
1206
      u16 new_ui_gp_leds = 0x0000;
1207
      for(i=0; i<16; ++i)
1208
    if( ui_page == ui_shortcut_menu_pages[i] )
1209
      new_ui_gp_leds |= (1 << i);
1210
      ui_gp_leds = new_ui_gp_leds;
1211
    }
1212
  } else {
1213
    // note: the background function is permanently interrupted - therefore we write the GP pattern
1214
    // into a temporary variable, and take it over once completed
1215
    u16 new_ui_gp_leds = 0x0000;
1216
    // request GP LED values from current menu page
1217
    // will be transfered to DOUT registers in SEQ_UI_LED_Handler_Periodic
1218
    new_ui_gp_leds = 0x0000;
206 tk 1219
 
306 tk 1220
    if( ui_led_callback != NULL )
1221
      ui_led_callback(&new_ui_gp_leds);
167 tk 1222
 
306 tk 1223
    ui_gp_leds = new_ui_gp_leds;
1224
  }
1225
 
134 tk 1226
  return 0; // no error
1227
}
1228
 
1229
 
1230
/////////////////////////////////////////////////////////////////////////////
1231
// updates high-prio LED functions (GP LEDs and Beat LED)
168 tk 1232
// called each mS
134 tk 1233
/////////////////////////////////////////////////////////////////////////////
1234
s32 SEQ_UI_LED_Handler_Periodic()
1235
{
1236
  // GP LEDs are only updated when ui_gp_leds or pos_marker_mask has changed
1237
  static u16 prev_ui_gp_leds = 0x0000;
1238
  static u16 prev_pos_marker_mask = 0x0000;
1239
 
1240
  // beat LED: tmp. for demo w/o real sequencer
193 tk 1241
  u8 sequencer_running = SEQ_BPM_IsRunning();
325 tk 1242
  SEQ_LED_PinSet(LED_BEAT, sequencer_running && ((seq_core_state.ref_step & 3) == 0));
134 tk 1243
 
1244
  // for song position marker (supports 16 LEDs, check for selected step view)
1245
  u16 pos_marker_mask = 0x0000;
325 tk 1246
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1247
  u8 played_step = seq_core_trk[visible_track].step;
1248
  if( seq_ui_button_state.STEPVIEW ) {
1249
    // if STEPVIEW button pressed: pos marker correlated to zoom ratio
1250
    if( sequencer_running )
1251
      pos_marker_mask = 1 << (played_step / (SEQ_TRG_NumStepsGet(visible_track)/16));
1252
  } else {
1253
    if( sequencer_running && (played_step >> 4) == ui_selected_step_view )
1254
      pos_marker_mask = 1 << (played_step & 0xf);
1255
  }
134 tk 1256
 
1257
  // exit of pattern hasn't changed
173 tk 1258
  if( prev_ui_gp_leds == ui_gp_leds && prev_pos_marker_mask == pos_marker_mask )
134 tk 1259
    return 0;
173 tk 1260
  prev_ui_gp_leds = ui_gp_leds;
134 tk 1261
  prev_pos_marker_mask = pos_marker_mask;
1262
 
1263
  // transfer to GP LEDs
1264
 
1265
#ifdef DEFAULT_GP_DOUT_SR_L
1266
# ifdef DEFAULT_GP_DOUT_SR_L2
173 tk 1267
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_L-1, (ui_gp_leds >> 0) & 0xff);
134 tk 1268
# else
173 tk 1269
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_L-1, ((ui_gp_leds ^ pos_marker_mask) >> 0) & 0xff);
134 tk 1270
# endif
1271
#endif
1272
#ifdef DEFAULT_GP_DOUT_SR_R
1273
# ifdef DEFAULT_GP_DOUT_SR_R2
173 tk 1274
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_R-1, (ui_gp_leds >> 8) & 0xff);
134 tk 1275
#else
173 tk 1276
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_R-1, ((ui_gp_leds ^ pos_marker_mask) >> 8) & 0xff);
134 tk 1277
#endif
1278
#endif
1279
 
1280
#ifdef DEFAULT_GP_DOUT_SR_L2
1281
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_L2-1, (pos_marker_mask >> 0) & 0xff);
1282
#endif
1283
#ifdef DEFAULT_GP_DOUT_SR_R2
1284
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_R2-1, (pos_marker_mask >> 8) & 0xff);
1285
#endif
1286
 
1287
#if DEFAULT_SRM_ENABLED && DEFAULT_SRM_DOUT_M_MAPPING == 1
1288
  // for wilba's frontpanel
1289
 
1290
  // BLM8X8 DOUT -> GP LED mapping
1291
  // 0 = 15,16  1 = 13,14   2 = 11,12   3 = 9,10
1292
  // 4 = 1,2    5 = 3,4     6 = 5,6     7 = 7,8
1293
 
1294
  // bit 7: first green (i.e. GP1-G)
1295
  // bit 6: first red (i.e. GP1-R)
1296
  // bit 5: second green (i.e. GP2-G)
1297
  // bit 4: second red (i.e. GP2-R)
1298
 
1299
  // this mapping routine takes ca. 5 uS
173 tk 1300
  // since it's only executed when ui_gp_leds or gp_mask has changed, it doesn't really hurt
134 tk 1301
 
173 tk 1302
  u16 modified_gp_leds = ui_gp_leds;
134 tk 1303
#if 1
1304
  // extra: red LED is lit exclusively for higher contrast
1305
  modified_gp_leds &= ~pos_marker_mask;
1306
#endif
1307
 
1308
  int sr;
1309
  const u8 blm8x8_sr_map[8] = {4, 5, 6, 7, 3, 2, 1, 0};
1310
  u16 gp_mask = 1 << 0;
1311
  for(sr=0; sr<8; ++sr) {
1312
    u8 pattern = 0;
1313
 
1314
    if( modified_gp_leds & gp_mask )
1315
      pattern |= 0x80;
1316
    if( pos_marker_mask & gp_mask )
1317
      pattern |= 0x40;
1318
    gp_mask <<= 1;
1319
    if( modified_gp_leds & gp_mask )
1320
      pattern |= 0x20;
1321
    if( pos_marker_mask & gp_mask )
1322
      pattern |= 0x10;
1323
    gp_mask <<= 1;
1324
 
1325
    u8 mapped_sr = blm8x8_sr_map[sr];
1326
    blm8x8_led_row[mapped_sr] = (blm8x8_led_row[mapped_sr] & 0x0f) | pattern;
1327
  }
1328
#endif
1329
 
184 tk 1330
  return 0; // no error
134 tk 1331
}
1332
 
1333
 
1334
/////////////////////////////////////////////////////////////////////////////
168 tk 1335
// for menu handling (e.g. flashing cursor, doubleclick counter, etc...)
1336
// called each mS
1337
/////////////////////////////////////////////////////////////////////////////
1338
s32 SEQ_UI_MENU_Handler_Periodic()
1339
{
1340
  if( ++ui_cursor_flash_ctr >= SEQ_UI_CURSOR_FLASH_CTR_MAX ) {
1341
    ui_cursor_flash_ctr = 0;
1342
    seq_ui_display_update_req = 1;
173 tk 1343
  } else if( ui_cursor_flash_ctr == SEQ_UI_CURSOR_FLASH_CTR_LED_OFF ) {
168 tk 1344
    seq_ui_display_update_req = 1;
173 tk 1345
  }
1346
  // important: flash flag has to be recalculated on each invocation of this
1347
  // handler, since counter could also be reseted outside this function
1348
  ui_cursor_flash = ui_cursor_flash_ctr >= SEQ_UI_CURSOR_FLASH_CTR_LED_OFF;
168 tk 1349
 
184 tk 1350
 
240 tk 1351
  // used in some pages for temporary messages
1352
  if( ui_hold_msg_ctr )
1353
    --ui_hold_msg_ctr;
1354
 
299 tk 1355
  // used for temporary SD Card messages
1356
  if( sdcard_msg_ctr )
1357
    --sdcard_msg_ctr;
1358
 
184 tk 1359
  // VU meters (used in MUTE menu, could also be available as LED matrix...)
1360
  static u8 vu_meter_prediv = 0; // predivider for VU meters
1361
 
1362
  if( ++vu_meter_prediv >= 4 ) {
1363
    vu_meter_prediv = 0;
1364
 
1365
    u8 track;
1366
    seq_core_trk_t *t = &seq_core_trk[0];
318 tk 1367
    portENTER_CRITICAL();
184 tk 1368
    for(track=0; track<SEQ_CORE_NUM_TRACKS; ++t, ++track)
1369
      if( t->vu_meter )
1370
    --t->vu_meter;
318 tk 1371
    portEXIT_CRITICAL();
184 tk 1372
  }
1373
 
168 tk 1374
  return 0;
1375
}
1376
 
1377
 
1378
/////////////////////////////////////////////////////////////////////////////
328 tk 1379
// Should be regulary called to check if the layer/instrument/step selection
1380
// is valid for the current track
1381
// At least executed before button/encoder and LCD function calls
1382
/////////////////////////////////////////////////////////////////////////////
1383
s32 SEQ_UI_CheckSelections(void)
1384
{
1385
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1386
 
1387
  if( ui_selected_instrument >= SEQ_PAR_NumInstrumentsGet(visible_track) )
1388
    ui_selected_instrument = 0;
1389
 
1390
  if( ui_selected_par_layer >= SEQ_PAR_NumLayersGet(visible_track) )
1391
    ui_selected_par_layer = 0;
1392
 
1393
  if( ui_selected_trg_layer >= SEQ_TRG_NumLayersGet(visible_track) )
1394
    ui_selected_trg_layer = 0;
1395
 
1396
  if( ui_selected_step >= SEQ_TRG_NumStepsGet(visible_track) )
1397
    ui_selected_step = 0;
1398
 
1399
  if( ui_selected_step_view >= (SEQ_TRG_NumStepsGet(visible_track)/16) ) {
1400
    ui_selected_step_view = 0;
1401
    ui_selected_step %= 16;
1402
  }
1403
 
1404
  if( ui_selected_step >= ui_selected_step_view*16 )
1405
    ui_selected_step_view = ui_selected_step / 16;
1406
 
1407
  return 0; // no error
1408
}
1409
 
1410
 
1411
/////////////////////////////////////////////////////////////////////////////
134 tk 1412
// Returns the currently visible track
1413
/////////////////////////////////////////////////////////////////////////////
1414
u8 SEQ_UI_VisibleTrackGet(void)
1415
{
1416
  u8 offset = 0;
1417
 
1418
  if( ui_selected_tracks & (1 << 3) )
1419
    offset = 3;
1420
  if( ui_selected_tracks & (1 << 2) )
1421
    offset = 2;
1422
  if( ui_selected_tracks & (1 << 1) )
1423
    offset = 1;
1424
  if( ui_selected_tracks & (1 << 0) )
1425
    offset = 0;
1426
 
1427
  return 4*ui_selected_group + offset;
1428
}
1429
 
168 tk 1430
 
1431
/////////////////////////////////////////////////////////////////////////////
178 tk 1432
// Returns 1 if 'track' is selected
1433
/////////////////////////////////////////////////////////////////////////////
1434
s32 SEQ_UI_IsSelectedTrack(u8 track)
1435
{
1436
  if( (track>>2) != ui_selected_group )
1437
    return 0;
1438
  return (ui_selected_tracks & (1 << (track&3))) ? 1 : 0;
1439
}
1440
 
1441
 
1442
/////////////////////////////////////////////////////////////////////////////
240 tk 1443
// Sets a new selected step and updates the step view
1444
/////////////////////////////////////////////////////////////////////////////
1445
s32 SEQ_UI_SelectedStepSet(u8 step)
1446
{
1447
  ui_selected_step = step;
328 tk 1448
  SEQ_UI_CheckSelections();
1449
 
240 tk 1450
  return 0; // no error
1451
}
1452
 
1453
 
1454
/////////////////////////////////////////////////////////////////////////////
168 tk 1455
// Increments the selected tracks/groups
1456
// OUT: 1 if value has been changed, otherwise 0
1457
/////////////////////////////////////////////////////////////////////////////
1458
s32 SEQ_UI_GxTyInc(s32 incrementer)
1459
{
1460
  int gxty = SEQ_UI_VisibleTrackGet();
1461
  int prev_gxty = gxty;
1462
 
1463
  if( incrementer >= 0 ) {
1464
    if( (gxty += incrementer) >= SEQ_CORE_NUM_TRACKS )
1465
      gxty = SEQ_CORE_NUM_TRACKS-1;
1466
  } else {
1467
    if( (gxty += incrementer) < 0 )
1468
      gxty = 0;
1469
  }
1470
 
1471
  if( gxty == prev_gxty )
1472
    return 0; // no change
1473
 
1474
  ui_selected_tracks = 1 << (gxty % 4);
1475
  ui_selected_group = gxty / 4;
1476
 
1477
  return 1; // value changed
1478
}
1479
 
1480
 
1481
/////////////////////////////////////////////////////////////////////////////
236 tk 1482
// Increments a 16bit variable within given min/max range
1483
// OUT: 1 if value has been changed, otherwise 0
1484
/////////////////////////////////////////////////////////////////////////////
240 tk 1485
s32 SEQ_UI_Var16_Inc(u16 *value, u16 min, u16 max, s32 incrementer)
236 tk 1486
{
1487
  int new_value = *value;
1488
  int prev_value = new_value;
1489
 
1490
  if( incrementer >= 0 ) {
1491
    if( (new_value += incrementer) >= max )
1492
      new_value = max;
1493
  } else {
1494
    if( (new_value += incrementer) < min )
1495
      new_value = min;
1496
  }
1497
 
1498
  if( new_value == prev_value )
1499
    return 0; // no change
1500
 
1501
  *value = new_value;
1502
 
1503
  return 1; // value changed
1504
}
1505
 
240 tk 1506
/////////////////////////////////////////////////////////////////////////////
1507
// Increments an 8bit variable within given min/max range
1508
// OUT: 1 if value has been changed, otherwise 0
1509
/////////////////////////////////////////////////////////////////////////////
1510
s32 SEQ_UI_Var8_Inc(u8 *value, u16 min, u16 max, s32 incrementer)
1511
{
1512
  u16 tmp = *value;
1513
  if( SEQ_UI_Var16_Inc(&tmp, min, max, incrementer) ) {
1514
    *value = tmp;
1515
    return 1; // value changed
1516
  }
236 tk 1517
 
240 tk 1518
  return 0; // value hasn't been changed
1519
}
1520
 
1521
 
236 tk 1522
/////////////////////////////////////////////////////////////////////////////
168 tk 1523
// Increments a CC within given min/max range
1524
// OUT: 1 if value has been changed, otherwise 0
1525
/////////////////////////////////////////////////////////////////////////////
248 tk 1526
s32 SEQ_UI_CC_Inc(u8 cc, u8 min, u8 max, s32 incrementer)
168 tk 1527
{
1528
  u8 visible_track = SEQ_UI_VisibleTrackGet();
173 tk 1529
  int new_value = SEQ_CC_Get(visible_track, cc);
1530
  int prev_value = new_value;
168 tk 1531
 
1532
  if( incrementer >= 0 ) {
173 tk 1533
    if( (new_value += incrementer) >= max )
1534
      new_value = max;
168 tk 1535
  } else {
173 tk 1536
    if( (new_value += incrementer) < min )
1537
      new_value = min;
168 tk 1538
  }
1539
 
173 tk 1540
  if( new_value == prev_value )
168 tk 1541
    return 0; // no change
1542
 
173 tk 1543
  SEQ_CC_Set(visible_track, cc, new_value);
168 tk 1544
 
179 tk 1545
  // set same value for all selected tracks
1546
  u8 track;
1547
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
1548
    if( track != visible_track && SEQ_UI_IsSelectedTrack(track) )
1549
      SEQ_CC_Set(track, cc, new_value);
1550
 
168 tk 1551
  return 1; // value changed
1552
}
1553
 
173 tk 1554
 
1555
/////////////////////////////////////////////////////////////////////////////
179 tk 1556
// Sets a CC value on all selected tracks
1557
// OUT: 1 if value has been changed, otherwise 0
1558
/////////////////////////////////////////////////////////////////////////////
248 tk 1559
s32 SEQ_UI_CC_Set(u8 cc, u8 value)
179 tk 1560
{
1561
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1562
  int prev_value = SEQ_CC_Get(visible_track, cc);
1563
 
1564
  if( value == prev_value )
1565
    return 0; // no change
1566
 
1567
  SEQ_CC_Set(visible_track, cc, value);
1568
 
1569
  // set same value for all selected tracks
1570
  u8 track;
1571
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
1572
    if( track != visible_track && SEQ_UI_IsSelectedTrack(track) )
1573
      SEQ_CC_Set(track, cc, value);
1574
 
1575
  return 1; // value changed
1576
}
1577
 
1578
/////////////////////////////////////////////////////////////////////////////
173 tk 1579
// Modifies a bitfield in a CC value to a given value
1580
// OUT: 1 if value has been changed, otherwise 0
1581
/////////////////////////////////////////////////////////////////////////////
248 tk 1582
s32 SEQ_UI_CC_SetFlags(u8 cc, u8 flag_mask, u8 value)
173 tk 1583
{
1584
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1585
  int new_value = SEQ_CC_Get(visible_track, cc);
1586
  int prev_value = new_value;
1587
 
1588
  new_value = (new_value & ~flag_mask) | value;
1589
 
1590
  if( new_value == prev_value )
1591
    return 0; // no change
1592
 
1593
  SEQ_CC_Set(visible_track, cc, new_value);
1594
 
179 tk 1595
  // do same modification for all selected tracks
1596
  u8 track;
1597
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
1598
    if( track != visible_track && SEQ_UI_IsSelectedTrack(track) ) {
1599
      int new_value = SEQ_CC_Get(track, cc);
1600
      new_value = (new_value & ~flag_mask) | value;
1601
      SEQ_CC_Set(track, cc, new_value);
1602
    }
1603
 
173 tk 1604
  return 1; // value changed
1605
}
1606
 
1607
 
299 tk 1608
/////////////////////////////////////////////////////////////////////////////
1609
// Print temporary messages after file operations
1610
// expects mS delay and two lines, each up to 20 characters
1611
/////////////////////////////////////////////////////////////////////////////
1612
s32 SEQ_UI_SDCardMsg(u16 delay, char *line1, char *line2)
1613
{
1614
  sdcard_msg_ctr = delay;
1615
  strncpy((char *)sdcard_msg[0], line1, SDCARD_MSG_MAX_CHAR);
1616
  strncpy((char *)sdcard_msg[1], line2, SDCARD_MSG_MAX_CHAR);
1617
 
1618
  return 0; // no error
1619
}
1620
 
1621
/////////////////////////////////////////////////////////////////////////////
1622
// Prints a temporary error messages after file operation
1623
// Expects error status number (as defined in seq_file.h)
1624
/////////////////////////////////////////////////////////////////////////////
1625
s32 SEQ_UI_SDCardErrMsg(u16 delay, s32 status)
1626
{
1627
  // TODO: add more verbose error messages, they are clearly defined in seq_file.h)
1628
  char str[21];
1629
  sprintf(str, "E%3d (DOSFS: D%3d)", -status, seq_file_dfs_errno < 1000 ? seq_file_dfs_errno : 999);
1630
  return SEQ_UI_SDCardMsg(delay, "!! SD Card Error !!!", str);
1631
}