Exemplo n.º 1
0
    async def monitor_start(self):
        """
        Start watching for device changes

        Listen for relevant add/remove events from udev and fire callbacks.
        """

        if self._monitor:
            return

        udev_monitor = Monitor.from_netlink(self._udev_context)
        udev_monitor.filter_by_tag('uchroma')
        udev_monitor.filter_by(subsystem='usb', device_type=u'usb_device')

        self._udev_observer = AsyncMonitorObserver(udev_monitor,
                                                   callback=self._udev_event,
                                                   name='uchroma-monitor')
        ensure_future(self._udev_observer.start())
        self._monitor = True

        if self._callbacks:
            for device in self._devices.values():
                ensure_future(self._fire_callbacks('add', device),
                              loop=self._loop)

        self._logger.debug('Udev monitor started')
Exemplo n.º 2
0
    def _run(self):
        dm = UChromaDeviceManager()

        atexit.register(UChromaServer.exit, self._loop)

        dbus = DeviceManagerAPI(dm, self._logger)
        power = PowerMonitor()

        for sig in (signal.SIGINT, signal.SIGTERM):
            self._loop.add_signal_handler(sig, self._shutdown_callback)

        try:
            dbus.run()
            power.start()

            ensure_future(dm.monitor_start(), loop=self._loop)

            self._loop.run_forever()

        except KeyboardInterrupt:
            pass

        finally:
            for sig in (signal.SIGTERM, signal.SIGINT):
                self._loop.remove_signal_handler(sig)

            power.stop()

            self._loop.run_until_complete(asyncio.wait( \
                    [dm.close_devices(), dm.monitor_stop()],
                    return_when=futures.ALL_COMPLETED))
Exemplo n.º 3
0
    def discover(self):
        """
        Perform HID device discovery

        Iterates over all connected HID devices with RAZER_VENDOR_ID
        and checks the product ID against the Hardware descriptor.

        Interface endpoint restrictions are currently hard-coded. In
        the future this should be done by checking the HID report
        descriptor of the endpoint, however this functionality in
        HIDAPI is broken (report_descriptor returns garbage) on
        Linux in the current release.

        Discovery is automatically performed when the object is
        constructed, so this should only need to be called if the
        list of devices changes (monitoring for changes is beyond
        the scope of this API).
        """
        devinfos = sorted(list(hidapi.enumerate(vendor_id=RAZER_VENDOR_ID)),
                          key=lambda x: x.path)

        for devinfo in devinfos:
            parent = self._get_parent(devinfo.product_id)
            if parent is None:
                continue

            if self._key_for_path(parent.sys_path) is not None:
                continue

            hardware = Hardware.get_device(devinfo.product_id)
            if hardware is None:
                continue

            if hardware.type == Hardware.Type.HEADSET:
                if devinfo.interface_number != 3:
                    continue
            elif hardware.type in (Hardware.Type.KEYBOARD,
                                   Hardware.Type.KEYPAD, Hardware.Type.LAPTOP):
                if devinfo.interface_number != 2:
                    continue
            elif hardware.type in (Hardware.Type.MOUSE,
                                   Hardware.Type.MOUSEPAD):
                if devinfo.interface_number != 1:
                    continue
            else:
                if devinfo.interface_number != 0:
                    continue

            device = self._create_device(parent, hardware, devinfo)
            if device is not None:
                self._devices[device.key] = device

                if hardware.type == Hardware.Type.KEYBOARD:
                    device.set_device_mode(0)

                if self._monitor and self._callbacks:
                    ensure_future(self._fire_callbacks('add', device),
                                  loop=self._loop)
Exemplo n.º 4
0
    def stop(self):
        if not self._running:
            return

        self._running = False

        self._task.cancel()

        self._driver.input_manager.grab(False)
        ensure_future(self._queue.detach())
Exemplo n.º 5
0
    def remove_renderer(self, zindex: int) -> bool:
        if self._loop is None:
            return False

        if zindex is None or zindex < 0 or zindex > len(self._loop.layers):
            self._logger.error("Z-index out of range (requested %d max %d)",
                               zindex, len(self._loop.layers))
            return False

        ensure_future(self._loop.remove_layer(zindex))
        return True
Exemplo n.º 6
0
    def start(self) -> bool:
        """
        Start the AnimationLoop

        Initializes the renderers, zeros the buffers, and starts the loop.

        Requires an active asyncio event loop.

        :return: True if the loop was started
        """
        if self.running:
            self._logger.error("Animation loop already running")
            return False

        if len(self.layers) == 0:
            self._logger.error("No renderers were configured")
            return False

        self._error = False
        self.running = True

        self._anim_task = ensure_future(self._animate())
        self._anim_task.add_done_callback(self._renderer_done)

        return True
Exemplo n.º 7
0
    async def _get_layers(self):
        """
        Wait for renderers to produce new layers, yields until at least one
        layer is active.
        """
        # schedule tasks to wait on each renderer queue
        for r_idx in range(0, len(self.layers)):
            layer = self.layers[r_idx]

            if layer.waiter is None or layer.waiter.done():
                layer.waiter = ensure_future(self._dequeue(r_idx))

        # async wait for at least one completion
        waiters = [layer.waiter for layer in self.layers]
        if len(waiters) == 0:
            return

        await asyncio.wait(waiters, return_when=futures.FIRST_COMPLETED)

        # check the rest without waiting
        for r_idx in range(0, len(self.layers)):
            layer = self.layers[r_idx]

            if layer.waiter is not None and not layer.waiter.done():
                self._dequeue_nowait(r_idx)
Exemplo n.º 8
0
    def _udev_event(self, device):
        self._logger.debug('Device event [%s]: %s', device.action, device)

        if device.action == 'remove':
            key = self._key_for_path(device.sys_path)
            if key is not None:
                removed = self._devices.pop(key, None)
                if removed is not None:
                    removed.close()
                    if self._callbacks:
                        ensure_future( \
                            self._fire_callbacks('remove', removed), loop=self._loop)

        else:
            if self._key_for_path(device.sys_path) is None:
                self.discover()
Exemplo n.º 9
0
    def _open_input_devices(self):
        if self._opened:
            return True

        for input_device in self._input_devices:
            try:
                event_device = evdev.InputDevice(input_device)
                self._event_devices.append(event_device)

                task = ensure_future(self._evdev_callback(event_device))
                task.add_done_callback(
                    functools.partial(self._evdev_close, event_device))
                self._tasks.append(task)

                self._logger.info('Opened event device %s', event_device)

            except Exception as err:
                self._logger.exception("Failed to open device: %s",
                                       input_device,
                                       exc_info=err)

        if len(self._event_devices) > 0:
            self._opened = True

        return self._opened
Exemplo n.º 10
0
    def stop(self, cb=None):
        if not self.running:
            return False

        task = ensure_future(self._stop())
        if cb is not None:
            task.add_done_callback(cb)
        return True
Exemplo n.º 11
0
    def InputSignalEnabled(self, state):
        if dev_mode_enabled():
            if state == self._signal_input:
                return

            if state:
                if self._input_queue is None:
                    self._input_queue = InputQueue(self._driver)
                self._input_queue.attach()
                self._input_task = ensure_future(self._dev_mode_input())
            else:
                ensure_future(self._input_queue.detach())
                self._input_task.cancel()

                self._input_queue = None

            self._signal_input = state
Exemplo n.º 12
0
    def start(self):
        if self._running:
            return

        self._uinput = UInput.from_device(driver.input_manager.input_devices[0], \
            name='UChroma Virtual Macro Device %d' % driver.device_index)
        self._queue = InputQueue(driver)

        self._queue.attach()
        self._driver.input_manager.grab(True)

        self._task = ensure_future(self._listen())
        self._running = True
Exemplo n.º 13
0
 def start(self):
     if not self.renderer.running:
         self.task = ensure_future(self.renderer._run())