Fix lock around speech.

the lock could be taken by a waiting thread between sentences in a multi-sentenced utterance. This locking method will allow the entire utterance to be synthezised before handling next.
pull/1293/head
Åke Forslund 2017-12-07 20:34:32 +01:00 committed by Steve Penrod
parent 8c8691e51c
commit 9ed40010fa
1 changed files with 33 additions and 35 deletions

View File

@ -45,38 +45,40 @@ def handle_speak(event):
Configuration.init(ws)
global _last_stop_signal
# Mild abuse of the signal system to allow other processes to detect
# when TTS is happening. See mycroft.util.is_speaking()
with lock:
# Mild abuse of the signal system to allow other processes to detect
# when TTS is happening. See mycroft.util.is_speaking()
utterance = event.data['utterance']
if event.data.get('expect_response', False):
# When expect_response is requested, the listener will be restarted
# at the end of the next bit of spoken audio.
ws.once('recognizer_loop:audio_output_end', _start_listener)
utterance = event.data['utterance']
if event.data.get('expect_response', False):
# When expect_response is requested, the listener will be restarted
# at the end of the next bit of spoken audio.
ws.once('recognizer_loop:audio_output_end', _start_listener)
# 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":
start = time.time()
chunks = re.split(r'(?<!\w\.\w.)(?<![A-Z][a-z]\.)(?<=\.|\?)\s',
utterance)
for chunk in chunks:
try:
mute_and_speak(chunk)
except KeyboardInterrupt:
raise
except:
LOG.error('Error in mute_and_speak', exc_info=True)
if _last_stop_signal > start or check_for_signal('buttonPress'):
break
else:
mute_and_speak(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":
start = time.time()
chunks = re.split(r'(?<!\w\.\w.)(?<![A-Z][a-z]\.)(?<=\.|\?)\s',
utterance)
for chunk in chunks:
try:
mute_and_speak(chunk)
except KeyboardInterrupt:
raise
except:
LOG.error('Error in mute_and_speak', exc_info=True)
if (_last_stop_signal > start or
check_for_signal('buttonPress')):
break
else:
mute_and_speak(utterance)
def mute_and_speak(utterance):
@ -88,7 +90,6 @@ def mute_and_speak(utterance):
"""
global tts_hash
lock.acquire()
# update TTS object if configuration has changed
if tts_hash != hash(str(config.get('tts', ''))):
global tts
@ -101,10 +102,7 @@ def mute_and_speak(utterance):
tts_hash = hash(str(config.get('tts', '')))
LOG.info("Speak: " + utterance)
try:
tts.execute(utterance)
finally:
lock.release()
tts.execute(utterance)
def handle_stop(event):