diff options
author | Thierry Crozat | 2019-07-31 22:26:57 +0100 |
---|---|---|
committer | Filippos Karapetis | 2019-09-01 22:47:55 +0300 |
commit | 9ca2602e82429cf3b210f363e0a478fd876a13b5 (patch) | |
tree | e9f45357db4dd2c157c242aa48def633ae7d914f /backends/text-to-speech/macosx | |
parent | 1694b930e652cd2cc549988f9960604a35e36c25 (diff) | |
download | scummvm-rg350-9ca2602e82429cf3b210f363e0a478fd876a13b5.tar.gz scummvm-rg350-9ca2602e82429cf3b210f363e0a478fd876a13b5.tar.bz2 scummvm-rg350-9ca2602e82429cf3b210f363e0a478fd876a13b5.zip |
TTS: Implement speech queueing on macOS
Diffstat (limited to 'backends/text-to-speech/macosx')
-rw-r--r-- | backends/text-to-speech/macosx/macosx-text-to-speech.h | 13 | ||||
-rw-r--r-- | backends/text-to-speech/macosx/macosx-text-to-speech.mm | 54 |
2 files changed, 60 insertions, 7 deletions
diff --git a/backends/text-to-speech/macosx/macosx-text-to-speech.h b/backends/text-to-speech/macosx/macosx-text-to-speech.h index fed0c05458..7c33a3b0c9 100644 --- a/backends/text-to-speech/macosx/macosx-text-to-speech.h +++ b/backends/text-to-speech/macosx/macosx-text-to-speech.h @@ -28,14 +28,14 @@ #if defined(USE_MACOSX_TTS) #include "common/text-to-speech.h" -#include "common/str.h" +#include "common/queue.h" class MacOSXTextToSpeechManager : public Common::TextToSpeechManager { public: MacOSXTextToSpeechManager(); virtual ~MacOSXTextToSpeechManager(); - virtual bool say(Common::String str, Common::String charset = ""); + virtual bool say(Common::String str, Action action, Common::String charset = ""); virtual bool stop(); virtual bool pause(); @@ -57,8 +57,17 @@ public: virtual void freeVoiceData(void *data); + bool startNextSpeech(); + private: virtual void updateVoices(); + + struct SpeechText { + Common::String text; + Common::String encoding; + SpeechText(const Common::String& txt, const Common::String& enc) : text(txt), encoding(enc) {} + }; + Common::Queue<SpeechText> _messageQueue; }; #endif diff --git a/backends/text-to-speech/macosx/macosx-text-to-speech.mm b/backends/text-to-speech/macosx/macosx-text-to-speech.mm index 281d92f926..9f668414b6 100644 --- a/backends/text-to-speech/macosx/macosx-text-to-speech.mm +++ b/backends/text-to-speech/macosx/macosx-text-to-speech.mm @@ -31,10 +31,32 @@ #include <Foundation/NSString.h> #include <CoreFoundation/CFString.h> -NSSpeechSynthesizer* synthesizer; +@interface MacOSXTextToSpeechManagerDelegate : NSObject<NSSpeechSynthesizerDelegate> { + MacOSXTextToSpeechManager *_ttsManager; +} +- (id)initWithManager:(MacOSXTextToSpeechManager*)ttsManager; +- (void)speechSynthesizer:(NSSpeechSynthesizer *)sender didFinishSpeaking:(BOOL)finishedSpeaking; +@end + +@implementation MacOSXTextToSpeechManagerDelegate +- (id)initWithManager:(MacOSXTextToSpeechManager*)ttsManager { + self = [super init]; + _ttsManager = ttsManager; + return self; +} + +- (void)speechSynthesizer:(NSSpeechSynthesizer *)sender didFinishSpeaking:(BOOL)finishedSpeaking { + _ttsManager->startNextSpeech(); +} +@end + +NSSpeechSynthesizer *synthesizer; +MacOSXTextToSpeechManagerDelegate *synthesizerDelegate; MacOSXTextToSpeechManager::MacOSXTextToSpeechManager() : Common::TextToSpeechManager() { synthesizer = [[NSSpeechSynthesizer alloc] init]; + synthesizerDelegate = [[MacOSXTextToSpeechManagerDelegate alloc] initWithManager:this]; + [synthesizer setDelegate:synthesizerDelegate]; #ifdef USE_TRANSLATION setLanguage(TransMan.getCurrentLanguage()); @@ -45,30 +67,52 @@ MacOSXTextToSpeechManager::MacOSXTextToSpeechManager() : Common::TextToSpeechMan MacOSXTextToSpeechManager::~MacOSXTextToSpeechManager() { [synthesizer release]; + [synthesizerDelegate release]; } -bool MacOSXTextToSpeechManager::say(Common::String text, Common::String encoding) { +bool MacOSXTextToSpeechManager::say(Common::String text, Action action, Common::String encoding) { + if ([synthesizer isSpeaking]) { + if (action == DROP) + return true; + else if (action == INTERRUPT) { + _messageQueue.clear(); + // Should we use NSSpeechImmediateBoundary, or even NSSpeechSentenceBoundary? + [synthesizer stopSpeakingAtBoundary:NSSpeechWordBoundary]; + } + } + if (encoding.empty()) { #ifdef USE_TRANSLATION encoding = TransMan.getCurrentCharset(); #endif } + _messageQueue.push(SpeechText(text, encoding)); + if (![synthesizer isSpeaking]) + startNextSpeech(); + return true; +} + +bool MacOSXTextToSpeechManager::startNextSpeech() { + if (_messageQueue.empty()) + return false; + SpeechText text = _messageQueue.pop(); // Get current encoding CFStringEncoding stringEncoding = kCFStringEncodingASCII; - if (!encoding.empty()) { - CFStringRef encStr = CFStringCreateWithCString(NULL, encoding.c_str(), kCFStringEncodingASCII); + if (!text.encoding.empty()) { + CFStringRef encStr = CFStringCreateWithCString(NULL, text.encoding.c_str(), kCFStringEncodingASCII); stringEncoding = CFStringConvertIANACharSetNameToEncoding(encStr); CFRelease(encStr); } - CFStringRef textNSString = CFStringCreateWithCString(NULL, text.c_str(), stringEncoding); + CFStringRef textNSString = CFStringCreateWithCString(NULL, text.text.c_str(), stringEncoding); bool status = [synthesizer startSpeakingString:(NSString *)textNSString]; CFRelease(textNSString); return status; } bool MacOSXTextToSpeechManager::stop() { + _messageQueue.clear(); // Should we use NSSpeechImmediateBoundary, or even NSSpeechSentenceBoundary? [synthesizer stopSpeakingAtBoundary:NSSpeechWordBoundary]; return true; |