def _panic_bypass(): # send all notes off (CC #123) and sustain off (CC #64) to all output # ports and on all channels for p in _engine.out_ports(): for c in range(16): _engine.output_event(_event.CtrlEvent(p, _util.offset(c), 123, 0)) _engine.output_event(_event.CtrlEvent(p, _util.offset(c), 64, 0))
def _panic_bypass(): # send all notes off (CC #123) and sustain off (CC #64) to all output # ports and on all channels for p in _engine.out_ports(): for c in range(16): _engine.output_event( _event.CtrlEvent(p, _util.offset(c), 123, 0)) _engine.output_event( _event.CtrlEvent(p, _util.offset(c), 64, 0))
def Output(port=None, channel=None, program=None, volume=None, pan=None, expression=None, ctrls={}): """ Output(port=None, channel=None, program=None, volume=None, pan=None, expression=None, ctrls={}) Route incoming events to the specified *port* and *channel*. When switching to the scene containing this unit, a program change and/or arbitrary control changes can be sent. To send a bank select (CC #0 and CC #32) before the program change, *program* can be a tuple with two elements, where the first element is the bank number, and the second is the program number. Values for the commonly used controllers *volume* (#7), *pan* (#10) and *expression* (#11) can be specified directly. For all other controllers, the *ctrls* argument can contain a mapping from controller numbers to their respective values. If *port* or *channel* are ``None``, events will be routed to the first port/channel. """ if port is None: port = _util.offset(0) if channel is None: channel = _util.offset(0) if isinstance(program, tuple): bank, program = program else: bank = None init = [] if bank is not None: init.append(Ctrl(port, channel, 0, bank // 128)) init.append(Ctrl(port, channel, 32, bank % 128)) if program is not None: init.append(Program(port, channel, program)) if volume is not None: init.append(Ctrl(port, channel, 7, volume)) if pan is not None: init.append(Ctrl(port, channel, 10, pan)) if expression is not None: init.append(Ctrl(port, channel, 11, expression)) for k, v in ctrls.items(): init.append(Ctrl(port, channel, k, v)) return Fork([Init(init), Port(port) >> Channel(channel)])
def Output(port=None, channel=None, program=None, volume=None, pan=None, expression=None, ctrls={}): """ Output(port=None, channel=None, program=None, volume=None, pan=None, expression=None, ctrls={}) Route incoming events to the specified *port* and *channel*. When switching to the scene containing this unit, a program change and/or arbitrary control changes can be sent. To send a bank select (CC #0 and CC #32) before the program change, *program* can be a tuple with two elements, where the first element is the bank number, and the second is the program number. Values for the commonly used controllers *volume* (#7), *pan* (#10) and *expression* (#11) can be specified directly. For all other controllers, the *ctrls* argument can contain a mapping from controller numbers to their respective values. If *port* or *channel* are ``None``, events will be routed to the first port/channel. """ if port is None: port = _util.offset(0) if channel is None: channel = _util.offset(0) if isinstance(program, tuple): bank, program = program else: bank = None init = [] if bank is not None: init.append(Ctrl(port, channel, 0, bank // 128)) init.append(Ctrl(port, channel, 32, bank % 128)) if program is not None: init.append(Program(port, channel, program)) if volume is not None: init.append(Ctrl(port, channel, 7, volume)) if pan is not None: init.append(Ctrl(port, channel, 10, pan)) if expression is not None: init.append(Ctrl(port, channel, 11, expression)) for k, v in ctrls.items(): init.append(Ctrl(port, channel, k, v)) return Fork([ Init(init), Port(port) >> Channel(channel) ])
def next_subscene_cb(self, path, args): s = _engine.scenes()[_engine.current_scene()] n = _util.actual(_engine.current_subscene()) + 1 if len(s[1]) and len(args) and args[0]: n %= len(s[1]) if n < len(s[1]): _engine.switch_subscene(_util.offset(n))
def Panic(bypass=True): """ Generate all-notes-off (CC #123) and sustain off (CC #64) events on all channels. :param bypass: If true, events will be sent directly on all output ports, instead of originating from the :func:`Panic()` unit and being subject to further processing. """ if bypass: return _m.Call(lambda ev: _panic_bypass()) else: return _m.Fork([(_m.Ctrl(p, _util.offset(c), 123, 0) // _m.Ctrl(p, _util.offset(c), 64, 0)) for p in _engine.out_ports() for c in range(16)])
def scene_switch_callback(self, scene, subscene): # scene and subscene parameters are the actual numbers without offset! if scene == -1: # no scene specified, use current scene = _mididings.Engine.current_scene(self) if subscene == -1: # no subscene specified, use first subscene = 0 # save actual subscene index subscene_index = subscene # add data offset to scene/subscene numbers scene = _util.offset(scene) subscene = _util.offset(subscene) found = (scene in self._scenes and (not subscene_index or subscene_index < len(self._scenes[scene][1]))) # get string representation of scene/subscene number if (subscene_index or (scene in self._scenes and len(self._scenes[scene][1]))): number = "%d.%d" % (scene, subscene) else: number = str(scene) if not _setup.get_config('silent'): if found: # get scene/subscene name scene_data = self._scenes[scene] if scene_data[1]: name = "%s - %s" % (scene_data[0], scene_data[1][subscene_index]) else: name = scene_data[0] scene_desc = (("%s: %s" % (number, name)) if name else str(number)) print("switching to scene %s" % scene_desc) else: print("no such scene: %s" % number) if found: self._call_hooks('on_switch_scene', scene, subscene)
def Panic(bypass=True): """ Generate all-notes-off (CC #123) and sustain off (CC #64) events on all channels. :param bypass: If true, events will be sent directly on all output ports, instead of originating from the :func:`Panic()` unit and being subject to further processing. """ if bypass: return _m.Call(lambda ev: _panic_bypass()) else: return _m.Fork([ (_m.Ctrl(p, _util.offset(c), 123, 0) // _m.Ctrl(p, _util.offset(c), 64, 0)) for p in _engine.out_ports() for c in range(16) ])
def run(patch): if (isinstance(patch, dict) and all(not isinstance(k, _constants._EventType) for k in patch.keys())): # bypass the overload mechanism (just this once...) if there's no way # the given dict could be accepted as a split run(scenes=patch) else: e = Engine() e.setup({_util.offset(0): patch}, None, None, None) e.run()
def process_file(infile, outfile, patch): """ Process a MIDI file, using pysmf. """ import smf # create dummy engine with no inputs or outputs _setup._config_impl(backend='dummy') engine = Engine() engine.setup({_util.offset(0): patch}, None, None, None) # open input file smf_in = smf.SMF(infile) # create SMF object with same ppqn and number of tracks as input file smf_out = smf.SMF() smf_out.ppqn = smf_in.ppqn for n in range(len(smf_in.tracks)): smf_out.add_track() for smf_ev in smf_in.events: if smf_ev.midi_buffer[0] == 0xff: # event is metadata. copy to output unmodified smf_out.add_event(smf.Event(smf_ev.midi_buffer), smf_ev.track_number, pulses=smf_ev.time_pulses) else: ev = _mididings.buffer_to_midi_event(smf_ev.midi_buffer, smf_ev.track_number, smf_ev.time_pulses) # use base class version of process_event() to bypass calling # ev._finalize(), which would fail since ev is of type # _mididings.MidiEvent. for out_ev in _mididings.Engine.process_event(engine, ev): buf, track, pulses = _mididings.midi_event_to_buffer(out_ev) smf_out.add_event(smf.Event(buf), track, pulses=pulses) smf_out.save(outfile)
def current_subscene(self): return _util.offset(_mididings.Engine.current_subscene(self))
def getter(self): self._check_type_attribute(type, name) return _util.offset(getattr(self, data))