Subversion Repositories svn.mios32

Rev

Rev 1142 | Rev 1493 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
399 tk 1
// $Id: seq_ui_song.c 1421 2012-02-11 23:44:23Z tk $
2
/*
3
 * Song page
4
 *
5
 * ==========================================================================
6
 *
7
 *  Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
8
 *  Licensed for personal non-commercial use only.
9
 *  All other rights reserved.
10
 *
11
 * ==========================================================================
12
 */
13
 
14
/////////////////////////////////////////////////////////////////////////////
15
// Include files
16
/////////////////////////////////////////////////////////////////////////////
17
 
18
#include <mios32.h>
19
#include <string.h>
690 tk 20
#include <seq_bpm.h>
21
 
399 tk 22
#include "seq_lcd.h"
23
#include "seq_ui.h"
24
#include "seq_core.h"
25
#include "seq_song.h"
26
#include "seq_pattern.h"
740 tk 27
#include "seq_file.h"
399 tk 28
#include "seq_file_b.h"
29
#include "seq_file_m.h"
30
 
31
 
32
/////////////////////////////////////////////////////////////////////////////
33
// Local definitions
34
/////////////////////////////////////////////////////////////////////////////
35
 
36
// Note/Chord/CC
37
#define NUM_OF_ITEMS        8
38
#define ITEM_SONG           0
39
#define ITEM_POS            1
40
#define ITEM_ACTION         2
41
#define ITEM_G1             3
42
#define ITEM_G2             4
43
#define ITEM_G3             5
44
#define ITEM_G4             6
45
#define ITEM_SEL_BANK       7
729 tk 46
#define ITEM_MODE           8
399 tk 47
 
48
 
729 tk 49
// used "In-Menu" messages
50
#define MSG_DEFAULT 0x00
51
#define MSG_COPY    0x81
52
#define MSG_PASTE   0x82
53
#define MSG_CLEAR   0x83
54
#define MSG_INSERT  0x84
55
#define MSG_DELETE  0x85
56
 
57
 
399 tk 58
/////////////////////////////////////////////////////////////////////////////
59
// Local variables
60
/////////////////////////////////////////////////////////////////////////////
61
 
62
static u8 sel_bank;
63
 
729 tk 64
static u8 show_song_util_page;
399 tk 65
 
729 tk 66
static u8 in_menu_msg;
67
 
68
static const char in_menu_msg_str[6][9] = {
69
  ">COPIED<",   // #1
70
  ">PASTED<",   // #2
71
  "CLEARED!",   // #3
72
  "INSERTED",   // #4
73
  " DELETED",   // #5
74
};
75
 
76
 
77
static u8 copypaste_buffer_filled = 0;
78
static seq_song_step_t copypaste_buffer;
79
 
80
 
399 tk 81
/////////////////////////////////////////////////////////////////////////////
82
// Local Prototypes
83
/////////////////////////////////////////////////////////////////////////////
84
 
729 tk 85
static s32 Button_Handler(seq_ui_button_t button, s32 depressed);
1421 tk 86
static s32 checkChangePattern(u8 group, u8 bank, u8 pattern);
87
static s32 takeoverCurrentPatterns(void);
399 tk 88
 
89
 
90
/////////////////////////////////////////////////////////////////////////////
91
// Local LED handler function
92
/////////////////////////////////////////////////////////////////////////////
93
static s32 LED_Handler(u16 *gp_leds)
94
{
740 tk 95
  if( SEQ_FILE_FormattingRequired() )
1044 tk 96
    return 0; // no LED action as long as files not available
740 tk 97
 
399 tk 98
  if( ui_cursor_flash ) // if flashing flag active: no LED flag set
99
    return 0;
100
 
1421 tk 101
  seq_song_step_t s = SEQ_SONG_StepEntryGet(ui_song_edit_pos);
401 tk 102
 
399 tk 103
  switch( ui_selected_item ) {
401 tk 104
    case ITEM_SONG:
105
      *gp_leds = 0x0001;
106
      break;
107
 
108
    case ITEM_POS:
1421 tk 109
      *gp_leds = 1 << ((ui_song_edit_pos>>3)&0xf);
401 tk 110
      break;
111
 
112
    case ITEM_ACTION:
729 tk 113
      if( show_song_util_page ) break;
401 tk 114
      *gp_leds = 0x0004;
115
      break;
116
 
117
    case ITEM_G1:
118
    case ITEM_G2:
119
    case ITEM_G3:
120
    case ITEM_G4: {
729 tk 121
      if( show_song_util_page ) break;
401 tk 122
      switch( s.action ) {
1421 tk 123
        case SEQ_SONG_ACTION_End:
401 tk 124
      *gp_leds = 1 << ui_selected_item;
125
      break;
126
 
127
        case SEQ_SONG_ACTION_JmpPos:
128
        case SEQ_SONG_ACTION_JmpSong:
129
        case SEQ_SONG_ACTION_SelMixerMap: {
130
      u8 val = (u8)s.action_value;
131
      *gp_leds = (1 << ((val>>3)&7)) | (0x100 << (val&7));
132
    } break;
133
 
592 tk 134
        case SEQ_SONG_ACTION_Tempo: {
135
      *gp_leds = 0x0000; // how to handle this?
136
      break;
137
    }
138
 
139
        case SEQ_SONG_ACTION_Mutes: {
140
      *gp_leds = ((s.pattern_g4&0xf) << 12) | ((s.pattern_g3&0xf) << 8) | ((s.pattern_g2&0xf) << 4) | (s.pattern_g1&0xf);
141
    } break;
142
 
401 tk 143
        default:
144
      if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 ) {
145
        *gp_leds = 1 << ui_selected_item;
146
      } else {
147
        if( sel_bank ) {
148
          u8 val_bank;
149
          switch( ui_selected_item - ITEM_G1 ) {
150
            case 0: val_bank = s.bank_g1; break;
151
            case 1: val_bank = s.bank_g2; break;
152
            case 2: val_bank = s.bank_g3; break;
153
            case 3: val_bank = s.bank_g4; break;
154
            default: return 0; // invalid bank selection
155
          }
156
          *gp_leds = 1 << val_bank;
157
        } else {
158
          u8 val_pattern;
159
          switch( ui_selected_item - ITEM_G1 ) {
160
            case 0: val_pattern = s.pattern_g1; break;
161
            case 1: val_pattern = s.pattern_g2; break;
162
            case 2: val_pattern = s.pattern_g3; break;
163
            case 3: val_pattern = s.pattern_g4; break;
164
            default: return 0; // invalid bank selection
165
          }
166
          *gp_leds = (1 << ((val_pattern>>3)&7)) | (0x100 << (val_pattern&7));
167
        }
168
      }
169
      }
170
    } break;
171
 
172
    case ITEM_SEL_BANK:
729 tk 173
      if( show_song_util_page ) break;
401 tk 174
      *gp_leds = 0x0080;
175
      break;
729 tk 176
 
177
    case ITEM_MODE:
178
      *gp_leds = 0x0300;
179
      break;
399 tk 180
  }
181
 
182
  return 0; // no error
183
}
184
 
185
 
186
/////////////////////////////////////////////////////////////////////////////
187
// Local encoder callback function
188
// Should return:
189
//   1 if value has been changed
190
//   0 if value hasn't been changed
191
//  -1 if invalid or unsupported encoder
192
/////////////////////////////////////////////////////////////////////////////
193
static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer)
194
{
740 tk 195
  if( SEQ_FILE_FormattingRequired() )
1044 tk 196
    return 0; // no encoder action as long as files not available
740 tk 197
 
1421 tk 198
  seq_song_step_t s = SEQ_SONG_StepEntryGet(ui_song_edit_pos);
399 tk 199
 
200
  switch( encoder ) {
201
    case SEQ_UI_ENCODER_GP1:
202
      ui_selected_item = ITEM_SONG;
203
      break;
204
 
205
    case SEQ_UI_ENCODER_GP2:
206
      ui_selected_item = ITEM_POS;
207
      break;
208
 
209
    case SEQ_UI_ENCODER_GP3:
729 tk 210
      if( show_song_util_page ) // -> forward to button function
211
    return Button_Handler((seq_ui_button_t)encoder, 1);
212
 
399 tk 213
      ui_selected_item = ITEM_ACTION;
214
      break;
215
 
216
    case SEQ_UI_ENCODER_GP4:
729 tk 217
      if( show_song_util_page ) // -> forward to button function
218
    return Button_Handler((seq_ui_button_t)encoder, 1);
219
 
399 tk 220
      ui_selected_item = ITEM_G1;
221
      break;
222
 
223
    case SEQ_UI_ENCODER_GP5:
729 tk 224
      if( show_song_util_page ) // -> forward to button function
225
    return Button_Handler((seq_ui_button_t)encoder, 1);
226
 
399 tk 227
      ui_selected_item = ITEM_G2;
228
      break;
229
 
230
    case SEQ_UI_ENCODER_GP6:
729 tk 231
      if( show_song_util_page ) // -> forward to button function
232
    return Button_Handler((seq_ui_button_t)encoder, 1);
233
 
399 tk 234
      ui_selected_item = ITEM_G3;
235
      break;
236
 
237
    case SEQ_UI_ENCODER_GP7:
729 tk 238
      if( show_song_util_page ) // -> forward to button function
239
    return Button_Handler((seq_ui_button_t)encoder, 1);
240
 
399 tk 241
      ui_selected_item = ITEM_G4;
242
      break;
243
 
244
    case SEQ_UI_ENCODER_GP8:
729 tk 245
      if( show_song_util_page ) // -> forward to button function
246
    return Button_Handler((seq_ui_button_t)encoder, 1);
247
 
399 tk 248
      ui_selected_item = ITEM_SEL_BANK;
249
      break;
250
 
251
    case SEQ_UI_ENCODER_GP9:
252
    case SEQ_UI_ENCODER_GP10:
729 tk 253
      ui_selected_item = ITEM_MODE;
254
      break;
255
 
399 tk 256
    case SEQ_UI_ENCODER_GP11:
257
    case SEQ_UI_ENCODER_GP12:
258
    case SEQ_UI_ENCODER_GP13:
259
    case SEQ_UI_ENCODER_GP14:
260
    case SEQ_UI_ENCODER_GP15:
261
    case SEQ_UI_ENCODER_GP16:
262
      return -1; // not mapped to encoder
263
  }
264
 
265
  // for GP encoders and Datawheel
266
  switch( ui_selected_item ) {
267
    case ITEM_SONG: {
268
      u8 song_num = SEQ_SONG_NumGet();
269
      u8 old_song_num = song_num;
270
      if( SEQ_UI_Var8_Inc(&song_num, 0, SEQ_SONG_NUM-1, incrementer) >= 0 ) {
271
    SEQ_SONG_Save(old_song_num);
272
    SEQ_SONG_Load(song_num);
273
    return 1; // value has been changed
274
      }
275
      return 0; // no change
276
    } break;
277
 
278
    case ITEM_POS:
1421 tk 279
      return SEQ_UI_Var8_Inc(&ui_song_edit_pos, 0, SEQ_SONG_NUM_STEPS-1, incrementer);
399 tk 280
 
281
    case ITEM_ACTION: {
282
      u8 action = (u8)s.action;
283
      if( SEQ_UI_Var8_Inc(&action, 0, SEQ_SONG_NUM_ACTIONS-1, incrementer) >= 0 ) {
284
    s.action = action;
1421 tk 285
    SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
399 tk 286
    return 1; // value has been changed
287
      }
288
      return 0; // no change
289
    } break;
290
 
291
    case ITEM_G1:
292
    case ITEM_G2:
293
    case ITEM_G3:
294
    case ITEM_G4: {
295
      switch( s.action ) {
1421 tk 296
        case SEQ_SONG_ACTION_End:
399 tk 297
      return 0; // do nothing
298
 
299
        case SEQ_SONG_ACTION_JmpPos: {
300
      u8 val = (u8)s.action_value;
301
      if( SEQ_UI_Var8_Inc(&val, 0, SEQ_SONG_NUM_STEPS-1, incrementer) >= 0 ) {
302
        s.action_value = val;
1421 tk 303
        SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
399 tk 304
        return 1; // value has been changed
305
      }
306
      return 0; // no change
307
    }
308
 
309
        case SEQ_SONG_ACTION_JmpSong: {
310
      u8 val = (u8)s.action_value;
311
      if( SEQ_UI_Var8_Inc(&val, 0, SEQ_SONG_NUM-1, incrementer) >= 0 ) {
312
        s.action_value = val;
1421 tk 313
        SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
399 tk 314
        return 1; // value has been changed
315
      }
316
      return 0; // no change
317
    }
318
 
319
        case SEQ_SONG_ACTION_SelMixerMap: {
320
      u8 val = (u8)s.action_value;
321
      u8 num_mixer_maps = SEQ_FILE_M_NumMaps();
322
      if( !num_mixer_maps )
323
        num_mixer_maps = 128;
324
      if( SEQ_UI_Var8_Inc(&val, 0, num_mixer_maps-1, incrementer) >= 0 ) {
325
        s.action_value = val;
1421 tk 326
        SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
592 tk 327
 
328
        // in phrase mode and no song pos selected: fetch patterns immediately
329
        if( !SEQ_SONG_ActiveGet() )
1117 tk 330
          SEQ_SONG_FetchPos(0);
399 tk 331
        return 1; // value has been changed
332
      }
333
      return 0; // no change
334
    }
335
 
592 tk 336
        case SEQ_SONG_ACTION_Tempo: {
337
      if( ui_selected_item == ITEM_G1 || ui_selected_item == ITEM_G2 ) {
338
        // BPM
339
        u8 val = (u8)s.action_value;
340
        if( SEQ_UI_Var8_Inc(&val, 25, 255, incrementer) >= 0 ) {
341
          s.action_value = val;
1421 tk 342
          SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
592 tk 343
          // in phrase mode and no song pos selected: fetch patterns immediately
344
          if( !SEQ_SONG_ActiveGet() )
1117 tk 345
        SEQ_SONG_FetchPos(0);
592 tk 346
          return 1; // value has been changed
347
        }
348
      } else {
349
        // Ramp
350
        u8 val = (u8)s.pattern_g1;
351
        if( SEQ_UI_Var8_Inc(&val, 0, 255, incrementer) >= 0 ) {
352
          s.pattern_g1 = val;
1421 tk 353
          SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
592 tk 354
          // in phrase mode and no song pos selected: fetch patterns immediately
355
          if( !SEQ_SONG_ActiveGet() )
1117 tk 356
        SEQ_SONG_FetchPos(0);
592 tk 357
          return 1; // value has been changed
358
        }
359
      }
360
 
361
      return 0; // no change
362
    }
363
 
364
        case SEQ_SONG_ACTION_Mutes: {
365
      u8 val;
366
      switch( ui_selected_item ) {
367
        case ITEM_G1: val = (u8)s.pattern_g1 & 0xf; break;
368
        case ITEM_G2: val = (u8)s.pattern_g2 & 0xf; break;
369
        case ITEM_G3: val = (u8)s.pattern_g3 & 0xf; break;
370
        case ITEM_G4: val = (u8)s.pattern_g4 & 0xf; break;
371
        default: return 0; // not mapped
372
      }
373
 
374
      if( SEQ_UI_Var8_Inc(&val, 0, 15, incrementer) >= 0 ) {
375
        switch( ui_selected_item ) {
376
          case ITEM_G1: s.pattern_g1 = val; break;
377
          case ITEM_G2: s.pattern_g2 = val; break;
378
          case ITEM_G3: s.pattern_g3 = val; break;
379
          case ITEM_G4: s.pattern_g4 = val; break;
380
          default: return 0; // not mapped
381
        }
1421 tk 382
        SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
592 tk 383
        // in phrase mode and no song pos selected: fetch patterns immediately
384
        if( !SEQ_SONG_ActiveGet() )
1117 tk 385
          SEQ_SONG_FetchPos(0);
592 tk 386
        return 1; // value has been changed
387
      }
388
      return 0; // no change
389
    }
390
 
399 tk 391
        default:
392
      if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 )
393
        return 0; // no change
394
      else {
395
        u8 val_bank;
396
        switch( ui_selected_item - ITEM_G1 ) {
397
          case 0: val_bank = s.bank_g1; break;
398
          case 1: val_bank = s.bank_g2; break;
399
          case 2: val_bank = s.bank_g3; break;
400
          case 3: val_bank = s.bank_g4; break;
401
          default: return 0; // invalid bank selection
402
        }
403
 
404
        u8 val_pattern;
405
        switch( ui_selected_item - ITEM_G1 ) {
406
          case 0: val_pattern = s.pattern_g1; break;
407
          case 1: val_pattern = s.pattern_g2; break;
408
          case 2: val_pattern = s.pattern_g3; break;
409
          case 3: val_pattern = s.pattern_g4; break;
410
          default: return 0; // invalid bank selection
411
        }
412
 
413
        if( sel_bank ) {
414
          if( SEQ_UI_Var8_Inc(&val_bank, 0, SEQ_FILE_B_NUM_BANKS-1, incrementer) >= 0 ) {
415
        switch( ui_selected_item - ITEM_G1 ) {
416
          case 0: s.bank_g1 = val_bank; break;
417
          case 1: s.bank_g2 = val_bank; break;
418
          case 2: s.bank_g3 = val_bank; break;
419
          case 3: s.bank_g4 = val_bank; break;
420
              default: return 0; // invalid bank selection
421
        }
1421 tk 422
        SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
423
        checkChangePattern(ui_selected_item - ITEM_G1, val_bank, val_pattern);
399 tk 424
        return 1; // value has been changed
425
          }
426
        } else {
427
          u8 num_patterns = SEQ_FILE_B_NumPatterns(val_bank);
428
          if( !num_patterns )
429
        num_patterns = 64;
430
          // move 0x80 (disable pattern) to the beginning of pattern selection for more comfortable editing
431
          u8 val_pattern_converted = (val_pattern >= 0x80) ? 0 : (val_pattern+1);
432
          if( SEQ_UI_Var8_Inc(&val_pattern_converted, 0, num_patterns, incrementer) >= 0 ) {
433
        val_pattern = (val_pattern_converted == 0) ? 0x80 : (val_pattern_converted-1);
434
        switch( ui_selected_item - ITEM_G1 ) {
435
          case 0: s.pattern_g1 = val_pattern; break;
436
          case 1: s.pattern_g2 = val_pattern; break;
437
          case 2: s.pattern_g3 = val_pattern; break;
438
          case 3: s.pattern_g4 = val_pattern; break;
439
              default: return 0; // invalid bank selection
440
        }
1421 tk 441
        SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
442
        checkChangePattern(ui_selected_item - ITEM_G1, val_bank, val_pattern);
399 tk 443
        return 1; // value has been changed
444
          }
445
        }
446
        return 0; // no change
447
      }
448
      }
449
    } break;
450
 
451
    case ITEM_SEL_BANK:
452
      if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 )
453
    return 0; // no change
454
 
455
      if( incrementer > 0 )
456
    sel_bank = 1;
457
      else if( incrementer < 0 )
458
    sel_bank = 0;
459
      else
460
    return 0; // no change
461
      return 1; // value has been changed
729 tk 462
 
463
    case ITEM_MODE:
464
      SEQ_SONG_ActiveSet((incrementer > 0) ? 1 : 0);
465
      return 1; // value has been changed
399 tk 466
  }
467
 
468
  return -1; // invalid or unsupported encoder
469
}
470
 
471
 
472
/////////////////////////////////////////////////////////////////////////////
473
// Local button callback function
474
// Should return:
475
//   1 if value has been changed
476
//   0 if value hasn't been changed
477
//  -1 if invalid or unsupported button
478
/////////////////////////////////////////////////////////////////////////////
479
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
480
{
740 tk 481
  if( SEQ_FILE_FormattingRequired() )
1044 tk 482
    return 0; // no button action as long as files not available
740 tk 483
 
401 tk 484
  // special mapping of GP buttons depending on ui_selected_item
485
#if 0
486
  // leads to: comparison is always true due to limited range of data type
487
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
488
#else
489
  if( button <= SEQ_UI_BUTTON_GP16 ) {
490
#endif
729 tk 491
    if( depressed ) return 0; // ignore when button depressed
401 tk 492
 
729 tk 493
    if( show_song_util_page ) {
494
      if( depressed ) return 0; // ignore when button depressed
401 tk 495
 
729 tk 496
      switch( button ) {
497
        case SEQ_UI_BUTTON_GP1:
498
          ui_selected_item = ITEM_SONG;
499
          return 1;
401 tk 500
 
729 tk 501
        case SEQ_UI_BUTTON_GP2:
502
          ui_selected_item = ITEM_POS;
503
          return 1;
401 tk 504
 
729 tk 505
        case SEQ_UI_BUTTON_GP3: // Copy
506
      // copy position
507
      SEQ_UI_SONG_Copy();
508
      // print message
509
      in_menu_msg = MSG_COPY & 0x7f;
510
      ui_hold_msg_ctr = 1000;
511
      return 1;
401 tk 512
 
729 tk 513
        case SEQ_UI_BUTTON_GP4: // Paste
514
      // paste position
515
      SEQ_UI_SONG_Paste();
516
      // print message
517
      in_menu_msg = MSG_PASTE & 0x7f;
518
      ui_hold_msg_ctr = 1000;
519
      return 1;
401 tk 520
 
729 tk 521
        case SEQ_UI_BUTTON_GP5: // Clear
522
      // clear position
523
      SEQ_UI_SONG_Clear();
524
      // print message
525
      in_menu_msg = MSG_CLEAR & 0x7f;
526
      ui_hold_msg_ctr = 1000;
527
      return 1;
592 tk 528
 
729 tk 529
        case SEQ_UI_BUTTON_GP6: // Insert
530
      // insert position
531
      SEQ_UI_SONG_Insert();
532
      // print message
533
      in_menu_msg = MSG_INSERT & 0x7f;
534
      ui_hold_msg_ctr = 1000;
535
      return 1;
592 tk 536
 
729 tk 537
        case SEQ_UI_BUTTON_GP7: // Delete
538
      // delete position
539
      SEQ_UI_SONG_Delete();
540
      // print message
541
      in_menu_msg = MSG_DELETE & 0x7f;
542
      ui_hold_msg_ctr = 1000;
543
      return 1;
592 tk 544
 
729 tk 545
        case SEQ_UI_BUTTON_GP8:
546
      return -1; // not used
592 tk 547
 
729 tk 548
        case SEQ_UI_BUTTON_GP9:
549
        case SEQ_UI_BUTTON_GP10:
550
          ui_selected_item = ITEM_MODE;
551
      SEQ_SONG_ActiveSet(SEQ_SONG_ActiveGet() ? 0 : 1);
552
          return 1;
1421 tk 553
 
554
        case SEQ_UI_BUTTON_GP13:
555
        case SEQ_UI_BUTTON_GP14:
556
        case SEQ_UI_BUTTON_GP15:
557
        case SEQ_UI_BUTTON_GP16:
558
          takeoverCurrentPatterns();
559
          return 1;
729 tk 560
      }
401 tk 561
 
729 tk 562
      return -1; // not used
563
    } else {
1421 tk 564
      seq_song_step_t s = SEQ_SONG_StepEntryGet(ui_song_edit_pos);
401 tk 565
 
729 tk 566
      switch( ui_selected_item ) {
567
        case ITEM_POS:
1421 tk 568
      ui_song_edit_pos = (u8)button << 3;
729 tk 569
 
1421 tk 570
      // set song position and fetch patterns
571
      SEQ_SONG_PosSet(ui_song_edit_pos);
572
      SEQ_SONG_FetchPos(0);
573
      ui_song_edit_pos = SEQ_SONG_PosGet();
758 tk 574
      return 1;
729 tk 575
 
576
        case ITEM_G1:
577
        case ITEM_G2:
578
        case ITEM_G3:
579
        case ITEM_G4: {
758 tk 580
      switch( s.action ) {
1421 tk 581
        case SEQ_SONG_ACTION_End:
758 tk 582
          return 0; // do nothing
729 tk 583
 
758 tk 584
            case SEQ_SONG_ACTION_JmpPos:
585
        case SEQ_SONG_ACTION_JmpSong:
586
        case SEQ_SONG_ACTION_SelMixerMap:
587
          if( button <= SEQ_UI_BUTTON_GP8 )
588
        s.action_value = (s.action_value & 0x07) | ((u8)button << 3);
589
          else
590
        s.action_value = (s.action_value & 0xf8) | ((u8)button & 0x7);
1421 tk 591
          SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
758 tk 592
 
593
          // in phrase mode and no song pos selected: fetch patterns immediately
594
          if( !SEQ_SONG_ActiveGet() && s.action != SEQ_SONG_ACTION_JmpSong )
1117 tk 595
        SEQ_SONG_FetchPos(0);
758 tk 596
          return 1; // value has been changed
597
 
598
        case SEQ_SONG_ACTION_Tempo:
599
          s.action_value = 75 + 5*button;
1421 tk 600
          SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
729 tk 601
 
758 tk 602
          // in phrase mode and no song pos selected: fetch patterns immediately
603
          if( !SEQ_SONG_ActiveGet() )
1117 tk 604
        SEQ_SONG_FetchPos(0);
758 tk 605
          return 1; // value has been changed
606
 
607
        case SEQ_SONG_ACTION_Mutes:
608
          if( button <= SEQ_UI_BUTTON_GP4 )
609
        s.pattern_g1 = (s.pattern_g1 & 0x0f) ^ (1 << (button&3));
610
          else if( button <= SEQ_UI_BUTTON_GP8 )
611
        s.pattern_g2 = (s.pattern_g2 & 0x0f) ^ (1 << (button&3));
612
          else if( button <= SEQ_UI_BUTTON_GP12 )
613
        s.pattern_g3 = (s.pattern_g3 & 0x0f) ^ (1 << (button&3));
614
          else if( button <= SEQ_UI_BUTTON_GP16 )
615
        s.pattern_g4 = (s.pattern_g4 & 0x0f) ^ (1 << (button&3));
616
          else
617
        return 0; // never reached...
1421 tk 618
          SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
729 tk 619
 
758 tk 620
          // in phrase mode and no song pos selected: fetch patterns immediately
621
          if( !SEQ_SONG_ActiveGet() )
1117 tk 622
        SEQ_SONG_FetchPos(1);
758 tk 623
          return 1; // value has been changed
729 tk 624
 
758 tk 625
        default:
626
          if( s.action >= SEQ_SONG_ACTION_Loop1 && s.action <= SEQ_SONG_ACTION_Loop16 ) {
627
        u8 val_bank;
628
        switch( ui_selected_item - ITEM_G1 ) {
629
          case 0: val_bank = s.bank_g1; break;
630
                  case 1: val_bank = s.bank_g2; break;
631
              case 2: val_bank = s.bank_g3; break;
632
              case 3: val_bank = s.bank_g4; break;
633
              default: return 0; // invalid bank selection
634
            }
729 tk 635
 
758 tk 636
        u8 val_pattern;
637
        switch( ui_selected_item - ITEM_G1 ) {
638
              case 0: val_pattern = s.pattern_g1; break;
639
              case 1: val_pattern = s.pattern_g2; break;
640
              case 2: val_pattern = s.pattern_g3; break;
641
              case 3: val_pattern = s.pattern_g4; break;
642
              default: return 0; // invalid bank selection
643
        }
729 tk 644
 
758 tk 645
        if( sel_bank ) {
646
          if( button <= SEQ_UI_BUTTON_GP8 ) {
647
            val_bank = (u8)button;
648
            switch( ui_selected_item - ITEM_G1 ) {
649
              case 0: s.bank_g1 = val_bank; break;
650
              case 1: s.bank_g2 = val_bank; break;
651
              case 2: s.bank_g3 = val_bank; break;
652
              case 3: s.bank_g4 = val_bank; break;
653
                      default: return 0; // invalid bank selection
654
            }
1421 tk 655
            SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
656
            checkChangePattern(ui_selected_item - ITEM_G1, val_bank, val_pattern);
758 tk 657
          }
658
          return 1; // value has been changed
659
        } else {
660
          if( button <= SEQ_UI_BUTTON_GP8 )
661
            val_pattern = (val_pattern & 0x07) | ((u8)button << 3);
662
          else
987 tk 663
            val_pattern = (val_pattern & 0x38) | ((u8)button & 0x7);
758 tk 664
          switch( ui_selected_item - ITEM_G1 ) {
665
            case 0: s.pattern_g1 = val_pattern; break;
666
            case 1: s.pattern_g2 = val_pattern; break;
667
            case 2: s.pattern_g3 = val_pattern; break;
668
            case 3: s.pattern_g4 = val_pattern; break;
729 tk 669
                    default: return 0; // invalid bank selection
670
          }
1421 tk 671
          SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
672
          checkChangePattern(ui_selected_item - ITEM_G1, val_bank, val_pattern);
758 tk 673
          return 1; // value has been changed
674
        }
675
        return 0; // no change
676
          }
677
      }
729 tk 678
        } break;
758 tk 679
 
729 tk 680
        case ITEM_SEL_BANK:
758 tk 681
      if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 )
682
        return 0; // no change
729 tk 683
 
758 tk 684
      sel_bank ^= 1;
685
      return 1; // value has been changed
729 tk 686
      }
401 tk 687
    }
688
  }
689
 
399 tk 690
  switch( button ) {
691
    case SEQ_UI_BUTTON_GP1:
729 tk 692
      if( depressed ) return 0; // ignore when button depressed
399 tk 693
      ui_selected_item = ITEM_SONG;
694
      return 1;
695
 
696
    case SEQ_UI_BUTTON_GP2:
729 tk 697
      if( depressed ) return 0; // ignore when button depressed
399 tk 698
      ui_selected_item = ITEM_POS;
699
      return 1;
700
 
701
    case SEQ_UI_BUTTON_GP3:
729 tk 702
      if( depressed || show_song_util_page ) return 0; // ignore when button depressed or not in main page
399 tk 703
      ui_selected_item = ITEM_ACTION;
704
      return 1;
705
 
706
    case SEQ_UI_BUTTON_GP4:
729 tk 707
      if( depressed || show_song_util_page ) return 0; // ignore when button depressed or not in main page
399 tk 708
      ui_selected_item = ITEM_G1;
709
      return 1;
710
 
711
    case SEQ_UI_BUTTON_GP5:
729 tk 712
      if( depressed || show_song_util_page ) return 0; // ignore when button depressed or not in main page
399 tk 713
      ui_selected_item = ITEM_G2;
714
      return 1;
715
 
716
    case SEQ_UI_BUTTON_GP6:
729 tk 717
      if( depressed || show_song_util_page ) return 0; // ignore when button depressed or not in main page
399 tk 718
      ui_selected_item = ITEM_G3;
719
      return 1;
720
 
721
    case SEQ_UI_BUTTON_GP7:
729 tk 722
      if( depressed || show_song_util_page ) return 0; // ignore when button depressed or not in main page
399 tk 723
      ui_selected_item = ITEM_G4;
724
      return 1;
725
 
726
    case SEQ_UI_BUTTON_GP8:
729 tk 727
      if( depressed || show_song_util_page ) return 0; // ignore when button depressed or not in main page
399 tk 728
      ui_selected_item = ITEM_SEL_BANK;
729
      return 1;
730
 
731
    case SEQ_UI_BUTTON_GP9:
732
    case SEQ_UI_BUTTON_GP10:
729 tk 733
      ui_selected_item = ITEM_MODE;
734
      SEQ_SONG_ActiveSet(SEQ_SONG_ActiveGet() ? 0 : 1);
735
      return 1;
736
 
399 tk 737
    case SEQ_UI_BUTTON_GP11:
738
    case SEQ_UI_BUTTON_GP12:
739
    case SEQ_UI_BUTTON_GP13:
740
    case SEQ_UI_BUTTON_GP14:
741
    case SEQ_UI_BUTTON_GP15:
742
    case SEQ_UI_BUTTON_GP16:
743
      // not mapped
744
      return -1;
745
 
746
    case SEQ_UI_BUTTON_Select:
729 tk 747
      show_song_util_page = depressed ? 0 : 1;
748
      return 1; // value always changed
749
 
399 tk 750
    case SEQ_UI_BUTTON_Right:
729 tk 751
      if( depressed ) return 0; // ignore when button depressed
399 tk 752
      if( ++ui_selected_item >= NUM_OF_ITEMS )
753
      ui_selected_item = 0;
754
      return 1; // value always changed
755
 
756
    case SEQ_UI_BUTTON_Left:
729 tk 757
      if( depressed ) return 0; // ignore when button depressed
399 tk 758
      if( ui_selected_item == 0 )
759
    ui_selected_item = NUM_OF_ITEMS-1;
1142 tk 760
      else
761
    --ui_selected_item;
762
 
399 tk 763
      return 1; // value always changed
764
 
765
    case SEQ_UI_BUTTON_Up:
729 tk 766
      if( depressed ) return 0; // ignore when button depressed
399 tk 767
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);
768
 
769
    case SEQ_UI_BUTTON_Down:
729 tk 770
      if( depressed ) return 0; // ignore when button depressed
399 tk 771
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
772
  }
773
 
774
  return -1; // invalid or unsupported button
775
}
776
 
777
 
778
/////////////////////////////////////////////////////////////////////////////
779
// Local Display Handler function
780
// IN: <high_prio>: if set, a high-priority LCD update is requested
781
/////////////////////////////////////////////////////////////////////////////
782
static s32 LCD_Handler(u8 high_prio)
783
{
740 tk 784
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
785
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
786
  // <--------------------------------------><-------------------------------------->
1044 tk 787
  //        No Songs available as long as theSession hasn't been created!            
959 tk 788
  //                   Please press EXIT and create a new Session!                   
740 tk 789
 
790
  if( SEQ_FILE_FormattingRequired() ) {
791
    if( high_prio )
792
      return 0;
793
 
794
    SEQ_LCD_CursorSet(0, 0);
1044 tk 795
    SEQ_LCD_PrintString("       No Songs available as long as theSession hasn't been created!            ");
740 tk 796
    SEQ_LCD_CursorSet(0, 1);
959 tk 797
    SEQ_LCD_PrintString("                  Please press EXIT and create a new Session!                   ");
740 tk 798
    return 0;
799
  }
800
 
729 tk 801
  if( show_song_util_page ) {
749 tk 802
    if( high_prio )
803
      return 0;
804
 
729 tk 805
    // layout:
806
    // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
807
    // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
808
    // <--------------------------------------><-------------------------------------->
1421 tk 809
    // Song  Pos     Utility Functions         Phrase                Take over current
810
    //   1    A1  Copy Paste Clr Ins. Del.      Mode                 Patterns into song
729 tk 811
    SEQ_LCD_CursorSet(0, 0);
812
    SEQ_LCD_PrintFormattedString("Song  Pos    Utility Functions  ");
813
    if( (in_menu_msg & 0x80) || ((in_menu_msg & 0x7f) && ui_hold_msg_ctr) ) {
814
      SEQ_LCD_PrintString((char *)in_menu_msg_str[(in_menu_msg & 0x7f)-1]);
815
    } else {
816
      SEQ_LCD_PrintSpaces(8);
817
    }
818
 
819
    SEQ_LCD_PrintString(SEQ_SONG_ActiveGet() ? " Song " : "Phrase");
1421 tk 820
    SEQ_LCD_PrintString("                Take over current ");
729 tk 821
 
399 tk 822
    ///////////////////////////////////////////////////////////////////////////
729 tk 823
    SEQ_LCD_CursorSet(0, 1);
399 tk 824
 
729 tk 825
    if( ui_selected_item == ITEM_SONG && ui_cursor_flash ) {
826
      SEQ_LCD_PrintSpaces(3);
827
    } else {
828
      SEQ_LCD_PrintFormattedString("%3d", SEQ_SONG_NumGet() + 1);
399 tk 829
    }
729 tk 830
    SEQ_LCD_PrintSpaces(4);
399 tk 831
 
832
    ///////////////////////////////////////////////////////////////////////////
729 tk 833
    if( ui_selected_item == ITEM_POS && ui_cursor_flash ) {
834
      SEQ_LCD_PrintSpaces(2);
835
    } else {
1421 tk 836
      SEQ_LCD_PrintFormattedString("%c%d", 'A' + (ui_song_edit_pos >> 3), (ui_song_edit_pos&7)+1);
729 tk 837
    }
399 tk 838
 
839
    ///////////////////////////////////////////////////////////////////////////
729 tk 840
    SEQ_LCD_PrintFormattedString("  Copy Paste Clr Ins. Del.     ");
1421 tk 841
    SEQ_LCD_PrintString(" Mode                 Patterns into song");
729 tk 842
  } else {
843
    if( high_prio ) {
844
      ///////////////////////////////////////////////////////////////////////////
845
      // frequently update VU meters
846
      u8 track;
847
      seq_core_trk_t *t = &seq_core_trk[0];
848
      for(track=0; track<16; ++t, ++track) {
849
    if( !(track % 4) )
850
      SEQ_LCD_CursorSet(46 + 10*(track>>2), 1);
851
 
1015 tk 852
    if( seq_core_trk_muted & (1 << track) )
729 tk 853
      SEQ_LCD_PrintVBar('M');
854
    else
855
      SEQ_LCD_PrintVBar(t->vu_meter >> 4);
856
      }
399 tk 857
 
729 tk 858
      ///////////////////////////////////////////////////////////////////////////
859
      // Song position
860
      SEQ_LCD_CursorSet(40 + 23, 0);
861
      u32 song_pos = SEQ_SONG_PosGet();
862
      SEQ_LCD_PrintFormattedString("%c%d.", 'A' + (song_pos>>3), (song_pos&7)+1);
863
 
399 tk 864
      if( SEQ_BPM_IsRunning() || ui_seq_pause )
729 tk 865
    SEQ_LCD_PrintFormattedString("%3d", seq_core_state.ref_step + 1);
399 tk 866
      else
729 tk 867
    SEQ_LCD_PrintString("---");
399 tk 868
 
729 tk 869
      ///////////////////////////////////////////////////////////////////////////
870
      // Loop counter
871
      if( SEQ_SONG_ActiveGet() ) {
872
    SEQ_LCD_CursorSet(40 + 35, 0);
399 tk 873
 
729 tk 874
    if( SEQ_BPM_IsRunning() || ui_seq_pause )
875
      SEQ_LCD_PrintFormattedString("%2d", SEQ_SONG_LoopCtrGet()+1);
876
    else
877
      SEQ_LCD_PrintString("--");
399 tk 878
 
729 tk 879
    SEQ_LCD_PrintFormattedString("/%2d", SEQ_SONG_LoopCtrMaxGet()+1);
880
      }
399 tk 881
 
729 tk 882
      return 0;
883
    }
399 tk 884
 
1421 tk 885
    seq_song_step_t s = SEQ_SONG_StepEntryGet(ui_song_edit_pos);
399 tk 886
 
887
 
729 tk 888
    // layout:
889
    // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
890
    // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
891
    // <--------------------------------------><-------------------------------------->
892
    // Song  Pos  Actn  G1   G2   G3   G4  Sel. Song Mode   S#xx  Pos xx.xxx Loop xx/xx
893
    //   1    A1  Stop 1:A1 1:C1 1:E1 1:G1 Pat  1:A1 ____ 1:C1 ____ 1:E1 ____ 1:G1 ____
399 tk 894
 
729 tk 895
    // Song Phrase      G1   G2   G3   G4  Sel.Phrase Mode  S#xx  Pos xx.xxx           
896
    //
399 tk 897
 
729 tk 898
    ///////////////////////////////////////////////////////////////////////////
899
    SEQ_LCD_CursorSet(0, 0);
900
    SEQ_LCD_PrintString("Song  Pos  Actn ");
399 tk 901
    switch( s.action ) {
1421 tk 902
      case SEQ_SONG_ACTION_End:
729 tk 903
        SEQ_LCD_PrintSpaces(24);
904
        break;
905
 
399 tk 906
      case SEQ_SONG_ACTION_JmpPos:
729 tk 907
        SEQ_LCD_PrintString(" ->  Pos.");
908
        SEQ_LCD_PrintSpaces(15);
909
        break;
910
 
399 tk 911
      case SEQ_SONG_ACTION_JmpSong:
729 tk 912
        SEQ_LCD_PrintString(" ->  Song");
913
        SEQ_LCD_PrintSpaces(15);
914
        break;
915
 
399 tk 916
      case SEQ_SONG_ACTION_SelMixerMap:
729 tk 917
        SEQ_LCD_PrintString(" ->  Map");
918
        SEQ_LCD_PrintSpaces(16);
919
        break;
920
 
592 tk 921
      case SEQ_SONG_ACTION_Tempo:
729 tk 922
        SEQ_LCD_PrintString(" ->   BPM  Ramp");
923
        SEQ_LCD_PrintSpaces(9);
924
        break;
925
 
592 tk 926
      case SEQ_SONG_ACTION_Mutes:
729 tk 927
        SEQ_LCD_PrintString(" G1   G2   G3   G4      ");
928
        break;
929
 
399 tk 930
      default:
729 tk 931
        if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 )
932
    SEQ_LCD_PrintSpaces(24);
933
        else
934
    SEQ_LCD_PrintString(" G1   G2   G3   G4  Sel.");
399 tk 935
    }
729 tk 936
 
937
    SEQ_LCD_PrintString(SEQ_SONG_ActiveGet() ? " Song Mode " : "Phrase Mode");
938
    SEQ_LCD_PrintFormattedString("  S#%2d  Pos ", SEQ_SONG_NumGet()+1);
939
    // (song position print in high_prio branch)
940
 
941
    SEQ_LCD_CursorSet(40 + 29, 0);
942
    if( SEQ_SONG_ActiveGet() ) {
943
      SEQ_LCD_PrintString(" Loop ");
944
      // (loop counter print in high_prio branch)
945
    } else
399 tk 946
      SEQ_LCD_PrintSpaces(12);
729 tk 947
 
948
 
949
    ///////////////////////////////////////////////////////////////////////////
950
    SEQ_LCD_CursorSet(0, 1);
951
 
952
    if( ui_selected_item == ITEM_SONG && ui_cursor_flash ) {
953
      SEQ_LCD_PrintSpaces(3);
954
    } else {
955
      SEQ_LCD_PrintFormattedString("%3d", SEQ_SONG_NumGet() + 1);
956
    }
957
    SEQ_LCD_PrintSpaces(4);
958
 
959
    ///////////////////////////////////////////////////////////////////////////
960
    if( ui_selected_item == ITEM_POS && ui_cursor_flash ) {
961
      SEQ_LCD_PrintSpaces(2);
962
    } else {
1421 tk 963
      SEQ_LCD_PrintFormattedString("%c%d", 'A' + (ui_song_edit_pos >> 3), (ui_song_edit_pos&7)+1);
729 tk 964
    }
965
    SEQ_LCD_PrintSpaces(1);
966
 
967
    ///////////////////////////////////////////////////////////////////////////
968
    if( ui_selected_item == ITEM_ACTION && ui_cursor_flash ) {
399 tk 969
      SEQ_LCD_PrintSpaces(5);
729 tk 970
    } else {
971
      switch( s.action ) {
1421 tk 972
        case SEQ_SONG_ACTION_End:
973
      SEQ_LCD_PrintString(" End ");
758 tk 974
      break;
729 tk 975
 
976
        case SEQ_SONG_ACTION_JmpPos:
977
        case SEQ_SONG_ACTION_JmpSong:
758 tk 978
      SEQ_LCD_PrintString(" Jump");
979
      break;
729 tk 980
 
981
        case SEQ_SONG_ACTION_SelMixerMap:
758 tk 982
      SEQ_LCD_PrintString("Mixer");
983
      break;
729 tk 984
 
985
        case SEQ_SONG_ACTION_Tempo:
758 tk 986
      SEQ_LCD_PrintString("Tempo");
987
      break;
729 tk 988
 
989
        case SEQ_SONG_ACTION_Mutes:
758 tk 990
      SEQ_LCD_PrintString("Mutes");
991
      break;
729 tk 992
 
993
        default:
758 tk 994
      if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 )
995
        SEQ_LCD_PrintString(" ????");
996
      else
997
        SEQ_LCD_PrintFormattedString(" x%2d ", (int)(s.action-SEQ_SONG_ACTION_Loop1+1));
399 tk 998
      }
729 tk 999
    }
1000
    SEQ_LCD_PrintSpaces(1);
1001
 
1002
    ///////////////////////////////////////////////////////////////////////////
1003
    switch( s.action ) {
1421 tk 1004
      case SEQ_SONG_ACTION_End:
729 tk 1005
        SEQ_LCD_PrintSpaces(20);
1006
        break;
1007
 
1008
      case SEQ_SONG_ACTION_JmpPos:
1009
        SEQ_LCD_PrintSpaces(6);
1010
        if( ui_selected_item >= ITEM_G1 && ui_selected_item <= ITEM_G4 && ui_cursor_flash ) {
758 tk 1011
      SEQ_LCD_PrintSpaces(2);
729 tk 1012
        } else {
758 tk 1013
      SEQ_LCD_PrintFormattedString("%c%d", 'A' + (s.action_value >> 3), (s.action_value&7)+1);
729 tk 1014
        }
1015
        SEQ_LCD_PrintSpaces(12);
1016
        break;
1017
 
1018
      case SEQ_SONG_ACTION_JmpSong:
1019
      case SEQ_SONG_ACTION_SelMixerMap:
1020
        SEQ_LCD_PrintSpaces(5);
1021
        if( ui_selected_item >= ITEM_G1 && ui_selected_item <= ITEM_G4 && ui_cursor_flash ) {
758 tk 1022
      SEQ_LCD_PrintSpaces(3);
729 tk 1023
        } else {
758 tk 1024
      SEQ_LCD_PrintFormattedString("%3d", s.action_value + 1);
729 tk 1025
        }
1026
        SEQ_LCD_PrintSpaces(12);
1027
        break;
1028
 
1029
      case SEQ_SONG_ACTION_Tempo:
1030
        SEQ_LCD_PrintSpaces(6);
1031
        if( ui_selected_item >= ITEM_G1 && ui_selected_item <= ITEM_G2 && ui_cursor_flash ) {
758 tk 1032
      SEQ_LCD_PrintSpaces(3);
729 tk 1033
        } else {
758 tk 1034
      SEQ_LCD_PrintFormattedString("%3d", s.action_value);
729 tk 1035
        }
1036
 
1037
        if( ui_selected_item >= ITEM_G3 && ui_selected_item <= ITEM_G4 && ui_cursor_flash ) {
758 tk 1038
      SEQ_LCD_PrintSpaces(7);
729 tk 1039
        } else {
758 tk 1040
      SEQ_LCD_PrintFormattedString("   %3ds", s.pattern_g1);
729 tk 1041
        }
1042
 
1043
        SEQ_LCD_PrintSpaces(4);
1044
        break;
1045
 
1046
      case SEQ_SONG_ACTION_Mutes:
1047
        if( ui_selected_item == ITEM_G1 && ui_cursor_flash ) {
758 tk 1048
      SEQ_LCD_PrintSpaces(4);
729 tk 1049
        } else {
758 tk 1050
      int i;
1051
      for(i=0; i<4; ++i)
1052
        SEQ_LCD_PrintChar((s.pattern_g1 & (1 << i)) ? '*' : 'o');
729 tk 1053
        }
1054
        SEQ_LCD_PrintSpaces(1);
1055
 
1056
        if( ui_selected_item == ITEM_G2 && ui_cursor_flash ) {
758 tk 1057
      SEQ_LCD_PrintSpaces(4);
729 tk 1058
        } else {
758 tk 1059
      int i;
1060
      for(i=0; i<4; ++i)
1061
        SEQ_LCD_PrintChar((s.pattern_g2 & (1 << i)) ? '*' : 'o');
729 tk 1062
        }
1063
        SEQ_LCD_PrintSpaces(1);
1064
 
1065
        if( ui_selected_item == ITEM_G3 && ui_cursor_flash ) {
758 tk 1066
      SEQ_LCD_PrintSpaces(4);
729 tk 1067
        } else {
758 tk 1068
      int i;
1069
      for(i=0; i<4; ++i)
1070
        SEQ_LCD_PrintChar((s.pattern_g3 & (1 << i)) ? '*' : 'o');
729 tk 1071
        }
1072
        SEQ_LCD_PrintSpaces(1);
1073
 
1074
        if( ui_selected_item == ITEM_G4 && ui_cursor_flash ) {
758 tk 1075
      SEQ_LCD_PrintSpaces(4);
729 tk 1076
        } else {
758 tk 1077
      int i;
1078
      for(i=0; i<4; ++i)
1079
        SEQ_LCD_PrintChar((s.pattern_g4 & (1 << i)) ? '*' : 'o');
729 tk 1080
        }
1081
        SEQ_LCD_PrintSpaces(5);
1082
        break;
1083
 
1084
      default:
1085
        if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 )
758 tk 1086
      SEQ_LCD_PrintSpaces(20);
729 tk 1087
        else {
1088
    if( ui_selected_item == ITEM_G1 && ui_cursor_flash )
1089
      SEQ_LCD_PrintSpaces(5);
1090
    else if( s.pattern_g1 >= 0x80 )
1091
      SEQ_LCD_PrintString("-:-- ");
1092
    else
1093
      SEQ_LCD_PrintFormattedString("%x:%c%d ", s.bank_g1+1, 'A' + (s.pattern_g1>>3), (s.pattern_g1&7)+1);
1094
 
1095
    if( ui_selected_item == ITEM_G2 && ui_cursor_flash )
1096
      SEQ_LCD_PrintSpaces(5);
1097
    else if( s.pattern_g2 >= 0x80 )
1098
      SEQ_LCD_PrintString("-:-- ");
1099
    else
1100
      SEQ_LCD_PrintFormattedString("%x:%c%d ", s.bank_g2+1, 'A' + (s.pattern_g2>>3), (s.pattern_g2&7)+1);
1101
 
1102
    if( ui_selected_item == ITEM_G3 && ui_cursor_flash )
1103
      SEQ_LCD_PrintSpaces(5);
1104
    else if( s.pattern_g3 >= 0x80 )
1105
      SEQ_LCD_PrintString("-:-- ");
1106
    else
1107
      SEQ_LCD_PrintFormattedString("%x:%c%d ", s.bank_g3+1, 'A' + (s.pattern_g3>>3), (s.pattern_g3&7)+1);
1108
 
1109
    if( ui_selected_item == ITEM_G4 && ui_cursor_flash )
1110
      SEQ_LCD_PrintSpaces(5);
1111
    else if( s.pattern_g4 >= 0x80 )
1112
      SEQ_LCD_PrintString("-:-- ");
1113
    else
1114
      SEQ_LCD_PrintFormattedString("%x:%c%d ", s.bank_g4+1, 'A' + (s.pattern_g4>>3), (s.pattern_g4&7)+1);
1115
        }
1116
    }
1117
 
1118
    ///////////////////////////////////////////////////////////////////////////
1119
    if( (s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16) ||
1120
        (ui_selected_item == ITEM_SEL_BANK && ui_cursor_flash) ) {
592 tk 1121
      SEQ_LCD_PrintSpaces(4);
729 tk 1122
    } else {
1123
      SEQ_LCD_PrintFormattedString(sel_bank ? "Bnk " : "Pat ", 0);
1124
    }
1125
 
1126
    ///////////////////////////////////////////////////////////////////////////
1127
    int group;
1128
    for(group=0; group<4; ++group) {
1129
      SEQ_LCD_CursorSet(40 + 10*group, 1);
1130
 
1131
      seq_pattern_t pattern = seq_pattern[group];
1132
      SEQ_LCD_PrintFormattedString(" %d:", pattern.bank + 1);
1133
 
1134
      if( pattern.pattern < SEQ_FILE_B_NumPatterns(pattern.bank) )
1135
        SEQ_LCD_PrintPattern(pattern);
1136
      else
1137
        SEQ_LCD_PrintString("!!"); // covers the case that bank is not available, or that pattern number too high
1138
 
1139
      SEQ_LCD_PrintChar(' ');
1140
 
1141
      // (VU meters print in high_prio branch)
1142
 
1143
    }
399 tk 1144
  }
1145
 
1146
  return 0; // no error
1147
}
1148
 
1149
 
1150
/////////////////////////////////////////////////////////////////////////////
401 tk 1151
// Local exit function
1152
/////////////////////////////////////////////////////////////////////////////
1153
static s32 EXIT_Handler(void)
1154
{
1155
  // save song (function exits automatically if no position has been changed)
1156
  SEQ_SONG_Save(SEQ_SONG_NumGet());
690 tk 1157
 
1158
  return 0; // no error
401 tk 1159
}
1160
 
1161
 
1162
/////////////////////////////////////////////////////////////////////////////
399 tk 1163
// Initialisation
1164
/////////////////////////////////////////////////////////////////////////////
1165
s32 SEQ_UI_SONG_Init(u32 mode)
1166
{
1167
  // install callback routines
1168
  SEQ_UI_InstallButtonCallback(Button_Handler);
1169
  SEQ_UI_InstallEncoderCallback(Encoder_Handler);
1170
  SEQ_UI_InstallLEDCallback(LED_Handler);
1171
  SEQ_UI_InstallLCDCallback(LCD_Handler);
401 tk 1172
  SEQ_UI_InstallExitCallback(EXIT_Handler);
399 tk 1173
 
1174
  // we want to show vertical VU meters
1175
  SEQ_LCD_InitSpecialChars(SEQ_LCD_CHARSET_VBars);
1176
 
729 tk 1177
 
1178
  // change pattern numbers by default and don't show util page
399 tk 1179
  sel_bank = 0;
729 tk 1180
  in_menu_msg = MSG_DEFAULT;
1181
  ui_hold_msg_ctr = 0;
1182
  show_song_util_page = 0;
399 tk 1183
 
401 tk 1184
  // always start with "pos" item (especially useful in phrase mode for quick selection)
1185
  ui_selected_item = ITEM_POS;
1186
 
729 tk 1187
  // disabled: don't change previous settings (values will be initialized with 0 by gcc)
1188
  // SEQ_SONG_NumSet(0);
1189
 
1190
  // copypaste_buffer_filled = 0;
1191
 
399 tk 1192
  return 0; // no error
1193
}
1194
 
1195
 
1196
/////////////////////////////////////////////////////////////////////////////
1197
// Change pattern immediately if in phrase mode or song position matches
1198
// with edit position
1199
/////////////////////////////////////////////////////////////////////////////
1421 tk 1200
static s32 checkChangePattern(u8 group, u8 bank, u8 pattern)
399 tk 1201
{
1421 tk 1202
  if( pattern < 0x80 && (!SEQ_SONG_ActiveGet() || ui_song_edit_pos == SEQ_SONG_PosGet()) ) {
399 tk 1203
    seq_pattern_t p;
1204
    p.ALL = 0;
1205
    p.pattern = pattern;
1206
    p.bank = bank;
1117 tk 1207
    return SEQ_PATTERN_Change(group, p, 0);
399 tk 1208
  }
1209
 
1210
  return 0; // no error
1211
}
1212
 
1421 tk 1213
/////////////////////////////////////////////////////////////////////////////
1214
// Set Edit Position
1215
/////////////////////////////////////////////////////////////////////////////
1216
static s32 takeoverCurrentPatterns(void)
1217
{
1218
  seq_song_step_t s = SEQ_SONG_StepEntryGet(ui_song_edit_pos);
729 tk 1219
 
1421 tk 1220
  if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 )
1221
    s.action = SEQ_SONG_ACTION_Loop1;
1222
  s.pattern_g1 = seq_pattern[0].pattern;
1223
  s.bank_g1 = seq_pattern[0].bank;
1224
  s.pattern_g2 = seq_pattern[1].pattern;
1225
  s.bank_g2 = seq_pattern[1].bank;
1226
  s.pattern_g3 = seq_pattern[2].pattern;
1227
  s.bank_g3 = seq_pattern[2].bank;
1228
  s.pattern_g4 = seq_pattern[3].pattern;
1229
  s.bank_g4 = seq_pattern[3].bank;
729 tk 1230
 
1421 tk 1231
  SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
1232
  SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "Patterns", "taken over!");
1233
 
1234
  return 0; // no error
1235
}
1236
 
1237
 
729 tk 1238
/////////////////////////////////////////////////////////////////////////////
1239
// Copy Song Position
1240
/////////////////////////////////////////////////////////////////////////////
1241
s32 SEQ_UI_SONG_Copy(void)
1242
{
1421 tk 1243
  copypaste_buffer = SEQ_SONG_StepEntryGet(ui_song_edit_pos);
729 tk 1244
 
1245
  // notify that copy&paste buffer is filled
1246
  copypaste_buffer_filled = 1;
1247
 
1248
  return 0; // no error
1249
}
1250
 
1251
/////////////////////////////////////////////////////////////////////////////
1252
// Paste Song Position
1253
/////////////////////////////////////////////////////////////////////////////
1254
s32 SEQ_UI_SONG_Paste(void)
1255
{
1256
  // branch to clear function if copy&paste buffer not filled
1257
  if( !copypaste_buffer_filled )
1258
    return SEQ_UI_SONG_Clear();
1259
 
1421 tk 1260
  SEQ_SONG_StepEntrySet(ui_song_edit_pos, copypaste_buffer);
729 tk 1261
 
1262
  return 0; // no error
1263
}
1264
 
1265
/////////////////////////////////////////////////////////////////////////////
1266
// Clear Song Position
1267
/////////////////////////////////////////////////////////////////////////////
1268
s32 SEQ_UI_SONG_Clear(void)
1269
{
1270
  // already available in SEQ_SONG layer
1421 tk 1271
  return SEQ_SONG_StepEntryClear(ui_song_edit_pos);
729 tk 1272
}
1273
 
1274
/////////////////////////////////////////////////////////////////////////////
1275
// Insert Song Position
1276
/////////////////////////////////////////////////////////////////////////////
1277
s32 SEQ_UI_SONG_Insert(void)
1278
{
1279
  int step;
1280
 
1421 tk 1281
  if( ui_song_edit_pos < (SEQ_SONG_NUM_STEPS-1) ) {
1282
    for(step=SEQ_SONG_NUM_STEPS-1; step>ui_song_edit_pos; --step)
729 tk 1283
      SEQ_SONG_StepEntrySet(step, SEQ_SONG_StepEntryGet(step-1));
1284
  }
1421 tk 1285
  SEQ_SONG_StepEntryClear(ui_song_edit_pos);
729 tk 1286
 
1287
  return 0; // no error
1288
}
1289
 
1290
/////////////////////////////////////////////////////////////////////////////
1291
// Delete Song Position
1292
/////////////////////////////////////////////////////////////////////////////
1293
s32 SEQ_UI_SONG_Delete(void)
1294
{
1295
  int step;
1296
 
1421 tk 1297
  if( ui_song_edit_pos < (SEQ_SONG_NUM_STEPS-1) ) {
1298
    for(step=ui_song_edit_pos; step<(SEQ_SONG_NUM_STEPS-1); ++step)
729 tk 1299
      SEQ_SONG_StepEntrySet(step, SEQ_SONG_StepEntryGet(step+1));
1300
  }
1301
  SEQ_SONG_StepEntryClear(SEQ_SONG_NUM_STEPS-1);
1302
 
1303
  return 0; // no error
1304
}
752 tk 1305
 
1306
 
1307
/////////////////////////////////////////////////////////////////////////////
1308
// Set Edit Position
1309
/////////////////////////////////////////////////////////////////////////////
1310
s32 SEQ_UI_SONG_EditPosSet(u8 new_edit_pos)
1311
{
1421 tk 1312
  ui_song_edit_pos = new_edit_pos;
752 tk 1313
 
1314
  return 0; // no error
1315
}