//------------------------------------------------------------------------------ bool SpeechApi51::setVoice(const std::wstring &voice) { m_voice = voice; if (!isLoaded()) { return true; } // get a voice enumerator CComPtr<IEnumSpObjectTokens> cpEnum; if (FAILED(SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum))) { return false; } // iterate through the list till we find a matching voice ISpObjectToken *voice_token; while (S_OK == cpEnum->Next(1, &voice_token, NULL)) { CSpDynamicString voice_str; if (SUCCEEDED(SpGetDescription(voice_token, &voice_str)) && (voice == voice_str.Copy())) { m_sapi->SetVoice(voice_token); return true; } } return false; }
QtSpeech::VoiceNames QtSpeech::voices() { VoiceNames vs; ULONG count = 0; CComPtr<IEnumSpObjectTokens> voices; CoInitialize(NULL); SysCall( SpEnumTokens(SPCAT_VOICES, NULL, NULL, &voices), LogicError); SysCall( voices->GetCount(&count), LogicError); for(int i=0; i< count; i++) { WCHAR * w_id = 0L; WCHAR * w_name = 0L; CComPtr<ISpObjectToken> voice; SysCall( voices->Next( 1, &voice, NULL ), LogicError); SysCall( SpGetDescription(voice, &w_name), LogicError); SysCall( voice->GetId(&w_id), LogicError); QString id = QString::fromWCharArray(w_id); QString name = QString::fromWCharArray(w_name); VoiceName n = { id, name }; vs << n; voice.Release(); } return vs; }
//------------------------------------------------------------------------------ std::vector<std::wstring> SpeechApi51::getVoices() const { std::vector<std::wstring> ret; CoInitialize(NULL); // get a voice enumerator CComPtr<IEnumSpObjectTokens> cpEnum; if (S_OK != SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum)) { return ret; } // iterate through the voices and add them to the string vector ISpObjectToken *voice_token; while (S_OK == cpEnum->Next(1, &voice_token, NULL)) { CSpDynamicString voice_str; if (SUCCEEDED(SpGetDescription(voice_token, &voice_str))) { ret.push_back(voice_str.Copy()); } } return ret; }
std::string CSpeechSynthesizer::GetVoice() { wchar_t* desc = new wchar_t[256]; SpGetDescription(cpToken, &desc); char desctext[256] = { 0 }; wcstombs(desctext, desc, 256); std::string voiceName = std::string(desctext); return voiceName; }
//Get available voices in system std::vector<WCHAR*> TTSLib::GetVoices() { std::vector<WCHAR*> voiceNames; voiceNames.resize(m_ispObjectTokens.size()); WCHAR *description; for (size_t i = 0; i < m_ispObjectTokens.size(); ++i) { SpGetDescription(m_ispObjectTokens[i], &description); voiceNames[i]= description; } return voiceNames; }
std::list<std::string*>* CSpeechSynthesizer::GetAvailableVoices() { std::list<std::string*>* namelist = new std::list<std::string*>(); // if we're not initialized return an empty list if (!m_initialized) return namelist; if (m_tokenMap->size() < 1) { for (std::map<std::string*, std::string*>::iterator mit = m_registryList->begin(); mit != m_registryList->end(); mit++) { std::string regToken = (*mit).first->c_str(); regToken.append("\\"); regToken.append((*mit).second->c_str()); // Enumerate voice tokens const char* text = regToken.c_str(); int size_needed = MultiByteToWideChar(CP_UTF8, 0, &text[0], (int)strlen(text), NULL, 0); TCHAR tokenId[1024] = { 0 }; MultiByteToWideChar(CP_UTF8, 0, &text[0], (int)strlen(text), &tokenId[0], size_needed); CComPtr<ISpObjectToken> cpTokenObj; HRESULT hr = SpGetTokenFromId(tokenId, &cpTokenObj, false); if (SUCCEEDED(hr)) { wchar_t* desc = new wchar_t[256]; SpGetDescription(cpTokenObj, &desc); char desctext[256] = { 0 }; wcstombs(desctext, desc, 256); std::string* voiceName = new std::string(desctext); namelist->push_back(voiceName); m_tokenMap->insert(std::pair<std::string*, std::string*>(voiceName, new std::string(regToken.c_str()))); } if (cpTokenObj != NULL) cpTokenObj.Release(); } } else { for (std::map<std::string*, std::string*>::iterator mit = m_tokenMap->begin(); mit != m_tokenMap->end(); mit++) { namelist->push_back((*mit).first); } } return namelist; }
void DumpCategory(LPCWSTR category) { // enumerate tokens in each category IEnumSpObjectTokens *pEnumSpObjectTokens = nullptr; HRESULT hr = SpEnumTokens(category, nullptr, nullptr, &pEnumSpObjectTokens); if (SPERR_NOT_FOUND == hr) { LOG(L" None found."); return; } else if (FAILED(hr)) { ERR(L"SpEnumTokens failed: hr = 0x%08x", hr); return; } ReleaseOnExit rEnumSpObjectTokens(pEnumSpObjectTokens); ULONG nTokens = 0; hr = pEnumSpObjectTokens->GetCount(&nTokens); if (FAILED(hr)) { ERR(L"IEnumSpObjectTokens::GetCount failed: hr = 0x%08x", hr); return; } for (ULONG token = 0; token < nTokens; token++) { ISpObjectToken *pSpObjectToken = nullptr; hr = pEnumSpObjectTokens->Next(1, &pSpObjectToken, nullptr); if (FAILED(hr)) { ERR(L"IEnumSpObjectTokens::Next failed: hr = 0x%08x", hr); return; } ReleaseOnExit rSpObjectToken(pSpObjectToken); LPWSTR description = nullptr; hr = SpGetDescription(pSpObjectToken, &description); if (FAILED(hr)) { ERR(L"SpGetDescription failed: hr = 0x%08x", hr); continue; } CoTaskMemFreeOnExit fDescription(description); LOG(L" #%u: %s", token + 1, description); EnumDataKey(2, pSpObjectToken); } }
QtSpeech::QtSpeech(VoiceName n, QObject * parent) :QObject(parent), d(new Private) { ULONG count = 0; CComPtr<IEnumSpObjectTokens> voices; CoInitialize(NULL); SysCall( d->voice.CoCreateInstance( CLSID_SpVoice ), InitError); if (n.id.isEmpty()) { WCHAR * w_id = 0L; WCHAR * w_name = 0L; CComPtr<ISpObjectToken> voice; SysCall( d->voice->GetVoice(&voice), InitError); SysCall( SpGetDescription(voice, &w_name), InitError); SysCall( voice->GetId(&w_id), InitError); n.name = QString::fromWCharArray(w_name); n.id = QString::fromWCharArray(w_id); voice.Release(); } else { SysCall( SpEnumTokens(SPCAT_VOICES, NULL, NULL, &voices), InitError); SysCall( voices->GetCount(&count), InitError); for (int i =0; i< count; i++) { WCHAR * w_id = 0L; CComPtr<ISpObjectToken> voice; SysCall( voices->Next( 1, &voice, NULL ), InitError); SysCall( voice->GetId(&w_id), InitError); QString id = QString::fromWCharArray(w_id); if (id == n.id) d->voice->SetVoice(voice); voice.Release(); } } if (n.id.isEmpty()) throw InitError(Where+"No default voice in system"); d->name = n; d->ptrs << this; }
TTSWidget::TTSWidget(QWidget* parent /*= 0*/, Qt::WFlags flags /*= 0*/) : QWidget(parent, flags) { setupUi(this); #ifdef _WIN32 CoInitialize(NULL); HRESULT hr = S_OK; CComPtr<ISpObjectToken> cpVoiceToken; CComPtr<IEnumSpObjectTokens> cpEnum; CComPtr<ISpVoice> cpVoice; ULONG ulCount = 0; // Create the SAPI voice if(SUCCEEDED(hr)) hr = cpVoice.CoCreateInstance( CLSID_SpVoice ); //Enumerate the available voices if(SUCCEEDED(hr)) hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum); //Get the number of voices if(SUCCEEDED(hr)) hr = cpEnum->GetCount(&ulCount); // Obtain a list of available voice tokens while (SUCCEEDED(hr) && ulCount-- ) { cpVoiceToken.Release(); if(SUCCEEDED(hr)) hr = cpEnum->Next( 1, &cpVoiceToken, NULL ); WCHAR* voiceName = 0; if (SUCCEEDED(SpGetDescription(cpVoiceToken, &voiceName))) { m_voice->addItem(QString::fromUtf16((const ushort*) voiceName)); CoTaskMemFree(voiceName); } } CoUninitialize(); #endif connect(m_voice, SIGNAL(currentIndexChanged(int)), this, SLOT(voiceChanged(int))); connect(m_speakButton, SIGNAL(clicked()), this, SLOT(speak())); }
bool SapiInterface::SetVoiceNative(CString voice) { CComPtr<IEnumSpObjectTokens> cpEnum; CSpDynamicString* szDescription; CComPtr<ISpObjectToken> cpVoiceToken; //the token is the voice CComPtr<ISpVoice> cpVoice; ULONG ulCount = 0; //This gets an enumeration of all voices on the system hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum); if (!SUCCEEDED(hr) ){ return false; //enumeration of voices failed } hr = cpEnum->GetCount(&ulCount); szDescription = new CSpDynamicString [ulCount]; UINT i = 0; while (SUCCEEDED(hr) && ulCount--) { cpVoiceToken.Release(); if (SUCCEEDED (hr)) { hr = cpEnum->Next(1, &cpVoiceToken, NULL); hr = SpGetDescription(cpVoiceToken, &szDescription[i]); } if (SUCCEEDED (hr)) { if(CString(szDescription[i]) == voice) { hr = pVoice->SetVoice(cpVoiceToken); delete [] szDescription; return true; } } i++; } //delete the voice list if one is not found and return false delete [] szDescription; return false; }
// implementation QtSpeech::QtSpeech(QObject * parent) :QObject(parent), d(new Private) { CoInitialize(NULL); SysCall( d->voice.CoCreateInstance( CLSID_SpVoice ), InitError); VoiceName n; WCHAR * w_id = 0L; WCHAR * w_name = 0L; CComPtr<ISpObjectToken> voice; SysCall( d->voice->GetVoice(&voice), InitError); SysCall( SpGetDescription(voice, &w_name), InitError); SysCall( voice->GetId(&w_id), InitError); n.name = QString::fromWCharArray(w_name); n.id = QString::fromWCharArray(w_id); voice.Release(); if (n.id.isEmpty()) throw InitError(Where+"No default voice in system"); d->name = n; d->ptrs << this; }
int voice_getVoices(lua_State *L) { if (!pVoice || !pTokens) return error_voice(L); if (lua_gettop(L) == 0) { ULONG count = 0; HRESULT hr = pTokens->GetCount(&count); if (FAILED(hr)) { lua_pushnil(L); return 1; } lua_newtable(L); WCHAR *buffer = NULL; ISpObjectToken *token = NULL; for (ULONG i=0; i<count; ++i) { pTokens->Item(i, &token); LANGID lang = 0; hr = SpGetLanguageFromToken(token, &lang); if (SUCCEEDED(hr)) hr = SpGetDescription(token, &buffer, lang); token->Release(); token=NULL; if (SUCCEEDED(hr)) { lua_pushinteger(L, i+1); lua_pushwstring(L, buffer); lua_settable(L, -3); CoTaskMemFree(buffer); buffer = NULL; } } return 1; } return error_invargs(L, L"getVoices"); }
/* * Some notes about this function: * This function returns a list of available SAPI voices. It has been fixed and should be working correclty * on Windows 7 and all other versions of Windows. * * The solution to getting this function working was found here: * http://stackoverflow.com/questions/4336245/how-to-return-a-java-string-in-c-using-jni * * In addition to the above StackOverflow thread, it was necessary to change this function to return an std::string instance instead * of a character pointer, and to use stringstreams instead of CStrings. */ std::string SapiInterface::GetVoiceNative() { std::stringstream sstream; sstream << "<?xml version=\"1.0\"?>"; ISpVoice * pVoice = NULL; CComPtr<ISpObjectToken> cpVoiceToken; CComPtr<IEnumSpObjectTokens> cpEnum; CComPtr<ISpVoice> cpVoice; ULONG ulCount = 0; HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice); if(SUCCEEDED(hr)) { WCHAR **m_ppszTokenIds; USES_CONVERSION; CComPtr<IEnumSpObjectTokens> cpEnum; WCHAR** szDescription; ISpObjectToken *pToken = NULL; CComPtr<ISpObjectToken> cpVoiceToken; //the token is the voice CComPtr<ISpVoice> cpVoice; ULONG ulCount = 0; if(SUCCEEDED(hr)) { hr = cpVoice.CoCreateInstance( CLSID_SpVoice ); if(SUCCEEDED(hr)) { WCHAR *pszCurTokenId = NULL; ULONG ulIndex = 0, ulNumTokens = 0, ulCurToken = -1; hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum); if (hr == S_OK) { hr = cpEnum->GetCount( &ulNumTokens ); if (SUCCEEDED(hr) && ulNumTokens != 0) { szDescription = new WCHAR* [ulNumTokens]; m_ppszTokenIds = new WCHAR* [ulNumTokens]; ZeroMemory(m_ppszTokenIds, ulNumTokens * sizeof(WCHAR *)); UINT i =0; while (cpEnum->Next(1, &pToken, NULL) == S_OK) { //Don't care about return value in next line: hr = SpGetDescription(pToken, &szDescription[ulIndex]); ulIndex++; int utf8_length = WideCharToMultiByte( CP_UTF8, // Convert to UTF-8 0, // No special character conversions required // (UTF-16 and UTF-8 support the same characters) szDescription[i], // UTF-16 string to convert -1, // utf16 is NULL terminated (if not, use length) NULL, // Determining correct output buffer size 0, // Determining correct output buffer size NULL, // Must be NULL for CP_UTF8 NULL); // Must be NULL for CP_UTF8 if (utf8_length == 0) { return std::string("WideCharToMultibyte error."); } char *utf8_voice = new char[utf8_length]; utf8_length = WideCharToMultiByte( CP_UTF8, // Convert to UTF-8 0, // No special character conversions required // (UTF-16 and UTF-8 support the same characters) szDescription[i], // UTF-16 string to convert -1, // utf16 is NULL terminated (if not, use length) utf8_voice, // UTF-8 output buffer utf8_length, // UTF-8 output buffer size NULL, // Must be NULL for CP_UTF8 NULL); // Must be NULL for CP_UTF8 //strConcatenateXML += "<voice>" + szDescription[i] + "</voice>"; sstream << "<voice>" << utf8_voice << "</voice>"; pToken->Release(); pToken = NULL; i++; } delete [] szDescription; } else { //strConcatenateXML = "No voice found. (5)"; sstream << "No voice found. (5)"; } } else { //strConcatenateXML = "No voice found. (4)"; sstream << "No voice found. (4)"; } } else { //strConcatenateXML = "No voice found. (3)"; sstream << "No voice found. (3)"; } } else { //strConcatenateXML = "No voice found. (2)"; sstream << "No voice found. (2)"; } } else { //strConcatenateXML = "No voice found. (1)"; sstream << "No voice found. (1)"; } return sstream.str(); }
/****************************************************************************** * ManageEmployeesPaneProc * *-------------------------* * Description: * Handles messages specifically for the manage employees pane. * ******************************************************************************/ LRESULT ManageEmployeesPaneProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { USES_CONVERSION; static ULONG ulNumTokens; static ULONG ulCurToken; static WCHAR** ppszTokenIds; static CSpDynamicString* ppcDesciptionString; // This is string helper class in sphelper.h switch ( message ) { case WM_GOTOOFFICE: { // Set the right message handler and repaint g_fpCurrentPane = OfficePaneProc; //Cleanup our variables ManageEmployeesPaneCleanup( ppszTokenIds, ppcDesciptionString, ulNumTokens ); ppszTokenIds = NULL; ppcDesciptionString = NULL; ulNumTokens = 0; // Set the hear voice rule to inactive HRESULT hr = g_cpCmdGrammar->SetRuleIdState( VID_HearTheVoice, SPRS_INACTIVE ); _ASSERTE( SUCCEEDED( hr ) ); PostMessage( hWnd, WM_INITPANE, NULL, NULL ); InvalidateRect( hWnd, NULL, TRUE ); return ( 1 ); } case WM_GOTOCOUNTER: { // Set the right message handler and repaint g_fpCurrentPane = CounterPaneProc; //Cleanup our variables ManageEmployeesPaneCleanup( ppszTokenIds, ppcDesciptionString, ulNumTokens ); ppszTokenIds = NULL; ppcDesciptionString = NULL; ulNumTokens = 0; // Set the hear voice rule to inactive HRESULT hr = g_cpCmdGrammar->SetRuleIdState( VID_HearTheVoice, SPRS_INACTIVE ); _ASSERTE( SUCCEEDED( hr ) ); PostMessage( hWnd, WM_INITPANE, NULL, NULL ); InvalidateRect( hWnd, NULL, TRUE ); return ( 1 ); } case WM_PAINT: { // Do the actual UI paint ManageEmployeesPanePaint( hWnd, ulNumTokens, ppcDesciptionString, ulCurToken ); return ( 1 ); } case WM_INITPANE: { ISpObjectToken *pToken = NULL; // Token interface pointer CComPtr<IEnumSpObjectTokens> cpEnum; // Pointer to token enumerator ULONG ulIndex = 0; ulCurToken = 0xffffffff; // Get a token enumerator for tts voices available HRESULT hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum); if ( S_OK == hr ) { // Get the numbers of tokens found hr = cpEnum->GetCount( &ulNumTokens ); if ( SUCCEEDED( hr ) && 0 != ulNumTokens ) { // Create arrays we need for storing data ppcDesciptionString = new CSpDynamicString [ulNumTokens]; if ( NULL == ppcDesciptionString ) { hr = E_OUTOFMEMORY; break; } ppszTokenIds = new WCHAR* [ulNumTokens]; if ( NULL == ppszTokenIds ) { hr = E_OUTOFMEMORY; break; } ZeroMemory( ppszTokenIds, ulNumTokens*sizeof( WCHAR* ) ); // Get the next token in the enumeration // State is maintained in the enumerator while (cpEnum->Next(1, &pToken, NULL) == S_OK) { // Get a string which describes the token, in our case, the voice name hr = SpGetDescription( pToken, &ppcDesciptionString[ulIndex] ); _ASSERTE( SUCCEEDED( hr ) ); // Get the token id, for a low overhead way to retrieve the token later // without holding on to the object itself hr = pToken->GetId( &ppszTokenIds[ulIndex] ); _ASSERTE( SUCCEEDED( hr ) ); ulIndex++; // Release the token itself pToken->Release(); pToken = NULL; } } // if we've failed to properly initialize, then we should completely shut-down if ( S_OK != hr ) { if ( pToken ) { pToken->Release(); } ManageEmployeesPaneCleanup( ppszTokenIds, ppcDesciptionString, ulNumTokens ); ppszTokenIds = NULL; ppcDesciptionString = NULL; ulNumTokens = 0; } // Find out which token corresponds to our voice which is currently in use else { WCHAR *pszCurTokenId = NULL; // Get the token representing the current voice HRESULT hr = g_cpVoice->GetVoice( &pToken ); if ( SUCCEEDED( hr ) ) { // Get the current token ID, and compare it against others to figure out // which desciption string is the one currently selected. hr = pToken->GetId( &pszCurTokenId ); if ( SUCCEEDED( hr ) ) { ulIndex = 0; while ( ulIndex < ulNumTokens && 0 != _wcsicmp( pszCurTokenId, ppszTokenIds[ulIndex] ) ) { ulIndex++; } // We found it, so set the current index to that of the current token if ( ulIndex < ulNumTokens ) { ulCurToken = ulIndex; } CoTaskMemFree( pszCurTokenId ); } pToken->Release(); } } } // Set the hear voice rule to active hr = g_cpCmdGrammar->SetRuleIdState( VID_HearTheVoice, SPRS_ACTIVE ); _ASSERTE( SUCCEEDED( hr ) ); return ( 1 ); } case WM_DESTROY: // Windows is closing down, so we should cleanup ManageEmployeesPaneCleanup( ppszTokenIds, ppcDesciptionString, ulNumTokens ); return ( 1 ); case WM_HEARTHEVOICE: // Set the voice to play LoadString( g_hInst, IDS_VOICESPEAK, g_szCounterDisplay, MAX_LOADSTRING ); g_cpVoice->Speak( T2W(g_szCounterDisplay), SPF_ASYNC | SPF_PURGEBEFORESPEAK, NULL ); } return ( 0 ); }
static void configure() { configure_changed = false; GtkWidget *window = gtk_dialog_new_with_buttons(_("SAPI TTS configuration"), GTK_WINDOW(plugin_info->pluginwin), GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); GtkWidget *vbox = gtk_vbox_new(false, 5); gtk_container_set_border_width(GTK_CONTAINER(vbox),5); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(window)->vbox), vbox); GtkWidget *frame = gtk_frame_new(_("TTS voice engine")); gtk_box_pack_start(GTK_BOX(vbox), frame, false, false, 3); GtkWidget *table = gtk_table_new(2, 3, false); gtk_container_set_border_width(GTK_CONTAINER(table),8); gtk_container_add (GTK_CONTAINER (frame), table); GtkWidget *label = gtk_label_new(_("Voice :")); gtk_misc_set_alignment (GTK_MISC (label), 0, .5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, (GtkAttachOptions)0, 5, 0); GtkWidget *combobox = gtk_combo_box_new_text(); gtk_table_attach(GTK_TABLE(table), combobox, 1, 2, 0, 1, GtkAttachOptions(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 5, 0); ULONG ulNumTokens; WCHAR** ppszTokenIds = NULL; CComPtr<IEnumSpObjectTokens> cpEnum; HRESULT hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum); if ( S_OK == hr ) { hr = cpEnum->GetCount( &ulNumTokens ); if ( SUCCEEDED( hr ) && 0 != ulNumTokens ) { WCHAR *pszCurTokenId = NULL; ISpObjectToken *pToken; HRESULT hr = pVoice->GetVoice( &pToken ); if ( SUCCEEDED( hr ) ) { pToken->GetId( &pszCurTokenId ); pToken->Release(); } if (pszCurTokenId) { ppszTokenIds = new WCHAR* [ulNumTokens]; ZeroMemory( ppszTokenIds, ulNumTokens*sizeof( WCHAR* ) ); LONG ulCurToken = -1; ULONG ulIndex = 0; while (cpEnum->Next(1, &pToken, NULL) == S_OK) { WCHAR *description; SpGetDescription( pToken, &description); DWORD dwNum = WideCharToMultiByte(CP_UTF8,NULL,description,-1,NULL,0,NULL,FALSE); char *text = new char[dwNum]; WideCharToMultiByte (CP_UTF8,NULL,description,-1,text,dwNum,NULL,FALSE); gtk_combo_box_append_text(GTK_COMBO_BOX(combobox), text); delete []text; CoTaskMemFree(description); pToken->GetId( &ppszTokenIds[ulIndex]); if (ulCurToken == -1 && _wcsicmp( pszCurTokenId, ppszTokenIds[ulIndex]) == 0) { ulCurToken = ulIndex; } ulIndex++; pToken->Release(); } CoTaskMemFree( pszCurTokenId ); if (ulCurToken != -1) gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), ulCurToken); } } } g_signal_connect (G_OBJECT (combobox), "changed", G_CALLBACK (on_voice_combobox_changed), ppszTokenIds); label = gtk_label_new(_("Volume :")); gtk_misc_set_alignment (GTK_MISC (label), 0, .5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, (GtkAttachOptions)0, 5, 0); GtkWidget *volume_hscale = gtk_hscale_new_with_range(0, 100, 1); gtk_table_attach(GTK_TABLE(table), volume_hscale, 1, 2, 1, 2, GtkAttachOptions(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 5, 0); USHORT volume; pVoice->GetVolume(&volume); gtk_range_set_value(GTK_RANGE(volume_hscale), volume); g_signal_connect(G_OBJECT(volume_hscale),"value-changed", G_CALLBACK(on_volume_hscale_value_changed), NULL); label = gtk_label_new(_("Rate :")); gtk_misc_set_alignment (GTK_MISC (label), 0, .5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, (GtkAttachOptions)0, 5, 0); GtkWidget *rate_hscale = gtk_hscale_new_with_range(-10, 10, 1); gtk_table_attach(GTK_TABLE(table), rate_hscale, 1, 2, 2, 3, GtkAttachOptions(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 5, 0); long rate; pVoice->GetRate(&rate); gtk_range_set_value(GTK_RANGE(rate_hscale), rate); g_signal_connect(G_OBJECT(rate_hscale),"value-changed", G_CALLBACK(on_rate_hscale_value_changed), NULL); GtkWidget *vbox1 = gtk_vbox_new(false, 5); gtk_box_pack_start(GTK_BOX(vbox), vbox1, false, false, 10); label = gtk_label_new(_("Input the test text:")); gtk_misc_set_alignment (GTK_MISC (label), 0, .5); gtk_box_pack_start(GTK_BOX(vbox1), label, false, false, 0); GtkWidget *hbox = gtk_hbox_new(false, 5); gtk_box_pack_start(GTK_BOX(vbox1), hbox, false, false, 0); GtkWidget *entry = gtk_entry_new(); gtk_entry_set_text(GTK_ENTRY(entry), "This is the test text"); gtk_box_pack_start(GTK_BOX(hbox), entry, true, true, 0); GtkWidget *button = gtk_button_new_with_label(_("Test")); gtk_box_pack_start(GTK_BOX(hbox), button, false, false, 0); g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(on_test_tts_button_clicked), GTK_ENTRY(entry)); gtk_widget_show_all(vbox); gtk_dialog_run(GTK_DIALOG(window)); if (configure_changed) { char *voice = NULL; ISpObjectToken *pToken; HRESULT hr = pVoice->GetVoice( &pToken ); if ( SUCCEEDED( hr ) ) { WCHAR *id; pToken->GetId( &id ); DWORD dwNum = WideCharToMultiByte(CP_UTF8,NULL,id,-1,NULL,0,NULL,FALSE); voice = new char[dwNum]; WideCharToMultiByte (CP_UTF8,NULL,id,-1,voice,dwNum,NULL,FALSE); CoTaskMemFree(id); pToken->Release(); } if (voice) { gint volume = (gint)gtk_range_get_value(GTK_RANGE(volume_hscale)); gint rate = (gint)gtk_range_get_value(GTK_RANGE(rate_hscale)); gchar *data = g_strdup_printf("[sapi_tts]\nvoice=%s\nvolume=%d\nrate=%d\n", voice, volume, rate); std::string res = get_cfg_filename(); g_file_set_contents(res.c_str(), data, -1, NULL); g_free(data); delete []voice; } } ULONG ulIndex; if ( ppszTokenIds ) { for ( ulIndex = 0; ulIndex < ulNumTokens; ulIndex++ ) { if ( NULL != ppszTokenIds[ulIndex] ) { CoTaskMemFree( ppszTokenIds[ulIndex] ); } } delete [] ppszTokenIds; } gtk_widget_destroy (window); }
/****************************************************************************** * ManageEmployeesPaneProc * *-------------------------* * Description: * Handles messages specifically for the manage employees pane. * ******************************************************************************/ LRESULT ManageEmployeesPaneProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { static ULONG ulNumTokens; static ULONG ulCurToken; static WCHAR** ppszTokenIds; static CSpDynamicString* ppcDescriptionString; // This is string helper class in sphelper.h static UINT iCurEnum; // Indicates if we should list males, females, or both switch ( message ) { case WM_GOTOOFFICE: { // Set the right message handler and repaint g_fpCurrentPane = OfficePaneProc; //Cleanup our variables ManageEmployeesPaneCleanup( ppszTokenIds, ppcDescriptionString, ulNumTokens ); ppszTokenIds = NULL; ppcDescriptionString = NULL; ulNumTokens = 0; // Set the hear voice rule to inactive HRESULT hr = g_cpCmdGrammar->SetRuleIdState( VID_HearTheVoice, SPRS_INACTIVE ); _ASSERTE( SUCCEEDED( hr ) ); hr = g_cpCmdGrammar->SetRuleIdState( VID_OtherRules, SPRS_INACTIVE ); _ASSERTE( SUCCEEDED( hr ) ); hr = g_cpCmdGrammar->SetRuleIdState( DYN_TTSVOICERULE, SPRS_ACTIVE ); _ASSERTE( SUCCEEDED( hr ) ); PostMessage( hWnd, WM_INITPANE, NULL, NULL ); InvalidateRect( hWnd, NULL, TRUE ); return ( 1 ); } case WM_GOTOCOUNTER: { // Set the right message handler and repaint g_fpCurrentPane = CounterPaneProc; //Cleanup our variables ManageEmployeesPaneCleanup( ppszTokenIds, ppcDescriptionString, ulNumTokens ); ppszTokenIds = NULL; ppcDescriptionString = NULL; ulNumTokens = 0; // Set the hear voice rule to inactive HRESULT hr = g_cpCmdGrammar->SetRuleIdState( VID_HearTheVoice, SPRS_INACTIVE ); _ASSERTE( SUCCEEDED( hr ) ); hr = g_cpCmdGrammar->SetRuleIdState( VID_OtherRules, SPRS_INACTIVE ); _ASSERTE( SUCCEEDED( hr ) ); hr = g_cpCmdGrammar->SetRuleIdState( DYN_TTSVOICERULE, SPRS_ACTIVE ); _ASSERTE( SUCCEEDED( hr ) ); PostMessage( hWnd, WM_INITPANE, NULL, NULL ); InvalidateRect( hWnd, NULL, TRUE ); return ( 1 ); } case WM_PAINT: { // Do the actual UI paint ManageEmployeesPanePaint( hWnd, ulNumTokens, ppcDescriptionString, ulCurToken, iCurEnum ); return ( 1 ); } case WM_INITPANE: { ISpObjectToken *pToken = NULL; // Token interface pointer CComPtr<IEnumSpObjectTokens> cpEnum; // Pointer to token enumerator ULONG ulIndex = 0; ulCurToken = 0xffffffff; WCHAR *szRequiredAttributes = NULL; SPSTATEHANDLE hDynamicRuleHandle; // Handle to our dynamic rule // Set the required attributes field for the enum if we have special needs // based on our LPARAM in if ( 0 == lParam ) { szRequiredAttributes = L"Gender=Male"; } else if ( 1 == lParam ) { szRequiredAttributes = L"Gender=Female"; } // Get a token enumerator for tts voices available HRESULT hr = SpEnumTokens(SPCAT_VOICES, szRequiredAttributes, NULL, &cpEnum); if ( S_OK == hr ) { // Get the numbers of tokens found hr = cpEnum->GetCount( &ulNumTokens ); if ( SUCCEEDED( hr ) && 0 != ulNumTokens ) { // Create arrays we need for storing data ppcDescriptionString = new CSpDynamicString [ulNumTokens]; if ( NULL == ppcDescriptionString ) { break; } ppszTokenIds = new WCHAR* [ulNumTokens]; if ( NULL == ppszTokenIds ) { break; } ZeroMemory( ppszTokenIds, ulNumTokens*sizeof( WCHAR* ) ); // Get the next token in the enumeration // State is maintained in the enumerator while (cpEnum->Next(1, &pToken, NULL) == S_OK) { // Get a string which describes the token, in our case, the voice name hr = SpGetDescription( pToken, &ppcDescriptionString[ulIndex] ); _ASSERTE( SUCCEEDED( hr ) ); // Get the token id, for a low overhead way to retrieve the token later // without holding on to the object itself hr = pToken->GetId( &ppszTokenIds[ulIndex] ); _ASSERTE( SUCCEEDED( hr ) ); ulIndex++; // Release the token itself pToken->Release(); pToken = NULL; } } // if we've failed to properly initialize, then we should completely shut-down if ( S_OK != hr ) { if ( pToken ) { pToken->Release(); } ManageEmployeesPaneCleanup( ppszTokenIds, ppcDescriptionString, ulNumTokens ); ppszTokenIds = NULL; ppcDescriptionString = NULL; ulNumTokens = 0; } // Find out which token corresponds to our voice which is currently in use else { WCHAR *pszCurTokenId = NULL; // Get the token representing the current voice hr = g_cpVoice->GetVoice( &pToken ); if ( SUCCEEDED( hr ) ) { // Get the current token ID, and compare it against others to figure out // which description string is the one currently selected. hr = pToken->GetId( &pszCurTokenId ); if ( SUCCEEDED( hr ) ) { ulIndex = 0; while ( ulIndex < ulNumTokens && 0 != _wcsicmp( pszCurTokenId, ppszTokenIds[ulIndex] ) ) { ulIndex++; } // We found it, so set the current index to that of the current token if ( ulIndex < ulNumTokens ) { ulCurToken = ulIndex; } CoTaskMemFree( pszCurTokenId ); } pToken->Release(); } } } // Initially, we see both genders _ASSERTE( lParam >= 0 && lParam <= 2); iCurEnum = (UINT)lParam; // Create a dynamic rule containing the description strings of the voice tokens hr = g_cpCmdGrammar->GetRule(NULL, DYN_TTSVOICERULE, SPRAF_TopLevel | SPRAF_Active | SPRAF_Dynamic, TRUE, &hDynamicRuleHandle); if ( SUCCEEDED( hr ) ) { // Clear the rule first hr = g_cpCmdGrammar->ClearRule( hDynamicRuleHandle ); _ASSERTE( SUCCEEDED( hr ) ); // Commit the changes hr = g_cpCmdGrammar->Commit(0); _ASSERTE( SUCCEEDED( hr ) ); // Add description names as the word, ulIndex as id for ( ulIndex = 0; ulIndex < ulNumTokens; ulIndex++ ) { SPPROPERTYINFO prop; prop.pszName = L"Id"; prop.pszValue = L"Property"; prop.vValue.vt = VT_I4; prop.vValue.ulVal = ulIndex; hr = g_cpCmdGrammar->AddWordTransition( hDynamicRuleHandle, NULL, ppcDescriptionString[ulIndex], L" ", SPWT_LEXICAL, 1.0, &prop); _ASSERTE( SUCCEEDED( hr ) ); } // Commit the changes hr = g_cpCmdGrammar->Commit(0); _ASSERTE( SUCCEEDED( hr ) ); // Set the dynamic rules to active hr = g_cpCmdGrammar->SetRuleIdState( DYN_TTSVOICERULE, SPRS_ACTIVE ); _ASSERTE( SUCCEEDED( hr ) ); } // Set the hear voice rule to active hr = g_cpCmdGrammar->SetRuleIdState( VID_HearTheVoice, SPRS_ACTIVE ); _ASSERTE( SUCCEEDED( hr ) ); hr = g_cpCmdGrammar->SetRuleIdState( VID_OtherRules, SPRS_ACTIVE ); _ASSERTE( SUCCEEDED( hr ) ); InvalidateRect( hWnd, NULL, TRUE ); return ( 1 ); } case WM_DESTROY: // Windows is closing down, so we should cleanup ManageEmployeesPaneCleanup( ppszTokenIds, ppcDescriptionString, ulNumTokens ); ppszTokenIds = NULL; ppcDescriptionString = NULL; ulNumTokens = 0; return ( 1 ); case WM_HEARTHEVOICE: // Set the voice to play LoadString( g_hInst, IDS_VOICESPEAK, g_szCounterDisplay, MAX_LOADSTRING ); g_cpVoice->Speak( CT2W(g_szCounterDisplay), SPF_ASYNC | SPF_PURGEBEFORESPEAK, NULL ); return ( 1 ); case WM_MISCCOMMAND: { // Find out the offset from the first property we're interested in, so we can verify that // it's within range. UINT iSelection = (UINT)(lParam - VID_MalesOnly); if ( 2 >= iSelection ) { // If we have a new listing criteria, we basically shutdown the pane and start it again if ( iSelection != iCurEnum ) { HRESULT hr = g_cpCmdGrammar->SetRuleIdState( VID_HearTheVoice, SPRS_INACTIVE ); _ASSERTE( SUCCEEDED( hr ) ); hr = g_cpCmdGrammar->SetRuleIdState( VID_OtherRules, SPRS_INACTIVE ); _ASSERTE( SUCCEEDED( hr ) ); ManageEmployeesPaneCleanup( ppszTokenIds, ppcDescriptionString, ulNumTokens ); ppszTokenIds = NULL; ppcDescriptionString = NULL; ulNumTokens = 0; PostMessage( hWnd, WM_INITPANE, 0, (LPARAM) iSelection ); } } return ( 1 ); } case WM_TTSVOICESEL: { // If we are out of range, it is a programming error _ASSERTE( 0 <= lParam && ulNumTokens > (ULONG) lParam ); // The returned Id is an index into our tokenId table, so create a token from the id CComPtr< ISpObjectToken > pToken; HRESULT hr = SpGetTokenFromId( ppszTokenIds[lParam], &pToken, FALSE); if ( SUCCEEDED( hr ) ) { // Set our current voice from the returned token hr = g_cpVoice->SetVoice( pToken ); _ASSERTE( SUCCEEDED( hr ) ); // Change our current voice index ulCurToken = (UINT)lParam; } InvalidateRect( hWnd, NULL, TRUE ); return ( 1 ); } } return ( 0 ); }