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.

1756 lines
62 KiB

  1. /*****************************************************************************
  2. midi.c
  3. Level 1 kitchen sink DLL midi support module
  4. Copyright (c) Microsoft Corporation 1990. All rights reserved
  5. *****************************************************************************/
  6. #include <windows.h>
  7. #include "mmsystem.h"
  8. #include "mmddk.h"
  9. #include "mmsysi.h"
  10. #include "thunks.h"
  11. /* -------------------------------------------------------------------------
  12. ** Local functions
  13. ** -------------------------------------------------------------------------
  14. */
  15. static UINT NEAR PASCAL
  16. midiGetErrorText(
  17. UINT wError,
  18. LPSTR lpText,
  19. UINT wSize
  20. );
  21. /* -------------------------------------------------------------------------
  22. ** Local structures
  23. ** -------------------------------------------------------------------------
  24. */
  25. typedef struct mididev_tag {
  26. PMIDIDRV mididrv;
  27. UINT wDevice;
  28. DWORD dwDrvUser;
  29. UINT wDeviceID;
  30. } MIDIDEV;
  31. typedef MIDIDEV *PMIDIDEV;
  32. /* -------------------------------------------------------------------------
  33. ** Segmentation
  34. **
  35. ** Define the fixed code for this file.
  36. ** -------------------------------------------------------------------------
  37. */
  38. #pragma alloc_text( FIX, midiIMessage)
  39. #pragma alloc_text( FIX, midiOMessage)
  40. #pragma alloc_text( FIX, midiOutMessage)
  41. #pragma alloc_text( FIX, midiOutShortMsg)
  42. #pragma alloc_text( FIX, midiOutLongMsg)
  43. #pragma alloc_text( FIX, midiOutReset)
  44. /* -------------------------------------------------------------------------
  45. ** Global data
  46. ** -------------------------------------------------------------------------
  47. */
  48. static int iMidiLockCount = 0;
  49. /*****************************************************************************
  50. * @doc INTERNAL MIDI
  51. *
  52. * @api void | midiLockData |
  53. *
  54. * This function is called every time a new MIDI handle is created, it
  55. * makes sure MMSYSTEM's data segment is page-locked. MIDI handles
  56. * are useable at interupt time so we must page-lock the data seg.
  57. *
  58. * in the future we should re-do the MIDI system.
  59. *
  60. ****************************************************************************/
  61. BOOL NEAR PASCAL
  62. midiLockData(
  63. void
  64. )
  65. {
  66. if (iMidiLockCount == 0) {
  67. DOUT("MMSYSTEM: Locking data segment\r\n");
  68. if ( !GlobalPageLock((HGLOBAL)HIWORD((DWORD)(LPVOID)&iMidiLockCount))
  69. && (WinFlags & WF_ENHANCED)) {
  70. return 0;
  71. }
  72. }
  73. return ++iMidiLockCount;
  74. }
  75. /*****************************************************************************
  76. * @doc INTERNAL MIDI
  77. *
  78. * @api void | midiUnlockData |
  79. *
  80. * This function is called every time a MIDI handle is closed, it
  81. * makes sure MMSYSTEM's data segment is un-page-locked. MIDI handles
  82. * are useable at interupt time so we must page-lock the data seg.
  83. *
  84. * in the future we should re-do the MIDI system.
  85. *
  86. ****************************************************************************/
  87. void NEAR PASCAL
  88. midiUnlockData(
  89. void
  90. )
  91. {
  92. #ifdef DEBUG
  93. if (iMidiLockCount == 0)
  94. DOUT("MMSYSTEM: midiUnlockData() underflow!!!!\r\n");
  95. #endif
  96. if (--iMidiLockCount == 0) {
  97. DOUT("MMSYSTEM: Unlocking data segment\r\n");
  98. GlobalPageUnlock((HGLOBAL)HIWORD((DWORD)(LPVOID)&iMidiLockCount));
  99. }
  100. }
  101. /*****************************************************************************
  102. * @doc INTERNAL MIDI
  103. *
  104. * @api UINT | midiPrepareHeader | This function prepares the header and data
  105. * if the driver returns MMSYSERR_NOTSUPPORTED.
  106. *
  107. * @rdesc Currently always returns MMSYSERR_NOERROR.
  108. ****************************************************************************/
  109. static UINT NEAR PASCAL
  110. midiPrepareHeader(
  111. LPMIDIHDR lpMidiHdr,
  112. UINT wSize
  113. )
  114. {
  115. if (!HugePageLock(lpMidiHdr, (DWORD)sizeof(MIDIHDR)))
  116. return MMSYSERR_NOMEM;
  117. if (!HugePageLock(lpMidiHdr->lpData, lpMidiHdr->dwBufferLength)) {
  118. HugePageUnlock(lpMidiHdr, (DWORD)sizeof(MIDIHDR));
  119. return MMSYSERR_NOMEM;
  120. }
  121. // lpMidiHdr->dwFlags |= MHDR_PREPARED;
  122. return MMSYSERR_NOERROR;
  123. }
  124. /*****************************************************************************
  125. * @doc INTERNAL MIDI
  126. *
  127. * @api UINT | midiUnprepareHeader | This function unprepares the header and
  128. * data if the driver returns MMSYSERR_NOTSUPPORTED.
  129. *
  130. * @rdesc Currently always returns MMSYSERR_NOERROR.
  131. ****************************************************************************/
  132. static UINT NEAR PASCAL
  133. midiUnprepareHeader(
  134. LPMIDIHDR lpMidiHdr,
  135. UINT wSize
  136. )
  137. {
  138. HugePageUnlock(lpMidiHdr->lpData, lpMidiHdr->dwBufferLength);
  139. HugePageUnlock(lpMidiHdr, (DWORD)sizeof(MIDIHDR));
  140. // lpMidiHdr->dwFlags &= ~MHDR_PREPARED;
  141. return MMSYSERR_NOERROR;
  142. }
  143. /*****************************************************************************
  144. * @doc EXTERNAL MIDI
  145. *
  146. * @api UINT | midiOutGetNumDevs | This function retrieves the number of MIDI
  147. * output devices present in the system.
  148. *
  149. * @rdesc Returns the number of MIDI output devices present in the system.
  150. *
  151. * @xref midiOutGetDevCaps
  152. ****************************************************************************/
  153. UINT WINAPI midiOutGetNumDevs(void)
  154. {
  155. return midiOIDMessage( 0, MODM_GETNUMDEVS, 0L, 0L, 0L );
  156. }
  157. /****************************************************************************
  158. * @doc EXTERNAL MIDI
  159. *
  160. * @api DWORD | midiOutMessage | This function sends messages to the MIDI device
  161. * drivers.
  162. *
  163. * @parm HMIDIOUT | hMidiOut | The handle to the MIDI device.
  164. *
  165. * @parm UINT | msg | The message to send.
  166. *
  167. * @parm DWORD | dw1 | Parameter 1.
  168. *
  169. * @parm DWORD | dw2 | Parameter 2.
  170. *
  171. * @rdesc Returns the value of the message sent.
  172. ***************************************************************************/
  173. DWORD WINAPI midiOutMessage(HMIDIOUT hMidiOut, UINT msg, DWORD dw1, DWORD dw2)
  174. {
  175. V_HANDLE(hMidiOut, TYPE_MIDIOUT, 0L);
  176. return midiOMessage( (HMIDI)hMidiOut, msg, dw1, dw2);
  177. }
  178. /*****************************************************************************
  179. * @doc EXTERNAL MIDI
  180. *
  181. * @api UINT | midiOutGetDevCaps | This function queries a specified
  182. * MIDI output device to determine its capabilities.
  183. *
  184. * @parm UINT | wDeviceID | Identifies the MIDI output device.
  185. *
  186. * @parm LPMIDIOUTCAPS | lpCaps | Specifies a far pointer to a <t MIDIOUTCAPS>
  187. * structure. This structure is filled with information about the
  188. * capabilities of the device.
  189. *
  190. * @parm UINT | wSize | Specifies the size of the <t MIDIOUTCAPS> structure.
  191. *
  192. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  193. * an error number. Possible error returns are:
  194. * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range.
  195. * @flag MMSYSERR_NODRIVER | The driver was not installed.
  196. * @flag MMSYSERR_NOMEM | Unable load mapper string description.
  197. *
  198. * @comm Use <f midiOutGetNumDevs> to determine the number of MIDI output
  199. * devices present in the system. The device ID specified by <p wDeviceID>
  200. * varies from zero to one less than the number of devices present.
  201. * The MIDI_MAPPER constant may also be used as a device id. Only
  202. * <p wSize> bytes (or less) of information is copied to the location
  203. * pointed to by <p lpCaps>. If <p wSize> is zero, nothing is copied,
  204. * and the function returns zero.
  205. *
  206. * @xref midiOutGetNumDevs
  207. ****************************************************************************/
  208. UINT WINAPI
  209. midiOutGetDevCaps(
  210. UINT wDeviceID,
  211. LPMIDIOUTCAPS lpCaps,
  212. UINT wSize
  213. )
  214. {
  215. if (wSize == 0) {
  216. return MMSYSERR_NOERROR;
  217. }
  218. V_WPOINTER(lpCaps, wSize, MMSYSERR_INVALPARAM);
  219. if (ValidateHandle((HMIDIOUT)wDeviceID, TYPE_MIDIOUT)) {
  220. return((UINT)midiOMessage((HMIDI)wDeviceID,
  221. MODM_GETDEVCAPS,
  222. (DWORD)lpCaps,
  223. (DWORD)wSize));
  224. }
  225. return midiOIDMessage( wDeviceID,
  226. MODM_GETDEVCAPS, 0L, (DWORD)lpCaps, (DWORD)wSize);
  227. }
  228. /*****************************************************************************
  229. * @doc EXTERNAL MIDI
  230. *
  231. * @api UINT | midiOutGetVolume | This function returns the current volume
  232. * setting of a MIDI output device.
  233. *
  234. * @parm UINT | wDeviceID | Identifies the MIDI output device.
  235. *
  236. * @parm LPDWORD | lpdwVolume | Specifies a far pointer to a location
  237. * to be filled with the current volume setting. The low-order word of
  238. * this location contains the left channel volume setting, and the high-order
  239. * WORD contains the right channel setting. A value of 0xFFFF represents
  240. * full volume, and a value of 0x0000 is silence.
  241. *
  242. * If a device does not support both left and right volume
  243. * control, the low-order word of the specified location contains
  244. * the mono volume level.
  245. *
  246. * The full 16-bit setting(s)
  247. * set with <f midiOutSetVolume> is returned, regardless of whether
  248. * the device supports the full 16 bits of volume level control.
  249. *
  250. *
  251. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  252. * an error number. Possible error returns are:
  253. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  254. * @flag MMSYSERR_NOTSUPPORTED | Function isn't supported.
  255. * @flag MMSYSERR_NODRIVER | The driver was not installed.
  256. *
  257. * @comm Not all devices support volume control. To determine whether the
  258. * device supports volume control, use the MIDICAPS_VOLUME
  259. * flag to test the <e MIDIOUTCAPS.dwSupport> field of the <t MIDIOUTCAPS>
  260. * structure (filled by <f midiOutGetDevCaps>).
  261. *
  262. * To determine whether the device supports volume control on both the
  263. * left and right channels, use the MIDICAPS_LRVOLUME flag to test
  264. * the <e MIDIOUTCAPS.dwSupport> field of the <t MIDIOUTCAPS>
  265. * structure (filled by <f midiOutGetDevCaps>).
  266. *
  267. * @xref midiOutSetVolume
  268. ****************************************************************************/
  269. UINT WINAPI
  270. midiOutGetVolume(
  271. UINT wDeviceID,
  272. LPDWORD lpdwVolume
  273. )
  274. {
  275. V_WPOINTER(lpdwVolume, sizeof(DWORD), MMSYSERR_INVALPARAM);
  276. if (ValidateHandle((HMIDIOUT)wDeviceID, TYPE_MIDIOUT)) {
  277. return((UINT)midiOMessage((HMIDI)wDeviceID,
  278. MODM_GETVOLUME,
  279. (DWORD)lpdwVolume,
  280. 0));
  281. }
  282. return midiOIDMessage( wDeviceID, MODM_GETVOLUME, 0L, (DWORD)lpdwVolume, 0 );
  283. }
  284. /*****************************************************************************
  285. * @doc EXTERNAL MIDI
  286. *
  287. * @api UINT | midiOutSetVolume | This function sets the volume of a
  288. * MIDI output device.
  289. *
  290. * @parm UINT | wDeviceID | Identifies the MIDI output device.
  291. *
  292. * @parm DWORD | dwVolume | Specifies the new volume setting.
  293. * The low-order word contains the left channel volume setting, and the
  294. * high-order word contains the right channel setting. A value of
  295. * 0xFFFF represents full volume, and a value of 0x0000 is silence.
  296. *
  297. * If a device does not support both left and right volume
  298. * control, the low-order word of <p dwVolume> specifies the volume
  299. * level, and the high-order word is ignored.
  300. *
  301. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  302. * an error number. Possible error returns are:
  303. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  304. * @flag MMSYSERR_NOTSUPPORTED | Function isn't supported.
  305. * @flag MMSYSERR_NODRIVER | The driver was not installed.
  306. *
  307. * @comm Not all devices support volume changes. To determine whether the
  308. * device supports volume control, use the MIDICAPS_VOLUME
  309. * flag to test the <e MIDIOUTCAPS.dwSupport> field of the <t MIDIOUTCAPS>
  310. * structure (filled by <f midiOutGetDevCaps>).
  311. *
  312. * To determine whether the device supports volume control on both the
  313. * left and right channels, use the MIDICAPS_LRVOLUME flag to test
  314. * the <e MIDIOUTCAPS.dwSupport> field of the <t MIDIOUTCAPS>
  315. * structure (filled by <f midiOutGetDevCaps>).
  316. *
  317. * Most devices do not support the full 16 bits of volume level control
  318. * and will use only the high-order bits of the requested volume setting.
  319. * For example, for a device that supports 4 bits of volume control,
  320. * requested volume level values of 0x4000, 0x4fff, and 0x43be will
  321. * all produce the same physical volume setting, 0x4000. The
  322. * <f midiOutGetVolume> function will return the full 16-bit setting set
  323. * with <f midiOutSetVolume>.
  324. *
  325. * Volume settings are interpreted logarithmically. This means the
  326. * perceived increase in volume is the same when increasing the
  327. * volume level from 0x5000 to 0x6000 as it is from 0x4000 to 0x5000.
  328. *
  329. * @xref midiOutGetVolume
  330. ****************************************************************************/
  331. UINT WINAPI
  332. midiOutSetVolume(
  333. UINT wDeviceID,
  334. DWORD dwVolume
  335. )
  336. {
  337. if (ValidateHandle((HMIDIOUT)wDeviceID, TYPE_MIDIOUT)) {
  338. return((UINT)midiOMessage((HMIDI)wDeviceID,
  339. MODM_SETVOLUME,
  340. dwVolume,
  341. 0));
  342. }
  343. return midiOIDMessage( wDeviceID, MODM_SETVOLUME, 0L, dwVolume, 0);
  344. }
  345. /*****************************************************************************
  346. * @doc INTERNAL MIDI
  347. *
  348. * @func UINT | midiGetErrorText | This function retrieves a textual
  349. * description of the error identified by the specified error number.
  350. *
  351. * @parm UINT | wError | Specifies the error number.
  352. *
  353. * @parm LPSTR | lpText | Specifies a far pointer to a buffer which
  354. * is filled with the textual error description.
  355. *
  356. * @parm UINT | wSize | Specifies the length of the buffer pointed to by
  357. * <p lpText>.
  358. *
  359. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  360. * an error number. Possible error returns are:
  361. * @flag MMSYSERR_BADERRNUM | Specified error number is out of range.
  362. *
  363. * @comm If the textual error description is longer than the specified buffer,
  364. * the description is truncated. The returned error string is always
  365. * null-terminated. If <p wSize> is zero, nothing is copied and MMSYSERR_NOERROR
  366. * is returned.
  367. ****************************************************************************/
  368. static UINT NEAR PASCAL
  369. midiGetErrorText(
  370. UINT wError,
  371. LPSTR lpText,
  372. UINT wSize
  373. )
  374. {
  375. lpText[0] = 0;
  376. #if MMSYSERR_BASE
  377. if ( ((wError < MMSYSERR_BASE) || (wError > MMSYSERR_LASTERROR))
  378. && ((wError < MIDIERR_BASE) || (wError > MIDIERR_LASTERROR))) {
  379. return MMSYSERR_BADERRNUM;
  380. }
  381. #else
  382. if ((wError > MMSYSERR_LASTERROR) && ((wError < MIDIERR_BASE)
  383. || (wError > MIDIERR_LASTERROR))) {
  384. return MMSYSERR_BADERRNUM;
  385. }
  386. #endif
  387. if (wSize > 1) {
  388. if (!LoadString(ghInst, wError, lpText, wSize)) {
  389. return MMSYSERR_BADERRNUM;
  390. }
  391. }
  392. return MMSYSERR_NOERROR;
  393. }
  394. /*****************************************************************************
  395. * @doc EXTERNAL MIDI
  396. *
  397. * @api UINT | midiOutGetErrorText | This function retrieves a textual
  398. * description of the error identified by the specified error number.
  399. *
  400. * @parm UINT | wError | Specifies the error number.
  401. *
  402. * @parm LPSTR | lpText | Specifies a far pointer to a buffer to be
  403. * filled with the textual error description.
  404. *
  405. * @parm UINT | wSize | Specifies the length of the buffer pointed to by
  406. * <p lpText>.
  407. *
  408. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  409. * an error number. Possible error returns are:
  410. * @flag MMSYSERR_BADERRNUM | Specified error number is out of range.
  411. *
  412. * @comm If the textual error description is longer than the specified buffer,
  413. * the description is truncated. The returned error string is always
  414. * null-terminated. If <p wSize> is zero, nothing is copied, and the
  415. * function returns MMSYSERR_NOERROR. All error descriptions are
  416. * less than MAXERRORLENGTH characters long.
  417. ****************************************************************************/
  418. UINT WINAPI
  419. midiOutGetErrorText(
  420. UINT wError,
  421. LPSTR lpText,
  422. UINT wSize
  423. )
  424. {
  425. if(wSize == 0) {
  426. return MMSYSERR_NOERROR;
  427. }
  428. V_WPOINTER(lpText, wSize, MMSYSERR_INVALPARAM);
  429. return midiGetErrorText(wError, lpText, wSize);
  430. }
  431. /*****************************************************************************
  432. * @doc EXTERNAL MIDI
  433. *
  434. * @api UINT | midiOutOpen | This function opens a specified MIDI
  435. * output device for playback.
  436. *
  437. * @parm LPHMIDIOUT | lphMidiOut | Specifies a far pointer to an HMIDIOUT
  438. * handle. This location is filled with a handle identifying the opened
  439. * MIDI output device. Use the handle to identify the device when calling
  440. * other MIDI output functions.
  441. *
  442. * @parm UINT | wDeviceID | Identifies the MIDI output device that is
  443. * to be opened.
  444. *
  445. * @parm DWORD | dwCallback | Specifies the address of a fixed callback
  446. * function or
  447. * a handle to a window called during MIDI playback to process
  448. * messages related to the progress of the playback. Specify NULL
  449. * for this parameter if no callback is desired.
  450. *
  451. * @parm DWORD | dwCallbackInstance | Specifies user instance data
  452. * passed to the callback. This parameter is not used with
  453. * window callbacks.
  454. *
  455. * @parm DWORD | dwFlags | Specifies a callback flag for opening the device.
  456. * @flag CALLBACK_WINDOW | If this flag is specified, <p dwCallback> is
  457. * assumed to be a window handle.
  458. * @flag CALLBACK_FUNCTION | If this flag is specified, <p dwCallback> is
  459. * assumed to be a callback procedure address.
  460. *
  461. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  462. * an error number. Possible error returns are as follows:
  463. * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range.
  464. * @flag MMSYSERR_ALLOCATED | Specified resource is already allocated.
  465. * @flag MMSYSERR_NOMEM | Unable to allocate or lock memory.
  466. * @flag MIDIERR_NOMAP | There is no current MIDI map. This occurs only
  467. * when opening the mapper.
  468. * @flag MIDIERR_NODEVICE | A port in the current MIDI map doesn't exist.
  469. * This occurs only when opening the mapper.
  470. *
  471. * @comm Use <f midiOutGetNumDevs> to determine the number of MIDI output
  472. * devices present in the system. The device ID specified by <p wDeviceID>
  473. * varies from zero to one less than the number of devices present.
  474. * You may also specify MIDI_MAPPER as the device ID to open the MIDI mapper.
  475. *
  476. * If a window is chosen to receive callback information, the following
  477. * messages are sent to the window procedure function to indicate the
  478. * progress of MIDI output: <m MM_MOM_OPEN>, <m MM_MOM_CLOSE>,
  479. * <m MM_MOM_DONE>.
  480. *
  481. * If a function is chosen to receive callback information, the following
  482. * messages are sent to the function to indicate the progress of MIDI
  483. * output: <m MOM_OPEN>, <m MOM_CLOSE>, <m MOM_DONE>. The callback function
  484. * must reside in a DLL. You do not have to use <f MakeProcInstance> to
  485. * get a procedure-instance address for the callback function.
  486. *
  487. * @cb void CALLBACK | MidiOutFunc | <f MidiOutFunc> is a placeholder for
  488. * the application-supplied function name. The actual name must be
  489. * exported by including it in an EXPORTS statement in the DLL's
  490. * module-definition file.
  491. *
  492. * @parm HMIDIOUT | hMidiOut | Specifies a handle to the MIDI device
  493. * associated with the callback.
  494. *
  495. * @parm UINT | wMsg | Specifies a MIDI output message.
  496. *
  497. * @parm DWORD | dwInstance | Specifies the instance data
  498. * supplied with <f midiOutOpen>.
  499. *
  500. * @parm DWORD | dwParam1 | Specifies a parameter for the message.
  501. *
  502. * @parm DWORD | dwParam2 | Specifies a parameter for the message.
  503. *
  504. * @comm Because the callback is accessed at interrupt time, it must reside
  505. * in a DLL and its code segment must be specified as FIXED in the
  506. * module-definition file for the DLL. Any data that the callback accesses
  507. * must be in a FIXED data segment as well. The callback may not make any
  508. * system calls except for <f PostMessage>, <f timeGetSystemTime>,
  509. * <f timeGetTime>, <f timeSetEvent>, <f timeKillEvent>,
  510. * <f midiOutShortMsg>, <f midiOutLongMsg>, and <f OutputDebugStr>.
  511. *
  512. * @xref midiOutClose
  513. ****************************************************************************/
  514. UINT WINAPI
  515. midiOutOpen(
  516. LPHMIDIOUT lphMidiOut,
  517. UINT wDeviceID,
  518. DWORD dwCallback,
  519. DWORD dwInstance,
  520. DWORD dwFlags
  521. )
  522. {
  523. MIDIOPENDESC mo;
  524. PMIDIDEV pdev;
  525. UINT wRet;
  526. V_WPOINTER(lphMidiOut, sizeof(HMIDIOUT), MMSYSERR_INVALPARAM);
  527. V_DCALLBACK(dwCallback, HIWORD(dwFlags), MMSYSERR_INVALPARAM);
  528. V_FLAGS(LOWORD(dwFlags), 0, midiOutOpen, MMSYSERR_INVALFLAG);
  529. /*
  530. ** Check for no devices
  531. */
  532. // if (wTotalMidiOutDevs == 0 ) {
  533. // return MMSYSERR_BADDEVICEID;
  534. // }
  535. //
  536. // /*
  537. // ** check for device ID being to large
  538. // */
  539. // if ( wDeviceID != MIDI_MAPPER ) {
  540. // if ( wDeviceID >= wTotalMidiOutDevs ) {
  541. // return MMSYSERR_BADDEVICEID;
  542. // }
  543. // }
  544. *lphMidiOut = NULL;
  545. if (!midiLockData()) {
  546. return MMSYSERR_NOMEM;
  547. }
  548. pdev = (PMIDIDEV)NewHandle(TYPE_MIDIOUT, sizeof(MIDIDEV));
  549. if( pdev == NULL) {
  550. return MMSYSERR_NOMEM;
  551. }
  552. pdev->wDevice = wDeviceID;
  553. pdev->wDeviceID = wDeviceID;
  554. mo.hMidi = (HMIDI)pdev;
  555. mo.dwCallback = dwCallback;
  556. mo.dwInstance = dwInstance;
  557. wRet = midiOIDMessage( wDeviceID, MODM_OPEN,
  558. (DWORD)(LPDWORD)&pdev->dwDrvUser,
  559. (DWORD)(LPMIDIOPENDESC)&mo, dwFlags );
  560. if (wRet) {
  561. FreeHandle((HMIDIOUT)pdev);
  562. midiUnlockData();
  563. } else {
  564. *lphMidiOut = (HMIDIOUT)pdev;
  565. }
  566. return wRet;
  567. }
  568. /*****************************************************************************
  569. * @doc EXTERNAL MIDI
  570. *
  571. * @api UINT | midiOutClose | This function closes the specified MIDI
  572. * output device.
  573. *
  574. * @parm HMIDIOUT | hMidiOut | Specifies a handle to the MIDI output device.
  575. * If the function is successful, the handle is no longer
  576. * valid after this call.
  577. *
  578. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  579. * an error number. Possible error returns are:
  580. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  581. * @flag MIDIERR_STILLPLAYING | There are still buffers in the queue.
  582. *
  583. * @comm If there are output buffers that have been sent with
  584. * <f midiOutLongMsg> and haven't been returned to the application,
  585. * the close operation will fail. Call <f midiOutReset> to mark all
  586. * pending buffers as being done.
  587. *
  588. * @xref midiOutOpen midiOutReset
  589. ****************************************************************************/
  590. UINT WINAPI
  591. midiOutClose(
  592. HMIDIOUT hMidiOut
  593. )
  594. {
  595. UINT wRet;
  596. V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE);
  597. wRet = (UINT)midiOMessage( (HMIDI)hMidiOut, MODM_CLOSE, 0L,0L);
  598. if (!wRet) {
  599. FreeHandle(hMidiOut);
  600. midiUnlockData();
  601. }
  602. return wRet;
  603. }
  604. /*****************************************************************************
  605. * @doc EXTERNAL MIDI
  606. *
  607. * @api UINT | midiOutPrepareHeader | This function prepares a MIDI
  608. * system-exclusive data block for output.
  609. *
  610. * @parm HMIDIOUT | hMidiOut | Specifies a handle to the MIDI output
  611. * device.
  612. *
  613. * @parm LPMIDIHDR | lpMidiOutHdr | Specifies a far pointer to a <t MIDIHDR>
  614. * structure that identifies the data block to be prepared.
  615. *
  616. * @parm UINT | wSize | Specifies the size of the <t MIDIHDR> structure.
  617. *
  618. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  619. * an error number. Possible error returns are:
  620. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  621. * @flag MMSYSERR_NOMEM | Unable to allocate or lock memory.
  622. *
  623. * @comm The <t MIDIHDR> data structure and the data block pointed to by its
  624. * <e MIDIHDR.lpData> field must be allocated with <f GlobalAlloc> using the
  625. * GMEM_MOVEABLE and GMEM_SHARE flags and locked with <f GlobalLock>.
  626. * Preparing a header that has already been prepared has no effect, and
  627. * the function returns zero.
  628. *
  629. * @xref midiOutUnprepareHeader
  630. ****************************************************************************/
  631. UINT WINAPI
  632. midiOutPrepareHeader(
  633. HMIDIOUT hMidiOut,
  634. LPMIDIHDR lpMidiOutHdr,
  635. UINT wSize
  636. )
  637. {
  638. UINT wRet;
  639. V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE);
  640. V_HEADER(lpMidiOutHdr, wSize, TYPE_MIDIOUT, MMSYSERR_INVALPARAM);
  641. if (lpMidiOutHdr->dwFlags & MHDR_PREPARED) {
  642. return MMSYSERR_NOERROR;
  643. }
  644. lpMidiOutHdr->dwFlags = 0;
  645. wRet = midiPrepareHeader(lpMidiOutHdr, wSize);
  646. if (wRet == MMSYSERR_NOERROR) {
  647. wRet = (UINT)midiOMessage( (HMIDI)hMidiOut, MODM_PREPARE,
  648. (DWORD)lpMidiOutHdr, (DWORD)wSize );
  649. }
  650. return wRet;
  651. }
  652. /*****************************************************************************
  653. * @doc EXTERNAL MIDI
  654. *
  655. * @api UINT | midiOutUnprepareHeader | This function cleans up the
  656. * preparation performed by <f midiOutPrepareHeader>. The
  657. * <f midiOutUnprepareHeader> function must be called
  658. * after the device driver fills a data buffer and returns it to the
  659. * application. You must call this function before freeing the data
  660. * buffer.
  661. *
  662. * @parm HMIDIOUT | hMidiOut | Specifies a handle to the MIDI output
  663. * device.
  664. *
  665. * @parm LPMIDIHDR | lpMidiOutHdr | Specifies a pointer to a <t MIDIHDR>
  666. * structure identifying the buffer to be cleaned up.
  667. *
  668. * @parm UINT | wSize | Specifies the size of the <t MIDIHDR> structure.
  669. *
  670. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  671. * an error number. Possible error returns are:
  672. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  673. * @flag MIDIERR_STILLPLAYING | <p lpMidiOutHdr> is still in the queue.
  674. *
  675. * @comm This function is the complementary function to
  676. * <f midiOutPrepareHeader>.
  677. * You must call this function before freeing the data buffer with
  678. * <f GlobalFree>.
  679. * After passing a buffer to the device driver with <f midiOutLongMsg>, you
  680. * must wait until the driver is finished with the buffer before calling
  681. * <f midiOutUnprepareHeader>.
  682. *
  683. * Unpreparing a buffer that has not been
  684. * prepared has no effect, and the function returns zero.
  685. *
  686. * @xref midiOutPrepareHeader
  687. ****************************************************************************/
  688. UINT WINAPI
  689. midiOutUnprepareHeader(
  690. HMIDIOUT hMidiOut,
  691. LPMIDIHDR lpMidiOutHdr,
  692. UINT wSize
  693. )
  694. {
  695. UINT wRet;
  696. V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE);
  697. V_HEADER(lpMidiOutHdr, wSize, TYPE_MIDIOUT, MMSYSERR_INVALPARAM);
  698. if (!(lpMidiOutHdr->dwFlags & MHDR_PREPARED)) {
  699. return MMSYSERR_NOERROR;
  700. }
  701. if(lpMidiOutHdr->dwFlags & MHDR_INQUEUE) {
  702. DebugErr( DBF_WARNING,
  703. "midiOutUnprepareHeader: header still in queue\r\n");
  704. return MIDIERR_STILLPLAYING;
  705. }
  706. wRet = midiUnprepareHeader(lpMidiOutHdr, wSize);
  707. if (wRet == MMSYSERR_NOERROR) {
  708. wRet = (UINT)midiOMessage( (HMIDI)hMidiOut, MODM_UNPREPARE,
  709. (DWORD)lpMidiOutHdr, (DWORD)wSize );
  710. }
  711. return wRet;
  712. }
  713. /*****************************************************************************
  714. * @doc EXTERNAL MIDI
  715. *
  716. * @api UINT | midiOutShortMsg | This function sends a short MIDI message to
  717. * the specified MIDI output device. Use this function to send any MIDI
  718. * message except for system-exclusive messages.
  719. *
  720. * @parm HMIDIOUT | hMidiOut | Specifies a handle to the MIDI output
  721. * device.
  722. *
  723. * @parm DWORD | dwMsg | Specifies the MIDI message. The message is packed
  724. * into a DWORD with the first byte of the message in the low-order byte.
  725. *
  726. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  727. * an error number. Possible error returns are:
  728. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  729. * @flag MIDIERR_NOTREADY | The hardware is busy with other data.
  730. *
  731. * @comm This function may not return until the message has been sent to the
  732. * output device.
  733. *
  734. * @xref midiOutLongMsg
  735. ****************************************************************************/
  736. UINT WINAPI
  737. midiOutShortMsg(
  738. HMIDIOUT hMidiOut,
  739. DWORD dwMsg
  740. )
  741. {
  742. V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE);
  743. return (UINT)midiOMessage( (HMIDI)hMidiOut, MODM_DATA, dwMsg, 0L );
  744. }
  745. /*****************************************************************************
  746. * @doc EXTERNAL MIDI
  747. *
  748. * @api UINT | midiOutLongMsg | This function sends a system-exclusive
  749. * MIDI message to the specified MIDI output device.
  750. *
  751. * @parm HMIDIOUT | hMidiOut | Specifies a handle to the MIDI output
  752. * device.
  753. *
  754. * @parm LPMIDIHDR | lpMidiOutHdr | Specifies a far pointer to a <t MIDIHDR>
  755. * structure that identifies the MIDI data buffer.
  756. *
  757. * @parm UINT | wSize | Specifies the size of the <t MIDIHDR> structure.
  758. *
  759. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  760. * an error number. Possible error returns are:
  761. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  762. * @flag MIDIERR_UNPREPARED | <p lpMidiOutHdr> hasn't been prepared.
  763. * @flag MIDIERR_NOTREADY | The hardware is busy with other data.
  764. *
  765. * @comm The data buffer must be prepared with <f midiOutPrepareHeader>
  766. * before it is passed to <f midiOutLongMsg>. The <t MIDIHDR> data
  767. * structure and the data buffer pointed to by its <e MIDIHDR.lpData>
  768. * field must be allocated with <f GlobalAlloc> using the GMEM_MOVEABLE
  769. * and GMEM_SHARE flags, and locked with <f GlobalLock>. The MIDI output
  770. * device driver determines whether the data is sent synchronously or
  771. * asynchronously.
  772. *
  773. * @xref midiOutShortMsg midiOutPrepareHeader
  774. ****************************************************************************/
  775. UINT WINAPI
  776. midiOutLongMsg(
  777. HMIDIOUT hMidiOut,
  778. LPMIDIHDR lpMidiOutHdr,
  779. UINT wSize
  780. )
  781. {
  782. V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE);
  783. //
  784. // we can't call these at interupt time.
  785. //
  786. #pragma message("header not validated for midiOutLongMessage")
  787. ////V_HEADER(lpMidiOutHdr, wSize, TYPE_MIDIOUT, MMSYSERR_INVALPARAM);
  788. if ( HIWORD(lpMidiOutHdr) == 0 ) {
  789. return MMSYSERR_INVALPARAM;
  790. }
  791. if ( wSize != sizeof(MIDIHDR) ) {
  792. return MMSYSERR_INVALPARAM;
  793. }
  794. if (LOWORD(lpMidiOutHdr->dwFlags) & ~MHDR_VALID) {
  795. return MMSYSERR_INVALFLAG;
  796. }
  797. if (!(lpMidiOutHdr->dwFlags & MHDR_PREPARED)) {
  798. return MIDIERR_UNPREPARED;
  799. }
  800. if (lpMidiOutHdr->dwFlags & MHDR_INQUEUE) {
  801. return MIDIERR_STILLPLAYING;
  802. }
  803. return (UINT)midiOMessage( (HMIDI)hMidiOut, MODM_LONGDATA,
  804. (DWORD)lpMidiOutHdr, (DWORD)wSize);
  805. }
  806. /*****************************************************************************
  807. * @doc EXTERNAL MIDI
  808. *
  809. * @api UINT | midiOutReset | This function turns off all notes on all MIDI
  810. * channels for the specified MIDI output device. Any pending
  811. * system-exclusive output buffers are marked as done and
  812. * returned to the application.
  813. *
  814. * @parm HMIDIOUT | hMidiOut | Specifies a handle to the MIDI output
  815. * device.
  816. *
  817. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  818. * an error number. Possible error returns are:
  819. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  820. *
  821. * @comm To turn off all notes, a note-off message for each note for each
  822. * channel is sent. In addition, the sustain controller is turned off for
  823. * each channel.
  824. *
  825. * @xref midiOutLongMsg midiOutClose
  826. ****************************************************************************/
  827. UINT WINAPI
  828. midiOutReset(
  829. HMIDIOUT hMidiOut
  830. )
  831. {
  832. V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE);
  833. return (UINT)midiOMessage( (HMIDI)hMidiOut, MODM_RESET, 0L, 0L );
  834. }
  835. /*****************************************************************************
  836. * @doc EXTERNAL MIDI
  837. *
  838. * @api UINT | midiOutCachePatches | This function requests that an internal
  839. * MIDI synthesizer device preload a specified set of patches. Some
  840. * synthesizers are not capable of keeping all patches loaded simultaneously
  841. * and must load data from disk when they receive MIDI program change
  842. * messages. Caching patches ensures specified patches are immediately
  843. * available.
  844. *
  845. * @parm HMIDIOUT | hMidiOut | Specifies a handle to the opened MIDI output
  846. * device. This device must be an internal MIDI synthesizer.
  847. *
  848. * @parm UINT | wBank | Specifies which bank of patches should be used.
  849. * This parameter should be set to zero to cache the default patch bank.
  850. *
  851. * @parm WORD FAR* | lpPatchArray | Specifies a pointer to a <t PATCHARRAY>
  852. * array indicating the patches to be cached or uncached.
  853. *
  854. * @parm UINT | wFlags | Specifies options for the cache operation. Only one
  855. * of the following flags can be specified:
  856. * @flag MIDI_CACHE_ALL | Cache all of the specified patches. If they
  857. * can't all be cached, cache none, clear the <t PATCHARRAY> array,
  858. * and return MMSYSERR_NOMEM.
  859. * @flag MIDI_CACHE_BESTFIT | Cache all of the specified patches.
  860. * If all patches can't be cached, cache as many patches as
  861. * possible, change the <t PATCHARRAY> array to reflect which
  862. * patches were cached, and return MMSYSERR_NOMEM.
  863. * @flag MIDI_CACHE_QUERY | Change the <t PATCHARRAY> array to indicate
  864. * which patches are currently cached.
  865. * @flag MIDI_UNCACHE | Uncache the specified patches and clear the
  866. * <t PATCHARRAY> array.
  867. *
  868. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  869. * one of the following error codes:
  870. * @flag MMSYSERR_INVALHANDLE | The specified device handle is invalid.
  871. * @flag MMSYSERR_NOTSUPPORTED | The specified device does not support
  872. * patch caching.
  873. * @flag MMSYSERR_NOMEM | The device does not have enough memory to cache
  874. * all of the requested patches.
  875. *
  876. * @comm The <t PATCHARRAY> data type is defined as:
  877. *
  878. * typedef WORD PATCHARRAY[MIDIPATCHSIZE];
  879. *
  880. * Each element of the array represents one of the 128 patches and
  881. * has bits set for
  882. * each of the 16 MIDI channels that use that particular patch. The
  883. * least-significant bit represents physical channel 0; the
  884. * most-significant bit represents physical channel 15 (0x0F). For
  885. * example, if patch 0 is used by physical channels 0 and 8, element 0
  886. * would be set to 0x0101.
  887. *
  888. * This function only applies to internal MIDI synthesizer devices.
  889. * Not all internal synthesizers support patch caching. Use the
  890. * MIDICAPS_CACHE flag to test the <e MIDIOUTCAPS.dwSupport> field of the
  891. * <t MIDIOUTCAPS> structure filled by <f midiOutGetDevCaps> to see if the
  892. * device supports patch caching.
  893. *
  894. * @xref midiOutCacheDrumPatches
  895. ****************************************************************************/
  896. UINT WINAPI
  897. midiOutCachePatches(
  898. HMIDIOUT hMidiOut,
  899. UINT wBank,
  900. WORD FAR* lpPatchArray,
  901. UINT wFlags
  902. )
  903. {
  904. V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE);
  905. V_WPOINTER(lpPatchArray, sizeof(PATCHARRAY), MMSYSERR_INVALPARAM);
  906. V_FLAGS(wFlags, MIDI_CACHE_VALID, midiOutCachePatches, MMSYSERR_INVALFLAG);
  907. return (UINT)midiOMessage( (HMIDI)hMidiOut,
  908. MODM_CACHEPATCHES, (DWORD)lpPatchArray,
  909. MAKELONG(wFlags, wBank) );
  910. }
  911. /*****************************************************************************
  912. * @doc EXTERNAL MIDI
  913. *
  914. * @api UINT | midiOutCacheDrumPatches | This function requests that an
  915. * internal MIDI synthesizer device preload a specified set of key-based
  916. * percussion patches. Some synthesizers are not capable of keeping all
  917. * percussion patches loaded simultaneously. Caching patches ensures
  918. * specified patches are available.
  919. *
  920. * @parm HMIDIOUT | hMidiOut | Specifies a handle to the opened MIDI output
  921. * device. This device should be an internal MIDI synthesizer.
  922. *
  923. * @parm UINT | wPatch | Specifies which drum patch number should be used.
  924. * This parameter should be set to zero to cache the default drum patch.
  925. *
  926. * @parm WORD FAR* | lpKeyArray | Specifies a pointer to a <t KEYARRAY>
  927. * array indicating the key numbers of the specified percussion patches
  928. * to be cached or uncached.
  929. *
  930. * @parm UINT | wFlags | Specifies options for the cache operation. Only one
  931. * of the following flags can be specified:
  932. * @flag MIDI_CACHE_ALL | Cache all of the specified patches. If they
  933. * can't all be cached, cache none, clear the <t KEYARRAY> array,
  934. * and return MMSYSERR_NOMEM.
  935. * @flag MIDI_CACHE_BESTFIT | Cache all of the specified patches.
  936. * If all patches can't be cached, cache as many patches as
  937. * possible, change the <t KEYARRAY> array to reflect which
  938. * patches were cached, and return MMSYSERR_NOMEM.
  939. * @flag MIDI_CACHE_QUERY | Change the <t KEYARRAY> array to indicate
  940. * which patches are currently cached.
  941. * @flag MIDI_UNCACHE | Uncache the specified patches and clear the
  942. * <t KEYARRAY> array.
  943. *
  944. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  945. * one of the following error codes:
  946. * @flag MMSYSERR_INVALHANDLE | The specified device handle is invalid.
  947. * @flag MMSYSERR_NOTSUPPORTED | The specified device does not support
  948. * patch caching.
  949. * @flag MMSYSERR_NOMEM | The device does not have enough memory to cache
  950. * all of the requested patches.
  951. *
  952. * @comm The <t KEYARRAY> data type is defined as:
  953. *
  954. * typedef WORD KEYARRAY[MIDIPATCHSIZE];
  955. *
  956. * Each element of the array represents one of the 128 key-based percussion
  957. * patches and has bits set for
  958. * each of the 16 MIDI channels that use that particular patch. The
  959. * least-significant bit represents physical channel 0; the
  960. * most-significant bit represents physical channel 15. For
  961. * example, if the patch on key number 60 is used by physical channels 9
  962. * and 15, element 60 would be set to 0x8200.
  963. *
  964. * This function applies only to internal MIDI synthesizer devices.
  965. * Not all internal synthesizers support patch caching. Use the
  966. * MIDICAPS_CACHE flag to test the <e MIDIOUTCAPS.dwSupport> field of the
  967. * <t MIDIOUTCAPS> structure filled by <f midiOutGetDevCaps> to see if the
  968. * device supports patch caching.
  969. *
  970. * @xref midiOutCachePatches
  971. ****************************************************************************/
  972. UINT WINAPI
  973. midiOutCacheDrumPatches(
  974. HMIDIOUT hMidiOut,
  975. UINT wPatch,
  976. WORD FAR* lpKeyArray,
  977. UINT wFlags
  978. )
  979. {
  980. V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE);
  981. V_WPOINTER(lpKeyArray, sizeof(KEYARRAY), MMSYSERR_INVALPARAM);
  982. V_FLAGS(wFlags, MIDI_CACHE_VALID, midiOutCacheDrumPatches, MMSYSERR_INVALFLAG);
  983. return (UINT)midiOMessage( (HMIDI)hMidiOut,
  984. MODM_CACHEDRUMPATCHES, (DWORD)lpKeyArray,
  985. MAKELONG(wFlags, wPatch) );
  986. }
  987. /*****************************************************************************
  988. * @doc EXTERNAL MIDI
  989. *
  990. * @api UINT | midiInGetNumDevs | This function retrieves the number of MIDI
  991. * input devices in the system.
  992. *
  993. * @rdesc Returns the number of MIDI input devices present in the system.
  994. *
  995. * @xref midiInGetDevCaps
  996. ****************************************************************************/
  997. UINT WINAPI
  998. midiInGetNumDevs(
  999. void
  1000. )
  1001. {
  1002. return midiIIDMessage( 0, MIDM_GETNUMDEVS, 0L, 0L, 0L );
  1003. }
  1004. /****************************************************************************
  1005. * @doc EXTERNAL MIDI
  1006. *
  1007. * @api DWORD | midiInMessage | This function sends messages to the MIDI device
  1008. * drivers.
  1009. *
  1010. * @parm HMIDIIN | hMidiIn | The handle to the MIDI device.
  1011. *
  1012. * @parm UINT | msg | The message to send.
  1013. *
  1014. * @parm DWORD | dw1 | Parameter 1.
  1015. *
  1016. * @parm DWORD | dw2 | Parameter 2.
  1017. *
  1018. * @rdesc Returns the value of the message sent.
  1019. ***************************************************************************/
  1020. DWORD WINAPI
  1021. midiInMessage(
  1022. HMIDIIN hMidiIn,
  1023. UINT msg,
  1024. DWORD dw1,
  1025. DWORD dw2
  1026. )
  1027. {
  1028. V_HANDLE(hMidiIn, TYPE_MIDIIN, 0L);
  1029. return midiIMessage( (HMIDI)hMidiIn, msg, dw1, dw2);
  1030. }
  1031. /*****************************************************************************
  1032. * @doc EXTERNAL MIDI
  1033. *
  1034. * @api UINT | midiInGetDevCaps | This function queries a specified MIDI input
  1035. * device to determine its capabilities.
  1036. *
  1037. * @parm UINT | wDeviceID | Identifies the MIDI input device.
  1038. *
  1039. * @parm LPMIDIINCAPS | lpCaps | Specifies a far pointer to a <t MIDIINCAPS>
  1040. * data structure. This structure is filled with information about
  1041. * the capabilities of the device.
  1042. *
  1043. * @parm UINT | wSize | Specifies the size of the <t MIDIINCAPS> structure.
  1044. *
  1045. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1046. * an error number. Possible error returns are:
  1047. * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range.
  1048. * @flag MMSYSERR_NODRIVER | The driver was not installed.
  1049. *
  1050. * @comm Use <f midiInGetNumDevs> to determine the number of MIDI input
  1051. * devices present in the system. The device ID specified by <p wDeviceID>
  1052. * varies from zero to one less than the number of devices present.
  1053. * The MIDI_MAPPER constant may also be used as a device id. Only
  1054. * <p wSize> bytes (or less) of information is copied to the location
  1055. * pointed to by <p lpCaps>. If <p wSize> is zero, nothing is copied,
  1056. * and the function returns zero.
  1057. *
  1058. * @xref midiInGetNumDevs
  1059. ****************************************************************************/
  1060. UINT WINAPI
  1061. midiInGetDevCaps(
  1062. UINT wDeviceID,
  1063. LPMIDIINCAPS lpCaps,
  1064. UINT wSize
  1065. )
  1066. {
  1067. if (wSize == 0) {
  1068. return MMSYSERR_NOERROR;
  1069. }
  1070. V_WPOINTER(lpCaps, wSize, MMSYSERR_INVALPARAM);
  1071. if (ValidateHandle((HMIDIIN)wDeviceID, TYPE_MIDIIN)) {
  1072. return((UINT)midiIMessage((HMIDIIN)wDeviceID,
  1073. MIDM_GETDEVCAPS,
  1074. (DWORD)lpCaps,
  1075. (DWORD)wSize));
  1076. }
  1077. return midiIIDMessage( wDeviceID,
  1078. MIDM_GETDEVCAPS, 0L, (DWORD)lpCaps, (DWORD)wSize);
  1079. }
  1080. /*****************************************************************************
  1081. * @doc EXTERNAL MIDI
  1082. *
  1083. * @api UINT | midiInGetErrorText | This function retrieves a textual
  1084. * description of the error identified by the specified error number.
  1085. *
  1086. * @parm UINT | wError | Specifies the error number.
  1087. *
  1088. * @parm LPSTR | lpText | Specifies a far pointer to the buffer to be
  1089. * filled with the textual error description.
  1090. *
  1091. * @parm UINT | wSize | Specifies the length of buffer pointed to by
  1092. * <p lpText>.
  1093. *
  1094. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1095. * an error number. Possible error returns are:
  1096. * @flag MMSYSERR_BADERRNUM | Specified error number is out of range.
  1097. *
  1098. * @comm If the textual error description is longer than the specified buffer,
  1099. * the description is truncated. The returned error string is always
  1100. * null-terminated. If <p wSize> is zero, nothing is copied, and
  1101. * the function returns zero. All error descriptions are
  1102. * less than MAXERRORLENGTH characters long.
  1103. ****************************************************************************/
  1104. UINT WINAPI
  1105. midiInGetErrorText(
  1106. UINT wError,
  1107. LPSTR lpText,
  1108. UINT wSize
  1109. )
  1110. {
  1111. if(wSize == 0) {
  1112. return MMSYSERR_NOERROR;
  1113. }
  1114. V_WPOINTER(lpText, wSize, MMSYSERR_INVALPARAM);
  1115. return midiGetErrorText(wError, lpText, wSize);
  1116. }
  1117. /*****************************************************************************
  1118. * @doc EXTERNAL MIDI
  1119. *
  1120. * @api UINT | midiInOpen | This function opens a specified MIDI input device.
  1121. *
  1122. * @parm LPHMIDIIN | lphMidiIn | Specifies a far pointer to an HMIDIIN handle.
  1123. * This location is filled with a handle identifying the opened MIDI
  1124. * input device. Use the handle to identify the device when calling
  1125. * other MIDI input functions.
  1126. *
  1127. * @parm UINT | wDeviceID | Identifies the MIDI input device to be
  1128. * opened.
  1129. *
  1130. * @parm DWORD | dwCallback | Specifies the address of a fixed callback
  1131. * function or a handle to a window called with information
  1132. * about incoming MIDI messages.
  1133. *
  1134. * @parm DWORD | dwCallbackInstance | Specifies user instance data
  1135. * passed to the callback function. This parameter is not
  1136. * used with window callbacks.
  1137. *
  1138. * @parm DWORD | dwFlags | Specifies a callback flag for opening the device.
  1139. * @flag CALLBACK_WINDOW | If this flag is specified, <p dwCallback> is
  1140. * assumed to be a window handle.
  1141. * @flag CALLBACK_FUNCTION | If this flag is specified, <p dwCallback> is
  1142. * assumed to be a callback procedure address.
  1143. *
  1144. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1145. * an error number. Possible error returns are:
  1146. * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range.
  1147. * @flag MMSYSERR_ALLOCATED | Specified resource is already allocated.
  1148. * @flag MMSYSERR_NOMEM | Unable to allocate or lock memory.
  1149. *
  1150. * @comm Use <f midiInGetNumDevs> to determine the number of MIDI input
  1151. * devices present in the system. The device ID specified by <p wDeviceID>
  1152. * varies from zero to one less than the number of devices present.
  1153. * The MIDI_MAPPER constant may also be used as a device id.
  1154. *
  1155. * If a window is chosen to receive callback information, the following
  1156. * messages are sent to the window procedure function to indicate the
  1157. * progress of MIDI input: <m MM_MIM_OPEN>, <m MM_MIM_CLOSE>,
  1158. * <m MM_MIM_DATA>, <m MM_MIM_LONGDATA>, <m MM_MIM_ERROR>,
  1159. * <m MM_MIM_LONGERROR>.
  1160. *
  1161. * If a function is chosen to receive callback information, the following
  1162. * messages are sent to the function to indicate the progress of MIDI
  1163. * input: <m MIM_OPEN>, <m MIM_CLOSE>, <m MIM_DATA>, <m MIM_LONGDATA>,
  1164. * <m MIM_ERROR>, <m MIM_LONGERROR>. The callback function must reside in
  1165. * a DLL. You do not have to use <f MakeProcInstance> to get a
  1166. * procedure-instance address for the callback function.
  1167. *
  1168. * @cb void CALLBACK | MidiInFunc | <f MidiInFunc> is a placeholder for
  1169. * the application-supplied function name. The actual name must be
  1170. * exported by including it in an EXPORTS statement in the DLL's module
  1171. * definition file.
  1172. *
  1173. * @parm HMIDIIN | hMidiIn | Specifies a handle to the MIDI input device.
  1174. *
  1175. * @parm UINT | wMsg | Specifies a MIDI input message.
  1176. *
  1177. * @parm DWORD | dwInstance | Specifies the instance data supplied
  1178. * with <f midiInOpen>.
  1179. *
  1180. * @parm DWORD | dwParam1 | Specifies a parameter for the message.
  1181. *
  1182. * @parm DWORD | dwParam2 | Specifies a parameter for the message.
  1183. *
  1184. * @comm Because the callback is accessed at interrupt time, it must reside
  1185. * in a DLL, and its code segment must be specified as FIXED in the
  1186. * module-definition file for the DLL. Any data that the callback accesses
  1187. * must be in a FIXED data segment as well. The callback may not make any
  1188. * system calls except for <f PostMessage>, <f timeGetSystemTime>,
  1189. * <f timeGetTime>, <f timeSetEvent>, <f timeKillEvent>,
  1190. * <f midiOutShortMsg>, <f midiOutLongMsg>, and <f OutputDebugStr>.
  1191. *
  1192. * @xref midiInClose
  1193. ****************************************************************************/
  1194. UINT WINAPI
  1195. midiInOpen(
  1196. LPHMIDIIN lphMidiIn,
  1197. UINT wDeviceID,
  1198. DWORD dwCallback,
  1199. DWORD dwInstance,
  1200. DWORD dwFlags
  1201. )
  1202. {
  1203. MIDIOPENDESC mo;
  1204. PMIDIDEV pdev;
  1205. UINT wRet;
  1206. V_WPOINTER(lphMidiIn, sizeof(HMIDIIN), MMSYSERR_INVALPARAM);
  1207. V_DCALLBACK(dwCallback, HIWORD(dwFlags), MMSYSERR_INVALPARAM);
  1208. V_FLAGS(LOWORD(dwFlags), 0, midiInOpen, MMSYSERR_INVALFLAG);
  1209. /*
  1210. ** Check for no devices
  1211. */
  1212. // if (wTotalMidiInDevs == 0 ) {
  1213. // return MMSYSERR_BADDEVICEID;
  1214. // }
  1215. //
  1216. // /*
  1217. // ** check for device ID being to large
  1218. // */
  1219. // if ( wDeviceID != MIDI_MAPPER ) {
  1220. // if ( wDeviceID >= wTotalMidiInDevs ) {
  1221. // return MMSYSERR_BADDEVICEID;
  1222. // }
  1223. // }
  1224. *lphMidiIn = NULL;
  1225. if (!midiLockData()) {
  1226. return MMSYSERR_NOMEM;
  1227. }
  1228. pdev = (PMIDIDEV)NewHandle(TYPE_MIDIIN, sizeof(MIDIDEV));
  1229. if( pdev == NULL) {
  1230. return MMSYSERR_NOMEM;
  1231. }
  1232. pdev->wDevice = wDeviceID;
  1233. pdev->wDeviceID = wDeviceID;
  1234. mo.hMidi = (HMIDI)pdev;
  1235. mo.dwCallback = dwCallback;
  1236. mo.dwInstance = dwInstance;
  1237. wRet = midiIIDMessage( wDeviceID, MIDM_OPEN,
  1238. (DWORD)(LPDWORD)&pdev->dwDrvUser,
  1239. (DWORD)(LPMIDIOPENDESC)&mo, dwFlags );
  1240. if (wRet) {
  1241. FreeHandle((HMIDIIN)pdev);
  1242. midiUnlockData();
  1243. } else {
  1244. *lphMidiIn = (HMIDIIN)pdev;
  1245. }
  1246. return wRet;
  1247. }
  1248. /*****************************************************************************
  1249. * @doc EXTERNAL MIDI
  1250. *
  1251. * @api UINT | midiInClose | This function closes the specified MIDI input
  1252. * device.
  1253. *
  1254. * @parm HMIDIIN | hMidiIn | Specifies a handle to the MIDI input device.
  1255. * If the function is successful, the handle is no longer
  1256. * valid after this call.
  1257. *
  1258. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1259. * an error number. Possible error returns are:
  1260. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1261. * @flag MIDIERR_STILLPLAYING | There are still buffers in the queue.
  1262. *
  1263. * @comm If there are input buffers that have been sent with
  1264. * <f midiInAddBuffer> and haven't been returned to the application,
  1265. * the close operation will fail. Call <f midiInReset> to mark all
  1266. * pending buffers as being done.
  1267. *
  1268. * @xref midiInOpen midiInReset
  1269. ****************************************************************************/
  1270. UINT WINAPI
  1271. midiInClose(
  1272. HMIDIIN hMidiIn
  1273. )
  1274. {
  1275. UINT wRet;
  1276. V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE);
  1277. wRet = (UINT)midiIMessage( (HMIDI)hMidiIn, MIDM_CLOSE, 0L, 0L);
  1278. if (!wRet) {
  1279. FreeHandle(hMidiIn);
  1280. midiUnlockData();
  1281. }
  1282. return wRet;
  1283. }
  1284. /*****************************************************************************
  1285. * @doc EXTERNAL MIDI
  1286. *
  1287. * @api UINT | midiInPrepareHeader | This function prepares a buffer for
  1288. * MIDI input.
  1289. *
  1290. * @parm HMIDIIN | hMidiIn | Specifies a handle to the MIDI input
  1291. * device.
  1292. *
  1293. * @parm LPMIDIHDR | lpMidiInHdr | Specifies a pointer to a <t MIDIHDR>
  1294. * structure that identifies the buffer to be prepared.
  1295. *
  1296. * @parm UINT | wSize | Specifies the size of the <t MIDIHDR> structure.
  1297. *
  1298. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1299. * an error number. Possible error returns are:
  1300. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1301. * @flag MMSYSERR_NOMEM | Unable to allocate or lock memory.
  1302. *
  1303. * @comm The <t MIDIHDR> data structure and the data block pointed to by its
  1304. * <e MIDIHDR.lpData> field must be allocated with <f GlobalAlloc> using the
  1305. * GMEM_MOVEABLE and GMEM_SHARE flags, and locked with <f GlobalLock>.
  1306. * Preparing a header that has already been prepared has no effect,
  1307. * and the function returns zero.
  1308. *
  1309. * @xref midiInUnprepareHeader
  1310. ****************************************************************************/
  1311. UINT WINAPI
  1312. midiInPrepareHeader(
  1313. HMIDIIN hMidiIn,
  1314. LPMIDIHDR lpMidiInHdr,
  1315. UINT wSize
  1316. )
  1317. {
  1318. UINT wRet;
  1319. V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE);
  1320. V_HEADER(lpMidiInHdr, wSize, TYPE_MIDIIN, MMSYSERR_INVALPARAM);
  1321. if (lpMidiInHdr->dwFlags & MHDR_PREPARED) {
  1322. return MMSYSERR_NOERROR;
  1323. }
  1324. lpMidiInHdr->dwFlags = 0;
  1325. wRet = midiPrepareHeader(lpMidiInHdr, wSize);
  1326. if (wRet == MMSYSERR_NOERROR) {
  1327. wRet = (UINT)midiIMessage( (HMIDI)hMidiIn, MIDM_PREPARE,
  1328. (DWORD)lpMidiInHdr, (DWORD)wSize);
  1329. }
  1330. return wRet;
  1331. }
  1332. /*****************************************************************************
  1333. * @doc EXTERNAL MIDI
  1334. *
  1335. * @api UINT | midiInUnprepareHeader | This function cleans up the
  1336. * preparation performed by <f midiInPrepareHeader>. The
  1337. * <f midiInUnprepareHeader> function must be called
  1338. * after the device driver fills a data buffer and returns it to the
  1339. * application. You must call this function before freeing the data
  1340. * buffer.
  1341. *
  1342. * @parm HMIDIIN | hMidiIn | Specifies a handle to the MIDI input
  1343. * device.
  1344. *
  1345. * @parm LPMIDIHDR | lpMidiInHdr | Specifies a pointer to a <t MIDIHDR>
  1346. * structure identifying the data buffer to be cleaned up.
  1347. *
  1348. * @parm UINT | wSize | Specifies the size of the <t MIDIHDR> structure.
  1349. *
  1350. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1351. * an error number. Possible error returns are:
  1352. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1353. * @flag MIDIERR_STILLPLAYING | <p lpMidiInHdr> is still in the queue.
  1354. *
  1355. * @comm This function is the complementary function to <f midiInPrepareHeader>.
  1356. * You must call this function before freeing the data buffer with
  1357. * <f GlobalFree>.
  1358. * After passing a buffer to the device driver with <f midiInAddBuffer>, you
  1359. * must wait until the driver is finished with the buffer before calling
  1360. * <f midiInUnprepareHeader>. Unpreparing a buffer that has not been
  1361. * prepared has no effect, and the function returns zero.
  1362. *
  1363. * @xref midiInPrepareHeader
  1364. ****************************************************************************/
  1365. UINT WINAPI
  1366. midiInUnprepareHeader(
  1367. HMIDIIN hMidiIn,
  1368. LPMIDIHDR lpMidiInHdr,
  1369. UINT wSize
  1370. )
  1371. {
  1372. UINT wRet;
  1373. V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE);
  1374. V_HEADER(lpMidiInHdr, wSize, TYPE_MIDIIN, MMSYSERR_INVALPARAM);
  1375. if (!(lpMidiInHdr->dwFlags & MHDR_PREPARED)) {
  1376. return MMSYSERR_NOERROR;
  1377. }
  1378. if(lpMidiInHdr->dwFlags & MHDR_INQUEUE) {
  1379. DebugErr( DBF_WARNING,
  1380. "midiInUnprepareHeader: header still in queue\r\n");
  1381. return MIDIERR_STILLPLAYING;
  1382. }
  1383. wRet = midiUnprepareHeader(lpMidiInHdr, wSize);
  1384. if (wRet == MMSYSERR_NOERROR) {
  1385. wRet = (UINT)midiIMessage( (HMIDI)hMidiIn, MIDM_UNPREPARE,
  1386. (DWORD)lpMidiInHdr, (DWORD)wSize);
  1387. }
  1388. return wRet;
  1389. }
  1390. /******************************************************************************
  1391. * @doc EXTERNAL MIDI
  1392. *
  1393. * @api UINT | midiInAddBuffer | This function sends an input buffer
  1394. * to a specified opened MIDI input device. When the buffer is filled,
  1395. * it is sent back to the application. Input buffers are
  1396. * used only for system-exclusive messages.
  1397. *
  1398. * @parm HMIDIIN | hMidiIn | Specifies a handle to the MIDI input device.
  1399. *
  1400. * @parm LPMIDIHDR | lpMidiInHdr | Specifies a far pointer to a <t MIDIHDR>
  1401. * structure that identifies the buffer.
  1402. *
  1403. * @parm UINT | wSize | Specifies the size of the <t MIDIHDR> structure.
  1404. *
  1405. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1406. * an error number. Possible error returns are:
  1407. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1408. * @flag MIDIERR_UNPREPARED | <p lpMidiInHdr> hasn't been prepared.
  1409. *
  1410. * @comm The data buffer must be prepared with <f midiInPrepareHeader> before
  1411. * it is passed to <f midiInAddBuffer>. The <t MIDIHDR> data structure
  1412. * and the data buffer pointed to by its <e MIDIHDR.lpData> field must be allocated
  1413. * with <f GlobalAlloc> using the GMEM_MOVEABLE and GMEM_SHARE flags, and
  1414. * locked with <f GlobalLock>.
  1415. *
  1416. * @xref midiInPrepareHeader
  1417. *****************************************************************************/
  1418. UINT WINAPI
  1419. midiInAddBuffer(
  1420. HMIDIIN hMidiIn,
  1421. LPMIDIHDR lpMidiInHdr,
  1422. UINT wSize
  1423. )
  1424. {
  1425. V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE);
  1426. V_HEADER(lpMidiInHdr, wSize, TYPE_MIDIIN, MMSYSERR_INVALPARAM);
  1427. if (!(lpMidiInHdr->dwFlags & MHDR_PREPARED)) {
  1428. DebugErr(DBF_WARNING, "midiInAddBuffer: buffer not prepared\r\n");
  1429. return MIDIERR_UNPREPARED;
  1430. }
  1431. if (lpMidiInHdr->dwFlags & MHDR_INQUEUE) {
  1432. DebugErr(DBF_WARNING, "midiInAddBuffer: buffer already in queue\r\n");
  1433. return MIDIERR_STILLPLAYING;
  1434. }
  1435. return (UINT)midiIMessage( (HMIDI)hMidiIn, MIDM_ADDBUFFER,
  1436. (DWORD)lpMidiInHdr, (DWORD)wSize );
  1437. }
  1438. /*****************************************************************************
  1439. * @doc EXTERNAL MIDI
  1440. *
  1441. * @api UINT | midiInStart | This function starts MIDI input on the
  1442. * specified MIDI input device.
  1443. *
  1444. * @parm HMIDIIN | hMidiIn | Specifies a handle to the MIDI input device.
  1445. *
  1446. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1447. * an error number. Possible error returns are:
  1448. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1449. *
  1450. * @comm This function resets the timestamps to zero; timestamp values for
  1451. * subsequently received messages are relative to the time this
  1452. * function was called.
  1453. *
  1454. * All messages other than system-exclusive messages are sent
  1455. * directly to the client when received. System-exclusive
  1456. * messages are placed in the buffers supplied by <f midiInAddBuffer>;
  1457. * if there are no buffers in the queue,
  1458. * the data is thrown away without notification to the client, and input
  1459. * continues.
  1460. *
  1461. * Buffers are returned to the client when full, when a
  1462. * complete system-exclusive message has been received,
  1463. * or when <f midiInReset> is
  1464. * called. The <e MIDIHDR.dwBytesRecorded> field in the header will contain the
  1465. * actual length of data received.
  1466. *
  1467. * Calling this function when input is already started has no effect, and
  1468. * the function returns zero.
  1469. *
  1470. * @xref midiInStop midiInReset
  1471. ****************************************************************************/
  1472. UINT WINAPI
  1473. midiInStart(
  1474. HMIDIIN hMidiIn
  1475. )
  1476. {
  1477. V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE);
  1478. return (UINT)midiIMessage( (HMIDI)hMidiIn, MIDM_START, 0L, 0L);
  1479. }
  1480. /*****************************************************************************
  1481. * @doc EXTERNAL MIDI
  1482. *
  1483. * @api UINT | midiInStop | This function terminates MIDI input on the
  1484. * specified MIDI input device.
  1485. *
  1486. * @parm HMIDIIN | hMidiIn | Specifies a handle to the MIDI input device.
  1487. *
  1488. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1489. * an error number. Possible error returns are:
  1490. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1491. *
  1492. * @comm Current status (running status, parsing state, etc.) is maintained
  1493. * across calls to <f midiInStop> and <f midiInStart>.
  1494. * If there are any system-exclusive message buffers in the queue,
  1495. * the current buffer
  1496. * is marked as done (the <e MIDIHDR.dwBytesRecorded> field in the header will
  1497. * contain the actual length of data), but any empty buffers in the queue
  1498. * remain there. Calling this function when input is not started has no
  1499. * no effect, and the function returns zero.
  1500. *
  1501. * @xref midiInStart midiInReset
  1502. ****************************************************************************/
  1503. UINT WINAPI
  1504. midiInStop(
  1505. HMIDIIN hMidiIn
  1506. )
  1507. {
  1508. V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE);
  1509. return (UINT)midiIMessage( (HMIDI)hMidiIn, MIDM_STOP, 0L, 0L);
  1510. }
  1511. /*****************************************************************************
  1512. * @doc EXTERNAL MIDI
  1513. *
  1514. * @api UINT | midiInReset | This function stops input on a given MIDI
  1515. * input device and marks all pending input buffers as done.
  1516. *
  1517. * @parm HMIDIIN | hMidiIn | Specifies a handle to the MIDI input device.
  1518. *
  1519. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1520. * an error number. Possible error returns are:
  1521. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1522. *
  1523. * @xref midiInStart midiInStop midiInAddBuffer midiInClose
  1524. ****************************************************************************/
  1525. UINT WINAPI
  1526. midiInReset(
  1527. HMIDIIN hMidiIn
  1528. )
  1529. {
  1530. V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE);
  1531. return (UINT)midiIMessage( (HMIDI)hMidiIn, MIDM_RESET, 0L, 0L );
  1532. }
  1533. /*****************************************************************************
  1534. * @doc EXTERNAL MIDI
  1535. *
  1536. * @api UINT | midiInGetID | This function gets the device ID for a
  1537. * MIDI input device.
  1538. *
  1539. * @parm HMIDIIN | hMidiIn | Specifies the handle to the MIDI input
  1540. * device.
  1541. * @parm UINT FAR* | lpwDeviceID | Specifies a pointer to the UINT-sized
  1542. * memory location to be filled with the device ID.
  1543. *
  1544. * @rdesc Returns zero if successful. Otherwise, returns
  1545. * an error number. Possible error returns are:
  1546. *
  1547. * @flag MMSYSERR_INVALHANDLE | The <p hMidiIn> parameter specifies an
  1548. * invalid handle.
  1549. *
  1550. ****************************************************************************/
  1551. UINT WINAPI
  1552. midiInGetID(
  1553. HMIDIIN hMidiIn,
  1554. UINT FAR* lpwDeviceID
  1555. )
  1556. {
  1557. V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE);
  1558. V_WPOINTER(lpwDeviceID, sizeof(UINT), MMSYSERR_INVALPARAM);
  1559. *lpwDeviceID = ((PMIDIDEV)hMidiIn)->wDeviceID;
  1560. return MMSYSERR_NOERROR;
  1561. }
  1562. /*****************************************************************************
  1563. * @doc EXTERNAL MIDI
  1564. *
  1565. * @api UINT | midiOutGetID | This function gets the device ID for a
  1566. * MIDI output device.
  1567. *
  1568. * @parm HMIDIOUT | hMidiOut | Specifies the handle to the MIDI output
  1569. * device.
  1570. * @parm UINT FAR* | lpwDeviceID | Specifies a pointer to the UINT-sized
  1571. * memory location to be filled with the device ID.
  1572. *
  1573. * @rdesc Returns MMSYSERR_NOERROR if successful. Otherwise, returns
  1574. * an error number. Possible error returns are:
  1575. *
  1576. * @flag MMSYSERR_INVALHANDLE | The <p hMidiOut> parameter specifies an
  1577. * invalid handle.
  1578. *
  1579. ****************************************************************************/
  1580. UINT WINAPI
  1581. midiOutGetID(
  1582. HMIDIOUT hMidiOut,
  1583. UINT FAR* lpwDeviceID
  1584. )
  1585. {
  1586. V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE);
  1587. V_WPOINTER(lpwDeviceID, sizeof(UINT), MMSYSERR_INVALPARAM);
  1588. *lpwDeviceID = ((PMIDIDEV)hMidiOut)->wDeviceID;
  1589. return MMSYSERR_NOERROR;
  1590. }
  1591. #if 0
  1592. /*****************************Private*Routine******************************\
  1593. * midiIDMessage
  1594. *
  1595. *
  1596. *
  1597. * History:
  1598. * dd-mm-93 - StephenE - Created
  1599. *
  1600. \**************************************************************************/
  1601. UINT FAR PASCAL
  1602. midiIDMessage(
  1603. LPSOUNDDEVMSGPROC lpProc,
  1604. UINT wDeviceID,
  1605. UINT wMessage,
  1606. DWORD dwUser,
  1607. DWORD dwParam1,
  1608. DWORD dwParam2
  1609. )
  1610. {
  1611. return CallProc32W( (DWORD)wDeviceID, (DWORD)wMessage,
  1612. dwUser, dwParam1, dwParam2, lpProc, 0L, 5L );
  1613. }
  1614. #endif
  1615.