Esempio n. 1
0
// need to figure out how to do this specifically
bool CSpeechSynthesizer::SetVoice(std::string* name)
{
	// if we're not initialized return false
	if (!m_initialized)
		return false;
	bool result = false;

	TCHAR lang[13] = { 0 };

	CComPtr<IEnumSpObjectTokens> cpIEnumeration;

	for (std::map<std::string*, std::string*>::iterator mit = m_tokenMap->begin(); mit != m_tokenMap->end(); mit++)
	{
		if (strcmp((*mit).first->c_str(), name->c_str()) == 0)
		{
			// Enumerate voice tokens
			const char* text = (*mit).second->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))
			{
				result = resetVoice((*mit).second);
			}
			break;
		}
	}

	return result;
}
static void on_voice_combobox_changed(GtkComboBox *combobox, WCHAR** ppszTokenIds)
{
	configure_changed = true;
	gint index = gtk_combo_box_get_active(combobox);
	if (ppszTokenIds && ppszTokenIds[index]) {
		ISpObjectToken *pToken;
		if (SpGetTokenFromId(ppszTokenIds[index] , &pToken) == S_OK) {
			pVoice->SetVoice(pToken);
			pToken->Release();
		}
	}
}
DLLIMPORT bool stardict_tts_plugin_init(StarDictTtsPlugInObject *obj)
{
	if (FAILED(::CoInitialize(NULL)))
		return true;
	HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
	if(!SUCCEEDED(hr)) {
		::CoUninitialize();
		return true;
	}
	std::string res = get_cfg_filename();
	if (!g_file_test(res.c_str(), G_FILE_TEST_EXISTS)) {
		g_file_set_contents(res.c_str(), "[sapi_tts]\nvoice=\nvolume=100\nrate=0\n", -1, NULL);
	}
	GKeyFile *keyfile = g_key_file_new();
	g_key_file_load_from_file(keyfile, res.c_str(), G_KEY_FILE_NONE, NULL);
	gchar *text = g_key_file_get_string(keyfile, "sapi_tts", "voice", NULL);
	if (text) {
		if (text[0] != '\0') {
			DWORD dwNum = MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
			wchar_t *pwText;
			pwText = new wchar_t[dwNum];
			MultiByteToWideChar(CP_UTF8, 0, text, -1, pwText, dwNum);
			ISpObjectToken *pToken;
			if (SpGetTokenFromId(pwText , &pToken) == S_OK) {
				pVoice->SetVoice(pToken);
				pToken->Release();
			}
			delete []pwText;
		}
		g_free(text);
	}
	GError *err;
	err = NULL;
	USHORT volume = g_key_file_get_integer(keyfile, "sapi_tts", "volume", &err);
	if (err) {
		g_error_free (err);
		volume = 100;
	}
	err = NULL;
	long rate = g_key_file_get_integer(keyfile, "sapi_tts", "rate", &err);
	if (err) {
		g_error_free (err);
		rate = 0;
	}
	g_key_file_free(keyfile);
	pVoice->SetVolume(volume);
	pVoice->SetRate(rate);
	obj->saytext_func = saytext;
	obj->tts_name = _("SAPI TTS");
	g_print(_("SAPI tts plug-in loaded.\n"));
	return false;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
bool CSpeechSynthesizer::resetVoice(std::string* name)
{
	cpVoice.Release();
	cpToken.Release();
	cpIEnum.Release();

	CoInitialize(cpIEnum);

	bool isServerVoice = name->find("Server");
	// Create a voice and set its token to the one we just found.
	const char* text = name->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);
	HRESULT hr = SpGetTokenFromId(tokenId, &cpToken, false);
	if (SUCCEEDED(hr))
	{
		if (isServerVoice)
			hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_INPROC_SERVER, IID_ISpVoice, (void**)&cpVoice);
		else
			hr = cpVoice.CoCreateInstance(CLSID_SpVoice);
	}

	// Set the voice.
	if (SUCCEEDED(hr))
	{
		hr = cpVoice->SetVoice(cpToken);
	}

	// Set the output to the default audio device.
	if (SUCCEEDED(hr))
	{
		hr = cpVoice->SetOutput(NULL, TRUE);
	}

	return SUCCEEDED(hr);
}
/******************************************************************************
* 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 );
}