示例#1
0
    async def play_url(self, url, **kwargs):
        """Play media from an URL on the device.

        Note: This method will not yield until the media has finished playing.
        The Apple TV requires the request to stay open during the entire
        play duration.
        """
        if not self.service:
            raise exceptions.NotSupportedError("AirPlay service is not available")

        server = None

        if os.path.exists(url):
            _LOGGER.debug("URL %s is a local file, setting up web server", url)
            server_address = net.get_local_address_reaching(self.config.address)
            server = StaticFileWebServer(url, server_address)
            await server.start()
            url = server.file_address

        # This creates a new ClientSession every time something is played.
        # It is not recommended by aiohttp, but it is the only way not having
        # a dangling connection laying around. So it will have to do for now.
        session = await net.create_session(self.loop)
        try:
            player = await self._player(session)
            position = int(kwargs.get("position", 0))
            self._play_task = asyncio.ensure_future(player.play_url(url, position))
            return await self._play_task
        finally:
            self._play_task = None
            await session.close()
            if server:
                await server.close()
示例#2
0
async def _start_mrp_proxy(loop, args, zconf: Zeroconf):
    def proxy_factory():
        try:
            proxy = MrpAppleTVProxy(loop, args.remote_ip, args.remote_port,
                                    args.credentials)
            asyncio.ensure_future(
                proxy.start(),
                loop=loop,
            )
        except Exception:
            _LOGGER.exception("failed to start proxy")
            raise
        else:
            return proxy

    if args.local_ip is None:
        args.local_ip = str(
            net.get_local_address_reaching(IPv4Address(args.remote_ip)))

    _LOGGER.debug("Binding to local address %s", args.local_ip)

    if not (args.remote_port or args.name):
        resp = await mdns.unicast(loop, args.remote_ip,
                                  ["_mediaremotetv._tcp.local"])

        if not args.remote_port:
            args.remote_port = resp.services[0].port
        if not args.name:
            args.name = resp.services[0].name + " Proxy"

    if not args.name:
        args.name = DEVICE_NAME

    # Setup server used to publish a fake MRP server
    server = await loop.create_server(proxy_factory, "0.0.0.0")
    port = server.sockets[0].getsockname()[1]
    _LOGGER.info("Started MRP server at port %d", port)

    unpublisher = await publish_mrp_service(zconf, args.local_ip, port,
                                            args.name)

    print("Press ENTER to quit")
    await loop.run_in_executor(None, sys.stdin.readline)

    return unpublisher
示例#3
0
async def _start_mrp_proxy(loop, args, zconf):
    def proxy_factory():
        try:
            proxy = MrpAppleTVProxy(loop)
            asyncio.ensure_future(
                proxy.start(args.remote_ip, args.remote_port,
                            args.credentials),
                loop=loop,
            )
        except Exception:
            _LOGGER.exception("failed to start proxy")
        return proxy

    if args.local_ip is None:
        args.local_ip = str(
            net.get_local_address_reaching(IPv4Address(args.remote_ip)))

    _LOGGER.debug("Binding to local address %s", args.local_ip)

    if not (args.remote_port or args.name):
        resp = await udns.request(loop, args.remote_ip,
                                  ["_mediaremotetv._tcp.local"])
        if not args.remote_port:
            args.remote_port = _get_property(resp, udns.QTYPE_SRV, "port")
        if not args.name:
            args.name = (
                _get_property(resp, udns.QTYPE_TXT, b"Name").decode("utf-8") +
                " Proxy")

    if not args.name:
        args.name = DEVICE_NAME

    # Setup server used to publish a fake MRP server
    server = await loop.create_server(proxy_factory, "0.0.0.0")
    port = server.sockets[0].getsockname()[1]
    _LOGGER.info("Started MRP server at port %d", port)

    service = await publish_mrp_service(zconf, args.local_ip, port, args.name)

    print("Press ENTER to quit")
    await loop.run_in_executor(None, sys.stdin.readline)

    return service
示例#4
0
async def request(
    loop: asyncio.AbstractEventLoop,
    address: str,
    services: List[str],
    port: int = 5353,
    timeout: int = 4,
):
    """Send request for services to a host."""
    if not net.get_local_address_reaching(IPv4Address(address)):
        raise exceptions.NonLocalSubnetError(
            f"address {address} is not in any local subnet")

    transport, protocol = await loop.create_datagram_endpoint(
        lambda: UnicastDnsSdClientProtocol(services, address, timeout),
        remote_addr=(address, port),
    )

    try:
        return await cast(UnicastDnsSdClientProtocol, protocol).get_response()
    finally:
        transport.close()
示例#5
0
    async def play_url(self, url: str, **kwargs) -> None:
        """Play media from an URL on the device.

        Note: This method will not yield until the media has finished playing.
        The Apple TV requires the request to stay open during the entire
        play duration.
        """
        if not self.service:
            raise exceptions.NotSupportedError(
                "AirPlay service is not available")

        server: Optional[StaticFileWebServer] = None

        if os.path.exists(url):
            _LOGGER.debug("URL %s is a local file, setting up web server", url)
            server_address = net.get_local_address_reaching(
                self.config.address)
            server = StaticFileWebServer(url, str(server_address))
            await server.start()
            url = server.file_address

        connection: Optional[HttpConnection] = None
        try:
            # Connect and verify connection to set up encryption
            connection = await http_connect(str(self.config.address),
                                            self.service.port)
            await verify_connection(self._credentials, connection)

            player = AirPlayPlayer(connection)
            position = int(kwargs.get("position", 0))
            self._play_task = asyncio.ensure_future(
                player.play_url(url, position))
            return await self._play_task
        finally:
            self._play_task = None
            if connection:
                connection.close()
            if server:
                await server.close()
示例#6
0
async def _start_companion_proxy(loop, args, zconf):
    def proxy_factory():
        try:
            proxy = CompanionAppleTVProxy(loop, args.remote_ip,
                                          args.remote_port, args.credentials)
            asyncio.ensure_future(
                proxy.start(),
                loop=loop,
            )
        except Exception:
            _LOGGER.exception("failed to start proxy")
            raise
        else:
            return proxy

    if args.local_ip is None:
        args.local_ip = str(
            net.get_local_address_reaching(IPv4Address(args.remote_ip)))

    _LOGGER.debug("Binding to local address %s", args.local_ip)

    if not args.remote_port:
        resp = await mdns.unicast(loop, args.remote_ip,
                                  ["_companion-link._tcp.local"])

        if not args.remote_port:
            args.remote_port = resp.services[0].port

    server = await loop.create_server(proxy_factory, "0.0.0.0")
    port = server.sockets[0].getsockname()[1]
    _LOGGER.info("Started Companion server at port %d", port)

    unpublisher = await publish_companion_service(zconf, args.local_ip, port)

    print("Press ENTER to quit")
    await loop.run_in_executor(None, sys.stdin.readline)

    return unpublisher