Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add timeout to quickplay interface #827

Merged
merged 3 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pychromecast/controllers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,5 +203,5 @@ class QuickPlayController(BaseController, abc.ABC):
"""ABC for controller which supports quick play."""

@abc.abstractmethod
def quick_play(self, *, media_id: str, **kwargs: Any) -> None:
def quick_play(self, *, media_id: str, timeout: float, **kwargs: Any) -> None:
"""Quick Play support for a controller."""
2 changes: 2 additions & 0 deletions pychromecast/controllers/bbciplayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def quick_play(
self,
*,
media_id: str,
timeout: float,
is_live: bool = False,
metadata: dict[str, Any] | None = None,
**kwargs: Any,
Expand All @@ -44,5 +45,6 @@ def quick_play(
stream_type=stream_type,
metadata=metadata,
media_info={"customData": {"secondary_title": subtitle}},
timeout=timeout,
**kwargs,
)
2 changes: 2 additions & 0 deletions pychromecast/controllers/bbcsounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def quick_play(
self,
*,
media_id: str,
timeout: float,
is_live: bool = False,
metadata: dict[str, Any] | None = None,
**kwargs: Any,
Expand All @@ -39,5 +40,6 @@ def quick_play(
media_type=None,
stream_type=stream_type,
metadata=metadata,
timeout=timeout,
**kwargs,
)
4 changes: 2 additions & 2 deletions pychromecast/controllers/media.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,12 +544,12 @@ def _send_start_play_media( # pylint: disable=too-many-locals

self.send_message(msg, inc_session_id=True, callback_function=callback_function)

def quick_play(self, *, media_id: str, **kwargs: Any) -> None:
def quick_play(self, *, media_id: str, timeout: float, **kwargs: Any) -> None:
"""Quick Play"""

media_type = kwargs.pop("media_type", "video/mp4")

response_handler = WaitResponse(30)
response_handler = WaitResponse(timeout)
self.play_media(
media_id, media_type, **kwargs, callback_function=response_handler.callback
)
Expand Down
4 changes: 2 additions & 2 deletions pychromecast/controllers/supla.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ def play_media(
)

def quick_play(
self, *, media_id: str, is_live: bool = False, **kwargs: Any
self, *, media_id: str, timeout: float, is_live: bool = False, **kwargs: Any
) -> None:
"""Quick Play"""
response_handler = WaitResponse(10)
response_handler = WaitResponse(timeout)
self.play_media(
media_id,
is_live=is_live,
Expand Down
3 changes: 2 additions & 1 deletion pychromecast/controllers/yleareena.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,13 @@ def quick_play(
self,
*,
media_id: str,
timeout: float,
audio_lang: str = "",
text_lang: str = "off",
**kwargs: Any,
) -> None:
"""Quick Play"""
response_handler = WaitResponse(10)
response_handler = WaitResponse(timeout)
self.play_areena_media(
media_id,
audio_language=audio_lang,
Expand Down
62 changes: 59 additions & 3 deletions pychromecast/controllers/youtube.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
Controller to interface with the YouTube-app.
Use the media controller to play, pause etc.
"""

import logging
import threading
from typing import Any
from typing import Any, cast

from casttube import YouTubeSession # type: ignore[import-untyped]
from casttube.YouTubeSession import HEADERS # type: ignore[import-untyped]
import requests

from . import QuickPlayController
from ..const import MESSAGE_TYPE
Expand All @@ -22,23 +25,73 @@
_LOGGER = logging.getLogger(__name__)


class TimeoutYouTubeSession(YouTubeSession): # type: ignore[misc]
"""A youtube session with timeout."""

def __init__(self, screen_id: str, timeout: float) -> None:
"""Initialize."""
super().__init__(screen_id)
self.__timeout = timeout

def _do_post(
self,
url: Any,
data: Any = None,
params: Any = None,
headers: Any = None,
session_request: Any = False,
) -> Any:
"""
Calls requests.post with custom headers,
increments RID(request id) on every post.
will raise if response is not 200
:param url:(str) request url
:param data: (dict) the POST body
:param params:(dict) POST url params
:param headers:(dict) Additional headers for the request
:param session_request:(bool) True to increment session
request counter(req_count)
:return: POST response
"""
if headers:
headers = {**HEADERS, **headers}
else:
headers = HEADERS
response = requests.post(
url, headers=headers, data=data, params=params, timeout=self.__timeout
)
# 404 resets the sid, session counters
# 400 in session probably means bad sid
# If user did a bad request (eg. remove an non-existing video from queue) bind restores the session.
emontnemery marked this conversation as resolved.
Show resolved Hide resolved
if response.status_code in (404, 400) and session_request:
self._bind()
response.raise_for_status()
if session_request:
self._req_count += 1
self._rid += 1
return response


class YouTubeController(QuickPlayController):
"""Controller to interact with Youtube."""

_session: YouTubeSession
_screen_id: str | None = None

def __init__(self) -> None:
def __init__(self, timeout: float = 10) -> None:
super().__init__(YOUTUBE_NAMESPACE, APP_YOUTUBE)
self.status_update_event = threading.Event()
self._timeout = timeout

def start_session_if_none(self) -> None:
"""
Starts a session it is not yet initialized.
"""
if not (self._screen_id and self._session):
self.update_screen_id()
self._session = YouTubeSession(screen_id=self._screen_id)
self._session = TimeoutYouTubeSession(
screen_id=cast(str, self._screen_id), timeout=self._timeout
)

def play_video(self, video_id: str, playlist_id: str | None = None) -> None:
"""
Expand Down Expand Up @@ -112,11 +165,14 @@ def quick_play(
self,
*,
media_id: str,
timeout: float,
playlist_id: str | None = None,
enqueue: bool = False,
**kwargs: Any,
) -> None:
"""Quick Play"""
self._timeout = timeout

if enqueue:
self.add_to_queue(media_id, **kwargs)
else:
Expand Down