summaryrefslogtreecommitdiff
path: root/plugins/WinterSpeak/src
diff options
context:
space:
mode:
authorPhilip Schell <github.com@blubbfish.net>2013-10-22 12:11:15 +0000
committerPhilip Schell <github.com@blubbfish.net>2013-10-22 12:11:15 +0000
commita27aa5dcda7e65de6e1bb04cfd8ea678242648d0 (patch)
tree6d126293901ae226f0a74f105f026a8f6085bf0f /plugins/WinterSpeak/src
parentd2f13f41feb91bbc53a86207d0a1f75d2d22f8fb (diff)
WinterSpeak now has SAPI40a support ticket:476 and other minor fixes
git-svn-id: http://svn.miranda-ng.org/main/trunk@6584 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/WinterSpeak/src')
-rw-r--r--plugins/WinterSpeak/src/EventInformation.cpp2
-rw-r--r--plugins/WinterSpeak/src/ProtocolInformation.cpp8
-rw-r--r--plugins/WinterSpeak/src/SpeakAnnounce.cpp8
-rw-r--r--plugins/WinterSpeak/src/SpeechApi40a.cpp271
-rw-r--r--plugins/WinterSpeak/src/SpeechApi40a.h88
-rw-r--r--plugins/WinterSpeak/src/SpeechApi40aLexicon.cpp51
-rw-r--r--plugins/WinterSpeak/src/SpeechApi40aLexicon.h28
-rw-r--r--plugins/WinterSpeak/src/SpeechInterface.cpp9
-rw-r--r--plugins/WinterSpeak/src/UserInformation.cpp2
-rw-r--r--plugins/WinterSpeak/src/Version.h6
10 files changed, 452 insertions, 21 deletions
diff --git a/plugins/WinterSpeak/src/EventInformation.cpp b/plugins/WinterSpeak/src/EventInformation.cpp
index 65923022d2..c277a7837a 100644
--- a/plugins/WinterSpeak/src/EventInformation.cpp
+++ b/plugins/WinterSpeak/src/EventInformation.cpp
@@ -67,7 +67,7 @@ std::wstring EventInformation::getMessage()
{
const std::wstring intro = TranslateW(L"%u says");
- return intro + L" " + mir_a2t_cp((char*)m_event_info.pBlob,CP_UTF8);
+ return intro + L" " + mir_a2t_cp((char*)m_event_info.pBlob, CP_UTF8);
}
//------------------------------------------------------------------------------
diff --git a/plugins/WinterSpeak/src/ProtocolInformation.cpp b/plugins/WinterSpeak/src/ProtocolInformation.cpp
index 5fff2526af..19f7c9f70b 100644
--- a/plugins/WinterSpeak/src/ProtocolInformation.cpp
+++ b/plugins/WinterSpeak/src/ProtocolInformation.cpp
@@ -19,9 +19,7 @@ ProtocolInformation::~ProtocolInformation()
m_instance = 0;
// kill all the timers
- for (ProtocolTimeoutQueue::const_iterator iter = m_protocol_timeout.begin();
- iter != m_protocol_timeout.end();
- ++iter)
+ for (ProtocolTimeoutQueue::const_iterator iter = m_protocol_timeout.begin(); iter != m_protocol_timeout.end(); ++iter)
{
KillTimer(NULL, (*iter).second);
}
@@ -59,9 +57,7 @@ bool ProtocolInformation::isDisabled(const char *protocol) const
}
// iterate through the list and see if the protocol has a timer callback
- for (ProtocolTimeoutQueue::const_iterator iter = m_protocol_timeout.begin();
- iter != m_protocol_timeout.end();
- ++iter)
+ for (ProtocolTimeoutQueue::const_iterator iter = m_protocol_timeout.begin(); iter != m_protocol_timeout.end(); ++iter)
{
if (0 == (*iter).first.compare(protocol))
{
diff --git a/plugins/WinterSpeak/src/SpeakAnnounce.cpp b/plugins/WinterSpeak/src/SpeakAnnounce.cpp
index c95550b4af..43efb965d5 100644
--- a/plugins/WinterSpeak/src/SpeakAnnounce.cpp
+++ b/plugins/WinterSpeak/src/SpeakAnnounce.cpp
@@ -19,17 +19,13 @@ void SpeakAnnounce::statusChange(DBCONTACTWRITESETTING *write_setting, HANDLE us
// if the user is myself (NULL) then return
// if it's not a status change then return
// check and update the user's status, if status didn't change the return
- if ((NULL == user)
- || (STATUS != write_setting->szSetting)
- || (!m_user_info.updateStatus(user, write_setting->value.wVal)))
+ if ((NULL == user) || (STATUS != write_setting->szSetting) || (!m_user_info.updateStatus(user, write_setting->value.wVal)))
{
return;
}
// check if we just connected, and want to suppress status changes
- if (!m_db.getStatusFlag(AnnounceDatabase::StatusFlag_SuppressConnect)
- && m_protocol_info.isDisabled(
- (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)user, 0)))
+ if (!m_db.getStatusFlag(AnnounceDatabase::StatusFlag_SuppressConnect) && m_protocol_info.isDisabled((char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)user, 0)))
{
return;
}
diff --git a/plugins/WinterSpeak/src/SpeechApi40a.cpp b/plugins/WinterSpeak/src/SpeechApi40a.cpp
new file mode 100644
index 0000000000..ab15e3e6bc
--- /dev/null
+++ b/plugins/WinterSpeak/src/SpeechApi40a.cpp
@@ -0,0 +1,271 @@
+#include "Common.h"
+#include "SpeechApi40a.h"
+
+#include "SpeechApi40aLexicon.h"
+
+#include <windows.h>
+#include <string.h>
+#include <stdio.h>
+#include <MMSystem.h>
+#include <InitGuid.h>
+#include <ObjBase.h>
+#include <ObjError.h>
+#include <Ole2Ver.h>
+
+#include <speech.h>
+//#include <spchwrap.h>
+
+#include <sstream>
+#include <memory>
+
+//------------------------------------------------------------------------------
+SpeechApi40a::SpeechApi40a() : m_tts_central(0), m_tts_attribs(0), m_state(TextToSpeech::State_Unloaded), m_voice(_T("")), m_volume(50), m_pitch(50), m_rate(50)
+{
+}
+
+//------------------------------------------------------------------------------
+SpeechApi40a::~SpeechApi40a()
+{
+ unload();
+ CoUninitialize();
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi40a::isAvailable()
+{
+ CoInitialize(NULL);
+
+ PITTSENUM pITTSEnum;
+ bool ret = true;
+
+ // create the enumerator
+ if (FAILED(CoCreateInstance(CLSID_TTSEnumerator, NULL, CLSCTX_ALL, IID_ITTSEnum, (void**)&pITTSEnum)))
+ {
+ ret = false;
+ }
+ else
+ {
+ pITTSEnum->Release();
+ }
+ return ret;
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi40a::load()
+{
+ if (isLoaded())
+ {
+ return true;
+ }
+
+ return loadWithVoice(std::wstring(m_voice));
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi40a::unload()
+{
+ if (m_tts_attribs)
+ {
+ m_tts_attribs->Release();
+ m_tts_attribs = 0;
+ }
+
+ if (m_tts_central)
+ {
+ m_tts_central->Release();
+ m_tts_central = 0;
+ }
+
+ m_state = TextToSpeech::State_Unloaded;
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi40a::isLoaded() const
+{
+ return (TextToSpeech::State_Loaded == m_state);
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi40a::say(const std::wstring &sentence)
+{
+ std::string text = mir_t2a_cp(sentence.c_str(), CP_UTF8);
+ bool ret = true;
+
+ if (!isLoaded())
+ {
+ ret = false;
+ }
+ else
+ {
+ SDATA data;
+ data.dwSize = (DWORD)text.size();
+ data.pData = (char *)text.c_str();
+ m_tts_central->TextData(CHARSET_TEXT, 0, data, NULL, IID_ITTSBufNotifySinkA);
+ }
+
+ return ret;
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi40a::setVolume(int volume)
+{
+ m_volume = volume;
+
+ if (!isLoaded())
+ {
+ return true;
+ }
+
+ DWORD new_vol = volume / 100.0 * 0xffff;
+ new_vol |= new_vol << 16;
+
+ if (FAILED(m_tts_attribs->VolumeSet(new_vol)))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi40a::setPitch(int pitch)
+{
+ m_pitch = pitch;
+
+ // valid range is 50 to 350
+ if (isLoaded() && FAILED(m_tts_attribs->PitchSet(pitch * 3.0 + 50)))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi40a::setRate(int rate)
+{
+ m_rate = rate;
+
+ // valid range is 50 to 350
+ if (isLoaded() && FAILED(m_tts_attribs->SpeedSet(rate * 3.0 + 50)))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi40a::setVoice(const std::wstring &voice)
+{
+ m_voice = voice;
+
+ if (!isLoaded())
+ {
+ return true;
+ }
+
+ unload();
+ return load();
+}
+
+//------------------------------------------------------------------------------
+std::vector<std::wstring> SpeechApi40a::getVoices() const
+{
+ std::vector<std::wstring> ret;
+
+ PITTSENUM pITTSEnum = NULL;
+ TTSMODEINFO inf;
+
+ CoInitialize(NULL);
+
+ if (FAILED(CoCreateInstance(CLSID_TTSEnumerator, NULL, CLSCTX_ALL, IID_ITTSEnum, (void**)&pITTSEnum)))
+ {
+ return ret;
+ }
+
+ while (!pITTSEnum->Next(1, &inf, NULL))
+ {
+ ret.push_back(inf.szModeName);
+ }
+
+ pITTSEnum->Release();
+
+ return ret;
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi40a::lexiconDialog(HWND window)
+{
+ // open the dialog
+ SpeechApi40aLexicon dialog(window, m_tts_central);
+
+ if (!dialog.display())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+std::wstring SpeechApi40a::getDescription()
+{
+ return _T("Microsoft SAPI v4.0");
+}
+
+//------------------------------------------------------------------------------
+// private:
+//------------------------------------------------------------------------------
+bool SpeechApi40a::loadWithVoice(std::wstring &voice)
+{
+ CoInitialize(NULL);
+
+ PITTSENUM pITTSEnum;
+ TTSMODEINFO inf;
+ LPUNKNOWN pAudioDest;
+
+ // create the enumerator
+ if (FAILED(CoCreateInstance(CLSID_TTSEnumerator, NULL, CLSCTX_ALL, IID_ITTSEnum, (void**)&pITTSEnum)))
+ {
+ return false;
+ }
+
+ // iterate through the voices until we find the right one
+ while (!pITTSEnum->Next(1, &inf, NULL))
+ {
+ if (inf.szModeName == voice)
+ {
+ break;
+ }
+ }
+
+ if (FAILED(CoCreateInstance(CLSID_MMAudioDest, NULL, CLSCTX_ALL, IID_IAudioMultiMediaDevice, (void**)&pAudioDest)))
+ {
+ pITTSEnum->Release();
+ return false;
+ }
+
+ // select that voice
+ if (FAILED(pITTSEnum->Select(inf.gModeID, &m_tts_central, pAudioDest)))
+ {
+ pITTSEnum->Release();
+ return NULL;
+ }
+
+ m_tts_central->QueryInterface(IID_ITTSAttributes, (LPVOID *)&m_tts_attribs);
+
+ pITTSEnum->Release();
+
+ // we made it
+ m_state = TextToSpeech::State_Loaded;
+
+ // configure the new voice
+ setVolume(m_volume);
+ setRate(m_rate);
+ setPitch(m_pitch);
+
+ return true;
+} \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/SpeechApi40a.h b/plugins/WinterSpeak/src/SpeechApi40a.h
new file mode 100644
index 0000000000..e9b524f954
--- /dev/null
+++ b/plugins/WinterSpeak/src/SpeechApi40a.h
@@ -0,0 +1,88 @@
+#pragma once
+#include "texttospeech.h"
+
+struct ITTSCentralW;
+struct ITTSAttributesA;
+
+class SpeechApi40a : public TextToSpeech
+{
+ public:
+ SpeechApi40a();
+ virtual ~SpeechApi40a();
+
+ //--------------------------------------------------------------------------
+ // Description : is the api available for use
+ // Return : true - it is available
+ // false - it is not available
+ //--------------------------------------------------------------------------
+ virtual bool isAvailable();
+
+ //--------------------------------------------------------------------------
+ // Description : load/unload/reload the speech api
+ // Return : true - the action succeeded
+ // false - the action failed
+ //--------------------------------------------------------------------------
+ virtual bool load();
+ virtual bool unload();
+
+ //--------------------------------------------------------------------------
+ // Description : check if the speech api is loaded
+ // Return : true - the speech_api is loaded
+ // false - its not loaded
+ //--------------------------------------------------------------------------
+ virtual bool isLoaded() const;
+
+ //--------------------------------------------------------------------------
+ // Description : speak a sentence
+ // Parameters : sentence - the sentence to speak
+ // Returns : true - speak successful
+ // false - speak failed
+ //--------------------------------------------------------------------------
+ virtual bool say(const std::wstring &sentence);
+
+ //--------------------------------------------------------------------------
+ // Description : set the voice settings
+ // Parameters : range from 0 to 100
+ //--------------------------------------------------------------------------
+ virtual bool setVolume(int volume);
+ virtual bool setPitch(int pitch);
+ virtual bool setRate(int rate);
+
+ //--------------------------------------------------------------------------
+ // Description : set the voice
+ //--------------------------------------------------------------------------
+ virtual bool setVoice(const std::wstring &voice);
+
+ //--------------------------------------------------------------------------
+ // Description : get the available voices
+ //--------------------------------------------------------------------------
+ virtual std::vector<std::wstring> getVoices() const;
+
+ //--------------------------------------------------------------------------
+ // Description : open the lexicon dialog for this engine
+ // Parameters : window - handle to the parent window
+ // Return : true - dialog completely successfully
+ // false - dialog failed
+ //--------------------------------------------------------------------------
+ virtual bool lexiconDialog(HWND window);
+
+ //--------------------------------------------------------------------------
+ // Description : get the description of the tts engine
+ //--------------------------------------------------------------------------
+ static std::wstring getDescription();
+
+ private:
+ //--------------------------------------------------------------------------
+ // Description : load the speech api with the specified voice
+ //--------------------------------------------------------------------------
+ bool loadWithVoice(std::wstring &voice);
+
+ ITTSCentralW *m_tts_central;
+ ITTSAttributesA *m_tts_attribs;
+
+ TextToSpeech::State m_state;
+ std::wstring m_voice;
+ int m_volume;
+ int m_pitch;
+ int m_rate;
+}; \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/SpeechApi40aLexicon.cpp b/plugins/WinterSpeak/src/SpeechApi40aLexicon.cpp
new file mode 100644
index 0000000000..efb82b84e7
--- /dev/null
+++ b/plugins/WinterSpeak/src/SpeechApi40aLexicon.cpp
@@ -0,0 +1,51 @@
+#include "Common.h"
+#include "SpeechApi40aLexicon.h"
+
+#include <windows.h>
+#include <string.h>
+#include <stdio.h>
+#include <MMSystem.h>
+#include <InitGuid.h>
+#include <ObjBase.h>
+#include <ObjError.h>
+#include <Ole2Ver.h>
+
+#include <speech.h>
+//#include <spchwrap.h>
+
+
+//------------------------------------------------------------------------------
+SpeechApi40aLexicon::SpeechApi40aLexicon(HWND window, ITTSCentralW *tts_central) : m_window(window), m_tts_central(tts_central)
+{
+}
+
+//------------------------------------------------------------------------------
+SpeechApi40aLexicon::~SpeechApi40aLexicon()
+{
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi40aLexicon::display()
+{
+ if (!m_tts_central)
+ {
+ return false;
+ }
+
+ ITTSDialogs *tts_dialogs = 0;
+
+ m_tts_central->QueryInterface(IID_ITTSDialogs, (void**)&tts_dialogs);
+
+ if (!tts_dialogs)
+ {
+ return false;
+ }
+
+ if (NOERROR != tts_dialogs->LexiconDlg(m_window, NULL))
+ {
+ return false;
+ }
+
+ tts_dialogs->Release();
+ return true;
+}
diff --git a/plugins/WinterSpeak/src/SpeechApi40aLexicon.h b/plugins/WinterSpeak/src/SpeechApi40aLexicon.h
new file mode 100644
index 0000000000..73bee51cb9
--- /dev/null
+++ b/plugins/WinterSpeak/src/SpeechApi40aLexicon.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <wtypes.h>
+
+struct ITTSCentralW;
+class SpeechApi40aLexicon
+{
+ public:
+ //--------------------------------------------------------------------------
+ // Description : Constuctor
+ // Parameters : window - handle to the parent window
+ // tts_central - pointer to the tts_central engine to use
+ //--------------------------------------------------------------------------
+ SpeechApi40aLexicon(HWND window, ITTSCentralW *tts_central);
+
+ ~SpeechApi40aLexicon();
+
+ //--------------------------------------------------------------------------
+ // Description : display the lexicon dialog
+ // Return : true - display ok
+ // false - display failed
+ //--------------------------------------------------------------------------
+ bool display();
+
+ private:
+ HWND m_window;
+ ITTSCentralW *m_tts_central;
+}; \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/SpeechInterface.cpp b/plugins/WinterSpeak/src/SpeechInterface.cpp
index 500165f356..261cf547ec 100644
--- a/plugins/WinterSpeak/src/SpeechInterface.cpp
+++ b/plugins/WinterSpeak/src/SpeechInterface.cpp
@@ -1,6 +1,7 @@
#include "Common.h"
#include "SpeechInterface.h"
#include "SpeechApi51.h"
+#include "SpeechApi40a.h"
SpeechInterface::SpeechInterface()
@@ -17,11 +18,11 @@ TextToSpeech * SpeechInterface::createTts(std::wstring &engine) const
{
TextToSpeech *tts = 0;
- /*if (SpeechApi40a::getDescription() == engine)
+ if (SpeechApi40a::getDescription() == engine)
{
tts = new SpeechApi40a();
}
- else*/
+ else
if (SpeechApi51::getDescription() == engine)
{
tts = new SpeechApi51();
@@ -50,11 +51,11 @@ std::vector<std::wstring> SpeechInterface::getAvailableEngines()
{
std::vector<std::wstring> engines;
- /*SpeechApi40a sapi40a;
+ SpeechApi40a sapi40a;
if (sapi40a.isAvailable())
{
engines.push_back(SpeechApi40a::getDescription());
- }*/
+ }
SpeechApi51 sapi51;
if (sapi51.isAvailable())
diff --git a/plugins/WinterSpeak/src/UserInformation.cpp b/plugins/WinterSpeak/src/UserInformation.cpp
index fa5db0b0e5..7163e9b23e 100644
--- a/plugins/WinterSpeak/src/UserInformation.cpp
+++ b/plugins/WinterSpeak/src/UserInformation.cpp
@@ -72,7 +72,7 @@ std::wstring UserInformation::nameString(HANDLE user) const
{
return L"";
}
- return TranslateW(mir_a2t(ret));
+ return TranslateW(mir_a2t_cp(ret, CP_UTF8));
}
//==============================================================================
diff --git a/plugins/WinterSpeak/src/Version.h b/plugins/WinterSpeak/src/Version.h
index 6dcfc0d27f..2c10081d2e 100644
--- a/plugins/WinterSpeak/src/Version.h
+++ b/plugins/WinterSpeak/src/Version.h
@@ -1,12 +1,12 @@
#define __MAJOR_VERSION 0
#define __MINOR_VERSION 9
#define __RELEASE_NUM 8
-#define __BUILD_NUM 0
+#define __BUILD_NUM 2
#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
-#define __PLUGIN_NAME "Speak"
-#define __FILENAME "speak.dll"
+#define __PLUGIN_NAME "WinterSpeak"
+#define __FILENAME "winterspeak.dll"
#define __DESCRIPTION "Miranda interface to the Microsoft Speech API"
#define __AUTHOR "Ryan Winter, BlubbFish"
#define __AUTHOREMAIL "miranda@blubbfish.net"