Пример #1
0
async def test_is_media_source_id():
    """Test media source validation."""
    assert media_source.is_media_source_id(const.URI_SCHEME)
    assert media_source.is_media_source_id(f"{const.URI_SCHEME}domain")
    assert media_source.is_media_source_id(
        f"{const.URI_SCHEME}domain/identifier")
    assert not media_source.is_media_source_id("test")
Пример #2
0
    async def async_play_media(self, media_type: str, media_id: str,
                               **kwargs: Any) -> None:
        """Play media from a URL or file."""
        # Handle media_source
        if media_source.is_media_source_id(media_id):
            sourced_media = await media_source.async_resolve_media(
                self.hass, media_id)
            media_type = MEDIA_TYPE_MUSIC
            media_id = sourced_media.url

        # Sign and prefix with URL if playing a relative URL
        if media_id[0] == "/":
            media_id = async_sign_path(
                self.hass,
                quote(media_id),
                timedelta(seconds=media_source.DEFAULT_EXPIRY_TIME),
            )

            # prepend external URL
            hass_url = get_url(self.hass)
            media_id = f"{hass_url}{media_id}"

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

        await self._vlc.add(media_id)
        self._state = STATE_PLAYING
Пример #3
0
    async def async_browse_media(self,
                                 media_content_type=None,
                                 media_content_id=None):
        """Implement the websocket media browsing helper."""
        _LOGGER.debug(
            "Reached async_browse_media with content_type %s and content_id %s",
            media_content_type,
            media_content_id,
        )

        if media_content_type in [None, "library"]:
            return await library_payload(self.hass, self._player)

        if media_source.is_media_source_id(media_content_id):
            return await media_source.async_browse_media(
                self.hass,
                media_content_id,
                content_filter=media_source_content_filter)

        payload = {
            "search_type": media_content_type,
            "search_id": media_content_id,
        }

        return await build_item_response(self, self._player, payload)
Пример #4
0
    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."""
        # Handle media_source
        if media_source.is_media_source_id(media_id):
            sourced_media = await media_source.async_resolve_media(
                self.hass, media_id, self.entity_id)
            media_id = sourced_media.url

        media_id = async_process_play_media_url(self.hass, media_id)

        queue_opt = QUEUE_OPTION_MAP.get(enqueue, QueueOption.PLAY)
        if announce is None:
            announce = "/api/tts_proxy" in media_id

        if announce:
            announce_sound = "/api/tts_proxy" in media_id
            self.hass.create_task(
                self.player.active_queue.play_alert(media_id, announce_sound))
        else:
            await self.player.active_queue.play_media(media_id, queue_opt)
Пример #5
0
    async def async_play_media(self, media_type: str, media_id: str,
                               **kwargs: Any) -> None:
        """Play a piece of media."""
        if media_source.is_media_source_id(media_id):
            media_type = MEDIA_TYPE_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:
            raise HomeAssistantError("Only music media type is supported")

        _LOGGER.debug("Playing Media %s for %s Speaker", media_id,
                      self.device.name)
        await self.async_media_stop()
        try:
            await self.device.play_audio(media_id, blocking=False)
        except StreamError as err:
            raise HomeAssistantError(err) from err
        else:
            # update state after starting player
            self._async_updated_event()
            # wait until player finishes to update state again
            await self.device.wait_until_audio_completes()

        self._async_updated_event()
Пример #6
0
    async def async_play_media(self, media_type: str, media_id: str,
                               **kwargs: Any) -> None:
        """Send the play_media command to the media player."""
        # If input (file) has a file format supported by pyatv, then stream it with
        # RAOP. Otherwise try to play it with regular AirPlay.
        if media_type == MEDIA_TYPE_APP:
            await self.atv.apps.launch_app(media_id)
            return

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

        if self._is_feature_available(
                FeatureName.StreamFile) and (media_type == MEDIA_TYPE_MUSIC
                                             or await is_streamable(media_id)):
            _LOGGER.debug("Streaming %s via RAOP", media_id)
            await self.atv.stream.stream_file(media_id)
        elif self._is_feature_available(FeatureName.PlayUrl):
            _LOGGER.debug("Playing %s via AirPlay", media_id)
            await self.atv.stream.play_url(media_id)
        else:
            _LOGGER.error(
                "Media streaming is not possible with current configuration")
Пример #7
0
    async def async_play_media(self, media_type, media_id, **kwargs):
        """Send the media player the command for playing a playlist."""
        if media_source.is_media_source_id(media_id):
            media_type = MEDIA_TYPE_MUSIC
            play_item = await media_source.async_resolve_media(
                self.hass, media_id)
            media_id = play_item.url

        if media_type == MEDIA_TYPE_PLAYLIST:
            _LOGGER.debug("Playing playlist: %s", media_id)
            if media_id in self._playlists:
                self._currentplaylist = media_id
            else:
                self._currentplaylist = None
                _LOGGER.warning("Unknown playlist name %s", media_id)
            await self._client.clear()
            await self._client.load(media_id)
            await self._client.play()
        else:
            media_id = async_process_play_media_url(self.hass, media_id)

            await self._client.clear()
            self._currentplaylist = None
            await self._client.add(media_id)
            await self._client.play()
Пример #8
0
    async def async_play_media(self, media_type: str, media_id: str,
                               **kwargs: Any) -> None:
        """Play a piece of media."""
        if media_source.is_media_source_id(media_id):
            media_type = MEDIA_TYPE_URL
            play_item = await media_source.async_resolve_media(
                self.hass, media_id, self.entity_id)
            media_id = play_item.url

        if media_type in (MEDIA_TYPE_URL, MEDIA_TYPE_MUSIC):
            media_id = async_process_play_media_url(self.hass, media_id)

            await self._player.play_url(media_id)
            return

        if media_type == "quick_select":
            # media_id may be an int or a str
            selects = await self._player.get_quick_selects()
            try:
                index: int | None = int(media_id)
            except ValueError:
                # Try finding index by name
                index = next(
                    (index for index, select in selects.items()
                     if select == media_id),
                    None,
                )
            if index is None:
                raise ValueError(f"Invalid quick select '{media_id}'")
            await self._player.play_quick_select(index)
            return

        if media_type == MEDIA_TYPE_PLAYLIST:
            playlists = await self._player.heos.get_playlists()
            playlist = next((p for p in playlists if p.name == media_id), None)
            if not playlist:
                raise ValueError(f"Invalid playlist '{media_id}'")
            add_queue_option = HA_HEOS_ENQUEUE_MAP.get(
                kwargs.get(ATTR_MEDIA_ENQUEUE))

            await self._player.add_to_queue(playlist, add_queue_option)
            return

        if media_type == "favorite":
            # media_id may be an int or str
            try:
                index = int(media_id)
            except ValueError:
                # Try finding index by name
                index = next(
                    (index for index, favorite in self._source_manager.
                     favorites.items() if favorite.name == media_id),
                    None,
                )
            if index is None:
                raise ValueError(f"Invalid favorite '{media_id}'")
            await self._player.play_favorite(index)
            return

        raise ValueError(f"Unsupported media type '{media_type}'")
Пример #9
0
    async def async_play_media(self, media_type: str, media_id: str,
                               **kwargs) -> None:
        """Play media from a URL or file, launch an application, or tune to a channel."""
        extra: dict[str, Any] = kwargs.get(ATTR_MEDIA_EXTRA) or {}

        # Handle media_source
        if media_source.is_media_source_id(media_id):
            sourced_media = await media_source.async_resolve_media(
                self.hass, media_id)
            media_type = MEDIA_TYPE_URL
            media_id = sourced_media.url

        # Sign and prefix with URL if playing a relative URL
        if media_id[0] == "/":
            media_id = async_sign_path(
                self.hass,
                quote(media_id),
                dt.timedelta(seconds=media_source.DEFAULT_EXPIRY_TIME),
            )

            # prepend external URL
            hass_url = get_url(self.hass)
            media_id = f"{hass_url}{media_id}"

        if media_type not in PLAY_MEDIA_SUPPORTED_TYPES:
            _LOGGER.error(
                "Invalid media type %s. Only %s, %s, %s, and camera HLS streams are supported",
                media_type,
                MEDIA_TYPE_APP,
                MEDIA_TYPE_CHANNEL,
                MEDIA_TYPE_URL,
            )
            return

        if media_type == MEDIA_TYPE_APP:
            params = {
                param: extra[attr]
                for attr, param in ATTRS_TO_LAUNCH_PARAMS.items()
                if attr in extra
            }

            await self.coordinator.roku.launch(media_id, params)
        elif media_type == MEDIA_TYPE_CHANNEL:
            await self.coordinator.roku.tune(media_id)
        elif media_type == MEDIA_TYPE_URL:
            params = {
                param: extra[attr]
                for (attr, param) in ATTRS_TO_PLAY_VIDEO_PARAMS.items()
                if attr in extra
            }

            await self.coordinator.roku.play_on_roku(media_id, params)
        elif media_type == FORMAT_CONTENT_TYPE[HLS_PROVIDER]:
            params = {
                "MediaType": "hls",
            }

            await self.coordinator.roku.play_on_roku(media_id, params)

        await self.coordinator.async_request_refresh()
Пример #10
0
    async def async_play_media(self, media_type, media_id, **kwargs):
        """Play a piece of media."""
        # Handle media_source
        if media_source.is_media_source_id(media_id):
            sourced_media = await media_source.async_resolve_media(self.hass, media_id)
            media_type = sourced_media.mime_type
            media_id = sourced_media.url

        # If media ID is a relative URL, we serve it from HA.
        # Create a signed path.
        if media_id[0] == "/":
            # Sign URL with Home Assistant Cast User
            config_entries = self.hass.config_entries.async_entries(CAST_DOMAIN)
            user_id = config_entries[0].data["user_id"]
            user = await self.hass.auth.async_get_user(user_id)
            if user.refresh_tokens:
                refresh_token: RefreshToken = list(user.refresh_tokens.values())[0]

                media_id = async_sign_path(
                    self.hass,
                    refresh_token.id,
                    media_id,
                    timedelta(minutes=5),
                )

            # prepend external URL
            hass_url = get_url(self.hass, prefer_external=True)
            media_id = f"{hass_url}{media_id}"

        await self.hass.async_add_executor_job(
            ft.partial(self.play_media, media_type, media_id, **kwargs)
        )
Пример #11
0
    async def async_play_media(self, media_type, media_id, **kwargs):
        """Play a piece of media."""
        # Handle media_source
        if media_source.is_media_source_id(media_id):
            sourced_media = await media_source.async_resolve_media(
                self.hass, media_id)
            media_type = sourced_media.mime_type
            media_id = sourced_media.url

        # If media ID is a relative URL, we serve it from HA.
        # Create a signed path.
        if media_id[0] == "/":
            # Sign URL with Safegate Pro Cast User
            config_entry_id = self.registry_entry.config_entry_id
            config_entry = self.hass.config_entries.async_get_entry(
                config_entry_id)
            user_id = config_entry.data["user_id"]
            user = await self.hass.auth.async_get_user(user_id)
            if user.refresh_tokens:
                refresh_token: RefreshToken = list(
                    user.refresh_tokens.values())[0]

                media_id = async_sign_path(
                    self.hass,
                    refresh_token.id,
                    quote(media_id),
                    timedelta(seconds=media_source.DEFAULT_EXPIRY_TIME),
                )

            # prepend external URL
            hass_url = get_url(self.hass, prefer_external=True)
            media_id = f"{hass_url}{media_id}"

        await self.hass.async_add_executor_job(
            ft.partial(self.play_media, media_type, media_id, **kwargs))
Пример #12
0
    async def async_play_media(self, media_type: str, media_id: str, **kwargs) -> None:
        """Play media."""
        if media_source.is_media_source_id(media_id):
            play_item = await media_source.async_resolve_media(
                self.hass, media_id, self.entity_id
            )
            media_id = play_item.url

        if self.state == STATE_OFF:
            await self.async_turn_on()

        if media_id:
            parts = media_id.split(":")

            if parts[0] == "list":
                if (index := parts[3]) == "-1":
                    index = "0"

                await self.coordinator.musiccast.play_list_media(index, self._zone_id)
                return

            if parts[0] == "presets":
                index = parts[1]
                await self.coordinator.musiccast.recall_netusb_preset(
                    self._zone_id, index
                )
                return

            if parts[0] in ("http", "https") or media_id.startswith("/"):
                media_id = async_process_play_media_url(self.hass, media_id)

                await self.coordinator.musiccast.play_url_media(
                    self._zone_id, media_id, "HomeAssistant"
                )
                return
Пример #13
0
    def play_media(self, media_type, media_id, **kwargs):
        # Play a piece of media.
        # <ServiceCall media_player.play_media: media_content_type=music, media_content_id=http://192.168.13.91:8123/api/tts_proxy/74a4297365735b6c107b85e034347ce013eeae01_en_-_google.mp3, entity_id=['media_player.mt_office']>
        self._parent.send('mrad.setzone "{}"'.format(self._zoneId))
        self._parent.send('mrad.setsource')

        media_type = media_type.lower()

        if media_source.is_media_source_id(media_id):
            media_type = "music"
            media_id = (asyncio.run_coroutine_threadsafe(
                media_source.async_resolve_media(self._hass, media_id,
                                                 self.entity_id),
                self._hass.loop,
            ).result().url)
            media_id = async_process_play_media_url(self.hass, media_id)

        if media_type == "music":
            self._parent.send('duckplay "{}"'.format(media_id))
        elif media_type == "scene":
            self._parent.send('recallscene "{}"'.format(media_id))
        elif media_type == "preset":
            self._parent.send('recallpreset "{}"'.format(media_id))
        elif media_type == "radiostation":
            self._parent.send('playradiostation "{}"'.format(media_id))
        else:
            _LOGGER.error("Unexpected media_type='%s'.", media_type)
Пример #14
0
    async def async_play_media(self, media_type, media_id, **kwargs):
        """Play media from media_source."""
        if media_source.is_media_source_id(media_id):
            sourced_media = await media_source.async_resolve_media(self.hass, media_id)
            media_type = sourced_media.mime_type
            media_id = sourced_media.url

            # If media ID is a relative URL, we serve it from HA.
            if media_id[0] == "/":
                user = await self.hass.auth.async_get_owner()
                if user.refresh_tokens:
                    refresh_token: RefreshToken = list(user.refresh_tokens.values())[0]

                    # Use kwargs so it works both before and after the change in Home Assistant 2022.2
                    media_id = async_sign_path(
                        hass=self.hass,
                        refresh_token_id=refresh_token.id,
                        path=media_id,
                        expiration=timedelta(minutes=5)
                    )

                # Prepend external URL.
                hass_url = get_url(self.hass, allow_internal=True)
                media_id = f"{hass_url}{media_id}"

            _LOGGER.info("Meural device %s: Playing media. Media type is %s, previewing image from %s", self.name, media_type, media_id)
            await self.local_meural.send_postcard(media_id, media_type)

        # Play gallery (playlist or album) by ID.
        elif media_type in ['playlist']:
            _LOGGER.info("Meural device %s: Playing media. Media type is %s, playing gallery %s", self.name, media_type, media_id)
            await self.local_meural.send_change_gallery(media_id)

        # "Preview image from URL.
        elif media_type in [ 'image/jpg', 'image/png', 'image/jpeg' ]:
            _LOGGER.info("Meural device %s: Playing media. Media type is %s, previewing image from %s", self.name, media_type, media_id)
            await self.local_meural.send_postcard(media_id, media_type)

        # Play item (artwork) by ID. Play locally if item is in currently displayed gallery. If not, play using Meural server."""
        elif media_type in ['item']:
            if media_id.isdigit():
                currentgallery_id = self._gallery_status["current_gallery"]
                currentitems = await self.local_meural.send_get_items_by_gallery(currentgallery_id)
                in_playlist = next((g["title"] for g in currentitems if g["id"] == media_id), None)
                if in_playlist is None:
                    _LOGGER.info("Meural device %s: Playing media. Item %s is not in current gallery, trying to display via Meural server", self.name, media_id)
                    try:
                        await self.meural.device_load_item(self.meural_device_id, media_id)
                    except:
                        _LOGGER.error("Meural device %s: Playing media. Error while trying to display %s item %s via Meural server", self.name, media_type, media_id, exc_info=True)
                else:
                    _LOGGER.info("Meural device %s: Playing media. Item %s is in current gallery %s, trying to display via local device", self.name, media_id, self._gallery_status["current_gallery_name"])
                    await self.local_meural.send_change_item(media_id)
            else:
                _LOGGER.error("Meural device %s: Playing media. ID %s is not an item", self.name, media_id)

        # This is an unsupported media type.
        else:
            _LOGGER.error("Meural device %s: Playing media. Does not support displaying this %s media with ID %s", self.name, media_type, media_id)
Пример #15
0
    async def async_play_media(self, media_type, media_id, **kwargs):
        """Play a piece of media."""
        if media_source.is_media_source_id(media_id):
            play_item = await media_source.async_resolve_media(
                self.hass, media_id)
            media_id = async_process_play_media_url(self.hass, play_item.url)

        await self.hass.async_add_executor_job(
            partial(self.play_media, media_type, media_id, **kwargs))
Пример #16
0
 async def async_play_media(self, media_type, media_id, **kwargs):
     if media_source.is_media_source_id(media_id):
         media_type = MEDIA_TYPE_URL
         play_item = await media_source.async_resolve_media(
             self.hass, media_id)
         media_id = play_item.url
     if media_type in (MEDIA_TYPE_URL, MEDIA_TYPE_MUSIC):
         media_id = async_process_play_media_url(self.hass, media_id)
     self.connection.send("play", media_content_id=media_id)
Пример #17
0
    async def async_play_media(self, media_type, media_id, **kwargs):
        """Send the play_media command to the media player."""
        index = None

        enqueue: MediaPlayerEnqueue | None = kwargs.get(ATTR_MEDIA_ENQUEUE)

        if enqueue == MediaPlayerEnqueue.ADD:
            cmd = "add"
        elif enqueue == MediaPlayerEnqueue.NEXT:
            cmd = "insert"
        elif enqueue == MediaPlayerEnqueue.PLAY:
            cmd = "play_now"
        else:
            cmd = "play"

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

        if media_type in MEDIA_TYPE_MUSIC:
            if not media_id.startswith(SQUEEZEBOX_SOURCE_STRINGS):
                # do not process special squeezebox "source" media ids
                media_id = async_process_play_media_url(self.hass, media_id)

            await self._player.async_load_url(media_id, cmd)
            return

        if media_type == MEDIA_TYPE_PLAYLIST:
            try:
                # a saved playlist by number
                payload = {
                    "search_id": int(media_id),
                    "search_type": MEDIA_TYPE_PLAYLIST,
                }
                playlist = await generate_playlist(self._player, payload)
            except ValueError:
                # a list of urls
                content = json.loads(media_id)
                playlist = content["urls"]
                index = content["index"]
        else:
            payload = {
                "search_id": media_id,
                "search_type": media_type,
            }
            playlist = await generate_playlist(self._player, payload)

            _LOGGER.debug("Generated playlist: %s", playlist)

        await self._player.async_load_playlist(playlist, cmd)
        if index is not None:
            await self._player.async_index(index)
Пример #18
0
    async def async_play_media(
        self, media_type: str, media_id: str, **kwargs: Any
    ) -> None:
        """Play a piece of media."""
        if media_source.is_media_source_id(media_id):
            play_item = await media_source.async_resolve_media(
                self.hass, media_id, self.entity_id
            )
            media_id = async_process_play_media_url(self.hass, play_item.url)

        await self.coordinator.fully.playSound(media_id, AUDIOMANAGER_STREAM_MUSIC)
        self._attr_state = STATE_PLAYING
        self.async_write_ha_state()
Пример #19
0
    async def async_play_media(self, media_type, media_id, **kwargs):
        """Play media."""
        if media_source.is_media_source_id(media_id):
            media_type = MEDIA_TYPE_URL
            play_item = await media_source.async_resolve_media(
                self.hass, media_id)
            media_id = play_item.url

        if media_type != MEDIA_TYPE_URL:
            _LOGGER.warning("Unsupported media_type: %s", media_type)
            return

        media_id = async_process_play_media_url(self.hass, media_id)
        await self._remote.async_play_media(media_type, media_id)
Пример #20
0
async def test_generate_media_source_id():
    """Test identifier generation."""
    tests = [
        (None, None),
        (None, ""),
        ("", ""),
        ("domain", None),
        ("domain", ""),
        ("domain", "identifier"),
    ]

    for domain, identifier in tests:
        assert media_source.is_media_source_id(
            media_source.generate_media_source_id(domain, identifier))
Пример #21
0
    async def async_play_media(
        self, media_type: str, media_id: str, **kwargs: Any
    ) -> None:
        """Send the play command with media url to the media player."""
        if media_source.is_media_source_id(media_id):
            sourced_media = await media_source.async_resolve_media(self.hass, media_id)
            media_id = sourced_media.url

        media_id = async_process_play_media_url(self.hass, media_id)

        await self._client.media_player_command(
            self._static_info.key,
            media_url=media_id,
        )
Пример #22
0
    async def async_play_media(self, media_type: str, media_id: str, **kwargs) -> None:
        """Send the play_media command to the media player."""
        to_send_media_type: str | None = media_type
        # Handle media_source
        if media_source.is_media_source_id(media_id):
            sourced_media = await media_source.async_resolve_media(self.hass, media_id)
            media_id = sourced_media.url
            to_send_media_type = sourced_media.mime_type

        if to_send_media_type and not to_send_media_type.startswith("audio/"):
            to_send_media_type = None
        media_id = async_process_play_media_url(self.hass, media_id)

        await self.player.play_url(media_id, mime_type=to_send_media_type)
Пример #23
0
    async def async_play_media(self, media_type, media_id, **kwargs):
        """Play media."""
        # Handle media_source
        if media_source.is_media_source_id(media_id):
            sourced_media = await media_source.async_resolve_media(self.hass, media_id)
            media_id = sourced_media.url

        elif media_type != MEDIA_TYPE_MUSIC:
            _LOGGER.error("Invalid media type")
            return

        media_id = async_process_play_media_url(self.hass, media_id)

        await self.hass.async_add_executor_job(self._player.queue, media_id)
Пример #24
0
    async def async_play_media(self, media_type, media_id, **kwargs):
        """Send the play_media command to the media player."""
        if self.is_grouped and not self.is_master:
            return

        if media_source.is_media_source_id(media_id):
            play_item = await media_source.async_resolve_media(
                self.hass, media_id, self.entity_id)
            media_id = play_item.url

        media_id = async_process_play_media_url(self.hass, media_id)

        url = f"Play?url={media_id}"

        return await self.send_bluesound_command(url)
Пример #25
0
    async def async_play_media(self, media_type, media_id, **kwargs):
        """
        Send the play_media command to the media player.

        If ATTR_MEDIA_ENQUEUE is True, add `media_id` to the current playlist.
        """
        cmd = "play"
        index = None

        if kwargs.get(ATTR_MEDIA_ENQUEUE):
            cmd = "add"

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

        if media_type in MEDIA_TYPE_MUSIC:
            media_id = async_process_play_media_url(self.hass, media_id)

            await self._player.async_load_url(media_id, cmd)
            return

        if media_type == MEDIA_TYPE_PLAYLIST:
            try:
                # a saved playlist by number
                payload = {
                    "search_id": int(media_id),
                    "search_type": MEDIA_TYPE_PLAYLIST,
                }
                playlist = await generate_playlist(self._player, payload)
            except ValueError:
                # a list of urls
                content = json.loads(media_id)
                playlist = content["urls"]
                index = content["index"]
        else:
            payload = {
                "search_id": media_id,
                "search_type": media_type,
            }
            playlist = await generate_playlist(self._player, payload)

            _LOGGER.debug("Generated playlist: %s", playlist)

        await self._player.async_load_playlist(playlist, cmd)
        if index is not None:
            await self._player.async_index(index)
Пример #26
0
    async def async_play_media(self, media_type, media_id, **kwargs):
        """Send the play_media command to the media player."""
        if media_source.is_media_source_id(media_id):
            media_type = MEDIA_TYPE_MUSIC
            play_item = await media_source.async_resolve_media(
                self.hass, media_id)
            media_id = play_item.url

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

        media_id = async_process_play_media_url(self.hass, media_id)

        track_details = {"title": "Home Assistant", "uri": media_id}
        await self._device.play_media(track_details)
Пример #27
0
    async def async_browse_media(self,
                                 media_content_type=None,
                                 media_content_id=None):
        """Implement the websocket media browsing helper."""
        is_internal = is_internal_request(self.hass)

        async def _get_thumbnail_url(
            media_content_type,
            media_content_id,
            media_image_id=None,
            thumbnail_url=None,
        ):
            if is_internal:
                return self._kodi.thumbnail_url(thumbnail_url)

            return self.get_browse_image_url(
                media_content_type,
                urllib.parse.quote_plus(media_content_id),
                media_image_id,
            )

        if media_content_type in [None, "library"]:
            return await library_payload(self.hass)

        if media_source.is_media_source_id(media_content_id):
            return await media_source.async_browse_media(
                self.hass,
                media_content_id,
                content_filter=media_source_content_filter)

        payload = {
            "search_type": media_content_type,
            "search_id": media_content_id,
        }

        response = await build_item_response(self._kodi, payload,
                                             _get_thumbnail_url)
        if response is None:
            raise BrowseError(
                f"Media not found: {media_content_type} / {media_content_id}")
        return response
Пример #28
0
    async def async_play_media(
        self, media_type: str, media_id: str, **kwargs: Any
    ) -> None:
        """Play a piece of media."""
        _LOGGER.debug("Playing media: %s, %s, %s", media_type, media_id, kwargs)
        assert self._device is not None

        didl_metadata: str | None = None
        title: str = ""

        # If media is media_source, resolve it to url and MIME type, and maybe metadata
        if media_source.is_media_source_id(media_id):
            sourced_media = await media_source.async_resolve_media(self.hass, media_id)
            media_type = sourced_media.mime_type
            media_id = sourced_media.url
            _LOGGER.debug("sourced_media is %s", sourced_media)
            if sourced_metadata := getattr(sourced_media, "didl_metadata", None):
                didl_metadata = didl_lite.to_xml_string(sourced_metadata).decode(
                    "utf-8"
                )
                title = sourced_metadata.title
Пример #29
0
    async def async_play_media(
        self, media_type: str, media_id: str, **kwargs: Any
    ) -> None:
        """Send the play_media command to the media player."""
        if media_source.is_media_source_id(media_id):
            media_type = MEDIA_TYPE_URL
            play_item = await media_source.async_resolve_media(self.hass, media_id)
            media_id = play_item.url

        media_type_lower = media_type.lower()

        if media_type_lower == MEDIA_TYPE_CHANNEL:
            await self._kodi.play_channel(int(media_id))
        elif media_type_lower == MEDIA_TYPE_PLAYLIST:
            await self._kodi.play_playlist(int(media_id))
        elif media_type_lower == "file":
            await self._kodi.play_file(media_id)
        elif media_type_lower == "directory":
            await self._kodi.play_directory(media_id)
        elif media_type_lower in [
            MEDIA_TYPE_ARTIST,
            MEDIA_TYPE_ALBUM,
            MEDIA_TYPE_TRACK,
        ]:
            await self.async_clear_playlist()
            await self.async_add_to_playlist(media_type_lower, media_id)
            await self._kodi.play_playlist(0)
        elif media_type_lower in [
            MEDIA_TYPE_MOVIE,
            MEDIA_TYPE_EPISODE,
            MEDIA_TYPE_SEASON,
            MEDIA_TYPE_TVSHOW,
        ]:
            await self._kodi.play_item(
                {MAP_KODI_MEDIA_TYPES[media_type_lower]: int(media_id)}
            )
        else:
            media_id = async_process_play_media_url(self.hass, media_id)

            await self._kodi.play_file(media_id)
Пример #30
0
    async def async_play_media(self, media_type: str, media_id: str,
                               **kwargs: Any) -> None:
        """Play media from a URL or file."""
        # Handle media_source
        if media_source.is_media_source_id(media_id):
            sourced_media = await media_source.async_resolve_media(
                self.hass, media_id)
            media_type = sourced_media.mime_type
            media_id = sourced_media.url

        if media_type != MEDIA_TYPE_MUSIC and not media_type.startswith(
                "audio/"):
            raise HomeAssistantError(
                f"Invalid media type {media_type}. Only {MEDIA_TYPE_MUSIC} is supported"
            )

        # If media ID is a relative URL, we serve it from HA.
        media_id = async_process_play_media_url(
            self.hass, media_id, for_supervisor_network=self._using_addon)

        await self._vlc.add(media_id)
        self._state = STATE_PLAYING