def OnShortPressDrumPad(event): global _pad_recording_task note = event.data1 velocity = event.data2 if _recorder.IsRecording(): log('midi', 'Stop Recording. short press detected for %s' % str(note)) _recorder.StopRecording() _scheduler.CancelTask(_pad_recording_task) _pad_recording_task = None elif event.status == 153: global _sustain_enabled log( 'midi', 'Play. short press detected for %s. Sustain=%s' % (str(note), _sustain_enabled)) if not _recorder.Play(note, loop=_sustain_enabled): if config.ENABLE_MPC_STYLE_PADS: index = note - 0x24 if index < channels.channelCount(): # 0x3C corresponds to middle C channels.midiNoteOn(index, 0x3C, velocity) else: channels.midiNoteOn(channels.selectedChannel(), note, _fallback_pad_values[note]) elif event.status == 137: if not _recorder.HasRecording(note): if config.ENABLE_MPC_STYLE_PADS: index = note - 0x24 if index < channels.channelCount(): # 0x3C corresponds to middle C channels.midiNoteOn(index, 0x3C, 0) else: channels.midiNoteOn(channels.selectedChannel(), note, 0)
def OnUpdateColorBlue(self, delta): r, g, b = utils.ColorToRGB( channels.getChannelColor(channels.selectedChannel())) b = self.clip(0, 255, b + delta) channels.setChannelColor(channels.selectedChannel(), utils.RGBToColor(r, g, b)) self._controller.encoders().Refresh()
def OnUpdateVolume(self, delta): channel = channels.selectedChannel() volume = self.clip( 0., 1., channels.getChannelVolume(channels.selectedChannel()) + (delta / 100.0)) channels.setChannelVolume(channel, volume)
def process(command): # Process master fader changing selected channel volume. if command.id == eventconsts.BASIC_FADER_9: current_channel = channels.selectedChannel() volume = processorhelpers.snap(processorhelpers.toFloat(command.value), internal.consts.CHANNEL_VOLUME_SNAP_TO) channels.setChannelVolume(current_channel, volume) action = "Set " + channels.getChannelName( current_channel) + " volume to " + str(round(volume * 100)) + "%" if processorhelpers.didSnap(processorhelpers.toFloat(command.value), internal.consts.CHANNEL_VOLUME_SNAP_TO): action += " [Snapped]" command.handle(action) # Process master fader button to mute/unmute. if command.id == eventconsts.BASIC_FADER_BUTTON_9: global mute_toggle_channel, previous_channel_volume if command.is_lift: if type(mute_toggle_channel) is int and type( previous_channel_volume) is float: if 0 == channels.getChannelVolume(mute_toggle_channel): channels.setChannelVolume(mute_toggle_channel, previous_channel_volume) command.handle( "Unmuted " + channels.getChannelName(mute_toggle_channel)) mute_toggle_channel = None previous_channel_volume = None else: mute_toggle_channel = channels.selectedChannel() previous_channel_volume = channels.getChannelVolume( mute_toggle_channel) channels.setChannelVolume(mute_toggle_channel, 0) command.handle("Muted " + channels.getChannelName(mute_toggle_channel)) for x in imports: object_to_call = getattr(pluginprocessors, x) if canHandle(object_to_call): object_to_call.process(command) if command.ignored: return # Only process mod-wheel and pitch-bend if they weren't already handled by plugin processors # Mod-wheel if command.id == eventconsts.MOD_WHEEL: pluginswrapper.setCCParam(command.note, command.value) command.handle("Mod-wheel", 1) # Pitch-bend wheel if command.id == eventconsts.PITCH_BEND: #pluginswrapper.setCCParam(command.note, command.value) current_channel = channels.selectedChannel() channels.setChannelPitch( current_channel, processorhelpers.snap( processorhelpers.toFloat(command.value, -1, 1), 0.0)) command.handle("Pitch Bend", 1)
def Sync(self, flags): """ Syncs up all visual indicators on keyboard with changes from FL Studio. """ # Update buttons if flags & midi.HW_Dirty_LEDs: led_map = { ArturiaLights.ID_TRANSPORTS_RECORD: ArturiaLights.AsOnOffByte(transport.isRecording()), ArturiaLights.ID_TRANSPORTS_LOOP: ArturiaLights.AsOnOffByte(ui.isLoopRecEnabled()), ArturiaLights.ID_GLOBAL_METRO: ArturiaLights.AsOnOffByte(ui.isMetronomeEnabled()), ArturiaLights.ID_GLOBAL_SAVE: ArturiaLights.AsOnOffByte(transport.getLoopMode() == 1), ArturiaLights.ID_GLOBAL_UNDO: ArturiaLights.AsOnOffByte(general.getUndoHistoryLast() == 0), ArturiaLights.ID_TRACK_SOLO: ArturiaLights.AsOnOffByte( channels.isChannelSolo(channels.selectedChannel())), ArturiaLights.ID_TRACK_MUTE: ArturiaLights.AsOnOffByte( channels.isChannelMuted(channels.selectedChannel())), ArturiaLights.ID_TRANSPORTS_STOP: ArturiaLights.AsOnOffByte(not transport.isPlaying()), ArturiaLights.ID_TRANSPORTS_PLAY: ArturiaLights.AsOnOffByte(transport.getSongPos() > 0), ArturiaLights.ID_GLOBAL_OUT: ArturiaLights.AsOnOffByte( arrangement.selectionEnd() > arrangement.selectionStart()), ArturiaLights.ID_NAVIGATION_LEFT: ArturiaLights.AsOnOffByte(ui.getVisible(midi.widChannelRack)), ArturiaLights.ID_NAVIGATION_RIGHT: ArturiaLights.AsOnOffByte(ui.getVisible(midi.widMixer)), ArturiaLights.ID_OCTAVE_PLUS: ArturiaLights.LED_OFF, ArturiaLights.ID_OCTAVE_MINUS: ArturiaLights.LED_OFF, } self._lights.SetLights(led_map) self._encoders.Refresh() # Update display channel_name = channels.getChannelName(channels.selectedChannel()) pattern_number = patterns.patternNumber() pattern_name = patterns.getPatternName(pattern_number) update = ( flags & ( 1024 # HW_Dirty_Patterns | 2048 # HW_Dirty_Tracks | 16384 # HW_Dirty_Names | 32 # HW_Dirty_FocusedWindow (channel selection) )) > 0 self._paged_display.SetPageLines( 'main', line1='[%d:%d] %s' % (channels.selectedChannel() + 1, pattern_number, channel_name), line2='%s' % pattern_name, update=update)
def _select_one_channel(self, index): if SCRIPT_VERSION >= 8: channels.selectOneChannel(index) else: channels.deselectAll() channels.selectChannel(index, 1) if config.ENABLE_CONTROLS_FL_HINTS: ui.setHintMsg( '[%d:%d] %s' % (channels.selectedChannel() + 1, patterns.patternNumber(), channels.getChannelName(channels.selectedChannel())))
def process(command): # REQUIRES SCRIPTING VERSION 8 #if general.getVersion() >= 8: # Process pitch bend wheel if command.id == eventconsts.PITCH_BEND: current_channel = channels.selectedChannel() channels.setChannelPitch( current_channel, processorhelpers.toFloat(command.value, -1, 1)) # Process master fader changing selected channel volume. if command.id == eventconsts.BASIC_FADER_9: current_channel = channels.selectedChannel() volume = processorhelpers.snap(processorhelpers.toFloat(command.value), internal.consts.CHANNEL_VOLUME_SNAP_TO) channels.setChannelVolume(current_channel, volume) action = "Set " + channels.getChannelName( current_channel) + " volume to " + str(round(volume * 100)) + "%" if processorhelpers.didSnap(processorhelpers.toFloat(command.value), internal.consts.CHANNEL_VOLUME_SNAP_TO): action += " [Snapped]" command.handle(action) # Process master fader button to mute/unmute. if command.id == eventconsts.BASIC_FADER_BUTTON_9: global mute_toggle_channel, previous_channel_volume if command.is_lift: if type(mute_toggle_channel) is int and type( previous_channel_volume) is float: if 0 == channels.getChannelVolume(mute_toggle_channel): channels.setChannelVolume(mute_toggle_channel, previous_channel_volume) command.handle( "Unmuted " + channels.getChannelName(mute_toggle_channel)) mute_toggle_channel = None previous_channel_volume = None else: mute_toggle_channel = channels.selectedChannel() previous_channel_volume = channels.getChannelVolume( mute_toggle_channel) channels.setChannelVolume(mute_toggle_channel, 0) command.handle("Muted " + channels.getChannelName(mute_toggle_channel)) for x in imports: object_to_call = getattr(pluginprocessors, x) if canHandle(object_to_call): object_to_call.process(command) if command.ignored: return
def random_color(unused_param_value): """Random color""" selected = channels.selectedChannel() if selected < 0: return rgb = int(Actions.RANDOM_GENERATOR.random() * 16777215.0) channels.setChannelColor(selected, rgb)
def handle_knob_change(self, event, knob, value): """ Put knob change code here. """ self.selected_channel = channels.selectedChannel() # Mixer Focused if (ui.getFocused(midi.widMixer) == 1): if knob.number != 1: offset = knob.number - 2 trackNum = helpers.getMixerTrackNum() helpers.mixerAdjustPan(trackNum + offset, event.data2) else: helpers.mixerAdjustPan(0, event.data2) event.handled = True # Everything else else: if knob.number == 1: ui.showWindow(midi.widChannelRack) ui.setFocused(midi.widChannelRack) helpers.channelAdjustPan(self.selected_channel, event.data2) elif knob.number == 2: ui.showWindow(midi.widChannelRack) ui.setFocused(midi.widChannelRack) helpers.channelAdjustVolume(self.selected_channel, event.data2) print("Changed knob " + str(knob.number) + " to " + str(value) + ".")
def _request_plugin_window_focus(self): current_time_ms = ArturiaDisplay.time_ms() # Require explicit window focus if last request to focus was more than a second ago. if current_time_ms > self._update_focus_time_ms + 1000: # This call is expensive so try to use sparingly. channels.focusEditor(channels.selectedChannel()) self._update_focus_time_ms = current_time_ms
def OnColorKnobPress(self): selected = channels.selectedChannel() if selected < 0: return rgb = int(self._random.random() * 16777215.0) channels.setChannelColor(selected, rgb) self._controller.encoders().Refresh()
def _next_free_mixer_track(self): last_track = 0 for i in range(channels.channelCount()): if i == channels.selectedChannel(): # Skip the assignment for the channel we are assigning. continue last_track = max(last_track, channels.getTargetFxTrack(i)) return last_track + 1
def _update_knob_value(self, status, control_num, delta): value = 64 key = (channels.selectedChannel(), status, control_num) if key in self._plugin_knob_map: value = self._plugin_knob_map[key] value = min(127, max(0, value + delta)) self._plugin_knob_map[key] = value return value
def OnUpdatePitch(self, delta): if SCRIPT_VERSION < 8: # This isn't supported in older versions return channel = channels.selectedChannel() pan = self.clip(-1., 1., channels.getChannelPitch(channel) + (delta / 100.0)) channels.setChannelPitch(channel, pan)
def _clone_active_pattern(self): active_channel = channels.selectedChannel() self._show_and_focus(midi.widChannelRack) channels.selectAll() ui.copy() self._new_empty_pattern() ui.paste() self._select_one_channel(active_channel)
def _update_toggle_value(self, plugin_index, button_index): bank_values = [False] * 9 key = (channels.selectedChannel(), plugin_index) if key in self._plugin_toggle_map: bank_values = self._plugin_toggle_map[key] bank_values[button_index] = not bank_values[button_index] self._plugin_toggle_map[key] = bank_values return 127 if bank_values[button_index] else 0
def process(command): command.actions.addProcessor("Channel rack Processor") current_channel = channels.selectedChannel() #--------------------------------- # Pads #--------------------------------- if command.type == eventconsts.TYPE_PAD: # UI Mode ui_mode.process(command) if not command.handled: command.handle("Drum pads catch-all", True) #--------------------------------- # Faders #--------------------------------- if command.type == eventconsts.TYPE_FADER: fader_num = command.coord_X if fader_num == 8 and not internal.shifts["MAIN"].use(): channel_num = current_channel else: channel_num = fader_num setVolume(command, channel_num, command.value) #--------------------------------- # Knobs #--------------------------------- if command.type == eventconsts.TYPE_KNOB: knob_num = command.coord_X if knob_num == 7 and not internal.shifts["MAIN"].use(): channel_num = current_channel else: channel_num = knob_num setPan(command, channel_num, command.value) #--------------------------------- # Mixer Buttons - mute/solo tracks #--------------------------------- if command.type == eventconsts.TYPE_FADER_BUTTON: fader_num = command.coord_X print(fader_num) if fader_num == 8 and not internal.shifts["MAIN"].use(): channel_num = current_channel else: channel_num = fader_num processMuteSolo(channel_num, command) return
def OnTrackPlaylistKnobPress(self): track_name = playlist.getTrackName( arturia_playlist.current_playlist_track()) channel_name = channels.getChannelName(channels.selectedChannel()) track_mode = track_name == channel_name and track_name.startswith('* ') if track_mode: self.OnChannelKnobPress() else: self._toggle_window_visibility(midi.widPlaylist)
def sync_current_color(unused_param_value): """Sync channel color""" selected = channels.selectedChannel() if selected < 0: return mixer_index = channels.getTargetFxTrack(selected) if mixer_index <= 0: return color = channels.getChannelColor(selected) mixer.setTrackColor(mixer_index, color)
def _new_empty_pattern(self, linked=True): pattern_id = patterns.patternCount() + 1 if linked: pattern_name = arturia_playlist.next_pattern_name() color = channels.getChannelColor(channels.selectedChannel()) patterns.setPatternName(pattern_id, pattern_name) patterns.setPatternColor(pattern_id, color) patterns.jumpToPattern(pattern_id) patterns.selectPattern(pattern_id, 1) return pattern_id
def _set_plugin_param(param_id, value, incremental=False): event_id = channels.getRecEventId( channels.selectedChannel()) + midi.REC_Chan_Plugin_First + param_id if incremental: value = channels.incEventValue(event_id, value, 0.01) else: value = ArturiaInputControls._to_rec_value(value, limit=65536) general.processRECEvent( event_id, value, midi.REC_UpdateValue | midi.REC_UpdatePlugLabel | midi.REC_ShowHint | midi.REC_UpdateControl | midi.REC_SetChanged)
def OnMidiNote(self, event): recording_key = self._recording if recording_key is None: # Don't process any notes if we are not recording return timestamp = int(round(time.time() * 1000)) channel = channels.selectedChannel() velocity = event.velocity if event.status == 0x80: velocity = 0 self._savedata.Get(recording_key).extend([timestamp, channel, event.note, velocity])
def OnTrackMute(self, event): debug.log('OnTrackMute', 'Dispatched', event=event) playlist_mode = self._navigation.GetMode() == 'Playlist Track' if self._button_mode == arturia_macros.SAVE_BUTTON or playlist_mode: current_track = arturia_playlist.current_playlist_track() playlist.muteTrack(current_track) status = playlist.isTrackMuted(current_track) self._display_playlist_track_op_hint("Mute Playlist: %d" % status) self._button_hold_action_committed = True else: channels.muteChannel(channels.selectedChannel())
def pad_hit(event): if event.midiId == 144: temp_step.clear() temp_step.append(event.data1 + offset[Switch.offset_iter]) if ui.getFocused(5) and plugins.isValid(channels.selectedChannel()): if event.midiId == 128 and event.data2 != 0: print('skip') elif plugins.getPluginName(channels.selectedChannel()) == 'FPC' and event.data1 in alesis_pads: print('FPC') channels.midiNoteOn(channels.selectedChannel(), FPC_pads[alesis_pads.index(event.data1 + offset[Switch.offset_iter])], event.data2) event.handled = True elif Switch.mode_toggle == 1 and event.midiId == 144: if channels.getGridBit(channels.selectedChannel(), event.data1 - 60 + offset[Switch.offset_iter]) == 0: channels.setGridBit(channels.selectedChannel(), event.data1 - 60 + offset[Switch.offset_iter], 1) event.handled = True else: channels.setGridBit(channels.selectedChannel(), event.data1 - 60 + offset[Switch.offset_iter], 0) event.handled = True elif Switch.mode_toggle == 2 and 60 <= event.data1 < (channels.channelCount() + 60): channels.setChannelPitch(event.data1-60, mapvalues(Switch.pitch_num, -1, 1, 0, 127)) channels.selectOneChannel(event.data1-60) channels.midiNoteOn(event.data1-60, 60, event.data2, Switch.pitch_num) print('a pad has been hit') event.handled = True
def ProcessBeat(self, value): """ Notify the metronome that a beat occured (e.g. OnUpdateBeatIndicator). """ if config.METRONOME_LIGHTS_ONLY_WHEN_METRONOME_ENABLED and not ui.isMetronomeEnabled(): # Disable metronome if configured to correlate to metronome toggle and is disabled. return should_color_pads = ((not arturia_leds.ESSENTIAL_KEYBOARD and config.ENABLE_MK2_COLORIZE_PAD_LIGHTS) or (arturia_leds.ESSENTIAL_KEYBOARD and config.ENABLE_COLORIZE_BANK_LIGHTS)) zero_val = 0 on_val = ArturiaLights.LED_ON if should_color_pads: channel_idx = channels.selectedChannel() color_val = channels.getChannelColor(channel_idx) zero_val = ArturiaLights.fadedColor(color_val) on_val = ArturiaLights.fullColor(color_val) lights = ArturiaLights.ZeroMatrix(zero=zero_val) current_bst_position = (playlist.getVisTimeBar(), playlist.getVisTimeStep(), playlist.getVisTimeTick()) if current_bst_position < self._last_bst_position: self.Reset() self._last_bst_position = current_bst_position if value == 2: # Indicates regular beat self._beat_count += 1 if value == 1: # Indicates beat at a bar self._beat_count = 0 self._bar_count += 1 num_rows = len(lights) num_cols = len(lights[0]) if value != 0: row = self._bar_count % num_rows col = self._beat_count % num_cols lights[row][col] = on_val two_step = self._beat_count % 2 == 0 if config.ENABLE_PAD_METRONOME_LIGHTS: self._lights.SetPadLights(lights, rgb=should_color_pads) if config.ENABLE_TRANSPORTS_METRONOME_LIGHTS: self._lights.SetLights({ ArturiaLights.ID_TRANSPORTS_REWIND: ArturiaLights.AsOnOffByte(two_step), ArturiaLights.ID_TRANSPORTS_FORWARD: ArturiaLights.AsOnOffByte(not two_step), })
def next_pattern_name(): """Returns the next suggested pattern name.""" pattern_names = _all_pattern_names() # If there are N patterns, then at most, N+1 instruments selected = channels.selectedChannel() name = strip_pattern_name(channels.getChannelName(selected)) if name not in pattern_names: return name for i in range(1, patterns.patternCount() + 1): suggested = '%s [%d]' % (name, i) if suggested not in pattern_names: return suggested return '%s [%d]' % (name, patterns.patternCount() + 1)
def OnUpdateTargetMixerTrack(self, delta): max_track_idx = mixer.trackCount() - 2 # One of the track is a control track prev_track = channels.getTargetFxTrack(channels.selectedChannel()) target_track = self.circular(0, max_track_idx, prev_track + delta) # Remember to unset the name of the previous pointed to track. mixer.setTrackNumber(target_track, midi.curfxMinimalLatencyUpdate) mixer.linkTrackToChannel(midi.ROUTE_ToThis) channel_idx = self._channel_with_route_to_mixer_track(prev_track) if channel_idx < 0: mixer.setTrackName(prev_track, '') elif mixer.getTrackName(prev_track) == mixer.getTrackName(target_track): mixer.setTrackName(prev_track, channels.getChannelName(channel_idx)) if target_track == 0: mixer.setTrackName(target_track, '')
def OnUpdatePlugin(self, delta): # Indicator to notify user that preset is in process of being set. self._request_plugin_window_focus() if SCRIPT_VERSION >= 10: idx = channels.selectedChannel() if delta > 0: plugins.nextPreset(idx) elif delta < 0: plugins.prevPreset(idx) else: if delta > 0: ui.next() elif delta < 0: ui.previous()
def setGridBits(lights): current_track = channels.selectedChannel() if channels.channelCount() <= current_track: return # Set scroll indicator light_num_scroll = gridBits.scroll if light_num_scroll < 8: if not gridBits.getBit(current_track, light_num_scroll): lights.setPadColour(light_num_scroll, 0, lightingconsts.colours["LIGHT LILAC"]) else: lights.setPadColour(light_num_scroll, 0, lightingconsts.colours["PINK"], lightingconsts.MODE_PULSE) # Set zoom indicator light_num_zoom = 7 - int(math.log(gridBits.zoom, 2)) if light_num_zoom >= 0 and internal.window.getAnimationTick() > 7: if not gridBits.getBit(current_track, light_num_zoom): lights.setPadColour(light_num_zoom, 0, lightingconsts.colours["LIGHT LIGHT BLUE"]) else: lights.setPadColour(light_num_zoom, 0, lightingconsts.colours["BLUE"], lightingconsts.MODE_PULSE) # If zoom and scroll lie on same pad if light_num_scroll == light_num_zoom: if not gridBits.getBit(current_track, light_num_zoom): lights.setPadColour(light_num_zoom, 0, lightingconsts.colours["LIGHT YELLOW"]) else: lights.setPadColour(light_num_zoom, 0, lightingconsts.colours["PINK"], lightingconsts.MODE_PULSE) # Set remaining grid bits for i in range(8): if i <= internal.window.getAnimationTick(): if gridBits.getBit(current_track, i): lights.setPadColour(i, 0, lightingconsts.colours["RED"], lightingconsts.MODE_PULSE) else: lights.setPadColour(i, 0, lightingconsts.colours["DARK GREY"]) return
def OnShortPressDrumPad(event): global _pad_recording_task note = event.data1 if _recorder.IsRecording(): log('midi', 'Stop Recording. short press detected for %s' % str(note)) _recorder.StopRecording() _scheduler.CancelTask(_pad_recording_task) _pad_recording_task = None else: global _sustain_enabled log( 'midi', 'Play. short press detected for %s. Sustain=%s' % (str(note), _sustain_enabled)) if not _recorder.Play(note, loop=_sustain_enabled): channels.midiNoteOn(channels.selectedChannel(), note, _fallback_pad_values[note])