class SingleBusManager(BusManager): def __init__(self, spotify: Spotify, bus: Bus = None, app_name: str = "spotpris"): super().__init__(spotify, app_name) self.registration = None if bus is None: self.bus = SessionBus() # Use built in method to get bus singleton self.bus.request_name(f"org.mpris.MediaPlayer2.{app_name}") else: self.bus = bus self.player = None def _register(self, player): self.player = player self.registration = self.bus.register_object("/org/mpris/MediaPlayer2", player, None) def main_loop(self): current_playback = self.spotify.current_playback() if current_playback is None: if self.registration is not None: self.registration.unregister() self.registration = None else: if self.registration is None: if self.player is None: self._register(MediaPlayer2(self.spotify, current_playback)) self.player.event_loop(current_playback)
class KbDaemon: def __init__(self): # Logging self.logger = logging.getLogger('daemon') self.logger.setLevel(logging.DEBUG) sh = logging.StreamHandler() sh.setLevel(logging.DEBUG) self.logger.addHandler(sh) # DBus self.bus = SessionBus() def start(self): try: self.bus.request_name('com.qtech.openkeyboard') self.bus.register_object('/com/qtech/openkeyboard', DaemonInterface(), None) except RuntimeError: self.logger.exception('Failed to connect to DBus') exit() # List keyboards kb_info = self.find_keyboard() print(kb_info) if kb_info is not None: self.logger.info(f'Connecting to keyboard at {kb_info["path"]}') rd = RedDragon(Device(path=kb_info['path'])) self.bus.register_object( f'/com/qtech/openkeyboard/{kb_info["manufacturer_string"]}', KeyboardInterface(rd), None) else: self.logger.info(f'Creating fake keyboard') fake = FakeKeyboard() self.bus.register_object('/com/qtech/openkeyboard/fake', KeyboardInterface(fake), None) # Start main loop GLib.MainLoop().run() def find_keyboard(self): devices = enumerate(VID, PID) for device in devices: print(device) if device['interface_number'] == 1: return device return None
def main(): parser = argparse.ArgumentParser( description="Control Spotify Connect devices using MPRIS2") parser.add_argument('-d', '--devices', nargs='+', metavar="DEVICE", help="Only create interfaces for the listed devices") parser.add_argument('-i', '--ignore', nargs='+', metavar="DEVICE", help="Ignore the listed devices") parser.add_argument('-a', '--auto', action="store_true", help="Automatically control the active device") parser.add_argument('-l', '--list', nargs='?', choices=["name", "id"], const="name", help="List available devices and exit") parser.add_argument( '-s', '--steal-bus', action="store_true", help="Steal the dbus bus name from spotify to prevent " "it from also offering an MPRIS2 interface. If --auto is used use the spotify bus name as own " "bus name (experimental)") args = parser.parse_args() MediaPlayer2.dbus = [ pkg_resources.resource_string(__name__, f"mpris/{iface}.xml").decode('utf-8') for iface in ifaces ] loop = GLib.MainLoop() oauth = authenticate() sp = Spotify(oauth_manager=oauth) if args.list: devices = sp.devices() for devices in devices["devices"]: print(devices[args.list]) return exclusive_count = 0 for arg in [args.devices, args.ignore, args.auto]: if arg: exclusive_count += 1 if exclusive_count >= 2: parser.error( "Only one of --devices, --ignore and --auto can be used at the same time" ) return if args.steal_bus: bus = SessionBus() try: # This sets the bus name for the SessionBus singleton which is also used by SingleBusManager bus.request_name("org.mpris.MediaPlayer2.spotify", allow_replacement=False, replace=True) except RuntimeError: print( "Failed to steal spotify bus name. You need to start spotPRIS2 before spotify" ) exit(1) if not args.auto: manager = MultiBusManager(sp, args.devices, args.ignore) else: if args.steal_bus: manager = SingleBusManager(sp, bus=bus) else: manager = SingleBusManager(sp) def timeout_handler(): try: manager.main_loop() except Exception as e: print(e) finally: return True GLib.timeout_add_seconds(1, timeout_handler) try: loop.run() except KeyboardInterrupt: pass
class TestFakeMethods(): def __init__(self, bluetoothAudioBridge): self.TestResult = 0 self.bluetoothAudioBridge = bluetoothAudioBridge self.bluetoothAudioBridge.DbusBluezBusName = "BluetoothAudioBridge.FakeDbusObject" self.bluetoothAudioBridge.DbusBluezObjectPath = "/BluetoothAudioBridge/FakeDbusObject/hci0" self.bluetoothAudioBridge.PollingCycle = 1 self.fakeDbusDevices = [] self.fakeDbusAdapter = None self.fakeDbusAdapterRegistration = None self.fakeDbusObjectManager = None self.fakeDbusObjectManagerRegistration = None self.bus = None self.bluetoothAudioBridge.DbusBluezOnSystemBus = False self.busName = None def callerWithOneParameterWasCalled(self): def methodCall(parameter): print("parameter " + parameter) #print(self.TestResult) self.TestResult = self.TestResult + 1 return methodCall def callerWithOneParameterWasCalledAsync(self): async def methodCall(parameter): print("parameter " + parameter) self.TestResult = self.TestResult + 1 return methodCall async def unexportAllDevices(self): if self.fakeDbusObjectManager: for name, obj in self.fakeDbusDevices: self.fakeDbusObjectManager.unexport(name) self.fakeDbusDevices = [] #if self.fakeDbusDevice: # self.fakeDbusDevice.unregister() #if self.fakeDbusObjectManager: # self.fakeDbusObjectManager.unregister() async def unexportDevice(self, path): self.fakeDbusObjectManager.unexport(path) self.fakeDbusDevices.remove(path) async def startTestFakeDbusBluez(self): if not self.bus: self.bus = SessionBus() await self.unexportAllDevices() if self.busName: busName.unown() if self.fakeDbusAdapterRegistration: self.fakeDbusAdapterRegistration.unregister() self.fakeDbusAdapterRegistration = None if self.fakeDbusObjectManagerRegistration: self.fakeDbusObjectManagerRegistration.unregister() self.fakeDbusObjectManagerRegistration = None await asyncio.sleep(0.5) prefix = "/" + self.bluetoothAudioBridge.DbusBluezBusName.replace( ".", "/") self.fakeDbusObjectManager = TestFakeObjectManager(self.bus) self.fakeDbusAdapter = TestFakeDbusBluezAdapter(self) self.fakeDbusObjectManagerRegistration = self.bus.register_object( "/", self.fakeDbusObjectManager, None) self.fakeDbusAdapterRegistration = self.fakeDbusObjectManager.export( prefix + "/hci0", self.fakeDbusAdapter) self.busName = self.bus.request_name( self.bluetoothAudioBridge.DbusBluezBusName) async def exportNewDevice(self, name): prefix = "/" + self.bluetoothAudioBridge.DbusBluezBusName.replace( ".", "/") self.fakeDbusDevice = TestFakeDbusBluezDevice(self) result = (prefix + "/hci0/dev_" + name, self.fakeDbusDevice) self.fakeDbusObjectManager.export(result[0], result[1]) self.fakeDbusDevices.append(result) return result async def stopTestFakeDbusBluez(self): await self.unexportAllDevices() if (self.fakeDbusObjectManagerRegistration): self.fakeDbusObjectManagerRegistration.unregister() if (self.fakeDbusAdapterRegistration): self.fakeDbusAdapterRegistration.unregister() if self.busName: self.busName.unown() self.busName = None self.fakeDbusDevices = [] self.fakeDbusObject = None self.fakeDbusObjectManager = None self.fakeDbusObjectManagerRegistration = None self.fakeDbusAdapter = None self.fakeDbusAdapterRegistration = None self.bus = None await asyncio.sleep(0.5) async def cancelIn2Seconds(self): await asyncio.sleep(2) self.bluetoothAudioBridge.CancellationToken.set_result(True) async def setResultInXSecondsCancelable(self, time): (finished, result) = await self.bluetoothAudioBridge.awaitOrStop( asyncio.sleep(time)) if finished: print("set Result to true") self.TestResult = 1