Subversion Repositories svn.mios32

Rev

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