summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordpapad@chromium.org <dpapad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-17 22:56:57 +0000
committerdpapad@chromium.org <dpapad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-17 22:56:57 +0000
commitbe7c1ac4c494b6f3de8297e915e87787ba561017 (patch)
tree74ebb34db8c3f400371cca5245c095d52e0da351
parent8801db19b85897e62484312f273d4a5c9d33abf2 (diff)
downloadchromium_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.gyp57
-rw-r--r--chrome/browser/speech/extension_api/tts_extension_api_linux.cc358
-rw-r--r--chrome/chrome_browser.gypi1
-rwxr-xr-xtools/generate_library_loader/generate_library_loader.py2
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: