windows-nt/Source/XPSP1/NT/enduser/speech/ce/regvoices/regvoices.cpp

392 lines
11 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
#include <windows.h>
#include <atlbase.h>
extern CComModule _Module;
#include <atlcom.h>
#include "sapi.h"
#include "sphelper.h"
#include "spddkhlp.h"
#include "spttseng.h"
#include "spttseng_i.c"
#include "ms1033ltsmap.h" // BUGBUG: Move to somewhere... else.
#ifdef _WIN32_WCE
#define GOTO_LRETURN(hres) {RETAILMSG(1, (_T("File: %s Line :%d, hr=%08x\n"),_T(__FILE__),__LINE__, hres)); goto LReturn;}
#define MARK(text) {RETAILMSG(1, (_T("%s Line :%d\n"), text,__LINE__));}
#else
#define GOTO_LRETURN(hres) {wprintf(L"Line :%d, hr=%08x\n",__LINE__, hres); goto LReturn;}
#define MARK(text) {wprintf(L"%s Line :%d\n", text,__LINE__);}
#endif
// This code does not ship
// This code creates the registry entries for the TTS voices. The
// datafiles registered here are the ones checked in the slm source tree. This is not
// done using a reg file because we need to compute the absolute path of the datafiles
// which can be different on different machines because of different root slm directories.
#ifndef _WIN32_WCE
#define DIRS_TO_GO_BACK_VOICE 3 // Back 3 levels to 'Voices" directory
#define DIRS_TO_GO_BACK_LEX 6 // Back 3 levels to Lex Data directory
#else
#define DIRS_TO_GO_BACK_VOICE 1 // Back 3 levels to 'Voices" directory
#define DIRS_TO_GO_BACK_LEX 1 // Back 3 levels to Lex Data directory
#endif
CSpUnicodeSupport g_Unicode;
/*****************************************************************************
* CreateLexSubKey *
*------------------*
* Description:
* Each TTS voice gets installed under one registry sub-key.
* This function installs the single voice from the passed params.
*
********************************************************************** MC ***/
HRESULT CreateLexSubKey(
ISpObjectToken * pToken,
const WCHAR * pszSubKeyName,
const CLSID * pclsid,
const WCHAR * pszFilePath,
const WCHAR * pszLexName,
const WCHAR * pszPhoneMap)
{
HRESULT hr = S_OK;
//---------------------------------------
// Create the lex sub-key (Lex or LTS)
//---------------------------------------
CComPtr<ISpObjectToken> cpSubToken;
hr = SpGetSubTokenFromToken(pToken, pszSubKeyName, &cpSubToken, TRUE);
if (SUCCEEDED(hr))
{
hr = SpSetCommonTokenData(
cpSubToken,
pclsid,
NULL,
0,
NULL,
NULL);
}
WCHAR szLexDataPath[MAX_PATH];
if (SUCCEEDED(hr))
{
//--------------------------------
// Lex DATA file location
//--------------------------------
wcscpy(szLexDataPath, pszFilePath);
wcscat(szLexDataPath, pszLexName);
hr = cpSubToken->SetStringValue(L"DataFile", szLexDataPath);
}
if (SUCCEEDED(hr) && pszPhoneMap)
{
CComPtr<ISpObjectToken> cpPhoneToken;
if (SUCCEEDED(hr))
hr = SpGetSubTokenFromToken(cpSubToken, L"PhoneConverter", &cpPhoneToken, TRUE);
if (SUCCEEDED(hr))
hr = SpSetCommonTokenData(cpPhoneToken, &CLSID_SpPhoneConverter, NULL, 0, NULL, NULL);
if (SUCCEEDED(hr))
hr = cpPhoneToken->SetStringValue(L"PhoneMap", pszPhoneMap);
}
return hr;
}
/*****************************************************************************
* CreateUISubKey *
*-----------------*
* Description:
* Creates the UI SubKey under a voice.
*
********************************************************************** AH ***/
HRESULT CreateUISubKey(
ISpObjectToken * pToken,
const CLSID * pclsid)
{
HRESULT hr = S_OK;
//-----------------------
// Create the UI sub-key
//-----------------------
CComPtr<ISpObjectToken> cpSubToken;
hr = SpGetSubTokenFromToken(pToken, L"UI", &cpSubToken, TRUE);
//--------------------------------------
// Create the EngineProperties sub-key
//--------------------------------------
CComPtr<ISpObjectToken> cpSubSubToken;
if ( SUCCEEDED( hr ) )
{
hr = SpGetSubTokenFromToken( cpSubToken, L"EngineProperties", &cpSubSubToken, TRUE );
}
if (SUCCEEDED(hr))
{
hr = SpSetCommonTokenData(
cpSubSubToken,
pclsid,
NULL,
0,
NULL,
NULL);
}
return hr;
}
/*****************************************************************************
* CreateVoiceSubKey *
*--------------------*
* Description:
* Each TTS voice gets installed under one registry sub-key.
* This function installs the single voice from the passed params.
*
********************************************************************** MC ***/
HRESULT CreateVoiceSubKey(
const WCHAR * pszSubKeyName,
const WCHAR * pszDescription,
BOOL fVendorDefault,
const WCHAR * pszGender,
const WCHAR * pszAge,
const WCHAR * pszVoicePath,
const WCHAR * pszVoiceName,
const WCHAR * pszLexPath)
{
HRESULT hr;
CComPtr<ISpObjectToken> cpToken;
CComPtr<ISpDataKey> cpDataKeyAttribs;
hr = SpCreateNewTokenEx(
SPCAT_VOICES,
pszSubKeyName,
&CLSID_MSVoiceData,
pszDescription,
0x409,
pszDescription,
&cpToken,
&cpDataKeyAttribs);
if (SUCCEEDED(hr))
{
hr = cpDataKeyAttribs->SetStringValue(L"Name", pszSubKeyName);
}
if (SUCCEEDED(hr))
{
hr = cpDataKeyAttribs->SetStringValue(L"Gender", pszGender);
}
if (SUCCEEDED(hr))
{
hr = cpDataKeyAttribs->SetStringValue(L"Age", pszAge);
}
if (SUCCEEDED(hr))
{
hr = cpDataKeyAttribs->SetStringValue(L"Vendor", L"Microsoft");
}
if (SUCCEEDED(hr))
{
hr = cpDataKeyAttribs->SetStringValue(L"Language", L"409");
}
if (SUCCEEDED(hr) && fVendorDefault)
{
hr = cpDataKeyAttribs->SetStringValue(L"VendorPreferred", L"");
}
WCHAR szVoiceDataPath[MAX_PATH];
if (SUCCEEDED(hr))
{
//--------------------------------
// Voice DATA file location
//--------------------------------
wcscpy(szVoiceDataPath, pszVoicePath);
wcscat(szVoiceDataPath, pszVoiceName);
wcscat(szVoiceDataPath, L".vdt");
hr = cpToken->SetStringValue(L"VoiceData", szVoiceDataPath);
}
if (SUCCEEDED(hr))
{
//--------------------------------
// Voice DEF file location
//--------------------------------
wcscpy(szVoiceDataPath, pszVoicePath);
wcscat(szVoiceDataPath, pszVoiceName);
wcscat(szVoiceDataPath, L".vdf");
hr = cpToken->SetStringValue(L"VoiceDef", szVoiceDataPath);
}
//------------------------------------------------
// Register TTS lexicons
//------------------------------------------------
if (SUCCEEDED(hr))
{
hr = CreateLexSubKey(cpToken, L"Lex", &CLSID_SpCompressedLexicon, pszLexPath, L"LTTS1033.LXA", NULL);
}
if (SUCCEEDED(hr))
{
hr = CreateLexSubKey(cpToken, L"LTS", &CLSID_SpLTSLexicon, pszLexPath, L"r1033tts.lxa", pszms1033ltsmap);
}
if ( SUCCEEDED( hr ) )
{
hr = CreateUISubKey( cpToken, &CLSID_SpTtsEngUI );
}
return hr;
}
/*****************************************************************************
* main *
*-------*
* Description:
* Locate the abs path to the Mary, Mike and Sam voices
* and register them in the system registry.
*
********************************************************************** MC ***/
int wmain()
{
HRESULT hr = S_OK;
CoInitialize(NULL);
//----------------------------------------
// Get the exe's location...
//----------------------------------------
WCHAR szVoiceDataPath[MAX_PATH];
if (!g_Unicode.GetModuleFileName(NULL, szVoiceDataPath, MAX_PATH))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
}
WCHAR szLexDataPath[MAX_PATH];
if (SUCCEEDED(hr))
{
wcscpy(szLexDataPath, szVoiceDataPath);
}
//----------------------------------------
// ...and derive abs path to VOICE data
//----------------------------------------
if (SUCCEEDED(hr))
{
// modulename is "<sapi5>\Src\TTS\msttsdrv\voices\RegVoices\debug_x86\RegVoices.exe"
// Data is at "<sapi5>\Src\TTS\msttsdrv\voices\"
WCHAR * psz;
psz = szVoiceDataPath;
for (int i = 0; i < DIRS_TO_GO_BACK_VOICE; i++)
{
psz = wcsrchr(psz, '\\');
if (!psz)
{
hr = E_FAIL;
break;
}
else
{
*psz = 0;
psz = szVoiceDataPath;
}
}
}
if (SUCCEEDED(hr))
{
wcscat(szVoiceDataPath, L"\\");
}
#ifdef _WIN32_WCE
MARK(szVoiceDataPath);
// if (SUCCEEDED(hr))
// {
// wcscat(szVoiceDataPath, L"voices\\");
// }
// MARK(szVoiceDataPath);
#endif // _WIN32_WCE
//----------------------------------------
// Derive abs path to LEX data
//----------------------------------------
if (SUCCEEDED(hr))
{
// modulename is "<sapi5>\Src\TTS\msttsdrv\voices\RegVoices\debug_x86\RegVoices.exe"
// Data is at "<sapi5>\Src\lexicon\data\"
WCHAR * psz = szLexDataPath;
for (int i = 0; i < DIRS_TO_GO_BACK_LEX; i++)
{
psz = wcsrchr(psz, '\\');
if (!psz)
{
hr = E_FAIL;
break;
}
else
{
*psz = 0;
psz = szLexDataPath;
}
}
}
MARK(szLexDataPath);
if (SUCCEEDED(hr))
{
wcscat(szLexDataPath, L"\\");
}
MARK(szLexDataPath);
//------------------------------------------------
// ...then register the three Microsoft voices..
//------------------------------------------------
if (SUCCEEDED(hr))
{
hr = CreateVoiceSubKey(L"MSMary",
L"MS Mary",
TRUE,
L"Female",
L"Adult",
szVoiceDataPath,
L"Mary",
szLexDataPath);
}
/* if (SUCCEEDED(hr))
{
hr = CreateVoiceSubKey(L"MSMike",
L"MS Mike",
FALSE,
L"Male",
L"Adult",
szVoiceDataPath,
L"Mike",
szLexDataPath);
}
if (SUCCEEDED(hr))
{
hr = CreateVoiceSubKey(L"MSSam",
L"MS Sam",
FALSE,
L"Male",
L"Adult",
szVoiceDataPath,
L"Sam",
szLexDataPath);
}
*/
CoUninitialize();
if (FAILED(hr))
return -1;
return 0;
}