From 39ef413544970af8876e0a4a8016261e70ee2db1 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Mon, 8 Jan 2024 01:05:53 +0000 Subject: [PATCH 01/10] feat/OCP_backends --- ovos_plugin_manager/templates/media.py | 277 +++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 ovos_plugin_manager/templates/media.py diff --git a/ovos_plugin_manager/templates/media.py b/ovos_plugin_manager/templates/media.py new file mode 100644 index 00000000..a522f509 --- /dev/null +++ b/ovos_plugin_manager/templates/media.py @@ -0,0 +1,277 @@ +from abc import ABCMeta, abstractmethod + +from ovos_bus_client.message import Message +from ovos_utils.log import LOG +from ovos_utils.messagebus import FakeBus + +from ovos_utils.ocp import MediaState, PlayerState, TrackState + + +class MediaBackend(metaclass=ABCMeta): + """Base class for all OCP media backend implementations. + + Media backends are single-track, playlists are handled by OCP + + Arguments: + config (dict): configuration dict for the instance + bus (MessageBusClient): Mycroft messagebus emitter + """ + + def __init__(self, config=None, bus=None): + self._now_playing = None # single uri + self._track_start_callback = None + self.supports_mime_hints = False + self.config = config or {} + self.bus = bus or FakeBus() + + def set_track_start_callback(self, callback_func): + """Register callback on track start. + + This method should be called as each track in a playlist is started. + """ + self._track_start_callback = callback_func + + def load_track(self, uri): + self._now_playing = uri + LOG.debug(f"queuing for {self.__class__.__name__} playback: {uri}") + self.bus.emit(Message("ovos.common_play.media.state", + {"state": MediaState.LOADED_MEDIA})) + + def ocp_start(self): + """Emit OCP status events for play""" + self.bus.emit(Message("ovos.common_play.player.state", + {"state": PlayerState.PLAYING})) + self.bus.emit(Message("ovos.common_play.media.state", + {"state": MediaState.LOADED_MEDIA})) + self.play() + + def ocp_error(self): + """Emit OCP status events for playback error""" + if self._now_playing: + self._now_playing = None + self.bus.emit(Message("ovos.common_play.media.state", + {"state": MediaState.INVALID_MEDIA})) + self.bus.emit(Message("ovos.common_play.player.state", + {"state": PlayerState.STOPPED})) + + def ocp_stop(self): + """Emit OCP status events for stop""" + if self._now_playing: + self._now_playing = None + self.bus.emit(Message("ovos.common_play.player.state", + {"state": PlayerState.STOPPED})) + self.bus.emit(Message("ovos.common_play.media.state", + {"state": MediaState.END_OF_MEDIA})) + self.stop() + + def ocp_pause(self): + """Emit OCP status events for pause""" + if self._now_playing: + self.bus.emit(Message("ovos.common_play.player.state", + {"state": PlayerState.PAUSED})) + self.pause() + + def ocp_resume(self): + """Emit OCP status events for resume""" + if self._now_playing: + self.bus.emit(Message("ovos.common_play.player.state", + {"state": PlayerState.PLAYING})) + self.bus.emit(Message("ovos.common_play.track.state", + {"state": TrackState.PLAYING_AUDIO})) + self.resume() + + @property + def playback_time(self): + return 0 + + @abstractmethod + def supported_uris(self): + """List of supported uri types. + + Returns: + list: Supported uri's + """ + + @abstractmethod + def play(self): + """Start playback. + + Starts playing the first track in the playlist and will contiune + until all tracks have been played. + """ + + @abstractmethod + def stop(self): + """Stop playback. + + Stops the current playback. + + Returns: + bool: True if playback was stopped, otherwise False + """ + + @abstractmethod + def pause(self): + """Pause playback. + + Stops playback but may be resumed at the exact position the pause + occured. + """ + + @abstractmethod + def resume(self): + """Resume paused playback. + + Resumes playback after being paused. + """ + + @abstractmethod + def lower_volume(self): + """Lower volume. + + This method is used to implement audio ducking. It will be called when + OpenVoiceOS is listening or speaking to make sure the media playing isn't + interfering. + """ + + @abstractmethod + def restore_volume(self): + """Restore normal volume. + + Called when to restore the playback volume to previous level after + OpenVoiceOS has lowered it using lower_volume(). + """ + + @abstractmethod + def get_track_length(self) -> int: + """ + getting the duration of the audio in milliseconds + """ + + @abstractmethod + def get_track_position(self) -> int: + """ + get current position in milliseconds + """ + + @abstractmethod + def set_track_position(self, milliseconds): + """ + go to position in milliseconds + Args: + milliseconds (int): number of milliseconds of final position + """ + + def seek_forward(self, seconds=1): + """Skip X seconds. + + Arguments: + seconds (int): number of seconds to seek, if negative rewind + """ + miliseconds = seconds * 1000 + new_pos = self.get_track_position() + miliseconds + self.set_track_position(new_pos) + + def seek_backward(self, seconds=1): + """Rewind X seconds. + + Arguments: + seconds (int): number of seconds to seek, if negative jump forward. + """ + miliseconds = seconds * 1000 + new_pos = self.get_track_position() - miliseconds + self.set_track_position(new_pos) + + def track_info(self): + """Get info about current playing track. + + Returns: + dict: Track info containing atleast the keys artist and album. + """ + ret = {} + ret['artist'] = '' + ret['album'] = '' + ret['title'] = self._now_playing + return ret + + def shutdown(self): + """Perform clean shutdown. + + Implements any audio backend specific shutdown procedures. + """ + self.stop() + + +class AudioBackend(MediaBackend): + """ for audio""" + + def load_track(self, uri): + super().load_track(uri) + self.bus.emit(Message("ovos.common_play.track.state", + {"state": TrackState.QUEUED_AUDIO})) + + def ocp_start(self): + """Emit OCP status events for play""" + super().ocp_start() + self.bus.emit(Message("ovos.common_play.track.state", + {"state": TrackState.PLAYING_AUDIO})) + + +class RemoteAudioBackend(AudioBackend): + """Base class for remote audio backends. + + RemoteAudioBackends will always be checked after the normal + AudioBackends to make playback start locally by default. + + An example of a RemoteAudioBackend would be things like mopidy servers, etc. + """ + + +class VideoBackend(MediaBackend): + """ for audio""" + def load_track(self, uri): + super().load_track(uri) + self.bus.emit(Message("ovos.common_play.track.state", + {"state": TrackState.QUEUED_VIDEO})) + + def ocp_start(self): + """Emit OCP status events for play""" + super().ocp_start() + self.bus.emit(Message("ovos.common_play.track.state", + {"state": TrackState.PLAYING_VIDEO})) + + +class RemoteVideoBackend(VideoBackend): + """Base class for remote audio backends. + + RemoteAudioBackends will always be checked after the normal + VideoBackends to make playback start locally by default. + + An example of a RemoteVideoBackend would be things like Chromecasts, etc. + """ + + +class VideoWebBackend(MediaBackend): + """ for web pages""" + + def load_track(self, uri): + super().load_track(uri) + self.bus.emit(Message("ovos.common_play.track.state", + {"state": TrackState.QUEUED_WEBVIEW})) + + def ocp_start(self): + """Emit OCP status events for play""" + super().ocp_start() + self.bus.emit(Message("ovos.common_play.track.state", + {"state": TrackState.PLAYING_WEBVIEW})) + + +class RemoteWebBackend(VideoBackend): + """Base class for remote web backends. + + RemoteAudioBackends will always be checked after the normal + VideoBackends to make playback start locally by default. + + An example of a RemoteVideoBackend would be + things that can render a webpage in a different machine + """ From 1f022c4e651109ae90ea55072f21fdd18745e829 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Mon, 8 Jan 2024 01:59:18 +0000 Subject: [PATCH 02/10] feat/OCP_backends --- ovos_plugin_manager/templates/media.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ovos_plugin_manager/templates/media.py b/ovos_plugin_manager/templates/media.py index a522f509..93b64872 100644 --- a/ovos_plugin_manager/templates/media.py +++ b/ovos_plugin_manager/templates/media.py @@ -228,7 +228,7 @@ class RemoteAudioBackend(AudioBackend): class VideoBackend(MediaBackend): - """ for audio""" + """ for video""" def load_track(self, uri): super().load_track(uri) self.bus.emit(Message("ovos.common_play.track.state", @@ -244,7 +244,7 @@ def ocp_start(self): class RemoteVideoBackend(VideoBackend): """Base class for remote audio backends. - RemoteAudioBackends will always be checked after the normal + RemoteVideoBackends will always be checked after the normal VideoBackends to make playback start locally by default. An example of a RemoteVideoBackend would be things like Chromecasts, etc. @@ -266,12 +266,12 @@ def ocp_start(self): {"state": TrackState.PLAYING_WEBVIEW})) -class RemoteWebBackend(VideoBackend): +class RemoteWebBackend(VideoWebBackend): """Base class for remote web backends. - RemoteAudioBackends will always be checked after the normal + RemoteWebBackends will always be checked after the normal VideoBackends to make playback start locally by default. - An example of a RemoteVideoBackend would be + An example of a RemoteWebBackend would be things that can render a webpage in a different machine """ From 0d146794a9b14399de88c1112371086eebc16ac5 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Mon, 8 Jan 2024 02:01:19 +0000 Subject: [PATCH 03/10] deprecation logs --- ovos_plugin_manager/audio.py | 4 ++++ ovos_plugin_manager/templates/audio.py | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/ovos_plugin_manager/audio.py b/ovos_plugin_manager/audio.py index 04d582a3..44855850 100644 --- a/ovos_plugin_manager/audio.py +++ b/ovos_plugin_manager/audio.py @@ -2,6 +2,10 @@ from ovos_utils.log import LOG from ovos_utils.messagebus import get_mycroft_bus from ovos_config import Configuration +from ovos_utils.log import log_deprecation + +log_deprecation("ovos_plugin_manager.audio has been deprecated on ovos-audio, " + "move to ovos_plugin_manager.media", "0.1.0") def find_plugins(*args, **kwargs): diff --git a/ovos_plugin_manager/templates/audio.py b/ovos_plugin_manager/templates/audio.py index 3bd0d2b1..0b448d00 100644 --- a/ovos_plugin_manager/templates/audio.py +++ b/ovos_plugin_manager/templates/audio.py @@ -8,6 +8,10 @@ from ovos_utils import classproperty from ovos_utils.messagebus import FakeBus from ovos_utils.process_utils import RuntimeRequirements +from ovos_utils.log import log_deprecation + +log_deprecation("ovos_plugin_manager.templates.audio has been deprecated on ovos-audio, " + "move to ovos_plugin_manager.templates.media", "0.1.0") class AudioBackend(metaclass=ABCMeta): From dad36dd42090b28acb6d70f5a20d3e2dd06d91cd Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Mon, 8 Jan 2024 04:58:23 +0000 Subject: [PATCH 04/10] refactor/ovos_media --- ovos_plugin_manager/audio.py | 2 +- ovos_plugin_manager/ocp.py | 7 +++++++ ovos_plugin_manager/templates/tts.py | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ovos_plugin_manager/audio.py b/ovos_plugin_manager/audio.py index 44855850..a60ff0db 100644 --- a/ovos_plugin_manager/audio.py +++ b/ovos_plugin_manager/audio.py @@ -1,6 +1,6 @@ from ovos_plugin_manager.utils import PluginConfigTypes, PluginTypes from ovos_utils.log import LOG -from ovos_utils.messagebus import get_mycroft_bus +from ovos_bus_client.util import get_mycroft_bus from ovos_config import Configuration from ovos_utils.log import log_deprecation diff --git a/ovos_plugin_manager/ocp.py b/ovos_plugin_manager/ocp.py index 5b88976f..8f5b7bf2 100644 --- a/ovos_plugin_manager/ocp.py +++ b/ovos_plugin_manager/ocp.py @@ -1,6 +1,7 @@ from ovos_plugin_manager.utils import PluginTypes, PluginConfigTypes from ovos_plugin_manager.templates.ocp import OCPStreamExtractor from ovos_utils.log import LOG +from functools import lru_cache def find_plugins(*args, **kwargs): @@ -92,3 +93,9 @@ def extract_stream(self, uri, video=True): # no extractor available, return raw url return meta or {"uri": uri} + + +@lru_cache() # to avoid loading StreamHandler more than once +def available_extractors(): + return ["/", "http:", "https:", "file:"] + \ + [f"{sei}//" for sei in StreamHandler().supported_seis] diff --git a/ovos_plugin_manager/templates/tts.py b/ovos_plugin_manager/templates/tts.py index 78aa4094..8f6edcb2 100644 --- a/ovos_plugin_manager/templates/tts.py +++ b/ovos_plugin_manager/templates/tts.py @@ -37,8 +37,8 @@ from ovos_plugin_manager.utils.config import get_plugin_config from ovos_plugin_manager.utils.tts_cache import TextToSpeechCache, hash_sentence from ovos_utils import classproperty -from ovos_utils import resolve_resource_file -from ovos_utils.enclosure.api import EnclosureAPI +from ovos_utils.file_utils import resolve_resource_file +from ovos_bus_client.apis.enclosure import EnclosureAPI from ovos_utils.file_utils import get_cache_directory from ovos_utils.lang.visimes import VISIMES from ovos_utils.log import LOG From 4b6ab49e6878482d6a9e2257dd72f7ae2c94b390 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Mon, 8 Jan 2024 05:22:16 +0000 Subject: [PATCH 05/10] deprecation --- ovos_plugin_manager/templates/audio.py | 169 ++++++------------------- 1 file changed, 36 insertions(+), 133 deletions(-) diff --git a/ovos_plugin_manager/templates/audio.py b/ovos_plugin_manager/templates/audio.py index 0b448d00..bd612f3f 100644 --- a/ovos_plugin_manager/templates/audio.py +++ b/ovos_plugin_manager/templates/audio.py @@ -3,18 +3,17 @@ These classes can be used to create an Audioservice plugin extending OpenVoiceOS's media playback options. """ -from abc import ABCMeta, abstractmethod - +from ovos_plugin_manager.templates.media import AudioBackend as _AB from ovos_utils import classproperty -from ovos_utils.messagebus import FakeBus -from ovos_utils.process_utils import RuntimeRequirements from ovos_utils.log import log_deprecation +from ovos_utils.process_utils import RuntimeRequirements +from ovos_bus_client.message import Message log_deprecation("ovos_plugin_manager.templates.audio has been deprecated on ovos-audio, " "move to ovos_plugin_manager.templates.media", "0.1.0") -class AudioBackend(metaclass=ABCMeta): +class AudioBackend(_AB): """Base class for all audio backend implementations. Arguments: @@ -22,12 +21,6 @@ class AudioBackend(metaclass=ABCMeta): bus (MessageBusClient): OpenVoiceOS messagebus emitter """ - def __init__(self, config=None, bus=None): - self._track_start_callback = None - self.supports_mime_hints = False - self.config = config or {} - self.bus = bus or FakeBus() - @classproperty def runtime_requirements(self): """ skill developers should override this if they do not require connectivity @@ -63,143 +56,53 @@ def runtime_requirements(self): no_internet_fallback=True, no_network_fallback=True) - @property - def playback_time(self): - return 0 - - @abstractmethod - def supported_uris(self): - """List of supported uri types. - - Returns: - list: Supported uri's - """ - - @abstractmethod + # methods below deprecated and handled by OCP directly + # playlists are no longer managed plugin side + # this is just a compat layer forwarding commands to OCP def clear_list(self): """Clear playlist.""" + msg = Message('ovos.common_play.playlist.clear') + self.bus.emit(msg) - @abstractmethod def add_list(self, tracks): """Add tracks to backend's playlist. Arguments: tracks (list): list of tracks. """ - - @abstractmethod - def play(self, repeat=False): - """Start playback. - - Starts playing the first track in the playlist and will contiune - until all tracks have been played. - - Arguments: - repeat (bool): Repeat playlist, defaults to False - """ - - @abstractmethod - def stop(self): - """Stop playback. - - Stops the current playback. - - Returns: - bool: True if playback was stopped, otherwise False - """ - - def set_track_start_callback(self, callback_func): - """Register callback on track start. - - This method should be called as each track in a playlist is started. - """ - self._track_start_callback = callback_func - - def pause(self): - """Pause playback. - - Stops playback but may be resumed at the exact position the pause - occured. - """ - - def resume(self): - """Resume paused playback. - - Resumes playback after being paused. - """ + tracks = tracks or [] + if isinstance(tracks, (str, tuple)): + tracks = [tracks] + elif not isinstance(tracks, list): + raise ValueError + tracks = [self._uri2meta(t) for t in tracks] + msg = Message('ovos.common_play.playlist.queue', + {'tracks': tracks}) + self.bus.emit(msg) + + @staticmethod + def _uri2meta(uri): + if isinstance(uri, list): + uri = uri[0] + try: + from ovos_ocp_files_plugin.plugin import OCPFilesMetadataExtractor + return OCPFilesMetadataExtractor.extract_metadata(uri) + except: + meta = {"uri": uri, + "skill_id": "mycroft.audio_interface", + "playback": 2, # PlaybackType.AUDIO, # TODO mime type check + "status": 33 # TrackState.QUEUED_AUDIO + } + meta["skill_id"] = "mycroft.audio_interface" + return meta def next(self): """Skip to next track in playlist.""" + self.bus.emit(Message("ovos.common_play.next")) def previous(self): """Skip to previous track in playlist.""" - - def lower_volume(self): - """Lower volume. - - This method is used to implement audio ducking. It will be called when - OpenVoiceOS is listening or speaking to make sure the media playing isn't - interfering. - """ - - def restore_volume(self): - """Restore normal volume. - - Called when to restore the playback volume to previous level after - OpenVoiceOS has lowered it using lower_volume(). - """ - - def get_track_length(self): - """ - getting the duration of the audio in milliseconds - NOTE: not yet supported by mycroft-core - """ - - def get_track_position(self): - """ - get current position in milliseconds - NOTE: not yet supported by mycroft-core - """ - - def set_track_position(self, milliseconds): - """ - go to position in milliseconds - NOTE: not yet supported by mycroft-core - Args: - milliseconds (int): number of milliseconds of final position - """ - - def seek_forward(self, seconds=1): - """Skip X seconds. - - Arguments: - seconds (int): number of seconds to seek, if negative rewind - """ - - def seek_backward(self, seconds=1): - """Rewind X seconds. - - Arguments: - seconds (int): number of seconds to seek, if negative jump forward. - """ - - def track_info(self): - """Get info about current playing track. - - Returns: - dict: Track info containing atleast the keys artist and album. - """ - ret = {} - ret['artist'] = '' - ret['album'] = '' - return ret - - def shutdown(self): - """Perform clean shutdown. - - Implements any audio backend specific shutdown procedures. - """ - self.stop() + self.bus.emit(Message("ovos.common_play.previous")) class RemoteAudioBackend(AudioBackend): From 2620466a2900231dcb6f63abdb4c43ee69904649 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Mon, 8 Jan 2024 05:26:07 +0000 Subject: [PATCH 06/10] optimize --- ovos_plugin_manager/ocp.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ovos_plugin_manager/ocp.py b/ovos_plugin_manager/ocp.py index 8f5b7bf2..f4e8ab91 100644 --- a/ovos_plugin_manager/ocp.py +++ b/ovos_plugin_manager/ocp.py @@ -96,6 +96,11 @@ def extract_stream(self, uri, video=True): @lru_cache() # to avoid loading StreamHandler more than once +def load_stream_extractors(): + return StreamHandler() + + def available_extractors(): + xtract = load_stream_extractors() return ["/", "http:", "https:", "file:"] + \ - [f"{sei}//" for sei in StreamHandler().supported_seis] + [f"{sei}//" for sei in xtract.supported_seis] From f8eac36f2b56277ab00188cd1228024a1dd01ed6 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Mon, 8 Jan 2024 06:28:21 +0000 Subject: [PATCH 07/10] tests --- .github/workflows/unit_tests.yml | 6 +++--- requirements/requirements.txt | 4 ++-- test/unittests/test_audio.py | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 62da0901..89dc6e84 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -46,12 +46,12 @@ jobs: sudo apt-get update sudo apt install python3-dev python -m pip install build wheel - - name: Install core repo - run: | - pip install . - name: Install test dependencies run: | pip install -r requirements/test.txt + - name: Install core repo + run: | + pip install . - name: Run unittests run: | pytest --cov=ovos_plugin_manager --cov-report xml test/unittests diff --git a/requirements/requirements.txt b/requirements/requirements.txt index b10d2770..3f1f5ef2 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,5 +1,5 @@ -ovos-utils < 0.2.0, >=0.0.37 -ovos-bus-client < 0.2.0, >=0.0.8 +ovos-utils < 0.2.0, >=0.1.0a8 +ovos-bus-client < 0.2.0, >=0.0.9a3 ovos-config < 0.2.0, >=0.0.12 combo_lock~=0.2 requests~=2.26 diff --git a/test/unittests/test_audio.py b/test/unittests/test_audio.py index 1ad550ff..369713f2 100644 --- a/test/unittests/test_audio.py +++ b/test/unittests/test_audio.py @@ -6,11 +6,11 @@ class TestAudioTemplate(unittest.TestCase): def test_audio_backend(self): - from ovos_plugin_manager.templates.audio import AudioBackend + from ovos_plugin_manager.templates.media import AudioBackend # TODO def test_remote_audio_backend(self): - from ovos_plugin_manager.templates.audio import RemoteAudioBackend + from ovos_plugin_manager.templates.media import RemoteAudioBackend class TestAudio(unittest.TestCase): From 85b545b349dc72a3f98155ea2454971abcb51820 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Mon, 8 Jan 2024 06:32:31 +0000 Subject: [PATCH 08/10] tests --- ovos_plugin_manager/templates/audio.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ovos_plugin_manager/templates/audio.py b/ovos_plugin_manager/templates/audio.py index bd612f3f..fc249112 100644 --- a/ovos_plugin_manager/templates/audio.py +++ b/ovos_plugin_manager/templates/audio.py @@ -3,11 +3,13 @@ These classes can be used to create an Audioservice plugin extending OpenVoiceOS's media playback options. """ +from ovos_bus_client.message import Message + from ovos_plugin_manager.templates.media import AudioBackend as _AB from ovos_utils import classproperty from ovos_utils.log import log_deprecation +from ovos_utils.ocp import PlaybackType, TrackState from ovos_utils.process_utils import RuntimeRequirements -from ovos_bus_client.message import Message log_deprecation("ovos_plugin_manager.templates.audio has been deprecated on ovos-audio, " "move to ovos_plugin_manager.templates.media", "0.1.0") @@ -90,10 +92,9 @@ def _uri2meta(uri): except: meta = {"uri": uri, "skill_id": "mycroft.audio_interface", - "playback": 2, # PlaybackType.AUDIO, # TODO mime type check - "status": 33 # TrackState.QUEUED_AUDIO + "playback": PlaybackType.AUDIO, # TODO mime type check + "status": TrackState.QUEUED_AUDIO, } - meta["skill_id"] = "mycroft.audio_interface" return meta def next(self): From fd794186e875d7c0a9732a0869b2a74f922a617a Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Mon, 8 Jan 2024 06:39:33 +0000 Subject: [PATCH 09/10] tests --- ovos_plugin_manager/ocp.py | 42 ++++++++++++++++---------- ovos_plugin_manager/templates/audio.py | 2 +- ovos_plugin_manager/templates/media.py | 12 ++++---- ovos_plugin_manager/utils/__init__.py | 5 ++- 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/ovos_plugin_manager/ocp.py b/ovos_plugin_manager/ocp.py index f4e8ab91..5749cae5 100644 --- a/ovos_plugin_manager/ocp.py +++ b/ovos_plugin_manager/ocp.py @@ -1,32 +1,42 @@ -from ovos_plugin_manager.utils import PluginTypes, PluginConfigTypes +from ovos_plugin_manager.utils import PluginTypes from ovos_plugin_manager.templates.ocp import OCPStreamExtractor +from ovos_plugin_manager.templates.media import AudioPlayerBackend, VideoPlayerBackend, WebPlayerBackend from ovos_utils.log import LOG from functools import lru_cache +from ovos_plugin_manager.utils import find_plugins -def find_plugins(*args, **kwargs): - # TODO: Deprecate in 0.1.0 - LOG.warning("This reference is deprecated. " - "Import from ovos_plugin_manager.utils directly") - from ovos_plugin_manager.utils import find_plugins - return find_plugins(*args, **kwargs) +def find_ocp_plugins() -> dict: + """ + Find all installed plugins + @return: dict plugin names to entrypoints + """ + return find_plugins(PluginTypes.STREAM_EXTRACTOR) -def load_plugin(*args, **kwargs): - # TODO: Deprecate in 0.1.0 - LOG.warning("This reference is deprecated. " - "Import from ovos_plugin_manager.utils directly") - from ovos_plugin_manager.utils import load_plugin - return load_plugin(*args, **kwargs) +def find_ocp_audio_plugins() -> dict: + """ + Find all installed plugins + @return: dict plugin names to entrypoints + """ + return find_plugins(PluginTypes.AUDIO_PLAYER) -def find_ocp_plugins() -> dict: + +def find_ocp_video_plugins() -> dict: """ Find all installed plugins @return: dict plugin names to entrypoints """ - from ovos_plugin_manager.utils import find_plugins - return find_plugins(PluginTypes.STREAM_EXTRACTOR) + return find_plugins(PluginTypes.VIDEO_PLAYER) + + +def find_ocp_web_plugins() -> dict: + """ + Find all installed plugins + @return: dict plugin names to entrypoints + """ + return find_plugins(PluginTypes.WEB_PLAYER) class StreamHandler: diff --git a/ovos_plugin_manager/templates/audio.py b/ovos_plugin_manager/templates/audio.py index fc249112..fbb1e330 100644 --- a/ovos_plugin_manager/templates/audio.py +++ b/ovos_plugin_manager/templates/audio.py @@ -5,7 +5,7 @@ """ from ovos_bus_client.message import Message -from ovos_plugin_manager.templates.media import AudioBackend as _AB +from ovos_plugin_manager.templates.media import AudioPlayerBackend as _AB from ovos_utils import classproperty from ovos_utils.log import log_deprecation from ovos_utils.ocp import PlaybackType, TrackState diff --git a/ovos_plugin_manager/templates/media.py b/ovos_plugin_manager/templates/media.py index 93b64872..bd1c385a 100644 --- a/ovos_plugin_manager/templates/media.py +++ b/ovos_plugin_manager/templates/media.py @@ -202,7 +202,7 @@ def shutdown(self): self.stop() -class AudioBackend(MediaBackend): +class AudioPlayerBackend(MediaBackend): """ for audio""" def load_track(self, uri): @@ -217,7 +217,7 @@ def ocp_start(self): {"state": TrackState.PLAYING_AUDIO})) -class RemoteAudioBackend(AudioBackend): +class RemoteAudioPlayerBackend(AudioPlayerBackend): """Base class for remote audio backends. RemoteAudioBackends will always be checked after the normal @@ -227,7 +227,7 @@ class RemoteAudioBackend(AudioBackend): """ -class VideoBackend(MediaBackend): +class VideoPlayerBackend(MediaBackend): """ for video""" def load_track(self, uri): super().load_track(uri) @@ -241,7 +241,7 @@ def ocp_start(self): {"state": TrackState.PLAYING_VIDEO})) -class RemoteVideoBackend(VideoBackend): +class RemoteVideoPlayerBackend(VideoPlayerBackend): """Base class for remote audio backends. RemoteVideoBackends will always be checked after the normal @@ -251,7 +251,7 @@ class RemoteVideoBackend(VideoBackend): """ -class VideoWebBackend(MediaBackend): +class WebPlayerBackend(MediaBackend): """ for web pages""" def load_track(self, uri): @@ -266,7 +266,7 @@ def ocp_start(self): {"state": TrackState.PLAYING_WEBVIEW})) -class RemoteWebBackend(VideoWebBackend): +class RemoteWebPlayerBackend(WebPlayerBackend): """Base class for remote web backends. RemoteWebBackends will always be checked after the normal diff --git a/ovos_plugin_manager/utils/__init__.py b/ovos_plugin_manager/utils/__init__.py index 26f3bd51..cfdfe09c 100644 --- a/ovos_plugin_manager/utils/__init__.py +++ b/ovos_plugin_manager/utils/__init__.py @@ -30,7 +30,7 @@ class PluginTypes(str, Enum): VAD = "ovos.plugin.VAD" PHONEME = "ovos.plugin.g2p" AUDIO2IPA = "ovos.plugin.audio2ipa" - AUDIO = 'mycroft.plugin.audioservice' + AUDIO = 'mycroft.plugin.audioservice' # DEPRECATED STT = 'mycroft.plugin.stt' TTS = 'mycroft.plugin.tts' WAKEWORD = 'mycroft.plugin.wake_word' @@ -52,6 +52,9 @@ class PluginTypes(str, Enum): TOKENIZATION = "intentbox.tokenization" POSTAG = "intentbox.postag" STREAM_EXTRACTOR = "ovos.ocp.extractor" + AUDIO_PLAYER = "opm.media.audio" + VIDEO_PLAYER = "opm.media.video" + WEB_PLAYER = "opm.media.web" PERSONA = "opm.plugin.persona" # personas are a dict, they have no config because they ARE a config From 926fe1a9b31b3690a71273946fd6d524e681a47d Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Mon, 8 Jan 2024 06:43:37 +0000 Subject: [PATCH 10/10] tests --- ovos_plugin_manager/utils/__init__.py | 3 +++ test/unittests/test_audio.py | 4 ++-- test/unittests/test_ocp.py | 5 +---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ovos_plugin_manager/utils/__init__.py b/ovos_plugin_manager/utils/__init__.py index cfdfe09c..441390bf 100644 --- a/ovos_plugin_manager/utils/__init__.py +++ b/ovos_plugin_manager/utils/__init__.py @@ -89,6 +89,9 @@ class PluginConfigTypes(str, Enum): TOKENIZATION = "intentbox.tokenization.config" POSTAG = "intentbox.postag.config" STREAM_EXTRACTOR = "ovos.ocp.extractor.config" + AUDIO_PLAYER = "opm.media.audio.config" + VIDEO_PLAYER = "opm.media.video.config" + WEB_PLAYER = "opm.media.web.config" def find_plugins(plug_type: PluginTypes = None) -> dict: diff --git a/test/unittests/test_audio.py b/test/unittests/test_audio.py index 369713f2..59db48d8 100644 --- a/test/unittests/test_audio.py +++ b/test/unittests/test_audio.py @@ -6,11 +6,11 @@ class TestAudioTemplate(unittest.TestCase): def test_audio_backend(self): - from ovos_plugin_manager.templates.media import AudioBackend + from ovos_plugin_manager.templates.media import AudioPlayerBackend # TODO def test_remote_audio_backend(self): - from ovos_plugin_manager.templates.media import RemoteAudioBackend + from ovos_plugin_manager.templates.media import RemoteAudioPlayerBackend class TestAudio(unittest.TestCase): diff --git a/test/unittests/test_ocp.py b/test/unittests/test_ocp.py index 61cbf058..3305dd43 100644 --- a/test/unittests/test_ocp.py +++ b/test/unittests/test_ocp.py @@ -22,10 +22,7 @@ def test_find_plugins(self, find_plugins): find_ocp_plugins() find_plugins.assert_called_once_with(self.PLUGIN_TYPE) - @patch("ovos_plugin_manager.utils.find_plugins") - def test_stream_handler(self, find_plugins): + def test_stream_handler(self): from ovos_plugin_manager.ocp import StreamHandler handler = StreamHandler() self.assertIsInstance(handler.extractors, dict) - find_plugins.assert_called_once_with(PluginTypes.STREAM_EXTRACTOR) - # TODO: More tests