flowm_main.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. /*************************************************************************/
  2. /* */
  3. /* Language Technologies Institute */
  4. /* Carnegie Mellon University */
  5. /* Copyright (c) 2008-2009 */
  6. /* All Rights Reserved. */
  7. /* */
  8. /* Permission is hereby granted, free of charge, to use and distribute */
  9. /* this software and its documentation without restriction, including */
  10. /* without limitation the rights to use, copy, modify, merge, publish, */
  11. /* distribute, sublicense, and/or sell copies of this work, and to */
  12. /* permit persons to whom this work is furnished to do so, subject to */
  13. /* the following conditions: */
  14. /* 1. The code must retain the above copyright notice, this list of */
  15. /* conditions and the following disclaimer. */
  16. /* 2. Any modifications must be clearly marked as such. */
  17. /* 3. Original authors' names are not deleted. */
  18. /* 4. The authors' names are not used to endorse or promote products */
  19. /* derived from this software without specific prior written */
  20. /* permission. */
  21. /* */
  22. /* CARNEGIE MELLON UNIVERSITY AND THE CONTRIBUTORS TO THIS WORK */
  23. /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
  24. /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
  25. /* SHALL CARNEGIE MELLON UNIVERSITY NOR THE CONTRIBUTORS BE LIABLE */
  26. /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
  27. /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
  28. /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
  29. /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
  30. /* THIS SOFTWARE. */
  31. /* */
  32. /*************************************************************************/
  33. /* Author: Alan W Black (awb@cs.cmu.edu) */
  34. /* Date: January 2009 */
  35. /*************************************************************************/
  36. /* */
  37. /* Flowm: Flite on Windows Mobile (pronounced flume) */
  38. /* 0.5 */
  39. /* */
  40. /* A simple file reader */
  41. /* */
  42. /* Thanks to Programming Microsoft Windows CE by Douglas Boling which */
  43. /* taught me a lot about how to program in WinCE */
  44. /* */
  45. /*************************************************************************/
  46. #include <windows.h>
  47. #include <windowsx.h>
  48. #include <commctrl.h>
  49. #include <aygshell.h>
  50. /* Apparently from pwingdi.h -- but I don't have that .h file */
  51. /* For DisplayOff */
  52. #define SETPOWERMANAGEMENT 6147
  53. #define VideoPowerOff 4
  54. typedef struct _VIDEO_POWER_MANAGEMENT {
  55. ULONG Length;
  56. ULONG DPMSVersion;
  57. ULONG PowerState;
  58. } VIDEO_POWER_MANAGEMENT;
  59. #include "flowm.h"
  60. #define AppName L"Flown"
  61. HINSTANCE hInst;
  62. int flowm_play_status = FLOWM_STOP;
  63. TCHAR fl_filename[257];
  64. int flowm_file_pos = 0;
  65. int flowm_file_size = 0;
  66. /* To hold position of previous utterances for backskipping */
  67. int flowm_utt_pos_pos=0;
  68. int flowm_prev_utt_pos[FLOWM_NUM_UTT_POS];
  69. int flowm_selected_voice = 0;
  70. int flowm_selected_relation = 0;
  71. float flowm_duration = 0.0;
  72. #define FL_BENCH_TEXT L"A whole joy was reaping, but they've gone south, you should fetch azure mike."
  73. HWND hmbar = 0;
  74. HWND TTSWindow = 0;
  75. TCHAR fl_tts_msg[FL_MAX_MSG_CHARS];
  76. TCHAR fl_fp_msg[FL_MAX_MSG_CHARS];
  77. SHACTIVATEINFO sai;
  78. HANDLE tts_thread = INVALID_HANDLE_VALUE;
  79. const MsgDispatch MainDispatchers[] =
  80. {
  81. { WM_CREATE, DoCreateMain },
  82. { WM_SIZE, DoSizeMain },
  83. { WM_COMMAND, DoCommandMain },
  84. { WM_NOTIFY, DoNotifyMain },
  85. { WM_SETTINGCHANGE, DoSettingChangeMain },
  86. { WM_HIBERNATE, DoHibernateMain },
  87. { WM_ACTIVATE, DoActivateMain },
  88. { WM_DESTROY, DoDestroyMain },
  89. { 0, NULL }
  90. };
  91. const CMDDispatch MainCommandItems[] = {
  92. { FL_EXIT, DoMainCommandExit },
  93. { FL_PLAY, DoMainCommandPlay },
  94. { FL_FILE, DoMainCommandFile },
  95. { FL_ABOUT, DoMainCommandAbout },
  96. { 0, NULL }
  97. };
  98. /*********************************************************************/
  99. /*********************************************************************/
  100. LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  101. {
  102. int i;
  103. for (i=0; MainDispatchers[i].Code != 0; i++)
  104. {
  105. if (msg == MainDispatchers[i].Code)
  106. return (MainDispatchers[i].Fxn)(hwnd,msg,wParam,lParam);
  107. }
  108. return DefWindowProc(hwnd,msg,wParam,lParam);
  109. }
  110. LRESULT DoCreateMain(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  111. {
  112. SHMENUBARINFO mbi;
  113. ZeroMemory(&mbi,sizeof(mbi));
  114. mbi.cbSize = sizeof(SHMENUBARINFO);
  115. mbi.hwndParent = hwnd;
  116. mbi.nToolBarId = FL_TOOLBAR1;
  117. mbi.hInstRes = hInst;
  118. SHCreateMenuBar(&mbi);
  119. hmbar=mbi.hwndMB;
  120. if (!hmbar)
  121. {
  122. MessageBox(hwnd, L"Couldn't create toolbar",AppName, MB_OK);
  123. DestroyWindow(hwnd);
  124. return 0;
  125. }
  126. fl_filename[0] = '\0';
  127. return 0;
  128. }
  129. LRESULT DoSizeMain(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  130. {
  131. return 0;
  132. }
  133. LRESULT DoCommandMain(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  134. {
  135. WORD idItem, wNotifyCode;
  136. HWND hwndCtl;
  137. int i;
  138. idItem = (WORD)LOWORD(wParam);
  139. wNotifyCode = (WORD)HIWORD(wParam);
  140. hwndCtl = (HWND)lParam;
  141. for (i=0; MainCommandItems[i].Code; i++)
  142. {
  143. if (idItem == MainCommandItems[i].Code)
  144. return MainCommandItems[i].Fxn(hwnd,idItem,hwndCtl,wNotifyCode);
  145. }
  146. return 0;
  147. }
  148. LRESULT DoNotifyMain (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  149. {
  150. return 0;
  151. }
  152. LRESULT DoSettingChangeMain(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  153. {
  154. SHHandleWMSettingChange(hwnd, wParam, lParam, &sai);
  155. return 0;
  156. }
  157. LRESULT DoHibernateMain(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  158. {
  159. return 0;
  160. }
  161. LRESULT DoActivateMain(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  162. {
  163. SHHandleWMActivate(hwnd, wParam, lParam, &sai, 0);
  164. return 0;
  165. }
  166. LRESULT DoDestroyMain(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  167. {
  168. PostQuitMessage(0);
  169. return 0;
  170. }
  171. /* Command handler routines */
  172. LPARAM DoMainCommandExit(HWND hwnd, WORD idItem, HWND hwndCtl, WORD wNotifyCode)
  173. {
  174. SendMessage(hwnd, WM_CLOSE, 0, 0);
  175. return 0;
  176. }
  177. LPARAM DoMainCommandAbout(HWND hwnd, WORD idItem,
  178. HWND hwndCtl, WORD wNotifyCode)
  179. {
  180. DialogBox(hInst, L"aboutbox", hwnd, AboutDlgProc);
  181. return 0;
  182. }
  183. BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  184. {
  185. SHINITDLGINFO idi;
  186. switch (msg)
  187. {
  188. case WM_INITDIALOG:
  189. idi.dwMask = SHIDIM_FLAGS;
  190. idi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIZEDLGFULLSCREEN |
  191. SHIDIF_SIPDOWN;
  192. idi.hDlg = hwnd;
  193. SHInitDialog (&idi);
  194. return TRUE;
  195. case WM_COMMAND:
  196. switch (LOWORD(wParam))
  197. {
  198. case IDOK:
  199. case IDCANCEL:
  200. EndDialog(hwnd,0);
  201. return TRUE;
  202. }
  203. break;
  204. }
  205. return FALSE;
  206. }
  207. LPARAM DoMainCommandPlay(HWND hwnd, WORD idItem,
  208. HWND hwndCtl, WORD wNotifyCode)
  209. {
  210. DialogBox(hInst, L"playbox", hwnd, PlayDlgProc);
  211. return 0;
  212. }
  213. BOOL CALLBACK PlayDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  214. {
  215. OPENFILENAME sf;
  216. const LPTSTR pszSaveFilter = L"Waveforms (*.wav)\0*.wav\0\0";
  217. SHINITDLGINFO idi;
  218. TCHAR text[FL_MAX_TEXTLEN];
  219. TCHAR szFilePos[FL_MAX_TEXTLEN];
  220. TCHAR *x;
  221. int i, looptimes;
  222. SYSTEMTIME StartTime, EndTime;
  223. float elapsedtime;
  224. switch (msg)
  225. {
  226. case WM_INITDIALOG:
  227. idi.dwMask = SHIDIM_FLAGS;
  228. idi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIZEDLGFULLSCREEN;
  229. idi.hDlg = hwnd;
  230. SHInitDialog (&idi);
  231. for (i=0; flowm_voice_name(i); i++)
  232. { /* Add regestered voices to the voice dropdown */
  233. SendDlgItemMessage(hwnd, FL_VOXLIST, CB_ADDSTRING,
  234. 0, (LPARAM)flowm_voice_name(i));
  235. }
  236. /* Position cursor at start, selecting first voice */
  237. SendDlgItemMessage(hwnd, FL_VOXLIST, CB_SETCURSEL, 0, 0);
  238. /* Add Relation types to the selection box */
  239. SendDlgItemMessage(hwnd,FL_RELLIST,CB_ADDSTRING,0,(LPARAM)L"Token");
  240. SendDlgItemMessage(hwnd,FL_RELLIST,CB_ADDSTRING,0,(LPARAM)L"Word");
  241. SendDlgItemMessage(hwnd,FL_RELLIST,CB_ADDSTRING,0,(LPARAM)L"Segment");
  242. SendDlgItemMessage(hwnd,FL_RELLIST,CB_SETCURSEL,0,0);
  243. TTSWindow = 0; /* just in case there is a race condition */
  244. return TRUE;
  245. case WM_COMMAND:
  246. switch (LOWORD(wParam))
  247. {
  248. case FL_PUSHPLAY:
  249. /* Synthesis the text with selection voice */
  250. /* Output items in selected relation at end */
  251. GetDlgItemText(hwnd, FL_TEXT, text, FL_MAX_TEXTLEN);
  252. flowm_selected_voice =
  253. ComboBox_GetCurSel(GetDlgItem(hwnd,FL_VOXLIST));
  254. flowm_selected_relation =
  255. ComboBox_GetCurSel(GetDlgItem(hwnd,FL_RELLIST));
  256. flowm_play_status = FLOWM_PLAY;
  257. flowm_say_text(text);
  258. flowm_play_status = FLOWM_STOP;
  259. if (flowm_selected_relation > 0)
  260. SetDlgItemText(hwnd, FL_OUTPUT, fl_tts_msg);
  261. return TRUE;
  262. case FL_PUSHSAVE:
  263. /* Save the last synthesized waveform */
  264. ZeroMemory(&sf,sizeof(sf));
  265. sf.lStructSize = sizeof(sf);
  266. sf.lpstrFile = fl_filename;
  267. sf.nMaxFile = 256;
  268. sf.lpstrFilter = pszSaveFilter;
  269. sf.Flags = 0;
  270. sf.lpstrTitle = L"Flowm Save";
  271. if (GetSaveFileName(&sf) != 0)
  272. {
  273. if (flowm_save_wave(fl_filename) == -1)
  274. wsprintf(fl_tts_msg,L"Wave NOT saved in %s",fl_filename);
  275. else
  276. wsprintf(fl_tts_msg,L"Wave saved in %s",fl_filename);
  277. MessageBox(hwnd, fl_tts_msg, AppName, MB_OK);
  278. }
  279. fl_filename[0] = '\0';
  280. return TRUE;
  281. case FL_BENCH:
  282. /* Bench marking, find out the speed of synthesis on device */
  283. if (flowm_play_status == FLOWM_BENCH)
  284. {
  285. flowm_play_status = FLOWM_STOP;
  286. return TRUE;
  287. }
  288. flowm_play_status = FLOWM_BENCH;
  289. /* Find out what voice we want */
  290. flowm_selected_voice =
  291. ComboBox_GetCurSel(GetDlgItem(hwnd,FL_VOXLIST));
  292. flowm_selected_relation = 0;
  293. flowm_duration = 0.0;
  294. GetSystemTime(&StartTime);
  295. GetDlgItemText(hwnd, FL_TEXT, szFilePos, FL_MAX_TEXTLEN);
  296. looptimes = wcstod(szFilePos,&x);
  297. if (looptimes < 5)
  298. looptimes = 5;
  299. wsprintf(fl_tts_msg,L"Bench marking: loop = %d ...",looptimes);
  300. SetDlgItemText(hwnd, FL_OUTPUT, fl_tts_msg);
  301. SetDlgItemText(hwnd, FL_TEXT,FL_BENCH_TEXT);
  302. for (i=0; i<looptimes; i++)
  303. flowm_say_text(FL_BENCH_TEXT);
  304. GetSystemTime(&EndTime);
  305. /* This will fail over noon (?) and midnight */
  306. elapsedtime =
  307. (EndTime.wHour*60.0*60.0+EndTime.wMinute*60.0+
  308. EndTime.wSecond+EndTime.wMilliseconds/1000.0) -
  309. (StartTime.wHour*60.0*60.0+StartTime.wMinute*60.0+
  310. StartTime.wSecond+ StartTime.wMilliseconds/1000.0);
  311. wsprintf(fl_tts_msg,L"%2.1f speech; %2.1f seconds; %2.2f rate;",
  312. flowm_duration,
  313. elapsedtime,
  314. flowm_duration/elapsedtime);
  315. SetDlgItemText(hwnd, FL_OUTPUT, fl_tts_msg);
  316. flowm_play_status = FLOWM_STOP;
  317. return TRUE;
  318. case IDOK:
  319. case IDCANCEL:
  320. flowm_play_status = FLOWM_STOP;
  321. EndDialog(hwnd,0);
  322. return TRUE;
  323. }
  324. break;
  325. }
  326. return FALSE;
  327. }
  328. LPARAM DoMainCommandFile(HWND hwnd, WORD idItem,
  329. HWND hwndCtl, WORD wNotifyCode)
  330. {
  331. DialogBox(hInst, L"filebox", hwnd, FileDlgProc);
  332. return 0;
  333. }
  334. DWORD WINAPI tts_thread_function(PVOID pArg)
  335. {
  336. while (flowm_play_status != FLOWM_STOP)
  337. {
  338. flowm_say_file(fl_filename);
  339. if (flowm_play_status == FLOWM_BACKSKIP)
  340. flowm_play_status = FLOWM_PLAY; /* restart at new place */
  341. else if (flowm_play_status != FLOWM_STOP)
  342. {
  343. /* If we finish the file without an explicit stop, reset */
  344. /* the file position to the start of the file */
  345. flowm_file_pos = 0;
  346. if (TTSWindow) SetDlgItemText(TTSWindow, FL_FILEPOS, L"0");
  347. flowm_play_status = FLOWM_STOP;
  348. }
  349. }
  350. return 0x15;
  351. }
  352. static int flowm_find_filesize(TCHAR *filename)
  353. {
  354. HANDLE fp;
  355. int fs = 0;
  356. fp = CreateFile(filename, GENERIC_READ,
  357. FILE_SHARE_READ, NULL,
  358. OPEN_EXISTING,
  359. FILE_ATTRIBUTE_NORMAL,
  360. NULL);
  361. if (!fp)
  362. return -1;
  363. fs = GetFileSize(fp,NULL);
  364. CloseHandle(fp);
  365. return fs;
  366. }
  367. void DisplayOff()
  368. { /* Switch the screen off now */
  369. HDC hdc;
  370. VIDEO_POWER_MANAGEMENT vpm;
  371. hdc = GetDC(NULL);
  372. vpm.PowerState = VideoPowerOff;
  373. vpm.Length = sizeof(VIDEO_POWER_MANAGEMENT);
  374. ExtEscape(hdc,
  375. SETPOWERMANAGEMENT,
  376. sizeof(VIDEO_POWER_MANAGEMENT),
  377. (LPCSTR)&vpm,
  378. 0,
  379. NULL);
  380. return;
  381. }
  382. BOOL CALLBACK FileDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  383. {
  384. SHINITDLGINFO idi;
  385. OPENFILENAME of;
  386. const LPTSTR pszOpenFilter = L"Text Documents (*.txt)\0*.txt\0\0";
  387. int nParameter = 5;
  388. DWORD dwThreadID = 0;
  389. TCHAR szFilePos[FL_MAX_TEXTLEN];
  390. TCHAR *x;
  391. int i;
  392. float nfilepos;
  393. HWND hwndvox;
  394. switch (msg)
  395. {
  396. case WM_INITDIALOG:
  397. idi.dwMask = SHIDIM_FLAGS;
  398. idi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIZEDLGFULLSCREEN;
  399. idi.hDlg = hwnd;
  400. SHInitDialog (&idi);
  401. if (fl_filename[0] != '\0')
  402. {
  403. SetDlgItemText(hwnd, FL_FILENAME, fl_filename);
  404. flowm_file_pos = 0;
  405. SetDlgItemText(hwnd, FL_FILEPOS, L"0");
  406. }
  407. for (i=0; flowm_voice_name(i); i++)
  408. { /* Add regestered voices to the voice dropdown */
  409. SendDlgItemMessage(hwnd, FL_VOXLIST, CB_ADDSTRING,
  410. 0, (LPARAM)flowm_voice_name(i));
  411. }
  412. /* Position cursor at start, selecting first voice */
  413. SendDlgItemMessage(hwnd, FL_VOXLIST, CB_SETCURSEL, 0, 0);
  414. return TRUE;
  415. case WM_COMMAND:
  416. switch (LOWORD(wParam))
  417. {
  418. case FL_PUSHSELECT:
  419. /* Find a file to synthesize */
  420. fl_filename[0] = '\0';
  421. ZeroMemory(&of,sizeof(of));
  422. of.lStructSize = sizeof(of);
  423. of.lpstrFile = fl_filename;
  424. of.nMaxFile = 256;
  425. of.lpstrFilter = pszOpenFilter;
  426. of.Flags = 0;
  427. of.lpstrTitle = L"Flowm Open";
  428. if (GetOpenFileName(&of) != 0)
  429. {
  430. flowm_play_status = FLOWM_STOP;
  431. SetDlgItemText(hwnd, FL_FILENAME, fl_filename);
  432. flowm_file_pos = 0;
  433. flowm_file_size = flowm_find_filesize(fl_filename);
  434. flowm_utt_pos_pos = 0;
  435. flowm_prev_utt_pos[flowm_utt_pos_pos] = 0;
  436. SetDlgItemText(hwnd, FL_FILEPOS, L"0");
  437. SetDlgItemText(hwnd, FL_SYNTHTEXT, L"");
  438. if (flowm_file_size == -1)
  439. {
  440. wsprintf(fl_fp_msg,L"File not found: %s",fl_filename);
  441. MessageBox(hwnd, fl_fp_msg,AppName, MB_OK);
  442. fl_filename[0] = '\0';
  443. }
  444. }
  445. return TRUE;
  446. case FL_PUSHTTS:
  447. /* Synthesize the selected file from the specified position */
  448. /* with the selected voice */
  449. if ((flowm_play_status != FLOWM_PLAY) &&
  450. (fl_filename[0] != '\0'))
  451. {
  452. flowm_play_status = FLOWM_PLAY;
  453. TTSWindow = hwnd;
  454. /* Find out what voice we want */
  455. hwndvox = GetDlgItem(hwnd,FL_VOXLIST);
  456. flowm_selected_voice = ComboBox_GetCurSel(hwndvox);
  457. /* Update file position, in case user changed it */
  458. GetDlgItemText(hwnd, FL_FILEPOS, szFilePos, FL_MAX_TEXTLEN);
  459. nfilepos = wcstod(szFilePos,&x);
  460. /* Be a little careful we don't reset file position */
  461. /* when we have an accuracy problem: filepos is an int */
  462. /* but the display field is the % */
  463. if (nfilepos > 100) nfilepos = 100.0;
  464. if (nfilepos < 0) nfilepos = 0.0;
  465. if (((nfilepos - flowm_find_file_percentage()) > 0.001) ||
  466. ((nfilepos - flowm_find_file_percentage()) < -0.001))
  467. flowm_file_pos = (int)((nfilepos*flowm_file_size)/100.0);
  468. /* Do the synthesis in a new thread, so we can still process */
  469. /* button pushes */
  470. tts_thread = CreateThread(NULL, 0, tts_thread_function,
  471. (PVOID)nParameter, 0, &dwThreadID);
  472. CloseHandle(tts_thread);
  473. }
  474. return TRUE;
  475. case FL_PUSHBACK:
  476. /* Move back to previous utterance */
  477. if (flowm_utt_pos_pos > 0)
  478. { /* Jump back to beginning of previous utt (we know about) */
  479. flowm_utt_pos_pos--;
  480. flowm_file_pos = flowm_prev_utt_pos[flowm_utt_pos_pos];
  481. }
  482. else if (flowm_file_pos > 1)
  483. /* Not got any previous -- we never payed that bit get */
  484. /* so just jump back 100 chars */
  485. flowm_file_pos -= 100;
  486. else /* At start of file already */
  487. flowm_file_pos = 0;
  488. wsprintf(fl_fp_msg,L"%2.3f",flowm_find_file_percentage());
  489. SetDlgItemText(TTSWindow, FL_FILEPOS, fl_fp_msg);
  490. flowm_play_status = FLOWM_BACKSKIP;
  491. return TRUE;
  492. case FL_PUSHFORWARD:
  493. /* Skip forward to next utterances now */
  494. if ((flowm_play_status == FLOWM_PLAY) ||
  495. (flowm_play_status == FLOWM_SKIP))
  496. flowm_play_status = FLOWM_SKIP; /* already playing/skipping */
  497. else
  498. { /* No playing so just jump forward 100 chars */
  499. flowm_file_pos += 100;
  500. wsprintf(fl_fp_msg,L"%2.3f",flowm_find_file_percentage());
  501. SetDlgItemText(TTSWindow, FL_FILEPOS, fl_fp_msg);
  502. }
  503. return TRUE;
  504. case FL_PUSHSTOP:
  505. flowm_play_status = FLOWM_STOP;
  506. return TRUE;
  507. case FL_SCREENOFF:
  508. /* turn off the screen */
  509. DisplayOff();
  510. return TRUE;
  511. case IDOK:
  512. if (flowm_play_status == FLOWM_STOP)
  513. { /* Only end if we are in stop mode */
  514. TTSWindow = 0; /* just in case there is a race condition */
  515. EndDialog(hwnd,0);
  516. }
  517. return TRUE; /* you need to press end to end */
  518. case FL_PUSHEND:
  519. case IDCANCEL:
  520. flowm_play_status = FLOWM_STOP;
  521. TTSWindow = 0; /* just in case there is a race condition */
  522. EndDialog(hwnd,0);
  523. return TRUE;
  524. }
  525. break;
  526. }
  527. return FALSE;
  528. }
  529. int WinMain(HINSTANCE hInstance,
  530. HINSTANCE hPrevInstance,
  531. LPWSTR lpCmdLine,
  532. int nCmdShow)
  533. {
  534. MSG msg;
  535. HWND hwndMain=0;
  536. int rc;
  537. rc = InitApp(hInstance);
  538. if (rc) return rc;
  539. hwndMain=InitInstance(hInstance,lpCmdLine, nCmdShow);
  540. if (hwndMain == 0) return 0x10;
  541. flowm_init(); /* Initialize the TTS system */
  542. while (GetMessage(&msg,NULL,0,0))
  543. {
  544. TranslateMessage(&msg);
  545. DispatchMessage(&msg);
  546. }
  547. flowm_terminate(); /* Close the TTS systems */
  548. return msg.wParam;
  549. }
  550. int InitApp(HINSTANCE hInstance)
  551. {
  552. WNDCLASS wc;
  553. HWND hWnd;
  554. /* If already running, return */
  555. hWnd = FindWindow(AppName,NULL);
  556. if (hWnd)
  557. {
  558. SetForegroundWindow((HWND)(((DWORD)hWnd) | 0x01));
  559. return -1;
  560. }
  561. wc.style = CS_VREDRAW | CS_HREDRAW;
  562. wc.lpfnWndProc = MainWndProc; /* main callback function */
  563. wc.cbClsExtra = 0;
  564. wc.cbWndExtra = 0;
  565. wc.hInstance = hInstance;
  566. wc.hIcon = NULL;
  567. wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Default cursor */
  568. wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  569. wc.lpszMenuName = NULL; /* Menu name */
  570. wc.lpszClassName = AppName; /* Window class name */
  571. if (RegisterClass(&wc) == 0)
  572. return 1;
  573. else
  574. return 0;
  575. }
  576. HWND InitInstance(HINSTANCE hInstance, LPWSTR lpCmdLine, int nCmdShow)
  577. {
  578. HWND hwnd;
  579. hInst = hInstance;
  580. hwnd = CreateWindow(AppName,
  581. AppName,
  582. WS_VISIBLE,
  583. CW_USEDEFAULT, /* x position */
  584. CW_USEDEFAULT, /* y position */
  585. CW_USEDEFAULT, /* Initial width */
  586. CW_USEDEFAULT, /* Initial height */
  587. NULL, /* Parent */
  588. NULL, /* Menu */
  589. hInstance,
  590. NULL); /* extra params */
  591. if (!IsWindow(hwnd))
  592. return 0; /* failed to create a window */
  593. ShowWindow(hwnd, nCmdShow);
  594. UpdateWindow(hwnd);
  595. return hwnd;
  596. }