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
parent
0d8567c9c1
commit
b78988bdfa
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
||||||
|
next track
|
||||||
|
skip
|
|
@ -0,0 +1 @@
|
||||||
|
pause
|
|
@ -0,0 +1 @@
|
||||||
|
play
|
|
@ -0,0 +1 @@
|
||||||
|
previous track
|
|
@ -0,0 +1,2 @@
|
||||||
|
resume
|
||||||
|
unpause
|
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue