Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Unified Diff: chrome/browser/speech/extension_api/tts_extension_api_linux.cc

Issue 11415243: Linux: use generated library loader for libspeechd. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « build/linux/system.gyp ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/speech/extension_api/tts_extension_api_linux.cc
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 698c03e540a35ca7f5d057f6dc1ad484b532476b..9d1181ef43d9108258f8500d208763d7e0898bc2 100644
--- a/chrome/browser/speech/extension_api/tts_extension_api_linux.cc
+++ b/chrome/browser/speech/extension_api/tts_extension_api_linux.cc
@@ -2,149 +2,22 @@
// 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.";
-// 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;
+} // namespace
class ExtensionTtsPlatformImplLinux : public ExtensionTtsPlatformImpl {
public:
@@ -163,10 +36,25 @@ class ExtensionTtsPlatformImplLinux : public ExtensionTtsPlatformImpl {
static ExtensionTtsPlatformImplLinux* GetInstance();
private:
- ExtensionTtsPlatformImplLinux(): utterance_id_(0) {}
- virtual ~ExtensionTtsPlatformImplLinux() {}
+ ExtensionTtsPlatformImplLinux();
+ virtual ~ExtensionTtsPlatformImplLinux();
+
+ // Resets the connection with speech dispatcher.
+ void Reset();
+
+ static void NotificationCallback(size_t msg_id,
+ size_t client_id,
+ SPDNotificationType type);
- SpeechDispatcherWrapper spd_;
+ 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_;
// These apply to the current utterance only.
std::string utterance_;
@@ -177,157 +65,61 @@ class ExtensionTtsPlatformImplLinux : public ExtensionTtsPlatformImpl {
DISALLOW_COPY_AND_ASSIGN(ExtensionTtsPlatformImplLinux);
};
-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;
+// static
+SPDNotificationType ExtensionTtsPlatformImplLinux::current_notification_ =
+ SPD_EVENT_END;
- spd_close = reinterpret_cast<spd_close_func>(dlsym(library_, "spd_close"));
- if (!spd_close)
+ExtensionTtsPlatformImplLinux::ExtensionTtsPlatformImplLinux()
+ : utterance_id_(0) {
+ if (!libspeechd_loader_.Load("libspeechd.so.2"))
return;
- conn_ = spd_open("chrome", "extension_api", NULL, SPD_MODE_THREADED);
+ conn_ = libspeechd_loader_.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 =
- &SpeechDispatcherWrapper::NotificationCallback;
-
- conn_->callback_im = &SpeechDispatcherWrapper::IndexMarkCallback;
+ &NotificationCallback;
- 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);
+ conn_->callback_im = &IndexMarkCallback;
- loaded_ = true;
+ 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);
}
-SpeechDispatcherWrapper::~SpeechDispatcherWrapper() {
+ExtensionTtsPlatformImplLinux::~ExtensionTtsPlatformImplLinux() {
if (conn_) {
- spd_close(conn_);
+ libspeechd_loader_.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);
}
-// Resets the connection with speech dispatcher.
-void SpeechDispatcherWrapper::Reset() {
+void ExtensionTtsPlatformImplLinux::Reset() {
if (conn_)
- 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));
- }
+ libspeechd_loader_.spd_close(conn_);
+ conn_ = libspeechd_loader_.spd_open(
+ "chrome", "extension_api", NULL, SPD_MODE_THREADED);
}
bool ExtensionTtsPlatformImplLinux::PlatformImplAvailable() {
- return spd_.loaded();
+ return libspeechd_loader_.loaded() && (conn_ != NULL);
}
bool ExtensionTtsPlatformImplLinux::Speak(
- int utterance_id,
- const std::string& utterance,
- const std::string& lang,
- const UtteranceContinuousParameters& params) {
- if (!spd_.loaded()) {
+ int utterance_id,
+ const std::string& utterance,
+ const std::string& lang,
+ const UtteranceContinuousParameters& params) {
+ if (!PlatformImplAvailable()) {
error_ = kNotSupportedError;
return false;
}
@@ -341,22 +133,31 @@ bool ExtensionTtsPlatformImplLinux::Speak(
// Map our multiplicative range to Speech Dispatcher's linear range.
// .334 = -100.
// 3 = 100.
- spd_.SetRate(100 * log10(rate) / log10(3));
- spd_.SetPitch(100 * log10(pitch) / log10(3));
+ libspeechd_loader_.spd_set_voice_rate(conn_, 100 * log10(rate) / log10(3));
+ libspeechd_loader_.spd_set_voice_pitch(conn_, 100 * log10(pitch) / log10(3));
utterance_ = utterance;
utterance_id_ = utterance_id;
- spd_.Speak(utterance.c_str());
+ if (libspeechd_loader_.spd_say(conn_, SPD_TEXT, utterance.c_str()) == -1) {
+ Reset();
+ return false;
+ }
return true;
}
bool ExtensionTtsPlatformImplLinux::StopSpeaking() {
- return spd_.StopSpeaking();
+ if (!PlatformImplAvailable())
+ return false;
+ if (libspeechd_loader_.spd_stop(conn_) == -1) {
+ Reset();
+ return false;
+ }
+ return true;
}
bool ExtensionTtsPlatformImplLinux::IsSpeaking() {
- return spd_.IsSpeaking();
+ return current_notification_ == SPD_EVENT_BEGIN;
}
bool ExtensionTtsPlatformImplLinux::SendsEvent(TtsEventType event_type) {
@@ -389,6 +190,39 @@ 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();
« no previous file with comments | « build/linux/system.gyp ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698