def armGenerator(self, generator_name): generator_name = self.validateGenerator(generator_name) armed = getattr(self.ns, 'armed', []) if generator_name is not None and generator_name not in armed: dsp.log('arming %s...' % generator_name) armed += [generator_name] setattr(self.ns, 'armed', armed) gen = self.loadGenerator(generator_name) ctl = self.setupCtl(gen) grid_ctl = self.loadGridCtl() trigger = midi.MidiTrigger(gen.trigger['device'], gen.trigger['notes']) respawn = mp.Event() p = mp.Process(target=self._armGenerator, args=(generator_name, gen, ctl, trigger, respawn, grid_ctl)) p.start() while generator_name in armed: respawn.wait() respawn.clear() p = mp.Process(target=self._armGenerator, args=(generator_name, gen, ctl, trigger, respawn, grid_ctl)) p.start() armed = getattr(self.ns, 'armed', [])
def armGenerator(self, generator_name): generator_name = self.validateGenerator(generator_name) armed = getattr(self.ns, 'armed', []) if generator_name is not None and generator_name not in armed: dsp.log('arming %s...' % generator_name) armed += [ generator_name ] setattr(self.ns, 'armed', armed) gen = self.loadGenerator(generator_name) ctl = self.setupCtl(gen) trigger = midi.MidiTrigger(gen.trigger['device'], gen.trigger['notes']) respawn = mp.Event() p = mp.Process(target=self._armGenerator, args=(generator_name, gen, ctl, trigger, respawn)) p.start() while generator_name in armed: respawn.wait() respawn.clear() dsp.log('rearming %s...' % generator_name) p = mp.Process(target=self._armGenerator, args=(generator_name, gen, ctl, trigger, respawn)) p.start() armed = getattr(self.ns, 'armed', [])
def wait(self): try: with mido.open_input(self.device_name) as incoming: for msg in incoming: if msg.type == 'note_on' and msg.note in self.notes: return (msg.note, msg.velocity) except IOError: dsp.log('Could not arm MIDI device %s' % self.device_name) return (None, None)
def register_midi_listener(device_name, ns): # check to see if this device has a listener already # start one up if not if not hasattr(ns, '%s-listener' % device_name): try: listener = mp.Process(target=device_scribe, args=(device_name, ns)) listener.start() setattr(ns, '%s-listener' % device_name, listener.pid) except IOError: dsp.log('Could not start listener for unknown MIDI device: %s' % device_name)
def _playGenerator(self, generator_name, gen, voice_id, ctl, grid_ctl): try: os.nice(-2) except OSError: os.nice(0) if not hasattr(self.ns, 'reload'): setattr(self.ns, 'reload', False) render_process = None def render_again(gen, ctl, generator_name, voice_id, ns): snd = gen.play(ctl) setattr(ns, 'buffer-%s-%s' % (generator_name, voice_id), snd) out = self.openAudioDevice() group = None if hasattr(gen, 'groups'): group = gen.groups[ voice_id % len(gen.groups) ] ctl['group'] = group iterations = 0 while True: ctl['count'] = iterations iterations += 1 if getattr(self.ns, 'reload') == True: reload(gen) if hasattr(self.ns, 'buffer-%s-%s' % (generator_name, voice_id)): snd = getattr(self.ns, 'buffer-%s-%s' % (generator_name, voice_id)) else: # First play render snd = gen.play(ctl) if render_process is None or not render_process.is_alive(): # async start render of next buffer render_process = mp.Process(name='render-%s-%s' % (generator_name, voice_id), target=render_again, args=(gen, ctl, generator_name, voice_id, self.ns)) render_process.start() if self.ns.grid: div = grid_ctl.geti(self.divcc, low=0, high=4, default=0) div = self.divs[div] self.ticks[div].wait() out.write(snd) if getattr(self.ns, '%s-%s-loop' % (generator_name, voice_id)) == False: break try: delattr(self.ns, 'buffer-%s-%s' % (generator_name, voice_id)) except AttributeError: dsp.log('Could not remove buffer-%s-%s' % (generator_name, voice_id))
def _playPattern(self, pattern): def _sendMidi(note, velocity, length, device): velocity = int(round(velocity * 127)) note = int(note) dsp.log(device) out = mido.open_output(device) msg = mido.Message('note_on', note=note, velocity=velocity) out.send(msg) dsp.delay(length) msg = mido.Message('note_off', note=note, velocity=0) out.send(msg) def _sendOsc(): pass device = getattr(self.ns, 'selected-pattern-device', self.default_midi_device) dsp.log(device) if self.validateGenerator(device): handler = self._playOneshot elif midi.validate_output_device_by_id(device): device = midi.validate_output_device_by_id(device) # FIXME dummy dsp.log(device) handler = _sendMidi elif osc.validateAddress(device): handler = _sendOsc else: # Fallback to internal generator handler = self._playOneshot device = 'default' setattr(self.ns, 'pattern-%s' % pattern.id, True) setattr(self.ns, 'pattern-play-%s' % pattern.id, True) grid_ctl = self.loadGridCtl() while getattr(self.ns, 'pattern-%s' % pattern.id): # wait for tick if self.ns.grid: div = getattr(self.ns, 'pattern-div-%s' % pattern.id) div = self.divs[div] self.ticks[div].wait() # freq, 0-1, frames note, velocity, length = pattern.next() note = tune.ftom(note) if velocity > 0 and getattr(self.ns, 'pattern-play-%s' % pattern.id): n = mp.Process(target=handler, args=(note, velocity, length, device)) n.start()
def log_listener(): try: device_names = mido.get_input_names() devices = [ mido.open_input(device_name) for device_name in device_names ] devices = mido.ports.MultiPort(devices) for msg in devices: if hasattr(ns, 'midi_log_active'): dsp.log(msg) else: continue except IOError: dsp.log('Could not open MIDI devices for logging %s' % str(device_names))
def _sendMidi(note, velocity, length, device): velocity = int(round(velocity * 127)) note = int(note) dsp.log(device) out = mido.open_output(device) msg = mido.Message('note_on', note=note, velocity=velocity) out.send(msg) dsp.delay(length) msg = mido.Message('note_off', note=note, velocity=0) out.send(msg)
def stopGenerator(self, generator_name, kill=False): if generator_name in self.looping: for voice_id, process in self.looping[generator_name].iteritems(): setattr(self.ns, '%s-%s-loop' % (generator_name, voice_id), False) if kill: process.terminate() del self.looping[generator_name] return True dsp.log('Could not stop %s generators: none currently playing' % generator_name) return False
def wait(self): try: with mido.open_input(self.device_name) as incoming: for msg in incoming: if self.notes is not None: if msg.type == 'note_on' and msg.note in self.notes: return (msg.note, msg.velocity) if self.cc is not None: if msg.type == 'control_change' and msg.control in self.cc and msg.value > 0: return (msg.control, msg.value) except IOError: dsp.log('Could not arm MIDI device %s' % self.device_name) return (None, None)
def play(self, generator, ns, voice_id, voice_index, loop=True): sys.path.insert(0, os.getcwd()) gen = __import__(generator) midi_devices = {} if hasattr(gen, 'midi'): for device, device_id in gen.midi.iteritems(): dsp.log('\ndevice: %s device_id: %s' % (device, device_id)) try: midi_devices[device] = MidiManager(device_id, ns) dsp.log('setting midi manager %s' % device_id) except: dsp.log('Could not load midi device %s with id %s' % (device, device_id)) param_manager = ParamManager(ns) if audio_engine == 'alsa': out = self.open_alsa_pcm(ns.device) elif audio_engine == 'portaudio': out = self.open_pyaudio_pcm(ns.device) else: print 'Playback is disabled.' return False try: os.nice(-2) except OSError: os.nice(0) group = None if hasattr(gen, 'groups'): group = gen.groups[ voice_index % len(gen.groups) ] meta = { 'midi': midi_devices, 'param': param_manager, 'id': voice_id, 'group': group } if not hasattr(ns, 'reload'): setattr(ns, 'reload', False) while getattr(ns, '%s-%s-loop' % (generator, voice_id)) == True: if getattr(ns, 'reload') == True: reload(gen) snd = gen.play(meta) snd = dsp.split(snd, 500) for s in snd: try: out.write(s) except AttributeError: dsp.log('Could not write to audio device') return False return True
def device_scribe(device_name, ns): try: with mido.open_input(device_name) as incoming: for msg in incoming: msg_id = None value = None if hasattr(msg, 'control'): msg_id = msg.control value = msg.value if hasattr(msg, 'note'): msg_id = msg.note value = msg.velocity setattr(ns, '%s-%s-%s' % (device_name, msg.type, msg_id), value) delattr(ns, '%s-listener' % device_name) except IOError: dsp.log('Could not open MIDI device %s' % device_name)
def findGenerators(self): generators = [] try: gens = glob.glob("*.py") for filename in gens: # Get base filename and strip .py extension filename = os.path.basename(filename)[:-3] generators += [ filename ] if len(generators) > 0: return generators dsp.log('Discovered %s available generator scripts' % len(generators)) except OSError: pass dsp.log('No generators found') return False
def findGenerators(self): generators = [] try: gens = glob.glob("*.py") for filename in gens: # Get base filename and strip .py extension filename = os.path.basename(filename)[:-3] generators += [filename] if len(generators) > 0: return generators dsp.log('Discovered %s available generator scripts' % len(generators)) except OSError: pass dsp.log('No generators found') return generators
def play(self, generator, ns, voice_id, voice_index, loop=True): sys.path.insert(0, os.getcwd()) gen = __import__(generator) midi_devices = {} if hasattr(gen, 'midi'): for device, device_id in gen.midi.iteritems(): dsp.log('\ndevice: %s device_id: %s' % (device, device_id)) try: pygame.midi.init() device_info = pygame.midi.get_device_info(device_id) device_type = 'input' if device_info[2] else 'output' pygame.midi.quit() except: dsp.log('could not read device %s' % device_id) device_type = 'output' try: mappings = None if hasattr(gen, 'mappings'): if device in gen.mappings: mappings = gen.mappings[device] midi_devices[device] = MidiManager(device_id, ns, device_type, mappings) dsp.log('setting midi manager %s' % device_id) except: dsp.log('Could not load midi device %s with id %s' % (device, device_id)) param_manager = ParamManager(ns) if audio_engine == 'alsa': out = self.open_alsa_pcm(ns.device) elif audio_engine == 'portaudio': out = self.open_pyaudio_pcm(ns.device) else: print 'Playback is disabled.' return False try: os.nice(-2) except OSError: os.nice(0) group = None if hasattr(gen, 'groups'): group = gen.groups[voice_index % len(gen.groups)] if hasattr(gen, 'sbank'): sbank = {} for snd in gen.sbank: sbank[snd[0]] = dsp.read(snd[1]).data else: sbank = None meta = { 'midi': midi_devices, 'param': param_manager, 'id': voice_id, 'group': group, 'sbank': sbank } if not hasattr(ns, 'reload'): setattr(ns, 'reload', False) render_process = None def render_again(gen, meta, voice_id, ns): snd = gen.play(meta) setattr(ns, 'buffer-%s' % voice_id, snd) iterations = 0 while getattr(ns, '%s-%s-loop' % (generator, voice_id)) == True: meta['iterations'] = iterations iterations += 1 dsp.log('playing %s, id %s, iter %s' % (generator, voice_id, iterations)) if getattr(ns, 'reload') == True and not hasattr(gen, 'automate'): reload(gen) # automate will always override play if hasattr(gen, 'play') and not hasattr(gen, 'automate'): if hasattr(ns, 'buffer-%s' % voice_id): snd = getattr(ns, 'buffer-%s' % voice_id) else: # First play render snd = gen.play(meta) if render_process is None or not render_process.is_alive(): # async start render of next buffer render_process = mp.Process(name='render-%s' % voice_id, target=render_again, args=(gen, meta, voice_id, ns)) render_process.start() snd = dsp.split(snd, 500) # if grid is on, wait for a tick to start playback if ns.grid: self.tick.wait() for s in snd: try: out.write(s) except AttributeError: dsp.log('Could not write to audio device') return False if hasattr(gen, 'automate'): gen.automate(meta) if hasattr(gen, 'loop_time'): time.sleep(gen.loop_time) delattr(ns, 'buffer-%s' % voice_id) return True
def _playGenerator(self, generator_name, gen, voice_id, ctl, grid_ctl): try: os.nice(-2) except OSError: os.nice(0) if not hasattr(self.ns, 'reload'): setattr(self.ns, 'reload', False) render_process = None def render_again(gen, ctl, generator_name, voice_id, ns): snd = gen.play(ctl) setattr(ns, 'buffer-%s-%s' % (generator_name, voice_id), snd) out = self.openAudioDevice() group = None if hasattr(gen, 'groups'): group = gen.groups[voice_id % len(gen.groups)] ctl['group'] = group iterations = 0 while True: ctl['count'] = iterations iterations += 1 if getattr(self.ns, 'reload') == True: reload(gen) if hasattr(self.ns, 'buffer-%s-%s' % (generator_name, voice_id)): snd = getattr(self.ns, 'buffer-%s-%s' % (generator_name, voice_id)) else: # First play render snd = gen.play(ctl) if render_process is None or not render_process.is_alive(): # async start render of next buffer render_process = mp.Process( name='render-%s-%s' % (generator_name, voice_id), target=render_again, args=(gen, ctl, generator_name, voice_id, self.ns)) render_process.start() if self.ns.grid: div = grid_ctl.geti(self.divcc, low=0, high=4, default=0) div = self.divs[div] self.ticks[div].wait() out.write(snd) if getattr(self.ns, '%s-%s-loop' % (generator_name, voice_id)) == False: break try: delattr(self.ns, 'buffer-%s-%s' % (generator_name, voice_id)) except AttributeError: dsp.log('Could not remove buffer-%s-%s' % (generator_name, voice_id))
def play(self, generator, ns, voice_id, voice_index, loop=True): sys.path.insert(0, os.getcwd()) gen = __import__(generator) midi_devices = {} if hasattr(gen, 'midi'): for device, device_id in gen.midi.iteritems(): dsp.log('\ndevice: %s device_id: %s' % (device, device_id)) try: pygame.midi.init() device_info = pygame.midi.get_device_info(device_id) device_type = 'input' if device_info[2] else 'output' pygame.midi.quit() except: dsp.log('could not read device %s' % device_id) device_type = 'output' try: mappings = None if hasattr(gen, 'mappings'): if device in gen.mappings: mappings = gen.mappings[device] midi_devices[device] = MidiManager(device_id, ns, device_type, mappings) dsp.log('setting midi manager %s' % device_id) except: dsp.log('Could not load midi device %s with id %s' % (device, device_id)) param_manager = ParamManager(ns) if audio_engine == 'alsa': out = self.open_alsa_pcm(ns.device) elif audio_engine == 'portaudio': out = self.open_pyaudio_pcm(ns.device) else: print 'Playback is disabled.' return False try: os.nice(-2) except OSError: os.nice(0) group = None if hasattr(gen, 'groups'): group = gen.groups[ voice_index % len(gen.groups) ] if hasattr(gen, 'sbank'): sbank = {} for snd in gen.sbank: sbank[snd[0]] = dsp.read(snd[1]).data else: sbank = None meta = { 'midi': midi_devices, 'param': param_manager, 'id': voice_id, 'group': group, 'sbank': sbank } if not hasattr(ns, 'reload'): setattr(ns, 'reload', False) render_process = None def render_again(gen, meta, voice_id, ns): snd = gen.play(meta) setattr(ns, 'buffer-%s' % voice_id, snd) iterations = 0 while getattr(ns, '%s-%s-loop' % (generator, voice_id)) == True: meta['iterations'] = iterations iterations += 1 dsp.log('playing %s, id %s, iter %s' % (generator, voice_id, iterations)) if getattr(ns, 'reload') == True and not hasattr(gen, 'automate'): reload(gen) # automate will always override play if hasattr(gen, 'play') and not hasattr(gen, 'automate'): if hasattr(ns, 'buffer-%s' % voice_id): snd = getattr(ns, 'buffer-%s' % voice_id) else: # First play render snd = gen.play(meta) if render_process is None or not render_process.is_alive(): # async start render of next buffer render_process = mp.Process(name='render-%s' % voice_id, target=render_again, args=(gen, meta, voice_id, ns)) render_process.start() snd = dsp.split(snd, 500) # if grid is on, wait for a tick to start playback if ns.grid: self.tick.wait() for s in snd: try: out.write(s) except AttributeError: dsp.log('Could not write to audio device') return False if hasattr(gen, 'automate'): gen.automate(meta) if hasattr(gen, 'loop_time'): time.sleep(gen.loop_time) delattr(ns, 'buffer-%s' % voice_id) return True