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.

1518 lines
36 KiB

  1. /* (C) Copyright Microsoft Corporation 1991-1994. All Rights Reserved */
  2. /* SoundRec.c
  3. *
  4. * SoundRec main loop etc.
  5. * Revision History.
  6. * 4/2/91 LaurieGr (AKA LKG) Ported to WIN32 / WIN16 common code
  7. * 21/2/94 LaurieGr Merged Daytona and Motown versions
  8. * LaurieGr Merged common button and trackbar code from StephenE
  9. */
  10. #undef NOWH // Allow SetWindowsHook and WH_*
  11. #include <windows.h>
  12. #include <shellapi.h>
  13. #include <shlobj.h>
  14. #include <windowsx.h>
  15. #include <mmsystem.h>
  16. #include <htmlhelp.h>
  17. #ifdef USE_MMCNTRLS
  18. #include "mmcntrls.h"
  19. #else
  20. #include <commctrl.h>
  21. #include "buttons.h"
  22. #endif
  23. #include <mmreg.h>
  24. #define INCLUDE_OLESTUBS
  25. #include "soundrec.h"
  26. #include "srecids.h"
  27. #include "fixreg.h"
  28. #include "reg.h"
  29. #include "convert.h"
  30. #include "helpids.h"
  31. #include <stdarg.h>
  32. #include <stdio.h>
  33. /* globals */
  34. BOOL gfUserClose; // user-driven shutdown
  35. HWND ghwndApp; // main application window
  36. HINSTANCE ghInst; // program instance handle
  37. TCHAR gachFileName[_MAX_PATH];// current file name (or UNTITLED)
  38. BOOL gfDirty; // file was modified and not saved?
  39. BOOL gfClipboard; // we have data in clipboard
  40. int gfErrorBox; // TRUE if we have a message box active
  41. HICON ghiconApp; // app's icon
  42. HWND ghwndWaveDisplay; // waveform display window handle
  43. HWND ghwndScroll; // scroll bar control window handle
  44. HWND ghwndPlay; // Play button window handle
  45. HWND ghwndStop; // Stop button window handle
  46. HWND ghwndRecord; // Record button window handle
  47. #ifdef THRESHOLD
  48. HWND ghwndSkipStart; // Needed to enable/disable...
  49. HWND ghwndSkipEnd; // ...the skip butons
  50. #endif //THRESHOLD
  51. HWND ghwndForward; // [>>] button
  52. HWND ghwndRewind; // [<<] button
  53. BOOL gfWasPlaying; // was playing before scroll, fwd, etc.
  54. BOOL gfWasRecording; // was recording before scroll etc.
  55. BOOL gfPaused; // are we paused now?
  56. BOOL gfPausing; // are we stopping into a paused state?
  57. HWAVE ghPausedWave; // holder for the paused wave handle
  58. int gidDefaultButton; // which button should have input focus
  59. BOOL gfEmbeddedObject; // Are we editing an embedded object?
  60. BOOL gfRunWithEmbeddingFlag; // TRUE if we are run with "-Embedding"
  61. BOOL gfHideAfterPlaying;
  62. BOOL gfShowWhilePlaying;
  63. BOOL gfInUserDestroy = FALSE;
  64. TCHAR chDecimal = TEXT('.');
  65. BOOL gfLZero = 1; // do we use leading zeros?
  66. BOOL gfIsRTL = 0; // no compile BIDI
  67. UINT guiACMHlpMsg = 0; // help message from ACM, none == 0
  68. //Data used for supporting context menu help
  69. BOOL bF1InMenu=FALSE; //If true F1 was pressed on a menu item.
  70. UINT currMenuItem=0; //The current selected menu item if any.
  71. BITMAPBTN tbPlaybar[] = {
  72. { ID_REWINDBTN - ID_BTN_BASE, ID_REWINDBTN, 0 }, /* index 0 */
  73. { ID_FORWARDBTN - ID_BTN_BASE, ID_FORWARDBTN,0 }, /* index 1 */
  74. { ID_PLAYBTN - ID_BTN_BASE, ID_PLAYBTN, 0 }, /* index 2 */
  75. { ID_STOPBTN - ID_BTN_BASE, ID_STOPBTN, 0 }, /* index 3 */
  76. { ID_RECORDBTN - ID_BTN_BASE, ID_RECORDBTN, 0 } /* index 4 */
  77. };
  78. #include <msacmdlg.h>
  79. #ifdef CHICAGO
  80. /* these id's are part of the main windows help file */
  81. #define IDH_AUDIO_CUST_ATTRIB 2403
  82. #define IDH_AUDIO_CUST_FORMAT 2404
  83. #define IDH_AUDIO_CUST_NAME 2405
  84. #define IDH_AUDIO_CUST_REMOVE 2406
  85. #define IDH_AUDIO_CUST_SAVEAS 2407
  86. const DWORD aChooserHelpIds[] = {
  87. IDD_ACMFORMATCHOOSE_CMB_FORMAT, IDH_AUDIO_CUST_ATTRIB,
  88. IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, IDH_AUDIO_CUST_FORMAT,
  89. IDD_ACMFORMATCHOOSE_CMB_CUSTOM, IDH_AUDIO_CUST_NAME,
  90. IDD_ACMFORMATCHOOSE_BTN_DELNAME, IDH_AUDIO_CUST_REMOVE,
  91. IDD_ACMFORMATCHOOSE_BTN_SETNAME, IDH_AUDIO_CUST_SAVEAS,
  92. 0, 0
  93. };
  94. UINT guChooserContextMenu = 0;
  95. UINT guChooserContextHelp = 0;
  96. #endif
  97. /*
  98. * constants
  99. */
  100. SZCODE aszNULL[] = TEXT("");
  101. SZCODE aszClassKey[] = TEXT(".wav");
  102. SZCODE aszIntl[] = TEXT("Intl");
  103. /*
  104. * statics
  105. */
  106. static HHOOK hMsgHook;
  107. /*
  108. * functions
  109. */
  110. BOOL SoundRec_OnHScroll(HWND hwnd, HWND hwndCtl, UINT code, int pos);
  111. BOOL SoundRec_OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT *lpdis);
  112. void SoundRec_ControlPanel(HINSTANCE hinst, HWND hwnd);
  113. BOOL NEAR PASCAL FreeWaveHeaders(void);
  114. /*
  115. * HelpMsgFilter - filter for F1 key in dialogs
  116. */
  117. LRESULT CALLBACK
  118. HelpMsgFilter(
  119. int nCode,
  120. WPARAM wParam,
  121. LPARAM lParam)
  122. {
  123. LPMSG msg;
  124. if (nCode >= 0){
  125. msg = (LPMSG)lParam;
  126. if ((msg->message == WM_KEYDOWN) && (LOWORD(msg->wParam) == VK_F1))
  127. {
  128. // testing for <0 tests MSB whether int is 16 or 32 bits
  129. // MSB set means key is down
  130. if (( GetAsyncKeyState(VK_SHIFT)
  131. | GetAsyncKeyState(VK_CONTROL)
  132. | GetAsyncKeyState(VK_MENU)) < 0 )
  133. //
  134. // do nothing
  135. //
  136. ;
  137. else
  138. {
  139. if(nCode == MSGF_MENU)
  140. {
  141. bF1InMenu = TRUE;
  142. SendMessage(ghwndApp, WM_COMMAND, IDM_HELPTOPICS, 0L);
  143. }
  144. }
  145. }
  146. }
  147. return CallNextHookEx(hMsgHook, nCode, wParam, lParam);
  148. }
  149. /* WinMain(hInst, hPrev, lpszCmdLine, cmdShow)
  150. *
  151. * The main procedure for the App. After initializing, it just goes
  152. * into a message-processing loop until it gets a WM_QUIT message
  153. * (meaning the app was closed).
  154. */
  155. int WINAPI // returns exit code specified in WM_QUIT
  156. WinMain(
  157. HINSTANCE hInst, // instance handle of current instance
  158. HINSTANCE hPrev, // instance handle of previous instance
  159. LPSTR lpszCmdLine, // null-terminated command line
  160. int iCmdShow) // how window should be initially displayed
  161. {
  162. HWND hDlg;
  163. MSG rMsg;
  164. //
  165. // save instance handle for dialog boxes
  166. //
  167. ghInst = hInst;
  168. DPF(TEXT("AppInit ...\n"));
  169. //
  170. // call initialization procedure
  171. //
  172. if (!AppInit(hInst, hPrev))
  173. {
  174. DPF(TEXT("AppInit failed\n"));
  175. return FALSE;
  176. }
  177. //
  178. // setup the message filter to handle grabbing F1 for this task
  179. //
  180. hMsgHook = SetWindowsHookEx(WH_MSGFILTER, HelpMsgFilter, ghInst, GetCurrentThreadId());
  181. //
  182. // display "SoundRec" dialog box
  183. //
  184. hDlg = CreateDialogParam( ghInst
  185. , MAKEINTRESOURCE(IDD_SOUNDRECBOX)
  186. , NULL
  187. , SoundRecDlgProc
  188. , iCmdShow );
  189. if (hDlg)
  190. {
  191. //
  192. // Polling messages from event queue
  193. //
  194. while (GetMessage(&rMsg, NULL, 0, 0))
  195. {
  196. if (ghwndApp) {
  197. if (TranslateAccelerator(ghwndApp, ghAccel, &rMsg))
  198. continue;
  199. if (IsDialogMessage(ghwndApp,&rMsg))
  200. continue;
  201. }
  202. TranslateMessage(&rMsg);
  203. DispatchMessage(&rMsg);
  204. }
  205. }
  206. //
  207. // free the current document
  208. //
  209. DestroyWave();
  210. //
  211. // if the message hook was installed, remove it and free
  212. // up our proc instance for it.
  213. //
  214. if (hMsgHook)
  215. {
  216. UnhookWindowsHookEx(hMsgHook);
  217. }
  218. //
  219. // random cleanup
  220. //
  221. DeleteObject(ghbrPanel);
  222. if(gfOleInitialized)
  223. {
  224. FlushOleClipboard();
  225. OleUninitialize();
  226. gfOleInitialized = FALSE;
  227. }
  228. return TRUE;
  229. }
  230. /*
  231. * Process file drop/drag options.
  232. */
  233. void SoundRec_OnDropFiles(
  234. HWND hwnd,
  235. HDROP hdrop)
  236. {
  237. TCHAR szPath[_MAX_PATH];
  238. if (DragQueryFile(hdrop, (UINT)(-1), NULL, 0) > 0)
  239. {
  240. //
  241. // If user dragged/dropped a file regardless of keys pressed
  242. // at the time, open the first selected file from file
  243. // manager.
  244. //
  245. DragQueryFile(hdrop,0,szPath,SIZEOF(szPath));
  246. SetActiveWindow(hwnd);
  247. ResolveIfLink(szPath);
  248. if (FileOpen(szPath))
  249. {
  250. gfHideAfterPlaying = FALSE;
  251. //
  252. // This is a bit hacked. The Ole caption should just never change.
  253. //
  254. if (gfEmbeddedObject && !gfLinked)
  255. {
  256. LPTSTR lpszObj, lpszApp;
  257. extern void SetOleCaption(LPTSTR lpsz);
  258. DoOleSave();
  259. AdviseSaved();
  260. OleObjGetHostNames(&lpszApp,&lpszObj);
  261. lpszObj = (LPTSTR)FileName((LPCTSTR)lpszObj);
  262. SetOleCaption(lpszObj);
  263. }
  264. PostMessage(ghwndApp, WM_COMMAND, ID_PLAYBTN, 0L);
  265. }
  266. }
  267. DragFinish(hdrop); // Delete structure alocated
  268. }
  269. /* Pause(BOOL fBeginPause)
  270. *
  271. * If <fBeginPause>, then if user is playing or recording do a StopWave().
  272. * The next call to Pause() should have <fBeginPause> be FALSE -- this will
  273. * cause the playing or recording to be resumed (possibly at a new position
  274. * if <glWavePosition> changed.
  275. */
  276. void
  277. Pause(BOOL fBeginPause)
  278. {
  279. if (fBeginPause) {
  280. if (ghWaveOut != NULL) {
  281. #ifdef NEWPAUSE
  282. gfPausing = TRUE;
  283. gfPaused = FALSE;
  284. ghPausedWave = (HWAVE)ghWaveOut;
  285. #endif
  286. gfWasPlaying = TRUE;
  287. // User intentionally stopped us. Don't go away.
  288. if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp))
  289. gfCloseAtEndOfPlay = FALSE;
  290. StopWave();
  291. }
  292. else if (ghWaveIn != NULL) {
  293. #ifdef NEWPAUSE
  294. gfPausing = TRUE;
  295. gfPaused = FALSE;
  296. ghPausedWave = (HWAVE)ghWaveIn;
  297. #endif
  298. gfWasRecording = TRUE;
  299. // User intentionally stopped us. Don't go away.
  300. if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp))
  301. gfCloseAtEndOfPlay = FALSE;
  302. StopWave();
  303. }
  304. }
  305. else {
  306. if (gfWasPlaying) {
  307. gfWasPlaying = FALSE;
  308. PlayWave();
  309. #ifdef NEWPAUSE
  310. gfPausing = FALSE;
  311. gfPaused = FALSE;
  312. #endif
  313. }
  314. else if (gfWasRecording) {
  315. gfWasRecording = FALSE;
  316. RecordWave();
  317. #ifdef NEWPAUSE
  318. gfPausing = FALSE;
  319. gfPaused = FALSE;
  320. #endif
  321. }
  322. }
  323. }
  324. void DoHtmlHelp()
  325. {
  326. //note, using ANSI version of function because UNICODE is foobar in NT5 builds
  327. char chDst[MAX_PATH];
  328. WideCharToMultiByte(CP_ACP, 0, gachHtmlHelpFile,
  329. -1, chDst, MAX_PATH, NULL, NULL);
  330. HtmlHelpA(GetDesktopWindow(), chDst, HH_DISPLAY_TOPIC, 0L);
  331. }
  332. void ProcessHelp(HWND hwnd)
  333. {
  334. static TCHAR HelpFile[] = TEXT("SOUNDREC.HLP");
  335. //Handle context menu help
  336. if(bF1InMenu)
  337. {
  338. switch(currMenuItem)
  339. {
  340. case IDM_NEW:
  341. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_FILE_NEW);
  342. break;
  343. case IDM_OPEN:
  344. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_FILE_OPEN);
  345. break;
  346. case IDM_SAVE:
  347. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_FILE_SAVE);
  348. break;
  349. case IDM_SAVEAS:
  350. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_FILE_SAVE_AS);
  351. break;
  352. case IDM_REVERT:
  353. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_FILE_REVERT);
  354. break;
  355. case IDM_PROPERTIES:
  356. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_FILE_PROPERTIES);
  357. break;
  358. case IDM_EXIT:
  359. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_FILE_EXIT);
  360. break;
  361. case IDM_COPY:
  362. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_COPY);
  363. break;
  364. case IDM_PASTE_INSERT:
  365. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_PASTE_INSERT);
  366. break;
  367. case IDM_PASTE_MIX:
  368. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_PASTE_MIX);
  369. break;
  370. case IDM_INSERTFILE:
  371. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_INSERT_FILE);
  372. break;
  373. case IDM_MIXWITHFILE:
  374. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_MIX_WITH_FILE);
  375. break;
  376. case IDM_DELETEBEFORE:
  377. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_DELETE_BEFORE_CURRENT_POSITION);
  378. break;
  379. case IDM_DELETEAFTER:
  380. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_DELETE_AFTER_CURRENT_POSITION);
  381. break;
  382. case IDM_VOLUME:
  383. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_AUDIO_PROPERTIES);
  384. break;
  385. case IDM_INCREASEVOLUME:
  386. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EFFECTS_INCREASE_VOLUME);
  387. break;
  388. case IDM_DECREASEVOLUME:
  389. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EFFECTS_DECREASE_VOLUME);
  390. break;
  391. case IDM_MAKEFASTER:
  392. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EFFECTS_INCREASE_SPEED);
  393. break;
  394. case IDM_MAKESLOWER:
  395. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EFFECTS_DECREASE_SPEED);
  396. break;
  397. case IDM_ADDECHO:
  398. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EFFECTS_ADD_ECHO);
  399. break;
  400. case IDM_REVERSE:
  401. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EFFECTS_REVERSE);
  402. break;
  403. case IDM_HELPTOPICS:
  404. case IDM_INDEX:
  405. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_HELP_HELP_TOPICS);
  406. break;
  407. case IDM_ABOUT:
  408. WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_HELP_ABOUT);
  409. break;
  410. default://In the default case just display the HTML Help.
  411. DoHtmlHelp();
  412. }
  413. bF1InMenu = FALSE; //This flag will be set again if F1 is pressed in a menu.
  414. }
  415. else
  416. DoHtmlHelp();
  417. }
  418. /*
  419. * SoundRec_OnCommand
  420. */
  421. BOOL
  422. SoundRec_OnCommand(
  423. HWND hwnd,
  424. int id,
  425. HWND hwndCtl,
  426. UINT codeNotify)
  427. {
  428. if (gfHideAfterPlaying && id != ID_PLAYBTN)
  429. {
  430. DPF(TEXT("Resetting HideAfterPlaying\n"));
  431. gfHideAfterPlaying = FALSE;
  432. }
  433. switch (id)
  434. {
  435. case IDM_NEW:
  436. if (PromptToSave(FALSE, FALSE) == enumCancel)
  437. return FALSE;
  438. #ifdef CHICAGO
  439. if (FileNew(FMT_DEFAULT,TRUE,FALSE))
  440. #else
  441. if (FileNew(FMT_DEFAULT,TRUE,TRUE))
  442. #endif
  443. {
  444. /* return to being a standalone */
  445. gfHideAfterPlaying = FALSE;
  446. }
  447. break;
  448. case IDM_OPEN:
  449. if (FileOpen(NULL)) {
  450. /* return to being a standalone */
  451. gfHideAfterPlaying = FALSE;
  452. }
  453. if (IsWindowEnabled(ghwndPlay))
  454. {
  455. SetDlgFocus(ghwndPlay);
  456. }
  457. break;
  458. case IDM_SAVE: // also OLE UPDATE
  459. if (!gfEmbeddedObject || gfLinked)
  460. {
  461. if (!FileSave(FALSE))
  462. break;
  463. }
  464. else
  465. {
  466. DoOleSave();
  467. gfDirty = FALSE;
  468. }
  469. break;
  470. case IDM_SAVEAS:
  471. if (FileSave(TRUE))
  472. {
  473. /* return to being a standalone */
  474. gfHideAfterPlaying = FALSE;
  475. }
  476. break;
  477. case IDM_REVERT:
  478. UpdateWindow(hwnd);
  479. // User intentionally stopped us. Don't go away.
  480. if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp))
  481. gfCloseAtEndOfPlay = FALSE;
  482. StopWave();
  483. SnapBack();
  484. if (FileRevert())
  485. {
  486. /* return to being a standalone */
  487. gfHideAfterPlaying = FALSE;
  488. }
  489. break;
  490. case IDM_EXIT:
  491. PostMessage(hwnd, WM_CLOSE, 0, 0L);
  492. return TRUE;
  493. case IDCANCEL:
  494. // User intentionally stopped us. Don't go away.
  495. if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp))
  496. gfCloseAtEndOfPlay = FALSE;
  497. StopWave();
  498. SnapBack();
  499. break;
  500. case IDM_COPY:
  501. if (!gfOleInitialized)
  502. {
  503. InitializeOle(ghInst);
  504. if (gfStandalone && gfOleInitialized)
  505. CreateStandaloneObject();
  506. }
  507. TransferToClipboard();
  508. gfClipboard = TRUE;
  509. break;
  510. case IDM_PASTE_INSERT:
  511. case IDM_INSERTFILE:
  512. UpdateWindow(hwnd);
  513. // User intentionally stopped us. Don't go away.
  514. if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp))
  515. gfCloseAtEndOfPlay = FALSE;
  516. StopWave();
  517. SnapBack();
  518. InsertFile(id == IDM_PASTE_INSERT);
  519. break;
  520. case IDM_PASTE_MIX:
  521. case IDM_MIXWITHFILE:
  522. UpdateWindow(hwnd);
  523. // User intentionally stopped us. Don't go away.
  524. if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp))
  525. gfCloseAtEndOfPlay = FALSE;
  526. StopWave();
  527. SnapBack();
  528. MixWithFile(id == IDM_PASTE_MIX);
  529. break;
  530. case IDM_DELETEBEFORE:
  531. UpdateWindow(hwnd);
  532. Pause(TRUE);
  533. DeleteBefore();
  534. Pause(FALSE);
  535. break;
  536. case IDM_DELETE:
  537. if (glWaveSamplesValid == 0L)
  538. return 0L;
  539. glWavePosition = 0L;
  540. // fall through to delete after.
  541. case IDM_DELETEAFTER:
  542. UpdateWindow(hwnd);
  543. Pause(TRUE);
  544. DeleteAfter();
  545. Pause(FALSE);
  546. break;
  547. #ifdef THRESHOLD
  548. // Threshold was an experiment to allow facilities to skip to the start
  549. // of the sound or to the end of the sound. The trouble was that it
  550. // required the ability to detect silence and different sound cards in
  551. // different machines with different background noises gave quite different
  552. // ideas of what counted as silence. Manual control over the threshold level
  553. // did sort-of work but was just too complicated. It really wanted to be
  554. // intuitive or intelligent (or both).
  555. case IDM_SKIPTOSTART:
  556. case ID_SKIPSTARTBTN:
  557. UpdateWindow(hwnd);
  558. Pause(TRUE);
  559. SkipToStart();
  560. Pause(FALSE);
  561. break;
  562. case ID_SKIPENDBTN:
  563. case IDM_SKIPTOEND:
  564. UpdateWindow(hwnd);
  565. Pause(TRUE);
  566. SkipToEnd();
  567. Pause(FALSE);
  568. break;
  569. case IDM_INCREASETHRESH:
  570. IncreaseThresh();
  571. break;
  572. case IDM_DECREASETHRESH:
  573. DecreaseThresh();
  574. break;
  575. #endif //THRESHOLD
  576. case IDM_INCREASEVOLUME:
  577. UpdateWindow(hwnd);
  578. Pause(TRUE);
  579. ChangeVolume(TRUE);
  580. Pause(FALSE);
  581. break;
  582. case IDM_DECREASEVOLUME:
  583. UpdateWindow(hwnd);
  584. Pause(TRUE);
  585. ChangeVolume(FALSE);
  586. Pause(FALSE);
  587. break;
  588. case IDM_MAKEFASTER:
  589. UpdateWindow(hwnd);
  590. Pause(TRUE);
  591. MakeFaster();
  592. Pause(FALSE);
  593. break;
  594. case IDM_MAKESLOWER:
  595. UpdateWindow(hwnd);
  596. Pause(TRUE);
  597. MakeSlower();
  598. Pause(FALSE);
  599. break;
  600. case IDM_ADDECHO:
  601. UpdateWindow(hwnd);
  602. Pause(TRUE);
  603. AddEcho();
  604. Pause(FALSE);
  605. break;
  606. #if defined(REVERB)
  607. case IDM_ADDREVERB:
  608. UpdateWindow(hwnd);
  609. Pause(TRUE);
  610. AddReverb();
  611. Pause(FALSE);
  612. break;
  613. #endif //REVERB
  614. case IDM_REVERSE:
  615. UpdateWindow(hwnd);
  616. Pause(TRUE);
  617. Reverse();
  618. Pause(FALSE);
  619. break;
  620. case IDM_VOLUME:
  621. SoundRec_ControlPanel(ghInst, hwnd);
  622. break;
  623. case IDM_PROPERTIES:
  624. {
  625. WAVEDOC wd;
  626. SGLOBALS sg;
  627. DWORD dw;
  628. wd.pwfx = gpWaveFormat;
  629. wd.pbdata = gpWaveSamples;
  630. wd.cbdata = wfSamplesToBytes(gpWaveFormat, glWaveSamplesValid);
  631. wd.fChanged = FALSE;
  632. wd.pszFileName = (LPTSTR)FileName(gachFileName);
  633. //
  634. // Need to extract these from the file
  635. //
  636. wd.hIcon = NULL;
  637. wd.pszCopyright = gpszInfo;
  638. wd.lpv = &sg;
  639. //
  640. // modify globals w/o returning from prop dialog
  641. //
  642. sg.ppwfx = &gpWaveFormat;
  643. sg.pcbwfx = &gcbWaveFormat;
  644. sg.pcbdata = &dw;
  645. sg.ppbdata = &gpWaveSamples;
  646. sg.plSamplesValid = &glWaveSamplesValid;
  647. sg.plSamples = &glWaveSamples;
  648. sg.plWavePosition = &dw;
  649. SoundRec_Properties(hwnd, ghInst, &wd);
  650. break;
  651. }
  652. #ifndef CHICAGO
  653. case IDM_INDEX:
  654. WinHelp(hwnd, gachHelpFile, HELP_INDEX, 0L);
  655. break;
  656. case IDM_SEARCH:
  657. WinHelp(hwnd, gachHelpFile, HELP_PARTIALKEY,
  658. (DWORD)(LPTSTR)aszNULL);
  659. break;
  660. #else
  661. case IDM_HELPTOPICS:
  662. ProcessHelp(hwnd);
  663. break;
  664. #endif
  665. case IDM_USINGHELP:
  666. WinHelp(hwnd, (LPTSTR)NULL, HELP_HELPONHELP, 0L);
  667. break;
  668. case IDM_ABOUT:
  669. {
  670. LPTSTR lpAbout = NULL;
  671. lpAbout = SoundRec_GetFormatName(gpWaveFormat);
  672. ShellAbout(hwnd,
  673. gachAppTitle,
  674. lpAbout,
  675. (HICON)SendMessage(hwnd, WM_QUERYDRAGICON, 0, 0L));
  676. // , ghiconApp
  677. if (lpAbout)
  678. GlobalFreePtr(lpAbout);
  679. break;
  680. }
  681. case ID_REWINDBTN:
  682. #if 1
  683. //Related to BombayBug 1609
  684. Pause(TRUE);
  685. glWavePosition = 0L;
  686. Pause(FALSE);
  687. UpdateDisplay(FALSE);
  688. #else
  689. //Behave as if the user pressed the 'Home' key
  690. //Call the handler directly
  691. SoundRec_OnHScroll(hwnd,ghwndScroll,SB_TOP,0);
  692. #endif
  693. break;
  694. case ID_PLAYBTN:
  695. // checks for empty file moved to PlayWave in wave.c
  696. // if at end of file, go back to beginning.
  697. if (glWavePosition == glWaveSamplesValid)
  698. glWavePosition = 0;
  699. PlayWave();
  700. break;
  701. case ID_STOPBTN:
  702. // User intentionally stopped us. Don't go away.
  703. if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp))
  704. gfCloseAtEndOfPlay = FALSE;
  705. StopWave();
  706. // I added this update because StopWave doesn't call it and
  707. // if you hit stop too quickly, the buttons aren't updated
  708. // Should StopWave() be calling UpdateDisplay()?
  709. UpdateDisplay(TRUE);
  710. SnapBack();
  711. break;
  712. case ID_RECORDBTN:
  713. /* Never let us be forced to quit after recording. */
  714. gfHideAfterPlaying = FALSE;
  715. RecordWave();
  716. break;
  717. case ID_FORWARDBTN:
  718. #if 1
  719. //Bombay bug 1610
  720. //Behave as if the user pressed the 'End' key
  721. Pause(TRUE);
  722. glWavePosition = glWaveSamplesValid;
  723. Pause(FALSE);
  724. UpdateDisplay(FALSE);
  725. #else
  726. //Call the handler directly
  727. SoundRec_OnHScroll(hwnd,ghwndScroll,SB_BOTTOM,0);
  728. #endif
  729. break;
  730. default:
  731. return FALSE;
  732. }
  733. return TRUE;
  734. } /* SoundRec_OnCommand */
  735. /*
  736. * handle WM_INIT from SoundRecDlgProc
  737. */
  738. void
  739. SoundRec_OnInitMenu(HWND hwnd, HMENU hMenu)
  740. {
  741. BOOL fUntitled; // file is untitled?
  742. UINT mf;
  743. //
  744. // see if we can insert/mix into this file.
  745. //
  746. mf = (glWaveSamplesValid == 0 || IsWaveFormatPCM(gpWaveFormat))
  747. ? MF_ENABLED : MF_GRAYED;
  748. EnableMenuItem(hMenu, IDM_INSERTFILE , mf);
  749. EnableMenuItem(hMenu, IDM_MIXWITHFILE , mf);
  750. //
  751. // see if any CF_WAVE data is in the clipboard
  752. //
  753. mf = ( (mf == MF_ENABLED)
  754. && IsClipboardFormatAvailable(CF_WAVE) //DOWECARE (|| IsClipboardNative())
  755. ) ? MF_ENABLED : MF_GRAYED;
  756. EnableMenuItem(hMenu, IDM_PASTE_INSERT, mf);
  757. EnableMenuItem(hMenu, IDM_PASTE_MIX , mf);
  758. //
  759. // see if we can delete before or after the current position.
  760. //
  761. EnableMenuItem(hMenu, IDM_DELETEBEFORE, glWavePosition > 0 ? MF_ENABLED : MF_GRAYED);
  762. EnableMenuItem(hMenu, IDM_DELETEAFTER, (glWaveSamplesValid-glWavePosition) > 0 ? MF_ENABLED : MF_GRAYED);
  763. //
  764. // see if we can do editing operations on the file.
  765. //
  766. mf = IsWaveFormatPCM(gpWaveFormat) ? MF_ENABLED : MF_GRAYED;
  767. EnableMenuItem(hMenu, IDM_INCREASEVOLUME , mf);
  768. EnableMenuItem(hMenu, IDM_DECREASEVOLUME , mf);
  769. EnableMenuItem(hMenu, IDM_MAKEFASTER , mf);
  770. EnableMenuItem(hMenu, IDM_MAKESLOWER , mf);
  771. EnableMenuItem(hMenu, IDM_ADDECHO , mf);
  772. EnableMenuItem(hMenu, IDM_REVERSE , mf);
  773. /* enable "Revert..." if the file was opened or saved
  774. * (not created using "New") and is currently dirty
  775. * and we're not using an embedded object
  776. */
  777. fUntitled = (lstrcmp(gachFileName, aszUntitled) == 0);
  778. EnableMenuItem( hMenu,
  779. IDM_REVERT,
  780. (!fUntitled && gfDirty && !gfEmbeddedObject)
  781. ? MF_ENABLED : MF_GRAYED);
  782. if (gfHideAfterPlaying) {
  783. DPF(TEXT("Resetting HideAfterPlaying"));
  784. gfHideAfterPlaying = FALSE;
  785. }
  786. } /* SoundRec_OnInitMenu() */
  787. /*
  788. * Handle WM_HSCROLL from SoundRecDlgProc
  789. * */
  790. BOOL
  791. SoundRec_OnHScroll(
  792. HWND hwnd,
  793. HWND hwndCtl,
  794. UINT code,
  795. int pos)
  796. {
  797. BOOL fFineControl;
  798. long lNewPosition; // new position in wave buffer
  799. LONG l;
  800. LONG lBlockInc;
  801. LONG lInc;
  802. fFineControl = (0 > GetKeyState(VK_SHIFT));
  803. if (gfHideAfterPlaying) {
  804. DPF(TEXT("Resetting HideAfterPlaying"));
  805. gfHideAfterPlaying = FALSE;
  806. }
  807. lBlockInc = wfBytesToSamples(gpWaveFormat,gpWaveFormat->nBlockAlign);
  808. switch (code)
  809. {
  810. case SB_LINEUP: // left-arrow
  811. // This is a mess. NT implemented SHIFT and Motown implemented CTRL
  812. // To do about the same thing!!
  813. if (fFineControl)
  814. lNewPosition = glWavePosition - 1;
  815. else {
  816. l = (GetKeyState(VK_CONTROL) < 0) ?
  817. (SCROLL_LINE_MSEC/10) : SCROLL_LINE_MSEC;
  818. lNewPosition = glWavePosition -
  819. MulDiv(l, (long) gpWaveFormat->nSamplesPerSec, 1000L);
  820. }
  821. break;
  822. case SB_PAGEUP: // left-page
  823. // NEEDS SOMETHING SENSIBLE !!! ???
  824. if (fFineControl)
  825. lNewPosition = glWavePosition - 10;
  826. else
  827. lNewPosition = glWavePosition -
  828. MulDiv((long) SCROLL_PAGE_MSEC,
  829. (long) gpWaveFormat->nSamplesPerSec, 1000L);
  830. break;
  831. case SB_LINEDOWN: // right-arrow
  832. if (fFineControl)
  833. lNewPosition = glWavePosition + 1;
  834. else {
  835. l = (GetKeyState(VK_CONTROL) & 0x8000) ?
  836. (SCROLL_LINE_MSEC/10) : SCROLL_LINE_MSEC;
  837. lInc = MulDiv(l, (long) gpWaveFormat->nSamplesPerSec, 1000L);
  838. lInc = (lInc < lBlockInc)?lBlockInc:lInc;
  839. lNewPosition = glWavePosition + lInc;
  840. }
  841. break;
  842. case SB_PAGEDOWN: // right-page
  843. if (fFineControl)
  844. lNewPosition = glWavePosition + 10;
  845. else {
  846. lInc = MulDiv((long) SCROLL_PAGE_MSEC,
  847. (long) gpWaveFormat->nSamplesPerSec, 1000L);
  848. lInc = (lInc < lBlockInc)?lBlockInc:lInc;
  849. lNewPosition = glWavePosition + lInc;
  850. }
  851. break;
  852. case SB_THUMBTRACK: // thumb has been positioned
  853. case SB_THUMBPOSITION: // thumb has been positioned
  854. lNewPosition = MulDiv(glWaveSamplesValid, pos, SCROLL_RANGE);
  855. break;
  856. case SB_TOP: // Home
  857. lNewPosition = 0L;
  858. break;
  859. case SB_BOTTOM: // End
  860. lNewPosition = glWaveSamplesValid;
  861. break;
  862. case SB_ENDSCROLL: // user released mouse button
  863. /* resume playing, if necessary */
  864. Pause(FALSE);
  865. return TRUE;
  866. default:
  867. return TRUE;
  868. }
  869. //
  870. // snap position to nBlockAlign
  871. //
  872. if (lNewPosition != glWaveSamplesValid)
  873. lNewPosition = wfSamplesToSamples(gpWaveFormat,lNewPosition);
  874. if (lNewPosition < 0)
  875. lNewPosition = 0;
  876. if (lNewPosition > glWaveSamplesValid)
  877. lNewPosition = glWaveSamplesValid;
  878. /* if user is playing or recording, pause until scrolling
  879. * is complete
  880. */
  881. Pause(TRUE);
  882. glWavePosition = lNewPosition;
  883. UpdateDisplay(FALSE);
  884. return TRUE;
  885. } /* SoundRec_OnHScroll() */
  886. /*
  887. * WM_SYSCOLORCHANGE needs to be send to all child windows (esp. trackbars)
  888. */
  889. void SoundRec_PropagateMessage(
  890. HWND hwnd,
  891. UINT uMessage,
  892. WPARAM wParam,
  893. LPARAM lParam)
  894. {
  895. HWND hwndChild;
  896. for (hwndChild = GetWindow(hwnd, GW_CHILD); hwndChild != NULL;
  897. hwndChild = GetWindow(hwndChild, GW_HWNDNEXT))
  898. {
  899. SendMessage(hwndChild, uMessage, wParam, lParam);
  900. }
  901. }
  902. /* SoundRecDlgProc(hwnd, wMsg, wParam, lParam)
  903. *
  904. * This function handles messages belonging to the main window dialog box.
  905. */
  906. INT_PTR CALLBACK
  907. SoundRecDlgProc(
  908. HWND hwnd,
  909. UINT wMsg,
  910. WPARAM wParam,
  911. LPARAM lParam)
  912. {
  913. switch (wMsg)
  914. {
  915. case WM_BADREG:
  916. //
  917. // Bad registry entries detected. Clean it up.
  918. //
  919. FixReg(hwnd);
  920. return TRUE;
  921. case WM_COMMAND:
  922. return HANDLE_WM_COMMAND( hwnd, wParam, lParam
  923. , SoundRec_OnCommand );
  924. case WM_INITDIALOG:
  925. //
  926. // Start async registry check.
  927. //
  928. if (!IgnoreRegCheck())
  929. BackgroundRegCheck(hwnd);
  930. //
  931. // restore window position
  932. //
  933. SoundRec_GetSetRegistryRect(hwnd, SGSRR_GET);
  934. return SoundDialogInit(hwnd, (int)lParam);
  935. case WM_SIZE:
  936. return FALSE; // let dialog manager do whatever else it wants
  937. case WM_WININICHANGE:
  938. if (!lParam || !lstrcmpi((LPTSTR)lParam, aszIntl))
  939. if (GetIntlSpecs())
  940. UpdateDisplay(TRUE);
  941. return (TRUE);
  942. case WM_INITMENU:
  943. HANDLE_WM_INITMENU(hwnd, wParam, lParam, SoundRec_OnInitMenu);
  944. return (TRUE);
  945. case WM_PASTE:
  946. UpdateWindow(hwnd);
  947. // User intentionally stopped us. Don't go away.
  948. if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp))
  949. gfCloseAtEndOfPlay = FALSE;
  950. StopWave();
  951. SnapBack();
  952. InsertFile(TRUE);
  953. break;
  954. case WM_DRAWITEM:
  955. return HANDLE_WM_DRAWITEM( hwnd, wParam, lParam, SoundRec_OnDrawItem );
  956. case WM_NOTIFY:
  957. {
  958. LPNMHDR pnmhdr;
  959. pnmhdr = (LPNMHDR)lParam;
  960. //
  961. // tooltips notifications
  962. //
  963. switch (pnmhdr->code)
  964. {
  965. case TTN_NEEDTEXT:
  966. {
  967. LPTOOLTIPTEXT lpTt;
  968. lpTt = (LPTOOLTIPTEXT)lParam;
  969. LoadString( ghInst, (UINT)lpTt->hdr.idFrom, lpTt->szText
  970. , SIZEOF(lpTt->szText) );
  971. break;
  972. }
  973. default:
  974. break;
  975. }
  976. break;
  977. }
  978. case WM_HSCROLL:
  979. HANDLE_WM_HSCROLL(hwnd, wParam, lParam, SoundRec_OnHScroll);
  980. return (TRUE);
  981. case WM_SYSCOMMAND:
  982. if (gfHideAfterPlaying)
  983. {
  984. DPF(TEXT("Resetting HideAfterPlaying"));
  985. gfHideAfterPlaying = FALSE;
  986. }
  987. switch (wParam & 0xFFF0)
  988. {
  989. case SC_CLOSE:
  990. PostMessage(hwnd, WM_CLOSE, 0, 0L);
  991. return TRUE;
  992. }
  993. break;
  994. case WM_QUERYENDSESSION:
  995. if (PromptToSave(FALSE, TRUE) == enumCancel)
  996. return TRUE;
  997. SoundRec_GetSetRegistryRect(hwnd, SGSRR_SET);
  998. #if 0 // this is bogus if someone else cancels the shutdown!
  999. ShowWindow(hwnd, SW_HIDE);
  1000. #endif
  1001. return FALSE;
  1002. case WM_SYSCOLORCHANGE:
  1003. if (ghbrPanel)
  1004. DeleteObject(ghbrPanel);
  1005. ghbrPanel = CreateSolidBrush(RGB_PANEL);
  1006. SoundRec_PropagateMessage(hwnd, wMsg, wParam, lParam);
  1007. break;
  1008. case WM_ERASEBKGND:
  1009. {
  1010. RECT rcClient; // client rectangle
  1011. GetClientRect(hwnd, &rcClient);
  1012. FillRect((HDC)wParam, &rcClient, ghbrPanel);
  1013. return TRUE;
  1014. }
  1015. case MM_WOM_DONE:
  1016. WaveOutDone((HWAVEOUT)wParam, (LPWAVEHDR) lParam);
  1017. return TRUE;
  1018. case MM_WIM_DATA:
  1019. WaveInData((HWAVEIN)wParam, (LPWAVEHDR) lParam);
  1020. return TRUE;
  1021. case WM_TIMER:
  1022. //
  1023. // timer message is only used for SYNCRONOUS drivers
  1024. //
  1025. UpdateDisplay(FALSE);
  1026. return TRUE;
  1027. case WM_MENUSELECT:
  1028. //Keep track of which menu bar item is currently popped up.
  1029. //This will be used for displaying the appropriate help from the mplayer.hlp file
  1030. //when the user presses the F1 key.
  1031. currMenuItem = (UINT)LOWORD(wParam);
  1032. return TRUE;
  1033. case MM_WIM_CLOSE:
  1034. return TRUE;
  1035. case WM_CTLCOLORBTN:
  1036. case WM_CTLCOLORSTATIC:
  1037. {
  1038. POINT pt;
  1039. pt.x = pt.y = 0;
  1040. ClientToScreen((HWND)lParam, &pt);
  1041. ScreenToClient(hwnd, &pt);
  1042. SetBrushOrgEx((HDC) wParam, -pt.x, -pt.y, NULL);
  1043. return (INT_PTR)ghbrPanel;
  1044. }
  1045. case WM_CLOSE:
  1046. if (gfInUserDestroy)
  1047. {
  1048. DestroyWindow(hwnd);
  1049. return TRUE;
  1050. }
  1051. DPF(TEXT("WM_CLOSE received\n"));
  1052. gfUserClose = TRUE;
  1053. if (gfHideAfterPlaying)
  1054. {
  1055. DPF(TEXT("Resetting HideAfterPlaying\n"));
  1056. gfHideAfterPlaying = FALSE;
  1057. }
  1058. if (gfErrorBox) {
  1059. // DPF("we have a error box up, ignoring WM_CLOSE.\n");
  1060. return TRUE;
  1061. }
  1062. if (PromptToSave(TRUE, FALSE) == enumCancel)
  1063. return TRUE;
  1064. //
  1065. // Don't free our data before terminating. When the clipboard
  1066. // is flushed, we need to commit the data.
  1067. //
  1068. TerminateServer();
  1069. FileNew(FMT_DEFAULT, FALSE, FALSE);
  1070. FreeACM();
  1071. FreeWaveHeaders();
  1072. //
  1073. // NOTE: TerminateServer() will destroy the window!
  1074. //
  1075. SoundRec_GetSetRegistryRect(hwnd, SGSRR_SET);
  1076. return TRUE; //!!!
  1077. case WM_USER_DESTROY:
  1078. DPF(TEXT("WM_USER_DESTROY\n"));
  1079. if (ghWaveOut || ghWaveIn) {
  1080. DPF(TEXT("Ignoring, we have a device open.\n"));
  1081. //
  1082. // Close later, when the play finishes.
  1083. //
  1084. return TRUE;
  1085. }
  1086. gfInUserDestroy = TRUE;
  1087. PostMessage(hwnd, WM_CLOSE, 0, 0);
  1088. return TRUE;
  1089. case WM_DESTROY:
  1090. DPF(TEXT("WM_DESTROY\n"));
  1091. WinHelp(hwnd, gachHelpFile, HELP_QUIT, 0L);
  1092. ghwndApp = NULL;
  1093. //
  1094. // Tell my app to die
  1095. //
  1096. PostQuitMessage(0);
  1097. return TRUE;
  1098. case WM_DROPFILES:
  1099. HANDLE_WM_DROPFILES(hwnd, wParam, lParam, SoundRec_OnDropFiles);
  1100. break;
  1101. default:
  1102. #ifdef CHICAGO
  1103. //
  1104. // if we have an ACM help message registered see if this
  1105. // message is it.
  1106. //
  1107. if (guiACMHlpMsg && wMsg == guiACMHlpMsg)
  1108. {
  1109. //
  1110. // message was sent from ACM because the user
  1111. // clicked on the HELP button on the chooser dialog.
  1112. // report help for that dialog.
  1113. //
  1114. WinHelp(hwnd, gachHelpFile, HELP_CONTEXT, IDM_NEW);
  1115. return TRUE;
  1116. }
  1117. //
  1118. // Handle context-sensitive help messages from acm dialog
  1119. //
  1120. if( wMsg == guChooserContextMenu )
  1121. {
  1122. WinHelp( (HWND)wParam, NULL, HELP_CONTEXTMENU,
  1123. (UINT_PTR)(LPSTR)aChooserHelpIds );
  1124. }
  1125. else if( wMsg == guChooserContextHelp )
  1126. {
  1127. WinHelp( ((LPHELPINFO)lParam)->hItemHandle, NULL,
  1128. HELP_WM_HELP, (UINT_PTR)(LPSTR)aChooserHelpIds );
  1129. }
  1130. #endif
  1131. break;
  1132. }
  1133. return FALSE;
  1134. } /* SoundRecDlgProc */
  1135. /*
  1136. * Bitmap Buttons
  1137. * */
  1138. BOOL SoundRec_OnDrawItem (
  1139. HWND hwnd,
  1140. const DRAWITEMSTRUCT *lpdis )
  1141. {
  1142. int i;
  1143. i = lpdis->CtlID - ID_BTN_BASE;
  1144. if (lpdis->CtlType == ODT_BUTTON ) {
  1145. /*
  1146. ** Now draw the button according to the buttons state information.
  1147. */
  1148. tbPlaybar[i].fsState = LOBYTE(lpdis->itemState);
  1149. if (lpdis->itemAction & (ODA_DRAWENTIRE | ODA_SELECT)) {
  1150. BtnDrawButton( hwnd, lpdis->hDC, (int)lpdis->rcItem.right,
  1151. (int)lpdis->rcItem.bottom,
  1152. &tbPlaybar[i] );
  1153. return(TRUE);
  1154. }
  1155. else if (lpdis->itemAction & ODA_FOCUS) {
  1156. BtnDrawFocusRect(lpdis->hDC, &lpdis->rcItem, lpdis->itemState);
  1157. return(TRUE);
  1158. }
  1159. }
  1160. return(FALSE);
  1161. }
  1162. /*
  1163. * void SoundRec_ControlPanel
  1164. *
  1165. * Launch "Audio" control panel/property sheet upon request.
  1166. *
  1167. * */
  1168. void SoundRec_ControlPanel(
  1169. HINSTANCE hInst,
  1170. HWND hParent)
  1171. {
  1172. const TCHAR gszOpen[] = TEXT("open");
  1173. const TCHAR gszRunDLL[] = TEXT("RUNDLL32.EXE");
  1174. const TCHAR gszMMSYSCPL[] = TEXT("MMSYS.CPL,ShowAudioPropertySheet");
  1175. ShellExecute (NULL, gszOpen, gszRunDLL, gszMMSYSCPL, NULL, SW_SHOWNORMAL);
  1176. }
  1177. /* ResolveLink
  1178. *
  1179. * This routine is called when the user drags and drops a shortcut
  1180. * onto Media Player. If it succeeds, it returns the full path
  1181. * of the actual file in szResolved.
  1182. */
  1183. BOOL ResolveLink(LPTSTR szPath, LPTSTR szResolved, LONG cbSize)
  1184. {
  1185. IShellLink *psl = NULL;
  1186. HRESULT hres;
  1187. if (!gfOleInitialized)
  1188. {
  1189. if (!InitializeOle(ghInst))
  1190. return FALSE;
  1191. }
  1192. hres = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC,
  1193. &IID_IShellLink, &psl);
  1194. if (SUCCEEDED(hres) && (psl != NULL))
  1195. {
  1196. IPersistFile *ppf;
  1197. psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf);
  1198. if (ppf)
  1199. {
  1200. WCHAR wszPath[MAX_PATH];
  1201. #ifdef UNICODE
  1202. lstrcpy (wszPath, szPath);
  1203. #else
  1204. AnsiToUnicodeString(szPath, wszPath, UNKNOWN_LENGTH);
  1205. #endif
  1206. hres = ppf->lpVtbl->Load(ppf, wszPath, 0);
  1207. ppf->lpVtbl->Release(ppf);
  1208. if (FAILED(hres))
  1209. {
  1210. psl->lpVtbl->Release(psl);
  1211. psl = NULL;
  1212. }
  1213. }
  1214. else
  1215. {
  1216. psl->lpVtbl->Release(psl);
  1217. psl = NULL;
  1218. }
  1219. }
  1220. if (psl)
  1221. {
  1222. psl->lpVtbl->Resolve(psl, NULL, SLR_NO_UI);
  1223. psl->lpVtbl->GetPath(psl, szResolved, cbSize, NULL, 0);
  1224. psl->lpVtbl->Release(psl);
  1225. }
  1226. return SUCCEEDED(hres);
  1227. }
  1228. /* ResolveIfLink
  1229. *
  1230. * Called to check whether a given file name is a shortcut
  1231. * on Windows 95.
  1232. *
  1233. * Copies the resolved file name into the buffer provided,
  1234. * overwriting the original name.
  1235. *
  1236. * Returns TRUE if the function succeeded, whether or not the
  1237. * file name was changed. FALSE indicates that an error occurred.
  1238. *
  1239. * Andrew Bell, 16 February 1995
  1240. */
  1241. BOOL ResolveIfLink(PTCHAR szFileName)
  1242. {
  1243. SHFILEINFO sfi;
  1244. BOOL rc = TRUE;
  1245. if ((SHGetFileInfo(szFileName, 0, &sfi, sizeof sfi, SHGFI_ATTRIBUTES) == 1)
  1246. && ((sfi.dwAttributes & SFGAO_LINK) == SFGAO_LINK))
  1247. {
  1248. TCHAR szResolvedLink[MAX_PATH];
  1249. if (ResolveLink(szFileName, szResolvedLink, SIZEOF(szResolvedLink)))
  1250. lstrcpy(szFileName, szResolvedLink);
  1251. else
  1252. rc = FALSE;
  1253. }
  1254. return rc;
  1255. }
  1256. #if DBG
  1257. void FAR cdecl dprintfA(LPSTR szFormat, ...)
  1258. {
  1259. char ach[128];
  1260. int s,d;
  1261. va_list va;
  1262. va_start(va, szFormat);
  1263. s = vsprintf (ach,szFormat, va);
  1264. va_end(va);
  1265. for (d=sizeof(ach)-1; s>=0; s--)
  1266. {
  1267. if ((ach[d--] = ach[s]) == '\n')
  1268. ach[d--] = '\r';
  1269. }
  1270. OutputDebugStringA("SNDREC32: ");
  1271. OutputDebugStringA(ach+d+1);
  1272. }
  1273. #ifdef UNICODE
  1274. void FAR cdecl dprintfW(LPWSTR szFormat, ...)
  1275. {
  1276. WCHAR ach[128];
  1277. int s,d;
  1278. va_list va;
  1279. va_start(va, szFormat);
  1280. s = vswprintf (ach,szFormat, va);
  1281. va_end(va);
  1282. for (d=(sizeof(ach)/sizeof(WCHAR))-1; s>=0; s--)
  1283. {
  1284. if ((ach[d--] = ach[s]) == TEXT('\n'))
  1285. ach[d--] = TEXT('\r');
  1286. }
  1287. OutputDebugStringW(TEXT("SNDREC32: "));
  1288. OutputDebugStringW(ach+d+1);
  1289. }
  1290. #endif
  1291. #endif