Ejemplo n.º 1
0
def test_get_enabled_controllers():
    # Setup
    f = mock.Mock()
    ctrl = midi_full.MidiProjectController(callback=f)
    # Get active project metadata
    testMsg = mido.Message('sysex')
    testMsg.data = [0x01, 0x30]
    # Init in-memory config
    cfg = serverconfiguration.ServerConfiguration()
    proj = cfg.getActiveProjectOrDefault()
    proj.activate()  # Needs to be activated
    proj.stopProcessing()
    # Handle message
    ctrl.handleMidiMsg(testMsg, cfg, proj)
    assert f.call_count == 1
    retMsg = f.call_args[0][0]
    # Check response message ID
    assert retMsg.data[0] == 0x01
    assert retMsg.data[1] == 0x30
    # Decode data
    dec = sysex_data.decode(retMsg.data[2:])
    metadata = json.loads(bytes(dec))
    assert metadata is not None
    assert len(metadata.keys()) == len(modulation.allController)
    for k, v in metadata.items():
        assert not v
Ejemplo n.º 2
0
def test_get_projects():
    # Setup
    f = mock.Mock()
    ctrl = midi_full.MidiProjectController(callback=f)
    # Get active project metadata
    testMsg = mido.Message('sysex')
    testMsg.data = [0x00, 0x30]
    # Init in-memory config
    cfg = serverconfiguration.ServerConfiguration()
    proj = cfg.getActiveProjectOrDefault()
    cfg.initDefaultProject()
    proj.stopProcessing()
    # Handle message
    ctrl.handleMidiMsg(testMsg, cfg, None)
    assert f.call_count == 1
    retMsg = f.call_args[0][0]
    # Check response message ID
    assert retMsg.data[0] == 0x00
    assert retMsg.data[1] == 0x30
    # Decode data
    dec = sysex_data.decode(retMsg.data[2:])
    assert dec is not None
    metadata = json.loads(bytes(dec))
    assert metadata is not None
    # TODO: Adjust check
    assert len(metadata.keys()) == 2
 def test_dec_list1_long(self):
     to_dec = [
         0x76, 0x65, 0x54, 0x43, 0x32, 0x21, 0x00, 0x7E, 0x00, 0x21, 0x32,
         0x43, 0x54, 0x65, 0x76, 0x3F
     ]
     dec = sysex_data.decode(to_dec)
     self.assertListEqual(dec, [
         0xF6, 0xE5, 0xD4, 0xC3, 0xB2, 0xA1, 0x00, 0x00, 0xA1, 0xB2, 0xC3,
         0xD4, 0xE5, 0xF6
     ])
Ejemplo n.º 4
0
def test_get_version():
    # Setup
    f = mock.Mock()
    ctrl = midi_full.MidiProjectController(callback=f)
    version._test_version = "1.0.0"
    # Get Version messsage
    testMsg = mido.Message('sysex')
    testMsg.data = [0x00, 0x00]
    # Handle message
    ctrl.handleMidiMsg(testMsg, None, None)
    retMsg = f.call_args[0][0]
    # Check response message ID
    assert retMsg.data[0] == 0x00
    assert retMsg.data[1] == 0x00
    # Decode data
    dec = sysex_data.decode(retMsg.data[2:])
    v = str(bytes(dec), encoding='utf8')
    # Check is version string
    assert len(v.split('.')) >= 3
Ejemplo n.º 5
0
def test_get_audio_rms():
    # Setup
    f = mock.Mock()
    ctrl = midi_full.MidiProjectController(callback=f)
    num_channels = 2
    chunk = [1 for _ in range(20)]
    audio.GlobalAudio.buffer = np.array(
        [chunk[i::num_channels] for i in range(num_channels)])
    print(audio.GlobalAudio.buffer)
    # Get Version messsage
    testMsg = mido.Message('sysex')
    testMsg.data = [0x02, 0x20]
    # Handle message
    ctrl.handleMidiMsg(testMsg, None, None)
    retMsg = f.call_args[0][0]
    # Check response message ID
    assert retMsg.data[0] == 0x02
    assert retMsg.data[1] == 0x20
    # Decode data
    dec = sysex_data.decode(retMsg.data[2:])
    v = json.loads(str(bytes(dec), encoding='utf8'))
    assert "0" in v
Ejemplo n.º 6
0
def test_get_active_scene_id_successful():
    # Setup
    f = mock.Mock()
    ctrl = midi_full.MidiProjectController(callback=f)
    # Init in-memory config
    cfg = serverconfiguration.ServerConfiguration()
    proj = cfg.getActiveProjectOrDefault()  # type: project.Project
    proj.stopProcessing()
    # Activate project
    testMsg = mido.Message('sysex')
    testMsg.data = [0x01, 0x00]

    # Handle message
    ctrl.handleMidiMsg(testMsg, cfg, proj)
    assert f.call_count == 1
    retMsg = f.call_args[0][0]
    # Check response message ID
    assert retMsg.data[0] == 0x01
    assert retMsg.data[1] == 0x00
    data = sysex_data.decode(retMsg.data[2:])
    data = bytes(data)
    assert data == bytes("12", encoding='utf8')
Ejemplo n.º 7
0
def test_get_server_config():
    # Setup
    f = mock.Mock()
    ctrl = midi_full.MidiProjectController(callback=f)
    # Init in-memory config
    cfg = serverconfiguration.ServerConfiguration()
    # Get active project metadata
    testMsg = mido.Message('sysex')
    testMsg.data = [0x02, 0x00]
    # Handle message
    ctrl.handleMidiMsg(testMsg, cfg, None)
    assert f.call_count == 1
    retMsg = f.call_args[0][0]
    # Check response message ID
    assert retMsg.data[0] == 0x02
    assert retMsg.data[1] == 0x00
    # Decode data
    dec = sysex_data.decode(retMsg.data[2:])
    dec = zlib.decompress(bytes(dec))
    j_dict = json.loads(dec)
    assert j_dict is not None
    print(j_dict)
    assert not j_dict["advertise_bluetooth"]
Ejemplo n.º 8
0
def test_export_project():
    # Setup
    f = mock.Mock()
    ctrl = midi_full.MidiProjectController(callback=f)
    # Init in-memory config
    cfg = serverconfiguration.ServerConfiguration()
    proj = cfg.getActiveProjectOrDefault()
    proj.stopProcessing()
    # Get active project metadata
    testMsg = mido.Message('sysex')
    testMsg.data = [0x00, 0x60] + sysex_data.encode(proj.id)
    # Handle message
    ctrl.handleMidiMsg(testMsg, cfg, proj)
    assert f.call_count == 1
    retMsg = f.call_args[0][0]
    # Check response message ID
    assert retMsg.data[0] == 0x00
    assert retMsg.data[1] == 0x60
    # Decode data
    dec = sysex_data.decode(retMsg.data[2:])
    dec = zlib.decompress(bytes(dec))
    restoredProj = jsonpickle.loads(dec)  # type project.Project
    assert restoredProj is not None
    assert restoredProj.id == proj.id
 def test_dec_list2(self):
     to_dec = [0x00, 0x21, 0x20]
     dec = sysex_data.decode(to_dec)
     self.assertListEqual(dec, [0x00, 0xA1])
 def test_dec_0x80(self):
     to_dec = [0x00, 0x40]
     dec = sysex_data.decode(to_dec)
     self.assertListEqual(dec, [0x80])
    def _handleSysex(self, data,
                     serverconfig: serverconfiguration.ServerConfiguration,
                     proj: project.Project):
        if len(data) < 2:
            logger.error("Sysex message too short")
            return

        if data[0] == 0x00 and data[1] == 0x00:
            # Version
            logger.info("MIDI-BLE REQ Version")
            if self._sendMidiCallback is not None:
                self._sendMidiCallback(self._createVersionMsg())
        elif data[0] == 0x00 and data[1] == 0x10:
            # Update
            logger.info("MIDI-BLE REQ Update")
            logger.info("Checking for update, current version is {}".format(
                version.get_version()))
            self._updatePathsAndUrls(serverconfig)
            if not self._isUpdating:
                self._isUpdating = True
                # New Downloaders will be created on request
                self.client.refresh()
                app_update = self.client.update_check('Molecole',
                                                      version.get_version())
                if app_update is not None:
                    logger.info("Update {} available".format(
                        app_update.current_version))
                    threading.Thread(target=self._updateApp,
                                     args=[app_update]).start()
                else:
                    self._isUpdating = False
                    logger.info("Update check returned no update")
                    if self._sendMidiCallback is not None:
                        self._sendMidiCallback(
                            self._createUpdateNotAvailableMsg())
            else:
                if self._sendMidiCallback is not None:
                    self._sendMidiCallback(self._createUpdateBusyMsg())
        elif data[0] == 0x00 and data[1] == 0x11:
            # Update check
            logger.info("MIDI-BLE REQ Update check")
            logger.info("Checking for update, current version is {}".format(
                version.get_version()))
            self._updatePathsAndUrls(serverconfig)

            if not self._isUpdating:
                self._isUpdating = True
                try:
                    # Move version.gz to force a reload
                    oldFile = os.path.join(self.client.data_dir,
                                           self.client.version_file)
                    if os.path.exists(oldFile):
                        shutil.move(oldFile, oldFile.replace('.gz', '.gz.bak'))

                    oldFile = os.path.join(self.client.data_dir,
                                           self.client.version_file_compat)
                    if os.path.exists(oldFile):
                        shutil.move(oldFile, oldFile.replace('.gz', '.gz.bak'))

                    self.client.refresh()
                    app_update = self.client.update_check(
                        'Molecole', version.get_version())
                    self._isUpdating = False
                    if app_update is not None:
                        logger.info("Update {} available".format(
                            app_update.version))
                        if self._sendMidiCallback is not None:
                            self._sendMidiCallback(
                                self._createUpdateVersionAvailableMsg(
                                    app_update.version))
                    else:
                        logger.info("Update check returned no update")
                        if self._sendMidiCallback is not None:
                            self._sendMidiCallback(
                                self._createUpdateNotAvailableMsg())
                except Exception as e:
                    logger.error("Error trying to update: {}".format(e))
                    self._isUpdating = False
            else:
                if self._sendMidiCallback is not None:
                    self._sendMidiCallback(self._createUpdateBusyMsg())
        elif data[0] == 0x00 and data[1] == 0x20:
            # Active project metadata
            if self._sendMidiCallback is not None:
                metadata = serverconfig.getProjectMetadata(proj.id)
                self._sendMidiCallback(self._createActiveProjectMsg(metadata))
        elif data[0] == 0x00 and data[1] == 0x30:
            # Get projects
            if self._sendMidiCallback is not None:
                metadata = serverconfig.getProjectsMetadata()
                self._sendMidiCallback(self._createProjectsMsg(metadata))
        elif data[0] == 0x00 and data[1] == 0x40:
            # Activate project
            projUid = str(bytes(sysex_data.decode(data[2:])), encoding='utf8')
            logger.info("MIDI-BLE REQ Activate project {}".format(projUid))
            proj = serverconfig.getProject(projUid)
            if proj is not None:
                if self._sendMidiCallback is not None:
                    self._sendMidiCallback(
                        self._createActivateProjSuccessfulMsg())
            else:
                if self._sendMidiCallback is not None:
                    self._sendMidiCallback(
                        self._createActivateProjNotFoundMsg())
        elif data[0] == 0x00 and data[1] == 0x50:
            # Import project
            logger.info("MIDI-BLE REQ Import project")
            dec = sysex_data.decode(data[2:])
            projGzip = zlib.decompress(bytes(dec))
            projJson = str(projGzip, encoding='utf8')
            try:
                serverconfig.importProject(projJson)
                if self._sendMidiCallback is not None:
                    self._sendMidiCallback(
                        self._createImportProjSuccessfulMsg())
            except Exception:
                if self._sendMidiCallback is not None:
                    self._sendMidiCallback(self._createImportProjErrorMsg())
        elif data[0] == 0x00 and data[1] == 0x60:
            # Export project
            byteArr = bytes(sysex_data.decode(data[2:]))
            logger.debug("Decoded {} to {}".format([hex(c) for c in data[2:]],
                                                   byteArr))
            projUid = str(byteArr, encoding='utf8')
            logger.info("MIDI-BLE REQ Export project {}".format(projUid))
            proj = serverconfig.getProject(projUid)
            if proj is not None:
                if self._sendMidiCallback is not None:
                    self._sendMidiCallback(
                        self._createExportProjSuccessfulMsg(proj))
            else:
                if self._sendMidiCallback is not None:
                    self._sendMidiCallback(self._createExportProjNotFoundMsg())
        elif data[0] == 0x00 and data[1] == 0x70:
            # Activate project
            projUid = str(bytes(sysex_data.decode(data[2:])), encoding='utf8')
            logger.info("MIDI-BLE REQ Delete project {}".format(projUid))
            proj = serverconfig.getProject(projUid)
            if proj is not None:
                serverconfig.deleteProject(projUid)
                if self._sendMidiCallback is not None:
                    self._sendMidiCallback(self._deleteProjSuccessfulMsg())
            else:
                if self._sendMidiCallback is not None:
                    self._sendMidiCallback(self._deleteProjNotFoundMsg())
        elif data[0] == 0x01 and data[1] == 0x00:
            # Get active scene ID
            logger.info("MIDI-BLE REQ Active scene index")
            sceneId = serverconfig.getActiveProjectOrDefault().activeSceneId
            if self._sendMidiCallback is not None:
                self._sendMidiCallback(
                    self._createGetActiveSceneIdMsg(sceneId))
        elif data[0] == 0x01 and data[1] == 0x10:
            # Get active scene metadata
            logger.info("MIDI-BLE REQ Get active scene metadata")
            proj = serverconfig.getActiveProjectOrDefault()
            metadata = proj.getSceneMetadata(proj.activeSceneId)
            if self._sendMidiCallback is not None:
                self._sendMidiCallback(
                    self._createActiveSceneMetadataMsg(metadata))
        elif data[0] == 0x01 and data[1] == 0x20:
            # Get scenes metadata
            logger.info("MIDI-BLE REQ Get scenes")
            proj = serverconfig.getActiveProjectOrDefault()
            metadata = proj.sceneMetadata
            if self._sendMidiCallback is not None:
                self._sendMidiCallback(self._createScenesMetadataMsg(metadata))
        elif data[0] == 0x01 and data[1] == 0x30:
            # Get enabled controllers for active scene
            logger.info("MIDI-BLE REQ Get controller enabled for active scene")
            proj = serverconfig.getActiveProjectOrDefault()
            if self._sendMidiCallback is not None:
                self._sendMidiCallback(self._createEnabledControllersMsg(proj))
        elif data[0] == 0x01 and data[1] == 0x40:
            # Request controller values for active project
            logger.info("MIDI-BLE REQ Get controller values for active scene")
            proj = serverconfig.getActiveProjectOrDefault()
            self._sendControllerStatus(proj)
        elif data[0] == 0x01 and data[1] == 0x50:
            # Reset controller values for active project
            logger.info("MIDI-BLE REQ Reset controller for active scene")
            proj = serverconfig.getActiveProjectOrDefault()
            proj.resetControllerModulation()
            self._sendControllerStatus(proj)
        elif data[0] == 0x02 and data[1] == 0x00:
            # Get server configuration
            logger.info("MIDI-BLE REQ Get server configuration")
            config = serverconfig.getFullConfiguration()
            if self._sendMidiCallback is not None:
                self._sendMidiCallback(self._createGetServerConfigMsg(config))
        elif data[0] == 0x02 and data[1] == 0x10:
            # Update server configuration
            logger.info("MIDI-BLE REQ Update server configuration")
            dec = sysex_data.decode(data[2:])
            configGzip = zlib.decompress(bytes(dec))
            configJson = str(configGzip, encoding='utf8')
            config = json.loads(configJson)
            try:
                serverconfig.setConfiguration(config)
                if self._sendMidiCallback is not None:
                    self._sendMidiCallback(
                        self._createUpdateServerConfigSuccessfulMsg())
            except Exception:
                if self._sendMidiCallback is not None:
                    self._sendMidiCallback(
                        self._createUpdateServerConfigErrorMsg())
        elif data[0] == 0x02 and data[1] == 0x20:
            logger.info("MIDI-BLE REQ Audio rms")
            rms = {"0": "NO_BUFFER"}
            if audio.GlobalAudio.buffer is not None:
                if isinstance(audio.GlobalAudio.buffer, Iterable):
                    numChannels = len(audio.GlobalAudio.buffer)

                    for i in range(numChannels):
                        rmsFromChannel = dsp.rms(audio.GlobalAudio.buffer[i])
                        rms[str(i)] = rmsFromChannel
                else:
                    logger.debug("audio.GlobalAudio.buffer not iterateable")
            if self._sendMidiCallback is not None:
                self._sendMidiCallback(self._createAudioRMSMsg(
                    json.dumps(rms)))
        else:
            logger.error("MIDI-BLE Unknown sysex {} {}".format(
                hex(data[0]), hex(data[1])))