Refining new "listening" sound mechanism

This adds several refinements to the listening sound mechanism added by:
* Added a default sound file
* Allowing various ways to override "resource files" for customization
* Moved the sound configuration path from "confirm_ding" to
  "sounds" > "start_listening"
* Also added "sounds" > "end_listening" configuration for the future

This submission adds the new mycroft.util.resolve_resource_file(res_name)
method.  This method takes a name such as "snd/start_listening.wav" and
looks (in order):
* For an absolute path <res_name>
* For ~/.mycroft/<res_name>
* For /opt/mycroft/<res_name>
* For mycroft/res/<res_name> within the source package
pull/520/head
penrods 2017-02-09 01:37:22 -08:00 committed by Arron Atchison
parent 990dd27c5e
commit 5f8775883a
4 changed files with 61 additions and 11 deletions

View File

@ -27,11 +27,9 @@ from mycroft.identity import IdentityManager
from mycroft.messagebus.client.ws import WebsocketClient
from mycroft.messagebus.message import Message
from mycroft.tts import TTSFactory
from mycroft.util import kill, play_wav
from mycroft.util import kill, play_wav, resolve_resource_file
from mycroft.util.log import getLogger
from os.path import expanduser
logger = getLogger("SpeechClient")
ws = None
tts = TTSFactory.create()
@ -44,11 +42,13 @@ config = ConfigurationManager.get()
def handle_record_begin():
logger.info("Begin Recording...")
# If enabled, play a wave file with a short sound to indicate recording has
# begun.
# If enabled, play a wave file with a short sound to audibly
# indicate recording has begun.
if config.get('confirm_listening'):
play_wav(expanduser(config.get('confirm_ding')))
file = resolve_resource_file(config.get('sounds').get('start_listening'))
if file:
play_wav(file)
ws.emit(Message('recognizer_loop:record_begin'))
@ -88,13 +88,13 @@ def handle_multi_utterance_intent_failure(event):
def handle_speak(event):
utterance = event.data['utterance']
# This is a bit of a hack for Picroft. The analog audio on a Pi blocks
# for 30 seconds fairly often, so we don't want to break on periods
# (decreasing the chance of encountering the block). But we will
# keep the split for non-Picroft installs since it give user feedback
# faster on longer phrases.
#
#
# TODO: Remove or make an option? This is really a hack, anyway,
# so we likely will want to get rid of this when not running on Mimic
if not config.get('enclosure', {}).get('platform') == "picroft":
@ -105,6 +105,7 @@ def handle_speak(event):
else:
mute_and_speak(utterance)
def handle_sleep(event):
loop.sleep()

View File

@ -3,8 +3,11 @@
"system_unit": "metric",
"time_format": "half",
"date_format": "MDY",
"confirm_listening": false,
"confirm_ding": "~/.mycroft/ding.wav",
"confirm_listening": true,
"sounds": {
"start_listening": "snd/start_listening.wav",
"end_listening": "snd/end_listening.wav"
},
"location": {
"city": {
"code": "Lawrence",

Binary file not shown.

View File

@ -28,6 +28,52 @@ from os.path import dirname
__author__ = 'jdorleans'
def resolve_resource_file(res_name):
"""Convert a resource into an absolute filename.
Resource names are in the form: 'filename.ext'
or 'path/filename.ext'
The system wil look for ~/.mycroft/res_name first, and
if not found will look at /opt/mycroft/res_name,
then finally it will look for res_name in the 'mycroft/res'
folder of the source code package.
Example:
With mycroft running as the user 'bob', if you called
resolve_resource_file('snd/beep.wav')
it would return either '/home/bob/.mycroft/snd/beep.wav' or
'/opt/mycroft/snd/beep.wav' or '.../mycroft/res/snd/beep.wav',
where the '...' is replaced by the path where the package has
been installed.
Args:
res_name (str): a resource path/name
"""
# First look for fully qualified file (e.g. a user setting)
if os.path.isfile(res_name):
return res_name
# Now look for ~/.mycroft/res_name (in user folder)
filename = os.path.expanduser("~/.mycroft/"+res_name)
if os.path.isfile(filename):
return filename
# Next look for /opt/mycroft/res/res_name
filename = os.path.expanduser("/opt/mycroft/"+res_name)
if os.path.isfile(filename):
return filename
# Finally look for it in the source package
filename = dirname(os.path.abspath(__file__))+"../res/"+res_name
filename = os.path.normpath(filename)
if os.path.isfile(filename):
return filename
return None # Resource cannot be resolved
def play_wav(uri):
return subprocess.Popen(["aplay", get_http(uri)])