diff options
author | dpapad@chromium.org <dpapad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-17 22:56:57 +0000 |
---|---|---|
committer | dpapad@chromium.org <dpapad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-17 22:56:57 +0000 |
commit | be7c1ac4c494b6f3de8297e915e87787ba561017 (patch) | |
tree | 74ebb34db8c3f400371cca5245c095d52e0da351 | |
parent | 8801db19b85897e62484312f273d4a5c9d33abf2 (diff) | |
download | chromium_src-be7c1ac4c494b6f3de8297e915e87787ba561017.zip chromium_src-be7c1ac4c494b6f3de8297e915e87787ba561017.tar.gz chromium_src-be7c1ac4c494b6f3de8297e915e87787ba561017.tar.bz2 |
Revert 173550
> Linux: use generated library loader for libspeechd.
>
> This will require an update to build/install-build-deps.sh
> (done in a separate CL as requested by the infra team).
>
> BUG=162733
>
> Review URL: https://codereview.chromium.org/11415243
TBR=phajdan.jr@chromium.org
Review URL: https://codereview.chromium.org/11573052
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@173561 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | build/linux/system.gyp | 57 | ||||
-rw-r--r-- | chrome/browser/speech/extension_api/tts_extension_api_linux.cc | 358 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 1 | ||||
-rwxr-xr-x | tools/generate_library_loader/generate_library_loader.py | 2 |
4 files changed, 262 insertions, 156 deletions
diff --git a/build/linux/system.gyp b/build/linux/system.gyp index 1bb764f..6c4488a 100644 --- a/build/linux/system.gyp +++ b/build/linux/system.gyp @@ -13,7 +13,6 @@ ], 'linux_link_libpci%': 0, - 'linux_link_libspeechd%': 0, }, 'conditions': [ [ 'os_posix==1 and OS!="mac"', { @@ -384,62 +383,6 @@ ], }, { - 'target_name': 'libspeechd', - 'type': 'static_library', - 'dependencies': [ - '../../base/base.gyp:base', - ], - 'direct_dependent_settings': { - 'include_dirs': [ - '<(SHARED_INTERMEDIATE_DIR)', - ], - 'conditions': [ - ['linux_link_libspeechd==1', { - 'link_settings': { - 'libraries': [ - '-lspeechd', - ], - } - }], - ], - }, - 'hard_dependency': 1, - 'actions': [ - { - 'variables': { - 'output_h': '<(SHARED_INTERMEDIATE_DIR)/library_loaders/libspeechd.h', - 'output_cc': '<(INTERMEDIATE_DIR)/libspeechd_loader.cc', - 'generator': '../../tools/generate_library_loader/generate_library_loader.py', - }, - 'action_name': 'generate_libspeechd_loader', - 'inputs': [ - '<(generator)', - ], - 'outputs': [ - '<(output_h)', - '<(output_cc)', - ], - 'action': ['python', - '<(generator)', - '--name', 'LibSpeechdLoader', - '--output-h', '<(output_h)', - '--output-cc', '<(output_cc)', - '--header', '<libspeechd.h>', - '--link-directly=<(linux_link_libspeechd)', - 'spd_open', - 'spd_say', - 'spd_stop', - 'spd_close', - 'spd_set_notification_on', - 'spd_set_voice_rate', - 'spd_set_voice_pitch', - ], - 'message': 'Generating libspeechd library loader.', - 'process_outputs_as_sources': 1, - }, - ], - }, - { 'target_name': 'x11', 'type': 'none', 'toolsets': ['host', 'target'], diff --git a/chrome/browser/speech/extension_api/tts_extension_api_linux.cc b/chrome/browser/speech/extension_api/tts_extension_api_linux.cc index 9d1181e..698c03e 100644 --- a/chrome/browser/speech/extension_api/tts_extension_api_linux.cc +++ b/chrome/browser/speech/extension_api/tts_extension_api_linux.cc @@ -2,22 +2,149 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <dlfcn.h> #include <math.h> #include "base/memory/singleton.h" #include "chrome/browser/speech/extension_api/tts_extension_api_platform.h" #include "content/public/browser/browser_thread.h" -#include "library_loaders/libspeechd.h" - using content::BrowserThread; namespace { - const char kNotSupportedError[] = "Native speech synthesis not supported on this platform."; -} // namespace +// Speech dispatcher exports. +// The following types come from the libspeechd-dev package/libspeechd.h. +typedef enum { + SPD_MODE_SINGLE = 0, + SPD_MODE_THREADED = 1 +} SPDConnectionMode; + +typedef enum { + SPD_IMPORTANT = 1, + SPD_MESSAGE = 2, + SPD_TEXT = 3, + SPD_NOTIFICATION = 4, + SPD_PROGRESS = 5 +} SPDPriority; + +typedef enum { + SPD_EVENT_BEGIN, + SPD_EVENT_END, + SPD_EVENT_CANCEL, + SPD_EVENT_PAUSE, + SPD_EVENT_RESUME, + SPD_EVENT_INDEX_MARK +} SPDNotificationType; + +typedef enum { + SPD_BEGIN = 1, + SPD_END = 2, + SPD_INDEX_MARKS = 4, + SPD_CANCEL = 8, + SPD_PAUSE = 16, + SPD_RESUME = 32 +} SPDNotification; + +typedef void (*SPDCallback)( + size_t msg_id, size_t client_id, SPDNotificationType state); +typedef void (*SPDCallbackIM)(size_t msg_id, + size_t client_id, + SPDNotificationType state, + char* index_mark); + +typedef struct { + /* PUBLIC */ + SPDCallback callback_begin; + SPDCallback callback_end; + SPDCallback callback_cancel; + SPDCallback callback_pause; + SPDCallback callback_resume; + SPDCallbackIM callback_im; + + /* PRIVATE */ + int socket; + FILE* stream; + SPDConnectionMode mode; + + pthread_mutex_t* ssip_mutex; + + pthread_t* events_thread; + pthread_mutex_t* comm_mutex; + pthread_cond_t* cond_reply_ready; + pthread_mutex_t* mutex_reply_ready; + pthread_cond_t* cond_reply_ack; + pthread_mutex_t* mutex_reply_ack; + + char* reply; +} SPDConnection; + +typedef SPDConnection* (*spd_open_func)(const char* client_name, + const char* connection_name, + const char* user_name, + SPDConnectionMode mode); +typedef int (*spd_say_func)(SPDConnection* connection, + SPDPriority priority, + const char* text); +typedef int (*spd_stop_func)(SPDConnection* connection); +typedef void (*spd_close_func)(SPDConnection* connection); +typedef int (*spd_set_notification_on_func)(SPDConnection* connection, + SPDNotification notification); +typedef int (*spd_set_voice_rate_func)(SPDConnection* connection, int rate); +typedef int (*spd_set_voice_pitch_func)(SPDConnection* connection, int pitch); +}; + +class SpeechDispatcherWrapper { + public: + static SPDNotificationType current_notification_; + + SpeechDispatcherWrapper(); + ~SpeechDispatcherWrapper(); + + bool Speak(const char* text); + bool IsSpeaking(); + bool StopSpeaking(); + void SetRate(int rate); + void SetPitch(int pitch); + + // Resets the connection with speech dispatcher. + void Reset(); + + // States whether Speech Dispatcher loaded successfully. + bool loaded() { + return loaded_; + } + + private: + static void NotificationCallback(size_t msg_id, + size_t client_id, + SPDNotificationType type); + + static void IndexMarkCallback(size_t msg_id, + size_t client_id, + SPDNotificationType state, + char* index_mark); + + // Interface bindings. + spd_open_func spd_open; + spd_say_func spd_say; + spd_stop_func spd_stop; + spd_close_func spd_close; + spd_set_notification_on_func spd_set_notification_on; + spd_set_voice_rate_func spd_set_voice_rate; + spd_set_voice_pitch_func spd_set_voice_pitch; + + bool loaded_; + void* library_; + SPDConnection* conn_; + DISALLOW_COPY_AND_ASSIGN(SpeechDispatcherWrapper); +}; + +// static +SPDNotificationType SpeechDispatcherWrapper::current_notification_ = + SPD_EVENT_END; class ExtensionTtsPlatformImplLinux : public ExtensionTtsPlatformImpl { public: @@ -36,25 +163,10 @@ class ExtensionTtsPlatformImplLinux : public ExtensionTtsPlatformImpl { static ExtensionTtsPlatformImplLinux* GetInstance(); private: - ExtensionTtsPlatformImplLinux(); - virtual ~ExtensionTtsPlatformImplLinux(); - - // Resets the connection with speech dispatcher. - void Reset(); - - static void NotificationCallback(size_t msg_id, - size_t client_id, - SPDNotificationType type); + ExtensionTtsPlatformImplLinux(): utterance_id_(0) {} + virtual ~ExtensionTtsPlatformImplLinux() {} - static void IndexMarkCallback(size_t msg_id, - size_t client_id, - SPDNotificationType state, - char* index_mark); - - static SPDNotificationType current_notification_; - - LibSpeechdLoader libspeechd_loader_; - SPDConnection* conn_; + SpeechDispatcherWrapper spd_; // These apply to the current utterance only. std::string utterance_; @@ -65,61 +177,157 @@ class ExtensionTtsPlatformImplLinux : public ExtensionTtsPlatformImpl { DISALLOW_COPY_AND_ASSIGN(ExtensionTtsPlatformImplLinux); }; -// static -SPDNotificationType ExtensionTtsPlatformImplLinux::current_notification_ = - SPD_EVENT_END; +SpeechDispatcherWrapper::SpeechDispatcherWrapper() : loaded_(false) { + library_ = dlopen("libspeechd.so", RTLD_LAZY); + if (!library_) + return; + + spd_open = reinterpret_cast<spd_open_func>(dlsym(library_, "spd_open")); + if (!spd_open) + return; + + spd_say = reinterpret_cast<spd_say_func>(dlsym(library_, "spd_say")); + if (!spd_say) + return; + + spd_stop = reinterpret_cast<spd_stop_func>(dlsym(library_, "spd_stop")); + if (!spd_stop) + return; -ExtensionTtsPlatformImplLinux::ExtensionTtsPlatformImplLinux() - : utterance_id_(0) { - if (!libspeechd_loader_.Load("libspeechd.so.2")) + spd_close = reinterpret_cast<spd_close_func>(dlsym(library_, "spd_close")); + if (!spd_close) return; - conn_ = libspeechd_loader_.spd_open( - "chrome", "extension_api", NULL, SPD_MODE_THREADED); + conn_ = spd_open("chrome", "extension_api", NULL, SPD_MODE_THREADED); if (!conn_) return; + spd_set_notification_on = reinterpret_cast<spd_set_notification_on_func>( + dlsym(library_, "spd_set_notification_on")); + if (!spd_set_notification_on) + return; + + spd_set_voice_rate = reinterpret_cast<spd_set_voice_rate_func>( + dlsym(library_, "spd_set_voice_rate")); + if (!spd_set_voice_rate) + return; + + spd_set_voice_pitch = reinterpret_cast<spd_set_voice_pitch_func>( + dlsym(library_, "spd_set_voice_pitch")); + if (!spd_set_voice_pitch) + return; + // Register callbacks for all events. conn_->callback_begin = conn_->callback_end = conn_->callback_cancel = conn_->callback_pause = conn_->callback_resume = - &NotificationCallback; + &SpeechDispatcherWrapper::NotificationCallback; + + conn_->callback_im = &SpeechDispatcherWrapper::IndexMarkCallback; - conn_->callback_im = &IndexMarkCallback; + spd_set_notification_on(conn_, SPD_BEGIN); + spd_set_notification_on(conn_, SPD_END); + spd_set_notification_on(conn_, SPD_CANCEL); + spd_set_notification_on(conn_, SPD_PAUSE); + spd_set_notification_on(conn_, SPD_RESUME); - libspeechd_loader_.spd_set_notification_on(conn_, SPD_BEGIN); - libspeechd_loader_.spd_set_notification_on(conn_, SPD_END); - libspeechd_loader_.spd_set_notification_on(conn_, SPD_CANCEL); - libspeechd_loader_.spd_set_notification_on(conn_, SPD_PAUSE); - libspeechd_loader_.spd_set_notification_on(conn_, SPD_RESUME); + loaded_ = true; } -ExtensionTtsPlatformImplLinux::~ExtensionTtsPlatformImplLinux() { +SpeechDispatcherWrapper::~SpeechDispatcherWrapper() { if (conn_) { - libspeechd_loader_.spd_close(conn_); + spd_close(conn_); conn_ = NULL; } + + if (library_) { + dlclose(library_); + library_ = NULL; + } +} +bool SpeechDispatcherWrapper::Speak(const char* text) { + if (!loaded()) + return false; + if (spd_say(conn_, SPD_TEXT, text) == -1) { + Reset(); + return false; + } + return true; +} + +bool SpeechDispatcherWrapper::IsSpeaking() { + return SpeechDispatcherWrapper::current_notification_ == SPD_EVENT_BEGIN; +} + +bool SpeechDispatcherWrapper::StopSpeaking() { + if (!loaded()) + return false; + if (spd_stop(conn_) == -1) { + Reset(); + return false; + } + return true; +} +void SpeechDispatcherWrapper::SetRate(int rate) { + spd_set_voice_rate(conn_, rate); +} + +void SpeechDispatcherWrapper::SetPitch(int pitch) { + spd_set_voice_pitch(conn_, pitch); } -void ExtensionTtsPlatformImplLinux::Reset() { +// Resets the connection with speech dispatcher. +void SpeechDispatcherWrapper::Reset() { if (conn_) - libspeechd_loader_.spd_close(conn_); - conn_ = libspeechd_loader_.spd_open( - "chrome", "extension_api", NULL, SPD_MODE_THREADED); + spd_close(conn_); + conn_ = spd_open("chrome", "extension_api", NULL, SPD_MODE_THREADED); +} + +// static +void SpeechDispatcherWrapper::NotificationCallback( + size_t msg_id, size_t client_id, SPDNotificationType type) { + // We run Speech Dispatcher in threaded mode, so these callbacks should always + // be in a separate thread. + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { + SpeechDispatcherWrapper::current_notification_ = type; + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&ExtensionTtsPlatformImplLinux::OnSpeechEvent, + base::Unretained(ExtensionTtsPlatformImplLinux::GetInstance()), + type)); + } +} + +// static +void SpeechDispatcherWrapper::IndexMarkCallback(size_t msg_id, + size_t client_id, + SPDNotificationType state, + char* index_mark) { + // TODO(dtseng): index_mark appears to specify an index type supplied by a + // client. Need to explore how this is used before hooking it up with existing + // word, sentence events. + // We run Speech Dispatcher in threaded mode, so these callbacks should always + // be in a separate thread. + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { + SpeechDispatcherWrapper::current_notification_ = state; + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&ExtensionTtsPlatformImplLinux::OnSpeechEvent, + base::Unretained(ExtensionTtsPlatformImplLinux::GetInstance()), + state)); + } } bool ExtensionTtsPlatformImplLinux::PlatformImplAvailable() { - return libspeechd_loader_.loaded() && (conn_ != NULL); + return spd_.loaded(); } bool ExtensionTtsPlatformImplLinux::Speak( - int utterance_id, - const std::string& utterance, - const std::string& lang, - const UtteranceContinuousParameters& params) { - if (!PlatformImplAvailable()) { + int utterance_id, + const std::string& utterance, + const std::string& lang, + const UtteranceContinuousParameters& params) { + if (!spd_.loaded()) { error_ = kNotSupportedError; return false; } @@ -133,31 +341,22 @@ bool ExtensionTtsPlatformImplLinux::Speak( // Map our multiplicative range to Speech Dispatcher's linear range. // .334 = -100. // 3 = 100. - libspeechd_loader_.spd_set_voice_rate(conn_, 100 * log10(rate) / log10(3)); - libspeechd_loader_.spd_set_voice_pitch(conn_, 100 * log10(pitch) / log10(3)); + spd_.SetRate(100 * log10(rate) / log10(3)); + spd_.SetPitch(100 * log10(pitch) / log10(3)); utterance_ = utterance; utterance_id_ = utterance_id; - if (libspeechd_loader_.spd_say(conn_, SPD_TEXT, utterance.c_str()) == -1) { - Reset(); - return false; - } + spd_.Speak(utterance.c_str()); return true; } bool ExtensionTtsPlatformImplLinux::StopSpeaking() { - if (!PlatformImplAvailable()) - return false; - if (libspeechd_loader_.spd_stop(conn_) == -1) { - Reset(); - return false; - } - return true; + return spd_.StopSpeaking(); } bool ExtensionTtsPlatformImplLinux::IsSpeaking() { - return current_notification_ == SPD_EVENT_BEGIN; + return spd_.IsSpeaking(); } bool ExtensionTtsPlatformImplLinux::SendsEvent(TtsEventType event_type) { @@ -190,39 +389,6 @@ void ExtensionTtsPlatformImplLinux::OnSpeechEvent(SPDNotificationType type) { } // static -void ExtensionTtsPlatformImplLinux::NotificationCallback( - size_t msg_id, size_t client_id, SPDNotificationType type) { - // We run Speech Dispatcher in threaded mode, so these callbacks should always - // be in a separate thread. - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { - current_notification_ = type; - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&ExtensionTtsPlatformImplLinux::OnSpeechEvent, - base::Unretained(ExtensionTtsPlatformImplLinux::GetInstance()), - type)); - } -} - -// static -void ExtensionTtsPlatformImplLinux::IndexMarkCallback(size_t msg_id, - size_t client_id, - SPDNotificationType state, - char* index_mark) { - // TODO(dtseng): index_mark appears to specify an index type supplied by a - // client. Need to explore how this is used before hooking it up with existing - // word, sentence events. - // We run Speech Dispatcher in threaded mode, so these callbacks should always - // be in a separate thread. - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { - current_notification_ = state; - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&ExtensionTtsPlatformImplLinux::OnSpeechEvent, - base::Unretained(ExtensionTtsPlatformImplLinux::GetInstance()), - state)); - } -} - -// static ExtensionTtsPlatformImplLinux* ExtensionTtsPlatformImplLinux::GetInstance() { return Singleton<ExtensionTtsPlatformImplLinux, LeakySingletonTraits<ExtensionTtsPlatformImplLinux> >::get(); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 7d8a702..f8f61cd 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2428,7 +2428,6 @@ 'dependencies': [ 'mtp_file_entry_proto', 'mtp_storage_info_proto', - '../build/linux/system.gyp:libspeechd', '../build/linux/system.gyp:udev', ], 'sources': [ diff --git a/tools/generate_library_loader/generate_library_loader.py b/tools/generate_library_loader/generate_library_loader.py index 5629562..0f5e051 100755 --- a/tools/generate_library_loader/generate_library_loader.py +++ b/tools/generate_library_loader/generate_library_loader.py @@ -44,8 +44,6 @@ class %(class_name)s { bool Load(const std::string& library_name) WARN_UNUSED_RESULT; - bool loaded() const { return loaded_; } - %(member_decls)s private: |