Subversion Repositories svn.mios32

Rev

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