///////////////////////////////////////////////////////////////////////////// // 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 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) { seq_midi_router_node_t *n = &seq_midi_router_node[selected_router_node]; if( encoder <= SEQ_UI_ENCODER_GP8 ) { switch( encoder ) { case SEQ_UI_ENCODER_GP1: case SEQ_UI_ENCODER_GP2: selected_subpage = SUBPAGE_TRANSPOSE; ui_selected_item = ITEM_IN_BUS; break; case SEQ_UI_ENCODER_GP3: case SEQ_UI_ENCODER_GP4: selected_subpage = SUBPAGE_SECTIONS; ui_selected_item = ITEM_S_PORT; break; case SEQ_UI_ENCODER_GP5: case SEQ_UI_ENCODER_GP6: selected_subpage = SUBPAGE_ROUTER; ui_selected_item = ITEM_R_NODE; break; case SEQ_UI_ENCODER_GP7: selected_subpage = SUBPAGE_EXT_CTRL; ui_selected_item = ITEM_EXT_PORT; break; default: selected_subpage = SUBPAGE_MISC; ui_selected_item = ITEM_BLM_SCALAR_PORT; } return 1; } switch( selected_subpage ) { case SUBPAGE_TRANSPOSE: switch( encoder ) { case SEQ_UI_ENCODER_GP9: ui_selected_item = ITEM_IN_BUS; break; case SEQ_UI_ENCODER_GP10: ui_selected_item = ITEM_IN_PORT; break; case SEQ_UI_ENCODER_GP11: ui_selected_item = ITEM_IN_CHN; break; case SEQ_UI_ENCODER_GP12: ui_selected_item = ITEM_IN_LOWER; break; case SEQ_UI_ENCODER_GP13: ui_selected_item = ITEM_IN_UPPER; break; case SEQ_UI_ENCODER_GP14: ui_selected_item = ITEM_IN_MODE; break; case SEQ_UI_ENCODER_GP15: return -1; // not mapped case SEQ_UI_ENCODER_GP16: ui_selected_item = ITEM_RESET_STACKS; break; } break; case SUBPAGE_SECTIONS: switch( encoder ) { case SEQ_UI_ENCODER_GP9: ui_selected_item = ITEM_S_PORT; break; case SEQ_UI_ENCODER_GP10: ui_selected_item = ITEM_S_CHN; break; case SEQ_UI_ENCODER_GP11: ui_selected_item = ITEM_S_OCT_G1; break; case SEQ_UI_ENCODER_GP12: ui_selected_item = ITEM_S_OCT_G2; break; case SEQ_UI_ENCODER_GP13: ui_selected_item = ITEM_S_OCT_G3; break; case SEQ_UI_ENCODER_GP14: ui_selected_item = ITEM_S_OCT_G4; break; case SEQ_UI_ENCODER_GP15: ui_selected_item = ITEM_S_FWD_PORT; break; case SEQ_UI_ENCODER_GP16: ui_selected_item = ITEM_S_RESET_STACKS; break; } break; case SUBPAGE_ROUTER: switch( encoder ) { case SEQ_UI_ENCODER_GP9: ui_selected_item = ITEM_R_NODE; break; case SEQ_UI_ENCODER_GP10: ui_selected_item = ITEM_R_SRC_PORT; break; case SEQ_UI_ENCODER_GP11: ui_selected_item = ITEM_R_SRC_CHN; break; case SEQ_UI_ENCODER_GP12: ui_selected_item = ITEM_R_DST_PORT; break; case SEQ_UI_ENCODER_GP13: ui_selected_item = ITEM_R_DST_CHN; break; case SEQ_UI_ENCODER_GP14: return -1; // not used (yet) case SEQ_UI_ENCODER_GP15: case SEQ_UI_ENCODER_GP16: ui_selected_item = ITEM_DEF_PORT; break; } break; case SUBPAGE_EXT_CTRL: switch( encoder ) { case SEQ_UI_ENCODER_GP9: ui_selected_item = ITEM_EXT_PORT; break; case SEQ_UI_ENCODER_GP10: ui_selected_item = ITEM_EXT_PORT_OUT; break; case SEQ_UI_ENCODER_GP11: ui_selected_item = ITEM_EXT_CHN; break; case SEQ_UI_ENCODER_GP12: case SEQ_UI_ENCODER_GP13: case SEQ_UI_ENCODER_GP14: ui_selected_item = ITEM_EXT_CTRL; break; case SEQ_UI_ENCODER_GP15: case SEQ_UI_ENCODER_GP16: ui_selected_item = ITEM_EXT_VALUE; break; } break; case SUBPAGE_MISC: switch( encoder ) { case SEQ_UI_ENCODER_GP9: case SEQ_UI_ENCODER_GP10: ui_selected_item = ITEM_BLM_SCALAR_PORT; break; case SEQ_UI_ENCODER_GP11: case SEQ_UI_ENCODER_GP12: case SEQ_UI_ENCODER_GP13: case SEQ_UI_ENCODER_GP14: return -1; // not used (yet) case SEQ_UI_ENCODER_GP15: case SEQ_UI_ENCODER_GP16: // enter midi monitor page SEQ_UI_PageSet(SEQ_UI_PAGE_MIDIMON); return 1; } break; default: return -1; // unsupported subpage } // for GP encoders and Datawheel switch( ui_selected_item ) { case ITEM_IN_BUS: { if( SEQ_UI_Var8_Inc(&selected_bus, 0, SEQ_MIDI_IN_NUM_BUSSES-1, incrementer) >= 0 ) { return 1; // value changed } return 0; // no change } break; case ITEM_IN_PORT: { u8 port_ix = SEQ_MIDI_PORT_InIxGet(seq_midi_in_port[selected_bus]); if( SEQ_UI_Var8_Inc(&port_ix, 0, SEQ_MIDI_PORT_InNumGet()-1-4, incrementer) >= 0 ) { // don't allow selection of Bus1..Bus4 seq_midi_in_port[selected_bus] = SEQ_MIDI_PORT_InPortGet(port_ix); store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_IN_CHN: if( SEQ_UI_Var8_Inc(&seq_midi_in_channel[selected_bus], 0, 16, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } return 0; // no change case ITEM_IN_LOWER: if( SEQ_UI_Var8_Inc(&seq_midi_in_lower[selected_bus], 0, 127, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } return 0; // no change case ITEM_IN_UPPER: if( SEQ_UI_Var8_Inc(&seq_midi_in_upper[selected_bus], 0, 127, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } return 0; // no change case ITEM_IN_MODE: { u8 fwd = seq_midi_in_options[selected_bus].MODE_PLAY; if( SEQ_UI_Var8_Inc(&fwd, 0, 1, incrementer) >= 0 ) { seq_midi_in_options[selected_bus].MODE_PLAY = fwd; store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_RESET_STACKS: { SEQ_MIDI_IN_ResetTransArpStacks(); SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 2000, "Transposer/Arp.", "Stacks cleared!"); // send to external SEQ_MIDI_IN_ExtCtrlSend(SEQ_MIDI_IN_EXT_CTRL_ALL_NOTES_OFF, 127, 0); return 1; } break; case ITEM_S_PORT: { u8 port_ix = SEQ_MIDI_PORT_InIxGet(seq_midi_in_sect_port); if( SEQ_UI_Var8_Inc(&port_ix, 0, SEQ_MIDI_PORT_InNumGet()-1, incrementer) >= 0 ) { seq_midi_in_sect_port = SEQ_MIDI_PORT_InPortGet(port_ix); store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_S_CHN: if( SEQ_UI_Var8_Inc(&seq_midi_in_sect_channel, 0, 16, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } return 0; // no change case ITEM_S_OCT_G1: { u8 oct = seq_midi_in_sect_note[0] / 12; if( SEQ_UI_Var8_Inc(&oct, 0, 11, incrementer) >= 0 ) { seq_midi_in_sect_note[0] = 12*oct; store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_S_OCT_G2: { u8 oct = seq_midi_in_sect_note[1] / 12; if( SEQ_UI_Var8_Inc(&oct, 0, 11, incrementer) >= 0 ) { seq_midi_in_sect_note[1] = 12*oct; store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_S_OCT_G3: { u8 oct = seq_midi_in_sect_note[2] / 12; if( SEQ_UI_Var8_Inc(&oct, 0, 11, incrementer) >= 0 ) { seq_midi_in_sect_note[2] = 12*oct; store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_S_OCT_G4: { u8 oct = seq_midi_in_sect_note[3] / 12; if( SEQ_UI_Var8_Inc(&oct, 0, 11, incrementer) >= 0 ) { seq_midi_in_sect_note[3] = 12*oct; store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_S_FWD_PORT: { u8 port_ix = SEQ_MIDI_PORT_OutIxGet(seq_midi_in_sect_fwd_port); if( SEQ_UI_Var8_Inc(&port_ix, 0, SEQ_MIDI_PORT_OutNumGet()-1, incrementer) >= 0 ) { seq_midi_in_sect_fwd_port = SEQ_MIDI_PORT_OutPortGet(port_ix); store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_S_RESET_STACKS: { SEQ_MIDI_IN_ResetChangerStacks(); SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 2000, "Section Changer", "Stacks cleared!"); // send to external SEQ_MIDI_IN_ExtCtrlSend(SEQ_MIDI_IN_EXT_CTRL_ALL_NOTES_OFF, 127, 0); return 1; } break; case ITEM_R_NODE: if( SEQ_UI_Var8_Inc(&selected_router_node, 0, SEQ_MIDI_ROUTER_NUM_NODES-1, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } return 0; // no change case ITEM_R_SRC_PORT: { u8 port_ix = SEQ_MIDI_PORT_InIxGet(n->src_port); if( SEQ_UI_Var8_Inc(&port_ix, 0, SEQ_MIDI_PORT_InNumGet()-1, incrementer) >= 0 ) { n->src_port = SEQ_MIDI_PORT_InPortGet(port_ix); store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_R_SRC_CHN: if( SEQ_UI_Var8_Inc(&n->src_chn, 0, 17, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } return 0; // no change case ITEM_R_DST_PORT: { u8 port_ix = SEQ_MIDI_PORT_OutIxGet(n->dst_port); if( SEQ_UI_Var8_Inc(&port_ix, 0, SEQ_MIDI_PORT_OutNumGet()-1, incrementer) >= 0 ) { n->dst_port = SEQ_MIDI_PORT_OutPortGet(port_ix); store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_R_DST_CHN: if( SEQ_UI_Var8_Inc(&n->dst_chn, 0, 19, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } return 0; // no change case ITEM_DEF_PORT: { u8 port_ix = SEQ_MIDI_PORT_OutIxGet(MIOS32_MIDI_DefaultPortGet()); if( SEQ_UI_Var8_Inc(&port_ix, 0, SEQ_MIDI_PORT_OutNumGet()-1, incrementer) >= 0 ) { MIOS32_MIDI_DefaultPortSet(SEQ_MIDI_PORT_OutPortGet(port_ix)); store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_EXT_PORT: { u8 numPorts = SEQ_MIDI_PORT_InNumGet(); u8 port_ix = (seq_midi_in_ext_ctrl_port == 0xff) ? numPorts : SEQ_MIDI_PORT_InIxGet(seq_midi_in_ext_ctrl_port); if( SEQ_UI_Var8_Inc(&port_ix, 0, numPorts, incrementer) >= 0 ) { seq_midi_in_ext_ctrl_port = (port_ix == numPorts) ? 0xff : SEQ_MIDI_PORT_InPortGet(port_ix); store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_EXT_PORT_OUT: { u8 port_ix = SEQ_MIDI_PORT_OutIxGet(seq_midi_in_ext_ctrl_out_port); if( SEQ_UI_Var8_Inc(&port_ix, 0, SEQ_MIDI_PORT_OutNumGet()-1, incrementer) >= 0 ) { seq_midi_in_ext_ctrl_out_port = SEQ_MIDI_PORT_OutPortGet(port_ix); store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_EXT_CHN: if( SEQ_UI_Var8_Inc(&seq_midi_in_ext_ctrl_channel, 0, 16, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } return 0; // no change case ITEM_EXT_CTRL: if( SEQ_UI_Var8_Inc(&selected_ext_ctrl, 0, SEQ_MIDI_IN_EXT_CTRL_NUM-1, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } return 0; // no change case ITEM_EXT_VALUE: if( selected_ext_ctrl == SEQ_MIDI_IN_EXT_CTRL_NRPN_ENABLED ) { if( SEQ_UI_Var8_Inc(&seq_midi_in_ext_ctrl_asg[selected_ext_ctrl], 0, 1, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } } else if( selected_ext_ctrl == SEQ_MIDI_IN_EXT_CTRL_PC_MODE ) { if( SEQ_UI_Var8_Inc(&seq_midi_in_ext_ctrl_asg[selected_ext_ctrl], 0, SEQ_MIDI_IN_EXT_CTRL_PC_MODE_NUM-1, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } } else if( selected_ext_ctrl <= SEQ_MIDI_IN_EXT_CTRL_NUM ) { if( SEQ_UI_Var8_Inc(&seq_midi_in_ext_ctrl_asg[selected_ext_ctrl], 0, 128, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } } return 0; // no change case ITEM_BLM_SCALAR_PORT: { u8 port_ix = SEQ_MIDI_PORT_InIxGet(seq_blm_port); if( SEQ_UI_Var8_Inc(&port_ix, 0, SEQ_MIDI_PORT_InNumGet()-1, incrementer) >= 0 ) { seq_blm_port = SEQ_MIDI_PORT_InPortGet(port_ix); MUTEX_MIDIOUT_TAKE; blm_timeout_ctr = 0; // fake timeout (so that "BLM not found" message will be displayed) SEQ_BLM_SYSEX_SendRequest(0x00); // request layout from BLM_SCALAR MUTEX_MIDIOUT_GIVE; store_file_required = 1; return 1; // value changed } return 0; // no change } break; } return -1; // invalid or unsupported encoder }
///////////////////////////////////////////////////////////////////////////// // fetches the pos entries of a song // returns -1 if recursion counter reached max position ///////////////////////////////////////////////////////////////////////////// s32 SEQ_SONG_FetchPos(u8 force_immediate_change, u8 dont_dump_mixer_map) { int recursion_ctr = 0; u8 again; do { again = 0; // stop song once recursion counter reached 64 loops if( ++recursion_ctr >= 64 ) { SEQ_BPM_Stop(); return -1; // recursion detected } // reset song position if we reached the end (loop over 128 steps) if( song_pos >= SEQ_SONG_NUM_STEPS ) song_pos = 0; // get step entry seq_song_step_t *s = (seq_song_step_t *)&seq_song_steps[song_pos]; // branch depending on action switch( s->action ) { case SEQ_SONG_ACTION_End: #if 0 if( song_active ) // not in phrase mode SEQ_BPM_Stop(); #else song_finished = 1; // deactivate song incrementer #endif break; case SEQ_SONG_ACTION_JmpPos: song_pos = s->action_value % SEQ_SONG_NUM_STEPS; again = 1; break; case SEQ_SONG_ACTION_JmpSong: { if( song_active ) { // not in phrase mode u32 new_song_num = s->action_value % SEQ_SONG_NUM; SEQ_SONG_Save(song_num); SEQ_SONG_Load(new_song_num); song_pos = 0; again = 1; } } break; case SEQ_SONG_ACTION_SelMixerMap: SEQ_MIXER_Load(s->action_value); SEQ_MIDI_IN_ExtCtrlSend(SEQ_MIDI_IN_EXT_CTRL_MIXER_MAP, s->action_value, 0); if( !dont_dump_mixer_map ) SEQ_MIXER_SendAll(); ++song_pos; again = 1; break; case SEQ_SONG_ACTION_Tempo: { float bpm = (float)s->action_value; if( bpm < 25.0 ) bpm = 25.0; float ramp = (float)s->pattern_g1; SEQ_CORE_BPM_Update(bpm, ramp); ++song_pos; again = 1; } break; case SEQ_SONG_ACTION_Mutes: { // access to seq_core_trk[] must be atomic! portENTER_CRITICAL(); seq_core_trk_muted = ((s->pattern_g1 & 0x0f) << 0) | ((s->pattern_g2 & 0x0f) << 4) | ((s->pattern_g3 & 0x0f) << 8) | ((s->pattern_g4 & 0x0f) << 12); portEXIT_CRITICAL(); ++song_pos; again = 1; } break; case SEQ_SONG_ACTION_GuideTrack: { if( s->action_value <= 16 ) seq_song_guide_track = s->action_value; ++song_pos; again = 1; } break; default: if( s->action >= SEQ_SONG_ACTION_Loop1 && s->action <= SEQ_SONG_ACTION_Loop16 ) { song_loop_ctr = 0; song_loop_ctr_max = s->action - SEQ_SONG_ACTION_Loop1; // TODO: implement prefetching until end of step! SEQ_SONG_FetchHlp_PatternChange(0, s->pattern_g1, s->bank_g1, force_immediate_change); SEQ_SONG_FetchHlp_PatternChange(1, s->pattern_g2, s->bank_g2, force_immediate_change); SEQ_SONG_FetchHlp_PatternChange(2, s->pattern_g3, s->bank_g3, force_immediate_change); SEQ_SONG_FetchHlp_PatternChange(3, s->pattern_g4, s->bank_g4, force_immediate_change); } } } while( again ); return 0; // no error }