diff --git a/ovos_workshop/skills/common_play.py b/ovos_workshop/skills/common_play.py index f3bc0f4..1ca34d5 100644 --- a/ovos_workshop/skills/common_play.py +++ b/ovos_workshop/skills/common_play.py @@ -392,14 +392,15 @@ def play_media(self, media, disambiguation=None, playlist=None): # @killable_event("ovos.common_play.stop", react_to_stop=True) def __handle_ocp_play(self, message): + self.activate() + self._playing.set() + self._paused.clear() if self.__playback_handler: params = signature(self.__playback_handler).parameters kwargs = {"message": message} if "message" in params else {} self.__playback_handler(**kwargs) self.bus.emit(Message("ovos.common_play.player.state", {"state": PlayerState.PLAYING})) - self._playing.set() - self._paused.clear() else: LOG.error(f"Playback requested but {self.skill_id} handler not " "implemented") @@ -417,6 +418,7 @@ def __handle_ocp_pause(self, message): "implemented") def __handle_ocp_resume(self, message): + self.activate() self._paused.clear() if self.__resume_handler: params = signature(self.__playback_handler).parameters diff --git a/ovos_workshop/skills/game_skill.py b/ovos_workshop/skills/game_skill.py index ce99a51..04ceb4c 100644 --- a/ovos_workshop/skills/game_skill.py +++ b/ovos_workshop/skills/game_skill.py @@ -124,14 +124,14 @@ def stop(self) -> bool: return True return False - def calc_intent(self, utterance: str, lang: str) -> Optional[Dict[str, str]]: + def calc_intent(self, utterance: str, lang: str, timeout=1.0) -> Optional[Dict[str, str]]: """helper to check what intent would be selected by ovos-core""" # let's see what intent ovos-core will assign to the utterance # NOTE: converse, common_query and fallbacks are not included in this check response = self.bus.wait_for_response(Message("intent.service.intent.get", {"utterance": utterance, "lang": lang}), "intent.service.intent.reply", - timeout=1.0) + timeout=timeout) if not response: return None return response.data["intent"] @@ -183,7 +183,6 @@ def on_game_command(self, utterance: str, lang: str): don't forget to self.speak the game output too! """ - @abc.abstractmethod def on_abandon_game(self): """user abandoned game mid interaction @@ -193,7 +192,7 @@ def on_abandon_game(self): on_game_stop will be called after this handler""" # converse - def skill_will_trigger(self, utterance: str, lang: str, skill_id: Optional[str] = None) -> bool: + def skill_will_trigger(self, utterance: str, lang: str, skill_id: Optional[str] = None, timeout=0.8) -> bool: """helper to check if this skill would be selected by ovos-core with the given utterance useful in converse method @@ -205,7 +204,7 @@ def skill_will_trigger(self, utterance: str, lang: str, skill_id: Optional[str] # determine if an intent from this skill # will be selected by ovos-core id_to_check = skill_id or self.skill_id - intent = self.calc_intent(utterance, lang) + intent = self.calc_intent(utterance, lang, timeout=timeout) skill_id = intent["skill_id"] if intent else "" return skill_id == id_to_check @@ -221,26 +220,44 @@ def _autosave(self): if self.settings.get("auto_save", False) and self.save_is_implemented: self.on_save_game() - def converse(self, message: Message): + def _async_cmd(self, message: Message): + utterance = message.data["utterances"][0] + lang = get_message_lang(message) + self.log.debug(f"Piping utterance to game: {utterance}") + self.on_game_command(utterance, lang) + + def converse(self, message: Message) -> bool: try: + utterance = message.data["utterances"][0] + lang = get_message_lang(message) + # let the user implemented intents do the job if they can handle the utterance + # otherwise pipe utterance to the game handler + if self.skill_will_trigger(utterance, lang): + self.log.debug("Skill intent will trigger, don't pipe utterance to game") + return False + if self.is_paused: + self.log.debug("game is paused") # let ocp_pipeline unpause as appropriate return False - self._autosave() - utterance = message.data["utterances"][0] - lang = get_message_lang(message) - # let the user implemented intents do the job if they can handle the utterance - if self.is_playing and not self.skill_will_trigger(utterance, lang): - # otherwise pipe utterance to the game handler - self.on_game_command(utterance, lang) + try: + self._autosave() + except Exception as e: + self.log.error(f"Autosave failed: {e}") + + if self.is_playing: + # do this async so converse executes faster + self.bus.once(f"{self.skill_id}.game_cmd", self._async_cmd) + self.bus.emit(message.forward(f"{self.skill_id}.game_cmd", message.data)) return True + return False except (KeyError, IndexError) as e: - self.log.error(f"Error processing converse message: {e}") + self.log.error(f"Error processing game converse message: {e}") return False except Exception as e: - self.log.exception(f"Unexpected error in converse: {e}") + self.log.exception(f"Unexpected error in game converse: {e}") return False def handle_deactivate(self, message: Message):