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

feat: save/load game intent #44

Merged
merged 5 commits into from
Dec 18, 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: 2 additions & 0 deletions ocp_pipeline/locale/en-us/load_game.intent
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
load
load [the] game
3 changes: 2 additions & 1 deletion ocp_pipeline/locale/en-us/next.intent
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
(play|go to) next (music|song|track|video|media)
next
next (song|track|music|movie|video|tune)
play next
play next
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
play [the] next (song|track|music|movie|video|tune)
2 changes: 1 addition & 1 deletion ocp_pipeline/locale/en-us/open.intent
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
open (OCP|O C P|common|ovos|open voice os) (player|media player)
open (OCP|O C P|ovos common play|common play|ovos media player|open voice os player) (home screen|home page|homescreen|homepage|menu)
open (OCP|O C P|ovos common play|open voice os common play|common play)
open (media|music|gui|video) (player|catalog|skills|menu|playback)
open [the] (media|music|gui|video) (player|catalog|skills|menu|playback)
2 changes: 1 addition & 1 deletion ocp_pipeline/locale/en-us/pause.intent
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pause
pause (music|song|track|video|media|playback)
pause [the] (music|song|track|video|media|playback|game)
3 changes: 2 additions & 1 deletion ocp_pipeline/locale/en-us/prev.intent
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
(play previous|previous) (music|song|track|video|media)
(play previous|previous|go back)
previous
previous (song|track|music|movie|video|tune)
previous (song|track|music|movie|video|tune)
play [the] previous (song|track|music|movie|video|tune)
2 changes: 1 addition & 1 deletion ocp_pipeline/locale/en-us/read.intent
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
read (book|audiobook|audio book) {query}
read [the] (book|audiobook|audio book) {query}
read {query}
read {query} (book|audiobook|audio book)
2 changes: 1 addition & 1 deletion ocp_pipeline/locale/en-us/resume.intent
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
(unpause|resume)
(unpause|resume|continue|restart) (music|song|track|video|media|playback)
(unpause|resume|continue|restart) [the] (music|song|track|video|media|playback|game)
play
2 changes: 2 additions & 0 deletions ocp_pipeline/locale/en-us/save_game.intent
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
save
save [the] game
48 changes: 47 additions & 1 deletion ocp_pipeline/opm.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class OCPPlayerProxy:
player_state: PlayerState = PlayerState.STOPPED
media_state: MediaState = MediaState.UNKNOWN
media_type: MediaType = MediaType.GENERIC
skill_id: Optional[str] = None


# for easier typing
Expand All @@ -47,7 +48,7 @@ class OCPPlayerProxy:
class OCPPipelineMatcher(ConfidenceMatcherPipeline, OVOSAbstractApplication):
intents = ["play.intent", "open.intent", "media_stop.intent",
"next.intent", "prev.intent", "pause.intent", "play_favorites.intent",
"resume.intent", "like_song.intent"]
"resume.intent", "like_song.intent", "save_game.intent", "load_game.intent"]
intent_matchers = {}
intent_cache = f"{xdg_data_home()}/{get_xdg_base()}/intent_cache"

Expand Down Expand Up @@ -187,6 +188,8 @@ def register_ocp_intents(self):
self.add_event("ocp:media_stop", self.handle_stop_intent, is_intent=True)
self.add_event("ocp:search_error", self.handle_search_error_intent, is_intent=True)
self.add_event("ocp:like_song", self.handle_like_intent, is_intent=True)
self.add_event("ocp:save_game", self.handle_save_intent, is_intent=True)
self.add_event("ocp:load_game", self.handle_load_intent, is_intent=True)

def update_player_proxy(self, player: OCPPlayerProxy):
"""remember OCP session state"""
Expand Down Expand Up @@ -289,6 +292,7 @@ def handle_track_state_update(self, message: Message):
TrackState.PLAYING_MPRIS]:
player = self.get_player(message)
player.player_state = PlayerState.PLAYING
player = self._update_player_skill_id(player, message)
LOG.info(f"Session: {player.session_id} OCP PlayerState: PlayerState.PLAYING")
self.update_player_proxy(player)

Expand All @@ -310,6 +314,7 @@ def handle_player_state_update(self, message: Message):
if mtype is not None:
player.media_type = MediaType(pstate)
LOG.debug(f"Session: {player.session_id} MediaType: {player.media_type}")
player = self._update_player_skill_id(player, message)
self.update_player_proxy(player)

# pipeline
Expand Down Expand Up @@ -347,6 +352,21 @@ def match_high(self, utterances: List[str], lang: str, message: Message = None)

player = self.get_player(message)

if player.media_type == MediaType.GAME:
# if the user is currently playing a game
# disable: next/prev/shuffle/... intents
# enable: load/save intents
game_blacklist = ["next", "prev", "open", "like_song", "play_favorites"]
if match["name"] in game_blacklist:
LOG.info(f'Ignoring OCP intent match {match["name"]}, playing MediaType.GAME')
return None
else:
# if no game is being played, disable game specific intents
game_only = ["save_game"]
if match["name"] in game_only:
LOG.info(f'Ignoring OCP intent match {match["name"]}, not playing MediaType.GAME')
return None

if match["name"] == "play":
utterance = match["entities"].pop("query")
return self._process_play_query(utterance, lang, match)
Expand Down Expand Up @@ -535,6 +555,14 @@ def _normalize_media_enum(m: Union[int, MediaType]):
return e
raise ValueError(f"{m} is not a valid media type")

def handle_save_intent(self, message: Message):
skill_id = self.get_player(message).skill_id
self.bus.emit(message.forward(f"ovos.common_play.{skill_id}.save"))

def handle_load_intent(self, message: Message):
skill_id = self.get_player(message).skill_id
self.bus.emit(message.forward(f"ovos.common_play.{skill_id}.load"))

def handle_play_intent(self, message: Message):

if not len(self.skill_aliases): # skill_id registered when skills load
Expand Down Expand Up @@ -574,6 +602,8 @@ def handle_play_intent(self, message: Message):

# ovos-PHAL-plugin-mk1 will display music icon in response to play message
player = self.get_player(message)
player.skill_id = best.skill_id
self.update_player_proxy(player)
if not player.ocp_available:
self.legacy_play(results, query, message=message)
else:
Expand Down Expand Up @@ -603,6 +633,7 @@ def handle_stop_intent(self, message: Message):
self.ocp_api.stop(source_message=message)
player = self.get_player(message)
player.player_state = PlayerState.STOPPED
player.skill_id = None
self.update_player_proxy(player)

def handle_next_intent(self, message: Message):
Expand Down Expand Up @@ -633,6 +664,7 @@ def handle_pause_intent(self, message: Message):
self.ocp_api.pause(source_message=message)
player = self.get_player(message)
player.player_state = PlayerState.PAUSED
player = self._update_player_skill_id(player, message)
self.update_player_proxy(player)

def handle_resume_intent(self, message: Message):
Expand All @@ -645,6 +677,7 @@ def handle_resume_intent(self, message: Message):
self.ocp_api.resume(source_message=message)
player = self.get_player(message)
player.player_state = PlayerState.PLAYING
player = self._update_player_skill_id(player, message)
self.update_player_proxy(player)

def handle_search_error_intent(self, message: Message):
Expand Down Expand Up @@ -833,6 +866,13 @@ def get_player(self, message: Optional[Message] = None, timeout=1) -> OCPPlayerP
player = self._player_sync(player, message, timeout)
return player

@staticmethod
def _update_player_skill_id(player, message):
skill_id = message.data.get("skill_id") or message.context.get("skill_id")
if skill_id and skill_id != OCP_ID:
player.skill_id = skill_id
return player

@staticmethod
def normalize_results(results: RawResultsList) -> NormalizedResultsList:
# support Playlist and MediaEntry objects in tracks
Expand Down Expand Up @@ -1055,6 +1095,7 @@ def legacy_play(self, results: NormalizedResultsList, phrase="",
playing = True
self.legacy_api.play(real_uri, utterance=phrase, source_message=message)
player.player_state = PlayerState.PLAYING
player.skill_id = r.skill_id
self.update_player_proxy(player)
else:
self.legacy_api.queue(real_uri, source_message=message)
Expand All @@ -1064,34 +1105,39 @@ def _handle_legacy_audio_stop(self, message: Message):
if not player.ocp_available:
player.player_state = PlayerState.STOPPED
player.media_state = MediaState.NO_MEDIA
player.skill_id = None
self.update_player_proxy(player)

def _handle_legacy_audio_pause(self, message: Message):
player = self.get_player(message)
if not player.ocp_available and player.player_state == PlayerState.PLAYING:
player.player_state = PlayerState.PAUSED
player.media_state = MediaState.LOADED_MEDIA
player = self._update_player_skill_id(player, message)
self.update_player_proxy(player)

def _handle_legacy_audio_resume(self, message: Message):
player = self.get_player(message)
if not player.ocp_available and player.player_state == PlayerState.PAUSED:
player.player_state = PlayerState.PLAYING
player.media_state = MediaState.LOADED_MEDIA
player = self._update_player_skill_id(player, message)
self.update_player_proxy(player)

def _handle_legacy_audio_start(self, message: Message):
player = self.get_player(message)
if not player.ocp_available:
player.player_state = PlayerState.PLAYING
player.media_state = MediaState.LOADED_MEDIA
player = self._update_player_skill_id(player, message)
self.update_player_proxy(player)

def _handle_legacy_audio_end(self, message: Message):
player = self.get_player(message)
if not player.ocp_available:
player.player_state = PlayerState.STOPPED
player.media_state = MediaState.END_OF_MEDIA
player.skill_id = None
self.update_player_proxy(player)

@classmethod
Expand Down
5 changes: 2 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
ovos-workshop>=0.1.7,<4.0.0
ovos-classifiers
ovos-utils>=0.3.5,<1.0.0
ovos-plugin-manager>=0.5.0,<1.0.0
langcodes
ovos-utils[extras]>=0.3.5,<1.0.0
ovos-plugin-manager>=0.5.0,<1.0.0
88 changes: 49 additions & 39 deletions translations/en-us/intents.json
Original file line number Diff line number Diff line change
@@ -1,63 +1,73 @@
{
"play.intent": [
"(play|start) {query}",
"search (common play|ocp|ovos common play|O C P) for {query}",
"search (ovos|open voice os) media for {query}",
"search {query} (in|on) (common play|ocp|ovos common play|O C P)",
"search {query} (in|on) (ovos|open voice os) media"
"featured.intent": [
"(open|show|display) (featured|) {media} (catalog|collection|playlist)",
"(open|show|display) featured {media}"
],
"like_song.intent": [
"i like (that|this|it)",
"i like (that|this)(song|music|track|jam|sound)",
"(good|nice|great|amazing|awesome|cool) (song|music|track|jam|sound)",
"(that|this|it) is a (good|nice|great|amazing|awesome|cool) (song|music|track|jam|sound)"
"(that|this|it) is a (good|nice|great|amazing|awesome|cool) (song|music|track|jam|sound)",
"i like (that|this)(song|music|track|jam|sound)",
"i like (that|this|it)"
],
"load_game.intent": [
"load",
"load [the] game"
],
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
"media_stop.intent": [
"stop",
"stop (playback|media|media playback|music|movie|movies|noise)",
"stop everything"
],
"next.intent": [
"(next|skip)",
"(next|skip) (music|song|track|video|media)",
"(play|go to) next (music|song|track|video|media)",
"play next",
"next",
"next (song|track|music|movie|video|tune)"
"next (song|track|music|movie|video|tune)",
"play [the] next (song|track|music|movie|video|tune)",
"play next"
],
"resume.intent": [
"(unpause|resume)",
"(unpause|resume|continue|restart) (music|song|track|video|media|playback)",
"play"
"open.intent": [
"open (OCP|O C P|common|ovos|open voice os) (player|media player)",
"open (OCP|O C P|ovos common play|common play|ovos media player|open voice os player) (home screen|home page|homescreen|homepage|menu)",
"open (OCP|O C P|ovos common play|open voice os common play|common play)",
"open [the] (media|music|gui|video) (player|catalog|skills|menu|playback)"
],
"read.intent": [
"read (book|audiobook|audio book) {query}",
"read {query}",
"read {query} (book|audiobook|audio book)"
"pause.intent": [
"pause",
"pause [the] (music|song|track|video|media|playback|game)"
],
"play.intent": [
"(play|start) {query}",
"search (common play|ocp|ovos common play|O C P) for {query}",
"search (ovos|open voice os) media for {query}",
"search {query} (in|on) (common play|ocp|ovos common play|O C P)",
"search {query} (in|on) (ovos|open voice os) media"
],
"play_favorites.intent": [
"(play|start) (favorite|liked) (tracks|song|songs|music|jam|jams)",
"(play|start) my (favorite|liked) (tracks|song|songs|music|jam|jams)"
],
"prev.intent": [
"(play previous|go back one) (music|song|track|video|media)",
"(play previous|previous) (music|song|track|video|media)",
"(play previous|previous|go back)",
"play [the] previous (song|track|music|movie|video|tune)",
"previous",
"previous (song|track|music|movie|video|tune)"
],
"pause.intent": [
"pause",
"pause (music|song|track|video|media|playback)"
],
"open.intent": [
"open (OCP|O C P|common|ovos|open voice os) (player|media player)",
"open (OCP|O C P|ovos common play|common play|ovos media player|open voice os player) (home screen|home page|homescreen|homepage|menu)",
"open (OCP|O C P|ovos common play|open voice os common play|common play)",
"open (media|music|gui|video) (player|catalog|skills|menu|playback)"
],
"featured.intent": [
"(open|show|display) (featured|) {media} (catalog|collection|playlist)",
"(open|show|display) featured {media}"
"read.intent": [
"read [the] (book|audiobook|audio book) {query}",
"read {query}",
"read {query} (book|audiobook|audio book)"
],
"play_favorites.intent": [
"(play|start) my (favorite|liked) (tracks|song|songs|music|jam|jams)",
"(play|start) (favorite|liked) (tracks|song|songs|music|jam|jams)"
"resume.intent": [
"(unpause|resume)",
"(unpause|resume|continue|restart) [the] (music|song|track|video|media|playback|game)",
"play"
],
"media_stop.intent": [
"stop",
"stop (playback|media|media playback|music|movie|movies|noise)",
"stop everything"
"save_game.intent": [
"save",
"save [the] game"
]
}
Loading