Skip to content

Commit

Permalink
Bump to pyatv 0.9.7
Browse files Browse the repository at this point in the history
  • Loading branch information
postlund committed Dec 6, 2021
1 parent cd2072c commit 554c9fb
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 103 deletions.
24 changes: 17 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ shipped with Home Assistant:

## Changes

## Release 2.0.0

Uplift to pyatv 0.9.7 which restores the MRP service internally of pyatv, allowing
migration of existing configuration (for people that have not used this component
before but used the official version shipped with Home Assistant) without having to
remove and add a device again.

Experimental support for audio streaming from HTTP(S) is now supported, but beware
that it is very rudimentary and likely breaks if buffering occurs. It should however
work good enough to support Text-To-Speech, which is now supported without my
previous hack.

This release also fixes a bug that some people reported when pairing the Companion
protocol (`TypeError: 0xc0`).

## Release 1.9.0 (1.9.1)

Pulled in more updates from core (just minor changes). Config entry version has
Expand Down Expand Up @@ -150,13 +165,8 @@ stop works in this case. This is a limitation in pyatv: those features are not s

## Text-To-Speech

A hack to support TTS is included here. It will likely not be included in the final
merged version of the integration, but hopefully serve as a PoC to show what is needed
to support it. The goal is to come up with a proper way of doing this.

This is built on top of "Streaming audio" above, so the same limitations apply.

**Again, please do not open issues regarding this!**
Experimental support for Text-To-Speech is included built on top of "Streaming audio"
above, so the same limitations apply.

## Debug logs

Expand Down
11 changes: 5 additions & 6 deletions custom_components/apple_tv/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from homeassistant.core import callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.typing import DiscoveryInfoType

from .const import CONF_CREDENTIALS, CONF_IDENTIFIERS, CONF_START_OFF, DOMAIN

Expand Down Expand Up @@ -147,12 +146,12 @@ async def async_step_user(self, user_input=None):
)

async def async_step_zeroconf(
self, discovery_info: DiscoveryInfoType
self, discovery_info: zeroconf.ZeroconfServiceInfo
) -> data_entry_flow.FlowResult:
"""Handle device found via zeroconf."""
service_type = discovery_info["type"][:-1] # Remove leading .
name = discovery_info["name"].replace(f".{service_type}.", "")
properties = discovery_info["properties"]
service_type = discovery_info.type[:-1] # Remove leading .
name = discovery_info.name.replace(f".{service_type}.", "")
properties = discovery_info.properties

# Extract unique identifier from service
self.scan_filter = get_unique_id(service_type, name, properties)
Expand Down Expand Up @@ -234,7 +233,7 @@ async def async_find_device(self, allow_exist=False):

# Protocols supported by the device are prospects for pairing
self.protocols_to_pair = deque(
service.protocol for service in self.atv.services
service.protocol for service in self.atv.services if service.enabled
)

dev_info = self.atv.device_info
Expand Down
4 changes: 2 additions & 2 deletions custom_components/apple_tv/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "Apple TV",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/apple_tv",
"requirements": ["pyatv==0.9.6"],
"requirements": ["pyatv==0.9.7"],
"zeroconf": [
"_mediaremotetv._tcp.local.",
"_touch-able._tcp.local.",
Expand All @@ -13,6 +13,6 @@
"_hscp._tcp.local."
],
"codeowners": ["@postlund"],
"version": "1.9.1",
"version": "2.0.0",
"iot_class": "local_push"
}
27 changes: 2 additions & 25 deletions custom_components/apple_tv/media_player.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
"""Support for Apple TV media player."""
import asyncio
import logging
from os import path

from pyatv.const import (
DeviceState,
Expand Down Expand Up @@ -231,31 +229,10 @@ def media_position_updated_at(self):

async def async_play_media(self, media_type, media_id, **kwargs):
"""Send the play_media command to the media player."""
# TODO: When streaming audio, only local files are supported (by AirPlay). So
# this is a hack to wait for the media file to be written to cache when playing
# a TTS stream. Obviously this should not be here, a proper solution is needed.
# Maybe a support flag stating if playback of local files is supported?
if "/api/tts_proxy/" in media_id:
media_id = path.join(
self.hass.config.config_dir, "tts", media_id.split("/")[-1]
)

try:

async def _wait_for_tts_file(tts_file):
_LOGGER.debug("Waiting for TTS file %s to appear", tts_file)
while not path.exists(tts_file):
await asyncio.sleep(0.5)

await asyncio.wait_for(_wait_for_tts_file(media_id), 5.0)
except asyncio.TimeoutError:
_LOGGER.error("Timed out while waiting for TTS file")
return

# If input (file) has a file format supported by pyatv, then stream it with
# RAOP. Otherwise try to play it with regular AirPlay.
if self._is_feature_available(FeatureName.StreamFile) and await is_streamable(
media_id
if self._is_feature_available(FeatureName.StreamFile) and (
await is_streamable(media_id) or media_type == MEDIA_TYPE_MUSIC
):
_LOGGER.debug("Streaming %s via RAOP", media_id)
await self.atv.stream.stream_file(media_id)
Expand Down
24 changes: 17 additions & 7 deletions info.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ shipped with Home Assistant:

## Changes

## Release 2.0.0

Uplift to pyatv 0.9.7 which restores the MRP service internally of pyatv, allowing
migration of existing configuration (for people that have not used this component
before but used the official version shipped with Home Assistant) without having to
remove and add a device again.

Experimental support for audio streaming from HTTP(S) is now supported, but beware
that it is very rudimentary and likely breaks if buffering occurs. It should however
work good enough to support Text-To-Speech, which is now supported without my
previous hack.

This release also fixes a bug that some people reported when pairing the Companion
protocol (`TypeError: 0xc0`).

## Release 1.9.0 (1.9.1)

Pulled in more updates from core (just minor changes). Config entry version has
Expand Down Expand Up @@ -150,13 +165,8 @@ stop works in this case. This is a limitation in pyatv: those features are not s

## Text-To-Speech

A hack to support TTS is included here. It will likely not be included in the final
merged version of the integration, but hopefully serve as a PoC to show what is needed
to support it. The goal is to come up with a proper way of doing this.

This is built on top of "Streaming audio" above, so the same limitations apply.

**Again, please do not open issues regarding this!**
Experimental support for Text-To-Speech is included built on top of "Streaming audio"
above, so the same limitations apply.

## Debug logs

Expand Down
2 changes: 1 addition & 1 deletion requirements-test.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pyatv==0.9.3
pyatv==0.9.7
pytest-homeassistant-custom-component==0.4.5
mypy-extensions
3 changes: 2 additions & 1 deletion tests/apple_tv/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@ def create_conf(name, address, *services):
return atv


def mrp_service():
def mrp_service(enabled=True):
"""Create example MRP service."""
return conf.ManualService(
"mrpid",
Protocol.MRP,
5555,
{},
pairing_requirement=const.PairingRequirement.Mandatory,
enabled=enabled,
)


Expand Down
28 changes: 24 additions & 4 deletions tests/apple_tv/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
@pytest.fixture(autouse=True, name="mock_scan")
def mock_scan_fixture():
"""Mock pyatv.scan."""
with patch("custom_components.apple_tv.config_flow.scan") as mock_scan:
with patch("homeassistant.components.apple_tv.config_flow.scan") as mock_scan:

async def _scan(loop, timeout=5, identifier=None, protocol=None, hosts=None):
if not mock_scan.hosts:
Expand All @@ -29,15 +29,15 @@ async def _scan(loop, timeout=5, identifier=None, protocol=None, hosts=None):
@pytest.fixture(name="dmap_pin")
def dmap_pin_fixture():
"""Mock pyatv.scan."""
with patch("custom_components.apple_tv.config_flow.randrange") as mock_pin:
with patch("homeassistant.components.apple_tv.config_flow.randrange") as mock_pin:
mock_pin.side_effect = lambda start, stop: 1111
yield mock_pin


@pytest.fixture
def pairing():
"""Mock pyatv.scan."""
with patch("custom_components.apple_tv.config_flow.pair") as mock_pair:
with patch("homeassistant.components.apple_tv.config_flow.pair") as mock_pair:

async def _pair(config, protocol, loop, session=None, **kwargs):
handler = MockPairingHandler(
Expand All @@ -54,7 +54,7 @@ async def _pair(config, protocol, loop, session=None, **kwargs):
@pytest.fixture
def pairing_mock():
"""Mock pyatv.scan."""
with patch("custom_components.apple_tv.config_flow.pair") as mock_pair:
with patch("homeassistant.components.apple_tv.config_flow.pair") as mock_pair:

async def _pair(config, protocol, loop, session=None, **kwargs):
return mock_pair
Expand Down Expand Up @@ -106,6 +106,26 @@ def mrp_device(mock_scan):
yield mock_scan


@pytest.fixture
def airplay_with_disabled_mrp(mock_scan):
"""Mock pyatv.scan."""
mock_scan.result.append(
create_conf(
"127.0.0.1",
"AirPlay Device",
mrp_service(enabled=False),
conf.ManualService(
"airplayid",
Protocol.AirPlay,
7777,
{},
pairing_requirement=PairingRequirement.Mandatory,
),
)
)
yield mock_scan


@pytest.fixture
def dmap_device(mock_scan):
"""Mock pyatv.scan."""
Expand Down
Loading

0 comments on commit 554c9fb

Please sign in to comment.