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.

547 lines
16 KiB

  1. /*
  2. ***************************************************************
  3. * sndfile.c
  4. *
  5. * This file contains the code to fill up the list and combo boxes,
  6. * show the RIFF Dibs and the current sound mappings
  7. *
  8. * Copyright 1993, Microsoft Corporation
  9. *
  10. * History:
  11. *
  12. * 07/94 - VijR (Created)
  13. *
  14. ***************************************************************
  15. */
  16. #include <windows.h>
  17. #include <mmsystem.h>
  18. #include <string.h>
  19. #include <ole2.h>
  20. #include <prsht.h>
  21. #include <cpl.h>
  22. #include "mmcpl.h"
  23. #include "draw.h"
  24. #include "sound.h"
  25. /*
  26. ***************************************************************
  27. * Globals
  28. ***************************************************************
  29. */
  30. HSOUND ghse;
  31. /*
  32. ***************************************************************
  33. * extern
  34. ***************************************************************
  35. */
  36. extern TCHAR gszMediaDir[];
  37. extern TCHAR gszCurDir[];
  38. extern BOOL gfWaveExists; // indicates wave device in system.
  39. extern BOOL gfChanged; // Is set TRUE if any changes are made
  40. extern BOOL gfNewScheme;
  41. //Globals used in painting disp chunk display.
  42. extern HTREEITEM ghOldItem;
  43. /*
  44. ***************************************************************
  45. * Defines
  46. ***************************************************************
  47. */
  48. #define DF_PM_SETBITMAP (WM_USER+1)
  49. #define FOURCC_INFO mmioFOURCC('I','N','F','O')
  50. #define FOURCC_DISP mmioFOURCC('D','I','S','P')
  51. #define FOURCC_INAM mmioFOURCC('I','N','A','M')
  52. #define FOURCC_ISBJ mmioFOURCC('I','S','B','J')
  53. #define MAXDESCLEN 220
  54. /*
  55. ***************************************************************
  56. * Prototypes
  57. ***************************************************************
  58. */
  59. HANDLE PASCAL GetRiffDisp (HMMIO);
  60. BOOL PASCAL ShowSoundMapping (HWND, PEVENT);
  61. BOOL PASCAL ChangeSoundMapping (HWND, LPTSTR, PEVENT);
  62. BOOL PASCAL PlaySoundFile (HWND, LPTSTR);
  63. BOOL PASCAL ChangeSetting (LPTSTR*, LPTSTR);
  64. LPTSTR PASCAL NiceName(LPTSTR sz, BOOL fNukePath);
  65. // Stuff in dib.c
  66. //
  67. HPALETTE WINAPI bmfCreateDIBPalette(HANDLE);
  68. HBITMAP WINAPI bmfBitmapFromDIB(HANDLE, HPALETTE);
  69. // Stuff in drivers.c
  70. //
  71. LPTSTR lstrchr (LPTSTR, TCHAR);
  72. int lstrnicmp (LPTSTR, LPTSTR, size_t);
  73. // Stuff in scheme.c
  74. //
  75. void PASCAL AddMediaPath (LPTSTR, LPTSTR);
  76. /*
  77. ***************************************************************
  78. ***************************************************************
  79. */
  80. STATIC void NEAR PASCAL ChopPath(LPTSTR lpszFile)
  81. {
  82. TCHAR szTmp[MAX_PATH];
  83. size_t cchTest = lstrlen (gszCurDir);
  84. szTmp[0] = TEXT('\0');
  85. ExpandEnvironmentStrings(lpszFile, (LPTSTR)szTmp, MAXSTR);
  86. lstrcpy(lpszFile,szTmp);
  87. if (gszCurDir[ cchTest-1 ] == TEXT('\\'))
  88. --cchTest;
  89. lstrcpy((LPTSTR)szTmp, lpszFile);
  90. if (!lstrnicmp((LPTSTR)szTmp, (LPTSTR)gszCurDir, cchTest))
  91. {
  92. if (szTmp[ cchTest ] == TEXT('\\'))
  93. {
  94. lstrcpy(lpszFile, (LPTSTR)(szTmp+cchTest+1));
  95. }
  96. }
  97. }
  98. /*
  99. ***************************************************************
  100. * QualifyFileName
  101. *
  102. * Description:
  103. * Verifies the existence and readability of a file.
  104. *
  105. * Parameters:
  106. * LPTSTR lpszFile - name of file to check.
  107. * LPTSTR lpszPath - returning full pathname of file.
  108. * int csSize - Size of return buffer
  109. *
  110. * Returns: BOOL
  111. * True if absolute path exists
  112. *
  113. ***************************************************************
  114. */
  115. BOOL PASCAL QualifyFileName(LPTSTR lpszFile, LPTSTR lpszPath, int cbSize, BOOL fTryCurDir)
  116. {
  117. BOOL fErrMode;
  118. BOOL f = FALSE;
  119. BOOL fHadEnvStrings;
  120. TCHAR szTmpFile[MAXSTR];
  121. int len;
  122. BOOL fTriedCurDir;
  123. TCHAR* pszFilePart;
  124. HFILE hFile;
  125. if (!lpszFile)
  126. return FALSE;
  127. fHadEnvStrings = (lstrchr (lpszFile, TEXT('%')) != NULL) ? TRUE : FALSE;
  128. ExpandEnvironmentStrings (lpszFile, (LPTSTR)szTmpFile, MAXSTR);
  129. len = lstrlen((LPTSTR)szTmpFile)+1;
  130. fErrMode = SetErrorMode(TRUE); // we will handle errors
  131. AddExt (szTmpFile, cszWavExt);
  132. fTriedCurDir = FALSE;
  133. TryOpen:
  134. hFile = (HFILE)HandleToUlong(CreateFile(szTmpFile,GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
  135. if (-1 != hFile)
  136. {
  137. if (fHadEnvStrings)
  138. lstrcpyn(lpszPath, lpszFile, cbSize);
  139. else
  140. GetFullPathName(szTmpFile,cbSize/sizeof(TCHAR),lpszPath,&pszFilePart);
  141. f = TRUE;
  142. CloseHandle(LongToHandle(hFile));
  143. }
  144. else
  145. /*
  146. ** If the test above failed, we try converting the name to OEM
  147. ** character set and try again.
  148. */
  149. {
  150. /*
  151. ** First, is it in MediaPath?
  152. **
  153. */
  154. if (lstrchr (lpszFile, TEXT('\\')) == NULL)
  155. {
  156. TCHAR szCurDirFile[MAXSTR];
  157. AddMediaPath (szCurDirFile, lpszFile);
  158. if (-1 != (HFILE)HandleToUlong(CreateFile(szCurDirFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)))
  159. {
  160. GetFullPathName(szCurDirFile,cbSize/sizeof(TCHAR),lpszPath,&pszFilePart);
  161. f = TRUE;
  162. goto DidOpen;
  163. }
  164. }
  165. //AnsiToOem((LPTSTR)szTmpFile, (LPTSTR)szTmpFile);
  166. if (-1 != (HFILE)HandleToUlong(CreateFile(szTmpFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)))
  167. {
  168. if (fHadEnvStrings)
  169. lstrcpyn(lpszPath, lpszFile, cbSize);
  170. else
  171. GetFullPathName(szTmpFile,cbSize/sizeof(TCHAR),lpszPath,&pszFilePart);
  172. f = TRUE;
  173. }
  174. else if (fTryCurDir && !fTriedCurDir)
  175. {
  176. TCHAR szCurDirFile[MAXSTR];
  177. //OemToAnsi((LPTSTR)szTmpFile, (LPTSTR)szTmpFile);
  178. lstrcpy (szCurDirFile, gszCurDir);
  179. lstrcat (szCurDirFile, cszSlash);
  180. lstrcat (szCurDirFile, szTmpFile);
  181. lstrcpy((LPTSTR)szTmpFile, (LPTSTR)szCurDirFile);
  182. fTriedCurDir = TRUE;
  183. goto TryOpen;
  184. }
  185. }
  186. DidOpen:
  187. SetErrorMode(fErrMode);
  188. return f;
  189. }
  190. /*
  191. ***************************************************************
  192. * ChangeSoundMapping
  193. *
  194. * Description:
  195. * Change the sound file associated with a sound
  196. *
  197. * Parameters:
  198. * HWND hDlg - handle to dialog window.
  199. * LPTSTR lpszFile - New filename for current event
  200. * LPTSTR lpszDir - New foldername for current event
  201. * LPTSTR lpszPath - New absolute path for file
  202. *
  203. * Returns: BOOL
  204. *
  205. ***************************************************************
  206. */
  207. BOOL PASCAL ChangeSoundMapping(HWND hDlg, LPTSTR lpszPath, PEVENT pEvent)
  208. {
  209. TCHAR szValue[MAXSTR];
  210. if (!pEvent)
  211. {
  212. if(!ghse)
  213. EnableWindow(GetDlgItem(hDlg, ID_PLAY), FALSE);
  214. EnableWindow(GetDlgItem(hDlg, IDC_SOUND_FILES), FALSE);
  215. ShowSoundMapping(hDlg,NULL);
  216. return TRUE;
  217. }
  218. szValue[0] = TEXT('\0');
  219. if (!ChangeSetting((LPTSTR *)&(pEvent->pszPath), lpszPath))
  220. return FALSE;
  221. if(!ghse)
  222. EnableWindow(GetDlgItem(hDlg, ID_PLAY), TRUE);
  223. EnableWindow(GetDlgItem(hDlg, IDC_SOUND_FILES), TRUE);
  224. ShowSoundMapping(hDlg,pEvent);
  225. gfChanged = TRUE;
  226. gfNewScheme = TRUE;
  227. PropSheet_Changed(GetParent(hDlg),hDlg);
  228. return TRUE;
  229. }
  230. STATIC void SetTreeStateIcon(HWND hDlg, int iImage)
  231. {
  232. TV_ITEM tvi;
  233. HWND hwndTree = GetDlgItem(hDlg, IDC_EVENT_TREE);
  234. HTREEITEM hti;
  235. if (ghOldItem)
  236. hti = ghOldItem;
  237. else
  238. hti = TreeView_GetSelection(hwndTree);
  239. if (hti)
  240. {
  241. tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  242. tvi.hItem = hti;
  243. tvi.iImage = tvi.iSelectedImage = iImage;
  244. TreeView_SetItem(hwndTree, &tvi);
  245. RedrawWindow(hwndTree, NULL, NULL, RDW_ERASE|RDW_ERASENOW|RDW_INTERNALPAINT|RDW_INVALIDATE | RDW_UPDATENOW);
  246. }
  247. }
  248. /*
  249. ***************************************************************
  250. * ShowSoundMapping
  251. *
  252. * Description:
  253. * Highlights the label and calls ShowSoundDib to display the Dib
  254. * associated with the current event.
  255. *
  256. * Parameters:
  257. * HWND hDlg - handle to dialog window.
  258. *
  259. * Returns: BOOL
  260. *
  261. ***************************************************************
  262. */
  263. BOOL PASCAL ShowSoundMapping(HWND hDlg, PEVENT pEvent)
  264. {
  265. TCHAR szOut[MAXSTR];
  266. if (!pEvent)
  267. {
  268. EnableWindow(GetDlgItem(hDlg, IDC_SOUND_FILES), FALSE);
  269. EnableWindow(GetDlgItem(hDlg, ID_BROWSE), FALSE);
  270. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_NAME), FALSE);
  271. // wsprintf((LPTSTR)szCurSound, (LPTSTR)gszSoundGrpStr, (LPTSTR)gszNull);
  272. }
  273. else
  274. {
  275. EnableWindow(GetDlgItem(hDlg, IDC_SOUND_FILES), TRUE);
  276. EnableWindow(GetDlgItem(hDlg, ID_BROWSE), TRUE);
  277. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_NAME), TRUE);
  278. // wsprintf((LPTSTR)szCurSound, (LPTSTR)gszSoundGrpStr, (LPTSTR)pEvent->pszEventLabel);
  279. }
  280. //SetWindowText(GetDlgItem(hDlg, IDC_SOUNDGRP), (LPTSTR)szCurSound);
  281. //RedrawWindow(GetDlgItem(hDlg, IDC_EVENT_TREE), NULL, NULL, RDW_ERASE|RDW_ERASENOW|RDW_INTERNALPAINT|RDW_INVALIDATE | RDW_UPDATENOW);
  282. if (!pEvent || !QualifyFileName(pEvent->pszPath, szOut, sizeof(szOut), FALSE))
  283. {
  284. int iLen;
  285. if(!ghse)
  286. EnableWindow(GetDlgItem(hDlg, ID_PLAY), FALSE);
  287. if(pEvent)
  288. iLen = lstrlen(pEvent->pszPath);
  289. if (pEvent && iLen > 0)
  290. {
  291. if (iLen < 5)
  292. {
  293. lstrcpy(pEvent->pszPath, gszNull);
  294. gfChanged = TRUE;
  295. gfNewScheme = TRUE;
  296. PropSheet_Changed(GetParent(hDlg),hDlg);
  297. }
  298. else
  299. {
  300. TCHAR szMsg[MAXSTR];
  301. TCHAR szTitle[MAXSTR];
  302. LoadString(ghInstance, IDS_NOSNDFILE, szTitle, sizeof(szTitle)/sizeof(TCHAR));
  303. wsprintf(szMsg, szTitle, pEvent->pszPath);
  304. LoadString(ghInstance, IDS_NOSNDFILETITLE, szTitle, sizeof(szTitle)/sizeof(TCHAR));
  305. if (MessageBox(hDlg, szMsg, szTitle, MB_YESNO) == IDNO)
  306. {
  307. lstrcpy(pEvent->pszPath, gszNull);
  308. ComboBox_SetText(GetDlgItem(hDlg, IDC_SOUND_FILES), gszNone);
  309. gfChanged = TRUE;
  310. gfNewScheme = TRUE;
  311. PropSheet_Changed(GetParent(hDlg),hDlg);
  312. if (pEvent && pEvent->fHasSound)
  313. {
  314. SetTreeStateIcon(hDlg, 2);
  315. pEvent->fHasSound = FALSE;
  316. }
  317. }
  318. else
  319. {
  320. lstrcpy(szOut ,pEvent->pszPath);
  321. ChopPath((LPTSTR)szOut);
  322. NiceName((LPTSTR)szOut, FALSE);
  323. ComboBox_SetText(GetDlgItem(hDlg, IDC_SOUND_FILES), szOut);
  324. if (!pEvent->fHasSound)
  325. {
  326. SetTreeStateIcon(hDlg, 1);
  327. pEvent->fHasSound = TRUE;
  328. }
  329. }
  330. }
  331. }
  332. else
  333. {
  334. ComboBox_SetText(GetDlgItem(hDlg, IDC_SOUND_FILES), gszNone);
  335. if (pEvent && pEvent->fHasSound)
  336. {
  337. SetTreeStateIcon(hDlg, 2);
  338. pEvent->fHasSound = FALSE;
  339. }
  340. }
  341. }
  342. else
  343. {
  344. if(!ghse)
  345. EnableWindow(GetDlgItem(hDlg, ID_PLAY),gfWaveExists);
  346. ChopPath((LPTSTR)szOut);
  347. NiceName((LPTSTR)szOut, FALSE);
  348. ComboBox_SetText(GetDlgItem(hDlg, IDC_SOUND_FILES), szOut);
  349. if (!pEvent->fHasSound)
  350. {
  351. SetTreeStateIcon(hDlg, 1);
  352. pEvent->fHasSound = TRUE;
  353. }
  354. }
  355. return TRUE;
  356. }
  357. /*
  358. ***************************************************************
  359. * PlaySoundFile
  360. *
  361. * Description:
  362. * Plays the given sound file.
  363. *
  364. * Parameters:
  365. * HWND hDlg - Window handle
  366. * LPTSTR lpszFile - absolute path of File to play.
  367. *
  368. * Returns: BOOL
  369. *
  370. ***************************************************************
  371. */
  372. BOOL PASCAL PlaySoundFile(HWND hDlg, LPTSTR lpszFile)
  373. {
  374. TCHAR szOut[MAXSTR];
  375. TCHAR szTemp[MAXSTR];
  376. BOOL rb = TRUE;
  377. if (!QualifyFileName(lpszFile, szTemp, sizeof(szTemp), FALSE))
  378. {
  379. ErrorBox(hDlg, IDS_ERRORPLAY, lpszFile);
  380. rb = FALSE;
  381. }
  382. else{
  383. MMRESULT err = MMSYSERR_NOERROR;
  384. ExpandEnvironmentStrings (szTemp, szOut, MAXSTR);
  385. if((soundOpen(szOut, hDlg, &ghse) != MMSYSERR_NOERROR) || ((err = soundPlay(ghse)) != MMSYSERR_NOERROR))
  386. {
  387. if (err >= (MMRESULT)MMSYSERR_LASTERROR)
  388. ErrorBox(hDlg, IDS_ERRORUNKNOWNPLAY, lpszFile);
  389. else if (err == (MMRESULT)MMSYSERR_ALLOCATED)
  390. ErrorBox(hDlg, IDS_ERRORDEVBUSY, lpszFile);
  391. else
  392. ErrorBox(hDlg, IDS_ERRORFILEPLAY, lpszFile);
  393. ghse = NULL;
  394. rb = FALSE;
  395. }
  396. }
  397. return rb;
  398. }
  399. /*
  400. ***************************************************************
  401. * ChangeSetting
  402. *
  403. * Description:
  404. * Displays the labels of all the links present in the lpszDir folder
  405. * in the LB_SOUNDS listbox
  406. *
  407. * Parameters:
  408. * HWND hDlg - Window handle
  409. * LPTSTR lpszDir - Name of sound folder whose files must be displayed.
  410. *
  411. * Returns: BOOL
  412. *
  413. ***************************************************************
  414. */
  415. BOOL PASCAL ChangeSetting(LPTSTR *npOldString, LPTSTR lpszNew)
  416. {
  417. int len = (lstrlen(lpszNew)*sizeof(TCHAR))+sizeof(TCHAR);
  418. if (*npOldString)
  419. {
  420. LocalFree(*npOldString);
  421. }
  422. *npOldString = (LPTSTR)LocalAlloc(LPTR, len);
  423. if (*npOldString == NULL)
  424. {
  425. DPF("LocalAlloc Failed\n");
  426. return FALSE;
  427. }
  428. lstrcpy(*npOldString, lpszNew);
  429. DPF("New file is %s\n", (LPTSTR)*npOldString);
  430. return TRUE;
  431. }
  432. STATIC HANDLE PASCAL GetRiffDisp(HMMIO hmmio)
  433. {
  434. MMCKINFO ck;
  435. MMCKINFO ckRIFF;
  436. HANDLE h = NULL;
  437. LONG lSize;
  438. DWORD dw;
  439. mmioSeek(hmmio, 0, SEEK_SET);
  440. /* descend the input file into the RIFF chunk */
  441. if (mmioDescend(hmmio, &ckRIFF, NULL, 0) != 0)
  442. goto error;
  443. if (ckRIFF.ckid != FOURCC_RIFF)
  444. goto error;
  445. while (!mmioDescend(hmmio, &ck, &ckRIFF, 0))
  446. {
  447. if (ck.ckid == FOURCC_DISP)
  448. {
  449. /* Read dword into dw, break if read unsuccessful */
  450. if (mmioRead(hmmio, (LPVOID)&dw, sizeof(dw)) != (LONG)sizeof(dw))
  451. goto error;
  452. /* Find out how much memory to allocate */
  453. lSize = ck.cksize - sizeof(dw);
  454. if ((int)dw == CF_DIB && h == NULL)
  455. {
  456. /* get a handle to memory to hold the description and
  457. lock it down */
  458. if ((h = GlobalAlloc(GHND, lSize+4)) == NULL)
  459. goto error;
  460. if (mmioRead(hmmio, GlobalLock(h), lSize) != lSize)
  461. goto error;
  462. }
  463. }
  464. //
  465. // if we have both a picture and a title, then exit.
  466. //
  467. if (h != NULL)
  468. break;
  469. /* Ascend so that we can descend into next chunk
  470. */
  471. if (mmioAscend(hmmio, &ck, 0))
  472. break;
  473. }
  474. goto exit;
  475. error:
  476. if (h)
  477. {
  478. GlobalUnlock(h);
  479. GlobalFree(h);
  480. }
  481. h = NULL;
  482. exit:
  483. return h;
  484. }