def test_sysex_deserialize_reply(self): m = AlesisV25() m.buttons.button1.cc = IntValue(0x55) q = SysexMessage('reply', m) b = q.serialize() r = SysexMessage.deserialize(b) assert r.type == 'reply' assert r.model.buttons.button1.cc.as_int() == 0x55
def set_config(self, model): if self.modelClass._SLOT_CONFIG: raise RuntimeError('Model class uses config slots') model_bin = model.serialize() self._send(SysexMessage('update', model)) if self.get_config().serialize() != model_bin: raise RuntimeError('Failed to update configuration')
def get_slot_config(self, slot): if not self.modelClass._SLOT_CONFIG: raise RuntimeError('Model class does not use config slots') config = b'' for offset in range(self.modelClass.num_bytes()): self._send(SysexMessage('slot_query', self.modelClass, slot, offset)) reply = self._recv() config += bytes([reply.datum]) return self.modelClass.deserialize(config)
def test_sysex_deserialize_slot_reply(self): message = bytes([ 0xf0, 0x00, 0x00, 0x0e, 0x00, 0x3f, 0x66, 0x00, 0x03, 0x02, 0x7f, 0x55, 0xf7 ]) r = SysexMessage.deserialize(message) assert r.type == 'slot_reply' assert r.model == AlesisVI49 assert r.offset == 0x17f assert r.datum == 0x55
def set_slot_config(self, slot, model): if not self.modelClass._SLOT_CONFIG: raise RuntimeError('Model class does not use config slots') config = model.serialize() for offset in range(model.num_bytes()): self._send(SysexMessage('slot_update', model, slot, offset, config[offset])) # KLUDGE: The VI61 (and possibly other devices) don't # appear to like getting more than one update message per # USB packet... Or it might be that they don't like # having two-and-a-bit, with the rest in the next packet. # This should be easy to accommodate: The Linux kernel # driver provides SNDRV_RAWMIDI_IOCTL_DRAIN which waits # until all pending MIDI output has been sent, which is # exposed by libalsa as snd_rawmidi_drain(). But we're # using mido, which uses python_rtmidi, which uses RtMidi, # which DOESN'T expose this functionality. I'm sure that # there's a very good reason why not. As a workaround, # since RtMidi sends messages "immediately", we sleep for # two milliseconds after each packet, being twice the # primary USB clock, in the hopes that it is sufficient to # clear the pending queue before we add to it. time.sleep(0.002)
def test_sysex_serialize_query_v25(self): q = SysexMessage('query', AlesisV25) assert q.serialize() == bytes( [0xf0, 0x00, 0x00, 0x0e, 0x00, 0x41, 0x62, 0x00, 0x5d, 0xf7])
def test_sysex_serialize_slot_update_vi49(self): q = SysexMessage('slot_update', AlesisVI49, 17, 262, 0x45) assert q.serialize() == bytes([ 0xf0, 0x00, 0x00, 0x0e, 0x00, 0x3f, 0x64, 0x00, 0x04, 0x11, 0x02, 0x06, 0x45, 0xf7 ])
def test_sysex_serialize_slot_query_vi49_slot23_offset143(self): q = SysexMessage('slot_query', AlesisVI49, 22, 143) assert q.serialize() == bytes([ 0xf0, 0x00, 0x00, 0x0e, 0x00, 0x3f, 0x65, 0x00, 0x03, 0x16, 0x01, 0x0f, 0xf7 ])
def test_sysex_serialize_slot_query_vi49_slot1_offset0(self): q = SysexMessage('slot_query', AlesisVI49, 0, 0) assert q.serialize() == bytes([ 0xf0, 0x00, 0x00, 0x0e, 0x00, 0x3f, 0x65, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf7 ])
def get_config(self): self._send(SysexMessage('query')) return self._recv().model
def test_sysex_serialize_query_vmini(self): q = SysexMessage('query', AlesisVMini) assert q.serialize() == bytes( [0xf0, 0x00, 0x00, 0x0e, 0x00, 0x49, 0x62, 0x00, 0x38, 0xf7])
def get_config(self): with open(self.filename, 'rb') as f: return SysexMessage.deserialize(f.read()).model
def set_config(self, model): with open(self.filename, 'wb') as f: f.write(SysexMessage('update', model).serialize())
def test_sysex_serialize_query(): q = SysexMessage('query') assert q.serialize() == bytes( [0xf0, 0x00, 0x00, 0x0e, 0x00, 0x41, 0x62, 0x00, 0x5d, 0xf7])
def test_deserialize_query(): b = bytes([0xf0, 0x00, 0x00, 0x0e, 0x00, 0x41, 0x62, 0x00, 0x5d, 0xf7]) r = SysexMessage.deserialize(b) assert r.type == 'query'
def test_deserialize_query_vmini(self): b = bytes([0xf0, 0x00, 0x00, 0x0e, 0x00, 0x49, 0x62, 0x00, 0x38, 0xf7]) r = SysexMessage.deserialize(b) assert r.type == 'query'
def _recv(self): while True: r = self._port.receive() if r.type == 'sysex': break return SysexMessage.deserialize(r.bin())
def test_sysex_serialize_update_vmini(self): q = SysexMessage('update', AlesisVMini()) begin = bytes([0xf0, 0x00, 0x00, 0x0e, 0x00, 0x49, 0x61, 0x00, 0x38]) end = bytes([0xf7]) res = q.serialize() assert res[0:len(begin)] == begin and res[-len(end):] == end
def set_config(self, model): model_bin = model.serialize() self._send(SysexMessage('update', model)) if self.get_config().serialize() != model_bin: raise RuntimeError('Failed to update configuration')
def get_config(self): if self.modelClass._SLOT_CONFIG: raise RuntimeError('Model class uses config slots') self._send(SysexMessage('query', self.modelClass)) return self._recv().model