/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
    if( depressed ) return 0; // ignore when button depressed

    if( button <= SEQ_UI_BUTTON_GP16 ) {
        // -> forward to encoder handler
        return Encoder_Handler((int)button, 0);
    }

    switch( button ) {
    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
        if( ++ui_selected_item >= NUM_OF_ITEMS )
            ui_selected_item = 0;
        return 1; // value always changed

    case SEQ_UI_BUTTON_Left:
        if( ui_selected_item == 0 )
            ui_selected_item = NUM_OF_ITEMS-1;
        else
            --ui_selected_item;
        return 1; // value always changed

    case SEQ_UI_BUTTON_Up:
        return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Down:
        return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
    }

    return -1; // invalid or unsupported button
}
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return 0; // ignore when button depressed

  switch( button ) {
    case SEQ_UI_BUTTON_GP1:
      ui_selected_item = ITEM_GXTY;
      return 0; // value hasn't been changed

    case SEQ_UI_BUTTON_GP2:
    case SEQ_UI_BUTTON_GP3:
      ui_selected_item = ITEM_LENGTH;
      return 0; // value hasn't been changed

    case SEQ_UI_BUTTON_GP4:
    case SEQ_UI_BUTTON_GP5:
      ui_selected_item = ITEM_LOOP;
      return 0; // value hasn't been changed

    case SEQ_UI_BUTTON_GP6:
      return 0; // not mapped

    case SEQ_UI_BUTTON_GP7:
    case SEQ_UI_BUTTON_GP8:
      // toggle quicksel mode
      return Encoder_Handler((int)button, (quicksel_mode == QUICKSEL_MODE_LENGTH) ? 1 : -1);

    case SEQ_UI_BUTTON_GP9:
    case SEQ_UI_BUTTON_GP10:
    case SEQ_UI_BUTTON_GP11:
    case SEQ_UI_BUTTON_GP12:
    case SEQ_UI_BUTTON_GP13:
    case SEQ_UI_BUTTON_GP14:
    case SEQ_UI_BUTTON_GP15:
    case SEQ_UI_BUTTON_GP16:
      return Encoder_Handler((int)button, 1);

    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
      if( ++ui_selected_item >= NUM_OF_ITEMS )
	ui_selected_item = 0;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Left:
      if( ui_selected_item == 0 )
	ui_selected_item = NUM_OF_ITEMS-1;
      else
	--ui_selected_item;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Up:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Down:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( button <= SEQ_UI_BUTTON_GP16 ) {
    if( !seq_midi_in_options[selected_bus].MODE_PLAY )
      return -1;

    u8 visible_track = SEQ_UI_VisibleTrackGet();
    mios32_midi_package_t p;

    if( depressed )
      gp_button_pressed &= ~(1 << button);
    else
      gp_button_pressed |= (1 << button);

    p.type = NoteOn;
    p.event = NoteOn;
    p.chn = Chn1; // will be overruled anyhow by SEQ_LIVE_PlayEvent()
    p.note = 0x30 + (u8)button;
    p.velocity = depressed ? 0x00 : seq_live_options.VELOCITY;
    SEQ_LIVE_PlayEvent(visible_track, p);
    return 0;
  }

  // exit if button depressed
  if( depressed )
    return -1;

  // remaining buttons:
  switch( button ) {
    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
      if( ++ui_selected_item >= NUM_OF_ITEMS )
	ui_selected_item = 0;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Left:
      if( ui_selected_item == 0 )
	ui_selected_item = NUM_OF_ITEMS-1;
      else
	--ui_selected_item;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Up:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Down:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}
Exemple #4
0
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed )
    return 0;

  if( button <= SEQ_UI_BUTTON_GP16 )
    return Encoder_Handler((seq_ui_encoder_t)button, 0);

  return -1; // invalid or unsupported button
}
Exemple #5
0
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return 0; // ignore when button depressed

  // GP button selects preset
  if( button <= SEQ_UI_BUTTON_GP16 ) {
    // GP1/2 toggles metronome function
    if( button == SEQ_UI_BUTTON_GP1 || button == SEQ_UI_BUTTON_GP2 )
      seq_core_state.METRONOME ^= 1;

    // re-use encoder function
    return Encoder_Handler(button, 0);
  }

  switch( button ) {
    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
      if( ++ui_selected_item >= NUM_OF_ITEMS )
	ui_selected_item = 0;

      return 1; // value always changed

    case SEQ_UI_BUTTON_Left:
      if( ui_selected_item == 0 )
	ui_selected_item = NUM_OF_ITEMS-1;
      else
	--ui_selected_item;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Up:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Down:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}
Exemple #6
0
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return 0; // ignore when button depressed

  // reset tap tempo if any button != GP16 has been pressed
  if( button != SEQ_UI_BUTTON_GP16 )
    resetTapTempo();

#if 0
  // leads to: comparison is always true due to limited range of data type
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
#else
  if( button <= SEQ_UI_BUTTON_GP16 ) {
#endif
    switch( button ) {
      case SEQ_UI_BUTTON_GP6:
      case SEQ_UI_BUTTON_GP7:
	// fire preset
	SEQ_CORE_BPM_Update(seq_core_bpm_preset_tempo[seq_core_bpm_preset_num], seq_core_bpm_preset_ramp[seq_core_bpm_preset_num]);
	return 1;

      case SEQ_UI_BUTTON_GP8:
	// enter preset selection page
	SEQ_UI_PageSet(SEQ_UI_PAGE_BPM_PRESETS);
	return 1;
    }

    // re-use encoder handler - only select UI item, don't increment
    return Encoder_Handler((int)button, 0);
  }

  // remaining buttons:
  switch( button ) {
    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
      if( ++ui_selected_item >= NUM_OF_ITEMS )
	ui_selected_item = 0;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Left:
      if( ui_selected_item == 0 )
	ui_selected_item = NUM_OF_ITEMS-1;
      else
	--ui_selected_item;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Up:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Down:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  if( high_prio )
    return 0; // there are no high-priority updates

  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  //  Mode Preset Tempo  Ramp    Fire  Preset  MClk In/Out              Ext.    Tap 
  // Master   1   140.0   1s    Preset  Page USB1 I:on O:off           Restart Tempo

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 0);
  SEQ_LCD_PrintString(" Mode Preset Tempo  Ramp    Fire  Preset  MClk In/Out               ");
  SEQ_LCD_PrintString(seq_core_state.EXT_RESTART_REQ ? "Ongoing" : " Ext.  ");
  SEQ_LCD_PrintString(" Tap ");


  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 1);

  if( ui_selected_item == ITEM_MODE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(6);
  } else {
    const char mode_str[3][7] = { " Auto ", "Master", "Slave "};
    SEQ_LCD_PrintString((char *)mode_str[SEQ_BPM_ModeGet()]);
  }
  SEQ_LCD_PrintSpaces(2);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_PRESET && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(2);
  } else {
    SEQ_LCD_PrintFormattedString("%2d", seq_core_bpm_preset_num+1);
  }
  SEQ_LCD_PrintSpaces(3);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_BPM && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    float bpm = seq_core_bpm_preset_tempo[seq_core_bpm_preset_num];
    SEQ_LCD_PrintFormattedString("%3d.%d", (int)bpm, (int)(10*bpm)%10);
  }
  SEQ_LCD_PrintSpaces(2);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_RAMP && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(3);
  } else {
    float ramp = seq_core_bpm_preset_ramp[seq_core_bpm_preset_num];
    SEQ_LCD_PrintFormattedString("%2ds", (int)ramp);
  }

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_PrintString("    Preset  Page  ");

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_MCLK_PORT && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintString(SEQ_MIDI_PORT_ClkNameGet(SEQ_MIDI_PORT_ClkIxGet(selected_mclk_port)));
  }
  SEQ_LCD_PrintSpaces(1);

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_PrintString("I:");
  if( ui_selected_item == ITEM_MCLK_IN && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(3);
  } else {
    s32 status = SEQ_MIDI_ROUTER_MIDIClockInGet(selected_mclk_port);

    if( !SEQ_MIDI_PORT_ClkCheckAvailable(selected_mclk_port) )
      status = -1; // MIDI In port not available

    switch( status ) {
      case 0:  SEQ_LCD_PrintString("off"); break;
      case 1:  SEQ_LCD_PrintString("on "); break;
      default: SEQ_LCD_PrintString("---");
    }
  }
  SEQ_LCD_PrintSpaces(1);

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_PrintString("O:");
  if( ui_selected_item == ITEM_MCLK_OUT && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(3);
  } else {
    s32 status = SEQ_MIDI_ROUTER_MIDIClockOutGet(selected_mclk_port);

    if( !SEQ_MIDI_PORT_ClkCheckAvailable(selected_mclk_port) )
      status = -1; // MIDI Out port not available

    switch( status ) {
      case 0:  SEQ_LCD_PrintString("off"); break;
      case 1:  SEQ_LCD_PrintString("on "); break;
      default: SEQ_LCD_PrintString("---");
    }
  }
  SEQ_LCD_PrintSpaces(3);

  // DIN Sync moved to CV configuration
  SEQ_LCD_PrintSpaces(3+4);

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_PrintString("Restart Tempo");


  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// Local exit function
/////////////////////////////////////////////////////////////////////////////
static s32 EXIT_Handler(void)
{
  s32 status = 0;

  if( store_file_required ) {
    // write config file
    MUTEX_SDCARD_TAKE;
    if( (status=SEQ_FILE_C_Write(seq_file_session_name)) < 0 )
      SEQ_UI_SDCardErrMsg(2000, status);
    MUTEX_SDCARD_GIVE;

    store_file_required = 0;
  }

  return status;
}
Exemple #7
0
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return 0; // ignore when button depressed

#if 0
  // leads to: comparison is always true due to limited range of data type
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
#else
  if( button <= SEQ_UI_BUTTON_GP16 ) {
#endif
    // -> same handling like for encoders
    return Encoder_Handler(button, 0);
  }

  switch( button ) {
    case SEQ_UI_BUTTON_Select:
      return -1; // unsupported (yet)

    case SEQ_UI_BUTTON_Right:
    case SEQ_UI_BUTTON_Up:
      if( depressed ) return 0; // ignore when button depressed
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Left:
    case SEQ_UI_BUTTON_Down:
      if( depressed ) return 0; // ignore when button depressed
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  // layout normal mode:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  // Gate Acc. Roll Glide Skip R.G  R.V No Fx                                        
  //   A    B    C    D    E    F    G    H                                          

  // layout drum mode (lower line shows drum labels):
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  // Select Drum Instrument:                                                         
  //  BD   SD   LT   MT   HT   CP   MA   RS   CB   CY   OH   CH  Smp1 Smp2 Smp3 Smp4 
  // ...horizontal VU meters...

  u8 visible_track = SEQ_UI_VisibleTrackGet();
  u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);

  if( high_prio && event_mode == SEQ_EVENT_MODE_Drum ) {
    ///////////////////////////////////////////////////////////////////////////
    // frequently update VU meters

    SEQ_LCD_CursorSet(0, 1);

    u8 drum;
    u8 num_instruments = SEQ_TRG_NumInstrumentsGet(visible_track);
    for(drum=0; drum<num_instruments; ++drum) {
      if( seq_core_trk[visible_track].layer_muted & (1 << drum) )
	SEQ_LCD_PrintString("Mute ");
      else
	SEQ_LCD_PrintHBar((seq_layer_vu_meter[drum] >> 3) & 0xf);
    }

    return 0; // no error
  }
Exemple #8
0
/////////////////////////////////////////////////////////////////////////////
// Local encoder callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported encoder
/////////////////////////////////////////////////////////////////////////////
static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer)
{
  // ensure that original screen will be print immediately
  ui_hold_msg_ctr = 0;

#if 0
  // leads to: comparison is always true due to limited range of data type
  if( (encoder >= SEQ_UI_ENCODER_GP1 && encoder <= SEQ_UI_ENCODER_GP16) ) {
#else
  if( encoder <= SEQ_UI_ENCODER_GP16 ) {
#endif
    // select step within view
    ui_selected_step = (ui_selected_step_view << 4) | (u8)encoder;

    // show edit page for 2 seconds
    ui_hold_msg_ctr = 2000;

    // forward manual trigger to SEQ_CORE
    SEQ_CORE_ManualTrigger(ui_selected_step);

    return 1; // value changed
  }

  return -1; // invalid or unsupported encoder
}


/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return 0; // ignore when button depressed

  // ensure that original screen will be print immediately
  ui_hold_msg_ctr = 0;

#if 0
  // leads to: comparison is always true due to limited range of data type
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
#else
  if( button <= SEQ_UI_BUTTON_GP16 ) {
#endif
    // -> same handling like for encoders
    return Encoder_Handler(button, 0);
  }

  switch( button ) {
    case SEQ_UI_BUTTON_Select: {
      // Request synch to measure for all selected tracks
      SEQ_CORE_ManualSynchToMeasure();
      return 1;
    } break;

    case SEQ_UI_BUTTON_Right:
    case SEQ_UI_BUTTON_Up:
      if( depressed ) return 0; // ignore when button depressed
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Left:
    case SEQ_UI_BUTTON_Down:
      if( depressed ) return 0; // ignore when button depressed
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  // branch to edit page if requested
  if( ui_hold_msg_ctr )
    return SEQ_UI_EDIT_LCD_Handler(high_prio, SEQ_UI_EDIT_MODE_MANUAL);


  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  //   Selected Tracks: 1234 1234 1234 1234     Press SELECT to Synch to Measure!    
  // lower line: print step 1..16/17..32/...

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 0);
  SEQ_LCD_PrintString("  Selected Tracks: ");

  u8 track;
  for(track=0; track<16; ++track) {
    if( seq_core_trk[track].state.SYNC_MEASURE )
      SEQ_LCD_PrintChar('S');
    else if( SEQ_UI_IsSelectedTrack(track) )
      SEQ_LCD_PrintChar('*');
    else
      SEQ_LCD_PrintChar('1' + (track&3));

    if( (track&3) == 3 )
      SEQ_LCD_PrintChar(' ');
  }
  SEQ_LCD_PrintSpaces(1);

  SEQ_LCD_PrintString("   Press SELECT to Synch to Measure!    ");


  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 1);

  u8 step;
  for(step=0; step<16; ++step)
    SEQ_LCD_PrintFormattedString(" %2d  ", 16*ui_selected_step_view + step + 1);

  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_MANUAL_Init(u32 mode)
{
  // install callback routines
  SEQ_UI_InstallButtonCallback(Button_Handler);
  SEQ_UI_InstallEncoderCallback(Encoder_Handler);
  SEQ_UI_InstallLEDCallback(LED_Handler);
  SEQ_UI_InstallLCDCallback(LCD_Handler);

  return 0; // no error
}
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return 0; // ignore when button depressed

#if 0
  // leads to: comparison is always true due to limited range of data type
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
#else
  if( button <= SEQ_UI_BUTTON_GP16 ) {
#endif
    // re-use encoder handler - only select UI item, don't increment, flags will be toggled
    return Encoder_Handler((int)button, 0);
  }

  // remaining buttons:
  switch( button ) {
    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
      if( ++ui_selected_item >= NUM_OF_ITEMS )
	ui_selected_item = 0;
      SetSubpageBasedOnItem(ui_selected_item);
      return 1; // value always changed

    case SEQ_UI_BUTTON_Left:
      if( ui_selected_item == 0 )
	ui_selected_item = NUM_OF_ITEMS-1;
      else
	--ui_selected_item;
      SetSubpageBasedOnItem(ui_selected_item);
      return 1; // value always changed

    case SEQ_UI_BUTTON_Up:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Down:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  if( high_prio )
    return 0; // there are no high-priority updates

  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  // Transposer  Section    MIDI   Ext.       Bus Port Chn. Lower/Upper Mode   Reset 
  //  and Arp.   Control   Router  Ctrl Misc.  1  IN1  #16   ---   ---  T&A    Stacks

  // Transposer  Section    MIDI   Ext.      Port Chn.  G1   G2   G3   G4  Fwd  Reset
  //  and Arp.   Control   Router  Ctrl Misc. All #16  C-1  C-2  C-3  C-4  USB1 Stcks

  // Transposer  Section    MIDI   Ext.      Node IN P/Chn  OUT P/Chn   | DefaultPort
  //  and Arp.   Control   Router  Ctrl Misc. #1  Def. All  Def. # 1    |    USB1    

  // Transposer  Section    MIDI   Ext.      Port Chn.      Function        CC#      
  // Transposer  Section    MIDI   Ext.       IN  OUT Chn.| Function        CC#      
  //  and Arp.   Control   Router  Ctrl Misc. All off --- | Morph Value       1      

  // Transposer  Section    MIDI   Ext.      BLM_SCALAR                       MIDI   
  //  and Arp.   Control   Router  Ctrl Misc.Port: OUT2                     Monitor 


  seq_midi_router_node_t *n = &seq_midi_router_node[selected_router_node];

  ///////////////////////////////////////////////////////////////////////////
//<<<<<<< .mine
 /*
  const char leftpage[2][41] = {
    "Transposer  Section    MIDI             ",
    " and Arp.   Control   Router    Misc.   "
  };
=======
*/
  SEQ_LCD_CursorSet(0, 0);
  SEQ_LCD_PrintString("Transposer  Section    MIDI   Ext.      ");
  SEQ_LCD_CursorSet(0, 1);
  SEQ_LCD_PrintString(" and Arp.   Control   Router  Ctrl Misc.");
//>>>>>>> .r1826

  if( ui_cursor_flash && selected_subpage <= 5 ) {
    const u8 select_pos1[5]  = {  0, 10, 20, 30, 35 };
    const u8 select_width[5] = { 10, 10, 10,  5,  5 };

    int line;
    for(line=0; line<2; ++line) {
      SEQ_LCD_CursorSet(select_pos1[selected_subpage], line);
      SEQ_LCD_PrintSpaces(select_width[selected_subpage]);
    }
  }
/*
	SEQ_LCD_CursorSet(0, 0);
	if (selected_subpage == SUBPAGE_TRANSPOSE && ui_cursor_flash) {
		SEQ_LCD_PrintSpaces(21);
	} else {
		SEQ_LCD_PrintString(" Transposer and Arp ");
    }
	SEQ_LCD_CursorSet(0, 1);
	if (selected_subpage == SUBPAGE_SECTIONS && ui_cursor_flash) {
		SEQ_LCD_PrintSpaces(21);
	} else {
		SEQ_LCD_PrintString("   Section control   ");
    }
	SEQ_LCD_CursorSet(0, 2);
	if (selected_subpage == SUBPAGE_ROUTER && ui_cursor_flash) {
		SEQ_LCD_PrintSpaces(21);
	} else {
		SEQ_LCD_PrintString("     MIDI router     ");
    }
	SEQ_LCD_CursorSet(0, 3);
	if (selected_subpage == SUBPAGE_MISC && ui_cursor_flash) {
		SEQ_LCD_PrintSpaces(21);
	} else {
		SEQ_LCD_PrintString("     Miscilenious     ");
    }
	*/
	SEQ_LCD_CursorSet(0, 4);
	
  switch( selected_subpage ) {
  ///////////////////////////////////////////////////////////////////////////
    case SUBPAGE_TRANSPOSE: {

	  //SEQ_LCD_CursorSet(40, 0);
      SEQ_LCD_PrintString(" Bus Port Chn. Mode  ");
	  SEQ_LCD_CursorSet(0, 6);
	  SEQ_LCD_PrintString(" Lower/Upper   Reset ");
      SEQ_LCD_CursorSet(0, 5);

      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_IN_BUS && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(5);
      } else {
	SEQ_LCD_PrintFormattedString("  %d  ", selected_bus+1);
      }

      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_IN_PORT && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(4);
      } else {
	if( seq_midi_in_port[selected_bus] )
	  SEQ_LCD_PrintString(SEQ_MIDI_PORT_InNameGet(SEQ_MIDI_PORT_InIxGet(seq_midi_in_port[selected_bus])));
	else
	  SEQ_LCD_PrintString(" All");
      }
      SEQ_LCD_PrintSpaces(1);


      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_IN_CHN && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(3);
      } else {
	if( seq_midi_in_channel[selected_bus] )
	  SEQ_LCD_PrintFormattedString("#%2d", seq_midi_in_channel[selected_bus]);
	else
	  SEQ_LCD_PrintString("---");
      }
      SEQ_LCD_PrintSpaces(3);

/*
      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_IN_MODE && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(4);
      } else {
	SEQ_LCD_PrintString(seq_midi_in_options[selected_bus].MODE_PLAY ? "Play" : "T&A ");
      }
      SEQ_LCD_PrintSpaces(3);	  
	  
	  SEQ_LCD_CursorSet(0, 7);
*/	  
      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_IN_LOWER && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(3);
      } else {
	SEQ_LCD_PrintNote(seq_midi_in_lower[selected_bus]);
      }
      SEQ_LCD_PrintSpaces(3);


      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_IN_UPPER && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(3);
      } else {
	SEQ_LCD_PrintNote(seq_midi_in_upper[selected_bus]);
      }
      SEQ_LCD_PrintSpaces(2);


      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_IN_MODE && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(4);
      } else {
	SEQ_LCD_PrintString(seq_midi_in_options[selected_bus].MODE_PLAY ? "Play" : "T&A ");
      }
      SEQ_LCD_PrintSpaces(3);

	  
      SEQ_LCD_PrintString("Stacks");
    } break;


  ///////////////////////////////////////////////////////////////////////////
    case SUBPAGE_SECTIONS: {
      //SEQ_LCD_CursorSet(40, 0);
      SEQ_LCD_PrintString(" Port Chn.  G1   G2  "); 
      SEQ_LCD_CursorSet(0, 6);
	  SEQ_LCD_PrintString(" G3   G4  Fwd  Reset ");

	  SEQ_LCD_CursorSet(0, 5);
	  
      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_S_PORT && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(4);
      } else {
	if( seq_midi_in_sect_port )
	  SEQ_LCD_PrintString(SEQ_MIDI_PORT_InNameGet(SEQ_MIDI_PORT_InIxGet(seq_midi_in_sect_port)));
	else
	  SEQ_LCD_PrintString(" All");
      }
      SEQ_LCD_PrintSpaces(1);

      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_S_CHN && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(3);
      } else {
	if( seq_midi_in_sect_channel )
	  SEQ_LCD_PrintFormattedString("#%2d", seq_midi_in_sect_channel);
	else
	  SEQ_LCD_PrintString("---");
      }
      SEQ_LCD_PrintSpaces(2);

      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_S_OCT_G1 && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(3);
      } else {
	SEQ_LCD_PrintNote(seq_midi_in_sect_note[0]);
      }
      SEQ_LCD_PrintSpaces(2);

      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_S_OCT_G2 && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(3);
      } else {
	SEQ_LCD_PrintNote(seq_midi_in_sect_note[1]);
      }
      SEQ_LCD_PrintSpaces(2);

	  
	  SEQ_LCD_CursorSet(0, 5);
	  
      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_S_OCT_G3 && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(3);
      } else {
	SEQ_LCD_PrintNote(seq_midi_in_sect_note[2]);
      }
      SEQ_LCD_PrintSpaces(2);

      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_S_OCT_G4 && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(3);
      } else {
	SEQ_LCD_PrintNote(seq_midi_in_sect_note[3]);
      }

      SEQ_LCD_PrintSpaces(2);

      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_S_FWD_PORT && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(4);
      } else {
	if( seq_midi_in_sect_fwd_port == 0 )
	  SEQ_LCD_PrintString("----");
	else
	  SEQ_LCD_PrintString(SEQ_MIDI_PORT_OutNameGet(SEQ_MIDI_PORT_OutIxGet(seq_midi_in_sect_fwd_port)));
      }

      SEQ_LCD_PrintSpaces(1);
      SEQ_LCD_PrintString("Stcks");
    } break;


  ///////////////////////////////////////////////////////////////////////////
    case SUBPAGE_ROUTER: {
//<<<<<<< .mine
      //SEQ_LCD_CursorSet(40, 0);
      SEQ_LCD_PrintString(" Node  IN Port/Chn   "); 
	  SEQ_LCD_CursorSet(0, 6);
	  SEQ_LCD_PrintString("OUT Port/Chn Def.Port");
      SEQ_LCD_CursorSet(0, 5);
/*
	  =======
      SEQ_LCD_CursorSet(40, 0);
      SEQ_LCD_PrintString("Node IN P/Chn  OUT P/Chn   | DefaultPort");
      SEQ_LCD_CursorSet(40, 1);
>>>>>>> .r1826
*/
      ///////////////////////////////////////////////////////////////////////
      SEQ_LCD_PrintSpaces(1);
      if( ui_selected_item == ITEM_R_NODE && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(3);
      } else {
	SEQ_LCD_PrintFormattedString("#%2d", selected_router_node+1);
      }
      SEQ_LCD_PrintSpaces(1);

      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_R_SRC_PORT && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(4);
      } else {
	SEQ_LCD_PrintString(SEQ_MIDI_PORT_InNameGet(SEQ_MIDI_PORT_InIxGet(n->src_port)));
      }
      SEQ_LCD_PrintSpaces(1);

      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_R_SRC_CHN && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(3);
      } else {
	if( !n->src_chn ) {
	  SEQ_LCD_PrintString("---");
	} else if( n->src_chn > 16 ) {
	  SEQ_LCD_PrintString("All");
	} else {
	  SEQ_LCD_PrintFormattedString("#%2d", n->src_chn);
	}
      }
      SEQ_LCD_PrintSpaces(2);

	  SEQ_LCD_CursorSet(0, 7);
	  
      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_R_DST_PORT && ui_cursor_flash ) {
	if( n->dst_chn >= 18 ) {
	  SEQ_LCD_PrintSpaces(2);
	} else {
	  SEQ_LCD_PrintSpaces(4);
	}
      } else {
	if( n->dst_chn >= 18 ) {
	  SEQ_LCD_PrintSpaces(2);
	} else {
	  SEQ_LCD_PrintString(SEQ_MIDI_PORT_OutNameGet(SEQ_MIDI_PORT_OutIxGet(n->dst_port)));
	}
      }

      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_R_DST_CHN && ui_cursor_flash ) {
	if( n->dst_chn >= 18 ) {
	  SEQ_LCD_PrintSpaces(7);
	} else {
	  SEQ_LCD_PrintSpaces(5);
	}
      } else {
	if( !n->dst_chn ) {
	  SEQ_LCD_PrintString(" --- ");
	} else if( n->dst_chn == 17 ) {
	  SEQ_LCD_PrintString(" All ");
	} else if( n->dst_chn == 18 ) {
	  SEQ_LCD_PrintString("  Track");
	} else if( n->dst_chn >= 19 ) {
	  SEQ_LCD_PrintString("Sel.Trk");
	} else {
	  SEQ_LCD_PrintFormattedString(" #%2d ", n->dst_chn);
	}
      }
      SEQ_LCD_PrintSpaces(3);

      ///////////////////////////////////////////////////////////////////////
      SEQ_LCD_PrintChar('|');
      SEQ_LCD_PrintSpaces(4);

      if( ui_selected_item == ITEM_DEF_PORT && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(4);
      } else {
	SEQ_LCD_PrintString(SEQ_MIDI_PORT_OutNameGet(SEQ_MIDI_PORT_OutIxGet(MIOS32_MIDI_DefaultPortGet())));
      }
      SEQ_LCD_PrintSpaces(4);
    } break;


  ///////////////////////////////////////////////////////////////////////////
    case SUBPAGE_EXT_CTRL: {
      SEQ_LCD_CursorSet(40, 0);
      SEQ_LCD_PrintString(" IN  OUT  Chn.|Function        ");
      if( selected_ext_ctrl < SEQ_MIDI_IN_EXT_CTRL_NUM_IX_CC ) {
	SEQ_LCD_PrintString("CC#      ");
      } else {
	SEQ_LCD_PrintSpaces(10);
      }
      SEQ_LCD_CursorSet(40, 1);

      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_EXT_PORT && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(4);
      } else {
	if( seq_midi_in_ext_ctrl_port == 0xff )
	  SEQ_LCD_PrintString(" All");
	else if( !seq_midi_in_ext_ctrl_port )
	  SEQ_LCD_PrintString(" off");
	else
	  SEQ_LCD_PrintString(SEQ_MIDI_PORT_InNameGet(SEQ_MIDI_PORT_InIxGet(seq_midi_in_ext_ctrl_port)));
      }
      SEQ_LCD_PrintSpaces(1);

      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_EXT_PORT_OUT && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(4);
      } else {
	if( seq_midi_in_ext_ctrl_out_port )
	  SEQ_LCD_PrintString(SEQ_MIDI_PORT_OutNameGet(SEQ_MIDI_PORT_OutIxGet(seq_midi_in_ext_ctrl_out_port)));
	else
	  SEQ_LCD_PrintString("off ");
      }
      SEQ_LCD_PrintSpaces(1);

      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_EXT_CHN && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(3);
      } else {
	if( seq_midi_in_ext_ctrl_channel )
	  SEQ_LCD_PrintFormattedString("#%2d", seq_midi_in_ext_ctrl_channel);
	else
	  SEQ_LCD_PrintString("---");
      }
      SEQ_LCD_PrintString(" |");

      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_EXT_CTRL && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(15);
      } else {
	SEQ_LCD_PrintStringPadded((char *)SEQ_MIDI_IN_ExtCtrlStr(selected_ext_ctrl), 15);
      }


      ///////////////////////////////////////////////////////////////////////
      if( ui_selected_item == ITEM_EXT_VALUE && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(10);
      } else {
	SEQ_LCD_PrintSpaces(1);
	if( selected_ext_ctrl == SEQ_MIDI_IN_EXT_CTRL_NRPN_ENABLED ) {
	  SEQ_LCD_PrintStringPadded(seq_midi_in_ext_ctrl_asg[selected_ext_ctrl] ? "enabled" : "disabled", 9);
	} else if( selected_ext_ctrl == SEQ_MIDI_IN_EXT_CTRL_PC_MODE ) {
	  SEQ_LCD_PrintStringPadded((char *)SEQ_MIDI_IN_ExtCtrlPcModeStr(seq_midi_in_ext_ctrl_asg[selected_ext_ctrl]), 9);
	} else {
	  u8 cc = seq_midi_in_ext_ctrl_asg[selected_ext_ctrl];
	  if( cc >= 0x80 )
	    SEQ_LCD_PrintString("off");
	  else
	    SEQ_LCD_PrintFormattedString("%3d", cc);
	  SEQ_LCD_PrintSpaces(7);
	}
      }

    } break;


  ///////////////////////////////////////////////////////////////////////////
    case SUBPAGE_MISC: {
      //SEQ_LCD_CursorSet(40, 0);
//<<<<<<< .mine
      SEQ_LCD_PrintString("BLM_SCALAR ");
      SEQ_LCD_PrintString(blm_timeout_ctr ? "connected  " : "not found ");
      SEQ_LCD_CursorSet(0, 6);
	  SEQ_LCD_PrintString("         MIDI   ");
      SEQ_LCD_CursorSet(0, 5);
/*
	  =======
      SEQ_LCD_PrintString("BLM_SCALAR                       MIDI   ");
      SEQ_LCD_CursorSet(40, 1);
>>>>>>> .r1826
*/
      ///////////////////////////////////////////////////////////////////////
      SEQ_LCD_PrintString("Port: ");
      if( ui_selected_item == ITEM_BLM_SCALAR_PORT && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(4);
      } else {
	if( !seq_blm_port )
	  SEQ_LCD_PrintString(" off");
	else
	  SEQ_LCD_PrintString(SEQ_MIDI_PORT_InNameGet(SEQ_MIDI_PORT_InIxGet(seq_blm_port)));
      }

//<<<<<<< .mine
	  SEQ_LCD_CursorSet(0, 7);
	  
//=======
      SEQ_LCD_PrintString(blm_timeout_ctr ? " (found)  " : "          ");

      // free for new parameters
      SEQ_LCD_PrintSpaces(12);

//>>>>>>> .r1826
      ///////////////////////////////////////////////////////////////////////
      SEQ_LCD_PrintString("Monitor ");

    } break;
  }

  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// Local exit function
/////////////////////////////////////////////////////////////////////////////
static s32 EXIT_Handler(void)
{
  s32 status = 0;

  if( store_file_required ) {
    // write config files
    MUTEX_SDCARD_TAKE;
    if( (status=SEQ_FILE_C_Write(seq_file_session_name)) < 0 )
      SEQ_UI_SDCardErrMsg(2000, status);
    MUTEX_SDCARD_GIVE;

    MUTEX_SDCARD_TAKE;
    if( (status=SEQ_FILE_GC_Write()) < 0 )
      SEQ_UI_SDCardErrMsg(2000, status);
    MUTEX_SDCARD_GIVE;
  }

  return status;
}
Exemple #10
0
/////////////////////////////////////////////////////////////////////////////
// Local encoder callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported encoder
/////////////////////////////////////////////////////////////////////////////
static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer)
{
#if 0
  // leads to: comparison is always true due to limited range of data type
  if( (encoder >= SEQ_UI_ENCODER_GP1 && encoder <= SEQ_UI_ENCODER_GP16) ) {
#else
  if( encoder <= SEQ_UI_ENCODER_GP16 ) {
#endif
    last_bookmark = encoder;
    SEQ_UI_Bookmark_Restore(last_bookmark);
    return 1;
  }

  // all other encoders
  return -1;
}


/////////////////////////////////////////////////////////////////////////////
// button callback function
// Also used by SEQ_UI_Button_DirectBookmark
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_BOOKMARKS_Button_Handler(seq_ui_button_t button, s32 depressed)
{
#if 0
  // leads to: comparison is always true due to limited range of data type
  if( (button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16) ) {
#else
  if( button <= SEQ_UI_BUTTON_GP16 ) {
#endif
    if( depressed ) {
      SEQ_UI_UnInstallDelayedActionCallback(Button_StoreRequest);
      if( store_state == 1 ) { // depressed within 1 second: select bookmark
	SEQ_UI_Bookmark_Restore(last_bookmark);
      }
      return 0;
    }
    last_bookmark = button;
    store_state = 1;
    SEQ_UI_InstallDelayedActionCallback(Button_StoreRequest, 500, 0);

    return 1;
  }

#if 0
  // doesn't make much sense here
  switch( button ) {
    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
    case SEQ_UI_BUTTON_Up:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Left:
    case SEQ_UI_BUTTON_Down:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }
#endif

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  if( high_prio )
    return 0; // there are no high-priority updates

  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  //             Global Bookmarks                        Session Bookmarks           
  // BM 1 BM 2 BM 3 BM 4 BM 5 BM 6 BM 7 BM 8 BM 9 BM10 BM11 BM12 BM13 BM14 BM15 BM16 

  SEQ_LCD_CursorSet(0, 0);
  SEQ_LCD_PrintString("            Global Bookmarks                        Session Bookmarks           ");

  SEQ_LCD_CursorSet(0, 1);
  int i;
  for(i=0; i<SEQ_UI_BOOKMARKS_NUM; ++i) {
    if( i >= 16 )
      break; // just to ensure...
    seq_ui_bookmark_t *bm = (seq_ui_bookmark_t *)&seq_ui_bookmarks[i];

    if( ui_cursor_flash && (i == last_bookmark) )
      SEQ_LCD_PrintSpaces(5);
    else
      SEQ_LCD_PrintStringPadded(bm->name, 5);
  }

  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_BOOKMARKS_Init(u32 mode)
{
  // install callback routines
  SEQ_UI_InstallButtonCallback(SEQ_UI_BOOKMARKS_Button_Handler);
  SEQ_UI_InstallEncoderCallback(Encoder_Handler);
  SEQ_UI_InstallLEDCallback(LED_Handler);
  SEQ_UI_InstallLCDCallback(LCD_Handler);

  store_state = 0;

  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// help function for delayed store action
/////////////////////////////////////////////////////////////////////////////
static void Button_StoreRequest(u32 state)
{
  if( store_state == 1 ) {
    SEQ_UI_Msg(last_bookmark >= 8 ? SEQ_UI_MSG_DELAYED_ACTION_R : SEQ_UI_MSG_DELAYED_ACTION, 2001,
	       "Hold Button", "to store Bookmark!");
    SEQ_UI_InstallDelayedActionCallback(Button_StoreRequest, 2000, 0);
    store_state = 2;
  } else {
    store_state = 0;
    // store into selected slot
    SEQ_UI_Bookmark_Store(last_bookmark);

    SEQ_UI_Msg(last_bookmark >= 8 ? SEQ_UI_MSG_USER_R : SEQ_UI_MSG_USER, 2000,
	       "Storing", "Bookmark!");      
#if !defined(MIOS32_FAMILY_EMULATION)
    // this yield ensures, that the display will be updated before storing the file
    taskYIELD();
#endif
    // and store file
    MUTEX_SDCARD_TAKE;
    s32 error = SEQ_FILE_BM_Write(seq_file_session_name, (last_bookmark < 8) ? 1 : 0);
    MUTEX_SDCARD_GIVE;
    if( error < 0 )
      SEQ_UI_SDCardErrMsg(2000, error);
    else {
      // return to bookmarked page
      SEQ_UI_PageSet((seq_ui_page_t)seq_ui_bookmarks[last_bookmark].page);

      // and print message
      SEQ_UI_Msg(last_bookmark >= 8 ? SEQ_UI_MSG_USER_R : SEQ_UI_MSG_USER, 2000,
		 "Bookmark", "stored!");      
    }
  }
}
Exemple #11
0
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return 0; // ignore when button depressed

  if( button <= SEQ_UI_BUTTON_GP8 || button == SEQ_UI_BUTTON_Select ) {
    if( button != SEQ_UI_BUTTON_Select )
      ui_selected_item = button / 2;

    SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 10000, "Sending Informations", "to MIOS Terminal!");

    switch( ui_selected_item + list_view_offset ) {

      //////////////////////////////////////////////////////////////////////////////////////////////
      case LIST_ITEM_SYSTEM:
	SEQ_TERMINAL_PrintSystem(DEBUG_MSG);
	break;

      //////////////////////////////////////////////////////////////////////////////////////////////
      case LIST_ITEM_GLOBALS:
	SEQ_TERMINAL_PrintGlobalConfig(DEBUG_MSG);
	break;

      //////////////////////////////////////////////////////////////////////////////////////////////
      case LIST_ITEM_CONFIG:
	SEQ_TERMINAL_PrintSessionConfig(DEBUG_MSG);
	break;

      //////////////////////////////////////////////////////////////////////////////////////////////
      case LIST_ITEM_TRACKS:
	SEQ_TERMINAL_PrintTracks(DEBUG_MSG);
	break;

      //////////////////////////////////////////////////////////////////////////////////////////////
      case LIST_ITEM_TRACK_INFO:
	SEQ_TERMINAL_PrintTrack(DEBUG_MSG, SEQ_UI_VisibleTrackGet());
	break;

      //////////////////////////////////////////////////////////////////////////////////////////////
      case LIST_ITEM_MIXER_MAP:
	SEQ_TERMINAL_PrintCurrentMixerMap(DEBUG_MSG);
	break;

      //////////////////////////////////////////////////////////////////////////////////////////////
      case LIST_ITEM_SONG:
	SEQ_TERMINAL_PrintCurrentSong(DEBUG_MSG);
	break;

      //////////////////////////////////////////////////////////////////////////////////////////////
      case LIST_ITEM_GROOVES:
	SEQ_TERMINAL_PrintGrooveTemplates(DEBUG_MSG);
	break;

      //////////////////////////////////////////////////////////////////////////////////////////////
      case LIST_ITEM_BOOKMARKS:
	SEQ_TERMINAL_PrintBookmarks(DEBUG_MSG);
	break;

      //////////////////////////////////////////////////////////////////////////////////////////////
      case LIST_ITEM_SD_CARD:
	SEQ_TERMINAL_PrintSdCardInfo(DEBUG_MSG);
	break;

      //////////////////////////////////////////////////////////////////////////////////////////////
      case LIST_ITEM_NETWORK:
#if !defined(MIOS32_FAMILY_EMULATION)
	UIP_TERMINAL_PrintNetwork(DEBUG_MSG);
#endif
	break;

      //////////////////////////////////////////////////////////////////////////////////////////////
      default:
	DEBUG_MSG("No informations available.");
    }

    SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "Sent Informations", "to MIOS Terminal!");

    return 1;
  }

  if( button >= SEQ_UI_BUTTON_GP9 && button <= SEQ_UI_BUTTON_GP16 ) {
    // re-using encoder handler
    return Encoder_Handler(button, 0);
  }

  switch( button ) {
    case SEQ_UI_BUTTON_Right:
    case SEQ_UI_BUTTON_Up:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Left:
    case SEQ_UI_BUTTON_Down:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}
/////////////////////////////////////////////////////////////////////////////
// Local encoder callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported encoder
/////////////////////////////////////////////////////////////////////////////
static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer)
{
#if 0
  // leads to: comparison is always true due to limited range of data type
  if( (encoder >= SEQ_UI_ENCODER_GP1 && encoder <= SEQ_UI_ENCODER_GP16) ) {
#else
  if( encoder <= SEQ_UI_ENCODER_GP16 ) {
#endif
    if( seq_ui_button_state.SELECT_PRESSED && !seq_ui_button_state.CHANGE_ALL_STEPS ) {
	// select button pressed: indirect MUTED flag modification (taken over when select button depressed)
	u16 mask = 1 << encoder;
	if( incrementer < 0 || (incrementer == 0 && !(latched_mute & mask)) )
	  latched_mute |= mask;
	else
	  latched_mute &= ~mask;
    } else {
      // select button not pressed: direct MUTED flag modification
      // access to seq_core_trk[] must be atomic!
      portENTER_CRITICAL();

      u8 visible_track = SEQ_UI_VisibleTrackGet();
      u16 mask = 1 << encoder;
      u16 *muted = (u16 *)&seq_core_trk_muted;

      if( seq_ui_button_state.CHANGE_ALL_STEPS ) {
	switch( encoder ) {
	case SEQ_UI_ENCODER_GP1:
	case SEQ_UI_ENCODER_GP2:
	  *muted = 0xffff;
	  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "All Tracks", "muted");
	  break;

	case SEQ_UI_ENCODER_GP3:
	case SEQ_UI_ENCODER_GP4:
	case SEQ_UI_ENCODER_GP5:
	  muted = (u16 *)&seq_core_trk[visible_track].layer_muted;
	  *muted = 0xffff;
	  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "All Layers", "of current Track muted");
	  break;

	case SEQ_UI_ENCODER_GP6:
	case SEQ_UI_ENCODER_GP7:
	case SEQ_UI_ENCODER_GP8: {
	  *muted = 0xffff;

	  int track;
	  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) {
	    seq_core_trk[track].layer_muted = 0xffff;
	  }
	  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "All Layers", "and Tracks muted");
	} break;

	case SEQ_UI_ENCODER_GP9:
	case SEQ_UI_ENCODER_GP10:
	  *muted = 0x0000;
	  SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "All Tracks", "unmuted");
	  break;

	case SEQ_UI_ENCODER_GP11:
	case SEQ_UI_ENCODER_GP12:
	case SEQ_UI_ENCODER_GP13:
	  muted = (u16 *)&seq_core_trk[visible_track].layer_muted;
	  *muted = 0x0000;
	  SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "All Layers", "of current Track unmuted");
	  break;

	case SEQ_UI_ENCODER_GP14:
	case SEQ_UI_ENCODER_GP15:
	case SEQ_UI_ENCODER_GP16: {
	  *muted = 0x0000;

	  int track;
	  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) {
	    seq_core_trk[track].layer_muted = 0x0000;
	  }
	  SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "All Layers", "and Tracks unmuted");
	} break;
	}
      } else {
	if( seq_ui_button_state.MUTE_PRESSED )
	  muted = (u16 *)&seq_core_trk[visible_track].layer_muted;
	else if( SEQ_BPM_IsRunning() ) { // Synched Mutes only when sequencer is running
	  if( !(*muted & mask) && seq_core_options.SYNCHED_MUTE && !seq_ui_button_state.FAST_ENCODERS ) { // Fast button will disable synched mute
	    muted = (u16 *)&seq_core_trk_synched_mute;
	  } else if( (*muted & mask) && seq_core_options.SYNCHED_UNMUTE && !seq_ui_button_state.FAST_ENCODERS ) { // Fast button will disable synched unmute
	    muted = (u16 *)&seq_core_trk_synched_unmute;
	  }
	} else {
	  // clear synched mutes/unmutes if sequencer not running
	  seq_core_trk_synched_mute = 0;
	  seq_core_trk_synched_unmute = 0;
	}
	  
	if( incrementer < 0 )
	  *muted |= mask;
	else if( incrementer > 0 )
	  *muted &= ~mask;
	else
	  *muted ^= mask;
      }

      portEXIT_CRITICAL();

      if( muted == ((u16 *)&seq_core_trk_muted) ) {
	// send to external
	SEQ_MIDI_IN_ExtCtrlSend(SEQ_MIDI_IN_EXT_CTRL_MUTES, (*muted & mask) ? 127 : 0, encoder);
      }
    }

    return 1; // value changed
  }

  return -1; // invalid or unsupported encoder
}


/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
#if 0
  // leads to: comparison is always true due to limited range of data type
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
#else
  if( button <= SEQ_UI_BUTTON_GP16 ) {
#endif
    if( depressed ) return 0; // ignore when button depressed

    // re-using encoder routine
    return Encoder_Handler(button, 0);
  }

  switch( button ) {
    case SEQ_UI_BUTTON_Select:
      portENTER_CRITICAL();
      if( depressed ) {
	// select button released: take over latched mutes
	if( seq_ui_button_state.MUTE_PRESSED ) {
	  u8 visible_track = SEQ_UI_VisibleTrackGet();
	  seq_core_trk[visible_track].layer_muted = latched_mute;
	} else {
	  u16 new_mutes = latched_mute & ~seq_core_trk_muted;
	  if( SEQ_BPM_IsRunning() && seq_core_options.SYNCHED_MUTE && !seq_ui_button_state.FAST_ENCODERS ) // Fast button will disable synched mute
	    seq_core_trk_synched_mute |= new_mutes;
	  else
	    seq_core_trk_muted |= new_mutes;

	  u16 new_unmutes = ~latched_mute & seq_core_trk_muted;
	  if( SEQ_BPM_IsRunning() && seq_core_options.SYNCHED_UNMUTE && !seq_ui_button_state.FAST_ENCODERS ) // Fast button will disable synched unmute
	    seq_core_trk_synched_unmute |= new_unmutes;
	  else
	    seq_core_trk_muted &= ~new_unmutes;
	}
      } else {
	// select pressed: init latched mutes which will be taken over once SELECT button released
	if( seq_ui_button_state.MUTE_PRESSED ) {
	  u8 visible_track = SEQ_UI_VisibleTrackGet();
	  latched_mute = seq_core_trk[visible_track].layer_muted;
	} else {
	  latched_mute = seq_core_trk_muted;
	}
      }

      portEXIT_CRITICAL();
      return 1;
  }

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  //  > 1<   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16 
  // ...horizontal VU meters...

  // Mute All screen:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  //    Mute       Mute       Mute all Tracks  Unmute      Unmute   Unmute all Tracks
  // all Tracks G1T1 Layers    and all Layersall Tracks G1T1 Layers    and all Layers

  if( seq_ui_button_state.CHANGE_ALL_STEPS ) {
    if( high_prio )
      return 0;

    SEQ_LCD_CursorSet(0, 0);
    SEQ_LCD_PrintString("   Mute       Mute       Mute all Tracks  Unmute      Unmute   Unmute all Tracks");
    SEQ_LCD_CursorSet(0, 1);
    SEQ_LCD_PrintString("all Tracks ");
    SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks);
    SEQ_LCD_PrintString(" Layers    and all Layersall Tracks ");
    SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks);
    SEQ_LCD_PrintString(" Layers    and all Layers");

    return 0;
  }

  if( high_prio ) {
    ///////////////////////////////////////////////////////////////////////////
    // frequently update VU meters
    SEQ_LCD_CursorSet(0, 1);

    u8 track;
    u16 mute_flags = 0;
    u16 mute_flags_from_midi = 0;

    if( !ui_cursor_flash && seq_ui_button_state.SELECT_PRESSED ) {
      mute_flags = latched_mute;
    } else {
      if( seq_ui_button_state.MUTE_PRESSED ) {
	u8 visible_track = SEQ_UI_VisibleTrackGet();
	mute_flags = seq_core_trk[visible_track].layer_muted;
	mute_flags_from_midi = seq_core_trk[visible_track].layer_muted_from_midi;
      } else {
	mute_flags = seq_core_trk_muted;
      }
    }

    if( seq_ui_button_state.MUTE_PRESSED ) {
      u8 layer;
      u16 mask = (1 << 0);
      for(layer=0; layer<16; ++layer, mask <<= 1)
	if( mute_flags_from_midi & mask ) {
	  SEQ_LCD_PrintString("MIDI ");
	} else if( mute_flags & mask ) {
	  SEQ_LCD_PrintString("Mute ");
	} else {
	  SEQ_LCD_PrintHBar((seq_layer_vu_meter[layer] >> 3) & 0xf);
	}
    } else {
      int remaining_steps = (seq_core_steps_per_measure - seq_core_state.ref_step) + 1;
      seq_core_trk_t *t = &seq_core_trk[0];
      u16 mask = (1 << 0);
      for(track=0; track<16; ++t, ++track, mask <<= 1)
	if( mute_flags & mask ) {
	  if( !seq_ui_button_state.SELECT_PRESSED && (seq_core_trk_synched_unmute & mask) ) {
	    SEQ_LCD_PrintFormattedString("U%3d ", remaining_steps);
	  } else {
	    SEQ_LCD_PrintString("Mute ");
	  }
	} else {
	  if( !seq_ui_button_state.SELECT_PRESSED && (seq_core_trk_synched_mute & mask) ) {
	    SEQ_LCD_PrintFormattedString("M%3d ", remaining_steps);
	  } else {
	    SEQ_LCD_PrintHBar(t->vu_meter >> 3);
	  }
	}
    }
  } else {
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{

  if( SEQ_FILE_FormattingRequired() )
    return 0; // no button action as long as files not available
	
	u8 group;
	s32 status;
	
  switch( button ) {
		
		case SEQ_UI_BUTTON_Edit: {
			
			
			if ( depressed && (selected_page == PAGE_REMIX) ) {
					
				// we want to show vertical VU meters normal mode
				SEQ_LCD_InitSpecialChars(SEQ_LCD_CHARSET_VBars);
				
				selected_page = PAGE_MAIN;		
				
				//
				// here we run the commands for remix states
				//
				u16 remix_map_tmp;
				
				// if we are in no preview_mode them call the demix procedment in case we got some request
				if ( (seq_pattern_remix_map != seq_pattern_demix_map) && ( remix_mode ) ) {
					remix_map_tmp = seq_pattern_remix_map;
					seq_pattern_remix_map = ~(seq_pattern_remix_map ^ seq_pattern_demix_map);
					
          if (ableton_api) {
						
            // TODO: implements a ableton remotescript to the clip control functionality
						
						u8 track;
						for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) {
						 
						 // if we got the track bit setup inside our remix_map, them do not send mixer data for that track channel, let it be mixed down
						 if ( ((1 << track) | seq_pattern_remix_map) == seq_pattern_remix_map ) {
							 // do nothing...
						 } else {
							 // delay our task for ableton get a breath before change the pattern line
							 vTaskDelay(50);
							 // send slot play envet to ableton: cc (111 + track) with value 127 to channel 16
							 MIOS32_MIDI_SendCC(ableton_port, 15, (111 + track), 127);
						 }
						 
						}           
						
          }
					
					// if we are in remix mode lets start the process
					if (remix_map_tmp == 0) {
												
						//pattern_name = pattern_name_remix;
						preview_mode = 0;
						remix_mode = 0;
						// set the pattern_remix_timer reference
						pattern_remix_timer = MIOS32_SYS_TimeGet();
						
					}
					
					// Change Pattern
					u8 group;
					for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group) {
						// change pattern
						SEQ_PATTERN_Change(group, seq_pattern[group], 0);
					}
					
					// copy the pattern name for future reference
					sprintf(pattern_name, seq_pattern_name[0]);
					
					// getting back
					seq_pattern_remix_map = remix_map_tmp;
					seq_pattern_demix_map = seq_pattern_remix_map;
					
				}
				
			} else if ( !depressed ) {		
				
				// we want to show horizontal VU meters in remix mode
				SEQ_LCD_InitSpecialChars(SEQ_LCD_CHARSET_HBars);
				
				selected_page = PAGE_REMIX;
			}
				
			return 1;	
				
		} break;				
			
    case SEQ_UI_BUTTON_Select: {
			
      if(!depressed) {
        selected_page = PAGE_OPTION;
        return 1;
      }
			
      if( (depressed) && (selected_page == PAGE_OPTION) ) {
        selected_page = PAGE_MAIN;
      }
			
		} break;
			
		default:
			break;
			
			
  }

  if( depressed ) return 0; // ignore when button depressed if its not SEQ_UI_BUTTON_Select or SEQ_UI_BUTTON_Edit
	
  switch( selected_page ) {

    ///////////////////////////////////////////////////////////////////////////
    // REMIX PAGE
    case PAGE_REMIX: {

      if( button <= SEQ_UI_BUTTON_GP16 ) {
        // re-using encoder routine
        return Encoder_Handler(button, 0);
      }			
			
    } break;

    ///////////////////////////////////////////////////////////////////////////
    // OPTION PAGE
    case PAGE_OPTION: {

      switch( button ) {

        case SEQ_UI_BUTTON_GP1:
          // Save Pattern(all 4 groups at once)
          for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group) {
						
            if( (status=SEQ_PATTERN_Save(group, seq_pattern[group])) < 0 ) {
              SEQ_UI_SDCardErrMsg(2000, status);
              return 0;
            }
						
          }
					
          // Save the pattern mixer
          SEQ_MIXER_Save(SEQ_MIXER_NumGet());
					
          break;

        case SEQ_UI_BUTTON_GP2:
          // Edit Pattern Name
					//SEQ_LCD_Clear();
          selected_page = PAGE_NAME_EDIT;
          break;

        case SEQ_UI_BUTTON_GP3:
          // Copy Pattern
					// We are going to use the multicopy procedure
					SEQ_UI_PATTERN_Copy();

					// coping mixer
					SEQ_UI_MIXER_Copy();

          break;

        case SEQ_UI_BUTTON_GP4:
          // Paste Pattern
					// We are going to use the multicopy procedure
					SEQ_UI_PATTERN_Paste();

					// paste mixer
					SEQ_UI_MIXER_Paste();
			
          break;

        case SEQ_UI_BUTTON_GP5:
        case SEQ_UI_BUTTON_GP6:
          return -1; // not mapped

        case SEQ_UI_BUTTON_GP7:
        case SEQ_UI_BUTTON_GP8:
          // Track Delay Page
					//SEQ_LCD_Clear();
          //selected_page = PAGE_TRK_DELAY;
          //break;
					return -1; // not mapped

        case SEQ_UI_BUTTON_GP9:
        case SEQ_UI_BUTTON_GP10:
					return -1; // not mapped

        case SEQ_UI_BUTTON_GP11:
        case SEQ_UI_BUTTON_GP12:
					return -1; // not mapped

        case SEQ_UI_BUTTON_GP13:
        case SEQ_UI_BUTTON_GP14:
          // Auto Save switch
          auto_save ^= 1;
          break;
          break;

        case SEQ_UI_BUTTON_GP15:
        case SEQ_UI_BUTTON_GP16:
					// Ableton API switch
          ableton_api ^= 1;
          return -1; // not mapped
      }

      return 0;

    } break;

    ///////////////////////////////////////////////////////////////////////////
    // PATTERN NAME EDIT PAGE
    case PAGE_NAME_EDIT: {

      return Encoder_Handler((seq_ui_encoder_t)button, 0);

    } break;

    ///////////////////////////////////////////////////////////////////////////
    // TRACK DELAY PAGE
    case PAGE_TRK_DELAY: {

    } break;

    ///////////////////////////////////////////////////////////////////////////
    // MAIN PAGE
    case PAGE_MAIN: {

      // Pattern Change Group Requests
      if( button <= SEQ_UI_BUTTON_GP8 ) {

        u8 group;
				
        for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group) {
          if( selected_pattern[group].group == button ) {
            if( SEQ_FILE_B_NumPatterns(selected_pattern[group].bank) > 64 ) {
              selected_pattern[group].lower ^= 1;
            } else {
              selected_pattern[group].lower = 0; // toggling not required
            }
          } else {
            selected_pattern[group].group = button;
            preview_bank = button;
            //preview_mode = 0;
          }
        }
				
				SEQ_PATTERN_PeekName(selected_pattern[0], preview_name);
				preview_mode = 1;
				
        return 1; // value always changed
      }

      // Pattern Change Request
      if( button >= SEQ_UI_BUTTON_GP9 && button <= SEQ_UI_BUTTON_GP16 ) {

        //u8 group;

        s32 status = 0;

        // setting save patterns for later autosave procedure
        //for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group)
        //  save_pattern[group] = seq_pattern[group];
				
        // change preview pattern
        selected_pattern[0].num = button-8;
        selected_pattern[1].num = button-8;
        selected_pattern[2].num = button-8;
        selected_pattern[3].num = button-8;

        if ( !preview_mode )
        {
          preview_num = button-8;
          SEQ_PATTERN_PeekName(selected_pattern[0], preview_name);
          preview_mode = 1;
					
					// for security reasons in live environment, we can not accept rapid 2x press of pattern button.
					// if the buttons are not good quality they can send a 2x rapid signal os pressing in just one physical pressing
					// the time we need is bassicly the human time to read the name of patterns requested
			    // start time in count
			    pc_time_control = seq_core_timestamp_ms + 200;
					// vTaksDelay(200);
        } else {

					// 
					if ( remix_mode == 0 ) {
					
						//char str[30];
						//sprintf(str, "%d = %d %d = %d", selected_pattern[0].num, preview_num, selected_pattern[0].group, preview_bank);
						//SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, str, "debug");
						
						// Check for remix state
						if ( (selected_pattern[0].num == preview_num) &&  (selected_pattern[0].group == preview_bank) ) {
						
							//if ( pc_time_control >= seq_core_timestamp_ms )
							//	return 0; // do nothing, just to be shure we are not handle acidental double clicks, it happens!					
							
							// if we got some remix bit setup, enter in remix mode
							if (seq_pattern_remix_map != 0) {
								// set the remix mode
								remix_mode = 1;
							}
						
						}
						
					}
					
          // Change Pattern
          if ( (selected_pattern[0].num == preview_num) &&  (selected_pattern[0].group == preview_bank) ) {

  	        if ( pc_time_control >= seq_core_timestamp_ms )
	            return 0; // do nothing, just to be shure we are not handle acidental double clicks

						if (ableton_api) {
							
							u8 ableton_pattern_number = 0;
							
							//
							// ABLETON API PATTERN CHANGE HANDLE
							//
							// send ableton event to change the line clips
							if (selected_pattern[0].lower) {
						  	ableton_pattern_number = ((selected_pattern[0].group - 1) * 8) + button;
							} else {
						  	ableton_pattern_number = (((selected_pattern[0].group - 1) + 8) * 8) + button;
							}
							
							// midi_cc to send = 110
							// midi_chn = 16
							// midi_port = ableton_port
							// here we need to send a clip line change request
							MIOS32_MIDI_SendCC(ableton_port, 15, 110, ableton_pattern_number);
						
							// delay our task for ableton get a breath before change the pattern line
							vTaskDelay(50);

							// clip triggering
							u8 track;
            	for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) {
              
              	// if we got the track bit setup inside our remix_map, them do not send mixer data for that track channel, let it be mixed down
              	if ( ((1 << track) | seq_pattern_remix_map) == seq_pattern_remix_map ) {
                	// do nothing...
              	} else {
									// delay our task for ableton get a breath before change the pattern line
									vTaskDelay(50);									
									// send clip slot play envet to ableton cc (111 + track) with value 127 to channel 16
                	MIOS32_MIDI_SendCC(ableton_port, 15, (111 + track), 127);
              	}
              
            	}           

							// send a global clip change(all clips in the clip line)	
							// send play envet to ableton cc 20 with value 127 to channel 16
							//MIOS32_MIDI_SendCC(ableton_port, 15, 20, 127);

						}
						
						//
						// Autosave Pattern
						//
						if (auto_save) {
							
							// Autosave all 4 group of patterns
							for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group) {
								
								// Save to SD Card
								if( (status=SEQ_PATTERN_Save(group, seq_pattern[group])) < 0 ) {
									SEQ_UI_SDCardErrMsg(2000, status);
								}
								
							}
							
							// Autosave Mixer Map
							SEQ_MIXER_Save(SEQ_MIXER_NumGet());
							
						}							
						
						// if we are not in remix mode 
						if (seq_pattern_remix_map == 0) {
							
							// keep the name of old pattern(because we still got 1 or more tracks belongs to this pattern)
							//pattern_name = seq_pattern_name;
							// set timer for mixed pattern
							pattern_remix_timer = MIOS32_SYS_TimeGet();
						}								
						
						//
						// Pattern change request
						//
            for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group) {

              // change pattern
              //selected_pattern[group].num = button-8;
              SEQ_PATTERN_Change(group, selected_pattern[group], 0);

							//if ( remix_mode ) {
								// keep the pattern name...
								//sprintf(seq_pattern_name[group], pattern_name);
							//}
							
            }
						
						if ( !remix_mode ) {
							// copy the pattern name for future reference
							//sprintf(pattern_name, seq_pattern_name[0]);	
							SEQ_PATTERN_PeekName(selected_pattern[0], pattern_name);
							// TODO: sync this with the pattern change handled by SEQ_PATTERN_Handler()
							//pattern_timer.seconds = 0;		
							preview_mode = 0;
						}
						
						// support for demix
            seq_pattern_demix_map = seq_pattern_remix_map;

            //preview_mode = 0;
						
          // Request a Pattern Preview
          } else {
            preview_num = button-8;
            SEQ_PATTERN_PeekName(selected_pattern[0], preview_name);

        	  // for security reasons in live environment, we can not accept 2x rapid press of pattern button.
      	    // if the buttons are not good quality they can send a 2x rapid signal os pressing in just one physical pressing
    	      // the time we need is bassicly the human time to read the name of patterns requested
  	        // start time in count
	          pc_time_control = seq_core_timestamp_ms + 200;

          }

        }			
				
        return 1; // value always changed
      }

      u8 visible_track = SEQ_UI_VisibleTrackGet();

      switch( button ) {

        case SEQ_UI_BUTTON_Right:
          // switch to next track
          if( visible_track < (SEQ_CORE_NUM_TRACKS - 1) )
            visible_track++;
					
          ui_selected_tracks = (1 << visible_track);
          ui_selected_group = visible_track / 4;

          return 1; // value always changed

        case SEQ_UI_BUTTON_Left:
          // switch to previous track
          if( visible_track >= 1 )
            visible_track--;
					
          ui_selected_tracks = (1 << visible_track);
          ui_selected_group = visible_track / 4;

          return 1; // value always changed

        case SEQ_UI_BUTTON_Up:
          return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

        case SEQ_UI_BUTTON_Down:
          return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
      }

      return -1; // invalid or unsupported button

    } break;

    ///////////////////////////////////////////////////////////////////////////
    // Page do not exist
    default:
      break;

  }
	
	return 0;

}
/////////////////////////////////////////////////////////////////////////////
// Local encoder callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported encoder
/////////////////////////////////////////////////////////////////////////////
static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer)
{
  u8 visible_track = SEQ_UI_VisibleTrackGet();
  int num_steps = SEQ_TRG_NumStepsGet(visible_track);
  int track_length = (int)SEQ_CC_Get(visible_track, SEQ_CC_LENGTH) + 1;

#if 0
  // leads to: comparison is always true due to limited range of data type
  if( (encoder >= SEQ_UI_ENCODER_GP1 && encoder <= SEQ_UI_ENCODER_GP16) ) {
#else
  if( encoder <= SEQ_UI_ENCODER_GP16 ) {
#endif
    if( seq_ui_button_state.SELECT_PRESSED ) {
      int section;
      if( num_steps > 128 )
	section = encoder / (track_length / 16);
      else if( num_steps > 64 )
	section = encoder / ((2 * track_length) / 16);
      else
	section = encoder / ((4 * track_length) / 16);

      // operation should be atomic (change all selected tracks)
      u8 track;
      seq_core_trk_t *t = &seq_core_trk[0];
      MIOS32_IRQ_Disable();
      for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track, ++t)
	if( ui_selected_tracks & (1 << track) )
	  t->play_section = section;
      MIOS32_IRQ_Enable();
    } else {
      // won't work if Follow function active!
      if( seq_core_state.FOLLOW ) {
	// print message and exit
	SEQ_UI_Msg((encoder <= SEQ_UI_ENCODER_GP8) ? SEQ_UI_MSG_USER : SEQ_UI_MSG_USER_R, 2000, "\"Follow\" active!", "Please deactivate!");
	return 1;
      }
    }

    // select new step view
    ui_selected_step_view = (encoder * (num_steps/16)) / 16;

    // select step within view
    if( !seq_ui_button_state.CHANGE_ALL_STEPS ) { // don't change the selected step if ALL function is active, otherwise the ramp can't be changed over multiple views
      ui_selected_step = (ui_selected_step_view << 4) | (ui_selected_step & 0xf);
    }

    if( seq_hwcfg_button_beh.step_view ) {
      // if toggle function active: jump back to previous menu
      // this is especially useful for the emulated MBSEQ, where we can only click on a single button
      // (stepview gets deactivated when clicking on GP button)
      if( seq_ui_button_state.STEP_VIEW ) {
	seq_ui_button_state.STEP_VIEW = 0;
	SEQ_UI_PageSet(ui_stepview_prev_page);
      }
    }

    return 1; // value changed
  } else if( encoder == SEQ_UI_ENCODER_Datawheel ) {
    if( SEQ_UI_Var8_Inc(&ui_selected_step_view, 0, (num_steps-1)/16, incrementer) >= 1 ) {
      // select step within view
      if( !seq_ui_button_state.CHANGE_ALL_STEPS ) { // don't change the selected step if ALL function is active, otherwise the ramp can't be changed over multiple views
	ui_selected_step = (ui_selected_step_view << 4) | (ui_selected_step & 0xf);
      }
    } else {
      return 0;
    }
  }

  return -1; // invalid or unsupported encoder
}


/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return 0; // ignore when button depressed

#if 0
  // leads to: comparison is always true due to limited range of data type
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
#else
  if( button <= SEQ_UI_BUTTON_GP16 ) {
#endif
    // -> same handling like for encoders
    return Encoder_Handler(button, 0);
  }

  switch( button ) {
    case SEQ_UI_BUTTON_Select:
      return 1; // selects section mode, checked via seq_ui_button_state.SELECT_PRESSED

    case SEQ_UI_BUTTON_Right:
    case SEQ_UI_BUTTON_Up:
      if( depressed ) return 0; // ignore when button depressed
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Left:
    case SEQ_UI_BUTTON_Down:
      if( depressed ) return 0; // ignore when button depressed
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  // 1                   17                  33                  49
  // *... *... *... *... *... *... *... *... *... *... *... *... *... *... *... *... 


  // 5 character usage in 256 step view (5 chars have to display 16 steps, 8 special chars available,
  // due to this limitation, we only display 15 steps (shouldn't really hurt))
  // 43210 43210 43210 43210 43210
  // * * * * . . . * . . . * . . .  (Small charset)

  // 5 character usage in 128 step view (5 chars have to display 8 steps):
  // 43210 43210 43210 43210 43210
  //  * *   . *   * .   . .         (Medium charset)

  // 5 character usage in 64 step view (5 chars have to display 4 steps):
  // 43210 43210 43210 43210 43210
  //   *     *     *     *     *    (Big charset)

  u8 visible_track = SEQ_UI_VisibleTrackGet();
  u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);
  int num_steps = SEQ_TRG_NumStepsGet(visible_track);
  int steps_per_item = num_steps / 16;
  int played_step = SEQ_BPM_IsRunning() ? seq_core_trk[visible_track].step : -1;

  int i;

  if( !high_prio ) {
    SEQ_LCD_CursorSet(0, 0);
    for(i=0; i<16; ++i)
      if( ((i*steps_per_item) % 16) || ((((i*steps_per_item)/16) == ui_selected_step_view) && ui_cursor_flash) )
	SEQ_LCD_PrintSpaces(5);
      else
	SEQ_LCD_PrintFormattedString("%-3d  ", i*steps_per_item+1);

    // print flashing *LOOPED* at right corner if loop mode activated to remind that steps will be played differntly
    if( (ui_cursor_flash_overrun_ctr & 1) && seq_core_state.LOOP ) {
      SEQ_LCD_CursorSet(71, 0);
      SEQ_LCD_PrintString(" *LOOPED*");
    } else if( (ui_cursor_flash_overrun_ctr & 1) && seq_core_trk[visible_track].play_section > 0 ) {
      SEQ_LCD_CursorSet(71, 0);
      SEQ_LCD_PrintFormattedString(" *Sect.%c*", 'A'+seq_core_trk[visible_track].play_section);
    } else {
      if( event_mode == SEQ_EVENT_MODE_Drum ) {
	// print drum name at the rightmost side
	SEQ_LCD_CursorSet(75, 0);
	SEQ_LCD_PrintTrackDrum(visible_track, ui_selected_instrument, (char *)seq_core_trk[visible_track].name);
      } else {
	// print trigger layer and name at the rightmost side
	SEQ_LCD_CursorSet(73, 0);
	SEQ_LCD_PrintFormattedString("%c:%s", 'A' + ui_selected_trg_layer, SEQ_TRG_AssignedTypeStr(visible_track, ui_selected_trg_layer));
      }
    }
  }

  SEQ_LCD_CursorSet(0, 1);

  if( steps_per_item > 8 ) {
    SEQ_LCD_InitSpecialChars(SEQ_LCD_CHARSET_DrumSymbolsSmall);

    for(i=0; i<16; ++i) {
      u16 step = i*steps_per_item;
      u8 step8 = step / 8;

      u8 layer = (event_mode == SEQ_EVENT_MODE_Drum) ? 0 : ui_selected_trg_layer;
      u16 steps = (SEQ_TRG_Get8(visible_track, step8+1, layer, ui_selected_instrument) << 8) |
	          (SEQ_TRG_Get8(visible_track, step8+0, layer, ui_selected_instrument) << 0);

      if( played_step >= step && played_step < (step+16) )
	steps ^= (1 << (played_step % 16));

      int j;
      for(j=0; j<5; ++j) {
	SEQ_LCD_PrintChar(steps & 0x7);
	steps >>= 3;
      }
    }
  } else if( steps_per_item > 4 ) {
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return 0; // ignore when button depressed

#if 0
  // leads to: comparison is always true due to limited range of data type
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
#else
  if( button <= SEQ_UI_BUTTON_GP16 ) {
#endif
    // re-use encoder handler - only select UI item, don't increment
    return Encoder_Handler((int)button, 0);
  }

  // remaining buttons:
  switch( button ) {
    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
      if( ++ui_selected_item >= NUM_OF_ITEMS )
	ui_selected_item = 0;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Left:
      if( ui_selected_item == 0 )
	ui_selected_item = NUM_OF_ITEMS-1;
      else
	--ui_selected_item;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Up:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Down:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  if( high_prio )
    return 0; // there are no high-priority updates

  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  // Trk. Wave Amp. Phs. Steps Rst OneShot   Note Vel. Len.  CC   ExtraCC# Offs. PPQN
  // GxTy Sine   64   0%   16   16  on        off  off  off  off        001   64  384

  u8 visible_track = SEQ_UI_VisibleTrackGet();

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 0);
  SEQ_LCD_PrintString("Trk. Wave Amp. Phs. Steps Rst OneShot   Note Vel. Len.  CC   ExtraCC# Offs. PPQN");

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 1);

  if( ui_selected_item == ITEM_GXTY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks);
  }
  SEQ_LCD_PrintSpaces(1);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_WAVEFORM && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    u8 value = SEQ_CC_Get(visible_track, SEQ_CC_LFO_WAVEFORM);

    if( value <= 3 ) {
      const char waveform_str[4][6] = {
	" off ",
	"Sine ",
	"Tri. ",
	"Saw. "
      };

      SEQ_LCD_PrintString((char *)waveform_str[value]);
    } else {
      SEQ_LCD_PrintFormattedString(" R%02d ", (value-4+1)*5);
    }
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_AMPLITUDE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    int value = (int)SEQ_CC_Get(visible_track, SEQ_CC_LFO_AMPLITUDE) - 128;
    SEQ_LCD_PrintFormattedString("%4d ", value);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_PHASE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(6);
  } else {
    SEQ_LCD_PrintFormattedString("%3d%%  ", SEQ_CC_Get(visible_track, SEQ_CC_LFO_PHASE));
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_STEPS && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintFormattedString("%3d  ", (int)SEQ_CC_Get(visible_track, SEQ_CC_LFO_STEPS)+1);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_STEPS_RST && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintFormattedString("%3d ", (int)SEQ_CC_Get(visible_track, SEQ_CC_LFO_STEPS_RST)+1);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_ENABLE_ONE_SHOT && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 0)) ? "  on " : " off ");
  }

  SEQ_LCD_PrintSpaces(5);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_ENABLE_NOTE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 1)) ? "  on " : " off ");
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_ENABLE_VELOCITY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 2)) ? "  on " : " off ");
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_ENABLE_LENGTH && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 3)) ? "  on " : " off ");
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_ENABLE_CC && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 4)) ? "  on " : " off ");
  }

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_PrintSpaces(5);
  if( ui_selected_item == ITEM_CC && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    u8 current_value = SEQ_CC_Get(visible_track, SEQ_CC_LFO_CC);
    u8 edit_value = (ui_selected_item == ITEM_CC) ? edit_cc_number : current_value;

    if( edit_value )
      SEQ_LCD_PrintFormattedString(" %03d", edit_value);
    else
      SEQ_LCD_PrintString(" ---");
    SEQ_LCD_PrintChar((current_value != edit_value) ? '!' : ' ');
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_CC_OFFSET && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintFormattedString(" %3d ", SEQ_CC_Get(visible_track, SEQ_CC_LFO_CC_OFFSET));
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_CC_PPQN && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    u8 value = SEQ_CC_Get(visible_track, SEQ_CC_LFO_CC_PPQN);
    int ppqn = 1;
    if( value )
      ppqn = 3 << (value-1);

    SEQ_LCD_PrintFormattedString(" %3d ", ppqn);
  }

  ///////////////////////////////////////////////////////////////////////////

  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_FX_LFO_Init(u32 mode)
{
  // install callback routines
  SEQ_UI_InstallButtonCallback(Button_Handler);
  SEQ_UI_InstallEncoderCallback(Encoder_Handler);
  SEQ_UI_InstallLEDCallback(LED_Handler);
  SEQ_UI_InstallLCDCallback(LCD_Handler);

  return 0; // no error
}
Exemple #16
0
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return 0; // ignore when button depressed

#if 0
  // leads to: comparison is always true due to limited range of data type
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
#else
  if( button <= SEQ_UI_BUTTON_GP16 ) {
#endif
    // re-use encoder handler - only select UI item, don't increment, flags will be toggled
    return Encoder_Handler((int)button, 0);
  }

  // remaining buttons:
  switch( button ) {
    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
      if( depressed ) return -1;
      if( ++ui_selected_item >= NUM_OF_ITEMS )
	ui_selected_item = 0;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Left:
      if( depressed ) return -1;
      if( ui_selected_item == 0 )
	ui_selected_item = NUM_OF_ITEMS-1;
      else
	--ui_selected_item;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Up:
      if( depressed ) return -1;
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Down:
      if( depressed ) return -1;
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  if( high_prio )
    return 0; // there are no high-priority updates

  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  //  CV  Curve SlewRate PRng  Gate  Calibr.  Clk   Rate    Width             Module 
  //   1  V/Oct    0 mS    2   Pos.    off     1   24 PPQN   1 mS             AOUT_NG


  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 0);
  SEQ_LCD_PrintString(" CV  Curve SlewRate PRng  Gate  Calibr.  Clk   Rate    Width             Module ");

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 1);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_CV && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintFormattedString(" %2d  ", selected_cv+1);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_CURVE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(6);
  } else {
    SEQ_LCD_PrintString((char *)SEQ_CV_CurveNameGet(selected_cv));
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_SLEWRATE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(9);
  } else {
    SEQ_LCD_PrintFormattedString(" %3d mS  ", SEQ_CV_SlewRateGet(selected_cv));
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_PITCHRANGE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(6);
  } else {
    SEQ_LCD_PrintFormattedString("%3d   ", SEQ_CV_PitchRangeGet(selected_cv));
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GATE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(6);
  } else {
    SEQ_LCD_PrintFormattedString(SEQ_CV_GateInversionGet(selected_cv) ? "Neg.  " : "Pos.  ");
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_CALIBRATION && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(8);
  } else {
    SEQ_LCD_PrintFormattedString(" %s ", SEQ_CV_CaliNameGet());
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_CLK_SEL && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintFormattedString("%3d ", selected_clkout + 1);
  }
  SEQ_LCD_PrintSpaces(2);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_CLK_PPQN && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(9);
  } else {
    u16 divider = SEQ_CV_ClkDividerGet(selected_clkout);
    if( !divider ) {
      SEQ_LCD_PrintFormattedString("StartStop", 384 / divider);
    } else {
      SEQ_LCD_PrintFormattedString("%3d PPQN ", 384 / divider);
    }
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_CLK_WIDTH && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(6);
  } else {
    SEQ_LCD_PrintFormattedString("%3d mS", SEQ_CV_ClkPulseWidthGet(selected_clkout));
  }

  SEQ_LCD_PrintSpaces(12);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_MODULE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(8);
  } else {
    SEQ_LCD_PrintString((char *)SEQ_CV_IfNameGet(SEQ_CV_IfGet()));
  }


  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// Local exit function
/////////////////////////////////////////////////////////////////////////////
static s32 EXIT_Handler(void)
{
  s32 status = 0;

  // ensure that calibration mode disabled
  SEQ_CV_CaliModeSet(selected_cv, AOUT_CALI_MODE_OFF);

  if( store_file_required ) {
    // write config file
    MUTEX_SDCARD_TAKE;
    if( (status=SEQ_FILE_GC_Write()) < 0 )
      SEQ_UI_SDCardErrMsg(2000, status);
    MUTEX_SDCARD_GIVE;

    store_file_required = 0;
  }

  return status;
}
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return 0; // ignore when button depressed

#if 0
  // leads to: comparison is always true due to limited range of data type
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
#else
  if( button <= SEQ_UI_BUTTON_GP16 ) {
#endif
    // re-use encoder handler - only select UI item, don't increment, flags will be toggled
    return Encoder_Handler((int)button, 0);
  }

  // remaining buttons:
  switch( button ) {
    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
      if( depressed ) return -1;
      if( ++ui_selected_item >= NUM_OF_ITEMS )
	ui_selected_item = 0;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Left:
      if( depressed ) return -1;
      if( ui_selected_item == 0 )
	ui_selected_item = NUM_OF_ITEMS-1;
      else
	--ui_selected_item;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Up:
      if( depressed ) return -1;
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Down:
      if( depressed ) return -1;
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  if( high_prio )
    return 0; // there are no high-priority updates

  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  //  Control  Root      Selected Scale      
  //  Global   Keyb   50:Hungarian Gypsy    


  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 0);
  SEQ_LCD_PrintString(" Control  Root      Selected Scale      ");
  SEQ_LCD_PrintSpaces(40);

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 1);
  SEQ_LCD_PrintSpaces(1);

  if( ui_selected_item == ITEM_SCALE_CTRL && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(8);
  } else {
    if( seq_core_global_scale_ctrl )
      SEQ_LCD_PrintFormattedString("Group G%d", seq_core_global_scale_ctrl);
    else
      SEQ_LCD_PrintString("Global  ");
  }
  SEQ_LCD_PrintSpaces(1);

  ///////////////////////////////////////////////////////////////////////////

  // determine the selected scale and root note selection depending on
  // global/group specific settings
  u8 scale, root_selection, root;
  SEQ_CORE_FTS_GetScaleAndRoot(&scale, &root_selection, &root);

  if( ui_selected_item == ITEM_SCALE_ROOT && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    const char root_str[13][5] = {
      "Keyb", " C  ", " C# ", " D  ", " D# ", " E  ", " F  ", " F# ", " G  ", " G# ", " A  ", " A# ", " B  "
    };
    SEQ_LCD_PrintString((char *)root_str[root_selection]);
  }
  SEQ_LCD_PrintSpaces(2);


  if( ui_selected_item == ITEM_SCALE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(24);
  } else {
    SEQ_LCD_PrintFormattedString("%3d:", scale);
    SEQ_LCD_PrintString(SEQ_SCALE_NameGet(scale));
  }

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_PrintSpaces(40);

  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// Local exit function
/////////////////////////////////////////////////////////////////////////////
static s32 EXIT_Handler(void)
{
  s32 status = 0;

  if( ui_store_file_required ) {
    // write config file
    MUTEX_SDCARD_TAKE;
    if( (status=SEQ_FILE_C_Write(seq_file_session_name)) < 0 )
      SEQ_UI_SDCardErrMsg(2000, status);
    MUTEX_SDCARD_GIVE;

    ui_store_file_required = 0;
  }

  return status;
}
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return 0; // ignore when button depressed

#if 0
  // leads to: comparison is always true due to limited range of data type
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
#else
  if( button <= SEQ_UI_BUTTON_GP16 ) {
#endif
    // re-use encoder handler - only select UI item, don't increment
    return Encoder_Handler((int)button, 0);
  }

  // remaining buttons:
  switch( button ) {
    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
      if( ++ui_selected_item >= NUM_OF_ITEMS )
	ui_selected_item = 0;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Left:
      if( ui_selected_item == 0 )
	ui_selected_item = NUM_OF_ITEMS-1;
      else
	--ui_selected_item;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Up:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Down:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  if( high_prio )
    return 0; // there are no high-priority updates

  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  // Trk.        Repeats   Delay   Vel.Level  FB Velocity  Note   Gatelen.    Ticks  
  // GxTy           3       1/16      75%        120%       + 0     100%       100%

  u8 visible_track = SEQ_UI_VisibleTrackGet();

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 0);
  SEQ_LCD_PrintString("Trk.        Repeats   Delay   Vel.Level  FB Velocity  Note   Gatelen.    Ticks  ");

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 1);

  if( ui_selected_item == ITEM_GXTY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks);
  }
  SEQ_LCD_PrintSpaces(10);

  ///////////////////////////////////////////////////////////////////////////

  if( ui_selected_item == ITEM_REPEATS && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(2);
  } else {
    SEQ_LCD_PrintFormattedString("%2d", SEQ_CC_Get(visible_track, SEQ_CC_ECHO_REPEATS));
  }
  SEQ_LCD_PrintSpaces(7);

  ///////////////////////////////////////////////////////////////////////////

  if( ui_selected_item == ITEM_DELAY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintString((char *)SEQ_CORE_Echo_GetDelayModeName(SEQ_CC_Get(visible_track, SEQ_CC_ECHO_DELAY)));
  }
  SEQ_LCD_PrintSpaces(6);

  ///////////////////////////////////////////////////////////////////////////

  if( ui_selected_item == ITEM_VELOCITY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintFormattedString("%3d%%", 5*SEQ_CC_Get(visible_track, SEQ_CC_ECHO_VELOCITY));
  }
  SEQ_LCD_PrintSpaces(2);

  ///////////////////////////////////////////////////////////////////////////

  SEQ_LCD_CursorSet(40, 1);
  SEQ_LCD_PrintSpaces(4);

  if( ui_selected_item == ITEM_FB_VELOCITY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintFormattedString("%3d%%", 5*SEQ_CC_Get(visible_track, SEQ_CC_ECHO_FB_VELOCITY));
  }
  SEQ_LCD_PrintSpaces(7);

  ///////////////////////////////////////////////////////////////////////////

  if( ui_selected_item == ITEM_FB_NOTE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(3);
  } else {
    u8 note_delta = SEQ_CC_Get(visible_track, SEQ_CC_ECHO_FB_NOTE);
    if( note_delta < 24 )
      SEQ_LCD_PrintFormattedString("-%2d", 24-note_delta);
    else if( note_delta < 49 )
      SEQ_LCD_PrintFormattedString("+%2d", note_delta-24);
    else
      SEQ_LCD_PrintString("Rnd");
  }
  SEQ_LCD_PrintSpaces(5);

  ///////////////////////////////////////////////////////////////////////////

  if( ui_selected_item == ITEM_FB_GATELENGTH && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintFormattedString("%3d%%", 5*SEQ_CC_Get(visible_track, SEQ_CC_ECHO_FB_GATELENGTH));
  }
  SEQ_LCD_PrintSpaces(7);

  ///////////////////////////////////////////////////////////////////////////

  if( ui_selected_item == ITEM_FB_TICKS && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintFormattedString("%3d%%", 5*SEQ_CC_Get(visible_track, SEQ_CC_ECHO_FB_TICKS));
  }
  SEQ_LCD_PrintSpaces(2);


  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_FX_ECHO_Init(u32 mode)
{
  // install callback routines
  SEQ_UI_InstallButtonCallback(Button_Handler);
  SEQ_UI_InstallEncoderCallback(Encoder_Handler);
  SEQ_UI_InstallLEDCallback(LED_Handler);
  SEQ_UI_InstallLCDCallback(LCD_Handler);

  return 0; // no error
}
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return -1; // ignore when button depressed, -1 ensures that message still print

  if( button <= SEQ_UI_BUTTON_GP16 || button == SEQ_UI_BUTTON_Select ) {

    if( button != SEQ_UI_BUTTON_Select )
      ui_selected_item = button / 2;

#if TEST_LIST
    char buffer[30];
    int i;
    for(i=0; i<LIST_ENTRY_WIDTH; ++i)
      buffer[i] = ui_global_dir_list[LIST_ENTRY_WIDTH*ui_selected_item + i];
    buffer[i] = 0;

    SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Selected:", buffer);
#else
    if( dir_name[0] == 0 && dir_num_items >= 0 ) {
      // Select MIDI Device
      int i;
      char *p = (char *)&dir_name[0];
      for(i=0; i<8; ++i) {
	char c = ui_global_dir_list[LIST_ENTRY_WIDTH*ui_selected_item + i];
	if( c != ' ' )
	  *p++ = c;
      }
      *p++ = 0;
      ui_selected_item = 0;
      dir_view_offset = 0;
      SEQ_UI_SYSEX_UpdateDirList();
    } else {
      switch( button ) {
        case SEQ_UI_BUTTON_GP15:
	  // increment MIDI port
	  return Encoder_Handler(button, 1);

        case SEQ_UI_BUTTON_GP16:
	  // EXIT
	  return Encoder_Handler(button, 0);

        default:
          if( dir_num_items >= 1 && (ui_selected_item+dir_view_offset) < dir_num_items ) {
	    // Send SysEx Dump
	    char syx_file[30];
	    int i;
	    char *p = (char *)&syx_file[0];
	    for(i=0; i<8; ++i) {
	      char c = ui_global_dir_list[LIST_ENTRY_WIDTH*ui_selected_item + i];
	      if( c != ' ' )
		*p++ = c;
	    }
	    *p++ = 0;

	    char path[40];
	    sprintf(path, "/SYSEX/%s/%s.SYX", dir_name, syx_file);
	    SEQ_UI_Msg((ui_selected_item < 4) ? SEQ_UI_MSG_USER : SEQ_UI_MSG_USER_R, 10000, "Sending:", syx_file);
	    MUTEX_SDCARD_TAKE;
	    MUTEX_MIDIOUT_TAKE;
	    s32 status = FILE_SendSyxDump(path, sysex_port);
	    MUTEX_MIDIOUT_GIVE;
	    MUTEX_SDCARD_GIVE;
	    if( status < 0 )
	      SEQ_UI_SDCardErrMsg(2000, status);
	    else {
	      char buffer[20];
	      sprintf(buffer, "Sent %d bytes", status);
	      SEQ_UI_Msg((ui_selected_item < 4) ? SEQ_UI_MSG_USER : SEQ_UI_MSG_USER_R, 1000, buffer, syx_file);
	    }
	  }
      }
    }
#endif

    return 1;
  }

  switch( button ) {
    case SEQ_UI_BUTTON_Right:
    case SEQ_UI_BUTTON_Up:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Left:
    case SEQ_UI_BUTTON_Down:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}
Exemple #20
0
/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return 0; // ignore when button depressed

  u8 visible_track = SEQ_UI_VisibleTrackGet();

#if 0
  // leads to: comparison is always true due to limited range of data type
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
#else
  if( button <= SEQ_UI_BUTTON_GP15 ) {
#endif
    // re-use encoder handler - only select UI item, don't increment
    return Encoder_Handler((int)button, 0);
  }

  // remaining buttons:
  switch( button ) {
    case SEQ_UI_BUTTON_GP16: {
      if( SEQ_GROOVE_Clear(SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_STYLE)) < 0 )
	SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Preset", "not editable!");
      else
	SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Groove", "cleared!");
    } break;

    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
      if( ++ui_selected_item >= NUM_OF_ITEMS )
	ui_selected_item = 0;

      return 1; // value always changed

    case SEQ_UI_BUTTON_Left:
      if( ui_selected_item == 0 )
	ui_selected_item = NUM_OF_ITEMS-1;
      else
	--ui_selected_item;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Up:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Down:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  if( high_prio )
    return 0; // there are no high-priority updates

  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  // Trk.  Groove Style  Intensity Change forStep Dly. Len. Vel. NumSteps        Clr 
  // G1T1  Inv. Shuffle     15     all Tracks  1    0    0    0  Preset not editable!


  u8 visible_track = SEQ_UI_VisibleTrackGet();
  u8 selected_groove = SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_STYLE);
  seq_groove_entry_t *g;
  if( selected_groove >= SEQ_GROOVE_NUM_PRESETS )
    g = (seq_groove_entry_t *)&seq_groove_templates[selected_groove-SEQ_GROOVE_NUM_PRESETS];
  else
    g = (seq_groove_entry_t *)&seq_groove_presets[selected_groove];


  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 0);

  SEQ_LCD_PrintString("Trk.  Groove Style  Intensity ");
  if( ui_selected_item == ITEM_GROOVE_VALUE_GLB && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(10);
  } else {
    SEQ_LCD_PrintString("Change for");
  }
  SEQ_LCD_PrintString("Step Dly. Len. Vel. NumSteps        Clr ");


  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 1);

  if( ui_selected_item == ITEM_GXTY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks);
  }
  SEQ_LCD_PrintSpaces(2);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GROOVE_STYLE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(12);
  } else {
    SEQ_LCD_PrintString(SEQ_GROOVE_NameGet(selected_groove));
  }
  SEQ_LCD_PrintSpaces(5);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GROOVE_VALUE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(3);
  } else {
    SEQ_LCD_PrintFormattedString("%3d", SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_VALUE));
  }
  SEQ_LCD_PrintSpaces(4);


  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GROOVE_VALUE_GLB && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(10);
  } else {
    SEQ_LCD_PrintString("all Tracks");
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GROOVE_STEP && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintFormattedString(" %2d ", edit_step+1);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GROOVE_DELAY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    int value = g->add_step_delay[edit_step];
    if( value <= -128 )
      SEQ_LCD_PrintString("VNEG ");
    else if( value >= 127 )
      SEQ_LCD_PrintString("VPOS ");
    else
      SEQ_LCD_PrintFormattedString("%4d ", value);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GROOVE_LENGTH && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    int value = g->add_step_length[edit_step];
    if( value <= -128 )
      SEQ_LCD_PrintString("VNEG ");
    else if( value >= 127 )
      SEQ_LCD_PrintString("VPOS ");
    else
      SEQ_LCD_PrintFormattedString("%4d ", value);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GROOVE_VELOCITY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    int value = g->add_step_velocity[edit_step];
    if( value <= -128 )
      SEQ_LCD_PrintString("VNEG ");
    else if( value >= 127 )
      SEQ_LCD_PrintString("VPOS ");
    else
      SEQ_LCD_PrintFormattedString("%4d ", value);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( selected_groove >= SEQ_GROOVE_NUM_PRESETS ) {
    if( ui_selected_item == ITEM_GROOVE_NUM_STEPS && ui_cursor_flash ) {
      SEQ_LCD_PrintSpaces(6);
    } else {
      SEQ_LCD_PrintFormattedString("  %2d  ", g->num_steps);
    }    
    SEQ_LCD_PrintSpaces(15);
  } else {
    if( ui_cursor_flash && ui_selected_item >= ITEM_GROOVE_LENGTH && ui_selected_item <= ITEM_GROOVE_DELAY )
      SEQ_LCD_PrintSpaces(21);
    else
      SEQ_LCD_PrintString(" Preset not editable!");
  }

  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// Local exit function
/////////////////////////////////////////////////////////////////////////////
static s32 EXIT_Handler(void)
{
  s32 status = 0;

  if( ui_store_file_required ) {
    // write config file
    MUTEX_SDCARD_TAKE;
    if( (status=SEQ_FILE_G_Write(seq_file_session_name)) < 0 )
      SEQ_UI_SDCardErrMsg(2000, status);
    MUTEX_SDCARD_GIVE;

    ui_store_file_required = 0;
  }

  return status;
}
Exemple #21
0
/////////////////////////////////////////////////////////////////////////////
// Local encoder callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported encoder
/////////////////////////////////////////////////////////////////////////////
static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer)
{
#if 0
  // leads to: comparison is always true due to limited range of data type
  if( (encoder >= SEQ_UI_ENCODER_GP1 && encoder <= SEQ_UI_ENCODER_GP16) ) {
#else
  if( encoder <= SEQ_UI_ENCODER_GP16 ) {
#endif
    if( seq_ui_button_state.SELECT_PRESSED ) {
      // select button pressed: indirect MUTED flag modification (taken over when select button depressed)
      u16 mask = 1 << encoder;
      if( incrementer < 0 || (incrementer == 0 && !(latched_mute & mask)) )
	latched_mute |= mask;
      else
	latched_mute &= ~mask;
    } else {
      // select button not pressed: direct MUTED flag modification
      // access to seq_core_trk[] must be atomic!
      portENTER_CRITICAL();

      u8 visible_track = SEQ_UI_VisibleTrackGet();
      u16 mask = 1 << encoder;
      u16 *muted = seq_ui_button_state.MUTE_PRESSED ? (u16 *)&seq_core_trk[visible_track].layer_muted : (u16 *)&seq_core_trk_muted;

      if( incrementer < 0 )
	*muted |= mask;
      else if( incrementer > 0 )
	*muted &= ~mask;
      else
	*muted ^= mask;

      portEXIT_CRITICAL();
    }

    return 1; // value changed
  }

  return -1; // invalid or unsupported encoder
}


/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
#if 0
  // leads to: comparison is always true due to limited range of data type
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
#else
  if( button <= SEQ_UI_BUTTON_GP16 ) {
#endif
    if( depressed ) return 0; // ignore when button depressed

    // re-using encoder routine
    return Encoder_Handler(button, 0);
  }

  switch( button ) {
    case SEQ_UI_BUTTON_Select:
      portENTER_CRITICAL();
      if( depressed ) {
	// select button released: take over latched mutes
	if( seq_ui_button_state.MUTE_PRESSED ) {
	  u8 visible_track = SEQ_UI_VisibleTrackGet();
	  seq_core_trk[visible_track].layer_muted = latched_mute;
	} else {
	  seq_core_trk_muted = latched_mute;
	}
      } else {
	// select pressed: init latched mutes which will be taken over once SELECT button released
	if( seq_ui_button_state.MUTE_PRESSED ) {
	  u8 visible_track = SEQ_UI_VisibleTrackGet();
	  latched_mute = seq_core_trk[visible_track].layer_muted;
	} else {
	  latched_mute = seq_core_trk_muted;
	}
      }

      portEXIT_CRITICAL();
      return 1;
  }

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  //  > 1<   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16 
  // ...horizontal VU meters...

  if( high_prio ) {
    ///////////////////////////////////////////////////////////////////////////
    // frequently update VU meters
    SEQ_LCD_CursorSet(0, 1);

    u8 track;
    u16 mute_flags = 0;

    if( !ui_cursor_flash && seq_ui_button_state.SELECT_PRESSED ) {
      mute_flags = latched_mute;
    } else {
      if( seq_ui_button_state.MUTE_PRESSED ) {
	u8 visible_track = SEQ_UI_VisibleTrackGet();
	mute_flags = seq_core_trk[visible_track].layer_muted;
      } else {
	mute_flags = seq_core_trk_muted;
      }
    }

    if( seq_ui_button_state.MUTE_PRESSED ) {
      u8 layer;
      for(layer=0; layer<16; ++layer)
	if( mute_flags & (1 << layer) )
	  SEQ_LCD_PrintString("Mute ");
	else
	  SEQ_LCD_PrintHBar((seq_layer_vu_meter[layer] >> 3) & 0xf);
    } else {
      seq_core_trk_t *t = &seq_core_trk[0];
      for(track=0; track<16; ++t, ++track)
	if( mute_flags & (1 << track) )
	  SEQ_LCD_PrintString("Mute ");
	else
	  SEQ_LCD_PrintHBar(t->vu_meter >> 3);
    }
  } else {