Skip to content

Commit

Permalink
Fix: simple commands ffwd and rewind begin (#22)
Browse files Browse the repository at this point in the history
Fixed simple commands ffwd and rewind begin where in some apps command remained stuck. Now pressing pause/back/next/previous stops the ffwd/begin action

---------

Co-authored-by: BAIN THOUVEREZ Damien DTSI/BLIM <[email protected]>
  • Loading branch information
albaintor and BAIN THOUVEREZ Damien DTSI/BLIM authored Jul 9, 2024
1 parent 5452b03 commit a266e09
Showing 1 changed file with 48 additions and 1 deletion.
49 changes: 48 additions & 1 deletion intg-appletv/tv.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import random
from asyncio import AbstractEventLoop
from collections import OrderedDict
from enum import IntEnum
from enum import Enum, IntEnum
from functools import wraps
from typing import (
Any,
Expand All @@ -30,6 +30,7 @@
)

import pyatv
import pyatv.const
import ucapi
from config import AtvDevice, AtvProtocol
from pyatv import interface
Expand Down Expand Up @@ -71,6 +72,14 @@ class EVENTS(IntEnum):
_P = ParamSpec("_P")


class PlaybackState(Enum):
"""Playback state for companion protocol."""

NORMAL = 0
FAST_FORWARD = 1
REWIND = 2


# Adapted from Home Assistant `asyncLOG_errors` in
# https://github.com/home-assistant/core/blob/fd1f0b0efeb5231d3ee23d1cb2a10cdeff7c23f1/homeassistant/components/denonavr/media_player.py
def async_handle_atvlib_errors(
Expand Down Expand Up @@ -165,6 +174,7 @@ def __init__(
self._app_list: dict[str, str] = {}
self._available_output_devices: dict[str, str] = {}
self._output_devices: OrderedDict[str, [str]] = OrderedDict()
self._playback_state = PlaybackState.NORMAL

@property
def identifier(self) -> str:
Expand Down Expand Up @@ -655,24 +665,30 @@ async def turn_off(self) -> ucapi.StatusCodes:
@async_handle_atvlib_errors
async def play_pause(self) -> ucapi.StatusCodes:
"""Toggle between play and pause."""
await self.stop_fast_forward_rewind()
await self._atv.remote_control.play_pause()

@async_handle_atvlib_errors
async def fast_forward(self) -> ucapi.StatusCodes:
"""Long press key right for fast-forward."""
await self.stop_fast_forward_rewind()
await self._atv.remote_control.right(InputAction.Hold)

@async_handle_atvlib_errors
async def rewind(self) -> ucapi.StatusCodes:
"""Long press key left for rewind."""
await self.stop_fast_forward_rewind()
await self._atv.remote_control.left(InputAction.Hold)

@async_handle_atvlib_errors
async def fast_forward_companion(self) -> ucapi.StatusCodes:
"""Fast-forward using companion protocol."""
companion = cast(FacadeRemoteControl, self._atv.remote_control).get(Protocol.Companion)
if companion:
if self._playback_state == PlaybackState.REWIND:
await self.stop_fast_forward_rewind()
await companion.api.mediacontrol_command(command=MediaControlCommand.FastForwardBegin)
self._playback_state = PlaybackState.FAST_FORWARD
else:
await self._atv.remote_control.right(InputAction.Hold)

Expand All @@ -681,19 +697,48 @@ async def rewind_companion(self) -> ucapi.StatusCodes:
"""Rewind using companion protocol."""
companion = cast(FacadeRemoteControl, self._atv.remote_control).get(Protocol.Companion)
if companion:
if self._playback_state == PlaybackState.FAST_FORWARD:
await self.stop_fast_forward_rewind()
await companion.api.mediacontrol_command(command=MediaControlCommand.RewindBegin)
self._playback_state = PlaybackState.REWIND
else:
await self._atv.remote_control.left(InputAction.Hold)

async def fast_forward_companion_end(self):
"""Fast-forward using companion protocol."""
companion = cast(FacadeRemoteControl, self._atv.remote_control).get(Protocol.Companion)
if companion:
await companion.api.mediacontrol_command(command=MediaControlCommand.FastForwardEnd)
self._playback_state = PlaybackState.NORMAL

async def rewind_companion_end(self):
"""Rewind using companion protocol."""
companion = cast(FacadeRemoteControl, self._atv.remote_control).get(Protocol.Companion)
if companion:
await companion.api.mediacontrol_command(command=MediaControlCommand.RewindEnd)
self._playback_state = PlaybackState.NORMAL

async def stop_fast_forward_rewind(self) -> bool:
"""Stop fast forward or rewind if running."""
if self._playback_state == PlaybackState.NORMAL:
return False
if self._playback_state == PlaybackState.FAST_FORWARD:
await self.fast_forward_companion_end()
else:
await self.rewind_companion_end()
return True

@async_handle_atvlib_errors
async def next(self) -> ucapi.StatusCodes:
"""Press key next."""
await self.stop_fast_forward_rewind()
if self._is_feature_available(FeatureName.Next): # to prevent timeout errors
await self._atv.remote_control.next()

@async_handle_atvlib_errors
async def previous(self) -> ucapi.StatusCodes:
"""Press key previous."""
await self.stop_fast_forward_rewind()
if self._is_feature_available(FeatureName.Previous):
await self._atv.remote_control.previous()

Expand All @@ -703,6 +748,7 @@ async def skip_forward(self) -> ucapi.StatusCodes:
Skip interval is typically 15-30s, but is decided by the app.
"""
await self.stop_fast_forward_rewind()
if self._is_feature_available(FeatureName.SkipForward):
await self._atv.remote_control.skip_forward()

Expand All @@ -712,6 +758,7 @@ async def skip_backward(self) -> ucapi.StatusCodes:
Skip interval is typically 15-30s, but is decided by the app.
"""
await self.stop_fast_forward_rewind()
if self._is_feature_available(FeatureName.SkipBackward):
await self._atv.remote_control.skip_backward()

Expand Down

0 comments on commit a266e09

Please sign in to comment.