Ejemplo n.º 1
0
def test_parse_strings():
    in_data = tags.string_tag("stra", "") + tags.string_tag(
        "strb", "test string")
    parsed = parser.parse(in_data, lookup_tag)
    assert 2 == len(parsed)
    assert "" == parser.first(parsed, "stra")
    assert "test string" == parser.first(parsed, "strb")
Ejemplo n.º 2
0
def test_parse_uint_of_various_lengths():
    in_data = (tags.uint8_tag("uuu8", 12) + tags.uint16_tag("uu16", 37888) +
               tags.uint32_tag("uu32", 305419896) +
               tags.uint64_tag("uu64", 8982983289232))
    parsed = parser.parse(in_data, lookup_tag)
    assert 4 == len(parsed)
    assert 12 == parser.first(parsed, "uuu8")
    assert 37888 == parser.first(parsed, "uu16")
    assert 305419896 == parser.first(parsed, "uu32")
    assert 8982983289232 == parser.first(parsed, "uu64")
Ejemplo n.º 3
0
def test_parse_value_in_container():
    in_data = tags.container_tag(
        "cona",
        tags.uint8_tag("uuu8", 36) + tags.uint16_tag("uu16", 13000))
    parsed = parser.parse(in_data, lookup_tag)
    assert 1 == len(parsed)
    inner = parser.first(parsed, "cona")
    assert 2 == len(inner)
    assert 36 == parser.first(inner, "uuu8")
    assert 13000 == parser.first(inner, "uu16")
Ejemplo n.º 4
0
async def test_succesful_pairing(mock_pairing):
    pairing, zeroconf, service = await mock_pairing()

    url = pairing_url(zeroconf, PAIRING_CODE)
    data, _ = await utils.simple_get(url)

    await pairing.finish()

    # Verify content returned in pairingresponse
    parsed = parser.parse(data, tag_definitions.lookup_tag)
    assert parser.first(parsed, "cmpa", "cmpg") == 1
    assert parser.first(parsed, "cmpa", "cmnm") == REMOTE_NAME
    assert parser.first(parsed, "cmpa", "cmty") == "iPhone"

    assert service.credentials == PAIRING_GUID
Ejemplo n.º 5
0
    def media_type() -> MediaType:
        """Type of media is currently playing, e.g. video, music."""
        state = parser.first(playstatus, "cmst", "caps")
        if not state:
            return MediaType.Unknown

        mediakind = parser.first(playstatus, "cmst", "cmmk")
        if mediakind is not None:
            return daap.media_kind(mediakind)

        # Fallback: if artist or album exists we assume music (not present
        # for video)
        if artist() or album():
            return MediaType.Music

        return MediaType.Video
Ejemplo n.º 6
0
    async def perform_pairing(self, remote_name, expected_code, port):
        """Pair with a remote client.

        This will perform a GET-request to the specified port and hand over
        information to the client (pyatv) so that the pairing process can be
        completed.
        """
        server = f"http://127.0.0.1:{port}"
        url = f"{server}/pair?pairingcode={expected_code}&servicename=test"
        data, _ = await utils.simple_get(url)

        # Verify content returned in pairingresponse
        parsed = parser.parse(data, tag_definitions.lookup_tag)
        assert parser.first(parsed, "cmpa", "cmpg") == 1
        assert parser.first(parsed, "cmpa", "cmnm") == remote_name
        assert parser.first(parsed, "cmpa", "cmty") == "iPhone"
Ejemplo n.º 7
0
 def _is_available(self, field: tuple, expected_value=None) -> FeatureState:
     if self.apple_tv.latest_playstatus:
         value = parser.first(self.apple_tv.latest_playstatus, *field)
         if value is not None:
             if not expected_value or expected_value == value:
                 return FeatureState.Available
     return FeatureState.Unavailable
Ejemplo n.º 8
0
def test_parse_binary_plist():
    data = {"key": "value"}
    in_data = tags.raw_tag("plst", plistlib.dumps(data,
                                                  fmt=plistlib.FMT_BINARY))
    parsed = parser.parse(in_data, lookup_tag)
    assert 1 == len(parsed)
    assert data, parser.first(parsed, "plst")
Ejemplo n.º 9
0
    def shuffle() -> Optional[ShuffleState]:
        """If shuffle is enabled or not."""
        state = parser.first(playstatus, "cmst", "cash")
        if state is None or state == 0:
            return ShuffleState.Off

        # DMAP does not support the "albums" state and will always report
        # "songs" if shuffle is active
        return ShuffleState.Songs
Ejemplo n.º 10
0
async def test_pair_custom_pairing_guid(mock_pairing):
    pairing, zeroconf, service = await mock_pairing(pin_code=PIN_CODE2,
                                                    pairing_guid=PAIRING_GUID2)

    url = pairing_url(zeroconf, PAIRING_CODE2)
    data, _ = await utils.simple_get(url)

    await pairing.finish()

    # Verify content returned in pairingresponse
    parsed = parser.parse(data, tag_definitions.lookup_tag)
    assert parser.first(parsed, "cmpa", "cmpg") == int(PAIRING_GUID2, 16)

    assert service.credentials == PAIRING_GUID2
Ejemplo n.º 11
0
 def handle_set_parameter(self,
                          request: HttpRequest) -> Optional[HttpResponse]:
     """Handle incoming SET_PARAMETER request."""
     _LOGGER.debug("Received SET_PARAMETER: %s", request)
     if request.headers["Content-Type"] == "application/x-dmap-tagged":
         tags = parser.parse(request.body, lookup_tag)
         self.state.metadata.title = parser.first(tags, "mlit", "minm")
         self.state.metadata.artist = parser.first(tags, "mlit", "asar")
         self.state.metadata.album = parser.first(tags, "mlit", "asal")
     elif request.body.startswith("volume:"):
         self.state.volume = float(request.body.split(" ", maxsplit=1)[1])
         _LOGGER.debug("Changing volume to %f", self.state.volume)
     else:
         return HttpResponse(
             "RTSP",
             "1.0",
             501,
             "Not implemented",
             {"CSeq": request.headers["CSeq"]},
             b"",
         )
     return HttpResponse("RTSP", "1.0", 200, "OK",
                         {"CSeq": request.headers["CSeq"]}, b"")
Ejemplo n.º 12
0
    async def playstatus(self, use_revision=False, timeout=None):
        """Request raw data about what is currently playing.

        If use_revision=True, this command will "block" until playstatus
        changes on the device.

        Must be logged in.
        """
        cmd_url = _PSU_CMD.format(self.playstatus_revision if use_revision else 0)
        resp = await self.daap.get(cmd_url, timeout=timeout)
        self.playstatus_revision = parser.first(resp, "cmst", "cmsr")
        self.latest_playstatus = resp
        self.latest_playing = build_playing_instance(resp)
        self.latest_hash = self.latest_playing.hash
        return self.latest_playing
Ejemplo n.º 13
0
    def _convert_button(self, data):
        value = parser.first(data, "cmbe")

        # Consider navigation buttons if six commands have been received
        if self.state.buttons_press_count == 6:
            if value == "touchUp&time=6&point=20,250":
                return "up"
            elif value == "touchUp&time=6&point=20,275":
                return "down"
            elif value == "touchUp&time=7&point=50,100":
                return "left"
            elif value == "touchUp&time=7&point=75,100":
                return "right"

        return value
Ejemplo n.º 14
0
    async def login(self):
        """Login to Apple TV using specified login id."""

        # Do not use session.get_data(...) in login as that would end up in
        # an infinite loop.
        def _login_request():
            url = self._mkurl("login?[AUTH]&hasFP=1",
                              session=False,
                              login_id=True)
            _login_request.log_text = "Login request: " + url
            return self.http.get_data(
                url,
                headers=_DMAP_HEADERS,
            )

        resp = await self._do(_login_request, is_login=True)
        self._session_id = parser.first(resp, "mlog", "mlid")

        _LOGGER.info("Logged in and got session id %s", self._session_id)
        return self._session_id
Ejemplo n.º 15
0
def test_ignore_value():
    elem = tags.uint8_tag("igno", 44)
    parsed = parser.parse(elem, lookup_tag)
    assert parser.first(parsed, "igno") is None
Ejemplo n.º 16
0
def test_extract_simplified_container():
    elem = tags.uint8_tag("uuu8", 12)
    inner = tags.container_tag("conb", elem)
    in_data = tags.container_tag("cona", inner)
    parsed = parser.parse(in_data, lookup_tag)
    assert 12 == parser.first(parsed, "cona", "conb", "uuu8")
Ejemplo n.º 17
0
def test_parse_bytes():
    in_data = tags.raw_tag("byte", b"\x01\xAA\xFF\x45")
    parsed = parser.parse(in_data, lookup_tag)
    assert 1 == len(parsed)
    assert "0x01aaff45" == parser.first(parsed, "byte")
Ejemplo n.º 18
0
 def album() -> Optional[str]:
     """Album of the currently playing song."""
     return parser.first(playstatus, "cmst", "canl")
Ejemplo n.º 19
0
 def _get_time_in_seconds(tag) -> int:
     time = parser.first(playstatus, "cmst", tag)
     return daap.ms_to_s(time)
Ejemplo n.º 20
0
def test_parse_bool():
    in_data = tags.bool_tag("bola", True) + tags.bool_tag("bolb", False)
    parsed = parser.parse(in_data, lookup_tag)
    assert 2 == len(parsed)
    assert parser.first(parsed, "bola")
    assert not parser.first(parsed, "bolb")
Ejemplo n.º 21
0
 def artist() -> Optional[str]:
     """Arist of the currently playing song."""
     return parser.first(playstatus, "cmst", "cana")
Ejemplo n.º 22
0
 def genre() -> Optional[str]:
     """Genre of the currently playing song."""
     return parser.first(playstatus, "cmst", "cang")
Ejemplo n.º 23
0
 def repeat() -> Optional[RepeatState]:
     """Repeat mode."""
     state = parser.first(playstatus, "cmst", "carp")
     if state is None:
         return RepeatState.Off
     return RepeatState(state)
Ejemplo n.º 24
0
 def device_state() -> DeviceState:
     """Device state, e.g. playing or paused."""
     state = parser.first(playstatus, "cmst", "caps")
     return daap.playstate(state)
Ejemplo n.º 25
0
 def title() -> Optional[str]:
     """Title of the current media, e.g. movie or song name."""
     return parser.first(playstatus, "cmst", "cann")