예제 #1
0
    def respond(self, byteArray, meta=None):
        if not self.conn:
            return False
        self.log("Sending Response. dataType: {0}, renderId: {1}".format(
            meta.get("dataType"), meta.get("renderId")))
        obj = {"type": self.TYPE_RESPONSE, "meta": meta or {}}

        memKey = self.nextMemoryKey()
        obj["memoryKey"] = memKey
        # TODO: check that the memory segment is not used

        # store data in shared memory
        mem = QSharedMemory(memKey)
        if mem.isAttached():
            mem.detach()

        if not mem.create(len(byteArray)):
            self.log(mem.errorString())
            return False
        self.log("Shared memory created: {0}, {1} bytes".format(
            memKey, len(byteArray)))

        mem.lock()
        try:
            ctypes.memmove(int(mem.data()), byteArray, len(byteArray))
        finally:
            mem.unlock()

        self._mem[memKey] = mem

        self.conn.write(json.dumps(obj).encode("utf-8") + b"\n")
        self.conn.flush()
        return True
예제 #2
0
class MemoryCondition:
    def __init__(self, key='memory_condition_key'):
        self._shm = QSharedMemory(key)
        if not self._shm.attach():
            if not self._shm.create(1):
                raise RuntimeError('error creating shared memory: %s' %
                                   self._shm.errorString())
        self.condition = False

    def __enter__(self):
        self._shm.lock()
        if self._shm.data()[0] == b'\x00':
            self.condition = True
            self._shm.data()[0] = b'\x01'
        self._shm.unlock()
        return self.condition

    def __exit__(self, exc_type, exc_value, traceback):
        if self.condition:
            self._shm.lock()
            self._shm.data()[0] = b'\x00'
            self._shm.unlock()
예제 #3
0
class LivePlotClient(object):
    def __init__(self, timeout=2000, size=2**28):
        self.app = QCoreApplication.instance()

        if self.app is None:
            self.app = QCoreApplication([])

        self.sock = QLocalSocket()
        self.sock.connectToServer("LivePlot")

        if not self.sock.waitForConnected():
            raise EnvironmentError("Couldn't find LivePlotter instance")
        self.sock.disconnected.connect(self.disconnect_received)

        key = str(uuid.uuid4())
        self.shared_mem = QSharedMemory(key)
        if not self.shared_mem.create(size):
            raise Exception("Couldn't create shared memory %s" %
                            self.shared_mem.errorString())
        logging.debug('Memory created with key %s and size %s' %
                      (key, self.shared_mem.size()))
        self.sock.write(key.encode())
        self.sock.waitForBytesWritten()

        self.is_connected = True
        self.timeout = timeout

        atexit.register(self.close)

    def close(self):
        self.shared_mem.detach()

    def send_to_plotter(self, meta, arr=None):
        if not self.is_connected:
            return
        if meta["name"] is None:
            meta["name"] = "*"
        if arr is not None:

            arrbytes = bytearray(arr)
            arrsize = len(arrbytes)
            if arrsize > self.shared_mem.size():
                raise ValueError("Array too big %s > %s" %
                                 (arrsize, self.shared_mem.size()))
            meta['arrsize'] = arrsize
            meta['dtype'] = str(arr.dtype)
            meta['shape'] = arr.shape
        else:
            meta['arrsize'] = 0
        meta_bytes = json.dumps(meta).ljust(300)
        if len(meta_bytes) > 300:
            raise ValueError("meta object is too large (> 300 char)")

        if arr is None:
            self.sock.write(meta_bytes.encode())
        else:
            if not self.sock.bytesAvailable():
                self.sock.waitForReadyRead()
            self.sock.read(2)
            self.shared_mem.lock()
            self.sock.write(meta_bytes.encode())
            region = self.shared_mem.data()
            region[:arrsize] = arrbytes
            self.shared_mem.unlock()

    def plot_y(self, name, arr, extent=None, start_step=(0, 1), label=''):
        arr = np.array(arr)
        if extent is not None and start_step is not None:
            raise ValueError(
                'extent and start_step provide the same info and are thus mutually exclusive'
            )
        if extent is not None:
            x0, x1 = extent
            nx = len(arr)
            start_step = x0, float(x1 - x0) / nx
        meta = {
            'name': name,
            'operation': 'plot_y',
            'start_step': start_step,
            'rank': 1,
            'label': label,
        }
        self.send_to_plotter(meta, arr.astype('float64'))
        self.send_to_plotter({
            'name': 'none',
            'operation': 'none'
        }, np.array([0.]))

    def plot_z(self, name, arr, extent=None, start_step=None, xname='X axis',\
     xscale='arb. u.', yname='Y axis', yscale='arb. u.', zname='Y axis', zscale='arb. u.'):
        '''
        extent is ((initial x, final x), (initial y, final y))
        start_step is ((initial x, delta x), (initial_y, final_y))
        '''
        arr = np.array(arr)
        if extent is not None and start_step is not None:
            raise ValueError(
                'extent and start_step provide the same info and are thus mutually exclusive'
            )
        if extent is not None:
            (x0, x1), (y0, y1) = extent
            nx, ny = arr.shape
            start_step = (x0, float(x1 - x0) / nx), (y0, float(y1 - y0) / ny)
        meta = {
            'name': name,
            'operation': 'plot_z',
            'rank': 2,
            'start_step': start_step,
            'X': xscale,
            'Y': yscale,
            'Z': zscale,
            'Xname': xname,
            'Yname': yname,
            'Zname': zname,
        }
        self.send_to_plotter(meta, arr.astype('float64'))
        self.send_to_plotter({
            'name': 'none',
            'operation': 'none'
        }, np.array([0.]))

    def plot_xy(self, name, xs, ys, label='', xname='X axis', xscale='arb. u.',\
     yname='Y axis', yscale='arb. u.', scatter='False', timeaxis='False'):
        arr = np.array([xs, ys])
        meta = {
            'name': name,
            'operation': 'plot_xy',
            'rank': 1,
            'label': label,
            'X': xscale,
            'Y': yscale,
            'Xname': xname,
            'Yname': yname,
            'Scatter': scatter,
            'TimeAxis': timeaxis
        }
        self.send_to_plotter(meta, np.array([xs, ys]).astype('float64'))
        self.send_to_plotter({
            'name': 'none',
            'operation': 'none'
        }, np.array([0.]))

    def append_y(self, name, point, start_step=(0, 1), label='', xname='X axis',\
     xscale='arb. u.', yname='Y axis', yscale='arb. u.',scatter='False', timeaxis='False'):
        self.send_to_plotter({
            'name': name,
            'operation': 'append_y',
            'value': point,
            'start_step': start_step,
            'rank': 1,
            'label': label,
            'X': xscale,
            'Y': yscale,
            'Xname': xname,
            'Yname': yname,
            'Scatter': scatter,
            'TimeAxis': timeaxis
        })
        self.send_to_plotter({
            'name': 'none',
            'operation': 'none'
        }, np.array([0.]))

    def append_xy(self, name, x, y, label=''):
        self.send_to_plotter({
            'name': name,
            'operation': 'append_xy',
            'value': (x, y),
            'rank': 1,
            'label': label,
        })
        self.send_to_plotter({
            'name': 'none',
            'operation': 'none'
        }, np.array([0.]))

    def append_z(self, name, arr, start_step=None, xname='X axis',\
     xscale='arb. u.', yname='Y axis', yscale='arb. u.', zname='Y axis', zscale='arb. u.'):
        arr = np.array(arr)
        meta = {
            'name': name,
            'operation': 'append_z',
            'rank': 2,
            'start_step': start_step,
            'X': xscale,
            'Y': yscale,
            'Z': zscale,
            'Xname': xname,
            'Yname': yname,
            'Zname': zname,
        }
        self.send_to_plotter(meta, arr.astype('float64'))
        self.send_to_plotter({
            'name': 'none',
            'operation': 'none'
        }, np.array([0.]))

    def label(self, name, text):
        self.send_to_plotter({
            'name': name,
            'operation': 'label',
            'value': text
        })
        self.send_to_plotter({
            'name': 'none',
            'operation': 'none'
        }, np.array([0.]))

    def clear(self, name=None):
        self.send_to_plotter({'name': name, 'operation': 'clear'})

    def hide(self, name=None):
        self.send_to_plotter({'name': name, 'operation': 'close'})

    def remove(self, name=None):
        self.send_to_plotter({'name': name, 'operation': 'remove'})
        self.send_to_plotter({
            'name': 'none',
            'operation': 'none'
        }, np.array([0.]))

    def disconnect_received(self):
        self.is_connected = False
        warnings.warn(
            'Disconnected from LivePlotter server, plotting has been disabled')
예제 #4
0
    def receiveMessage(self):
        stream = QTextStream(self.conn)
        if stream.atEnd():
            return
        data = stream.readAll()

        for json_str in data.split("\n")[:-1]:
            obj = json.loads(json_str)
            msgType = obj["type"]
            if msgType == self.TYPE_NOTIFICATION:
                self.log("Notification Received. code: {0}".format(
                    obj["params"].get("code")))
                if obj["params"].get("code") == self.N_DATA_RECEIVED:
                    memKey = obj["params"]["memoryKey"]
                    mem = self._mem[memKey]
                    if mem.isAttached():
                        mem.detach()
                        self.log(
                            "Shared memory detached: key={0}".format(memKey))
                    del self._mem[memKey]
                else:
                    self.notified.emit(obj["params"])

            elif msgType == self.TYPE_REQUEST:
                self.log(
                    "Request Received. dataType: {0}, renderId: {1}".format(
                        obj["params"].get("dataType"),
                        obj["params"].get("renderId")))
                self.requestReceived.emit(obj["params"])

            elif msgType == self.TYPE_RESPONSE:
                self.log(
                    "Response Received. dataType: {0}, renderId: {1}".format(
                        obj["meta"].get("dataType"),
                        obj["meta"].get("renderId")))
                mem = QSharedMemory(obj["memoryKey"])
                if not mem.attach(QSharedMemory.ReadOnly):
                    self.log(
                        "Cannot attach this process to the shared memory segment: {0}"
                        .format(mem.errorString()))
                    return

                size = mem.size()
                self.log("Size of memory segment is {0} bytes.".format(size))

                mem.lock()
                ba = QByteArray()
                buffer = QBuffer(ba)
                buffer.setData(mem.constData())
                mem.unlock()
                mem.detach()

                data = ba.data()
                lines = data.split(b"\n")
                for line in lines[:5]:
                    self.log(line[:76])
                if len(lines) > 5:
                    self.log("--Total {0} Lines Received--".format(len(lines)))

                self.notify({
                    "code": self.N_DATA_RECEIVED,
                    "memoryKey": obj["memoryKey"]
                })
                self.responseReceived.emit(data, obj["meta"])
예제 #5
0
class MusicianSuite(QApplication):
    signalReceived = pyqtSignal(object)

    def __init__(self, argv, key):
        super().__init__(argv)
        QSharedMemory(key).attach()
        self._memory = QSharedMemory(self)
        self._memory.setKey(key)
        if self._memory.attach():
            self._running = True
        else:
            self._running = False
            if not self._memory.create(1):
                raise RuntimeError(self._memory.errorString())
        self._key = key
        self._timeout = 1000
        self._server = QLocalServer(self)
        if not self.isRunning():
            self._server.newConnection.connect(self.handleMessage)
            self._server.listen(self._key)

        self._settings = QSettings("Raul Sangonzalo", "Musician Suite")

        # self._settings.setValue("currentDatabase", None)  # testing purposes
        self.initialPrompt = InitialPrompt()
        self.initialPrompt.databaseSelected.connect(self.reloadInit)

    def isRunning(self):
        return self._running

    def handleMessage(self):
        socket = self._server.nextPendingConnection()
        if socket.waitForReadyRead(self._timeout):
            self.signalReceived.emit(
                socket.readAll().data().decode('utf-8'))
            socket.disconnectFromServer()
        else:
            Qt.QDebug(socket.errorString())

    def sendNotification(self, message):
        if self.isRunning():
            socket = QLocalSocket(self)
            socket.connectToServer(self._key, QIODevice.WriteOnly)
            if not socket.waitForConnected(self._timeout):
                print(socket.errorString())
                return False
            if not isinstance(message, bytes):
                message = message.encode('utf-8')
            socket.write(message)
            if not socket.waitForBytesWritten(self._timeout):
                print(socket.errorString())
                return False
            socket.disconnectFromServer()
            return True
        return False

    def init(self):
        """True initiation of the App, if only one instance"""

        if self._settings.value("currentDatabase") == None:
            self.initialPrompt.show()

        else:  # check in case user moves the location of db
            location = self._settings.value("currentDatabase")
            print("------>", location)
            if not os.path.exists(location):
                self.initialPrompt.show()
            else:
                self.mainWindow = MusicMainWindow()

                # mac madness
                os.chdir(os.path.dirname(os.path.abspath(__file__)))
                resourcesPath = os.getcwd()
                resourcesPath = os.path.join(resourcesPath, "resources")
                if not os.path.exists(resourcesPath):
                    os.mkdir(resourcesPath)

                self.MAIN_ICON = QIcon(os.path.join(resourcesPath, "test.ico"))
                self.ICON0 = QIcon(
                    QPixmap(os.path.join(resourcesPath, "icon0.png")))
                self.ICON1 = QIcon(
                    QPixmap(os.path.join(resourcesPath, "icon1.png")))
                self.RECORD_ICON = QIcon(
                    QPixmap(os.path.join(resourcesPath, "record.png")))

                self.widget = QWidget()
                self.trayIcon = QSystemTrayIcon(self.MAIN_ICON, self.widget)
                self.trayIcon.setToolTip("Musician Suite")
                self.trayIconMenu = QMenu()

                self.songListAction = QAction(self.ICON0, "Song List")
                self.recordIdeasAction = QAction(self.ICON1, "Recorded Ideas")
                self.recordAction = QAction(self.RECORD_ICON, "Record now!")
                self.exitAction = QAction("Exit")

                self.trayIconMenu.addAction(self.songListAction)
                self.trayIconMenu.addAction(self.recordIdeasAction)
                self.trayIconMenu.addAction(self.recordAction)
                self.trayIconMenu.addAction(self.exitAction)

                self.trayIcon.setContextMenu(self.trayIconMenu)

                self.trayIcon.show()

                self.trayIcon.activated.connect(self.iconDoubleClickMain)
                self.trayIconMenu.triggered.connect(self.messagePopup)

                self.mainWindow.stackedWidget.setCurrentIndex(0)

                self.signalReceived.connect(self.showMainWindow)
                self.mainWindow.show()

    def showMainWindow(self):
        self.mainWindow.show()

    def reloadInit(self):
        print("I am in reload Init")
        self.initialPrompt.hide()
        self.init()

    def iconDoubleClickMain(self, reason):
        if reason == QSystemTrayIcon.DoubleClick:
            self.mainWindow.stackedWidget.setCurrentIndex(0)
            self.mainWindow.show()

    def messagePopup(self, action):
        """Pressing the menu and toast """
        if action == self.songListAction:
            if not self.mainWindow.isVisible():
                self.mainWindow.stackedWidget.setCurrentIndex(0)
                self.mainWindow.show()
        elif action == self.recordIdeasAction:
            if not self.mainWindow.isVisible():
                self.mainWindow.stackedWidget.setCurrentIndex(1)
                self.mainWindow.show()
        elif action == self.recordAction:
            self.startRecordingHook()
        else:
            self.exit()

    def startRecordingHook(self):
        self.mainWindow.stackedWidget.setCurrentIndex(1)
        self.mainWindow.show()
        listRows = self.mainWindow.recordIdeas.recordedIdeasListWidget.count()
        print(listRows)
        self.mainWindow.recordIdeas.recordedIdeasListWidget.setCurrentRow(
            listRows-1)
        self.mainWindow.recordIdeas.record()