From 138331f438ef1bf3177a4b05848118ec62735a60 Mon Sep 17 00:00:00 2001 From: "dtseng@chromium.org" Date: Tue, 28 May 2013 22:08:43 +0000 Subject: [PATCH] Support multiple voices for all available modules (text-to-speech engines) on Linux. This adds appropriate calls to retrieve voices from SpeechDispatcher and make it available through Chrome. We combine all voices across all available modules into one list in order to conform to the way Chrome exposes voices. Review URL: https://chromiumcodereview.appspot.com/15846006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202665 0039d316-1c4b-4281-b951-d872f2087c98 --- build/linux/system.gyp | 4 +++ chrome/browser/speech/tts_linux.cc | 73 ++++++++++++++++++++++++++++++++------ 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/build/linux/system.gyp b/build/linux/system.gyp index 49acd6573e53..bc8172eba038 100644 --- a/build/linux/system.gyp +++ b/build/linux/system.gyp @@ -520,6 +520,10 @@ 'spd_set_notification_on', 'spd_set_voice_rate', 'spd_set_voice_pitch', + 'spd_list_synthesis_voices', + 'spd_set_synthesis_voice', + 'spd_list_modules', + 'spd_set_output_module', ], 'message': 'Generating libspeechd library loader.', 'process_outputs_as_sources': 1, diff --git a/chrome/browser/speech/tts_linux.cc b/chrome/browser/speech/tts_linux.cc index 9ab9fe85ef25..83e1e2778f05 100644 --- a/chrome/browser/speech/tts_linux.cc +++ b/chrome/browser/speech/tts_linux.cc @@ -4,6 +4,9 @@ #include +#include + +#include "base/memory/scoped_ptr.h" #include "base/memory/singleton.h" #include "base/synchronization/lock.h" #include "chrome/browser/speech/tts_platform.h" @@ -18,6 +21,11 @@ namespace { const char kNotSupportedError[] = "Native speech synthesis not supported on this platform."; +struct SPDChromeVoice { + std::string name; + std::string module; +}; + } // namespace class TtsPlatformImplLinux : public TtsPlatformImpl { @@ -67,6 +75,10 @@ class TtsPlatformImplLinux : public TtsPlatformImpl { std::string utterance_; int utterance_id_; + // Map a string composed of a voicename and module to the voicename. Used to + // uniquely identify a voice across all available modules. + scoped_ptr > all_native_voices_; + friend struct DefaultSingletonTraits; DISALLOW_COPY_AND_ASSIGN(TtsPlatformImplLinux); @@ -153,6 +165,13 @@ bool TtsPlatformImplLinux::Speak( float pitch = params.pitch > 3 ? 3 : params.pitch; pitch = params.pitch < 0.334 ? 0.334 : pitch; + std::map::iterator it = + all_native_voices_->find(voice.name); + if (it != all_native_voices_->end()) { + libspeechd_loader_.spd_set_output_module(conn_, it->second.module.c_str()); + libspeechd_loader_.spd_set_synthesis_voice(conn_, it->second.name.c_str()); + } + // Map our multiplicative range to Speech Dispatcher's linear range. // .334 = -100. // 3 = 100. @@ -185,16 +204,50 @@ bool TtsPlatformImplLinux::IsSpeaking() { void TtsPlatformImplLinux::GetVoices( std::vector* out_voices) { - // TODO: get all voices, not just default voice. - // http://crbug.com/88059 - out_voices->push_back(VoiceData()); - VoiceData& voice = out_voices->back(); - voice.native = true; - voice.name = "native"; - voice.events.insert(TTS_EVENT_START); - voice.events.insert(TTS_EVENT_END); - voice.events.insert(TTS_EVENT_CANCELLED); - voice.events.insert(TTS_EVENT_MARKER); + if (!all_native_voices_.get()) { + all_native_voices_.reset(new std::map()); + char** modules = libspeechd_loader_.spd_list_modules(conn_); + if (!modules) + return; + for (int i = 0; modules[i]; i++) { + char* module = modules[i]; + libspeechd_loader_.spd_set_output_module(conn_, module); + SPDVoice** native_voices = + libspeechd_loader_.spd_list_synthesis_voices(conn_); + if (!native_voices) { + free(module); + continue; + } + for (int j = 0; native_voices[j]; j++) { + SPDVoice* native_voice = native_voices[j]; + SPDChromeVoice native_data; + native_data.name = native_voice->name; + native_data.module = module; + std::string key; + key.append(native_data.name); + key.append(" "); + key.append(native_data.module); + all_native_voices_->insert( + std::pair(key, native_data)); + free(native_voices[j]); + } + free(modules[i]); + } + } + + for (std::map::iterator it = + all_native_voices_->begin(); + it != all_native_voices_->end(); + it++) { + out_voices->push_back(VoiceData()); + VoiceData& voice = out_voices->back(); + voice.native = true; + voice.name = it->first; + voice.events.insert(TTS_EVENT_START); + voice.events.insert(TTS_EVENT_END); + voice.events.insert(TTS_EVENT_CANCELLED); + voice.events.insert(TTS_EVENT_MARKER); + } } void TtsPlatformImplLinux::OnSpeechEvent(SPDNotificationType type) { -- 2.11.4.GIT