Subversion Repositories svn.mios32

Rev

Rev 1516 | Rev 1806 | 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 1794 2013-05-31 19:25:43Z 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"
1794 tk 26
#include "seq_mixer.h"
399 tk 27
#include "seq_pattern.h"
1794 tk 28
#include "seq_midi_in.h"
740 tk 29
#include "seq_file.h"
399 tk 30
#include "seq_file_b.h"
31
#include "seq_file_m.h"
32
 
33
 
34
/////////////////////////////////////////////////////////////////////////////
35
// Local definitions
36
/////////////////////////////////////////////////////////////////////////////
37
 
38
// Note/Chord/CC
39
#define NUM_OF_ITEMS        8
40
#define ITEM_SONG           0
41
#define ITEM_POS            1
42
#define ITEM_ACTION         2
43
#define ITEM_G1             3
44
#define ITEM_G2             4
45
#define ITEM_G3             5
46
#define ITEM_G4             6
47
#define ITEM_SEL_BANK       7
729 tk 48
#define ITEM_MODE           8
399 tk 49
 
50
 
729 tk 51
// used "In-Menu" messages
52
#define MSG_DEFAULT 0x00
53
#define MSG_COPY    0x81
54
#define MSG_PASTE   0x82
55
#define MSG_CLEAR   0x83
56
#define MSG_INSERT  0x84
57
#define MSG_DELETE  0x85
58
 
59
 
1794 tk 60
#define SONG_UTIL_PAGE_NONE        0
61
#define SONG_UTIL_PAGE_SELECT      1
62
#define SONG_UTIL_PAGE_NEW_PATTERN 2
63
 
64
 
399 tk 65
/////////////////////////////////////////////////////////////////////////////
66
// Local variables
67
/////////////////////////////////////////////////////////////////////////////
68
 
69
static u8 sel_bank;
70
 
1794 tk 71
static u8 song_util_page;
72
static u16 song_util_page_new_pattern__led_pattern;
399 tk 73
 
729 tk 74
static u8 in_menu_msg;
75
 
76
static const char in_menu_msg_str[6][9] = {
77
  ">COPIED<",   // #1
78
  ">PASTED<",   // #2
79
  "CLEARED!",   // #3
80
  "INSERTED",   // #4
81
  " DELETED",   // #5
82
};
83
 
84
 
85
static u8 copypaste_buffer_filled = 0;
86
static seq_song_step_t copypaste_buffer;
87
 
88
 
399 tk 89
/////////////////////////////////////////////////////////////////////////////
90
// Local Prototypes
91
/////////////////////////////////////////////////////////////////////////////
92
 
729 tk 93
static s32 Button_Handler(seq_ui_button_t button, s32 depressed);
1421 tk 94
static s32 checkChangePattern(u8 group, u8 bank, u8 pattern);
95
static s32 takeoverCurrentPatterns(void);
1794 tk 96
static s32 createNewPatterns(u8 slot);
399 tk 97
 
98
 
99
/////////////////////////////////////////////////////////////////////////////
100
// Local LED handler function
101
/////////////////////////////////////////////////////////////////////////////
102
static s32 LED_Handler(u16 *gp_leds)
103
{
740 tk 104
  if( SEQ_FILE_FormattingRequired() )
1044 tk 105
    return 0; // no LED action as long as files not available
740 tk 106
 
1794 tk 107
  switch( song_util_page ) {
1493 tk 108
 
1794 tk 109
  ///////////////////////////////////////////////////////////////////////////
110
  case SONG_UTIL_PAGE_NONE: {
111
    if( ui_cursor_flash ) // if flashing flag active: no LED flag set
112
      return 0;
399 tk 113
 
1794 tk 114
    seq_song_step_t s = SEQ_SONG_StepEntryGet(ui_song_edit_pos);
401 tk 115
 
1794 tk 116
    switch( ui_selected_item ) {
401 tk 117
    case ITEM_SONG:
118
      *gp_leds = 0x0001;
119
      break;
120
 
121
    case ITEM_POS:
1421 tk 122
      *gp_leds = 1 << ((ui_song_edit_pos>>3)&0xf);
401 tk 123
      break;
124
 
125
    case ITEM_ACTION:
126
      *gp_leds = 0x0004;
127
      break;
128
 
129
    case ITEM_G1:
130
    case ITEM_G2:
131
    case ITEM_G3:
132
    case ITEM_G4: {
133
      switch( s.action ) {
1421 tk 134
        case SEQ_SONG_ACTION_End:
401 tk 135
      *gp_leds = 1 << ui_selected_item;
136
      break;
137
 
138
        case SEQ_SONG_ACTION_JmpPos:
139
        case SEQ_SONG_ACTION_JmpSong:
140
        case SEQ_SONG_ACTION_SelMixerMap: {
141
      u8 val = (u8)s.action_value;
142
      *gp_leds = (1 << ((val>>3)&7)) | (0x100 << (val&7));
143
    } break;
144
 
592 tk 145
        case SEQ_SONG_ACTION_Tempo: {
146
      *gp_leds = 0x0000; // how to handle this?
147
      break;
148
    }
149
 
150
        case SEQ_SONG_ACTION_Mutes: {
151
      *gp_leds = ((s.pattern_g4&0xf) << 12) | ((s.pattern_g3&0xf) << 8) | ((s.pattern_g2&0xf) << 4) | (s.pattern_g1&0xf);
152
    } break;
153
 
1515 tk 154
        case SEQ_SONG_ACTION_GuideTrack: {
155
      u8 val = (u8)s.action_value;
156
      *gp_leds = (val && val <= 16) ? (1 << (val-1)) : 0x0000;
157
      break;
158
    }
159
 
401 tk 160
        default:
161
      if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 ) {
162
        *gp_leds = 1 << ui_selected_item;
163
      } else {
164
        if( sel_bank ) {
165
          u8 val_bank;
166
          switch( ui_selected_item - ITEM_G1 ) {
167
            case 0: val_bank = s.bank_g1; break;
168
            case 1: val_bank = s.bank_g2; break;
169
            case 2: val_bank = s.bank_g3; break;
170
            case 3: val_bank = s.bank_g4; break;
171
            default: return 0; // invalid bank selection
172
          }
173
          *gp_leds = 1 << val_bank;
174
        } else {
175
          u8 val_pattern;
176
          switch( ui_selected_item - ITEM_G1 ) {
177
            case 0: val_pattern = s.pattern_g1; break;
178
            case 1: val_pattern = s.pattern_g2; break;
179
            case 2: val_pattern = s.pattern_g3; break;
180
            case 3: val_pattern = s.pattern_g4; break;
181
            default: return 0; // invalid bank selection
182
          }
183
          *gp_leds = (1 << ((val_pattern>>3)&7)) | (0x100 << (val_pattern&7));
184
        }
185
      }
186
      }
187
    } break;
188
 
189
    case ITEM_SEL_BANK:
190
      *gp_leds = 0x0080;
191
      break;
729 tk 192
 
193
    case ITEM_MODE:
194
      *gp_leds = 0x0300;
195
      break;
1794 tk 196
    }
197
  } break;
198
 
199
  ///////////////////////////////////////////////////////////////////////////
200
  case SONG_UTIL_PAGE_SELECT: {
201
    *gp_leds = 0x0000;
202
  } break;
203
 
204
  ///////////////////////////////////////////////////////////////////////////
205
  case SONG_UTIL_PAGE_NEW_PATTERN: {
206
    if( seq_ui_button_state.SELECT_PRESSED ) {
207
      *gp_leds = 0x0000;
208
    } else {
209
      *gp_leds = song_util_page_new_pattern__led_pattern;
210
 
211
      if( ui_cursor_flash )
212
    *gp_leds &= ~(1 << (ui_song_edit_pos >> 3));
213
    }
214
  } break;
399 tk 215
  }
216
 
217
  return 0; // no error
218
}
219
 
220
 
221
/////////////////////////////////////////////////////////////////////////////
222
// Local encoder callback function
223
// Should return:
224
//   1 if value has been changed
225
//   0 if value hasn't been changed
226
//  -1 if invalid or unsupported encoder
227
/////////////////////////////////////////////////////////////////////////////
228
static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer)
229
{
740 tk 230
  if( SEQ_FILE_FormattingRequired() )
1044 tk 231
    return 0; // no encoder action as long as files not available
740 tk 232
 
1421 tk 233
  seq_song_step_t s = SEQ_SONG_StepEntryGet(ui_song_edit_pos);
399 tk 234
 
235
 
1794 tk 236
  switch( song_util_page ) {
399 tk 237
 
1794 tk 238
  ///////////////////////////////////////////////////////////////////////////
239
  case SONG_UTIL_PAGE_NONE: {
1493 tk 240
    switch( encoder ) {
241
      case SEQ_UI_ENCODER_GP1:
242
        ui_selected_item = ITEM_SONG;
243
        break;
729 tk 244
 
1493 tk 245
      case SEQ_UI_ENCODER_GP2:
246
        ui_selected_item = ITEM_POS;
247
        break;
399 tk 248
 
1493 tk 249
      case SEQ_UI_ENCODER_GP3:
250
    ui_selected_item = ITEM_ACTION;
251
    break;
729 tk 252
 
1493 tk 253
      case SEQ_UI_ENCODER_GP4:
254
    ui_selected_item = ITEM_G1;
255
    break;
256
 
257
      case SEQ_UI_ENCODER_GP5:
258
    ui_selected_item = ITEM_G2;
259
    break;
260
 
261
      case SEQ_UI_ENCODER_GP6:
262
    ui_selected_item = ITEM_G3;
263
    break;
264
 
265
      case SEQ_UI_ENCODER_GP7:
266
    ui_selected_item = ITEM_G4;
267
    break;
268
 
269
      case SEQ_UI_ENCODER_GP8:
270
    ui_selected_item = ITEM_SEL_BANK;
271
    break;
272
 
273
      case SEQ_UI_ENCODER_GP9:
274
      case SEQ_UI_ENCODER_GP10:
275
        ui_selected_item = ITEM_MODE;
276
        break;
277
 
278
      case SEQ_UI_ENCODER_GP11:
279
      case SEQ_UI_ENCODER_GP12:
280
      case SEQ_UI_ENCODER_GP13:
281
      case SEQ_UI_ENCODER_GP14:
282
      case SEQ_UI_ENCODER_GP15:
283
      case SEQ_UI_ENCODER_GP16:
284
    return -1; // not mapped to encoder
285
    }
1794 tk 286
  } break;
287
 
288
  ///////////////////////////////////////////////////////////////////////////
289
  case SONG_UTIL_PAGE_SELECT: {
290
    switch( encoder ) {
291
    case SEQ_UI_ENCODER_GP1:
292
      ui_selected_item = ITEM_SONG;
293
      break;
294
 
295
    case SEQ_UI_ENCODER_GP2:
296
      ui_selected_item = ITEM_POS;
297
      break;
298
 
299
    case SEQ_UI_ENCODER_GP3: // Copy
300
      // copy position
301
      SEQ_UI_SONG_Copy();
302
      // print message
303
      in_menu_msg = MSG_COPY & 0x7f;
304
      ui_hold_msg_ctr = 1000;
305
      return 1;
306
 
307
    case SEQ_UI_ENCODER_GP4: // Paste
308
      // paste position
309
      SEQ_UI_SONG_Paste();
310
      // print message
311
      in_menu_msg = MSG_PASTE & 0x7f;
312
      ui_hold_msg_ctr = 1000;
313
      return 1;
314
 
315
    case SEQ_UI_ENCODER_GP5: // Clear
316
      // clear position
317
      SEQ_UI_SONG_Clear();
318
      // print message
319
      in_menu_msg = MSG_CLEAR & 0x7f;
320
      ui_hold_msg_ctr = 1000;
321
      return 1;
322
 
323
    case SEQ_UI_ENCODER_GP6: // Insert
324
      // insert position
325
      SEQ_UI_SONG_Insert();
326
      // print message
327
      in_menu_msg = MSG_INSERT & 0x7f;
328
      ui_hold_msg_ctr = 1000;
329
      return 1;
330
 
331
    case SEQ_UI_ENCODER_GP7: // Delete
332
      // delete position
333
      SEQ_UI_SONG_Delete();
334
      // print message
335
      in_menu_msg = MSG_DELETE & 0x7f;
336
      ui_hold_msg_ctr = 1000;
337
      return 1;
338
 
339
    case SEQ_UI_ENCODER_GP8:
340
      return -1; // not used
341
 
342
    case SEQ_UI_ENCODER_GP9:
343
    case SEQ_UI_ENCODER_GP10:
344
      ui_selected_item = ITEM_MODE;
345
      break;
346
 
347
    case SEQ_UI_ENCODER_GP11:
348
    case SEQ_UI_ENCODER_GP12:
349
      if( SEQ_SONG_ActiveGet() ) {
350
    u8 guide = SEQ_SONG_GuideTrackGet();
351
 
352
    if( incrementer == 0 ) {
353
      // button pressed: cycle through selections
354
      if( guide == SEQ_CORE_NUM_TRACKS ) { // 0..16, 0 disables track
355
        SEQ_SONG_GuideTrackSet(0);
356
        return 1;
357
      }
358
      incrementer = 1;
359
    }
360
    if( SEQ_UI_Var8_Inc(&guide, 0, SEQ_CORE_NUM_TRACKS, incrementer) ) { // 0..16, 0 disables guide track
361
      SEQ_SONG_GuideTrackSet(guide);
362
      return 1;
363
    }
364
    return -1;
365
      }
366
      return -1; // only used in song mode
367
 
368
    case SEQ_UI_ENCODER_GP13:
369
    case SEQ_UI_ENCODER_GP14:
370
      takeoverCurrentPatterns();
371
      return 1;
372
 
373
    case SEQ_UI_ENCODER_GP15:
374
    case SEQ_UI_ENCODER_GP16:
375
      song_util_page = SONG_UTIL_PAGE_NEW_PATTERN;
376
      return 1;
377
    }
378
  } break;
379
 
380
  ///////////////////////////////////////////////////////////////////////////
381
  case SONG_UTIL_PAGE_NEW_PATTERN: {
382
    if( seq_ui_button_state.SELECT_PRESSED ) {
383
      return 0;
384
    }
385
 
386
 
387
    if( encoder <= SEQ_UI_ENCODER_GP16 ) {
388
      u8 slot = (u8)encoder;
389
      createNewPatterns(slot);
390
      song_util_page = SONG_UTIL_PAGE_NONE;
391
      return 1;
392
    }
393
    return 0;
394
  } break;
399 tk 395
  }
396
 
397
  // for GP encoders and Datawheel
398
  switch( ui_selected_item ) {
1794 tk 399
  case ITEM_SONG: {
400
    u8 song_num = SEQ_SONG_NumGet();
401
    u8 old_song_num = song_num;
402
    if( SEQ_UI_Var8_Inc(&song_num, 0, SEQ_SONG_NUM-1, incrementer) >= 0 ) {
403
      // store old song
404
      SEQ_SONG_Save(old_song_num);
405
 
406
      // send to external
407
      SEQ_MIDI_IN_ExtCtrlSend(SEQ_MIDI_IN_EXT_CTRL_SONG, song_num);
408
 
409
      // change to new song
410
      SEQ_SONG_Load(song_num);
411
      return 1; // value has been changed
412
    }
413
    return 0; // no change
414
  } break;
415
 
416
  case ITEM_POS:
417
    return SEQ_UI_Var8_Inc(&ui_song_edit_pos, 0, SEQ_SONG_NUM_STEPS-1, incrementer);
418
 
419
  case ITEM_ACTION: {
420
    u8 action = (u8)s.action;
421
    if( SEQ_UI_Var8_Inc(&action, 0, SEQ_SONG_NUM_ACTIONS-1, incrementer) >= 0 ) {
422
      s.action = action;
423
      SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
424
      return 1; // value has been changed
425
    }
426
    return 0; // no change
427
  } break;
428
 
429
  case ITEM_G1:
430
  case ITEM_G2:
431
  case ITEM_G3:
432
  case ITEM_G4: {
433
    switch( s.action ) {
434
    case SEQ_SONG_ACTION_End:
435
      return 0; // do nothing
436
 
437
    case SEQ_SONG_ACTION_JmpPos: {
438
      u8 val = (u8)s.action_value;
439
      if( SEQ_UI_Var8_Inc(&val, 0, SEQ_SONG_NUM_STEPS-1, incrementer) >= 0 ) {
440
    s.action_value = val;
441
    SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
399 tk 442
    return 1; // value has been changed
443
      }
444
      return 0; // no change
1794 tk 445
    }
399 tk 446
 
1794 tk 447
    case SEQ_SONG_ACTION_JmpSong: {
448
      u8 val = (u8)s.action_value;
449
      if( SEQ_UI_Var8_Inc(&val, 0, SEQ_SONG_NUM-1, incrementer) >= 0 ) {
450
    s.action_value = val;
1421 tk 451
    SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
399 tk 452
    return 1; // value has been changed
453
      }
454
      return 0; // no change
1794 tk 455
    }
399 tk 456
 
1794 tk 457
    case SEQ_SONG_ACTION_SelMixerMap: {
458
      u8 val = (u8)s.action_value;
459
      u8 num_mixer_maps = SEQ_FILE_M_NumMaps();
460
      if( !num_mixer_maps )
461
    num_mixer_maps = 128;
462
      if( SEQ_UI_Var8_Inc(&val, 0, num_mixer_maps-1, incrementer) >= 0 ) {
463
    s.action_value = val;
464
    SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
399 tk 465
 
1794 tk 466
    // in phrase mode and no song pos selected: fetch patterns immediately if SynchChange not set
467
    if( !SEQ_SONG_ActiveGet() ) {
468
      u8 force_immediate_change = seq_core_options.SYNCHED_PATTERN_CHANGE ? 0 : 1;
469
      SEQ_SONG_FetchPos(force_immediate_change);
470
      SEQ_CORE_ManualSynchToMeasure(0xffff); // ensure that the new selection is in sync
399 tk 471
    }
1794 tk 472
    return 1; // value has been changed
473
      }
474
      return 0; // no change
475
    }
399 tk 476
 
1794 tk 477
    case SEQ_SONG_ACTION_Tempo: {
478
      if( ui_selected_item == ITEM_G1 || ui_selected_item == ITEM_G2 ) {
479
    // BPM
480
    u8 val = (u8)s.action_value;
481
    if( SEQ_UI_Var8_Inc(&val, 25, 255, incrementer) >= 0 ) {
482
      s.action_value = val;
483
      SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
484
      // in phrase mode and no song pos selected: fetch patterns immediately
485
      if( !SEQ_SONG_ActiveGet() )
486
        SEQ_SONG_FetchPos(0);
487
      return 1; // value has been changed
399 tk 488
    }
1794 tk 489
      } else {
490
    // Ramp
491
    u8 val = (u8)s.pattern_g1;
492
    if( SEQ_UI_Var8_Inc(&val, 0, 255, incrementer) >= 0 ) {
493
      s.pattern_g1 = val;
494
      SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
495
      // in phrase mode and no song pos selected: fetch patterns immediately
496
      if( !SEQ_SONG_ActiveGet() )
497
        SEQ_SONG_FetchPos(0);
498
      return 1; // value has been changed
499
    }
500
      }
399 tk 501
 
1794 tk 502
      return 0; // no change
503
    }
592 tk 504
 
1794 tk 505
    case SEQ_SONG_ACTION_Mutes: {
506
      u8 val;
507
      switch( ui_selected_item ) {
508
      case ITEM_G1: val = (u8)s.pattern_g1 & 0xf; break;
509
      case ITEM_G2: val = (u8)s.pattern_g2 & 0xf; break;
510
      case ITEM_G3: val = (u8)s.pattern_g3 & 0xf; break;
511
      case ITEM_G4: val = (u8)s.pattern_g4 & 0xf; break;
512
      default: return 0; // not mapped
513
      }
514
 
515
      if( SEQ_UI_Var8_Inc(&val, 0, 15, incrementer) >= 0 ) {
516
    switch( ui_selected_item ) {
517
    case ITEM_G1: s.pattern_g1 = val; break;
518
    case ITEM_G2: s.pattern_g2 = val; break;
519
    case ITEM_G3: s.pattern_g3 = val; break;
520
    case ITEM_G4: s.pattern_g4 = val; break;
521
    default: return 0; // not mapped
399 tk 522
    }
1794 tk 523
    SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
524
    // in phrase mode and no song pos selected: fetch patterns immediately
525
    if( !SEQ_SONG_ActiveGet() )
526
      SEQ_SONG_FetchPos(0);
527
    return 1; // value has been changed
528
      }
529
      return 0; // no change
530
    }
399 tk 531
 
1794 tk 532
    case SEQ_SONG_ACTION_GuideTrack: {
533
      if( s.action_value > 16 )
534
    s.action_value = 0;
535
      u8 val = (u8)s.action_value;
536
      if( SEQ_UI_Var8_Inc(&val, 0, 16, incrementer) >= 0 ) {
537
    s.action_value = val;
538
    SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
539
    return 1; // value has been changed
540
      }
541
      return 0; // no change
542
    }
592 tk 543
 
1794 tk 544
    default:
545
      if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 )
546
    return 0; // no change
547
      else {
548
    u8 val_bank;
549
    switch( ui_selected_item - ITEM_G1 ) {
550
    case 0: val_bank = s.bank_g1; break;
551
    case 1: val_bank = s.bank_g2; break;
552
    case 2: val_bank = s.bank_g3; break;
553
    case 3: val_bank = s.bank_g4; break;
554
    default: return 0; // invalid bank selection
592 tk 555
    }
556
 
1794 tk 557
    u8 val_pattern;
558
    switch( ui_selected_item - ITEM_G1 ) {
559
    case 0: val_pattern = s.pattern_g1; break;
560
    case 1: val_pattern = s.pattern_g2; break;
561
    case 2: val_pattern = s.pattern_g3; break;
562
    case 3: val_pattern = s.pattern_g4; break;
563
    default: return 0; // invalid bank selection
564
    }
592 tk 565
 
1794 tk 566
    if( sel_bank ) {
567
      if( SEQ_UI_Var8_Inc(&val_bank, 0, SEQ_FILE_B_NUM_BANKS-1, incrementer) >= 0 ) {
568
        switch( ui_selected_item - ITEM_G1 ) {
569
        case 0: s.bank_g1 = val_bank; break;
570
        case 1: s.bank_g2 = val_bank; break;
571
        case 2: s.bank_g3 = val_bank; break;
572
        case 3: s.bank_g4 = val_bank; break;
573
        default: return 0; // invalid bank selection
592 tk 574
        }
1421 tk 575
        SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
1794 tk 576
        checkChangePattern(ui_selected_item - ITEM_G1, val_bank, val_pattern);
592 tk 577
        return 1; // value has been changed
578
      }
1794 tk 579
    } else {
580
      u8 num_patterns = SEQ_FILE_B_NumPatterns(val_bank);
581
      if( !num_patterns )
582
        num_patterns = 64;
583
      // move 0x80 (disable pattern) to the beginning of pattern selection for more comfortable editing
584
      u8 val_pattern_converted = (val_pattern >= 0x80) ? 0 : (val_pattern+1);
585
      if( SEQ_UI_Var8_Inc(&val_pattern_converted, 0, num_patterns, incrementer) >= 0 ) {
586
        val_pattern = (val_pattern_converted == 0) ? 0x80 : (val_pattern_converted-1);
587
        switch( ui_selected_item - ITEM_G1 ) {
588
        case 0: s.pattern_g1 = val_pattern; break;
589
        case 1: s.pattern_g2 = val_pattern; break;
590
        case 2: s.pattern_g3 = val_pattern; break;
591
        case 3: s.pattern_g4 = val_pattern; break;
592
        default: return 0; // invalid bank selection
593
        }
1515 tk 594
        SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
1794 tk 595
        checkChangePattern(ui_selected_item - ITEM_G1, val_bank, val_pattern);
1515 tk 596
        return 1; // value has been changed
597
      }
598
    }
1794 tk 599
    return 0; // no change
399 tk 600
      }
1794 tk 601
    }
602
  } break;
399 tk 603
 
1794 tk 604
  case ITEM_SEL_BANK:
605
    if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 )
606
      return 0; // no change
399 tk 607
 
1794 tk 608
    if( incrementer > 0 )
609
      sel_bank = 1;
610
    else if( incrementer < 0 )
611
      sel_bank = 0;
612
    else
613
      return 0; // no change
614
    return 1; // value has been changed
729 tk 615
 
1794 tk 616
  case ITEM_MODE:
617
    if( incrementer == 0 ) // button: toggle
618
      SEQ_SONG_ActiveSet(SEQ_SONG_ActiveGet() ? 0 : 1);
619
    else
620
      SEQ_SONG_ActiveSet((incrementer > 0) ? 1 : 0);
621
    return 1; // value has been changed
399 tk 622
  }
623
 
624
  return -1; // invalid or unsupported encoder
625
}
626
 
627
 
628
/////////////////////////////////////////////////////////////////////////////
629
// Local button callback function
630
// Should return:
631
//   1 if value has been changed
632
//   0 if value hasn't been changed
633
//  -1 if invalid or unsupported button
634
/////////////////////////////////////////////////////////////////////////////
635
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
636
{
740 tk 637
  if( SEQ_FILE_FormattingRequired() )
1044 tk 638
    return 0; // no button action as long as files not available
740 tk 639
 
401 tk 640
  // special mapping of GP buttons depending on ui_selected_item
641
#if 0
642
  // leads to: comparison is always true due to limited range of data type
643
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
644
#else
645
  if( button <= SEQ_UI_BUTTON_GP16 ) {
646
#endif
729 tk 647
    if( depressed ) return 0; // ignore when button depressed
401 tk 648
 
1794 tk 649
    if( song_util_page ) {
1493 tk 650
      // re-use encoder handler - only select/select UI item, don't increment
651
      return Encoder_Handler((int)button, 0);
652
    }
1794 tk 653
 
1493 tk 654
    seq_song_step_t s = SEQ_SONG_StepEntryGet(ui_song_edit_pos);
401 tk 655
 
1493 tk 656
    switch( ui_selected_item ) {
657
    case ITEM_POS:
658
      ui_song_edit_pos = (u8)button << 3;
729 tk 659
 
1794 tk 660
 
661
      // send to external
662
      SEQ_MIDI_IN_ExtCtrlSend(SEQ_MIDI_IN_EXT_CTRL_PHRASE, ui_song_edit_pos >> 3);
663
 
1493 tk 664
      // set song position and fetch patterns
665
      SEQ_SONG_PosSet(ui_song_edit_pos);
666
      SEQ_SONG_FetchPos(0);
667
      ui_song_edit_pos = SEQ_SONG_PosGet();
668
      return 1;
729 tk 669
 
1493 tk 670
      case ITEM_G1:
671
      case ITEM_G2:
672
      case ITEM_G3:
673
      case ITEM_G4: {
674
    switch( s.action ) {
675
      case SEQ_SONG_ACTION_End:
676
        return 0; // do nothing
729 tk 677
 
1493 tk 678
      case SEQ_SONG_ACTION_JmpPos:
679
      case SEQ_SONG_ACTION_JmpSong:
680
      case SEQ_SONG_ACTION_SelMixerMap:
681
        if( button <= SEQ_UI_BUTTON_GP8 )
682
          s.action_value = (s.action_value & 0x07) | ((u8)button << 3);
683
        else
684
          s.action_value = (s.action_value & 0xf8) | ((u8)button & 0x7);
685
        SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
758 tk 686
 
1493 tk 687
        // in phrase mode and no song pos selected: fetch patterns immediately
688
        if( !SEQ_SONG_ActiveGet() && s.action != SEQ_SONG_ACTION_JmpSong )
689
          SEQ_SONG_FetchPos(0);
690
        return 1; // value has been changed
758 tk 691
 
1493 tk 692
      case SEQ_SONG_ACTION_Tempo:
693
        s.action_value = 75 + 5*button;
694
        SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
695
 
696
        // in phrase mode and no song pos selected: fetch patterns immediately
697
        if( !SEQ_SONG_ActiveGet() )
698
          SEQ_SONG_FetchPos(0);
699
        return 1; // value has been changed
758 tk 700
 
1493 tk 701
      case SEQ_SONG_ACTION_Mutes:
702
        if( button <= SEQ_UI_BUTTON_GP4 )
703
          s.pattern_g1 = (s.pattern_g1 & 0x0f) ^ (1 << (button&3));
704
        else if( button <= SEQ_UI_BUTTON_GP8 )
705
          s.pattern_g2 = (s.pattern_g2 & 0x0f) ^ (1 << (button&3));
706
        else if( button <= SEQ_UI_BUTTON_GP12 )
707
          s.pattern_g3 = (s.pattern_g3 & 0x0f) ^ (1 << (button&3));
708
        else if( button <= SEQ_UI_BUTTON_GP16 )
709
          s.pattern_g4 = (s.pattern_g4 & 0x0f) ^ (1 << (button&3));
710
        else
711
          return 0; // never reached...
712
        SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
729 tk 713
 
1493 tk 714
        // in phrase mode and no song pos selected: fetch patterns immediately
715
        if( !SEQ_SONG_ActiveGet() )
716
          SEQ_SONG_FetchPos(1);
717
        return 1; // value has been changed
729 tk 718
 
1515 tk 719
      case SEQ_SONG_ACTION_GuideTrack:
720
        if( s.action_value && button == (s.action_value-1) )
721
          s.action_value = 0;
722
        else
723
          s.action_value = button+1;
724
 
725
        SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
726
 
727
        // in phrase mode: change guide track immediately
728
        if( !SEQ_SONG_ActiveGet() )
729
          SEQ_SONG_FetchPos(1);
730
        return 1; // value has been changed
731
 
1493 tk 732
      default:
733
        if( s.action >= SEQ_SONG_ACTION_Loop1 && s.action <= SEQ_SONG_ACTION_Loop16 ) {
734
          u8 val_bank;
735
          switch( ui_selected_item - ITEM_G1 ) {
736
          case 0: val_bank = s.bank_g1; break;
737
          case 1: val_bank = s.bank_g2; break;
738
          case 2: val_bank = s.bank_g3; break;
739
          case 3: val_bank = s.bank_g4; break;
740
          default: return 0; // invalid bank selection
741
          }
729 tk 742
 
1493 tk 743
          u8 val_pattern;
744
          switch( ui_selected_item - ITEM_G1 ) {
745
          case 0: val_pattern = s.pattern_g1; break;
746
          case 1: val_pattern = s.pattern_g2; break;
747
          case 2: val_pattern = s.pattern_g3; break;
748
          case 3: val_pattern = s.pattern_g4; break;
749
          default: return 0; // invalid bank selection
750
          }
729 tk 751
 
1493 tk 752
          if( sel_bank ) {
753
        if( button <= SEQ_UI_BUTTON_GP8 ) {
754
          val_bank = (u8)button;
755
          switch( ui_selected_item - ITEM_G1 ) {
756
          case 0: s.bank_g1 = val_bank; break;
757
          case 1: s.bank_g2 = val_bank; break;
758
          case 2: s.bank_g3 = val_bank; break;
759
          case 3: s.bank_g4 = val_bank; break;
760
          default: return 0; // invalid bank selection
758 tk 761
          }
1493 tk 762
          SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
763
          checkChangePattern(ui_selected_item - ITEM_G1, val_bank, val_pattern);
758 tk 764
        }
1493 tk 765
        return 1; // value has been changed
766
          } else {
767
        if( button <= SEQ_UI_BUTTON_GP8 )
768
          val_pattern = (val_pattern & 0x07) | ((u8)button << 3);
769
        else
770
          val_pattern = (val_pattern & 0x38) | ((u8)button & 0x7);
771
        switch( ui_selected_item - ITEM_G1 ) {
772
        case 0: s.pattern_g1 = val_pattern; break;
773
        case 1: s.pattern_g2 = val_pattern; break;
774
        case 2: s.pattern_g3 = val_pattern; break;
775
        case 3: s.pattern_g4 = val_pattern; break;
776
        default: return 0; // invalid bank selection
777
        }
778
        SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
779
        checkChangePattern(ui_selected_item - ITEM_G1, val_bank, val_pattern);
780
        return 1; // value has been changed
758 tk 781
          }
1493 tk 782
          return 0; // no change
783
        }
784
    }
785
      } break;
401 tk 786
    }
787
  }
788
 
399 tk 789
  switch( button ) {
790
    case SEQ_UI_BUTTON_GP1:
729 tk 791
      if( depressed ) return 0; // ignore when button depressed
399 tk 792
      ui_selected_item = ITEM_SONG;
793
      return 1;
794
 
795
    case SEQ_UI_BUTTON_GP2:
729 tk 796
      if( depressed ) return 0; // ignore when button depressed
399 tk 797
      ui_selected_item = ITEM_POS;
798
      return 1;
799
 
800
    case SEQ_UI_BUTTON_GP3:
1794 tk 801
      if( depressed ) return 0; // ignore when button depressed
399 tk 802
      ui_selected_item = ITEM_ACTION;
803
      return 1;
804
 
805
    case SEQ_UI_BUTTON_GP4:
1794 tk 806
      if( depressed ) return 0; // ignore when button depressed
399 tk 807
      ui_selected_item = ITEM_G1;
808
      return 1;
809
 
810
    case SEQ_UI_BUTTON_GP5:
1794 tk 811
      if( depressed ) return 0; // ignore when button depressed
399 tk 812
      ui_selected_item = ITEM_G2;
813
      return 1;
814
 
815
    case SEQ_UI_BUTTON_GP6:
1794 tk 816
      if( depressed ) return 0; // ignore when button depressed
399 tk 817
      ui_selected_item = ITEM_G3;
818
      return 1;
819
 
820
    case SEQ_UI_BUTTON_GP7:
1794 tk 821
      if( depressed ) return 0; // ignore when button depressed
399 tk 822
      ui_selected_item = ITEM_G4;
823
      return 1;
824
 
825
    case SEQ_UI_BUTTON_GP8:
1794 tk 826
      if( depressed ) return 0; // ignore when button depressed
399 tk 827
      ui_selected_item = ITEM_SEL_BANK;
828
      return 1;
829
 
830
    case SEQ_UI_BUTTON_GP9:
831
    case SEQ_UI_BUTTON_GP10:
729 tk 832
      ui_selected_item = ITEM_MODE;
833
      SEQ_SONG_ActiveSet(SEQ_SONG_ActiveGet() ? 0 : 1);
834
      return 1;
835
 
399 tk 836
    case SEQ_UI_BUTTON_GP11:
837
    case SEQ_UI_BUTTON_GP12:
838
    case SEQ_UI_BUTTON_GP13:
839
    case SEQ_UI_BUTTON_GP14:
840
    case SEQ_UI_BUTTON_GP15:
841
    case SEQ_UI_BUTTON_GP16:
842
      // not mapped
843
      return -1;
844
 
845
    case SEQ_UI_BUTTON_Select:
1794 tk 846
      switch( song_util_page ) {
847
      case SONG_UTIL_PAGE_NONE: {
848
    if( !depressed )
849
      song_util_page = SONG_UTIL_PAGE_SELECT;
850
      } break;
851
 
852
      case SONG_UTIL_PAGE_SELECT: {
853
    if( depressed )
854
      song_util_page = SONG_UTIL_PAGE_NONE;
855
      } break;
856
 
857
      case SONG_UTIL_PAGE_NEW_PATTERN: {
858
    if( !depressed ) // also allows to cancel the operation...
859
      song_util_page = SONG_UTIL_PAGE_SELECT;
860
      } break;
861
      }
729 tk 862
      return 1; // value always changed
863
 
399 tk 864
    case SEQ_UI_BUTTON_Right:
729 tk 865
      if( depressed ) return 0; // ignore when button depressed
399 tk 866
      if( ++ui_selected_item >= NUM_OF_ITEMS )
867
      ui_selected_item = 0;
868
      return 1; // value always changed
869
 
870
    case SEQ_UI_BUTTON_Left:
729 tk 871
      if( depressed ) return 0; // ignore when button depressed
399 tk 872
      if( ui_selected_item == 0 )
873
    ui_selected_item = NUM_OF_ITEMS-1;
1142 tk 874
      else
875
    --ui_selected_item;
876
 
399 tk 877
      return 1; // value always changed
878
 
879
    case SEQ_UI_BUTTON_Up:
729 tk 880
      if( depressed ) return 0; // ignore when button depressed
399 tk 881
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);
882
 
883
    case SEQ_UI_BUTTON_Down:
729 tk 884
      if( depressed ) return 0; // ignore when button depressed
399 tk 885
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
886
  }
887
 
888
  return -1; // invalid or unsupported button
889
}
890
 
891
 
892
/////////////////////////////////////////////////////////////////////////////
893
// Local Display Handler function
894
// IN: <high_prio>: if set, a high-priority LCD update is requested
895
/////////////////////////////////////////////////////////////////////////////
896
static s32 LCD_Handler(u8 high_prio)
897
{
740 tk 898
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
899
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
900
  // <--------------------------------------><-------------------------------------->
1044 tk 901
  //        No Songs available as long as theSession hasn't been created!            
959 tk 902
  //                   Please press EXIT and create a new Session!                   
740 tk 903
 
904
  if( SEQ_FILE_FormattingRequired() ) {
905
    if( high_prio )
906
      return 0;
907
 
908
    SEQ_LCD_CursorSet(0, 0);
1044 tk 909
    SEQ_LCD_PrintString("       No Songs available as long as theSession hasn't been created!            ");
740 tk 910
    SEQ_LCD_CursorSet(0, 1);
959 tk 911
    SEQ_LCD_PrintString("                  Please press EXIT and create a new Session!                   ");
740 tk 912
    return 0;
913
  }
914
 
1794 tk 915
  switch( song_util_page ) {
749 tk 916
 
1794 tk 917
  ///////////////////////////////////////////////////////////////////////////
918
  case SONG_UTIL_PAGE_NONE: {
729 tk 919
    if( high_prio ) {
920
      ///////////////////////////////////////////////////////////////////////////
921
      // frequently update VU meters
922
      u8 track;
923
      seq_core_trk_t *t = &seq_core_trk[0];
924
      for(track=0; track<16; ++t, ++track) {
925
    if( !(track % 4) )
926
      SEQ_LCD_CursorSet(46 + 10*(track>>2), 1);
927
 
1015 tk 928
    if( seq_core_trk_muted & (1 << track) )
729 tk 929
      SEQ_LCD_PrintVBar('M');
930
    else
931
      SEQ_LCD_PrintVBar(t->vu_meter >> 4);
932
      }
399 tk 933
 
729 tk 934
      ///////////////////////////////////////////////////////////////////////////
935
      // Song position
936
      SEQ_LCD_CursorSet(40 + 23, 0);
937
      u32 song_pos = SEQ_SONG_PosGet();
938
      SEQ_LCD_PrintFormattedString("%c%d.", 'A' + (song_pos>>3), (song_pos&7)+1);
939
 
399 tk 940
      if( SEQ_BPM_IsRunning() || ui_seq_pause )
1513 tk 941
    SEQ_LCD_PrintFormattedString("%3d", seq_core_state.ref_step_song + 1);
399 tk 942
      else
729 tk 943
    SEQ_LCD_PrintString("---");
399 tk 944
 
729 tk 945
      ///////////////////////////////////////////////////////////////////////////
946
      // Loop counter
947
      if( SEQ_SONG_ActiveGet() ) {
948
    SEQ_LCD_CursorSet(40 + 35, 0);
399 tk 949
 
729 tk 950
    if( SEQ_BPM_IsRunning() || ui_seq_pause )
951
      SEQ_LCD_PrintFormattedString("%2d", SEQ_SONG_LoopCtrGet()+1);
952
    else
953
      SEQ_LCD_PrintString("--");
399 tk 954
 
729 tk 955
    SEQ_LCD_PrintFormattedString("/%2d", SEQ_SONG_LoopCtrMaxGet()+1);
956
      }
957
    }
1794 tk 958
 
399 tk 959
 
1421 tk 960
    seq_song_step_t s = SEQ_SONG_StepEntryGet(ui_song_edit_pos);
399 tk 961
 
962
 
729 tk 963
    // layout:
964
    // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
965
    // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
966
    // <--------------------------------------><-------------------------------------->
967
    // Song  Pos  Actn  G1   G2   G3   G4  Sel. Song Mode   S#xx  Pos xx.xxx Loop xx/xx
968
    //   1    A1  Stop 1:A1 1:C1 1:E1 1:G1 Pat  1:A1 ____ 1:C1 ____ 1:E1 ____ 1:G1 ____
399 tk 969
 
729 tk 970
    // Song Phrase      G1   G2   G3   G4  Sel.Phrase Mode  S#xx  Pos xx.xxx           
971
    //
399 tk 972
 
729 tk 973
    ///////////////////////////////////////////////////////////////////////////
974
    SEQ_LCD_CursorSet(0, 0);
975
    SEQ_LCD_PrintString("Song  Pos  Actn ");
399 tk 976
    switch( s.action ) {
1421 tk 977
      case SEQ_SONG_ACTION_End:
729 tk 978
        SEQ_LCD_PrintSpaces(24);
979
        break;
980
 
399 tk 981
      case SEQ_SONG_ACTION_JmpPos:
729 tk 982
        SEQ_LCD_PrintString(" ->  Pos.");
983
        SEQ_LCD_PrintSpaces(15);
984
        break;
985
 
399 tk 986
      case SEQ_SONG_ACTION_JmpSong:
729 tk 987
        SEQ_LCD_PrintString(" ->  Song");
988
        SEQ_LCD_PrintSpaces(15);
989
        break;
990
 
399 tk 991
      case SEQ_SONG_ACTION_SelMixerMap:
729 tk 992
        SEQ_LCD_PrintString(" ->  Map");
993
        SEQ_LCD_PrintSpaces(16);
994
        break;
995
 
592 tk 996
      case SEQ_SONG_ACTION_Tempo:
729 tk 997
        SEQ_LCD_PrintString(" ->   BPM  Ramp");
998
        SEQ_LCD_PrintSpaces(9);
999
        break;
1000
 
592 tk 1001
      case SEQ_SONG_ACTION_Mutes:
729 tk 1002
        SEQ_LCD_PrintString(" G1   G2   G3   G4      ");
1003
        break;
1004
 
1515 tk 1005
      case SEQ_SONG_ACTION_GuideTrack:
1006
        SEQ_LCD_PrintString(" -> Guide Track");
1007
        SEQ_LCD_PrintSpaces(9);
1008
        break;
1009
 
399 tk 1010
      default:
729 tk 1011
        if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 )
1012
    SEQ_LCD_PrintSpaces(24);
1013
        else
1014
    SEQ_LCD_PrintString(" G1   G2   G3   G4  Sel.");
399 tk 1015
    }
729 tk 1016
 
1017
    SEQ_LCD_PrintString(SEQ_SONG_ActiveGet() ? " Song Mode " : "Phrase Mode");
1018
    SEQ_LCD_PrintFormattedString("  S#%2d  Pos ", SEQ_SONG_NumGet()+1);
1019
    // (song position print in high_prio branch)
1020
 
1021
    SEQ_LCD_CursorSet(40 + 29, 0);
1022
    if( SEQ_SONG_ActiveGet() ) {
1023
      SEQ_LCD_PrintString(" Loop ");
1024
      // (loop counter print in high_prio branch)
1025
    } else
399 tk 1026
      SEQ_LCD_PrintSpaces(12);
729 tk 1027
 
1028
 
1029
    ///////////////////////////////////////////////////////////////////////////
1030
    SEQ_LCD_CursorSet(0, 1);
1031
 
1032
    if( ui_selected_item == ITEM_SONG && ui_cursor_flash ) {
1033
      SEQ_LCD_PrintSpaces(3);
1034
    } else {
1035
      SEQ_LCD_PrintFormattedString("%3d", SEQ_SONG_NumGet() + 1);
1036
    }
1037
    SEQ_LCD_PrintSpaces(4);
1038
 
1039
    ///////////////////////////////////////////////////////////////////////////
1040
    if( ui_selected_item == ITEM_POS && ui_cursor_flash ) {
1041
      SEQ_LCD_PrintSpaces(2);
1042
    } else {
1421 tk 1043
      SEQ_LCD_PrintFormattedString("%c%d", 'A' + (ui_song_edit_pos >> 3), (ui_song_edit_pos&7)+1);
729 tk 1044
    }
1045
    SEQ_LCD_PrintSpaces(1);
1046
 
1047
    ///////////////////////////////////////////////////////////////////////////
1048
    if( ui_selected_item == ITEM_ACTION && ui_cursor_flash ) {
399 tk 1049
      SEQ_LCD_PrintSpaces(5);
729 tk 1050
    } else {
1051
      switch( s.action ) {
1421 tk 1052
        case SEQ_SONG_ACTION_End:
1053
      SEQ_LCD_PrintString(" End ");
758 tk 1054
      break;
729 tk 1055
 
1056
        case SEQ_SONG_ACTION_JmpPos:
1057
        case SEQ_SONG_ACTION_JmpSong:
758 tk 1058
      SEQ_LCD_PrintString(" Jump");
1059
      break;
729 tk 1060
 
1061
        case SEQ_SONG_ACTION_SelMixerMap:
758 tk 1062
      SEQ_LCD_PrintString("Mixer");
1063
      break;
729 tk 1064
 
1065
        case SEQ_SONG_ACTION_Tempo:
758 tk 1066
      SEQ_LCD_PrintString("Tempo");
1067
      break;
729 tk 1068
 
1069
        case SEQ_SONG_ACTION_Mutes:
758 tk 1070
      SEQ_LCD_PrintString("Mutes");
1071
      break;
729 tk 1072
 
1515 tk 1073
        case SEQ_SONG_ACTION_GuideTrack:
1074
      SEQ_LCD_PrintString(" G.T.");
1075
      break;
1076
 
729 tk 1077
        default:
758 tk 1078
      if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 )
1079
        SEQ_LCD_PrintString(" ????");
1080
      else
1081
        SEQ_LCD_PrintFormattedString(" x%2d ", (int)(s.action-SEQ_SONG_ACTION_Loop1+1));
399 tk 1082
      }
729 tk 1083
    }
1084
    SEQ_LCD_PrintSpaces(1);
1085
 
1086
    ///////////////////////////////////////////////////////////////////////////
1087
    switch( s.action ) {
1421 tk 1088
      case SEQ_SONG_ACTION_End:
729 tk 1089
        SEQ_LCD_PrintSpaces(20);
1090
        break;
1091
 
1092
      case SEQ_SONG_ACTION_JmpPos:
1093
        SEQ_LCD_PrintSpaces(6);
1094
        if( ui_selected_item >= ITEM_G1 && ui_selected_item <= ITEM_G4 && ui_cursor_flash ) {
758 tk 1095
      SEQ_LCD_PrintSpaces(2);
729 tk 1096
        } else {
758 tk 1097
      SEQ_LCD_PrintFormattedString("%c%d", 'A' + (s.action_value >> 3), (s.action_value&7)+1);
729 tk 1098
        }
1099
        SEQ_LCD_PrintSpaces(12);
1100
        break;
1101
 
1102
      case SEQ_SONG_ACTION_JmpSong:
1103
      case SEQ_SONG_ACTION_SelMixerMap:
1104
        SEQ_LCD_PrintSpaces(5);
1105
        if( ui_selected_item >= ITEM_G1 && ui_selected_item <= ITEM_G4 && ui_cursor_flash ) {
758 tk 1106
      SEQ_LCD_PrintSpaces(3);
729 tk 1107
        } else {
758 tk 1108
      SEQ_LCD_PrintFormattedString("%3d", s.action_value + 1);
729 tk 1109
        }
1110
        SEQ_LCD_PrintSpaces(12);
1111
        break;
1112
 
1113
      case SEQ_SONG_ACTION_Tempo:
1114
        SEQ_LCD_PrintSpaces(6);
1115
        if( ui_selected_item >= ITEM_G1 && ui_selected_item <= ITEM_G2 && ui_cursor_flash ) {
758 tk 1116
      SEQ_LCD_PrintSpaces(3);
729 tk 1117
        } else {
758 tk 1118
      SEQ_LCD_PrintFormattedString("%3d", s.action_value);
729 tk 1119
        }
1120
 
1121
        if( ui_selected_item >= ITEM_G3 && ui_selected_item <= ITEM_G4 && ui_cursor_flash ) {
758 tk 1122
      SEQ_LCD_PrintSpaces(7);
729 tk 1123
        } else {
758 tk 1124
      SEQ_LCD_PrintFormattedString("   %3ds", s.pattern_g1);
729 tk 1125
        }
1126
 
1127
        SEQ_LCD_PrintSpaces(4);
1128
        break;
1129
 
1130
      case SEQ_SONG_ACTION_Mutes:
1131
        if( ui_selected_item == ITEM_G1 && ui_cursor_flash ) {
758 tk 1132
      SEQ_LCD_PrintSpaces(4);
729 tk 1133
        } else {
758 tk 1134
      int i;
1135
      for(i=0; i<4; ++i)
1136
        SEQ_LCD_PrintChar((s.pattern_g1 & (1 << i)) ? '*' : 'o');
729 tk 1137
        }
1138
        SEQ_LCD_PrintSpaces(1);
1139
 
1140
        if( ui_selected_item == ITEM_G2 && ui_cursor_flash ) {
758 tk 1141
      SEQ_LCD_PrintSpaces(4);
729 tk 1142
        } else {
758 tk 1143
      int i;
1144
      for(i=0; i<4; ++i)
1145
        SEQ_LCD_PrintChar((s.pattern_g2 & (1 << i)) ? '*' : 'o');
729 tk 1146
        }
1147
        SEQ_LCD_PrintSpaces(1);
1148
 
1149
        if( ui_selected_item == ITEM_G3 && ui_cursor_flash ) {
758 tk 1150
      SEQ_LCD_PrintSpaces(4);
729 tk 1151
        } else {
758 tk 1152
      int i;
1153
      for(i=0; i<4; ++i)
1154
        SEQ_LCD_PrintChar((s.pattern_g3 & (1 << i)) ? '*' : 'o');
729 tk 1155
        }
1156
        SEQ_LCD_PrintSpaces(1);
1157
 
1158
        if( ui_selected_item == ITEM_G4 && ui_cursor_flash ) {
758 tk 1159
      SEQ_LCD_PrintSpaces(4);
729 tk 1160
        } else {
758 tk 1161
      int i;
1162
      for(i=0; i<4; ++i)
1163
        SEQ_LCD_PrintChar((s.pattern_g4 & (1 << i)) ? '*' : 'o');
729 tk 1164
        }
1165
        SEQ_LCD_PrintSpaces(5);
1166
        break;
1167
 
1515 tk 1168
      case SEQ_SONG_ACTION_GuideTrack:
1169
        SEQ_LCD_PrintSpaces(5);
1170
        if( ui_selected_item >= ITEM_G1 && ui_selected_item <= ITEM_G4 && ui_cursor_flash ) {
1171
      SEQ_LCD_PrintSpaces(4);
1172
        } else {
1173
      if( s.action_value )
1516 tk 1174
        SEQ_LCD_PrintGxTy((s.action_value-1)/4, (1 << (s.action_value-1)));
1515 tk 1175
      else
1176
        SEQ_LCD_PrintString("----");
1177
        }
1178
        SEQ_LCD_PrintSpaces(11);
1179
        break;
1180
 
729 tk 1181
      default:
1182
        if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 )
758 tk 1183
      SEQ_LCD_PrintSpaces(20);
729 tk 1184
        else {
1185
    if( ui_selected_item == ITEM_G1 && ui_cursor_flash )
1186
      SEQ_LCD_PrintSpaces(5);
1187
    else if( s.pattern_g1 >= 0x80 )
1188
      SEQ_LCD_PrintString("-:-- ");
1189
    else
1190
      SEQ_LCD_PrintFormattedString("%x:%c%d ", s.bank_g1+1, 'A' + (s.pattern_g1>>3), (s.pattern_g1&7)+1);
1191
 
1192
    if( ui_selected_item == ITEM_G2 && ui_cursor_flash )
1193
      SEQ_LCD_PrintSpaces(5);
1194
    else if( s.pattern_g2 >= 0x80 )
1195
      SEQ_LCD_PrintString("-:-- ");
1196
    else
1197
      SEQ_LCD_PrintFormattedString("%x:%c%d ", s.bank_g2+1, 'A' + (s.pattern_g2>>3), (s.pattern_g2&7)+1);
1198
 
1199
    if( ui_selected_item == ITEM_G3 && ui_cursor_flash )
1200
      SEQ_LCD_PrintSpaces(5);
1201
    else if( s.pattern_g3 >= 0x80 )
1202
      SEQ_LCD_PrintString("-:-- ");
1203
    else
1204
      SEQ_LCD_PrintFormattedString("%x:%c%d ", s.bank_g3+1, 'A' + (s.pattern_g3>>3), (s.pattern_g3&7)+1);
1205
 
1206
    if( ui_selected_item == ITEM_G4 && ui_cursor_flash )
1207
      SEQ_LCD_PrintSpaces(5);
1208
    else if( s.pattern_g4 >= 0x80 )
1209
      SEQ_LCD_PrintString("-:-- ");
1210
    else
1211
      SEQ_LCD_PrintFormattedString("%x:%c%d ", s.bank_g4+1, 'A' + (s.pattern_g4>>3), (s.pattern_g4&7)+1);
1212
        }
1213
    }
1214
 
1215
    ///////////////////////////////////////////////////////////////////////////
1216
    if( (s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16) ||
1217
        (ui_selected_item == ITEM_SEL_BANK && ui_cursor_flash) ) {
592 tk 1218
      SEQ_LCD_PrintSpaces(4);
729 tk 1219
    } else {
1220
      SEQ_LCD_PrintFormattedString(sel_bank ? "Bnk " : "Pat ", 0);
1221
    }
1222
 
1223
    ///////////////////////////////////////////////////////////////////////////
1224
    int group;
1225
    for(group=0; group<4; ++group) {
1226
      SEQ_LCD_CursorSet(40 + 10*group, 1);
1227
 
1493 tk 1228
      seq_pattern_t pattern = ui_cursor_flash ? seq_pattern_req[group] : seq_pattern[group];
729 tk 1229
      SEQ_LCD_PrintFormattedString(" %d:", pattern.bank + 1);
1230
 
1231
      if( pattern.pattern < SEQ_FILE_B_NumPatterns(pattern.bank) )
1232
        SEQ_LCD_PrintPattern(pattern);
1233
      else
1234
        SEQ_LCD_PrintString("!!"); // covers the case that bank is not available, or that pattern number too high
1235
 
1493 tk 1236
      if( seq_pattern_req[group].pattern != seq_pattern[group].pattern ||
1237
      seq_pattern_req[group].bank != seq_pattern[group].bank )
1238
    SEQ_LCD_PrintChar('*');
1239
      else
1240
    SEQ_LCD_PrintChar(' ');
729 tk 1241
 
1242
      // (VU meters print in high_prio branch)
1243
 
1244
    }
1794 tk 1245
  } break;
1246
 
1247
  ///////////////////////////////////////////////////////////////////////////
1248
  case SONG_UTIL_PAGE_SELECT: {
1249
 
1250
    if( high_prio )
1251
      return 0;
1252
 
1253
    // layout:
1254
    // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
1255
    // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1256
    // <--------------------------------------><-------------------------------------->
1257
    // Song  Pos     Utility Functions         Phrase              TakeOver  Save&Take 
1258
    //   1    A1  Copy Paste Clr Ins. Del.      Mode               Patterns  Over Ptns.
1259
 
1260
    // Song  Pos     Utility Functions          Song   GuideTrack  TakeOver  Save&Take 
1261
    //   1    A1  Copy Paste Clr Ins. Del.      Mode      G1T1     Patterns  Over Ptns.
1262
 
1263
    SEQ_LCD_CursorSet(0, 0);
1264
    SEQ_LCD_PrintFormattedString("Song  Pos    Utility Functions  ");
1265
    if( (in_menu_msg & 0x80) || ((in_menu_msg & 0x7f) && ui_hold_msg_ctr) ) {
1266
      SEQ_LCD_PrintString((char *)in_menu_msg_str[(in_menu_msg & 0x7f)-1]);
1267
    } else {
1268
      SEQ_LCD_PrintSpaces(8);
1269
    }
1270
 
1271
    if( SEQ_SONG_ActiveGet() ) {
1272
      SEQ_LCD_PrintString(" Song   GuideTrack  TakeOver  Save&Take ");
1273
    } else {
1274
      SEQ_LCD_PrintString("Phrase              TakeOver  Save&Take ");
1275
    }
1276
 
1277
    ///////////////////////////////////////////////////////////////////////////
1278
    SEQ_LCD_CursorSet(0, 1);
1279
 
1280
    if( ui_selected_item == ITEM_SONG && ui_cursor_flash ) {
1281
      SEQ_LCD_PrintSpaces(3);
1282
    } else {
1283
      SEQ_LCD_PrintFormattedString("%3d", SEQ_SONG_NumGet() + 1);
1284
    }
1285
    SEQ_LCD_PrintSpaces(4);
1286
 
1287
    ///////////////////////////////////////////////////////////////////////////
1288
    if( ui_selected_item == ITEM_POS && ui_cursor_flash ) {
1289
      SEQ_LCD_PrintSpaces(2);
1290
    } else {
1291
      SEQ_LCD_PrintFormattedString("%c%d", 'A' + (ui_song_edit_pos >> 3), (ui_song_edit_pos&7)+1);
1292
    }
1293
 
1294
    ///////////////////////////////////////////////////////////////////////////
1295
    SEQ_LCD_PrintFormattedString("  Copy Paste Clr Ins. Del.     ");
1296
    SEQ_LCD_PrintString(" Mode      ");
1297
    if( SEQ_SONG_ActiveGet() ) {
1298
      if( SEQ_SONG_GuideTrackGet() ) {
1299
    u8 track = SEQ_SONG_GuideTrackGet()-1;
1300
    SEQ_LCD_PrintGxTy(track / 4, (1 << track));
1301
      } else
1302
    SEQ_LCD_PrintString("----");
1303
    } else {
1304
      SEQ_LCD_PrintSpaces(4);
1305
    }
1306
    SEQ_LCD_PrintString("     Patterns  Over Ptns.");
1307
  } break;
1308
 
1309
 
1310
  ///////////////////////////////////////////////////////////////////////////
1311
  case SONG_UTIL_PAGE_NEW_PATTERN: {
1312
 
1313
    if( high_prio )
1314
      return 0;
1315
 
1316
    // layout:
1317
    // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
1318
    // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1319
    // <--------------------------------------><-------------------------------------->
1320
    // This function will store your current   Mutes, Mixer Map and Patterns into      
1321
    // predefined bank positions, and insert   references into the selected Phrase Slot
1322
 
1323
    // Please select Phrase Slot (* indicates, that the slot is already allocated)     
1324
    //   A    B    C    D    E    F    G    H    I    J    K    L    M    N    O    P  
1325
 
1326
    if( seq_ui_button_state.SELECT_PRESSED ) {
1327
      SEQ_LCD_CursorSet(0, 0);
1328
      SEQ_LCD_PrintString("This function will store your current   Mutes, Mixer Map and Patterns into      ");
1329
      SEQ_LCD_CursorSet(0, 1);
1330
      SEQ_LCD_PrintString("predefined bank positions, and insert   references into the selected Phrase Slot");
1331
    } else {
1332
      SEQ_LCD_CursorSet(0, 0);
1333
      SEQ_LCD_PrintString("Please select Phrase Slot (* indicates, that the slot is already allocated)     ");
1334
      SEQ_LCD_CursorSet(0, 1);
1335
 
1336
      int i;
1337
      for(i=0; i<16; ++i) {
1338
    seq_song_step_t entry = SEQ_SONG_StepEntryGet(i*8);
1339
    u8 allocated = entry.action != SEQ_SONG_ACTION_End;
1340
    SEQ_LCD_PrintFormattedString("  %c%c ", 'A'+i, allocated ? '*' : ' ');
1341
 
1342
    if( allocated )
1343
      song_util_page_new_pattern__led_pattern |= (1 << i);
1344
    else
1345
      song_util_page_new_pattern__led_pattern &= ~(1 << i);
1346
      }
1347
    }
1348
  } break;
399 tk 1349
  }
1350
 
1351
  return 0; // no error
1352
}
1353
 
1354
 
1355
/////////////////////////////////////////////////////////////////////////////
401 tk 1356
// Local exit function
1357
/////////////////////////////////////////////////////////////////////////////
1358
static s32 EXIT_Handler(void)
1359
{
1360
  // save song (function exits automatically if no position has been changed)
1361
  SEQ_SONG_Save(SEQ_SONG_NumGet());
690 tk 1362
 
1363
  return 0; // no error
401 tk 1364
}
1365
 
1366
 
1367
/////////////////////////////////////////////////////////////////////////////
399 tk 1368
// Initialisation
1369
/////////////////////////////////////////////////////////////////////////////
1370
s32 SEQ_UI_SONG_Init(u32 mode)
1371
{
1372
  // install callback routines
1373
  SEQ_UI_InstallButtonCallback(Button_Handler);
1374
  SEQ_UI_InstallEncoderCallback(Encoder_Handler);
1375
  SEQ_UI_InstallLEDCallback(LED_Handler);
1376
  SEQ_UI_InstallLCDCallback(LCD_Handler);
401 tk 1377
  SEQ_UI_InstallExitCallback(EXIT_Handler);
399 tk 1378
 
1379
  // we want to show vertical VU meters
1380
  SEQ_LCD_InitSpecialChars(SEQ_LCD_CHARSET_VBars);
1381
 
729 tk 1382
 
1383
  // change pattern numbers by default and don't show util page
399 tk 1384
  sel_bank = 0;
729 tk 1385
  in_menu_msg = MSG_DEFAULT;
1386
  ui_hold_msg_ctr = 0;
1794 tk 1387
  song_util_page = 0;
399 tk 1388
 
401 tk 1389
  // always start with "pos" item (especially useful in phrase mode for quick selection)
1390
  ui_selected_item = ITEM_POS;
1391
 
729 tk 1392
  // disabled: don't change previous settings (values will be initialized with 0 by gcc)
1393
  // SEQ_SONG_NumSet(0);
1394
 
1395
  // copypaste_buffer_filled = 0;
1396
 
399 tk 1397
  return 0; // no error
1398
}
1399
 
1400
 
1401
/////////////////////////////////////////////////////////////////////////////
1402
// Change pattern immediately if in phrase mode or song position matches
1403
// with edit position
1404
/////////////////////////////////////////////////////////////////////////////
1421 tk 1405
static s32 checkChangePattern(u8 group, u8 bank, u8 pattern)
399 tk 1406
{
1421 tk 1407
  if( pattern < 0x80 && (!SEQ_SONG_ActiveGet() || ui_song_edit_pos == SEQ_SONG_PosGet()) ) {
399 tk 1408
    seq_pattern_t p;
1409
    p.ALL = 0;
1410
    p.pattern = pattern;
1411
    p.bank = bank;
1117 tk 1412
    return SEQ_PATTERN_Change(group, p, 0);
399 tk 1413
  }
1414
 
1415
  return 0; // no error
1416
}
1417
 
1421 tk 1418
/////////////////////////////////////////////////////////////////////////////
1794 tk 1419
// Copy current pattern numbers into song position
1421 tk 1420
/////////////////////////////////////////////////////////////////////////////
1421
static s32 takeoverCurrentPatterns(void)
1422
{
1423
  seq_song_step_t s = SEQ_SONG_StepEntryGet(ui_song_edit_pos);
729 tk 1424
 
1421 tk 1425
  if( s.action < SEQ_SONG_ACTION_Loop1 || s.action > SEQ_SONG_ACTION_Loop16 )
1426
    s.action = SEQ_SONG_ACTION_Loop1;
1427
  s.pattern_g1 = seq_pattern[0].pattern;
1428
  s.bank_g1 = seq_pattern[0].bank;
1429
  s.pattern_g2 = seq_pattern[1].pattern;
1430
  s.bank_g2 = seq_pattern[1].bank;
1431
  s.pattern_g3 = seq_pattern[2].pattern;
1432
  s.bank_g3 = seq_pattern[2].bank;
1433
  s.pattern_g4 = seq_pattern[3].pattern;
1434
  s.bank_g4 = seq_pattern[3].bank;
729 tk 1435
 
1421 tk 1436
  SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
1794 tk 1437
  SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 2000, "Patterns", "taken over!");
1421 tk 1438
 
1439
  return 0; // no error
1440
}
1441
 
1442
 
729 tk 1443
/////////////////////////////////////////////////////////////////////////////
1794 tk 1444
// Create new mixer map and patterns, store together with mutes into song position
1445
/////////////////////////////////////////////////////////////////////////////
1446
static s32 createNewPatterns(u8 slot)
1447
{
1448
  // new song edit pos depending on slot
1449
  ui_song_edit_pos = 8*slot;
1450
 
1451
  // 1st Step: Mutes
1452
  {
1453
    seq_song_step_t s = SEQ_SONG_StepEntryGet(ui_song_edit_pos);
1454
    s.action = SEQ_SONG_ACTION_Mutes;
1455
    s.action_value = 0;
1456
    s.pattern_g1 = (seq_core_trk_muted >>  0) & 0xf;
1457
    s.pattern_g2 = (seq_core_trk_muted >>  4) & 0xf;
1458
    s.pattern_g3 = (seq_core_trk_muted >>  8) & 0xf;
1459
    s.pattern_g4 = (seq_core_trk_muted >> 12) & 0xf;
1460
    s.bank_g1 = 0;
1461
    s.bank_g2 = 1;
1462
    s.bank_g3 = 2;
1463
    s.bank_g4 = 3;
1464
    SEQ_SONG_StepEntrySet(ui_song_edit_pos, s);
1465
  }
1466
 
1467
  // 2nd Step: Mixer Map
1468
  {
1469
    // set & store mixer map
1470
    SEQ_MIXER_NumSet(slot);
1471
    SEQ_MIXER_Save(slot);
1472
 
1473
    // store in step
1474
    seq_song_step_t s = SEQ_SONG_StepEntryGet(ui_song_edit_pos+1);
1475
    s.action = SEQ_SONG_ACTION_SelMixerMap;
1476
    s.action_value = SEQ_MIXER_NumGet();
1477
    s.pattern_g1 = 0;
1478
    s.pattern_g2 = 0;
1479
    s.pattern_g3 = 0;
1480
    s.pattern_g4 = 0;
1481
    s.bank_g1 = 0;
1482
    s.bank_g2 = 1;
1483
    s.bank_g3 = 2;
1484
    s.bank_g4 = 3;
1485
    SEQ_SONG_StepEntrySet(ui_song_edit_pos+1, s);
1486
  }
1487
 
1488
  // 3rd Step: Pattern Set
1489
  {
1490
    // store patterns into new bank slots
1491
    {
1492
      int group;
1493
      for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group) {
1494
    seq_pattern_t save_pattern;
1495
    save_pattern = seq_pattern[group];
1496
    save_pattern.pattern = slot;
1497
    save_pattern.bank = group;
1498
    SEQ_PATTERN_Save(group, save_pattern);
1499
    seq_pattern[group] = save_pattern; // take over immediately
1500
      }
1501
    }
1502
 
1503
    seq_song_step_t s = SEQ_SONG_StepEntryGet(ui_song_edit_pos+2);
1504
    s.action = SEQ_SONG_ACTION_Loop1;
1505
    s.action_value = 0;
1506
    s.pattern_g1 = seq_pattern[0].pattern;
1507
    s.bank_g1 = seq_pattern[0].bank;
1508
    s.pattern_g2 = seq_pattern[1].pattern;
1509
    s.bank_g2 = seq_pattern[1].bank;
1510
    s.pattern_g3 = seq_pattern[2].pattern;
1511
    s.bank_g3 = seq_pattern[2].bank;
1512
    s.pattern_g4 = seq_pattern[3].pattern;
1513
    s.bank_g4 = seq_pattern[3].bank;
1514
    SEQ_SONG_StepEntrySet(ui_song_edit_pos+2, s);
1515
  }
1516
 
1517
  // 4th Step: Jump to previous step
1518
  {
1519
    seq_song_step_t s = SEQ_SONG_StepEntryGet(ui_song_edit_pos+3);
1520
    s.action = SEQ_SONG_ACTION_JmpPos;
1521
    s.action_value = ui_song_edit_pos+2;
1522
    s.pattern_g1 = 0;
1523
    s.pattern_g2 = 0;
1524
    s.pattern_g3 = 0;
1525
    s.pattern_g4 = 0;
1526
    s.bank_g1 = 0;
1527
    s.bank_g2 = 1;
1528
    s.bank_g3 = 2;
1529
    s.bank_g4 = 3;
1530
    SEQ_SONG_StepEntrySet(ui_song_edit_pos+3, s);
1531
  }
1532
 
1533
  // print message
1534
  SEQ_UI_Msg((slot >= 8) ? SEQ_UI_MSG_USER_R : SEQ_UI_MSG_USER, 2000, "Created Mutes,", "Mixer Map and Patterns!");
1535
 
1536
  return 0; // no error
1537
}
1538
 
1539
 
1540
/////////////////////////////////////////////////////////////////////////////
729 tk 1541
// Copy Song Position
1542
/////////////////////////////////////////////////////////////////////////////
1543
s32 SEQ_UI_SONG_Copy(void)
1544
{
1421 tk 1545
  copypaste_buffer = SEQ_SONG_StepEntryGet(ui_song_edit_pos);
729 tk 1546
 
1547
  // notify that copy&paste buffer is filled
1548
  copypaste_buffer_filled = 1;
1549
 
1550
  return 0; // no error
1551
}
1552
 
1553
/////////////////////////////////////////////////////////////////////////////
1554
// Paste Song Position
1555
/////////////////////////////////////////////////////////////////////////////
1556
s32 SEQ_UI_SONG_Paste(void)
1557
{
1558
  // branch to clear function if copy&paste buffer not filled
1559
  if( !copypaste_buffer_filled )
1560
    return SEQ_UI_SONG_Clear();
1561
 
1421 tk 1562
  SEQ_SONG_StepEntrySet(ui_song_edit_pos, copypaste_buffer);
729 tk 1563
 
1564
  return 0; // no error
1565
}
1566
 
1567
/////////////////////////////////////////////////////////////////////////////
1568
// Clear Song Position
1569
/////////////////////////////////////////////////////////////////////////////
1570
s32 SEQ_UI_SONG_Clear(void)
1571
{
1572
  // already available in SEQ_SONG layer
1421 tk 1573
  return SEQ_SONG_StepEntryClear(ui_song_edit_pos);
729 tk 1574
}
1575
 
1576
/////////////////////////////////////////////////////////////////////////////
1577
// Insert Song Position
1578
/////////////////////////////////////////////////////////////////////////////
1579
s32 SEQ_UI_SONG_Insert(void)
1580
{
1581
  int step;
1582
 
1421 tk 1583
  if( ui_song_edit_pos < (SEQ_SONG_NUM_STEPS-1) ) {
1584
    for(step=SEQ_SONG_NUM_STEPS-1; step>ui_song_edit_pos; --step)
729 tk 1585
      SEQ_SONG_StepEntrySet(step, SEQ_SONG_StepEntryGet(step-1));
1586
  }
1421 tk 1587
  SEQ_SONG_StepEntryClear(ui_song_edit_pos);
729 tk 1588
 
1589
  return 0; // no error
1590
}
1591
 
1592
/////////////////////////////////////////////////////////////////////////////
1593
// Delete Song Position
1594
/////////////////////////////////////////////////////////////////////////////
1595
s32 SEQ_UI_SONG_Delete(void)
1596
{
1597
  int step;
1598
 
1421 tk 1599
  if( ui_song_edit_pos < (SEQ_SONG_NUM_STEPS-1) ) {
1600
    for(step=ui_song_edit_pos; step<(SEQ_SONG_NUM_STEPS-1); ++step)
729 tk 1601
      SEQ_SONG_StepEntrySet(step, SEQ_SONG_StepEntryGet(step+1));
1602
  }
1603
  SEQ_SONG_StepEntryClear(SEQ_SONG_NUM_STEPS-1);
1604
 
1605
  return 0; // no error
1606
}
752 tk 1607
 
1608
 
1609
/////////////////////////////////////////////////////////////////////////////
1610
// Set Edit Position
1611
/////////////////////////////////////////////////////////////////////////////
1612
s32 SEQ_UI_SONG_EditPosSet(u8 new_edit_pos)
1613
{
1421 tk 1614
  ui_song_edit_pos = new_edit_pos;
752 tk 1615
 
1616
  return 0; // no error
1617
}