Add media base class (#267)

* Add media base class

* Clean up media base vocabulary keywords

* Rename header for common MediaSkill settings to "MediaSkill"

* Stop procedure cleaned up

* mycroft.media.stop now contains information of the message origin, this is used by the handler to make sure the calling skill doesn't stop itself.
* the play() method was renamed before_play() for clarity

* Rename _set_sink to something understandable.
pull/275/head
Åke 2016-07-08 21:06:57 +02:00 committed by Jonathan D'Orleans
parent 0d8567c9c1
commit b78988bdfa
8 changed files with 156 additions and 2 deletions

View File

@ -0,0 +1,141 @@
from os.path import join, dirname
from adapt.intent import IntentBuilder
from mycroft.skills import time_rules
from mycroft.skills.core import MycroftSkill
from mycroft.messagebus.message import Message
from mycroft.configuration import ConfigurationManager
from mycroft.util.log import getLogger
import mycroft.skills.media.mopidy
logger = getLogger(__name__)
__author__ = 'forslund'
class MediaSkill(MycroftSkill):
"""
The MediaSkill class is a base class for media skills containing
vocabulary and intents for the common functions expected by a media
skill. In addition event handlers to lower volume when mycroft starts
to speak and raise it again when (s)he stops.
But wait there is one more thing! A small event emitter and matching
handler to stop media currently playing when new media is started.
"""
def __init__(self, name):
super(MediaSkill, self).__init__(name)
self.isPlaying = False
config = ConfigurationManager.get()
self.base_conf = config.get('MediaSkill')
def initialize(self):
logger.info('Initializing MediaSkill commons')
logger.info('loading vocab files from ' + join(dirname(__file__),
'vocab', self.lang))
self.load_vocab_files(join(dirname(__file__), 'vocab', self.lang))
self._register_common_intents()
self._register_event_handlers()
def _register_common_intents(self):
"""
Register common intents, these include basically all intents
except the intents to start playback.
"""
intent = IntentBuilder('NextIntent').require('NextKeyword')
self.register_intent(intent, self.handle_next)
intent = IntentBuilder('PrevIntent').require('PrevKeyword')
self.register_intent(intent, self.handle_prev)
intent = IntentBuilder('PauseIntent').require('PauseKeyword')
self.register_intent(intent, self.handle_pause)
intent = IntentBuilder('PlayIntent') \
.one_of('PlayKeyword', 'ResumeKeyword')
self.register_intent(intent, self.handle_play)
intent = IntentBuilder('CurrentlyPlayingIntent')\
.require('CurrentlyPlayingKeyword')
self.register_intent(intent, self.handle_currently_playing)
def _register_event_handlers(self):
"""
Register event handlers for stopping currently playing media
when new media is started and handlers for lowering media volume
while mycroft is speaking.
"""
self.emitter.on('mycroft.media.stop', self._media_stop)
self.emitter.on('recognizer_loop:audio_output_start',
self.lower_volume)
self.emitter.on('recognizer_loop:audio_output_end',
self.restore_volume)
def handle_next(self, message):
"""
handle_next() should be implemented by the skill to switch to next
song/channel/video in queue.
"""
logger.debug('handle_next not implemented in ' + self.name)
def handle_prev(self, message):
"""
handle_prev() should be implemented by the skill to switch to
previous song/channel/video in queue
"""
logger.debug('handle_prev not implemented in ' + self.name)
def handle_currently_playing(self, message):
"""
handle_currently_playing() should be implemented to tell the user
what is currently playing
"""
logger.debug('handle_currently_playing not implemented in ' +
self.name)
def before_play(self):
"""
Stop currently playing media before starting the new. This method
should always be called before the skill starts playback.
"""
logger.info('Stopping currently playing media if any')
self.emitter.emit(Message('mycroft.media.stop',
metadata={'origin': self.name}))
def handle_pause(self, message):
""" handle_pause() should pause currently playing media """
logger.debug('handle_pause not implemented in ' + self.name)
def handle_play(self, message):
""" handle_play() generic play handler. Should resume paused media
and/or implement generic playback functionality.
The skill creator should make sure to call before_play() here
if applicable"""
logger.debug('handle_play not implemented in ' + self.name)
def _media_stop(self, message):
""" handler for 'mycroft.media.stop' """
origin = message.metadata.get('origin', '')
if origin != self.name:
self.stop()
def stop(self):
"""
stop() should be implemented to stop currently playing media. This
function will be called by either the general mycroft 'stop'
functionallity or internal message bus communication.
"""
logger.debug('Stop not implemented in ' + self.name)
def lower_volume(self, message):
logger.debug('Lower volume not implemented in ' + self.name)
def restore_volume(self, message):
logger.debug('Restore volume not implemented in ' + self.name)
def _set_output_device(self, message):
""" Selects the output device """
pass

View File

@ -0,0 +1,6 @@
what's currently playing
what is currently playing
what are you playing
What are we listening to
what's playing
what is playing

View File

@ -0,0 +1,2 @@
next track
skip

View File

@ -0,0 +1 @@
pause

View File

@ -0,0 +1 @@
play

View File

@ -0,0 +1 @@
previous track

View File

@ -0,0 +1,2 @@
resume
unpause

View File

@ -1,7 +1,7 @@
{ {
"utterance": "play the news", "utterance": "is there any news",
"intent_type": "NPRNewsIntent", "intent_type": "NPRNewsIntent",
"intent": { "intent": {
"NPRNewsKeyword": "news" "NPRNewsKeyword": "news"
} }
} }