#!/usr/bin/fades

"""Replicator of mpris.MediaPlayer2 PlayPause method calls.

To hit this service:

    dbus-send --type=method_call --dest=com.facundo.DBusReplicator \
        /com/facundo/DBusReplicator com.facundo.DBusReplicator.playpause

fades:
    dbus_next
"""

import asyncio

from dbus_next.aio import MessageBus
from dbus_next.constants import BusType
from dbus_next.errors import DBusError
from dbus_next.service import ServiceInterface, method


MEDIA_PLAYERS = ["clementine", "spotify"]


class DBusReplicator(ServiceInterface):
    """Replicator of playpause method calls."""

    objectpath = "/com/facundo/DBusReplicator"
    interface = name = "com.facundo.DBusReplicator"

    def __init__(self, bus):
        super().__init__(self.interface)
        self.bus = bus

    async def _get_player(self, name):
        """Retrieve the player from the DBus infrastructure."""
        app_name = f'org.mpris.MediaPlayer2.{name}'
        try:
            introspection = await self.bus.introspect(app_name, "/org/mpris/MediaPlayer2")
        except DBusError:
            # the app is not available through DBus
            return

        proxy = self.bus.get_proxy_object(app_name, "/org/mpris/MediaPlayer2", introspection)
        player = proxy.get_interface('org.mpris.MediaPlayer2.Player')
        return player

    @method()
    async def playpause(self):
        """Call the play/pause method on the different players."""
        for name in MEDIA_PLAYERS:
            player = await self._get_player(name)
            if player is not None:
                await player.call_play_pause()


async def main():
    loop = asyncio.get_running_loop()

    # setup the bus
    bus = await MessageBus(bus_type=BusType.SESSION).connect()

    # register the service
    replicator = DBusReplicator(bus)
    await bus.request_name(replicator.name)
    bus.export(replicator.objectpath, replicator)

    # wait forever
    await loop.create_future()

if __name__ == '__main__':
    asyncio.run(main())
