def _setup_mixer_control(self): is_momentary = True self._num_tracks = (2) #A mixer is one-dimensional; self._mixer = MixerComponent(2, 0, False, True) self._mixer.name = 'Mixer' self._mixer.tracks_to_use = self._mixer_tracks_to_use(self._mixer) self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left)
def _setup_mixer_control(self): is_momentary = True self._num_tracks = (1) #A mixer is one-dimensional; self._mixer = MixerComponent(1, 0, False, False) self._mixer.name = 'Mixer' self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) for index in range(1): self._mixer.channel_strip(index)._invert_mute_feedback = True self._mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) #for index in range(4): # self._mixer.return_strip(index).name = 'Mixer_ReturnStrip_' + str(index) self._mixer.selected_strip().name = 'Mixer_SelectedStrip' self.song().view.selected_track = self._mixer.channel_strip(0)._track
def _setup_alt_mixer(self): is_momentary = True self._num_tracks = (8) #A mixer is one-dimensional self._mixer2 = MixerComponent(8, 0, False, False) self._mixer2.name = 'Mixer_2' self._mixer2.set_track_offset(4) #Sets start point for mixer strip (offset from left) for index in range(8): self._mixer2.channel_strip(index).name = 'Mixer_2_ChannelStrip_' + str(index) self._mixer2.channel_strip(index)._invert_mute_feedback = True self._mixer3 = MixerComponent(4, 4, False, False) self._mixer3.name = 'Mixer_3' self._mixer3.set_track_offset(8) #Sets start point for mixer strip (offset from left) for index in range(4): self._mixer3.channel_strip(index).name = 'Mixer_3_ChannelStrip_' + str(index) self._mixer3.channel_strip(index)._invert_mute_feedback = True
def _setup_mixer_control(self): is_momentary = True self._num_tracks = 2 # A mixer is one-dimensional; self._mixer = MixerComponent(2, 0, False, True) self._mixer.name = "Mixer" self._mixer.tracks_to_use = self._mixer_tracks_to_use(self._mixer) self._mixer.set_track_offset(0) # Sets start point for mixer strip (offset from left)
def __init__(self, num_tracks, num_returns, with_EQs, with_FILTERs): self._is_locked = False #added MixerComponent.__init__(self, num_tracks, num_returns, with_EQs, with_FILTERs)
def _setup_mixer_control(self): is_momentary = True # We use non-latching buttons (keys) throughout, so we'll set this as a constant num_tracks = 4 # Here we define the mixer width in tracks (a mixer has only one dimension) global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...) mixer = MixerComponent(num_tracks, 2, with_eqs=True, with_filters=False) #(num_tracks, num_returns, with_eqs, with_filters) mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) """set up the mixer buttons""" self.song().view.selected_track = mixer.channel_strip(0)._track #mute_notes = [1,5,9,13] #solo_notes = [2,6,10,14] #arm_notes = [3,7,11,15] track_select_notes = [38,39,40,41]#more note numbers need to be added if num_scenes is increased send_ccs = [2,6,10,14,1,5,9,13] pan_ccs = [3,7,11,15] slider_ccs = [4,8,12,16] for index in range(num_tracks): mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, track_select_notes[index])) mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, CHAN, slider_ccs[index])) mixer.channel_strip(index).set_pan_control(EncoderElement(MIDI_CC_TYPE, CHAN, pan_ccs[index], Live.MidiMap.MapMode.absolute)) #put send A and send B controllers into an array, which is then "tupled" for set_send_controls: send_controlers = [EncoderElement(MIDI_CC_TYPE, CHAN, send_ccs[index], Live.MidiMap.MapMode.absolute), EncoderElement(MIDI_CC_TYPE, CHAN, send_ccs[index+num_tracks], Live.MidiMap.MapMode.absolute)] mixer.channel_strip(index).set_send_controls(tuple(send_controlers)) crossfader = SliderElement(MIDI_CC_TYPE, CHAN, 28) master_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 32) returna_pan_control = SliderElement(MIDI_CC_TYPE, CHAN, 19) returna_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 20) returnb_pan_control = SliderElement(MIDI_CC_TYPE, CHAN, 23) returnb_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 24) master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 31) prehear_control = EncoderElement(MIDI_CC_TYPE, CHAN, 30, Live.MidiMap.MapMode.absolute) crossfader.name = 'Crossfader' master_volume_control.name = 'Master_Volume_Control' returna_pan_control.name = 'ReturnA_Pan_Control' returna_volume_control.name = 'ReturnA_Volume_Control' returnb_pan_control.name = 'ReturnB_Pan_Control' returnb_volume_control.name = 'ReturnB_Volume_Control' master_select_button.name = 'Master_Select_Button' prehear_control.name = 'Prehear_Volume_Control' mixer.set_crossfader_control(crossfader) mixer.master_strip().set_volume_control(master_volume_control) mixer.master_strip().set_select_button(master_select_button) mixer.set_prehear_volume_control(prehear_control) mixer.return_strip(0).set_pan_control(returna_pan_control) mixer.return_strip(0).set_volume_control(returna_volume_control) mixer.return_strip(1).set_pan_control(returnb_pan_control) mixer.return_strip(1).set_volume_control(returnb_volume_control)
class Tweaker(ControlSurface): __module__ = __name__ __doc__ = " MonOhmod companion controller script " def __init__(self, c_instance): """everything except the '_on_selected_track_changed' override and 'disconnect' runs from here""" ControlSurface.__init__(self, c_instance) with self.component_guard(): self._update_linked_device_selection = None self._tweaker_version = '0.4' self.log_message("--------------= Tweaker Mixer " + str(self._tweaker_version) + " log opened =--------------") self._update_linked_device_selection = None self._setup_mixer_control() self._setup_session_control() """script initialization methods""" def _setup_controls(self): is_momentary = True self._grid = [None for index in range(8)] for column in range(8): self._grid[column] = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, column + (row * 8), 'Grid_' + str(column) + '_' + str(row), self) for row in range(4)] self._button = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_BUTTONS[index], 'Button_' + str(index), self) for index in range(len(TWEAKER_BUTTONS))] self._nav = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_NAVS[index], 'Nav_' + str(index), self) for index in range(len(TWEAKER_NAVS))] self._encoder_buttons = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_ENCODER_BUTTONS[index], 'Encoder_Button_' + str(index), self) for index in range(len(TWEAKER_ENCODER_BUTTONS))] self._dial = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_DIALS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_DIALS))] self._fader = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_FADERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_FADERS))] self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute) self._encoder = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_ENCODERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_ENCODERS))] self._pad = [FlashingButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, TWEAKER_PADS[index], 'Pad_' + str(index), self) for index in range(len(TWEAKER_PADS))] self._matrix = ButtonMatrixElement() self._matrix.name = 'Matrix' for row in range(4): button_row = [] for column in range(7): button_row.append(self._grid[column][row]) self._matrix.add_row(tuple(button_row)) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_mixer_control(self): is_momentary = True self._num_tracks = (2) #A mixer is one-dimensional; self._mixer = MixerComponent(2, 0, False, True) self._mixer.name = 'Mixer' self._mixer.tracks_to_use = self._mixer_tracks_to_use(self._mixer) self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) def _setup_session_control(self): is_momentary = True num_tracks = 2 num_scenes = 3 self._session = SessionComponent(num_tracks, num_scenes) self._session.name = "Session" self._session.set_offsets(0, 0) self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) """general functionality""" def allow_updates(self, allow_updates): for component in self.components: component.set_allow_update(int(allow_updates!=0)) def disconnect(self): """clean things up on disconnect""" if self._session._is_linked(): self._session._unlink() self.log_message("--------------= Tweaker Mixer " + str(self._tweaker_version) + " log closed =--------------") #Create entry in log file ControlSurface.disconnect(self) return None def connect_script_instances(self, instanciated_scripts): link = False for s in instanciated_scripts: if '_tweaker_version' in dir(s): if s._tweaker_version == self._tweaker_version: link = True if not s is self: s._linked_session = self._session #break if link is True: if not self._session._is_linked(): #self._session.set_offsets(0, 0) self._session._link() def _mixer_tracks_to_use(self, mixer): def tracks_to_use(): return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) return tracks_to_use # a
def _setup_mixer_control(self): is_momentary = True self._num_tracks = (COLS) global mixer mixer = MixerComponent(COLS, 0, True, True) mixer.name = 'Mixer' self._mixer = mixer mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) for index in range(COLS): #use the bottom row of encoders for volume, so add 24 to offset the index mixer.channel_strip(index).set_volume_control(self._dial[index+24]) for index in range(COLS): mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) mixer.track_eq(index).name = 'Mixer_EQ_' + str(index) mixer.track_filter(index).name = 'Mixer_Filter_' + str(index) #added by a mixer.channel_strip(index)._invert_mute_feedback = True #mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index])) self.song().view.selected_track = mixer.channel_strip(0)._track #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error
def _setup_mixer_control(self): is_momentary = True # We use non-latching buttons (keys) throughout, so we'll set this as a constant num_tracks = 4 # Here we define the mixer width in tracks (a mixer has only one dimension) global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...) mixer = MixerComponent( num_tracks, 2, with_eqs=True, with_filters=False ) #(num_tracks, num_returns, with_eqs, with_filters) mixer.set_track_offset( 0) #Sets start point for mixer strip (offset from left) """set up the mixer buttons""" self.song().view.selected_track = mixer.channel_strip(0)._track #mute_notes = [1,5,9,13] #solo_notes = [2,6,10,14] #arm_notes = [3,7,11,15] track_select_notes = [ 38, 39, 40, 41 ] #more note numbers need to be added if num_scenes is increased send_ccs = [2, 6, 10, 14, 1, 5, 9, 13] pan_ccs = [3, 7, 11, 15] slider_ccs = [4, 8, 12, 16] for index in range(num_tracks): mixer.channel_strip(index).set_select_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, track_select_notes[index])) mixer.channel_strip(index).set_volume_control( SliderElement(MIDI_CC_TYPE, CHAN, slider_ccs[index])) mixer.channel_strip(index).set_pan_control( EncoderElement(MIDI_CC_TYPE, CHAN, pan_ccs[index], Live.MidiMap.MapMode.absolute)) #put send A and send B controllers into an array, which is then "tupled" for set_send_controls: send_controlers = [ EncoderElement(MIDI_CC_TYPE, CHAN, send_ccs[index], Live.MidiMap.MapMode.absolute), EncoderElement(MIDI_CC_TYPE, CHAN, send_ccs[index + num_tracks], Live.MidiMap.MapMode.absolute) ] mixer.channel_strip(index).set_send_controls( tuple(send_controlers)) crossfader = SliderElement(MIDI_CC_TYPE, CHAN, 28) master_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 32) returna_pan_control = SliderElement(MIDI_CC_TYPE, CHAN, 19) returna_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 20) returnb_pan_control = SliderElement(MIDI_CC_TYPE, CHAN, 23) returnb_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 24) master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 31) prehear_control = EncoderElement(MIDI_CC_TYPE, CHAN, 30, Live.MidiMap.MapMode.absolute) crossfader.name = 'Crossfader' master_volume_control.name = 'Master_Volume_Control' returna_pan_control.name = 'ReturnA_Pan_Control' returna_volume_control.name = 'ReturnA_Volume_Control' returnb_pan_control.name = 'ReturnB_Pan_Control' returnb_volume_control.name = 'ReturnB_Volume_Control' master_select_button.name = 'Master_Select_Button' prehear_control.name = 'Prehear_Volume_Control' mixer.set_crossfader_control(crossfader) mixer.master_strip().set_volume_control(master_volume_control) mixer.master_strip().set_select_button(master_select_button) mixer.set_prehear_volume_control(prehear_control) mixer.return_strip(0).set_pan_control(returna_pan_control) mixer.return_strip(0).set_volume_control(returna_volume_control) mixer.return_strip(1).set_pan_control(returnb_pan_control) mixer.return_strip(1).set_volume_control(returnb_volume_control)
class AumTroll(Cntrlr): __module__ = __name__ __doc__ = " MonOhmod companion controller script " def __init__(self, *a, **k): self._monohm = None self._aumpush = None self._shifted = False self._use_pedal = True self._suppress_next_mod_display = False self._monomod_version = 'b996' self._codec_version = 'b996' super(AumTroll, self).__init__(*a, **k) self._host_name = "AumTroll" with self.component_guard(): self._setup_alt_device_control() self._setup_alt_mixer() #self._setup_device_selector() # Not sure why this was HERE, but removed 051314 because it was overriding mod grid updates #self._setup_alt_device_control() #self.schedule_message(3, self._session._do_show_highlight) self._send_midi(tuple(request_snapshot)) """script initialization methods""" def _open_log(self): self.log_message("<<<<<<<<<<<<<<<<<<<<= " + str(self._host_name) + " " + str(self._monomod_version) + " log opened =>>>>>>>>>>>>>>>>>>>") self.show_message(str(self._host_name) + ' Control Surface Loaded') def _setup_modes(self): super(AumTroll, self)._setup_modes() self._alt_shift_mode = ModesComponent() self._alt_shift_mode.add_mode( 'alt_shift', tuple([self._enable_alt_shift, self._disable_alt_shift]), behaviour=CancellableBehaviourWithRelease()) self._alt_shift_mode.set_mode_button('alt_shift', self._grid[15]) def _enable_alt_shift(self): self._alt_shift_enabled = True self._on_shift_button_value(1) def _disable_alt_shift(self): self._alt_shift_enabled = False self._on_shift_button_value(0) def deassign_live_controls(self): self._leds_last = None self._device_selector.set_enabled(False) self._device._parameter_controls = None self._device1._parameter_controls = None self._device2._parameter_controls = None for index in range(8): self._mixer2.channel_strip(index).set_select_button(None) self._mixer2.channel_strip(index).set_volume_control(None) for index in range(4): self._mixer3.channel_strip(index).set_select_button(None) self._mixer3.channel_strip(index).set_volume_control(None) self._mixer3.return_strip(index).set_volume_control(None) #if self._aumpush: # self._aumpush._host._set_bank_buttons(None) #self._on_shift_button_value.subject = None self._alt_shift_mode.set_mode_button('alt_shift', None) self._mixer.set_crossfader_control(None) """THIS SECTION IS MISSING FROM THE ORIGINAL SCRIPT AND NEEDS TO BE FIXED...THE ASSIGNMENTS WERE MADE AT __init__""" for index in range(4): self._mixer.channel_strip(index).set_volume_control( None ) #Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it for index in range(2): self._mixer.return_strip(index).set_volume_control( None ) #assign the right faders to control the volume of our return strips self._mixer.master_strip().set_volume_control( None ) #assign the far right fader to control our master channel strip self._mixer.set_prehear_volume_control( None ) #assign the remaining fader to control our prehear volume of the the master channel strip for index in range(4): #for the left side of the mixer self._mixer.channel_strip(index).set_solo_button( None) #remove the solo button assignments self._mixer.channel_strip(index).set_arm_button( None) #remove the arm button assignments self._mixer.channel_strip(index).set_mute_button( None) #remove the mute button assignments self._mixer.channel_strip(index).set_select_button( None) #remove the select button assignments for column in range(4): for row in range(4): self._scene[row].clip_slot(column).set_launch_button( None) #remove the clip launch assignments self._send_reset.set_buttons( tuple([None for index in range(4)]) ) #remove the send_reset button assignments - this has to be sent as a tuple self._session.set_stop_track_clip_buttons( None) #remove the clip_stop button assignments self._session.set_track_bank_buttons( None, None ) #set the track bank buttons for the Session navigation controls self._session.set_scene_bank_buttons( None, None ) #set the scnee bank buttons for the Session navigation controls self._transport.set_play_button( None) #remove the play button assignment self._transport.set_record_button( None) #remove the record button assignment self._transport.set_stop_button( None) #remove the stop button assignment for index in range(16): self._grid[index].set_on_off_values( 127, 0) #reset the on/off values of the grid buttons self._grid[index].reset() #turn the buttons LEDs off for index in range(32): self._button[index].set_on_off_values( 127, 0) #reset the on/off values for the key buttons self._button[index].release_parameter( ) #remove the parameter assignment that was assigned to the keys self._button[index].send_value(0, True) #turn the buttons LEDs off #self._device.set_parameter_controls(tuple([self._encoder[index+4] for index in range(8)])) #assign the encoders from the device component controls - we are doing this here b self._device_navigator.set_nav_buttons( None, None) #remove the assignment of the device nav buttons self._device_navigator.set_enabled( False) #turn off the device navigator self._device.set_on_off_button( None ) #remove the assignment of the on/off button from the device component self._device.set_lock_button( None ) #remove the assignment of the lock button from the device component self._device.set_bank_nav_buttons( None, None ) #remove the assignment of the navigation buttons from the device component self._device.set_enabled(False) #turn off the device component self._session.set_enabled(False) #turn off the session component self._session_zoom.set_enabled(False) #turn off the zoom component for index in range(16): self._grid[index].force_next_send( ) #set the last_sent value of the grid to -1, so that the next value it receives will always be transmitted to the CNTRLR for index in range(32): self._button[index].force_next_send( ) #set the last_sent value of the keys to -1, so that the next value it receives will always be transmitted to the CNTRLR for index in range(12): self._device._parameter_controls = None self._encoder[index].release_parameter() self._encoder[index].send_value( 0, True ) #turn off all the encoder rings. We send it the second argument, True, so that it is forced to update regardless of its last_sent property self._encoder[index].force_next_send( ) #set the last_sent value of the encoder rings to -1, so that the next value it receives will always be transmitted to the CNTRLR for index in range(8): self._encoder_button[index + 4].send_value( 0, True ) #turn off all the encoder LEDs. We send it the second argument, True, so that it is forced to update regardless of its last_sent property self._encoder_button[index + 4].force_next_send( ) #set the last_sent value of the encoder LEDs to -1, so that the next value it receives will always be transmitted to the CNTRLR for index in range(8): self._mixer2.channel_strip(index).set_select_button(None) self._mixer2.channel_strip(index).set_mute_button(None) self._mixer2.channel_strip(index).set_select_button(None) self._session_zoom.set_zoom_button( None ) #remove the assignment of the shift button from the ZoomingComponent self.request_rebuild_midi_map( ) #now that we've finished deassigning all of our controls, we tell the main script to rebuild its MIDI map and update the values in Live def assign_live_controls(self): """the following lines update all of the controls' last_sent properties, so that they forward the next value they receive regardless of whether or not it is the same as the last it recieved""" """we also reset the encoder rings and buttons, since the device component will not update them if it is not locked to a device in Live""" for index in range(16): self._grid[index].force_next_send() for index in range(32): self._button[index].force_next_send() for index in range(8): self._encoder_button[index + 4].send_value(0, True) self._encoder_button[index + 4].force_next_send() for index in range(12): self._encoder[index].send_value(0, True) self._encoder[index].force_next_send() """here we assign the left side of our mixer's buttons on the lower 32 keys""" if self._monohm == None and self._aumpush == None: for index in range( 4 ): #we set up a recursive loop to assign all four of our track channel strips' controls self._button[index].set_on_value( SOLO[self._rgb]) #set the solo color from the Map.py self._mixer.channel_strip(index).set_solo_button( self._button[index] ) #assign the solo buttons to our mixer channel strips self._button[index + 4].set_on_value( ARM[self._rgb]) #set the arm color from the Map.py self._mixer.channel_strip(index).set_arm_button( self._button[index + 4] ) #assign the arm buttons to our mixer channel strips self._button[index + 16].set_on_value( MUTE[self._rgb]) #set the mute color from the Map.py self._mixer.channel_strip(index).set_mute_button( self._button[index + 16] ) #assign the mute buttons to our mixer channel strips self._button[index + 20].set_on_value( SELECT[self._rgb]) #set the select color from the Map.py self._mixer.channel_strip(index).set_select_button( self._button[index + 20] ) #assign the select buttons to our mixer channel strips self._send_reset.set_buttons( tuple(self._button[index + 8] for index in range(4)) ) #this is yet another way to quickly assign multiple elements conveniently in-place. We are creating a recursion inside an assignment. The tuple() method creates an immutable array. It can't be modified until it gets where it's going and is unpacked. self._session.set_stop_track_clip_buttons( tuple(self._button[index + 24] for index in range(4)) ) #these last two lines assign the send_reset buttons and the stop_clip buttons for each track for index in range(4): self._button[index + 8].send_value( SEND_RESET[self._rgb], True ) #now we are going to send a message to turn the LEDs on for the send_reset buttons self._button[index + 24].set_on_off_values( STOP_CLIP[self._rgb], STOP_CLIP[self._rgb] ) #this assigns the custom colors defined in the Map.py file to the stop_clip buttons. They have seperate on/off values, but we assign them both the same value so we can always identify them self._button[index + 24].send_value( STOP_CLIP[self._rgb], True ) #finally, we send the on/off colors out to turn the LEDs on for the stop clip buttons self._button[28].set_on_off_values( PLAY_ON[self._rgb], PLAY[self._rgb] ) #assing the on/off colors for play. These are two seperate values, dependant upon whether play is engaged or not self._transport.set_play_button( self._button[28] ) #set the transports play control to the corresponding button on the CNTRLR self._button[30].set_on_off_values( RECORD_ON[self._rgb], RECORD[self._rgb] ) #set the on/off colors for the transport record buttons self._transport.set_record_button( self._button[30] ) #assign the correct button for the transport record control self._button[29].set_on_value( STOP[self._rgb]) #set the on value for the Stop button self._transport.set_stop_button( self._button[29] ) #assign the correct button for the transport stop control self._button[29].send_value( STOP_OFF[self._rgb], True) #turn on the LED for the stop button for index in range( 4 ): #set up a for loop to generate an index for assigning the session nav buttons' colors self._button[index + 12].set_on_off_values( SESSION_NAV[self._rgb], SESSION_NAV_OFF[self._rgb] ) #assign the colors from Map.py to the session nav buttons self._session.set_track_bank_buttons( self._button[15], self._button[14] ) #set the track bank buttons for the Session navigation controls self._session.set_scene_bank_buttons( self._button[13], self._button[12] ) #set the scnee bank buttons for the Session navigation controls """this section assigns the grid to the clip launch functionality of the SessionComponent""" for column in range( 4 ): #we need to set up a double recursion so that we can generate the indexes needed to assign the grid buttons for row in range( 4 ): #the first recursion passes the column index, the second the row index self._scene[row].clip_slot(column).set_launch_button( self._grid[(row * 4) + column] ) #we use the indexes to grab the first the scene and then the clip we assigned above, and then we use them again to define the button held in the grid array that we want to assign to the clip slot from the session component """this section assigns the faders and knobs""" for index in range(2): self._mixer.return_strip(index).set_volume_control( self._fader[index + 4] ) #assign the right faders to control the volume of our return strips self._mixer.master_strip().set_volume_control( self._fader[7] ) #assign the far right fader to control our master channel strip self._mixer.set_prehear_volume_control( self._fader[6] ) #assign the remaining fader to control our prehear volume of the the master channel strip for track in range( 4 ): #we set up a recursive loop to assign all four of our track channel strips' controls channel_strip_send_controls = [ ] #the channelstripcomponent requires that we pass the send controls in an array, so we create a local variable, channel_strip_send_controls, to hold them for control in range( 2 ): #since we are going to assign two controls to the sends, we create a recursion channel_strip_send_controls.append( self._dial_left[track + (control * 4)] ) #then use the append __builtin__ method to add them to the array self._mixer.channel_strip(track).set_volume_control( self._fader[track] ) #Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it self._mixer.channel_strip(track).set_send_controls( tuple(channel_strip_send_controls) ) #now that we have an array containing the send controls, we pass it to the channelstrip component with its set_send_controls() method self._mixer.channel_strip(track).set_pan_control( self._dial_left[ track + 8]) #now we set the pan control to the bottom self._mixer.track_eq(track).set_gain_controls( tuple([ self._dial_right[track + 8], self._dial_right[track + 4], self._dial_right[track] ]) ) #here's another way of doing the same thing, but instead of creating the array before hand, we define it in-place. Its probably bad coding to mix styles like this, but I'll leave it for those of you trying to figure this stuff out self._mixer.track_eq(track).set_enabled( True) #turn the eq component on self._session_zoom.set_zoom_button( self._button[31] ) #assign the lower right key button to the shift function of the Zoom component self._session.update( ) #tell the Session component to update so that the grid will display the currently selected session region self._session.set_enabled(True) #enable the Session Component self._session_zoom.set_enabled(True) #enable the Session Zoom elif not self._aumpush == None: self.assign_aumpush_controls() elif not self._monohm == None: for index in range(8): self._mixer2.channel_strip(index).set_volume_control( self._fader[index]) self._mixer2.set_track_offset(TROLL_OFFSET) self._device_selector.set_buttons(self._grid) self._device_selector.set_enabled(True) if not self._shifted: self._assign_monomodular_controls() else: self._assign_shifted_controls() self._device1.set_parameter_controls( tuple([self._knobs[index] for index in range(8)])) self._device2.set_parameter_controls( tuple([self._knobs[index + 12] for index in range(8)])) self._device1.set_enabled(True) self._device2.set_enabled(True) self._find_devices() self._device1.update() self._device2.update() """this section assigns the encoders and encoder buttons""" if self._aumpush == None: self._device.set_parameter_controls( tuple([self._encoder[index + 4] for index in range(8)]) ) #assign the encoders from the device component controls - we are doing this here b self._encoder_button[7].set_on_value( DEVICE_LOCK[self._rgb] ) #set the on color for the Device lock encoder button self._device.set_lock_button( self._encoder_button[7] ) #assign encoder button 7 to the device lock control self._encoder_button[4].set_on_value( DEVICE_ON[self._rgb] ) #set the on color for the Device on/off encoder button self._device.set_on_off_button( self._encoder_button[4] ) #assing encoder button 4 to the device on/off control for index in range( 2 ): #setup a recursion to generate indexes so that we can reference the correct controls to assing to the device_navigator functions self._encoder_button[index + 8].set_on_value( DEVICE_NAV[self._rgb] ) #assign the on color for the device navigator self._encoder_button[index + 10].set_on_value( DEVICE_BANK[self._rgb] ) #assign the on color for the device bank controls self._device_navigator.set_nav_buttons( self._encoder_button[10], self._encoder_button[11] ) #set the device navigators controls to encoder buttons 10 and 11 self._device.set_bank_nav_buttons( self._encoder_button[8], self._encoder_button[9] ) #set the device components bank nav controls to encoder buttons 8 and 9 """now we turn on and update some of the components we've just made assignments to""" self._device.set_enabled(True) #enable the Device Component self._device_navigator.set_enabled( True) #enable the Device Navigator self._device.update( ) #tell the Device component to update its assingments so that it will detect the currently selected device parameters and display them on the encoder rings """function mode callbacks""" """this method changes modes when we press a modButton. It is also called from Monomod when it needs to update the modDial assignments""" def shift_update(self): super(AumTroll, self).shift_update() if self._shift_mode._mode_index == 0: if self._aumpush == None: for index in range(8): self._mixer2.channel_strip(index).set_volume_control( self._fader[index]) self._mixer2.set_track_offset(TROLL_OFFSET) self._device1.set_parameter_controls( tuple([self._knobs[index] for index in range(8)])) self._device2.set_parameter_controls( tuple([self._knobs[index + 12] for index in range(8)])) self._device1.set_enabled(True) self._device2.set_enabled(True) self._find_devices() self._device1.update() self._device2.update() else: self.assign_aumpush_controls() def find_inputs(self): found_device = None tracks = self.song().tracks for track in tracks: if track.name == 'Inputs': for device in track.devices: if bool(device.can_have_chains ) and device.name == 'Inputs': found_device = device return found_device def find_perc_crossfader(self): found_parameter = None tracks = self.song().tracks for track in tracks: if track.name == 'Perc': for device in track.devices: if bool(device.can_have_chains) and device.name == 'Perc': for parameter in device.parameters: if parameter.name == 'XFade': found_parameter = parameter return found_parameter def assign_aumpush_controls(self): if self._aumpush: inputs = self.find_inputs() if not inputs is None: for index in range(4): self._knobs[index + 8].connect_to(inputs.parameters[index + 1]) #for index in range(3): # self._mixer2.channel_strip(index+4).set_volume_control(self._knobs[index+20]) self._mixer.set_crossfader_control(self._knobs[23]) xfade = self.find_perc_crossfader() if not xfade is None: self._knobs[20].connect_to(xfade) for index in range(4): self._mixer3.return_strip(index).set_volume_control( self._encoder[index + 4]) self._encoder_button[index + 4].send_value(127, True) if self._shift_mode._mode_index is 0: #self._on_shift_button_value.subject = self._grid[15] self._alt_shift_mode.set_mode_button('alt_shift', self._grid[15]) #if self._aumpush._host._is_connected: # self._aumpush._host._set_bank_buttons(tuple(self._button[4:12]+self._button[20:28])) #for index in range(8): # self._button[index+4].set_on_off_values(SELECT[self._rgb], (5, 6)[int(index>3)]) # self._mixer2.channel_strip(index).set_select_button(self._button[index+4]) for index in range(4): self._send_reset.set_buttons( tuple(self._encoder_button[4:8])) self._button[index].set_on_off_values(SELECT[self._rgb], 1) self._mixer.channel_strip(index).set_select_button( self._button[index]) self._mixer.channel_strip(index).set_mute_button( self._button[index + 16]) self._button[index + 12].set_on_off_values( SELECT[self._rgb], 1) self._mixer2.channel_strip(index).set_select_button( self._button[index + 12]) self._mixer2.channel_strip(index).set_mute_button( self._button[index + 28]) if not self._shifted: self._mixer.selected_strip().set_send_controls( self._encoder[8:12]) for index in range(4): self._encoder_button[index + 8].send_value(3, True) else: self._mixer.return_strip(0).set_send_controls( tuple([None, self._encoder[8]])) self._mixer.return_strip(1).set_send_controls( tuple([self._encoder[9], None])) #self._mixer.set_crossfader_control(self._encoder[11]) self._mixer3.channel_strip(0).set_volume_control( self._encoder[11]) self._encoder_button[8].send_value(5, True) self._encoder_button[9].send_value(5, True) self._encoder_button[11].send_value(1, True) for index in range(4): self._mixer.channel_strip(index).set_volume_control( self._fader[index]) self._mixer2.channel_strip(index).set_volume_control( self._fader[index + 4]) self._device1.set_parameter_controls( tuple([self._knobs[index] for index in range(8)])) self._device2.set_parameter_controls( tuple([self._knobs[index + 12] for index in range(8)])) self._device1.set_enabled(True) self._device2.set_enabled(True) self._find_devices() self._device1.update() self._device2.update() self._device_selector.set_buttons(self._grid[:15]) self._device_selector.set_enabled(True) self._device_selector.update() self.request_rebuild_midi_map() """used to connect different control_surfaces so that they can communicate""" def connect_script_instances(self, instanciated_scripts): if AUMPUSH_LINK is True: link = False for s in instanciated_scripts: #self.log_message('script check' + str(s)) if link == False: #self.log_message(str(type(s))) if '_cntrlr_version' in dir(s): if s._cntrlr_version == self._monomod_version and s._host_name == 'AumPush': link = True with self.component_guard(): self._connect_aumpush(s) break elif MONOHM_LINK is True: link = False for s in instanciated_scripts: #self.log_message('script check' + str(s)) if link == False: #self.log_message(str(type(s))) if '_cntrlr_version' in dir(s): if s._cntrlr_version == self._monomod_version: link = True with self.component_guard(): self._connect_monohm(s) break """device component methods and overrides""" def _device_set_device(self, device_component): def set_device(device): is_monodevice = False for client in self._client: if (device != None) and (client.device == device): is_monodevice = client if is_monodevice != False: #device = client._device_component._device #self.log_message('is monodevice' + str(device.name)) assert ((device == None) or isinstance(device, Live.Device.Device)) if ((not device_component._locked_to_device) and (device != device_component._device)): if (device_component._device != None): device_component._device.remove_name_listener( device_component._on_device_name_changed) device_component._device.remove_parameters_listener( device_component._on_parameters_changed) parameter = device_component._on_off_parameter() if (parameter != None): parameter.remove_value_listener( device_component._on_on_off_changed) if (device_component._parameter_controls != None): for control in device_component._parameter_controls: control.release_parameter() device_component._device = device if (device_component._device != None): device_component._bank_index = 0 device_component._device.add_name_listener( self._on_device_name_changed) device_component._device.add_parameters_listener( self._on_parameters_changed) parameter = device_component._on_off_parameter() if (parameter != None): parameter.add_value_listener( device_component._on_on_off_changed) for key in device_component._device_bank_registry.keys(): if (key == device_component._device): device_component._bank_index = device_component._device_bank_registry.get( key, 0) del device_component._device_bank_registry[key] break device_component._bank_name = '<No Bank>' #added device_component._bank_index = max( is_monodevice._cntrl_offset, device_component._bank_index) device_component._on_device_name_changed() device_component.update() else: DeviceComponent.set_device(device_component, device) return set_device """this closure replaces the default ChannelStripComponent _on_cf_assign_changed() method without requiring us to build an override class""" """it allows us to change different colors to its assigned controls based on the crossfade assignment, which the default _Framework doesn't support""" def mixer_on_cf_assign_changed(self, channel_strip): def _on_cf_assign_changed(): if (channel_strip.is_enabled() and (channel_strip._crossfade_toggle != None)): if (channel_strip._track != None) and (channel_strip._track in (channel_strip.song().tracks + channel_strip.song().return_tracks)): if channel_strip._track.mixer_device.crossfade_assign == 1: #modified channel_strip._crossfade_toggle.turn_off() elif channel_strip._track.mixer_device.crossfade_assign == 0: channel_strip._crossfade_toggle.send_value(1) else: channel_strip._crossfade_toggle.send_value(2) return _on_cf_assign_changed """a closure fix for banking when we deassign the bank buttons and still want to change bank indexes""" def device_is_banking_enabled(self, device): def _is_banking_enabled(): return True return _is_banking_enabled """this is called by connect_script_instances() when a AumPush script is found to be installed""" def _connect_aumpush(self, aumpush): self.log_message('AumTroll connecting to AumPush...') self._aumpush = aumpush self._aumpush._cntrlr = self with self.component_guard(): self.deassign_live_controls() self.schedule_message(3, self.assign_live_controls) #self._device_selector.update = self._make_device_selector_update(self._device_selector) """these two secondary DeviceComponents are only set up if the MONOHM_LINK flag in .Map is turned on""" def _setup_alt_device_control(self): self._device1 = DeviceComponent() self._device1.name = 'Device_Component1' self._device2 = DeviceComponent() self._device2.name = 'Device_Component2' """this method is used to find the devices the alt controls will latch to""" def _find_devices(self): if self._device1: if len(self.song().return_tracks) > 0: if len(self.song().return_tracks[0].devices) > 0: #self._device.set_device(self.song().return_tracks[0].devices[0]) if self._device1._locked_to_device: self._device1.set_lock_to_device( False, self._device1._device) self._device1.set_lock_to_device( True, self.song().return_tracks[0].devices[0]) if self._device2: if len(self.song().return_tracks) > 1: if len(self.song().return_tracks[1].devices) > 0: #self._device2.set_device(self.song().return_tracks[1].devices[0]) if self._device2._locked_to_device: self._device2.set_lock_to_device( False, self._device2._device) self._device2.set_lock_to_device( True, self.song().return_tracks[1].devices[0]) #self.log_message('find devices') """this secondary MixerComponent is only set up if the MONOHM_LINK flag in .Map is turned on""" def _setup_alt_mixer(self): is_momentary = True self._num_tracks = (8) #A mixer is one-dimensional self._mixer2 = MixerComponent(8, 0, False, False) self._mixer2.name = 'Mixer_2' self._mixer2.set_track_offset( 4) #Sets start point for mixer strip (offset from left) for index in range(8): self._mixer2.channel_strip( index).name = 'Mixer_2_ChannelStrip_' + str(index) self._mixer2.channel_strip(index)._invert_mute_feedback = True self._mixer3 = MixerComponent(4, 4, False, False) self._mixer3.name = 'Mixer_3' self._mixer3.set_track_offset( 8) #Sets start point for mixer strip (offset from left) for index in range(4): self._mixer3.channel_strip( index).name = 'Mixer_3_ChannelStrip_' + str(index) self._mixer3.channel_strip(index)._invert_mute_feedback = True @subject_slot('value') def _on_shift_button_value(self, value): shifted = value > 0 if not self._shifted is shifted: self._shifted = shifted self.deassign_live_controls() self.assign_live_controls() if self._shifted and self._on_shift_button_value.subject: self._on_shift_button_value.subject.send_value(12, True) # a
def _setup_mixer_control(self): is_momentary = True self._num_tracks = COLS global mixer mixer = MixerComponent(COLS, 0, True, True) mixer.name = "Mixer" self._mixer = mixer mixer.set_track_offset(0) # Sets start point for mixer strip (offset from left) for index in range(COLS): # use the bottom row of encoders for volume, so add 24 to offset the index mixer.channel_strip(index).set_volume_control(self._dial[index + 24]) for index in range(COLS): mixer.channel_strip(index).name = "Mixer_ChannelStrip_" + str(index) mixer.track_eq(index).name = "Mixer_EQ_" + str(index) mixer.track_filter(index).name = "Mixer_Filter_" + str(index) # added by a mixer.channel_strip(index)._invert_mute_feedback = True # mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index])) self.song().view.selected_track = mixer.channel_strip( 0 )._track # set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error
class Tweaker(ControlSurface): __module__ = __name__ __doc__ = " MonOhmod companion controller script " def __init__(self, c_instance): """everything except the '_on_selected_track_changed' override and 'disconnect' runs from here""" ControlSurface.__init__(self, c_instance) with self.component_guard(): self._update_linked_device_selection = None self._tweaker_version = "0.4" self.log_message( "--------------= Tweaker Mixer " + str(self._tweaker_version) + " log opened =--------------" ) self._update_linked_device_selection = None self._setup_mixer_control() self._setup_session_control() """script initialization methods""" def _setup_controls(self): is_momentary = True self._grid = [None for index in range(8)] for column in range(8): self._grid[column] = [ FlashingButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, column + (row * 8), "Grid_" + str(column) + "_" + str(row), self, ) for row in range(4) ] self._button = [ FlashingButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_BUTTONS[index], "Button_" + str(index), self ) for index in range(len(TWEAKER_BUTTONS)) ] self._nav = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_NAVS[index], "Nav_" + str(index), self) for index in range(len(TWEAKER_NAVS)) ] self._encoder_buttons = [ FlashingButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_ENCODER_BUTTONS[index], "Encoder_Button_" + str(index), self, ) for index in range(len(TWEAKER_ENCODER_BUTTONS)) ] self._dial = [ EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_DIALS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_DIALS)) ] self._fader = [ EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_FADERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_FADERS)) ] self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute) self._encoder = [ EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_ENCODERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_ENCODERS)) ] self._pad = [ FlashingButtonElement( not is_momentary, MIDI_CC_TYPE, CHANNEL, TWEAKER_PADS[index], "Pad_" + str(index), self ) for index in range(len(TWEAKER_PADS)) ] self._matrix = ButtonMatrixElement() self._matrix.name = "Matrix" for row in range(4): button_row = [] for column in range(7): button_row.append(self._grid[column][row]) self._matrix.add_row(tuple(button_row)) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = "Transport" def _setup_mixer_control(self): is_momentary = True self._num_tracks = 2 # A mixer is one-dimensional; self._mixer = MixerComponent(2, 0, False, True) self._mixer.name = "Mixer" self._mixer.tracks_to_use = self._mixer_tracks_to_use(self._mixer) self._mixer.set_track_offset(0) # Sets start point for mixer strip (offset from left) def _setup_session_control(self): is_momentary = True num_tracks = 2 num_scenes = 3 self._session = SessionComponent(num_tracks, num_scenes) self._session.name = "Session" self._session.set_offsets(0, 0) self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) """general functionality""" def allow_updates(self, allow_updates): for component in self.components: component.set_allow_update(int(allow_updates != 0)) def disconnect(self): """clean things up on disconnect""" if self._session._is_linked(): self._session._unlink() self.log_message( "--------------= Tweaker Mixer " + str(self._tweaker_version) + " log closed =--------------" ) # Create entry in log file ControlSurface.disconnect(self) return None def connect_script_instances(self, instanciated_scripts): link = False for s in instanciated_scripts: if "_tweaker_version" in dir(s): if s._tweaker_version == self._tweaker_version: link = True if not s is self: s._linked_session = self._session # break if link is True: if not self._session._is_linked(): # self._session.set_offsets(0, 0) self._session._link() def _mixer_tracks_to_use(self, mixer): def tracks_to_use(): return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) return tracks_to_use
class AumTroll(Cntrlr): __module__ = __name__ __doc__ = " MonOhmod companion controller script " def __init__(self, *a, **k): self._monohm = None self._aumpush = None self._shifted = False self._use_pedal = True self._suppress_next_mod_display = False self._monomod_version = 'b996' self._codec_version = 'b996' super(AumTroll, self).__init__(*a, **k) self._host_name = "AumTroll" with self.component_guard(): self._setup_alt_device_control() self._setup_alt_mixer() #self._setup_device_selector() # Not sure why this was HERE, but removed 051314 because it was overriding mod grid updates #self._setup_alt_device_control() #self.schedule_message(3, self._session._do_show_highlight) self._send_midi(tuple(request_snapshot)) """script initialization methods""" def _open_log(self): self.log_message("<<<<<<<<<<<<<<<<<<<<= " + str(self._host_name) + " " + str(self._monomod_version) + " log opened =>>>>>>>>>>>>>>>>>>>") self.show_message(str(self._host_name) + ' Control Surface Loaded') def _setup_modes(self): super(AumTroll, self)._setup_modes() self._alt_shift_mode = ModesComponent() self._alt_shift_mode.add_mode('alt_shift', tuple([self._enable_alt_shift, self._disable_alt_shift]), behaviour = CancellableBehaviourWithRelease()) self._alt_shift_mode.set_mode_button('alt_shift', self._grid[15]) def _enable_alt_shift(self): self._alt_shift_enabled = True self._on_shift_button_value(1) def _disable_alt_shift(self): self._alt_shift_enabled = False self._on_shift_button_value(0) def deassign_live_controls(self): self._leds_last = None self._device_selector.set_enabled(False) self._device._parameter_controls = None self._device1._parameter_controls = None self._device2._parameter_controls = None for index in range(8): self._mixer2.channel_strip(index).set_select_button(None) self._mixer2.channel_strip(index).set_volume_control(None) for index in range(4): self._mixer3.channel_strip(index).set_select_button(None) self._mixer3.channel_strip(index).set_volume_control(None) self._mixer3.return_strip(index).set_volume_control(None) #if self._aumpush: # self._aumpush._host._set_bank_buttons(None) #self._on_shift_button_value.subject = None self._alt_shift_mode.set_mode_button('alt_shift', None) self._mixer.set_crossfader_control(None) """THIS SECTION IS MISSING FROM THE ORIGINAL SCRIPT AND NEEDS TO BE FIXED...THE ASSIGNMENTS WERE MADE AT __init__""" for index in range(4): self._mixer.channel_strip(index).set_volume_control(None) #Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it for index in range(2): self._mixer.return_strip(index).set_volume_control(None) #assign the right faders to control the volume of our return strips self._mixer.master_strip().set_volume_control(None) #assign the far right fader to control our master channel strip self._mixer.set_prehear_volume_control(None) #assign the remaining fader to control our prehear volume of the the master channel strip for index in range(4): #for the left side of the mixer self._mixer.channel_strip(index).set_solo_button(None) #remove the solo button assignments self._mixer.channel_strip(index).set_arm_button(None) #remove the arm button assignments self._mixer.channel_strip(index).set_mute_button(None) #remove the mute button assignments self._mixer.channel_strip(index).set_select_button(None) #remove the select button assignments for column in range(4): for row in range(4): self._scene[row].clip_slot(column).set_launch_button(None) #remove the clip launch assignments self._send_reset.set_buttons(tuple([None for index in range(4)])) #remove the send_reset button assignments - this has to be sent as a tuple self._session.set_stop_track_clip_buttons(None) #remove the clip_stop button assignments self._session.set_track_bank_buttons(None, None) #set the track bank buttons for the Session navigation controls self._session.set_scene_bank_buttons(None, None) #set the scnee bank buttons for the Session navigation controls self._transport.set_play_button(None) #remove the play button assignment self._transport.set_record_button(None) #remove the record button assignment self._transport.set_stop_button(None) #remove the stop button assignment for index in range(16): self._grid[index].set_on_off_values(127, 0) #reset the on/off values of the grid buttons self._grid[index].reset() #turn the buttons LEDs off for index in range(32): self._button[index].set_on_off_values(127, 0) #reset the on/off values for the key buttons self._button[index].release_parameter() #remove the parameter assignment that was assigned to the keys self._button[index].send_value(0, True) #turn the buttons LEDs off #self._device.set_parameter_controls(tuple([self._encoder[index+4] for index in range(8)])) #assign the encoders from the device component controls - we are doing this here b self._device_navigator.set_nav_buttons(None, None) #remove the assignment of the device nav buttons self._device_navigator.set_enabled(False) #turn off the device navigator self._device.set_on_off_button(None) #remove the assignment of the on/off button from the device component self._device.set_lock_button(None) #remove the assignment of the lock button from the device component self._device.set_bank_nav_buttons(None, None) #remove the assignment of the navigation buttons from the device component self._device.set_enabled(False) #turn off the device component self._session.set_enabled(False) #turn off the session component self._session_zoom.set_enabled(False) #turn off the zoom component for index in range(16): self._grid[index].force_next_send() #set the last_sent value of the grid to -1, so that the next value it receives will always be transmitted to the CNTRLR for index in range(32): self._button[index].force_next_send() #set the last_sent value of the keys to -1, so that the next value it receives will always be transmitted to the CNTRLR for index in range(12): self._device._parameter_controls = None self._encoder[index].release_parameter() self._encoder[index].send_value(0, True) #turn off all the encoder rings. We send it the second argument, True, so that it is forced to update regardless of its last_sent property self._encoder[index].force_next_send() #set the last_sent value of the encoder rings to -1, so that the next value it receives will always be transmitted to the CNTRLR for index in range(8): self._encoder_button[index+4].send_value(0, True) #turn off all the encoder LEDs. We send it the second argument, True, so that it is forced to update regardless of its last_sent property self._encoder_button[index+4].force_next_send() #set the last_sent value of the encoder LEDs to -1, so that the next value it receives will always be transmitted to the CNTRLR for index in range(8): self._mixer2.channel_strip(index).set_select_button(None) self._mixer2.channel_strip(index).set_mute_button(None) self._mixer2.channel_strip(index).set_select_button(None) self._session_zoom.set_zoom_button(None) #remove the assignment of the shift button from the ZoomingComponent self.request_rebuild_midi_map() #now that we've finished deassigning all of our controls, we tell the main script to rebuild its MIDI map and update the values in Live def assign_live_controls(self): """the following lines update all of the controls' last_sent properties, so that they forward the next value they receive regardless of whether or not it is the same as the last it recieved""" """we also reset the encoder rings and buttons, since the device component will not update them if it is not locked to a device in Live""" for index in range(16): self._grid[index].force_next_send() for index in range(32): self._button[index].force_next_send() for index in range(8): self._encoder_button[index+4].send_value(0, True) self._encoder_button[index+4].force_next_send() for index in range(12): self._encoder[index].send_value(0, True) self._encoder[index].force_next_send() """here we assign the left side of our mixer's buttons on the lower 32 keys""" if self._monohm == None and self._aumpush == None: for index in range(4): #we set up a recursive loop to assign all four of our track channel strips' controls self._button[index].set_on_value(SOLO[self._rgb]) #set the solo color from the Map.py self._mixer.channel_strip(index).set_solo_button(self._button[index]) #assign the solo buttons to our mixer channel strips self._button[index+4].set_on_value(ARM[self._rgb]) #set the arm color from the Map.py self._mixer.channel_strip(index).set_arm_button(self._button[index+4]) #assign the arm buttons to our mixer channel strips self._button[index+16].set_on_value(MUTE[self._rgb]) #set the mute color from the Map.py self._mixer.channel_strip(index).set_mute_button(self._button[index+16]) #assign the mute buttons to our mixer channel strips self._button[index+20].set_on_value(SELECT[self._rgb]) #set the select color from the Map.py self._mixer.channel_strip(index).set_select_button(self._button[index+20]) #assign the select buttons to our mixer channel strips self._send_reset.set_buttons(tuple(self._button[index + 8] for index in range(4))) #this is yet another way to quickly assign multiple elements conveniently in-place. We are creating a recursion inside an assignment. The tuple() method creates an immutable array. It can't be modified until it gets where it's going and is unpacked. self._session.set_stop_track_clip_buttons(tuple(self._button[index+24] for index in range(4))) #these last two lines assign the send_reset buttons and the stop_clip buttons for each track for index in range(4): self._button[index+8].send_value(SEND_RESET[self._rgb], True) #now we are going to send a message to turn the LEDs on for the send_reset buttons self._button[index + 24].set_on_off_values(STOP_CLIP[self._rgb], STOP_CLIP[self._rgb]) #this assigns the custom colors defined in the Map.py file to the stop_clip buttons. They have seperate on/off values, but we assign them both the same value so we can always identify them self._button[index+24].send_value(STOP_CLIP[self._rgb], True) #finally, we send the on/off colors out to turn the LEDs on for the stop clip buttons self._button[28].set_on_off_values(PLAY_ON[self._rgb], PLAY[self._rgb]) #assing the on/off colors for play. These are two seperate values, dependant upon whether play is engaged or not self._transport.set_play_button(self._button[28]) #set the transports play control to the corresponding button on the CNTRLR self._button[30].set_on_off_values(RECORD_ON[self._rgb], RECORD[self._rgb]) #set the on/off colors for the transport record buttons self._transport.set_record_button(self._button[30]) #assign the correct button for the transport record control self._button[29].set_on_value(STOP[self._rgb]) #set the on value for the Stop button self._transport.set_stop_button(self._button[29]) #assign the correct button for the transport stop control self._button[29].send_value(STOP_OFF[self._rgb], True) #turn on the LED for the stop button for index in range(4): #set up a for loop to generate an index for assigning the session nav buttons' colors self._button[index + 12].set_on_off_values(SESSION_NAV[self._rgb], SESSION_NAV_OFF[self._rgb]) #assign the colors from Map.py to the session nav buttons self._session.set_track_bank_buttons(self._button[15], self._button[14]) #set the track bank buttons for the Session navigation controls self._session.set_scene_bank_buttons(self._button[13], self._button[12]) #set the scnee bank buttons for the Session navigation controls """this section assigns the grid to the clip launch functionality of the SessionComponent""" for column in range(4): #we need to set up a double recursion so that we can generate the indexes needed to assign the grid buttons for row in range(4): #the first recursion passes the column index, the second the row index self._scene[row].clip_slot(column).set_launch_button(self._grid[(row*4)+column]) #we use the indexes to grab the first the scene and then the clip we assigned above, and then we use them again to define the button held in the grid array that we want to assign to the clip slot from the session component """this section assigns the faders and knobs""" for index in range(2): self._mixer.return_strip(index).set_volume_control(self._fader[index+4]) #assign the right faders to control the volume of our return strips self._mixer.master_strip().set_volume_control(self._fader[7]) #assign the far right fader to control our master channel strip self._mixer.set_prehear_volume_control(self._fader[6]) #assign the remaining fader to control our prehear volume of the the master channel strip for track in range(4): #we set up a recursive loop to assign all four of our track channel strips' controls channel_strip_send_controls = [] #the channelstripcomponent requires that we pass the send controls in an array, so we create a local variable, channel_strip_send_controls, to hold them for control in range(2): #since we are going to assign two controls to the sends, we create a recursion channel_strip_send_controls.append(self._dial_left[track + (control * 4)]) #then use the append __builtin__ method to add them to the array self._mixer.channel_strip(track).set_volume_control(self._fader[track]) #Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it self._mixer.channel_strip(track).set_send_controls(tuple(channel_strip_send_controls)) #now that we have an array containing the send controls, we pass it to the channelstrip component with its set_send_controls() method self._mixer.channel_strip(track).set_pan_control(self._dial_left[track + 8]) #now we set the pan control to the bottom self._mixer.track_eq(track).set_gain_controls(tuple([self._dial_right[track+8], self._dial_right[track+4], self._dial_right[track]])) #here's another way of doing the same thing, but instead of creating the array before hand, we define it in-place. Its probably bad coding to mix styles like this, but I'll leave it for those of you trying to figure this stuff out self._mixer.track_eq(track).set_enabled(True) #turn the eq component on self._session_zoom.set_zoom_button(self._button[31]) #assign the lower right key button to the shift function of the Zoom component self._session.update() #tell the Session component to update so that the grid will display the currently selected session region self._session.set_enabled(True) #enable the Session Component self._session_zoom.set_enabled(True) #enable the Session Zoom elif not self._aumpush == None: self.assign_aumpush_controls() elif not self._monohm == None: for index in range(8): self._mixer2.channel_strip(index).set_volume_control(self._fader[index]) self._mixer2.set_track_offset(TROLL_OFFSET) self._device_selector.set_buttons(self._grid) self._device_selector.set_enabled(True) if not self._shifted: self._assign_monomodular_controls() else: self._assign_shifted_controls() self._device1.set_parameter_controls(tuple([self._knobs[index] for index in range(8)])) self._device2.set_parameter_controls(tuple([self._knobs[index+12] for index in range(8)])) self._device1.set_enabled(True) self._device2.set_enabled(True) self._find_devices() self._device1.update() self._device2.update() """this section assigns the encoders and encoder buttons""" if self._aumpush == None: self._device.set_parameter_controls(tuple([self._encoder[index+4] for index in range(8)])) #assign the encoders from the device component controls - we are doing this here b self._encoder_button[7].set_on_value(DEVICE_LOCK[self._rgb]) #set the on color for the Device lock encoder button self._device.set_lock_button(self._encoder_button[7]) #assign encoder button 7 to the device lock control self._encoder_button[4].set_on_value(DEVICE_ON[self._rgb]) #set the on color for the Device on/off encoder button self._device.set_on_off_button(self._encoder_button[4]) #assing encoder button 4 to the device on/off control for index in range(2): #setup a recursion to generate indexes so that we can reference the correct controls to assing to the device_navigator functions self._encoder_button[index + 8].set_on_value(DEVICE_NAV[self._rgb]) #assign the on color for the device navigator self._encoder_button[index + 10].set_on_value(DEVICE_BANK[self._rgb]) #assign the on color for the device bank controls self._device_navigator.set_nav_buttons(self._encoder_button[10], self._encoder_button[11]) #set the device navigators controls to encoder buttons 10 and 11 self._device.set_bank_nav_buttons(self._encoder_button[8], self._encoder_button[9]) #set the device components bank nav controls to encoder buttons 8 and 9 """now we turn on and update some of the components we've just made assignments to""" self._device.set_enabled(True) #enable the Device Component self._device_navigator.set_enabled(True) #enable the Device Navigator self._device.update() #tell the Device component to update its assingments so that it will detect the currently selected device parameters and display them on the encoder rings """function mode callbacks""" """this method changes modes when we press a modButton. It is also called from Monomod when it needs to update the modDial assignments""" def shift_update(self): super(AumTroll, self).shift_update() if self._shift_mode._mode_index == 0: if self._aumpush == None: for index in range(8): self._mixer2.channel_strip(index).set_volume_control(self._fader[index]) self._mixer2.set_track_offset(TROLL_OFFSET) self._device1.set_parameter_controls(tuple([self._knobs[index] for index in range(8)])) self._device2.set_parameter_controls(tuple([self._knobs[index+12] for index in range(8)])) self._device1.set_enabled(True) self._device2.set_enabled(True) self._find_devices() self._device1.update() self._device2.update() else: self.assign_aumpush_controls() def find_inputs(self): found_device = None tracks = self.song().tracks for track in tracks: if track.name == 'Inputs': for device in track.devices: if bool(device.can_have_chains) and device.name == 'Inputs': found_device = device return found_device def find_perc_crossfader(self): found_parameter = None tracks = self.song().tracks for track in tracks: if track.name == 'Perc': for device in track.devices: if bool(device.can_have_chains) and device.name == 'Perc': for parameter in device.parameters: if parameter.name == 'XFade': found_parameter = parameter return found_parameter def assign_aumpush_controls(self): if self._aumpush: inputs = self.find_inputs() if not inputs is None: for index in range(4): self._knobs[index+8].connect_to(inputs.parameters[index+1]) #for index in range(3): # self._mixer2.channel_strip(index+4).set_volume_control(self._knobs[index+20]) self._mixer.set_crossfader_control(self._knobs[23]) xfade = self.find_perc_crossfader() if not xfade is None: self._knobs[20].connect_to(xfade) for index in range(4): self._mixer3.return_strip(index).set_volume_control(self._encoder[index+4]) self._encoder_button[index+4].send_value(127, True) if self._shift_mode._mode_index is 0: #self._on_shift_button_value.subject = self._grid[15] self._alt_shift_mode.set_mode_button('alt_shift', self._grid[15]) #if self._aumpush._host._is_connected: # self._aumpush._host._set_bank_buttons(tuple(self._button[4:12]+self._button[20:28])) #for index in range(8): # self._button[index+4].set_on_off_values(SELECT[self._rgb], (5, 6)[int(index>3)]) # self._mixer2.channel_strip(index).set_select_button(self._button[index+4]) for index in range(4): self._send_reset.set_buttons(tuple(self._encoder_button[4:8])) self._button[index].set_on_off_values(SELECT[self._rgb], 1) self._mixer.channel_strip(index).set_select_button(self._button[index]) self._mixer.channel_strip(index).set_mute_button(self._button[index+16]) self._button[index+12].set_on_off_values(SELECT[self._rgb], 1) self._mixer2.channel_strip(index).set_select_button(self._button[index+12]) self._mixer2.channel_strip(index).set_mute_button(self._button[index+28]) if not self._shifted: self._mixer.selected_strip().set_send_controls(self._encoder[8:12]) for index in range(4): self._encoder_button[index+8].send_value(3, True) else: self._mixer.return_strip(0).set_send_controls(tuple([None, self._encoder[8]])) self._mixer.return_strip(1).set_send_controls(tuple([self._encoder[9], None])) #self._mixer.set_crossfader_control(self._encoder[11]) self._mixer3.channel_strip(0).set_volume_control(self._encoder[11]) self._encoder_button[8].send_value(5, True) self._encoder_button[9].send_value(5, True) self._encoder_button[11].send_value(1, True) for index in range(4): self._mixer.channel_strip(index).set_volume_control(self._fader[index]) self._mixer2.channel_strip(index).set_volume_control(self._fader[index+4]) self._device1.set_parameter_controls(tuple([self._knobs[index] for index in range(8)])) self._device2.set_parameter_controls(tuple([self._knobs[index+12] for index in range(8)])) self._device1.set_enabled(True) self._device2.set_enabled(True) self._find_devices() self._device1.update() self._device2.update() self._device_selector.set_buttons(self._grid[:15]) self._device_selector.set_enabled(True) self._device_selector.update() self.request_rebuild_midi_map() """used to connect different control_surfaces so that they can communicate""" def connect_script_instances(self, instanciated_scripts): if AUMPUSH_LINK is True: link = False for s in instanciated_scripts: #self.log_message('script check' + str(s)) if link == False: #self.log_message(str(type(s))) if '_cntrlr_version' in dir(s): if s._cntrlr_version == self._monomod_version and s._host_name == 'AumPush': link = True with self.component_guard(): self._connect_aumpush(s) break elif MONOHM_LINK is True: link = False for s in instanciated_scripts: #self.log_message('script check' + str(s)) if link == False: #self.log_message(str(type(s))) if '_cntrlr_version' in dir(s): if s._cntrlr_version == self._monomod_version: link = True with self.component_guard(): self._connect_monohm(s) break """device component methods and overrides""" def _device_set_device(self, device_component): def set_device(device): is_monodevice = False for client in self._client: if (device != None) and (client.device == device): is_monodevice = client if is_monodevice != False: #device = client._device_component._device #self.log_message('is monodevice' + str(device.name)) assert ((device == None) or isinstance(device, Live.Device.Device)) if ((not device_component._locked_to_device) and (device != device_component._device)): if (device_component._device != None): device_component._device.remove_name_listener(device_component._on_device_name_changed) device_component._device.remove_parameters_listener(device_component._on_parameters_changed) parameter = device_component._on_off_parameter() if (parameter != None): parameter.remove_value_listener(device_component._on_on_off_changed) if (device_component._parameter_controls != None): for control in device_component._parameter_controls: control.release_parameter() device_component._device = device if (device_component._device != None): device_component._bank_index = 0 device_component._device.add_name_listener(self._on_device_name_changed) device_component._device.add_parameters_listener(self._on_parameters_changed) parameter = device_component._on_off_parameter() if (parameter != None): parameter.add_value_listener(device_component._on_on_off_changed) for key in device_component._device_bank_registry.keys(): if (key == device_component._device): device_component._bank_index = device_component._device_bank_registry.get(key, 0) del device_component._device_bank_registry[key] break device_component._bank_name = '<No Bank>' #added device_component._bank_index = max(is_monodevice._cntrl_offset, device_component._bank_index) device_component._on_device_name_changed() device_component.update() else: DeviceComponent.set_device(device_component, device) return set_device """this closure replaces the default ChannelStripComponent _on_cf_assign_changed() method without requiring us to build an override class""" """it allows us to change different colors to its assigned controls based on the crossfade assignment, which the default _Framework doesn't support""" def mixer_on_cf_assign_changed(self, channel_strip): def _on_cf_assign_changed(): if (channel_strip.is_enabled() and (channel_strip._crossfade_toggle != None)): if (channel_strip._track != None) and (channel_strip._track in (channel_strip.song().tracks + channel_strip.song().return_tracks)): if channel_strip._track.mixer_device.crossfade_assign == 1: #modified channel_strip._crossfade_toggle.turn_off() elif channel_strip._track.mixer_device.crossfade_assign == 0: channel_strip._crossfade_toggle.send_value(1) else: channel_strip._crossfade_toggle.send_value(2) return _on_cf_assign_changed """a closure fix for banking when we deassign the bank buttons and still want to change bank indexes""" def device_is_banking_enabled(self, device): def _is_banking_enabled(): return True return _is_banking_enabled """this is called by connect_script_instances() when a AumPush script is found to be installed""" def _connect_aumpush(self, aumpush): self.log_message('AumTroll connecting to AumPush...') self._aumpush = aumpush self._aumpush._cntrlr = self with self.component_guard(): self.deassign_live_controls() self.schedule_message(3, self.assign_live_controls) #self._device_selector.update = self._make_device_selector_update(self._device_selector) """these two secondary DeviceComponents are only set up if the MONOHM_LINK flag in .Map is turned on""" def _setup_alt_device_control(self): self._device1 = DeviceComponent() self._device1.name = 'Device_Component1' self._device2 = DeviceComponent() self._device2.name = 'Device_Component2' """this method is used to find the devices the alt controls will latch to""" def _find_devices(self): if self._device1: if len(self.song().return_tracks) > 0: if len(self.song().return_tracks[0].devices) > 0: #self._device.set_device(self.song().return_tracks[0].devices[0]) if self._device1._locked_to_device: self._device1.set_lock_to_device(False, self._device1._device) self._device1.set_lock_to_device(True, self.song().return_tracks[0].devices[0]) if self._device2: if len(self.song().return_tracks) > 1: if len(self.song().return_tracks[1].devices) > 0: #self._device2.set_device(self.song().return_tracks[1].devices[0]) if self._device2._locked_to_device: self._device2.set_lock_to_device(False, self._device2._device) self._device2.set_lock_to_device(True, self.song().return_tracks[1].devices[0]) #self.log_message('find devices') """this secondary MixerComponent is only set up if the MONOHM_LINK flag in .Map is turned on""" def _setup_alt_mixer(self): is_momentary = True self._num_tracks = (8) #A mixer is one-dimensional self._mixer2 = MixerComponent(8, 0, False, False) self._mixer2.name = 'Mixer_2' self._mixer2.set_track_offset(4) #Sets start point for mixer strip (offset from left) for index in range(8): self._mixer2.channel_strip(index).name = 'Mixer_2_ChannelStrip_' + str(index) self._mixer2.channel_strip(index)._invert_mute_feedback = True self._mixer3 = MixerComponent(4, 4, False, False) self._mixer3.name = 'Mixer_3' self._mixer3.set_track_offset(8) #Sets start point for mixer strip (offset from left) for index in range(4): self._mixer3.channel_strip(index).name = 'Mixer_3_ChannelStrip_' + str(index) self._mixer3.channel_strip(index)._invert_mute_feedback = True @subject_slot('value') def _on_shift_button_value(self, value): shifted = value > 0 if not self._shifted is shifted: self._shifted = shifted self.deassign_live_controls() self.assign_live_controls() if self._shifted and self._on_shift_button_value.subject: self._on_shift_button_value.subject.send_value(12, True) # a
class GuitarWing(ControlSurface): __module__ = __name__ __doc__ = " GuitarWing controller script " def __init__(self, c_instance): super(GuitarWing, self).__init__(c_instance) self._connected = False self._host_name = 'GuitarWing' self._color_type = 'OhmRGB' self.oscServer = None self.log_message("<<<<<<<<<<<<<<<<<= GuitarWing log opened =>>>>>>>>>>>>>>>>>>>>>") self._timer = 0 self._current_nav_buttons = [] self.flash_status = 1 self._clutch_device_selection = False self._touched = 0 self._last_selected_track = None self._last_selected_track_arm = False self._device_selection_follows_track_selection = True with self.component_guard(): self._setup_monobridge() self._setup_controls() self._setup_m4l_interface() #self._setup_OSC_layer() self._setup_device_control() self._setup_transport_control() #self._setup_selected_session_control() self._setup_mixer_control() self._setup_session_control() #self._setup_step_sequencer() #self._device.add_device_listener(self._on_new_device_set) self._device.set_parameter_controls(tuple([self._fader[0], self._fader[1], self._fader[2], self._accel[2], self._ccs[0], self._ccs[1], self._ccs[2], self._ccs[3]])) #, self._fader_button[0], self._fader_button[1], self._fader_button[2], self._padCC[4]])) self._mixer.set_select_buttons(self._button[1], self._button[0]) #self._session.set_scene_launch_buttons(self._pad[:4]) for index in range(4): self._scene[index].set_launch_button(self._pad[index]) #for index in range(4): # self._pad[index].set_identifier(36+index) # self._pad[index].set_channel(CHANNEL) # self._pad[index].set_enabled(False) self._transport.set_stop_button(self._button[6]) self._transport.set_loop_button(self._button[7]) self._transport.set_seek_backward_button(self._button[8]) self._transport.set_record_button(self._button[9]) #self._on_select_track_down_value.subject = self._button[0] #self._on_select_track_up_value.subject = self._button[1] @subject_slot('value') def _on_select_track_up_value(self, value): if value: pass @subject_slot('value') def _on_select_track_down_value(self, value): if value: pass def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_controls(self): is_momentary = True self._button = [MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, BUTTONS[index], 'Button_' + str(index), self) for index in range(10)] self._fader = [MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, SLIDERS[index], Live.MidiMap.MapMode.absolute, 'Fader_' + str(index), index, self) for index in range(3)] #self._fader_button = [MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, index, 'Fader_Button_' + str(index), self) for index in range(3)] self._fader_button = [MonoEncoderElement(MIDI_NOTE_TYPE, CHANNEL, SLIDERS[index], Live.MidiMap.MapMode.absolute, 'Fader_Button_' + str(index), index, self) for index in range(3)] self._ccs = [MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, CCS[index], Live.MidiMap.MapMode.absolute, 'CCs_' + str(index), index, self) for index in range(4)] self._pad = [MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, PADS[index], 'Pad_' + str(index), self) for index in range(5)] self._padCC = [MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, PADS[index], Live.MidiMap.MapMode.absolute, 'PadCC_' + str(index), index, self) for index in range(5)] self._accel = [MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, ACCELS[index], Live.MidiMap.MapMode.absolute, 'Accel_' + str(index), index, self) for index in range(3)] def _setup_mixer_control(self): is_momentary = True self._num_tracks = (1) #A mixer is one-dimensional; self._mixer = MixerComponent(1, 0, False, False) self._mixer.name = 'Mixer' self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) for index in range(1): self._mixer.channel_strip(index)._invert_mute_feedback = True self._mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) #for index in range(4): # self._mixer.return_strip(index).name = 'Mixer_ReturnStrip_' + str(index) self._mixer.selected_strip().name = 'Mixer_SelectedStrip' self.song().view.selected_track = self._mixer.channel_strip(0)._track def _setup_session_control(self): self._session = GuitarWingSessionComponent(1, 4, self) self._session.name = "Session" self._session.set_offsets(0, 0) self._session.set_stop_clip_value(STOP_CLIP) self._scene = [None for index in range(4)] for row in range(4): self._scene[row] = self._session.scene(row) self._scene[row].name = 'Scene_' + str(row) for column in range(1): clip_slot = self._scene[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_' + str(row) clip_slot.set_triggered_to_play_value(CLIP_TRG_PLAY) clip_slot.set_triggered_to_record_value(CLIP_TRG_REC) clip_slot.set_stopped_value(CLIP_STOP) clip_slot.set_started_value(CLIP_STARTED) clip_slot.set_recording_value(CLIP_RECORDING) self._session.set_mixer(self._mixer) #self._session.set_track_banking_increment(TRACK_BANKING_INCREMENT) self.set_highlighting_session_component(self._session) self._session._do_show_highlight() def _setup_transport_control(self): self._transport = TransportComponent() def _setup_selected_session_control(self): self._selected_session = GuitarWingSessionComponent(1, 16, self) self._selected_session.name = "SelectedSession" self._selected_session.set_offsets(0, 0) self._selected_session.set_stop_clip_value(STOP_CLIP) self._selected_scene = [None for index in range(16)] for row in range(16): self._selected_scene[row] = self._selected_session.scene(row) self._selected_scene[row].name = 'SelectedScene_' + str(row) clip_slot = self._selected_scene[row].clip_slot(0) clip_slot.name = 'Selected_Clip_Slot_' + str(row) clip_slot.set_triggered_to_play_value(CLIP_TRG_PLAY) clip_slot.set_triggered_to_record_value(CLIP_TRG_REC) clip_slot.set_stopped_value(CLIP_STOP) clip_slot.set_started_value(CLIP_STARTED) clip_slot.set_recording_value(CLIP_RECORDING) def _setup_device_control(self): self._device = GuitarWingDeviceComponent(self) #, MOD_BANK_DICT, MOD_TYPES) self._device.name = 'Device_Component' self.set_device_component(self._device) self._device.set_enabled(True) def _setup_m4l_interface(self): self._m4l_interface = M4LInterfaceComponent(controls=self.controls, component_guard=self.component_guard) self.get_control_names = self._m4l_interface.get_control_names self.get_control = self._m4l_interface.get_control self.grab_control = self._m4l_interface.grab_control self.release_control = self._m4l_interface.release_control def _setup_mod(self): if isinstance(__builtins__, dict): if not 'monomodular' in __builtins__.keys() or not isinstance(__builtins__['monomodular'], ModRouter): __builtins__['monomodular'] = ModRouter() else: if not hasattr(__builtins__, 'monomodular') or not isinstance(__builtins__['monomodular'], ModRouter): setattr(__builtins__, 'monomodular', ModRouter()) self.monomodular = __builtins__['monomodular'] if not self.monomodular.has_host(): self.monomodular.set_host(self) self.monomodular.name = 'monomodular_switcher' self.modhandler = GuitarWingModHandler(script = self) self.modhandler.name = 'ModHandler' # self.log_message('mod is: ' + str(self.monomodular) + ' ' + str(__builtins__['monomodular'])) def _setup_OSC_layer(self): self._OSC_id = 0 if hasattr(__builtins__, 'control_surfaces') or (isinstance(__builtins__, dict) and 'control_surfaces' in __builtins__.keys()): for cs in __builtins__['control_surfaces']: if cs is self: break elif isinstance(cs, GuitarWing): self._OSC_id += 1 self._prefix = '/Live/GuitarWing/'+str(self._OSC_id) self._outPrt = OSC_OUTPORT if not self.oscServer is None: self.oscServer.shutdown() self.oscServer = RemixNet.OSCServer('localhost', self._outPrt, 'localhost', 10001) def _deassign_all(self): self.modhandler._fader_color_override = False self._send_midi(tuple([240, 0, 1, 97, 12, 50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 247])) self._send_midi(tuple([191, 122, 64])) #turn local OFF for CapFaders #for index in range(8): # self._send_midi(tuple([191, index+10, 125])) #self._send_midi(tuple([191, 18, 105])) self._current_nav_buttons = [] with self.component_guard(): self.release_controlled_track() self._step_sequencer.set_loop_selector_matrix(None) self._step_sequencer.set_quantization_buttons(None) self._step_sequencer.set_follow_button(None) self._step_sequencer.set_button_matrix(None) self._step_sequencer.set_drum_matrix(None) self._step_sequencer.set_drum_bank_up_button(None) self._step_sequencer.set_drum_bank_down_button(None) self._step_sequencer.set_mute_button(None) self._step_sequencer.set_solo_button(None) self._step_sequencer.set_playhead(None) self._on_note_matrix_pressed.subject = None self._note_sequencer.set_loop_selector_matrix(None) self._note_sequencer.set_quantization_buttons(None) self._note_sequencer.set_follow_button(None) self._note_sequencer.set_button_matrix(None) self._note_sequencer.set_playhead(None) self._drumgroup.set_drum_matrix(None) self.modhandler._assign_keys(None) self.modhandler._assign_base_grid(None) self.modhandler._assign_base_grid_CC(None) self.modhandler.set_shift_button(None) self.modhandler.set_device_component(None) self._transport.set_overdub_button(None) self._recorder.set_new_button(None) self._recorder.set_record_button(None) self._recorder.set_length_button(None) self._recorder.set_length_buttons(None) self._offset_component.deassign_all() self._vertical_offset_component.deassign_all() self._scale_offset_component.deassign_all() self._device_navigator.deassign_all() self._device.deassign_all() self._mixer.deassign_all() self._selected_session.deassign_all() self._session.deassign_all() self.set_highlighting_session_component(self._session) self._session._do_show_highlight() self._user_mode_selector.set_enabled(False) self._midi_mode_selector.set_enabled(False) self._split_mode_selector.set_enabled(False) self._sequencer_mode_selector.set_enabled(False) for pad in self._touchpad: pad.set_on_off_values(127, 0) pad.release_parameter() pad.use_default_message() pad.reset(True) pad.set_enabled(True) pad._descriptor = '_' for pad in self._pad: pad.display_press = False pad.set_on_off_values(127, 0) pad.release_parameter() pad.use_default_message() pad.reset(True) pad.set_enabled(True) pad._descriptor = '_' pad.set_force_next_value() for pad in self._pad_CC: pad.release_parameter() pad.use_default_message() pad.set_enabled(True) for button in self._button[4:8]: button.set_on_off_values(127, 0) button.release_parameter() button.use_default_message() button.reset(True) button.set_enabled(True) button._descriptor = '_' for fader in self._fader[0:8]: fader.release_parameter() fader.use_default_message() fader.send_value(0, True) fader.set_enabled(True) for runner in self._runner: runner.release_parameter() runner.reset(True) #fader.force_next_send() #self.request_rebuild_midi_map() def _notify_descriptors(self): if OSC_TRANSMIT: for pad in self._pad: self.oscServer.sendOSC(self._prefix+'/'+pad.name+'/lcd_name/', str(self.generate_strip_string(pad._descriptor))) for touchpad in self._touchpad: self.oscServer.sendOSC(self._prefix+'/'+touchpad.name+'/lcd_name/', str(self.generate_strip_string(touchpad._descriptor))) for button in self._button: self.oscServer.sendOSC(self._prefix+'/'+button.name+'/lcd_name/', str(self.generate_strip_string(button._descriptor))) def _set_device_attribute(self, device, attribute, value, force = False): if not device is None and hasattr(device, 'name'): name = device.name.split(' ') for index in range(len(name)): if len(str(name[index])) and str(name[index][0])=='@': vals = name[index][1:].split(':') if vals[0] == attribute: #vals[1] = value name[index] = str('@'+str(attribute)+':'+str(value)) device.name = ' '.join(name) def _top_device(self): selected_device = self._device._device if not selected_device is None and hasattr(selected_device, 'canonical_parent'): while not isinstance(selected_device.canonical_parent, Live.Track.Track): selected_device = selected_device.canonical_parent return selected_device def _detect_instrument_type(self, track): scale = DEFAULT_AUTO_SCALE #for device in self._get_devices(track): if self._assign_mod(): scale = 'Mod' else: for device in track.devices: if isinstance(device, Live.Device.Device): #self.log_message('device: ' + str(device.class_name)) if device.class_name == 'DrumGroupDevice': scale = 'DrumPad' self._step_sequencer.set_drum_group_device(device) break return scale def _get_devices(self, track): def dig(container_device): contained_devices = [] if container_device.can_have_chains: for chain in container_device.chains: for chain_device in chain.devices: for item in dig(chain_device): contained_devices.append(item) else: contained_devices.append(container_device) return contained_devices devices = [] for device in track.devices: for item in dig(device): devices.append(item) #self.log_message('appending ' + str(item)) return devices @subject_slot('value') def _on_duplicate_button_value(self, value): #self.log_message('duplicate button value: ' + str(value)) track = self._mixer.selected_strip()._track #track_index = [t for t in self._mixer.tracks_to_use()].index(self._mixer.selected_strip()._track) #self._session.selected_scene.clip_slot(track_index)._do_duplicate_clipslot() if not value is 0 and not track is None: try: track.duplicate_clip_slot([s for s in self.song().scenes].index(self.song().view.selected_scene)) #self._session.selected_scene.clip_slot(track_index)._do_duplicate_clipslot() except: self.log_message('couldnt duplicate') self.log_message('because: ' + str([s for s in self.song().scenes].index(self.song().view.selected_scene))) @subject_slot('value') def _on_new_button_value(self, value): #self.log_message('new button value: ' +str(value)) song = self.song() view = song.view try: selected_track = view.selected_track selected_scene_index = list(song.scenes).index(view.selected_scene) selected_track.stop_all_clips(False) self._jump_to_next_slot(selected_track, selected_scene_index) except: self.log_message('couldnt create new') #self._view_selected_clip_detail() def _jump_to_next_slot(self, track, start_index): song = self.song() new_scene_index = self._next_empty_slot(track, start_index) song.view.selected_scene = song.scenes[new_scene_index] def _next_empty_slot(self, track, scene_index): song = self.song() scene_count = len(song.scenes) while track.clip_slots[scene_index].has_clip: scene_index += 1 if scene_index == scene_count: song.create_scene(scene_count) return scene_index """called on timer""" def update_display(self): super(GuitarWing, self).update_display() self._timer = (self._timer + 1) % 256 self.flash() def flash(self): if(self.flash_status > 0): for control in self.controls: if isinstance(control, MonoButtonElement): control.flash(self._timer) """m4l bridge""" def _on_device_name_changed(self): name = self._device.device_name_data_source().display_string() self._monobridge._send('Device_Name', 'lcd_name', str(self.generate_strip_string('Device'))) self._monobridge._send('Device_Name', 'lcd_value', str(self.generate_strip_string(name))) self.touched() if OSC_TRANSMIT: self.oscServer.sendOSC(self._prefix+'/glob/device/', str(self.generate_strip_string(name))) def _on_device_bank_changed(self): name = 'No Bank' if is_device(self._device._device): name, _ = self._device._current_bank_details() self._monobridge._send('Device_Bank', 'lcd_name', str(self.generate_strip_string('Bank'))) self._monobridge._send('Device_Bank', 'lcd_value', str(self.generate_strip_string(name))) self.touched() def _on_device_chain_changed(self): name = " " if is_device(self._device._device) and self._device._device.canonical_parent and isinstance(self._device._device.canonical_parent, Live.Chain.Chain): name = self._device._device.canonical_parent.name self._monobridge._send('Device_Chain', 'lcd_name', str(self.generate_strip_string('Chain'))) self._monobridge._send('Device_Chain', 'lcd_value', str(self.generate_strip_string(name))) self.touched() def generate_strip_string(self, display_string): NUM_CHARS_PER_DISPLAY_STRIP = 12 if (not display_string): return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) else: display_string = str(display_string) if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center((NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' ret = ret.replace(' ', '_') assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return ret def notification_to_bridge(self, name, value, sender): #self.log_message('monobridge:' + str(name) + str(value)) if isinstance(sender, MonoEncoderElement): if OSC_TRANSMIT: self.oscServer.sendOSC(self._prefix+'/'+sender.name+'/lcd_name/', str(self.generate_strip_string(name))) self.oscServer.sendOSC(self._prefix+'/'+sender.name+'/lcd_value/', str(self.generate_strip_string(value))) self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value))) else: self._monobridge._send(name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(name, 'lcd_value', str(self.generate_strip_string(value))) if OSC_TRANSMIT: self.oscServer.sendOSC(self._prefix+'/'+name+'/lcd_name/', str(self.generate_strip_string(name))) self.oscServer.sendOSC(self._prefix+'/'+name+'/lcd_value/', str(self.generate_strip_string(value))) def touched(self): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched +=1 def check_touch(self): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) """general functionality""" def disconnect(self): if not self.oscServer is None: self.oscServer.shutdown() self.oscServer = None self.log_message("--------------= GuitarWing log closed =--------------") super(GuitarWing, self).disconnect() """some cheap overrides""" """def set_highlighting_session_component(self, session_component): self._highlighting_session_component = session_component self._highlighting_session_component.set_highlighting_callback(self._set_session_highlight)""" def handle_sysex(self, midi_bytes): #self.log_message('sysex: ' + str(midi_bytes)) if len(midi_bytes) > 14: if midi_bytes[:6] == tuple([240, 0, 1, 97, 12, 64]): self._register_pad_pressed(midi_bytes[6:14]) elif midi_bytes[3:10] == tuple([6, 2, 0, 1, 97, 1, 0]): if not self._connected: self._connected = True self._initialize_hardware() def _on_selected_track_changed(self): super(GuitarWing, self)._on_selected_track_changed() track = self._mixer.selected_strip()._track track_list = [] for t in self._mixer.tracks_to_use(): track_list.append(t) if self._last_selected_track and self._last_selected_track.can_be_armed and not self._last_selected_track_arm: self.schedule_message(1, self._disarm_track, self._last_selected_track) self.schedule_message(1, self._arm_current_track, track) if track.can_be_armed: self._last_selected_track_arm = track.arm self._last_selected_track = track def _arm_current_track(self, track): track.arm = 1 def _disarm_track(self, track): track.arm = 0 # a