def set_device_parameter_value(self, device_name, parameter_name, value, raise_if_not_exists=False): # type: (str, str, Any) -> None device = find_if(lambda d: d.name.lower() == device_name.lower(), self.song.current_track.all_devices) if not device: if not raise_if_not_exists: return raise Protocol0Error("Couldn't find device %s in track devices" % device_name) param = find_if(lambda d: d.name.lower() == parameter_name.lower(), device.parameters) if not param: if not raise_if_not_exists: return raise Protocol0Error("Couldn't find parameter %s in device %s" % (parameter_name, device_name)) if param.is_enabled: seq = Sequence().add(wait=1) seq.add(lambda: setattr(param, "value", value)) return seq.done()
def create_automation_envelope(self, parameter): # type: (Clip, DeviceParameter) -> Live.Clip.AutomationEnvelope if parameter is None: raise Protocol0Error( "You passed None to Clip.create_automation_envelope") return self._clip.create_automation_envelope( parameter._device_parameter)
def _get_presets_path(self): # type: () -> str if not self.selected_category: raise Protocol0Error( "the track name does not correspond with a sample directory") return join(SAMPLE_PATH, self.selected_category)
def set_object_attr(obj, attr, value): if not hasattr(obj, attr): raise Protocol0Error("object %s has not specified attr : %s" % (obj, attr)) previous_value = getattr(obj, attr) setattr(obj, attr, value) yield setattr(obj, attr, previous_value)
def _connect(self, clip): # type: (AutomationAudioClip) -> None if not clip: raise Protocol0Error("Inconsistent clip state for %s (%s)" % (self, self.track)) self.automated_audio_clip = clip self._playing_status_listener.subject = self.automated_audio_clip._clip return clip._connect(self)
def next_track(self, increment=1, base_track=None): # type: (int, SimpleTrack) -> SimpleTrack base_track = base_track or self.selected_track if base_track is None: raise Protocol0Error( "You called next_track before selected_track computation") return self.simple_tracks[(base_track.index + increment) % len(self.simple_tracks)]
def _get_simple_track(self, track, default=None): # type: (Any, Optional[SimpleTrack]) -> Optional[SimpleTrack] """ default is useful when the _ableton_track_to_simple_track is not built yet """ if not track: return None if isinstance(track, AbstractTrack): raise Protocol0Error( "Expected Live track, got AbstractTrack instead") if track == self.song._song.master_track or track in self.song._song.return_tracks: return default if track not in self._live_track_to_simple_track.keys(): if default: return default raise Protocol0Error("_get_simple_track mismatch on %s" % track.name) return self._live_track_to_simple_track[track]
def __init__(self, object, message="a sequence error occurred"): # type: (Union[Sequence, SequenceStep], str) -> None from a_protocol_0.sequence.Sequence import Sequence from a_protocol_0.sequence.SequenceStep import SequenceStep if not isinstance(object, Sequence) and not isinstance(object, SequenceStep): raise Protocol0Error("You didn't pass an appropriate object parameter to SequenceError") object._errored = True super(RuntimeError, self).__init__("%s, (%s)" % (str(message), object))
def _added_track_init(self): """ this can be called once, when the Live track is created """ if self.group_track is None: raise Protocol0Error( "An automation track should always be grouped") seq = Sequence() seq.add(wait=1) seq.add(lambda: [self.delete_device(d) for d in self.devices]) if len(self.clips) == 0: seq.add(self._create_base_clips) return seq.done()
def _wait(self, ticks_count, callback): # type: (int, callable) -> None if not callable(callback): raise Protocol0Error("callback must be callable") if ticks_count == 0: callback() else: if Protocol0.LIVE_ENVIRONMENT_LOADED: self.schedule_message(ticks_count, callback) else: # emulate schedule_message threading.Timer(float(Fraction(ticks_count, 10)), callback).start()
def selected_parameter(self): # type: () -> DeviceParameter param = find_if( lambda p: p._device_parameter == self.song._view. selected_parameter, [ param for track in self.simple_tracks for param in track.device_parameters ]) if not param: raise Protocol0Error("There is no currently selected parameter") return param
def _find_parent_rack(self, device): # type: (Device) -> Optional[RackDevice] if device in device.track.devices: return None for rack_device in [ d for d in device.track.devices if isinstance(d, RackDevice) ]: if device in rack_device.chains[0].devices: return rack_device raise Protocol0Error( "The device %s is too be too nested to be detected" % device.name)
def __init__(self, audio_track, midi_track, *a, **k): # type: (AutomationAudioTrack, AutomationMidiTrack) -> None super(AutomationTracksCouple, self).__init__(*a, **k) if audio_track.index != midi_track.index - 1: raise Protocol0Error( "Inconsistent automation track state, midi should always be right adjacent to audio" ) self.audio_track = audio_track self.midi_track = midi_track self._connect.subject = self.midi_track self.parent.defer(self._connect)
def _after_timeout(self): if self.timed_out: raise Protocol0Error( "Tried to execute timeout function twice: %s" % self) if self.executed: return self.timed_out = True if self.on_timeout: self.on_timeout() return else: self.parent.log_error("Timeout reached for %s" % self)
def _make_automated_track(self, group_track, wrapped_track=None): # type: (SimpleGroupTrack, AbstractTrack) -> Optional[AutomatedTrack] automation_audio_tracks = [track for track in group_track.sub_tracks if isinstance(track, AutomationAudioTrack)] automation_midi_tracks = [track for track in group_track.sub_tracks if isinstance(track, AutomationMidiTrack)] if len(automation_audio_tracks) == 0 and len(automation_midi_tracks) == 0: return None main_tracks = [t for t in group_track.sub_tracks if t not in automation_audio_tracks + automation_midi_tracks] if wrapped_track is None: if len(main_tracks) != 1: raise Protocol0Error("an AutomatedTrack should wrap one and only one main track (or one composite track)") wrapped_track = main_tracks[0] if wrapped_track != group_track.sub_tracks[-1]: raise Protocol0Error("The main track of a AutomatedTrack track should always be the last of the group") if len(automation_audio_tracks) != len(automation_midi_tracks): return None # inconsistent state, happens on creation or when tracks are deleted # at this point we should have a consistent state with audio - midi * n and main track at this end # any other state is a bug and raises in AutomationTracksCouple __init__ automation_tracks_couples = [AutomationTracksCouple(audio_track, midi_track) for audio_track, midi_track in itertools.izip(automation_audio_tracks, automation_midi_tracks)] return AutomatedTrack(group_track=group_track, automation_tracks_couples=automation_tracks_couples, wrapped_track=wrapped_track)
def _added_track_init(self): if self.group_track is None: raise Protocol0Error( "An automation track should always be grouped") self.has_monitor_in = True seq = Sequence() seq.add(self.clear_devices) seq.add( partial(self.parent.browserManager.load_rack_device, self.base_name.split(":")[1])) seq.add(partial(self.set_input_routing_type, None)) seq.add(self._get_automated_device_and_parameter) return seq.done()
def value_to_name(value): # type: (int) -> str if value not in LogLevel._values_dict: raise Protocol0Error( "You gave an inexistent value for class LogLevel") return LogLevel._values_dict[value]
def _connect(self, clip_slot): # type: (AutomationAudioClipSlot) -> None if not clip_slot: raise Protocol0Error("Inconsistent clip_slot state for %s (%s)" % (self, self.track)) self.automated_audio_clip_slot = clip_slot clip_slot._connect(self)
def remove_callback(self, callback): # type: (callable) -> None if callback not in self._callbacks: raise Protocol0Error( "Tried to remove a nonexistent callback from %s" % self) self._callbacks.remove(callback)