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

default to OCP pipeline + support for utils 0.0.38 #119

Merged
merged 8 commits into from
Jun 2, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions .github/workflows/unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ jobs:
# NOTE: additional pytest invocations should also add the --cov-append flag
# or they will overwrite previous invocations' coverage reports
# (for an example, see OVOS Skill Manager's workflow)
- name: Run unittests with ovos-utils 0.0.38
run: |
pip install ovos-utils==0.0.38
pytest --cov=ovos_plugin_common_play --cov-report xml test/unittests
- name: Upload coverage
env:
CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}}
Expand Down
6 changes: 4 additions & 2 deletions ovos_plugin_common_play/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from pprint import pformat

from ovos_bus_client import Message
from ovos_utils.log import LOG
from ovos_workshop.decorators.ocp import *

from ovos_plugin_common_play.ocp import OCP
from ovos_plugin_common_play.ocp.base import OCPAudioPlayerBackend
from ovos_utils.ocp import *
from ovos_utils.log import LOG
from ovos_plugin_common_play.ocp.constants import OCP_ID


class OCPAudioBackend(OCPAudioPlayerBackend):
Expand Down
4 changes: 3 additions & 1 deletion ovos_plugin_common_play/launcher.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#!/usr/bin/env python3
from ovos_bus_client import MessageBusClient
from ovos_plugin_common_play.ocp import OCP, OCP_ID
from ovos_utils import wait_for_exit_signal

from ovos_plugin_common_play.ocp import OCP
from ovos_plugin_common_play.ocp.constants import OCP_ID


def main():
"""
Expand Down
17 changes: 12 additions & 5 deletions ovos_plugin_common_play/ocp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
from ovos_utils.gui import can_use_gui
from ovos_utils.log import LOG
from ovos_utils.messagebus import Message
from ovos_utils.ocp import OCP_ID

from padacioso import IntentContainer

from ovos_workshop import OVOSAbstractApplication
from ovos_workshop.decorators.ocp import *
from ovos_plugin_manager.ocp import load_stream_extractors

from ovos_plugin_common_play.ocp.constants import OCP_ID


class OCP(OVOSAbstractApplication):
intent2media = {
Expand Down Expand Up @@ -125,10 +127,15 @@ def handle_home(self, message=None):

@property
def using_new_pipeline(self) -> bool:
# TODO - default to True in ovos-core 0.1.0
# more info: https://github.com/OpenVoiceOS/ovos-core/pull/456
moved_to_pipelines = Configuration().get("intents", {}).get("experimental_ocp_pipeline")
return moved_to_pipelines
# this is no longer configurable, most of this repo is dead code
# keep this check to allow smooth updates from the couple alpha versions this was live
if Configuration().get("intents", {}).get("experimental_ocp_pipeline"):
return True
# check for min version for default ovos-config to contain OCP pipeline
from ovos_config.version import VERSION_BUILD, VERSION_ALPHA, VERSION_MAJOR, VERSION_MINOR
if VERSION_BUILD > 13 or VERSION_MAJOR >= 1 or VERSION_MINOR >= 1:
return True
return VERSION_BUILD == 13 and VERSION_ALPHA >= 14
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for anyone reviewing this is the relevant change to account for OpenVoiceOS/ovos-core#491 and OpenVoiceOS/ovos-config#96


def register_ocp_intents(self, message=None):
if self.using_new_pipeline:
Expand Down
10 changes: 5 additions & 5 deletions ovos_plugin_common_play/ocp/base.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from os.path import join, isfile

from ovos_bus_client.message import Message
from ovos_plugin_common_play.ocp.utils import extract_metadata
from ovos_utils.log import LOG
from ovos_utils.ocp import MediaState, PlayerState, OCP_ID, TrackState


from ovos_config.locations import get_xdg_config_save_path
from ovos_plugin_manager.templates.audio import AudioBackend
from ovos_utils.log import LOG
from ovos_workshop.decorators.ocp import MediaState, PlayerState, TrackState

from ovos_plugin_common_play.ocp.constants import OCP_ID
from ovos_plugin_common_play.ocp.utils import extract_metadata


class OCPAbstractComponent:
Expand Down
2 changes: 1 addition & 1 deletion ovos_plugin_common_play/ocp/constants.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from ovos_utils.ocp import OCP_ID
OCP_ID = "ovos.common_play"
87 changes: 44 additions & 43 deletions ovos_plugin_common_play/ocp/gui.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import enum
from os.path import join, dirname

from ovos_utils.ocp import OCP_ID, MediaType, PlayerState, LoopState, PlaybackType
from threading import Timer
from time import sleep

from ovos_bus_client.apis.gui import GUIInterface
from ovos_bus_client.message import Message
from ovos_config import Configuration
from ovos_utils.events import EventSchedulerInterface
from ovos_bus_client.apis.gui import GUIInterface
from ovos_utils.log import LOG
from ovos_workshop.decorators.ocp import MediaType, PlayerState, LoopState, PlaybackType

from ovos_plugin_common_play.ocp.constants import OCP_ID
from ovos_plugin_common_play.ocp.utils import is_qtav_available
from threading import Timer


class VideoPlayerBackend(str, enum.Enum):
Expand Down Expand Up @@ -53,12 +54,12 @@ def bind(self, player):
@property
def video_backend(self):
return self.player.settings.get("video_player_backend") or \
VideoPlayerBackend.AUTO
VideoPlayerBackend.AUTO

@property
def home_screen_page(self):
return "Home"

@property
def disambiguation_playlists_page(self):
return "SuggestionsView"
Expand Down Expand Up @@ -113,7 +114,7 @@ def update_ocp_skills(self):
"title": skill["skill_name"],
"image": skill["thumbnail"],
"media_type": skill.get("media_type") or [MediaType.GENERIC]
} for skill in self.player.media.get_featured_skills()]
} for skill in self.player.media.get_featured_skills()]
self["skillCards"] = skills_cards

def update_seekbar_capabilities(self):
Expand Down Expand Up @@ -142,10 +143,10 @@ def update_current_track(self):
self["uri"] = self.player.now_playing.uri
self["title"] = self.player.now_playing.title
self["image"] = self.player.now_playing.image or \
join(dirname(__file__), "res/ui/images/ocp.png")
join(dirname(__file__), "res/ui/images/ocp.png")
self["artist"] = self.player.now_playing.artist
self["bg_image"] = self.player.now_playing.bg_image or \
join(dirname(__file__), "res/ui/images/ocp_bg.png")
join(dirname(__file__), "res/ui/images/ocp_bg.png")
self["duration"] = self.player.now_playing.length
self["position"] = self.player.now_playing.position
# options below control the web player
Expand All @@ -154,7 +155,7 @@ def update_current_track(self):
# TODO default permissive or restrictive?
self["javascript"] = self.player.now_playing.javascript
self["javascriptCanOpenWindows"] = False # TODO allow to be defined per track
self["allowUrlChange"] = False # TODO allow to be defined per track
self["allowUrlChange"] = False # TODO allow to be defined per track

def update_search_results(self):
self["searchModel"] = {
Expand All @@ -181,30 +182,30 @@ def manage_display(self, page_requested, timeout=None):
# This is to ensure that the home is always available to the user
# regardless of what other pages are currently open
# Swiping from the player to the left will always show the home page

# The home page will only be in view if the user is not currently playing an active track
# If the user is playing a track, the player will be shown instead
# This is to ensure that the user always returns to the player when they are playing a track

# The search_spinner_page has been integrated into the home page as an overlay
# It will be shown when the user is searching for a track and will be hidden when the search is complete
# on platforms that don't support the notification system

# Player:
# Player loader will always be shown at Protocol level index 1
# The merged playlist and disambiguation pages will always be shown at Protocol level index 2

# If the user has just opened the ocp home page, and nothing was played previously,
# the player and merged playlist/disambiguation page will not be shown

# If the user has just opened the ocp home page, and a track was previously played,
# the player and merged playlist/disambiguation page will always be shown

# If the player is not paused or stopped, the player will be shown instead of the home page
# when ocp is opened

# Timeout is used to ensure that ocp is fully closed once the timeout has expired

sleep(0.2)
player_status = self.player.state
state2str = {PlayerState.PLAYING: "Playing", PlayerState.PAUSED: "Paused", PlayerState.STOPPED: "Stopped"}
Expand All @@ -215,11 +216,11 @@ def manage_display(self, page_requested, timeout=None):

LOG.debug(f"manage_display: page_requested: {page_requested}")
LOG.debug(f"manage_display: player_status: {player_status}")

if page_requested == "home":
self["homepage_index"] = 0
self["displayBottomBar"] = False

# Check if the skills page has anything to show, only show it if it does
if self["skillCards"]:
self["displayBottomBar"] = True
Expand All @@ -238,16 +239,16 @@ def manage_display(self, page_requested, timeout=None):
elif page_requested == "playlist":
self["displaySuggestionBar"] = False
self._show_suggestion_playlist()

if timeout is not None:
self.show_page(self.disambiguation_playlists_page, override_idle=timeout, override_animations=True)
else:
self.show_page(self.disambiguation_playlists_page, override_idle=True, override_animations=True)

elif page_requested == "disambiguation":
self["displaySuggestionBar"] = False
self._show_suggestion_disambiguation()

if timeout is not None:
self.show_page(self.disambiguation_playlists_page, override_idle=timeout, override_animations=True)
else:
Expand All @@ -264,7 +265,7 @@ def cancel_app_view_timeout(self, restart=False):

def schedule_app_view_pause_timeout(self):
if (self.player.app_view_timeout_enabled
and self.player.app_view_timeout_mode == "pause"
and self.player.app_view_timeout_mode == "pause"
and self.player.state == PlayerState.PAUSED):
self.schedule_app_view_timeout()

Expand Down Expand Up @@ -332,19 +333,19 @@ def _get_pages_to_display(self):
# determine pages to be shown
self["playerBackend"] = self._get_player_page()
LOG.debug(f"pages to display backend: {self['playerBackend']}")

if len(self.player.disambiguation):
self["displaySuggestionBar"] = False
self._show_suggestion_disambiguation()

if len(self.player.tracks):
self["displaySuggestionBar"] = False
self._show_suggestion_playlist()

if len(self.player.disambiguation) and len(self.player.tracks):
if len(self.player.disambiguation) and len(self.player.tracks):
self["displaySuggestionBar"] = True
self._show_suggestion_playlist()

pages = [self.player_loader_page, self.disambiguation_playlists_page]

return pages
Expand All @@ -357,7 +358,7 @@ def _show_home_skills(self):

def _show_suggestion_playlist(self):
self.send_event("ocp.gui.show.suggestion.view.playlist")

def _show_suggestion_disambiguation(self):
self.send_event("ocp.gui.show.suggestion.view.disambiguation")

Expand All @@ -374,7 +375,7 @@ def handle_play_from_playlist(self, message):

def handle_play_from_search(self, message):
LOG.debug("Playback requested from search results")
media = message.data["playlistData"]
media = message.data["playlistData"]
for track in self.player.disambiguation:
if track == media: # found track
self.player.play_media(track)
Expand Down Expand Up @@ -417,7 +418,7 @@ def handle_end_of_playback(self, message=None):
# show search results, release screen after 60 seconds
if show_results:
self.manage_display("playlist", timeout=60)

def display_notification(self, text, style="info"):
""" Display a notification on the screen instead of spinner on platform that support it """
self.show_controlled_notification(text, style=style)
Expand Down Expand Up @@ -447,7 +448,7 @@ def show_search_spinner(self, persist_home=False):

def remove_search_spinner(self):
self.send_event("ocp.gui.hide.busy.overlay")

def remove_homescreen(self):
self.release()

Expand All @@ -467,7 +468,7 @@ def __init__(self, skill_id):
# - Extra / Disambiguation / Playlist, this is the page that will be shown when the skill is launched and the skill is playing
# - Custom, allow the skill to show any custom page it wants
# Page management lifecycle will be handled by the skill itself

def bind(self, player):
self.player = player
super().set_bus(self.bus)
Expand All @@ -476,38 +477,38 @@ def register_screen_type(self, page_url, page_type):
for page in self.ocp_registered_pages:
if page["type"] == page_type:
return

page_to_register = {
"page_url": page_url,
"type": page_type
}
self.ocp_registered_pages[page_type] = page_to_register

def get_screen_type(self, page_type):
return self.ocp_registered_pages[page_type]

def show_screen(self, page_type, override_idle=False, override_animations=False):
page_to_show = self.get_screen_type(page_type)
self.show_page(page_to_show["page_url"], override_idle=override_idle, override_animations=override_animations)

def show_home(self, override_idle=False, override_animations=False):
self.show_screen("home", override_idle, override_animations)

def show_player(self, override_idle=False, override_animations=False):
self.show_screen("player", override_idle, override_animations)

def show_extra(self, override_idle=False, override_animations=False):
self.show_screen("extra", override_idle, override_animations)

def remove_screen(self, page_type):
page_to_remove = self.get_screen_type(page_type)
self.remove_page(page_to_remove["page_url"])

def remove_home(self):
self.remove_screen("home")

def remove_player(self):
self.remove_screen("player")

def remove_extra(self):
self.remove_screen("extra")
Loading
Loading