2016-12-09 15:54:25 +00:00
|
|
|
import time
|
2017-04-10 14:20:01 +00:00
|
|
|
from os.path import abspath
|
Initial commit of audio service
Three backends have been added, mopidy, vlc and mpg123. Depending on uri type an apporpriate service is selected when media playback is requested. (for example mopidy service can handle spotify://... and local://...)
A playback Control skill can pause, resume, stop change track, etc any started media. So for example if the NPR news skill used this after starting playing the news the user can say "Hey Mycroft, pause" and the playback will pause. The playback control also handles stuff like lowering the volume of the playback if mycroft is asked another question.
Currently the different backend runs under the playbeck control, this was made most for convenience and the services should be moved in the future.
Usage:
The user needs to import the audioservice interface
`from mycroft.skills.audioservice import AudioService`
and initialize an instance in the skill `initialize` method
`self.audio_service = AudioService(self.emitter)`
Then playing an uri is as simple as
`self.audio_service.play(uri)`
TODO:
* Configuration (Alias for the different backends, service specific config, active services, etc.)
* Manual selection of backend (This is prepared in the audioservice interface biut not implemented)
* More feature complete audio service interface (playback control, get trackname etc)
* Separate audio services from the playback control
* Probably lots more
2016-12-02 06:12:21 +00:00
|
|
|
from mycroft.messagebus.message import Message
|
|
|
|
|
|
|
|
|
2017-04-10 14:20:01 +00:00
|
|
|
def ensure_uri(s):
|
2017-04-11 18:20:45 +00:00
|
|
|
"""
|
|
|
|
Interprete paths as file:// uri's
|
|
|
|
|
|
|
|
Args:
|
|
|
|
s: string to be checked
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
if s is uri, s is returned otherwise file:// is prepended
|
|
|
|
"""
|
2017-04-10 14:20:01 +00:00
|
|
|
if '://' not in s:
|
|
|
|
return 'file://' + abspath(s)
|
|
|
|
else:
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
Initial commit of audio service
Three backends have been added, mopidy, vlc and mpg123. Depending on uri type an apporpriate service is selected when media playback is requested. (for example mopidy service can handle spotify://... and local://...)
A playback Control skill can pause, resume, stop change track, etc any started media. So for example if the NPR news skill used this after starting playing the news the user can say "Hey Mycroft, pause" and the playback will pause. The playback control also handles stuff like lowering the volume of the playback if mycroft is asked another question.
Currently the different backend runs under the playbeck control, this was made most for convenience and the services should be moved in the future.
Usage:
The user needs to import the audioservice interface
`from mycroft.skills.audioservice import AudioService`
and initialize an instance in the skill `initialize` method
`self.audio_service = AudioService(self.emitter)`
Then playing an uri is as simple as
`self.audio_service.play(uri)`
TODO:
* Configuration (Alias for the different backends, service specific config, active services, etc.)
* Manual selection of backend (This is prepared in the audioservice interface biut not implemented)
* More feature complete audio service interface (playback control, get trackname etc)
* Separate audio services from the playback control
* Probably lots more
2016-12-02 06:12:21 +00:00
|
|
|
class AudioService():
|
2017-04-11 18:20:45 +00:00
|
|
|
"""
|
|
|
|
AudioService object for interacting with the audio subsystem
|
|
|
|
|
|
|
|
Args:
|
|
|
|
emitter: eventemitter or websocket object
|
|
|
|
"""
|
Initial commit of audio service
Three backends have been added, mopidy, vlc and mpg123. Depending on uri type an apporpriate service is selected when media playback is requested. (for example mopidy service can handle spotify://... and local://...)
A playback Control skill can pause, resume, stop change track, etc any started media. So for example if the NPR news skill used this after starting playing the news the user can say "Hey Mycroft, pause" and the playback will pause. The playback control also handles stuff like lowering the volume of the playback if mycroft is asked another question.
Currently the different backend runs under the playbeck control, this was made most for convenience and the services should be moved in the future.
Usage:
The user needs to import the audioservice interface
`from mycroft.skills.audioservice import AudioService`
and initialize an instance in the skill `initialize` method
`self.audio_service = AudioService(self.emitter)`
Then playing an uri is as simple as
`self.audio_service.play(uri)`
TODO:
* Configuration (Alias for the different backends, service specific config, active services, etc.)
* Manual selection of backend (This is prepared in the audioservice interface biut not implemented)
* More feature complete audio service interface (playback control, get trackname etc)
* Separate audio services from the playback control
* Probably lots more
2016-12-02 06:12:21 +00:00
|
|
|
def __init__(self, emitter):
|
|
|
|
self.emitter = emitter
|
2017-07-30 07:02:07 +00:00
|
|
|
self.emitter.on('mycroft.audio.service.track_info_reply',
|
|
|
|
self._track_info)
|
2016-12-09 15:54:25 +00:00
|
|
|
self.info = None
|
|
|
|
|
|
|
|
def _track_info(self, message=None):
|
2017-04-11 18:20:45 +00:00
|
|
|
"""
|
|
|
|
Handler for catching returning track info
|
|
|
|
"""
|
2016-12-18 08:43:55 +00:00
|
|
|
self.info = message.data
|
Initial commit of audio service
Three backends have been added, mopidy, vlc and mpg123. Depending on uri type an apporpriate service is selected when media playback is requested. (for example mopidy service can handle spotify://... and local://...)
A playback Control skill can pause, resume, stop change track, etc any started media. So for example if the NPR news skill used this after starting playing the news the user can say "Hey Mycroft, pause" and the playback will pause. The playback control also handles stuff like lowering the volume of the playback if mycroft is asked another question.
Currently the different backend runs under the playbeck control, this was made most for convenience and the services should be moved in the future.
Usage:
The user needs to import the audioservice interface
`from mycroft.skills.audioservice import AudioService`
and initialize an instance in the skill `initialize` method
`self.audio_service = AudioService(self.emitter)`
Then playing an uri is as simple as
`self.audio_service.play(uri)`
TODO:
* Configuration (Alias for the different backends, service specific config, active services, etc.)
* Manual selection of backend (This is prepared in the audioservice interface biut not implemented)
* More feature complete audio service interface (playback control, get trackname etc)
* Separate audio services from the playback control
* Probably lots more
2016-12-02 06:12:21 +00:00
|
|
|
|
|
|
|
def play(self, tracks=[], utterance=''):
|
2017-04-10 14:20:01 +00:00
|
|
|
""" Start playback.
|
2017-04-11 18:20:45 +00:00
|
|
|
|
|
|
|
Args:
|
|
|
|
tracks: track uri or list of track uri's
|
|
|
|
utterance: forward utterance for further processing by the
|
|
|
|
audio service.
|
2017-04-10 14:20:01 +00:00
|
|
|
"""
|
2017-04-08 09:28:48 +00:00
|
|
|
if isinstance(tracks, basestring):
|
|
|
|
tracks = [tracks]
|
|
|
|
elif not isinstance(tracks, list):
|
|
|
|
raise ValueError
|
2017-04-10 14:20:01 +00:00
|
|
|
tracks = [ensure_uri(t) for t in tracks]
|
2017-05-25 15:05:38 +00:00
|
|
|
self.emitter.emit(Message('mycroft.audio.service.play',
|
2016-12-18 08:43:55 +00:00
|
|
|
data={'tracks': tracks,
|
|
|
|
'utterance': utterance}))
|
Initial commit of audio service
Three backends have been added, mopidy, vlc and mpg123. Depending on uri type an apporpriate service is selected when media playback is requested. (for example mopidy service can handle spotify://... and local://...)
A playback Control skill can pause, resume, stop change track, etc any started media. So for example if the NPR news skill used this after starting playing the news the user can say "Hey Mycroft, pause" and the playback will pause. The playback control also handles stuff like lowering the volume of the playback if mycroft is asked another question.
Currently the different backend runs under the playbeck control, this was made most for convenience and the services should be moved in the future.
Usage:
The user needs to import the audioservice interface
`from mycroft.skills.audioservice import AudioService`
and initialize an instance in the skill `initialize` method
`self.audio_service = AudioService(self.emitter)`
Then playing an uri is as simple as
`self.audio_service.play(uri)`
TODO:
* Configuration (Alias for the different backends, service specific config, active services, etc.)
* Manual selection of backend (This is prepared in the audioservice interface biut not implemented)
* More feature complete audio service interface (playback control, get trackname etc)
* Separate audio services from the playback control
* Probably lots more
2016-12-02 06:12:21 +00:00
|
|
|
|
2017-04-10 14:20:01 +00:00
|
|
|
def next(self):
|
|
|
|
""" Change to next track. """
|
2017-05-25 15:05:38 +00:00
|
|
|
self.emitter.emit(Message('mycroft.audio.service.next'))
|
2017-04-10 14:20:01 +00:00
|
|
|
|
|
|
|
def prev(self):
|
|
|
|
""" Change to previous track. """
|
2017-05-25 15:05:38 +00:00
|
|
|
self.emitter.emit(Message('mycroft.audio.service.prev'))
|
2017-04-10 14:20:01 +00:00
|
|
|
|
|
|
|
def pause(self):
|
|
|
|
""" Pause playback. """
|
2017-05-25 15:05:38 +00:00
|
|
|
self.emitter.emit(Message('mycroft.audio.service.pause'))
|
2017-04-10 14:20:01 +00:00
|
|
|
|
|
|
|
def resume(self):
|
|
|
|
""" Resume paused playback. """
|
2017-05-25 15:05:38 +00:00
|
|
|
self.emitter.emit(Message('mycroft.audio.service.resume'))
|
2017-04-10 14:20:01 +00:00
|
|
|
|
2016-12-09 15:54:25 +00:00
|
|
|
def track_info(self):
|
2017-04-11 18:20:45 +00:00
|
|
|
""" Request information of current playing track.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Dict with track info.
|
|
|
|
"""
|
2016-12-09 15:54:25 +00:00
|
|
|
self.info = None
|
2017-05-25 15:05:38 +00:00
|
|
|
self.emitter.emit(Message('mycroft.audio.service.track_info'))
|
2017-07-30 07:02:07 +00:00
|
|
|
wait = 5.0
|
|
|
|
while self.info is None and wait >= 0:
|
2016-12-09 15:54:25 +00:00
|
|
|
time.sleep(0.1)
|
2017-07-30 07:02:07 +00:00
|
|
|
wait -= 0.1
|
|
|
|
|
|
|
|
return self.info or {}
|
2017-07-31 11:36:28 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def is_playing(self):
|
|
|
|
return self.track_info() != {}
|