Skip to content

Commit

Permalink
Restore Text to Speech from Media page
Browse files Browse the repository at this point in the history
  • Loading branch information
roleoroleo committed Nov 9, 2022
1 parent 8e5550f commit a2a7907
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 46 deletions.
2 changes: 1 addition & 1 deletion custom_components/yi_hack/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"codeowners": ["@roleoroleo"],
"iot_class": "local_push",
"config_flow": true,
"version": "0.4.1"
"version": "0.4.2"
}
68 changes: 41 additions & 27 deletions custom_components/yi_hack/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,20 @@

import requests
from requests.auth import HTTPBasicAuth
from typing import Any

from homeassistant.components import media_source
from homeassistant.components.media_player import (
DEVICE_CLASS_SPEAKER,
MediaPlayerEntity
BrowseMedia,
MediaType,
MediaPlayerDeviceClass,
MediaPlayerEnqueue,
MediaPlayerEntity,
MediaPlayerEntityFeature
)
from homeassistant.components.media_player.browse_media import (
async_process_play_media_url
)
from homeassistant.components.media_player.const import (
MEDIA_TYPE_MUSIC,
SUPPORT_PLAY_MEDIA,
SUPPORT_TURN_OFF,
SUPPORT_TURN_ON
)
from homeassistant.const import (
CONF_HOST,
CONF_MAC,
Expand Down Expand Up @@ -53,12 +52,6 @@
MSTAR
)

SUPPORT_YIHACK_MEDIA = (
SUPPORT_PLAY_MEDIA
| SUPPORT_TURN_OFF
| SUPPORT_TURN_ON
)

_LOGGER = logging.getLogger(__name__)

async def async_setup_entry(hass, config_entry, async_add_entities):
Expand All @@ -70,6 +63,14 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class YiHackMediaPlayer(MediaPlayerEntity):
"""Define an implementation of a Yi Camera media player."""

_attr_device_class = MediaPlayerDeviceClass.SPEAKER
_attr_supported_features = (
MediaPlayerEntityFeature.BROWSE_MEDIA
| MediaPlayerEntityFeature.PLAY_MEDIA
| MediaPlayerEntityFeature.TURN_OFF
| MediaPlayerEntityFeature.TURN_ON
)

def __init__(self, config):
"""Initialize the device."""
self._device_name = config.data[CONF_NAME]
Expand Down Expand Up @@ -141,15 +142,10 @@ def is_volume_muted(self):
"""Boolean if volume is currently muted."""
return False

@property
def supported_features(self):
"""Flag media player features that are supported."""
return SUPPORT_YIHACK_MEDIA

@property
def device_class(self):
"""Set the device class to SPEAKER."""
return DEVICE_CLASS_SPEAKER
# @property
# def device_class(self):
# """Set the device class to SPEAKER."""
# return MediaPlayerDeviceClass.SPEAKER

def turn_off(self):
"""Turn off camera (set privacy on)."""
Expand Down Expand Up @@ -181,7 +177,13 @@ def turn_on(self):
self._state = True
self.schedule_update_ha_state(force_refresh=True)

async def async_play_media(self, media_type, media_id, **kwargs):
async def async_play_media(
self,
media_type: str,
media_id: str,
enqueue: MediaPlayerEnqueue | None = None,
announce: bool | None = None, **kwargs: Any
) -> None:
"""Send the play_media command to the media player."""

def _perform_speaker(data):
Expand Down Expand Up @@ -218,15 +220,15 @@ def _perform_cmd(p_cmd):
return subprocess.run(p_cmd, check=False, shell=False, stdout=subprocess.PIPE).stdout

if media_source.is_media_source_id(media_id):
media_type = MEDIA_TYPE_MUSIC
media_type = MediaType.MUSIC
play_item = await media_source.async_resolve_media(self.hass, media_id)
media_id = async_process_play_media_url(self.hass, play_item.url)

if media_type != MEDIA_TYPE_MUSIC:
if media_type != MediaType.MUSIC:
_LOGGER.error(
"Invalid media type %s. Only %s is supported",
media_type,
MEDIA_TYPE_MUSIC,
MediaType.MUSIC,
)
return

Expand All @@ -241,3 +243,15 @@ def _perform_cmd(p_cmd):
await self.hass.async_add_executor_job(_perform_speaker, data)
else:
_LOGGER.error("Failed to send data to speaker %s, no data available", self._host)

async def async_browse_media(
self,
media_content_type: str | None = None,
media_content_id: str | None = None
) -> BrowseMedia:
"""Implement the websocket media browsing helper."""
return await media_source.async_browse_media(
self.hass,
media_content_id,
content_filter=lambda item: item.media_content_type.startswith("audio/"),
)
34 changes: 16 additions & 18 deletions custom_components/yi_hack/media_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,23 @@
from requests.auth import HTTPBasicAuth

from homeassistant.components.media_player.const import (
MEDIA_CLASS_APP,
MEDIA_CLASS_DIRECTORY,
MEDIA_CLASS_VIDEO,
MEDIA_TYPE_VIDEO,
MediaClass,
MediaType
)
from homeassistant.components.media_player.errors import BrowseError
from homeassistant.components.media_source.error import MediaSourceError, Unresolvable
from homeassistant.components.media_source.models import (
BrowseMediaSource,
MediaSource,
MediaSourceItem,
PlayMedia,
PlayMedia
)
from homeassistant.const import (
CONF_HOST,
CONF_NAME,
CONF_PASSWORD,
CONF_PORT,
CONF_USERNAME,
CONF_USERNAME
)
from homeassistant.core import HomeAssistant, callback

Expand Down Expand Up @@ -93,12 +91,12 @@ def _browse_media(self, entry_id:str, event_dir:str) -> BrowseMediaSource:
response = None

if entry_id is None:
media_class = MEDIA_CLASS_DIRECTORY
media_class = MediaClass.DIRECTORY
media = BrowseMediaSource(
domain=DOMAIN,
identifier="root",
media_class=media_class,
media_content_type=MEDIA_TYPE_VIDEO,
media_content_type=MediaType.VIDEO,
title=DOMAIN,
can_play=False,
can_expand=True,
Expand All @@ -111,12 +109,12 @@ def _browse_media(self, entry_id:str, event_dir:str) -> BrowseMediaSource:
if config_entry.data[CONF_NAME] == device.name:
title = device.name_by_user if device.name_by_user is not None else device.name

media_class = MEDIA_CLASS_APP
media_class = MediaClass.APP
child_dev = BrowseMediaSource(
domain=DOMAIN,
identifier=config_entry.data[CONF_NAME],
media_class=media_class,
media_content_type=MEDIA_TYPE_VIDEO,
media_content_type=MediaType.VIDEO,
title=title,
can_play=False,
can_expand=True,
Expand All @@ -134,12 +132,12 @@ def _browse_media(self, entry_id:str, event_dir:str) -> BrowseMediaSource:
if host == "":
return None

media_class = MEDIA_CLASS_DIRECTORY
media_class = MediaClass.DIRECTORY
media = BrowseMediaSource(
domain=DOMAIN,
identifier=entry_id,
media_class=media_class,
media_content_type=MEDIA_TYPE_VIDEO,
media_content_type=MediaType.VIDEO,
title=entry_id,
can_play=False,
can_expand=True,
Expand Down Expand Up @@ -172,13 +170,13 @@ def _browse_media(self, entry_id:str, event_dir:str) -> BrowseMediaSource:
for record_dir in records_dir:
dir_path = record_dir["dirname"].replace("/", "-")
title = record_dir["datetime"].replace("Date: ", "").replace("Time: ", "")
media_class = MEDIA_CLASS_DIRECTORY
media_class = MediaClass.DIRECTORY

child_dir = BrowseMediaSource(
domain=DOMAIN,
identifier=entry_id + "/" + dir_path,
media_class=media_class,
media_content_type=MEDIA_TYPE_VIDEO,
media_content_type=MediaType.VIDEO,
title=title,
can_play=False,
can_expand=True,
Expand All @@ -198,13 +196,13 @@ def _browse_media(self, entry_id:str, event_dir:str) -> BrowseMediaSource:
return None

title = event_dir
media_class = MEDIA_CLASS_VIDEO
media_class = MediaClass.VIDEO

media = BrowseMediaSource(
domain=DOMAIN,
identifier=entry_id + "/" + event_dir,
media_class=media_class,
media_content_type=MEDIA_TYPE_VIDEO,
media_content_type=MediaType.VIDEO,
title=title,
can_play=False,
can_expand=True,
Expand Down Expand Up @@ -243,13 +241,13 @@ def _browse_media(self, entry_id:str, event_dir:str) -> BrowseMediaSource:
thumb_path = ""

title = record_file["time"]
media_class = MEDIA_CLASS_VIDEO
media_class = MediaClass.VIDEO

child_file = BrowseMediaSource(
domain=DOMAIN,
identifier=entry_id + "/" + event_dir + "/" + file_path,
media_class=media_class,
media_content_type=MEDIA_TYPE_VIDEO,
media_content_type=MediaType.VIDEO,
title=title,
can_play=True,
can_expand=False,
Expand Down

0 comments on commit a2a7907

Please sign in to comment.