Retrieving metadata — pyatv 0.3.4 documentation

# Retrieving metadata

It is possible to get metadata, i.e. what is playing, using two different methods:

- Manually polling
- Push updates

Polling metadata from the device works very similar to the remote control API, but one asynchronous call will return an object containing all metadata. This is to lower the amount of device calls needed. Artwork is retrieved separately.

When using push updates, new updates are pushed from the Apple TV when someting of interest happens. The exact same data that is available when polling, is passed to a callback provided by the API user. Please see the example further down for more details.

Note

Only what is currently playing is supported by the push API. Artwork must still be polled.

## What is currently playing

To retrieve what is currently playing, use the asynchronous playing method:

    playing = yield from atv.metadata.playing()

You can easily extract fields like title, album or media type. See `pyatv.interface.Playing` and `pyatv.const`.

## Artwork

To retrieve the artwork, use the asynchronous artwork method:

    artwork = yield from atv.metadata.artwork()

Remember that the artwork (which is a PNG file) is relatively large, so you should try to minimize this call. More information is available at `pyatv.interface.Metadata.artwork()`.

It is also possible to get an artwork URL instead by using `artwork_url()`. In this case, the same URL will always be returned as long as current session is valid and no check is performed if artwork is available (user of the library must handle this). An example:

    artwork = yield from atv.metadata.artwork_url()

## Device ID

A unique SHA256 identifier can be generated to separate devices from one another:

    device_id = atv.metadata.device_id

Note

This id is based on the device address solely. No domain name resolution is performed, so different identifiers will be returned for the same device depending on if an IP-address is specified or a domain name. This might change in the future.

## Hash

To simplify detection if content has changed between retrieval of what is currently playing, a unique hash can be generated. It is a SHA256 hash based on the following data:

- Title
- Artist
- Album
- Total time

These properties has been selected as they are in general unique for the same content. No guarantee is however given that the same hash is not given for different content nor the same content. It can be used as a fair guess.

    playing = yield from atv.metadata.playing()
    ...  # Some time later
    playing2 = yield from atv.metadata.playing()
    if playing2.hash != playing.hash:
        print('Content has changed')

## Push updates

The push update API is based on a regular callback interface. When playstatus information is available, a method called `playstatus_update` is called. Similarily, `playstatus_error` is called if an error occur. See the following example:

    class PushListener:

        def playstatus_update(self, updater, playstatus):
            # Currently playing in playstatus

        @staticmethod
        def playstatus_error(updater, exception):
            # Error in exception
            updater.start(initial_delay=10)

    @asyncio.coroutine
    def listen_to_updates(self);
        listener = PushListener()
        self.atv.push_updater.listener = listener
        self.atv.push_updater.start()

A few things worth noting:

- Both callback methods must be part of a “listener” (class)
- There can be only one listener
- If an error occurs, push updates are stopped

Think a bit extra about the last point. You must manually restart push updates in case an error occur. The simplest way is to do like in the example above, but make sure to provide an “initial delay” (in seconds). Otherwhise you might end up in a loop where a push connection can never be established. This might for instance happen if the device loses its IP-address.

When done, the async method `stop` must be called to not leak resources. Unless push updates were stopped because an error occurred and never restarted again.