Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

342 lines
9.8 KiB

  1. #include <windows.h>
  2. #include <atlbase.h>
  3. #include "sapi.h"
  4. #include "sphelper.h"
  5. #include "spddkhlp.h"
  6. #include "spttseng.h"
  7. #include "spttseng_i.c"
  8. #include "spcommon.h"
  9. #include "spcommon_i.c"
  10. #include <spunicode.h>
  11. #include "ms1033ltsmap.h"
  12. // This code does not ship
  13. // This code creates the registry entries for the TTS voices. The
  14. // datafiles registered here are the ones checked in the slm source tree. This is not
  15. // done using a reg file because we need to compute the absolute path of the datafiles
  16. // which can be different on different machines because of different root slm directories.
  17. // BUGBUG: Check out the ATL UpdateRegistryFromResource et al. and see whether you could
  18. // use them instead, a la RegSR. That seems much easier.
  19. #ifndef _WIN32_WCE
  20. #define DIRS_TO_GO_BACK_TTSENG 4 // Back 4 levels and up 1 to 'Voices" directory
  21. #define DIRS_TO_GO_BACK_LEX 6 // Back 6 levels to Lex Data directory
  22. #else
  23. #define DIRS_TO_GO_BACK_TTSENG 1 //
  24. #define DIRS_TO_GO_BACK_LEX 1 //
  25. #endif
  26. CSpUnicodeSupport g_Unicode;
  27. /*****************************************************************************
  28. * CreateLexSubKey *
  29. *------------------*
  30. * Description:
  31. * Each TTS voice gets installed under one registry sub-key.
  32. * This function installs the single voice from the passed params.
  33. *
  34. ********************************************************************** MC ***/
  35. HRESULT CreateLexSubKey(
  36. ISpObjectToken * pToken,
  37. const WCHAR * pszSubKeyName,
  38. const CLSID * pclsid,
  39. const WCHAR * pszFilePath,
  40. const WCHAR * pszLexName,
  41. const WCHAR * pszPhoneMap)
  42. {
  43. HRESULT hr = S_OK;
  44. //---------------------------------------
  45. // Create the lex sub-key (Lex or LTS)
  46. //---------------------------------------
  47. CComPtr<ISpObjectToken> cpSubToken;
  48. hr = SpGetSubTokenFromToken(pToken, pszSubKeyName, &cpSubToken, TRUE);
  49. if (SUCCEEDED(hr))
  50. {
  51. hr = SpSetCommonTokenData(
  52. cpSubToken,
  53. pclsid,
  54. NULL,
  55. 0,
  56. NULL,
  57. NULL);
  58. }
  59. WCHAR szLexDataPath[MAX_PATH];
  60. if (SUCCEEDED(hr))
  61. {
  62. //--------------------------------
  63. // Lex DATA file location
  64. //--------------------------------
  65. wcscpy(szLexDataPath, pszFilePath);
  66. wcscat(szLexDataPath, pszLexName);
  67. hr = cpSubToken->SetStringValue(L"DataFile", szLexDataPath);
  68. }
  69. if (SUCCEEDED(hr) && pszPhoneMap)
  70. {
  71. CComPtr<ISpObjectToken> cpPhoneToken;
  72. if (SUCCEEDED(hr))
  73. hr = SpGetSubTokenFromToken(cpSubToken, L"PhoneConverter", &cpPhoneToken, TRUE);
  74. if (SUCCEEDED(hr))
  75. hr = SpSetCommonTokenData(cpPhoneToken, &CLSID_SpPhoneConverter, NULL, 0, NULL, NULL);
  76. if (SUCCEEDED(hr))
  77. hr = cpPhoneToken->SetStringValue(L"PhoneMap", pszPhoneMap);
  78. }
  79. return hr;
  80. }
  81. /*****************************************************************************
  82. * CreateVoiceSubKey *
  83. *--------------------*
  84. * Description:
  85. * Each TTS voice gets installed under one registry sub-key.
  86. * This function installs the single voice from the passed params.
  87. *
  88. ********************************************************************** MC ***/
  89. HRESULT CreateVoiceSubKey(
  90. const WCHAR * pszSubKeyName,
  91. const WCHAR * pszDescription,
  92. BOOL fVendorDefault,
  93. const WCHAR * pszGender,
  94. const WCHAR * pszAge,
  95. const WCHAR * pszVoicePath,
  96. const WCHAR * pszVoiceName,
  97. const WCHAR * pszLexPath)
  98. {
  99. HRESULT hr;
  100. CComPtr<ISpObjectToken> cpToken;
  101. CComPtr<ISpDataKey> cpDataKeyAttribs;
  102. hr = SpCreateNewTokenEx(
  103. SPCAT_VOICES,
  104. pszSubKeyName,
  105. &CLSID_MSVoiceData,
  106. pszDescription,
  107. 0x409,
  108. pszDescription,
  109. &cpToken,
  110. &cpDataKeyAttribs);
  111. if (SUCCEEDED(hr))
  112. {
  113. hr = cpDataKeyAttribs->SetStringValue(L"Name", pszDescription);
  114. }
  115. if (SUCCEEDED(hr))
  116. {
  117. hr = cpDataKeyAttribs->SetStringValue(L"Gender", pszGender);
  118. }
  119. if (SUCCEEDED(hr))
  120. {
  121. hr = cpDataKeyAttribs->SetStringValue(L"Age", pszAge);
  122. }
  123. if (SUCCEEDED(hr))
  124. {
  125. hr = cpDataKeyAttribs->SetStringValue(L"Vendor", L"Microsoft");
  126. }
  127. if (SUCCEEDED(hr))
  128. {
  129. hr = cpDataKeyAttribs->SetStringValue(L"Language", L"409");
  130. }
  131. if (SUCCEEDED(hr) && fVendorDefault)
  132. {
  133. hr = cpDataKeyAttribs->SetStringValue(L"VendorPreferred", L"");
  134. }
  135. WCHAR szVoiceDataPath[MAX_PATH];
  136. if (SUCCEEDED(hr))
  137. {
  138. //--------------------------------
  139. // Voice DATA file location
  140. //--------------------------------
  141. wcscpy(szVoiceDataPath, pszVoicePath);
  142. wcscat(szVoiceDataPath, pszVoiceName);
  143. wcscat(szVoiceDataPath, L".SPD");
  144. hr = cpToken->SetStringValue(L"VoiceData", szVoiceDataPath);
  145. }
  146. if (SUCCEEDED(hr))
  147. {
  148. //--------------------------------
  149. // Voice DEF file location
  150. //--------------------------------
  151. wcscpy(szVoiceDataPath, pszVoicePath);
  152. wcscat(szVoiceDataPath, pszVoiceName);
  153. wcscat(szVoiceDataPath, L".SDF");
  154. hr = cpToken->SetStringValue(L"VoiceDef", szVoiceDataPath);
  155. }
  156. //------------------------------------------------
  157. // Register TTS lexicons
  158. //------------------------------------------------
  159. if (SUCCEEDED(hr))
  160. {
  161. hr = CreateLexSubKey(cpToken, L"Lex", &CLSID_SpCompressedLexicon, pszLexPath, L"LTTS1033.LXA", NULL);
  162. }
  163. if (SUCCEEDED(hr))
  164. {
  165. hr = CreateLexSubKey(cpToken, L"LTS", &CLSID_SpLTSLexicon, pszLexPath, L"r1033tts.lxa", pszms1033ltsmap);
  166. }
  167. return hr;
  168. }
  169. /*****************************************************************************
  170. * main *
  171. *-------*
  172. * Description:
  173. * Locate the abs path to the Mary, Mike and Sam voices
  174. * and register them in the system registry.
  175. *
  176. ********************************************************************** MC ***/
  177. int _tmain()
  178. {
  179. HRESULT hr = S_OK;
  180. CoInitialize(NULL);
  181. //----------------------------------------
  182. // Get the exe's location...
  183. //----------------------------------------
  184. WCHAR szVoiceDataPath[MAX_PATH];
  185. if (!g_Unicode.GetModuleFileName(NULL, szVoiceDataPath, MAX_PATH))
  186. {
  187. hr = HRESULT_FROM_WIN32(::GetLastError());
  188. }
  189. WCHAR szLexDataPath[MAX_PATH];
  190. if (SUCCEEDED(hr))
  191. {
  192. wcscpy(szLexDataPath, szVoiceDataPath);
  193. }
  194. //----------------------------------------
  195. // ...and derive abs path to VOICE data
  196. //----------------------------------------
  197. if (SUCCEEDED(hr))
  198. {
  199. // modulename is "<Speech>\TTS\msttsdrv\RegVoices\obj\i386\RegVoices.exe"
  200. // Data is at "<Speech>\TTS\msttsdrv\voices\"
  201. WCHAR * psz;
  202. psz = szVoiceDataPath;
  203. for (int i = 0; i < DIRS_TO_GO_BACK_TTSENG; i++)
  204. {
  205. psz = wcsrchr(psz, '\\');
  206. if (!psz)
  207. {
  208. hr = E_FAIL;
  209. break;
  210. }
  211. else
  212. {
  213. *psz = 0;
  214. psz = szVoiceDataPath;
  215. }
  216. }
  217. }
  218. if (SUCCEEDED(hr))
  219. {
  220. #ifndef _WIN32_WCE
  221. wcscat(szVoiceDataPath, L"\\Voices\\");
  222. #else
  223. wcscat(szVoiceDataPath, L"\\");
  224. #endif
  225. }
  226. //----------------------------------------
  227. // Derive abs path to LEX data
  228. //----------------------------------------
  229. if (SUCCEEDED(hr))
  230. {
  231. // modulename is "<sapi5>\Src\TTS\msttsdrv\voices\RegVoices\debug_x86\RegVoices.exe"
  232. // Data is at "<sapi5>\Src\lexicon\data\"
  233. WCHAR * psz = szLexDataPath;
  234. for (int i = 0; i < DIRS_TO_GO_BACK_LEX; i++)
  235. {
  236. psz = wcsrchr(psz, '\\');
  237. if (!psz)
  238. {
  239. hr = E_FAIL;
  240. break;
  241. }
  242. else
  243. {
  244. *psz = 0;
  245. psz = szLexDataPath;
  246. }
  247. }
  248. }
  249. if (SUCCEEDED(hr))
  250. {
  251. #ifndef _WIN32_WCE
  252. wcscat(szLexDataPath, L"\\src\\lexicon\\data\\");
  253. #else
  254. wcscat(szLexDataPath, L"\\");
  255. #endif
  256. }
  257. //------------------------------------------------
  258. // ...then register the three Microsoft voices..
  259. //------------------------------------------------
  260. if (SUCCEEDED(hr))
  261. {
  262. hr = CreateVoiceSubKey(L"MSMary",
  263. L"Microsoft Mary",
  264. TRUE,
  265. L"Female",
  266. L"Adult",
  267. szVoiceDataPath,
  268. L"Mary",
  269. szLexDataPath);
  270. }
  271. #ifndef _WIN32_WCE
  272. if (SUCCEEDED(hr))
  273. {
  274. hr = CreateVoiceSubKey(L"MSMike",
  275. L"Microsoft Mike",
  276. FALSE,
  277. L"Male",
  278. L"Adult",
  279. szVoiceDataPath,
  280. L"Mike",
  281. szLexDataPath);
  282. }
  283. if (SUCCEEDED(hr))
  284. {
  285. hr = CreateVoiceSubKey(L"MSSam",
  286. L"Microsoft Sam",
  287. FALSE,
  288. L"Male",
  289. L"Adult",
  290. szVoiceDataPath,
  291. L"Sam",
  292. szLexDataPath);
  293. }
  294. #endif //_WIN32_WCE
  295. CoUninitialize();
  296. if (FAILED(hr))
  297. return -1;
  298. return 0;
  299. }