def test_parse_strings(self): in_data = tags.string_tag('stra', '') + \ tags.string_tag('strb', 'test string') parsed = dmap.parse(in_data, lookup_tag) self.assertEqual(2, len(parsed)) self.assertEqual('', dmap.first(parsed, 'stra')) self.assertEqual('test string', dmap.first(parsed, 'strb'))
def test_parse_bool(self): in_data = tags.bool_tag('bola', True) + \ tags.bool_tag('bolb', False) parsed = dmap.parse(in_data, lookup_tag) self.assertEqual(2, len(parsed)) self.assertTrue(dmap.first(parsed, 'bola')) self.assertFalse(dmap.first(parsed, 'bolb'))
def media_type(self): """Type of media is currently playing, e.g. video, music.""" state = dmap.first(self.playstatus, 'cmst', 'caps') print('midia_type state={0}'.format(state)) if not state: return const.MEDIA_TYPE_NONE mediakind = dmap.first(self.playstatus, 'cmst', 'cmmk') print('mediakind={0}'.format(mediakind)) if mediakind == const.MEDIA_TYPE_UNKNOWN: # Fallback: if artist or album exists we assume music (not present # for video) print('artist={0}, album{1}'.format(self.artist.strip("\0"), self.album.strip("\0"))) if self.artist or self.album: print('media_type=Music') return const.MEDIA_TYPE_MUSIC print('media_type=Video') return const.MEDIA_TYPE_VIDEO if mediakind is not None: return convert.media_kind(mediakind) return const.MEDIA_TYPE_UNKNOWN
def test_parse_uint_of_various_lengths(self): in_data = tags.uint8_tag('uuu8', 12) + \ tags.uint16_tag('uu16', 37888) + \ tags.uint32_tag('uu32', 305419896) parsed = dmap.parse(in_data, lookup_tag) self.assertEqual(3, len(parsed)) self.assertEqual(12, dmap.first(parsed, 'uuu8')) self.assertEqual(37888, dmap.first(parsed, 'uu16')) self.assertEqual(305419896, dmap.first(parsed, 'uu32'))
def test_parse_value_in_container(self): in_data = tags.container_tag('cona', tags.uint8_tag('uuu8', 36) + tags.uint16_tag('uu16', 13000)) parsed = dmap.parse(in_data, lookup_tag) self.assertEqual(1, len(parsed)) inner = dmap.first(parsed, 'cona') self.assertEqual(2, len(inner)) self.assertEqual(36, dmap.first(inner, 'uuu8')) self.assertEqual(13000, dmap.first(inner, 'uu16'))
def test_succesful_pairing(self): yield from self.pairing.start(self.zeroconf) url = self._pairing_url(PAIRING_CODE) data, _ = yield from utils.simple_get(url, self.loop) # Verify content returned in pairingresponse parsed = dmap.parse(data, tag_definitions.lookup_tag) self.assertEqual(dmap.first(parsed, 'cmpa', 'cmpg'), 1) self.assertEqual(dmap.first(parsed, 'cmpa', 'cmnm'), REMOTE_NAME) self.assertEqual(dmap.first(parsed, 'cmpa', 'cmty'), 'ipod')
def handle_remote_button(self, request): """Handler for remote control buttons.""" self._verify_auth_parameters(request) content = yield from request.content.read() parsed = dmap.parse(content, tag_definitions.lookup_tag) self.last_button_pressed = dmap.first(parsed, 'cmbe') return web.Response(status=200)
def media_type(self): """Type of media is currently playing, e.g. video, music.""" state = dmap.first(self.playstatus, 'cmst', 'caps') if not state: return const.MEDIA_TYPE_UNKNOWN mediakind = dmap.first(self.playstatus, 'cmst', 'cmmk') if mediakind is not None: return convert.media_kind(mediakind) # Fallback: if artist or album exists we assume music (not present # for video) if self.artist or self.album: return const.MEDIA_TYPE_MUSIC return const.MEDIA_TYPE_VIDEO
def controlpromptupdate(self): """Request session id used to control a device. Must be logged in.""" cmd_url = 'controlpromptupdate?[AUTH]&prompt-id=0' resp = yield from self.daap.post(cmd_url) self.daap.revision_number = dmap.first(resp, 'cmcp', 'miid') _LOGGER.info('Got revision id %d for controlpromptupdate', self.daap.revision_number) return resp
def perform_pairing(self, pairing_response, 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 = 'http://127.0.0.1:{}'.format(port) url = '{}/pairing?pairingcode={}&servicename=test'.format( server, pairing_response.pairing_code) data, _ = yield from utils.simple_get(url, self.loop) # Verify content returned in pairingresponse parsed = dmap.parse(data, tag_definitions.lookup_tag) self.tc.assertEqual(dmap.first(parsed, 'cmpa', 'cmpg'), 1) self.tc.assertEqual(dmap.first(parsed, 'cmpa', 'cmnm'), pairing_response.remote_name) self.tc.assertEqual(dmap.first(parsed, 'cmpa', 'cmty'), 'ipod')
def login(self): """Login to Apple TV using specified HSGID.""" # Do not use session.get_data(...) in login as that would end up in # an infinte loop. url = self._mkurl('login?[AUTH]&hasFP=1', session=False) resp = yield from self._do(self.session.get_data, url) self._session_id = dmap.first(resp, 'mlog', 'mlid') _LOGGER.info('Logged in and got session id %s', self._session_id) return self._session_id
def test_pair_custom_pairing_guid(self): self.pairing.pin_code = PIN_CODE2 self.pairing.pairing_guid = PAIRING_GUID2 yield from self.pairing.start(self.zeroconf) url = self._pairing_url(PAIRING_CODE2) data, _ = yield from utils.simple_get(url, self.loop) # Verify content returned in pairingresponse parsed = dmap.parse(data, tag_definitions.lookup_tag) self.assertEqual(dmap.first(parsed, 'cmpa', 'cmpg'), int(PAIRING_GUID2, 16))
def _convert_button(data): value = dmap.first(data, 'cmbe') 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' else: return value
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 = yield from self.daap.get(cmd_url, timeout=timeout) self.playstatus_revision = dmap.first(resp, 'cmst', 'cmsr') return resp
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 infinte loop. def _login_request(): return self.http.get_data( self._mkurl('login?[AUTH]&hasFP=1', session=False, login_id=True), headers=_DMAP_HEADERS) resp = yield from self._do(_login_request) self._session_id = dmap.first(resp, 'mlog', 'mlid') _LOGGER.info('Logged in and got session id %s', self._session_id) return self._session_id
def _get_time_in_seconds(self, tag): time = dmap.first(self.playstatus, 'cmst', tag) return convert.ms_to_s(time)
def repeat(self): """Repeat mode.""" return dmap.first(self.playstatus, 'cmst', 'carp')
def shuffle(self): """If shuffle is enabled or not.""" return bool(dmap.first(self.playstatus, 'cmst', 'cash'))
def album(self): """Album of the currently playing song.""" return dmap.first(self.playstatus, 'cmst', 'canl')
def artist(self): """Arist of the currently playing song.""" return dmap.first(self.playstatus, 'cmst', 'cana')
def play_state(self): """Play state, e.g. playing or paused.""" return dmap.first(self.playstatus, 'cmst', 'caps')
def play_state(self): """Play state, e.g. playing or paused.""" state = dmap.first(self.playstatus, 'cmst', 'caps') return convert.playstate(state)
def genre(self): """Genre of the currently playing song.""" return dmap.first(self.playstatus, 'cmst', 'cang')
def test_parse_raw_data(self): in_data = tags.raw_tag('rawa', b'\x01\x02\x03') parsed = dmap.parse(in_data, lookup_tag) self.assertEqual(1, len(parsed)) self.assertEqual(b'\x01\x02\x03', dmap.first(parsed, 'rawa'))
def test_extract_simplified_container(self): elem = tags.uint8_tag('uuu8', 12) inner = tags.container_tag('conb', elem) in_data = tags.container_tag('cona', inner) parsed = dmap.parse(in_data, lookup_tag) self.assertEqual(12, dmap.first(parsed, 'cona', 'conb', 'uuu8'))
def title(self): """Title of the current media, e.g. movie or song name.""" return dmap.first(self.playstatus, 'cmst', 'cann')
def test_ignore_value(self): elem = tags.uint8_tag('igno', 44) parsed = dmap.parse(elem, lookup_tag) self.assertEqual(dmap.first(parsed, 'igno'), None)