2017-10-04 06:28:44 +00:00
|
|
|
# Copyright 2017 Mycroft AI Inc.
|
2017-02-09 11:09:56 +00:00
|
|
|
#
|
2017-10-04 06:28:44 +00:00
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
2017-02-09 11:09:56 +00:00
|
|
|
#
|
2017-10-04 06:28:44 +00:00
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
2017-02-09 11:09:56 +00:00
|
|
|
#
|
2017-10-04 06:28:44 +00:00
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
2017-02-09 11:09:56 +00:00
|
|
|
#
|
2017-09-18 19:14:21 +00:00
|
|
|
import imp
|
2017-02-09 11:09:56 +00:00
|
|
|
import json
|
|
|
|
import sys
|
|
|
|
import time
|
|
|
|
|
2017-09-18 19:14:21 +00:00
|
|
|
from os import listdir
|
|
|
|
from os.path import abspath, dirname, basename, isdir, join
|
|
|
|
|
|
|
|
import mycroft.audio.speech as speech
|
2017-09-23 12:13:50 +00:00
|
|
|
from mycroft.configuration import Configuration
|
2017-02-09 11:09:56 +00:00
|
|
|
from mycroft.messagebus.client.ws import WebsocketClient
|
2017-07-30 07:02:07 +00:00
|
|
|
from mycroft.messagebus.message import Message
|
2017-09-18 18:55:58 +00:00
|
|
|
from mycroft.util.log import LOG
|
2017-02-09 11:09:56 +00:00
|
|
|
|
2017-07-31 11:29:06 +00:00
|
|
|
try:
|
|
|
|
import pulsectl
|
|
|
|
except:
|
|
|
|
pulsectl = None
|
|
|
|
|
2017-02-09 11:09:56 +00:00
|
|
|
|
2017-03-22 06:31:18 +00:00
|
|
|
MainModule = '__init__'
|
2017-02-09 11:09:56 +00:00
|
|
|
sys.path.append(abspath(dirname(__file__)))
|
|
|
|
|
|
|
|
ws = None
|
|
|
|
|
|
|
|
default = None
|
|
|
|
service = []
|
|
|
|
current = None
|
2017-06-15 12:47:44 +00:00
|
|
|
config = None
|
2017-07-31 11:29:06 +00:00
|
|
|
pulse = None
|
2017-08-08 08:37:43 +00:00
|
|
|
pulse_quiet = None
|
|
|
|
pulse_restore = None
|
2017-02-09 11:09:56 +00:00
|
|
|
|
2017-03-22 06:31:18 +00:00
|
|
|
|
|
|
|
def create_service_descriptor(service_folder):
|
2017-04-11 18:20:45 +00:00
|
|
|
"""Prepares a descriptor that can be used together with imp.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
service_folder: folder that shall be imported.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Dict with import information
|
|
|
|
"""
|
2017-03-22 06:31:18 +00:00
|
|
|
info = imp.find_module(MainModule, [service_folder])
|
|
|
|
return {"name": basename(service_folder), "info": info}
|
|
|
|
|
|
|
|
|
|
|
|
def get_services(services_folder):
|
2017-04-11 18:20:45 +00:00
|
|
|
"""
|
|
|
|
Load and initialize services from all subfolders.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
services_folder: base folder to look for services in.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Sorted list of audio services.
|
|
|
|
"""
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info("Loading skills from " + services_folder)
|
2017-03-22 06:31:18 +00:00
|
|
|
services = []
|
|
|
|
possible_services = listdir(services_folder)
|
|
|
|
for i in possible_services:
|
|
|
|
location = join(services_folder, i)
|
|
|
|
if (isdir(location) and
|
|
|
|
not MainModule + ".py" in listdir(location)):
|
|
|
|
for j in listdir(location):
|
|
|
|
name = join(location, j)
|
|
|
|
if (not isdir(name) or
|
|
|
|
not MainModule + ".py" in listdir(name)):
|
|
|
|
continue
|
|
|
|
try:
|
|
|
|
services.append(create_service_descriptor(name))
|
|
|
|
except:
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.error('Failed to create service from ' + name,
|
2017-09-18 19:14:21 +00:00
|
|
|
exc_info=True)
|
2017-03-22 06:31:18 +00:00
|
|
|
if (not isdir(location) or
|
|
|
|
not MainModule + ".py" in listdir(location)):
|
|
|
|
continue
|
|
|
|
try:
|
|
|
|
services.append(create_service_descriptor(location))
|
|
|
|
except:
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.error('Failed to create service from ' + name,
|
2017-09-18 19:14:21 +00:00
|
|
|
exc_info=True)
|
2017-03-22 06:31:18 +00:00
|
|
|
return sorted(services, key=lambda p: p.get('name'))
|
|
|
|
|
|
|
|
|
2017-06-16 08:59:57 +00:00
|
|
|
def load_services(config, ws, path=None):
|
2017-04-11 18:20:45 +00:00
|
|
|
"""
|
|
|
|
Search though the service directory and load any services.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
config: configuration dicrt for the audio backends.
|
|
|
|
ws: websocket object for communication.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
List of started services.
|
|
|
|
"""
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info("Loading services")
|
2017-06-16 08:59:57 +00:00
|
|
|
if path is None:
|
|
|
|
path = dirname(abspath(__file__)) + '/services/'
|
|
|
|
service_directories = get_services(path)
|
2017-03-22 06:31:18 +00:00
|
|
|
service = []
|
|
|
|
for descriptor in service_directories:
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('Loading ' + descriptor['name'])
|
2017-03-27 19:10:27 +00:00
|
|
|
try:
|
|
|
|
service_module = imp.load_module(descriptor["name"] + MainModule,
|
|
|
|
*descriptor["info"])
|
|
|
|
except:
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.error('Failed to import module ' + descriptor['name'],
|
2017-09-18 19:14:21 +00:00
|
|
|
exc_info=True)
|
2017-03-22 06:31:18 +00:00
|
|
|
if (hasattr(service_module, 'autodetect') and
|
|
|
|
callable(service_module.autodetect)):
|
2017-03-27 19:10:27 +00:00
|
|
|
try:
|
|
|
|
s = service_module.autodetect(config, ws)
|
|
|
|
service += s
|
|
|
|
except:
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.error('Failed to autodetect...',
|
2017-09-18 19:14:21 +00:00
|
|
|
exc_info=True)
|
2017-03-27 05:37:25 +00:00
|
|
|
if (hasattr(service_module, 'load_service')):
|
2017-03-27 19:10:27 +00:00
|
|
|
try:
|
|
|
|
s = service_module.load_service(config, ws)
|
|
|
|
service += s
|
|
|
|
except:
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.error('Failed to load service...',
|
2017-09-18 19:14:21 +00:00
|
|
|
exc_info=True)
|
2017-03-22 06:31:18 +00:00
|
|
|
|
|
|
|
return service
|
|
|
|
|
|
|
|
|
2017-02-09 11:09:56 +00:00
|
|
|
def load_services_callback():
|
2017-04-11 18:20:45 +00:00
|
|
|
"""
|
|
|
|
Main callback function for loading services. Sets up the globals
|
|
|
|
service and default and registers the event handlers for the subsystem.
|
|
|
|
"""
|
2017-02-09 11:09:56 +00:00
|
|
|
global ws
|
|
|
|
global default
|
|
|
|
global service
|
|
|
|
|
2017-09-23 12:13:50 +00:00
|
|
|
config = Configuration.get().get("Audio")
|
2017-03-22 06:31:18 +00:00
|
|
|
service = load_services(config, ws)
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info(service)
|
2017-02-09 11:09:56 +00:00
|
|
|
default_name = config.get('default-backend', '')
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('Finding default backend...')
|
2017-02-09 11:09:56 +00:00
|
|
|
for s in service:
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('checking ' + s.name)
|
2017-02-09 11:09:56 +00:00
|
|
|
if s.name == default_name:
|
|
|
|
default = s
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('Found ' + default.name)
|
2017-02-09 11:09:56 +00:00
|
|
|
break
|
|
|
|
else:
|
|
|
|
default = None
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('no default found')
|
|
|
|
LOG.info('Default:' + str(default))
|
2017-02-09 11:09:56 +00:00
|
|
|
|
2017-05-25 15:05:38 +00:00
|
|
|
ws.on('mycroft.audio.service.play', _play)
|
|
|
|
ws.on('mycroft.audio.service.pause', _pause)
|
2017-06-14 17:21:23 +00:00
|
|
|
ws.on('mycroft.audio.service.resume', _resume)
|
2017-05-25 15:05:38 +00:00
|
|
|
ws.on('mycroft.audio.service.stop', _stop)
|
|
|
|
ws.on('mycroft.audio.service.next', _next)
|
|
|
|
ws.on('mycroft.audio.service.prev', _prev)
|
|
|
|
ws.on('mycroft.audio.service.track_info', _track_info)
|
2017-02-09 11:09:56 +00:00
|
|
|
ws.on('recognizer_loop:audio_output_start', _lower_volume)
|
2017-07-31 11:29:06 +00:00
|
|
|
ws.on('recognizer_loop:record_begin', _lower_volume)
|
2017-02-09 11:09:56 +00:00
|
|
|
ws.on('recognizer_loop:audio_output_end', _restore_volume)
|
2017-07-31 11:29:06 +00:00
|
|
|
ws.on('recognizer_loop:record_end', _restore_volume)
|
2017-03-27 05:31:51 +00:00
|
|
|
ws.on('mycroft.stop', _stop)
|
2017-02-09 11:09:56 +00:00
|
|
|
|
2017-03-27 05:50:51 +00:00
|
|
|
|
2017-02-09 11:09:56 +00:00
|
|
|
def _pause(message=None):
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-05-25 15:05:38 +00:00
|
|
|
Handler for mycroft.audio.service.pause. Pauses the current audio
|
|
|
|
service.
|
2017-04-11 18:20:45 +00:00
|
|
|
|
|
|
|
Args:
|
|
|
|
message: message bus message, not used but required
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-02-09 11:09:56 +00:00
|
|
|
global current
|
|
|
|
if current:
|
|
|
|
current.pause()
|
|
|
|
|
|
|
|
|
2017-03-22 06:48:11 +00:00
|
|
|
def _resume(message=None):
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-05-25 15:05:38 +00:00
|
|
|
Handler for mycroft.audio.service.resume.
|
2017-04-11 18:20:45 +00:00
|
|
|
|
|
|
|
Args:
|
|
|
|
message: message bus message, not used but required
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-03-22 06:48:11 +00:00
|
|
|
global current
|
|
|
|
if current:
|
|
|
|
current.resume()
|
|
|
|
|
|
|
|
|
2017-02-09 11:09:56 +00:00
|
|
|
def _next(message=None):
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-05-25 15:05:38 +00:00
|
|
|
Handler for mycroft.audio.service.next. Skips current track and
|
|
|
|
starts playing the next.
|
2017-04-11 18:20:45 +00:00
|
|
|
|
|
|
|
Args:
|
|
|
|
message: message bus message, not used but required
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-02-09 11:09:56 +00:00
|
|
|
global current
|
|
|
|
if current:
|
|
|
|
current.next()
|
|
|
|
|
|
|
|
|
|
|
|
def _prev(message=None):
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-05-25 15:05:38 +00:00
|
|
|
Handler for mycroft.audio.service.prev. Starts playing the previous
|
|
|
|
track.
|
2017-04-11 18:20:45 +00:00
|
|
|
|
|
|
|
Args:
|
|
|
|
message: message bus message, not used but required
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-02-09 11:09:56 +00:00
|
|
|
global current
|
|
|
|
if current:
|
|
|
|
current.prev()
|
|
|
|
|
|
|
|
|
|
|
|
def _stop(message=None):
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-05-25 15:05:38 +00:00
|
|
|
Handler for mycroft.stop. Stops any playing service.
|
2017-04-11 18:20:45 +00:00
|
|
|
|
|
|
|
Args:
|
|
|
|
message: message bus message, not used but required
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-02-09 11:09:56 +00:00
|
|
|
global current
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('stopping all playing services')
|
2017-02-09 11:09:56 +00:00
|
|
|
if current:
|
|
|
|
current.stop()
|
|
|
|
current = None
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('Stopped')
|
2017-02-09 11:09:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
def _lower_volume(message):
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
|
|
|
Is triggered when mycroft starts to speak and reduces the volume.
|
2017-04-11 18:20:45 +00:00
|
|
|
|
|
|
|
Args:
|
|
|
|
message: message bus message, not used but required
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-02-09 11:09:56 +00:00
|
|
|
global current
|
|
|
|
global volume_is_low
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('lowering volume')
|
2017-02-09 11:09:56 +00:00
|
|
|
if current:
|
|
|
|
current.lower_volume()
|
|
|
|
volume_is_low = True
|
2017-07-31 11:29:06 +00:00
|
|
|
try:
|
2017-08-08 08:37:43 +00:00
|
|
|
if pulse_quiet:
|
|
|
|
pulse_quiet()
|
2017-07-31 11:29:06 +00:00
|
|
|
except Exception as e:
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.error(e)
|
2017-07-31 11:29:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
muted_sinks = []
|
|
|
|
|
|
|
|
|
|
|
|
def pulse_mute():
|
2017-08-08 08:37:43 +00:00
|
|
|
"""
|
|
|
|
Mute all pulse audio input sinks except for the one named
|
|
|
|
'mycroft-voice'.
|
|
|
|
"""
|
2017-07-31 11:29:06 +00:00
|
|
|
global muted_sinks
|
|
|
|
for sink in pulse.sink_input_list():
|
|
|
|
if sink.name != 'mycroft-voice':
|
|
|
|
pulse.sink_input_mute(sink.index, 1)
|
|
|
|
muted_sinks.append(sink.index)
|
|
|
|
|
|
|
|
|
|
|
|
def pulse_unmute():
|
2017-08-08 08:37:43 +00:00
|
|
|
"""
|
|
|
|
Unmute all pulse audio input sinks.
|
|
|
|
"""
|
2017-07-31 11:29:06 +00:00
|
|
|
global muted_sinks
|
|
|
|
for sink in pulse.sink_input_list():
|
|
|
|
if sink.index in muted_sinks:
|
|
|
|
pulse.sink_input_mute(sink.index, 0)
|
|
|
|
muted_sinks = []
|
2017-02-09 11:09:56 +00:00
|
|
|
|
2017-03-22 06:31:18 +00:00
|
|
|
|
2017-08-08 08:37:43 +00:00
|
|
|
def pulse_lower_volume():
|
|
|
|
"""
|
|
|
|
Lower volume of all pulse audio input sinks except the one named
|
|
|
|
'mycroft-voice'.
|
|
|
|
"""
|
|
|
|
for sink in pulse.sink_input_list():
|
|
|
|
if sink.name != 'mycroft-voice':
|
|
|
|
v = sink.volume
|
|
|
|
v.value_flat *= 0.3
|
|
|
|
pulse.volume_set(sink, v)
|
|
|
|
|
|
|
|
|
|
|
|
def pulse_restore_volume():
|
|
|
|
"""
|
|
|
|
Restore volume of all pulse audio input sinks except the one named
|
|
|
|
'mycroft-voice'.
|
|
|
|
"""
|
|
|
|
for sink in pulse.sink_input_list():
|
|
|
|
if sink.name != 'mycroft-voice':
|
|
|
|
v = sink.volume
|
|
|
|
v.value_flat /= 0.3
|
|
|
|
pulse.volume_set(sink, v)
|
|
|
|
|
|
|
|
|
2017-02-09 11:09:56 +00:00
|
|
|
def _restore_volume(message):
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
|
|
|
Is triggered when mycroft is done speaking and restores the volume
|
2017-04-11 18:20:45 +00:00
|
|
|
|
|
|
|
Args:
|
|
|
|
message: message bus message, not used but required
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-02-09 11:09:56 +00:00
|
|
|
global current
|
|
|
|
global volume_is_low
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('maybe restoring volume')
|
2017-02-09 11:09:56 +00:00
|
|
|
if current:
|
|
|
|
volume_is_low = False
|
|
|
|
time.sleep(2)
|
|
|
|
if not volume_is_low:
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('restoring volume')
|
2017-02-09 11:09:56 +00:00
|
|
|
current.restore_volume()
|
2017-08-08 08:37:43 +00:00
|
|
|
if pulse_restore:
|
|
|
|
pulse_restore()
|
2017-02-09 11:09:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
def play(tracks, prefered_service):
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
|
|
|
play starts playing the audio on the prefered service if it supports
|
|
|
|
the uri. If not the next best backend is found.
|
2017-04-11 18:20:45 +00:00
|
|
|
|
|
|
|
Args:
|
|
|
|
tracks: list of tracks to play.
|
|
|
|
prefered_service: indecates the service the user prefer to play
|
|
|
|
the tracks.
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-02-09 11:09:56 +00:00
|
|
|
global current
|
2017-10-18 15:29:25 +00:00
|
|
|
global service
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('play')
|
2017-02-09 11:09:56 +00:00
|
|
|
_stop()
|
|
|
|
uri_type = tracks[0].split(':')[0]
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('uri_type: ' + uri_type)
|
2017-02-09 11:09:56 +00:00
|
|
|
# check if user requested a particular service
|
|
|
|
if prefered_service and uri_type in prefered_service.supported_uris():
|
2017-10-18 15:29:25 +00:00
|
|
|
selected_service = prefered_service
|
2017-02-09 11:09:56 +00:00
|
|
|
# check if default supports the uri
|
|
|
|
elif default and uri_type in default.supported_uris():
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info("Using default backend")
|
|
|
|
LOG.info(default.name)
|
2017-10-18 15:29:25 +00:00
|
|
|
selected_service = default
|
2017-02-09 11:09:56 +00:00
|
|
|
else: # Check if any other service can play the media
|
2017-10-18 15:29:25 +00:00
|
|
|
LOG.info("Searching the services")
|
2017-02-09 11:09:56 +00:00
|
|
|
for s in service:
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info(str(s))
|
2017-02-09 11:09:56 +00:00
|
|
|
if uri_type in s.supported_uris():
|
2017-10-18 15:29:25 +00:00
|
|
|
LOG.info("Service "+str(s)+" supports URI "+uri_type)
|
|
|
|
selected_service = s
|
2017-02-09 11:09:56 +00:00
|
|
|
break
|
|
|
|
else:
|
2017-10-18 15:29:25 +00:00
|
|
|
LOG.info('No service found for uri_type: ' + uri_type)
|
2017-02-09 11:09:56 +00:00
|
|
|
return
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('Clear list')
|
2017-10-18 15:29:25 +00:00
|
|
|
selected_service.clear_list()
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('Add tracks' + str(tracks))
|
2017-10-18 15:29:25 +00:00
|
|
|
selected_service.add_list(tracks)
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('Playing')
|
2017-10-18 15:29:25 +00:00
|
|
|
selected_service.play()
|
|
|
|
current = selected_service
|
2017-02-09 11:09:56 +00:00
|
|
|
|
2017-03-22 06:31:18 +00:00
|
|
|
|
2017-02-09 11:09:56 +00:00
|
|
|
def _play(message):
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-05-25 15:05:38 +00:00
|
|
|
Handler for mycroft.audio.service.play. Starts playback of a
|
|
|
|
tracklist. Also determines if the user requested a special service.
|
2017-04-11 18:20:45 +00:00
|
|
|
|
|
|
|
Args:
|
|
|
|
message: message bus message, not used but required
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-02-09 11:09:56 +00:00
|
|
|
global service
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info('mycroft.audio.service.play')
|
|
|
|
LOG.info(message.data['tracks'])
|
2017-02-09 11:09:56 +00:00
|
|
|
|
|
|
|
tracks = message.data['tracks']
|
|
|
|
|
|
|
|
# Find if the user wants to use a specific backend
|
|
|
|
for s in service:
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info(s.name)
|
2017-02-09 11:09:56 +00:00
|
|
|
if s.name in message.data['utterance']:
|
|
|
|
prefered_service = s
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info(s.name + ' would be prefered')
|
2017-02-09 11:09:56 +00:00
|
|
|
break
|
|
|
|
else:
|
|
|
|
prefered_service = None
|
|
|
|
play(tracks, prefered_service)
|
|
|
|
|
|
|
|
|
|
|
|
def _track_info(message):
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
|
|
|
Returns track info on the message bus.
|
2017-04-11 18:20:45 +00:00
|
|
|
|
|
|
|
Args:
|
|
|
|
message: message bus message, not used but required
|
2017-03-27 05:50:51 +00:00
|
|
|
"""
|
2017-02-09 11:09:56 +00:00
|
|
|
global current
|
|
|
|
if current:
|
2017-07-30 07:02:07 +00:00
|
|
|
track_info = current.track_info()
|
2017-02-09 11:09:56 +00:00
|
|
|
else:
|
|
|
|
track_info = {}
|
2017-07-30 07:02:07 +00:00
|
|
|
ws.emit(Message('mycroft.audio.service.track_info_reply',
|
|
|
|
data=track_info))
|
2017-02-09 11:09:56 +00:00
|
|
|
|
|
|
|
|
2017-08-08 08:37:43 +00:00
|
|
|
def setup_pulseaudio_handlers(pulse_choice=None):
|
|
|
|
"""
|
|
|
|
Select functions for handling lower volume/restore of
|
|
|
|
pulse audio input sinks.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
pulse_choice: method selection, can be eithe 'mute' or 'lower'
|
|
|
|
"""
|
|
|
|
global pulse, pulse_quiet, pulse_restore
|
|
|
|
|
|
|
|
if pulsectl and pulse_choice is not None:
|
|
|
|
pulse = pulsectl.Pulse('Mycroft-audio-service')
|
|
|
|
if pulse_choice == 'mute':
|
|
|
|
pulse_quiet = pulse_mute
|
|
|
|
pulse_restore = pulse_unmute
|
|
|
|
elif pulse_choice == 'lower':
|
|
|
|
pulse_quiet = pulse_lower_volume
|
|
|
|
pulse_restore = pulse_restore_volume
|
|
|
|
|
|
|
|
|
2017-02-09 11:09:56 +00:00
|
|
|
def connect():
|
|
|
|
global ws
|
|
|
|
ws.run_forever()
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
global ws
|
2017-06-15 12:47:44 +00:00
|
|
|
global config
|
2017-02-09 11:09:56 +00:00
|
|
|
ws = WebsocketClient()
|
2017-09-23 12:13:50 +00:00
|
|
|
Configuration.init(ws)
|
|
|
|
config = Configuration.get()
|
2017-06-15 12:47:44 +00:00
|
|
|
speech.init(ws)
|
2017-02-09 11:09:56 +00:00
|
|
|
|
2017-07-31 11:29:06 +00:00
|
|
|
# Setup control of pulse audio
|
2017-08-08 08:37:43 +00:00
|
|
|
setup_pulseaudio_handlers(config.get('Audio').get('pulseaudio'))
|
2017-07-31 11:29:06 +00:00
|
|
|
|
2017-02-09 11:09:56 +00:00
|
|
|
def echo(message):
|
|
|
|
try:
|
|
|
|
_message = json.loads(message)
|
2017-08-08 12:23:02 +00:00
|
|
|
if 'mycroft.audio.service' not in _message.get('type'):
|
2017-03-28 05:27:20 +00:00
|
|
|
return
|
2017-02-09 11:09:56 +00:00
|
|
|
message = json.dumps(_message)
|
|
|
|
except:
|
|
|
|
pass
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.debug(message)
|
2017-02-09 11:09:56 +00:00
|
|
|
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.info("Staring Audio Services")
|
2017-02-09 11:09:56 +00:00
|
|
|
ws.on('message', echo)
|
|
|
|
ws.once('open', load_services_callback)
|
2017-08-02 21:04:55 +00:00
|
|
|
try:
|
|
|
|
ws.run_forever()
|
|
|
|
except KeyboardInterrupt, e:
|
2017-09-18 18:55:58 +00:00
|
|
|
LOG.exception(e)
|
2017-08-02 21:04:55 +00:00
|
|
|
speech.shutdown()
|
|
|
|
sys.exit()
|
2017-02-09 11:09:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|