Beispiel #1
0
 async def start(self, address, port, credentials):
     """Start the proxy instance."""
     self.connection = MrpConnection(address, port, self.loop)
     protocol = MrpProtocol(
         self.connection,
         SRPAuthHandler(),
         MrpService(None, port, credentials=credentials),
     )
     await protocol.start(skip_initial_messages=True)
     self.connection.listener = self
     self._process_buffer()
Beispiel #2
0
    def __init__(self, loop, session, details, airplay):
        """Initialize a new Apple TV."""
        super().__init__()

        self._session = session
        self._mrp_service = details.usable_service()

        self._connection = MrpConnection(details.address,
                                         self._mrp_service.port, loop)
        self._srp = SRPAuthHandler()
        self._protocol = MrpProtocol(loop, self._connection, self._srp,
                                     self._mrp_service)

        self._mrp_remote = MrpRemoteControl(loop, self._protocol)
        self._mrp_metadata = MrpMetadata(self._protocol)
        self._mrp_push_updater = MrpPushUpdater(loop, self._mrp_metadata,
                                                self._protocol)
        self._mrp_pairing = MrpPairingHandler(self._protocol, self._srp,
                                              self._mrp_service)
        self._airplay = airplay
Beispiel #3
0
def setup(  # pylint: disable=too-many-locals
    loop: asyncio.AbstractEventLoop,
    config: conf.AppleTV,
    interfaces: Dict[Any, Relayer],
    device_listener: StateProducer,
    session_manager: ClientSessionManager,
) -> Optional[
    Tuple[Callable[[], Awaitable[None]], Callable[[], None], Set[FeatureName]]
]:
    """Set up a new MRP service."""
    service = config.get_service(Protocol.MRP)
    assert service is not None

    connection = MrpConnection(config.address, service.port, loop, atv=device_listener)
    protocol = MrpProtocol(connection, SRPAuthHandler(), service)
    psm = PlayerStateManager(protocol)

    remote_control = MrpRemoteControl(loop, psm, protocol)
    metadata = MrpMetadata(protocol, psm, config.identifier)
    push_updater = MrpPushUpdater(loop, metadata, psm)
    power = MrpPower(loop, protocol, remote_control)

    interfaces[RemoteControl].register(remote_control, Protocol.MRP)
    interfaces[Metadata].register(metadata, Protocol.MRP)
    interfaces[Power].register(power, Protocol.MRP)
    interfaces[PushUpdater].register(push_updater, Protocol.MRP)
    interfaces[Features].register(MrpFeatures(config, psm), Protocol.MRP)

    # Forward power events to the facade instance
    power.listener = interfaces[Power]

    async def _connect() -> None:
        await protocol.start()

    def _close() -> None:
        push_updater.stop()
        protocol.stop()

    # Features managed by this protocol
    features = set(
        [
            FeatureName.Artwork,
            FeatureName.VolumeDown,
            FeatureName.VolumeUp,
            FeatureName.App,
        ]
    )
    features.update(_FEATURES_SUPPORTED)
    features.update(_FEATURE_COMMAND_MAP.keys())
    features.update(_FIELD_FEATURES.keys())

    return _connect, _close, features
Beispiel #4
0
    def __init__(self, loop, session, config, airplay):
        """Initialize a new Apple TV."""
        super().__init__()

        self._session = session
        self._mrp_service = config.get_service(Protocol.MRP)

        self._connection = MrpConnection(config.address,
                                         self._mrp_service.port,
                                         loop,
                                         atv=self)
        self._srp = SRPAuthHandler()
        self._protocol = MrpProtocol(loop, self._connection, self._srp,
                                     self._mrp_service)
        self._psm = PlayerStateManager(self._protocol, loop)

        self._mrp_remote = MrpRemoteControl(loop, self._protocol)
        self._mrp_metadata = MrpMetadata(self._protocol, self._psm,
                                         config.identifier)
        self._mrp_push_updater = MrpPushUpdater(loop, self._mrp_metadata,
                                                self._psm)
        self._airplay = airplay
Beispiel #5
0
class MrpAppleTV(AppleTV):
    """Implementation of API support for Apple TV."""

    # This is a container class so it's OK with many attributes
    # pylint: disable=too-many-instance-attributes
    def __init__(
        self,
        loop: asyncio.AbstractEventLoop,
        session_manager: ClientSessionManager,
        config: conf.AppleTV,
        airplay: Stream,
    ) -> None:
        """Initialize a new Apple TV."""
        super().__init__()

        self._session_manager = session_manager
        self._config = config
        self._mrp_service = config.get_service(Protocol.MRP)
        assert self._mrp_service is not None

        self._connection = MrpConnection(config.address,
                                         self._mrp_service.port,
                                         loop,
                                         atv=self)
        self._srp = SRPAuthHandler()
        self._protocol = MrpProtocol(self._connection, self._srp,
                                     self._mrp_service)
        self._psm = PlayerStateManager(self._protocol, loop)

        self._mrp_remote = MrpRemoteControl(loop, self._psm, self._protocol)
        self._mrp_metadata = MrpMetadata(self._protocol, self._psm,
                                         config.identifier)
        self._mrp_power = MrpPower(loop, self._protocol, self._mrp_remote)
        self._mrp_push_updater = MrpPushUpdater(loop, self._mrp_metadata,
                                                self._psm)
        self._mrp_features = MrpFeatures(self._config, self._psm)
        self._airplay = airplay

    async def connect(self) -> None:
        """Initiate connection to device.

        No need to call it yourself, it's done automatically.
        """
        await self._protocol.start()

    def close(self) -> None:
        """Close connection and release allocated resources."""
        asyncio.ensure_future(self._session_manager.close())
        self._airplay.close()
        self.push_updater.stop()
        self._protocol.stop()

    @property
    def device_info(self) -> DeviceInfo:
        """Return API for device information."""
        return self._config.device_info

    @property
    def service(self):
        """Return service used to connect to the Apple TV."""
        return self._mrp_service

    @property
    def remote_control(self) -> RemoteControl:
        """Return API for controlling the Apple TV."""
        return self._mrp_remote

    @property
    def metadata(self) -> Metadata:
        """Return API for retrieving metadata from Apple TV."""
        return self._mrp_metadata

    @property
    def push_updater(self) -> PushUpdater:
        """Return API for handling push update from the Apple TV."""
        return self._mrp_push_updater

    @property
    def stream(self) -> Stream:
        """Return API for streaming media."""
        return self._airplay

    @property
    def power(self) -> Power:
        """Return API for streaming media."""
        return self._mrp_power

    @property
    def features(self) -> Features:
        """Return features interface."""
        return self._mrp_features
Beispiel #6
0
class MrpAppleTV(AppleTV):
    """Implementation of API support for Apple TV."""

    # This is a container class so it's OK with many attributes
    # pylint: disable=too-many-instance-attributes
    def __init__(self, loop, session, config, airplay):
        """Initialize a new Apple TV."""
        super().__init__()

        self._session = session
        self._mrp_service = config.get_service(Protocol.MRP)

        self._connection = MrpConnection(config.address,
                                         self._mrp_service.port,
                                         loop,
                                         atv=self)
        self._srp = SRPAuthHandler()
        self._protocol = MrpProtocol(loop, self._connection, self._srp,
                                     self._mrp_service)
        self._psm = PlayerStateManager(self._protocol, loop)

        self._mrp_remote = MrpRemoteControl(loop, self._protocol)
        self._mrp_metadata = MrpMetadata(self._protocol, self._psm,
                                         config.identifier)
        self._mrp_push_updater = MrpPushUpdater(loop, self._mrp_metadata,
                                                self._psm)
        self._airplay = airplay

    async def connect(self):
        """Initiate connection to device.

        No need to call it yourself, it's done automatically.
        """
        await self._protocol.start()

    async def close(self):
        """Close connection and release allocated resources."""
        if net.is_custom_session(self._session):
            await self._session.close()
        self._protocol.stop()

    @property
    def service(self):
        """Return service used to connect to the Apple TV."""
        return self._mrp_service

    @property
    def remote_control(self):
        """Return API for controlling the Apple TV."""
        return self._mrp_remote

    @property
    def metadata(self):
        """Return API for retrieving metadata from Apple TV."""
        return self._mrp_metadata

    @property
    def push_updater(self):
        """Return API for handling push update from the Apple TV."""
        return self._mrp_push_updater

    @property
    def stream(self):
        """Return API for streaming media."""
        return self._airplay
Beispiel #7
0
class MrpAppleTV(AppleTV):
    """Implementation of API support for Apple TV."""

    # This is a container class so it's OK with many attributes
    # pylint: disable=too-many-instance-attributes
    def __init__(self, loop, session, details, airplay):
        """Initialize a new Apple TV."""
        super().__init__()

        self._session = session
        self._mrp_service = details.usable_service()

        self._connection = MrpConnection(details.address,
                                         self._mrp_service.port, loop)
        self._srp = SRPAuthHandler()
        self._protocol = MrpProtocol(loop, self._connection, self._srp,
                                     self._mrp_service)

        self._mrp_remote = MrpRemoteControl(loop, self._protocol)
        self._mrp_metadata = MrpMetadata(self._protocol)
        self._mrp_push_updater = MrpPushUpdater(loop, self._mrp_metadata,
                                                self._protocol)
        self._mrp_pairing = MrpPairingHandler(self._protocol, self._srp,
                                              self._mrp_service)
        self._airplay = airplay

    async def login(self):
        """Perform an explicit login."""
        await self._protocol.start()

    async def logout(self):
        """Perform an explicit logout.

        Must be done when session is no longer needed to not leak resources.
        """
        await self._session.close()
        self._protocol.stop()

    @property
    def service(self):
        """Return service used to connect to the Apple TV.."""
        return self._mrp_service

    @property
    def pairing(self):
        """Return API for pairing with the Apple TV."""
        return self._mrp_pairing

    @property
    def remote_control(self):
        """Return API for controlling the Apple TV."""
        return self._mrp_remote

    @property
    def metadata(self):
        """Return API for retrieving metadata from Apple TV."""
        return self._mrp_metadata

    @property
    def push_updater(self):
        """Return API for handling push update from the Apple TV."""
        return self._mrp_push_updater

    @property
    def airplay(self):
        """Return API for working with AirPlay."""
        return self._airplay