Source code of Windows XP (NT5)
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.

350 lines
10 KiB

  1. /******************************************************************************
  2. * RegVoices.cpp *
  3. *---------------*
  4. *
  5. * This code does not ship. Based on MC's code for msttsdrv.
  6. *
  7. * This code creates the registry entries for the TTS voices. The
  8. * datafiles registered here are the ones checked in the slm source
  9. * tree. This is not done using a reg file because we need to compute
  10. * the absolute path of the datafiles which can be different on different
  11. * machines because of different root slm directories.
  12. *------------------------------------------------------------------------------
  13. * Copyright (C) 2000 Microsoft Corporation Date: 03/20/00
  14. * All Rights Reserved
  15. *
  16. ********************************************************************* PACOG ***/
  17. #include <windows.h>
  18. #include <atlbase.h>
  19. #include "sphelper.h"
  20. #include "spddkhlp.h"
  21. #include "getopt.h"
  22. #include <spunicode.h>
  23. #include <stdio.h>
  24. #define SYNTAX fprintf (stderr, "RegVoices [-u (UK Eng voice)] [voicesPath]\n")
  25. #define DIR_LEVELS_BACK 4 // Back levels to 'TrueTalk' directory
  26. static HRESULT CreateVoiceSubKey(
  27. const WCHAR * pszSubKeyName,
  28. const WCHAR * pszDescription,
  29. BOOL fVendorDefault,
  30. const WCHAR * pszLanguage,
  31. const WCHAR * pszGender,
  32. const WCHAR * pszAge,
  33. const WCHAR * pszVoicePath,
  34. const WCHAR * pszVoiceName,
  35. const WCHAR * pszLexPath,
  36. double dGain);
  37. const CLSID CLSID_TrueTalk = {0x8E67289A,0x609C,0x4B68,{0x91,0x8B,0x5C,0x35,0x2D,0x9E,0x5D,0x38}};
  38. const CLSID CLSID_PhoneConverter = {0x9185F743,0x1143,0x4C28,{0x86,0xB5,0xBF,0xF1,0x4F,0x20,0xE5,0xC8}};
  39. const WCHAR* g_UKPhoneMap = L"- 0001 ! 0002 & 0003 , 0004 . 0005 ? 0006 _ 0007 1 0008 2 0009 AA 000A AE 000B AH 000C AO 000D AW 000E AX 000F AY 0010 B 0011 CH 0012 D 0013 DH 0014 EH 0015 ER 0016 EY 0017 F 0018 G 0019 H 001A IH 001B IY 001C JH 001D K 001E L 001F M 0020 N 0021 NG 0022 OW 0023 OY 0024 P 0025 R 0026 S 0027 SH 0028 T 0029 TH 002A UH 002B UW 002C V 002D W 002E Y 002F Z 0030 ZH 0031 EX 0032 UR 0033";
  40. //-- Static
  41. CSpUnicodeSupport g_Unicode;
  42. /*****************************************************************************
  43. * main *
  44. *-------*
  45. * Description:
  46. * Locate the abs path to Simon, etc.
  47. * and register them in the system registry.
  48. *
  49. ******************************************************************* PACOG ***/
  50. int wmain (int argc, wchar_t* argv[])
  51. {
  52. HRESULT hr = S_OK;
  53. WCHAR szVoiceDataPath[MAX_PATH];
  54. WCHAR szDictDataPath[MAX_PATH];
  55. bool fUkVoice = false;
  56. CWGetOpt getOpt;
  57. int iChar;
  58. CoInitialize(NULL);
  59. getOpt.Init(argc, argv, L"u");
  60. while ( (iChar = getOpt.NextOption()) != EOF )
  61. {
  62. switch (iChar)
  63. {
  64. case L'u':
  65. fUkVoice = true;
  66. break;
  67. case L'?':
  68. default:
  69. SYNTAX;
  70. goto exit;
  71. }
  72. }
  73. switch (argc - getOpt.OptInd())
  74. {
  75. case 1:
  76. wcscpy (szVoiceDataPath, argv[getOpt.OptInd()]);
  77. wcscat (szVoiceDataPath, L"\\" );
  78. break;
  79. case 0:
  80. //-- Get the exe's location...
  81. if( !g_Unicode.GetModuleFileName(NULL, szVoiceDataPath, MAX_PATH) )
  82. {
  83. hr = HRESULT_FROM_WIN32(GetLastError());
  84. }
  85. //-- ...and derive abs path to VOICE and DICT data
  86. if( SUCCEEDED(hr) )
  87. {
  88. WCHAR *psz;
  89. // modulename is "<sapi5>\Src\TTS\TrueTalk\RegVoices\Obj\i386\RegVoices.exe"
  90. // data is at "<sapi5>\Src\TTS\TrueTalk\Voices\"
  91. for ( int i = 0; i < DIR_LEVELS_BACK; i++ )
  92. {
  93. psz = wcsrchr( szVoiceDataPath, '\\' );
  94. if (psz != 0)
  95. {
  96. *psz= 0;
  97. }
  98. else
  99. {
  100. hr = E_FAIL;
  101. break;
  102. }
  103. }
  104. }
  105. wcscat( szVoiceDataPath, L"\\Voices\\" );
  106. break;
  107. default:
  108. SYNTAX;
  109. goto exit;
  110. }
  111. wcscat( wcscpy(szDictDataPath, szVoiceDataPath), L"Dict");
  112. //-- Register the TrueTalk voices..
  113. if( SUCCEEDED(hr) )
  114. {
  115. hr = CreateVoiceSubKey(L"TTSimonMin",
  116. L"TrueTalk Simon Min",
  117. FALSE,
  118. L"409;9",
  119. L"Male",
  120. L"Adult",
  121. szVoiceDataPath,
  122. L"Simon\\sa8kMin.sfont",
  123. szDictDataPath,
  124. 3.0);
  125. }
  126. if( SUCCEEDED(hr) )
  127. {
  128. hr = CreateVoiceSubKey(L"TTSimon150",
  129. L"TrueTalk Simon 150",
  130. FALSE,
  131. L"409;9",
  132. L"Male",
  133. L"Adult",
  134. szVoiceDataPath,
  135. L"Simon\\sa8k150.sfont",
  136. szDictDataPath,
  137. 3.0);
  138. }
  139. if( SUCCEEDED(hr) )
  140. {
  141. hr = CreateVoiceSubKey(L"TTMaryMin",
  142. L"TrueTalk Mary Min",
  143. FALSE,
  144. L"409;9",
  145. L"Female",
  146. L"Adult",
  147. szVoiceDataPath,
  148. L"Mary\\ml8kMin.sfont",
  149. szDictDataPath,
  150. 3.0);
  151. }
  152. if( SUCCEEDED(hr) )
  153. {
  154. hr = CreateVoiceSubKey(L"TTMary150",
  155. L"TrueTalk Mary 150",
  156. FALSE,
  157. L"409;9",
  158. L"Female",
  159. L"Adult",
  160. szVoiceDataPath,
  161. L"Mary\\ml8k150.sfont",
  162. szDictDataPath,
  163. 3.0);
  164. }
  165. if (fUkVoice)
  166. {
  167. if( SUCCEEDED(hr) )
  168. {
  169. hr = CreateVoiceSubKey(L"TTDianeMin",
  170. L"TrueTalk Diane Min",
  171. FALSE,
  172. L"809;9",
  173. L"Female",
  174. L"Adult",
  175. szVoiceDataPath,
  176. L"Diane\\dk8kMin.sfont",
  177. szDictDataPath,
  178. 5.0);
  179. }
  180. if( SUCCEEDED(hr) )
  181. {
  182. hr = CreateVoiceSubKey(L"TTDiane150",
  183. L"TrueTalk Diane 150",
  184. FALSE,
  185. L"809;9",
  186. L"Female",
  187. L"Adult",
  188. szVoiceDataPath,
  189. L"Diane\\dk8k150.sfont",
  190. szDictDataPath,
  191. 5.0);
  192. }
  193. if( SUCCEEDED(hr) )
  194. {
  195. CComPtr<ISpObjectToken> cpToken;
  196. CComPtr<ISpDataKey> cpDataKeyAttribs;
  197. hr = SpCreateNewTokenEx(
  198. SPCAT_PHONECONVERTERS,
  199. L"English (UK)",
  200. &CLSID_PhoneConverter,
  201. L"UK English Phone Converter",
  202. 0x0,
  203. NULL,
  204. &cpToken,
  205. &cpDataKeyAttribs);
  206. if (SUCCEEDED(hr))
  207. {
  208. hr = cpToken->SetStringValue(L"PhoneMap", g_UKPhoneMap);
  209. }
  210. if (SUCCEEDED(hr))
  211. {
  212. hr = cpDataKeyAttribs->SetStringValue(L"Language", L"809");
  213. }
  214. }
  215. }
  216. exit:
  217. CoUninitialize();
  218. if (FAILED(hr))
  219. {
  220. return -1;
  221. }
  222. return 0;
  223. }
  224. /*****************************************************************************
  225. * CreateVoiceSubKey *
  226. *--------------------*
  227. * Description:
  228. * Each TTS voice gets installed under one registry sub-key.
  229. * This function installs the single voice from the passed params.
  230. *
  231. ********************************************************************** MC ***/
  232. HRESULT CreateVoiceSubKey(
  233. const WCHAR * pszSubKeyName,
  234. const WCHAR * pszDescription,
  235. BOOL fVendorDefault,
  236. const WCHAR * pszLanguage,
  237. const WCHAR * pszGender,
  238. const WCHAR * pszAge,
  239. const WCHAR * pszVoicePath,
  240. const WCHAR * pszVoiceName,
  241. const WCHAR * pszDictPath,
  242. double dGain)
  243. {
  244. HRESULT hr;
  245. CComPtr<ISpObjectToken> cpToken;
  246. CComPtr<ISpDataKey> cpDataKeyAttribs;
  247. hr = SpCreateNewTokenEx(
  248. SPCAT_VOICES,
  249. pszSubKeyName,
  250. &CLSID_TrueTalk,
  251. pszDescription,
  252. 0x409,
  253. pszDescription,
  254. &cpToken,
  255. &cpDataKeyAttribs);
  256. if (SUCCEEDED(hr))
  257. {
  258. hr = cpDataKeyAttribs->SetStringValue(L"Name", pszDescription);
  259. }
  260. if (SUCCEEDED(hr))
  261. {
  262. hr = cpDataKeyAttribs->SetStringValue(L"Vendor", L"Microsoft");
  263. }
  264. if (SUCCEEDED(hr))
  265. {
  266. hr = cpDataKeyAttribs->SetStringValue(L"Language", pszLanguage);
  267. }
  268. if (SUCCEEDED(hr))
  269. {
  270. hr = cpDataKeyAttribs->SetStringValue(L"Age", pszAge);
  271. }
  272. if (SUCCEEDED(hr))
  273. {
  274. hr = cpDataKeyAttribs->SetStringValue(L"Gender", pszGender);
  275. }
  276. if (SUCCEEDED(hr) && fVendorDefault)
  277. {
  278. hr = cpDataKeyAttribs->SetStringValue(L"VendorDefault", L"");
  279. }
  280. WCHAR szVoiceDataPath[MAX_PATH];
  281. if (SUCCEEDED(hr))
  282. {
  283. //--------------------------------
  284. // Voice DATA file location
  285. //--------------------------------
  286. wcscpy(szVoiceDataPath, pszVoicePath);
  287. wcscat(szVoiceDataPath, pszVoiceName);
  288. hr = cpToken->SetStringValue(L"Sfont", szVoiceDataPath);
  289. }
  290. if (SUCCEEDED(hr))
  291. {
  292. hr = cpToken->SetStringValue(L"Dictionary", pszDictPath);
  293. }
  294. if (SUCCEEDED(hr))
  295. {
  296. WCHAR pszGain[20];
  297. swprintf (pszGain, L"%.1f", dGain);
  298. hr = cpToken->SetStringValue(L"Gain", pszGain);
  299. }
  300. return hr;
  301. }