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.

691 lines
20 KiB

  1. /****************************************************************************
  2. *
  3. * midiin.c
  4. *
  5. * WDM Audio support for Midi Input devices
  6. *
  7. * Copyright (C) Microsoft Corporation, 1997 - 1999 All Rights Reserved.
  8. *
  9. * History
  10. * 5-12-97 - Noel Cross (NoelC)
  11. *
  12. ***************************************************************************/
  13. #include "wdmdrv.h"
  14. #include <stdarg.h>
  15. #ifndef UNDER_NT
  16. #pragma alloc_text(FIXCODE, midiCallback)
  17. #pragma alloc_text(FIXCODE, midiInCompleteHeader)
  18. #endif
  19. /****************************************************************************
  20. This function conforms to the standard Midi input driver message proc
  21. (midMessage), which is documented in mmddk.h
  22. ****************************************************************************/
  23. DWORD FAR PASCAL _loadds midMessage
  24. (
  25. UINT id,
  26. UINT msg,
  27. DWORD_PTR dwUser,
  28. DWORD_PTR dwParam1,
  29. DWORD_PTR dwParam2
  30. )
  31. {
  32. LPDEVICEINFO DeviceInfo;
  33. LPDEVICEINFO pInClient;
  34. MMRESULT mmr;
  35. switch (msg)
  36. {
  37. case MIDM_INIT:
  38. DPF(DL_TRACE|FA_MIDI, ("MIDM_INIT") );
  39. return wdmaudAddRemoveDevNode(MidiInDevice, (LPCWSTR)dwParam2, TRUE);
  40. case DRVM_EXIT:
  41. DPF(DL_TRACE|FA_MIDI, ("DRVM_EXIT: MidiIn") );
  42. return wdmaudAddRemoveDevNode(MidiInDevice, (LPCWSTR)dwParam2, FALSE);
  43. case MIDM_GETNUMDEVS:
  44. DPF(DL_TRACE|FA_MIDI, ("MIDM_GETNUMDEVS") );
  45. return wdmaudGetNumDevs(MidiInDevice, (LPCWSTR)dwParam1);
  46. case MIDM_GETDEVCAPS:
  47. DPF(DL_TRACE|FA_MIDI, ("MIDM_GETDEVCAPS") );
  48. if (DeviceInfo = GlobalAllocDeviceInfo((LPWSTR)dwParam2))
  49. {
  50. DeviceInfo->DeviceType = MidiInDevice;
  51. DeviceInfo->DeviceNumber = id;
  52. mmr = wdmaudGetDevCaps(DeviceInfo, (MDEVICECAPSEX FAR*)dwParam1);
  53. GlobalFreeDeviceInfo(DeviceInfo);
  54. return mmr;
  55. } else {
  56. MMRRETURN( MMSYSERR_NOMEM );
  57. }
  58. case MIDM_OPEN:
  59. {
  60. LPMIDIOPENDESC pmod = (LPMIDIOPENDESC)dwParam1;
  61. DPF(DL_TRACE|FA_MIDI, ("MIDM_OPEN") );
  62. if (DeviceInfo = GlobalAllocDeviceInfo((LPWSTR)pmod->dnDevNode))
  63. {
  64. DeviceInfo->DeviceType = MidiInDevice;
  65. DeviceInfo->DeviceNumber = id;
  66. mmr = midiOpen(DeviceInfo, dwUser, pmod, (DWORD)dwParam2);
  67. DPF(DL_TRACE|FA_MIDI,("dwUser(DI)=%08X",dwUser) );
  68. GlobalFreeDeviceInfo(DeviceInfo);
  69. return mmr;
  70. } else {
  71. MMRRETURN( MMSYSERR_NOMEM );
  72. }
  73. }
  74. case MIDM_CLOSE:
  75. DPF(DL_TRACE|FA_MIDI, ("MIDM_CLOSE dwUser(DI)=%08X",dwUser) );
  76. pInClient = (LPDEVICEINFO)dwUser;
  77. if( (mmr=IsValidDeviceInfo(pInClient)) != MMSYSERR_NOERROR )
  78. {
  79. MMRRETURN( mmr );
  80. }
  81. mmr = wdmaudCloseDev( pInClient );
  82. if (MMSYSERR_NOERROR == mmr)
  83. {
  84. #ifdef UNDER_NT
  85. //
  86. // Wait for all of the queued up I/O to come back from
  87. // wdmaud.sys.
  88. //
  89. wdmaudDestroyCompletionThread ( pInClient );
  90. #endif
  91. //
  92. // Tell the caller we're done
  93. //
  94. midiCallback( pInClient, MIM_CLOSE, 0L, 0L);
  95. ISVALIDDEVICEINFO(pInClient);
  96. ISVALIDDEVICESTATE(pInClient->DeviceState,FALSE);
  97. midiCleanUp( pInClient );
  98. }
  99. return mmr;
  100. case MIDM_ADDBUFFER:
  101. DPF(DL_TRACE|FA_MIDI, ("MIDM_ADDBUFFER") );
  102. //
  103. // Don't touch bad pointers!
  104. //
  105. pInClient = (LPDEVICEINFO)dwUser;
  106. if( ( (mmr=IsValidDeviceInfo(pInClient)) != MMSYSERR_NOERROR) ||
  107. ( (mmr=IsValidDeviceState(pInClient->DeviceState,FALSE)) != MMSYSERR_NOERROR ) ||
  108. ( (mmr=IsValidMidiHeader((LPMIDIHDR)dwParam1)) != MMSYSERR_NOERROR)
  109. )
  110. {
  111. MMRRETURN( mmr );
  112. }
  113. // check if it's been prepared
  114. if (!(((LPMIDIHDR)dwParam1)->dwFlags & MHDR_PREPARED))
  115. MMRRETURN( MIDIERR_UNPREPARED );
  116. DPFASSERT(!(((LPMIDIHDR)dwParam1)->dwFlags & MHDR_INQUEUE));
  117. // if it is already in our Q, then we cannot do this
  118. if ( ((LPMIDIHDR)dwParam1)->dwFlags & MHDR_INQUEUE )
  119. MMRRETURN( MIDIERR_STILLPLAYING );
  120. DPF(DL_TRACE|FA_MIDI,("dwUser(DI)=%08X,dwParam1(HDR)=%08X",pInClient,dwParam1) );
  121. return midiInRead( pInClient, (LPMIDIHDR)dwParam1);
  122. case MIDM_STOP:
  123. DPF(DL_TRACE|FA_MIDI, ("MIDM_STOP dwUser(DI)=%08X",dwUser) );
  124. pInClient = (LPDEVICEINFO)dwUser;
  125. return wdmaudSetDeviceState(pInClient,
  126. IOCTL_WDMAUD_MIDI_IN_STOP);
  127. case MIDM_START:
  128. DPF(DL_TRACE|FA_MIDI, ("MIDM_START dwUser(DI)=%08X",dwUser) );
  129. pInClient = (LPDEVICEINFO)dwUser;
  130. return wdmaudSetDeviceState(pInClient,
  131. IOCTL_WDMAUD_MIDI_IN_RECORD);
  132. case MIDM_RESET:
  133. DPF(DL_TRACE|FA_MIDI, ("MIDM_RESET dwUser(DI)=%08X",dwUser) );
  134. pInClient = (LPDEVICEINFO)dwUser;
  135. return wdmaudSetDeviceState(pInClient,
  136. IOCTL_WDMAUD_MIDI_IN_RESET);
  137. #ifdef MIDI_THRU
  138. case DRVM_ADD_THRU:
  139. case DRVM_REMOVE_THRU:
  140. #endif
  141. default:
  142. MMRRETURN( MMSYSERR_NOTSUPPORTED );
  143. }
  144. //
  145. // Should not get here
  146. //
  147. DPFASSERT(0);
  148. MMRRETURN( MMSYSERR_NOTSUPPORTED );
  149. }
  150. /****************************************************************************
  151. * @doc INTERNAL
  152. *
  153. * @api void | midiCallback | This calls DriverCallback for a MIDIHDR.
  154. *
  155. * @parm LPDEVICEINFO | pMidiDevice | pointer to midi device.
  156. *
  157. * @parm UINT | msg | The message.
  158. *
  159. * @parm DWORD | dw1 | message DWORD (dw2 is always set to 0).
  160. *
  161. * @rdesc There is no return value.
  162. ***************************************************************************/
  163. VOID FAR midiCallback
  164. (
  165. LPDEVICEINFO pMidiDevice,
  166. UINT msg,
  167. DWORD_PTR dw1,
  168. DWORD_PTR dw2
  169. )
  170. {
  171. // invoke the callback function, if it exists. dwFlags contains
  172. // midi driver specific flags in the LOWORD and generic driver
  173. // flags in the HIWORD
  174. if (pMidiDevice->dwCallback)
  175. DriverCallback(pMidiDevice->dwCallback, // user's callback DWORD
  176. HIWORD(pMidiDevice->dwFlags), // callback flags
  177. (HDRVR)pMidiDevice->DeviceHandle, // handle to the midi device
  178. msg, // the message
  179. pMidiDevice->dwInstance, // user's instance data
  180. dw1, // first DWORD
  181. dw2); // second DWORD
  182. }
  183. /****************************************************************************
  184. * @doc INTERNAL
  185. *
  186. * @api DWORD | midiOpen | Open midi device and set up logical device data
  187. *
  188. * @parm LPDEVICEINFO | DeviceInfo | Specifies if it's a midi input or output
  189. * device
  190. *
  191. * @parm DWORD | dwUser | Input parameter to modMessage - pointer to
  192. * application's handle (generated by this routine)
  193. *
  194. * @parm DWORD | pmod | pointer to MIDIOPENDESC, was dwParam1 parameter
  195. * to modMessage
  196. *
  197. * @parm DWORD | dwParam2 | Input parameter to modMessage
  198. *
  199. * @rdesc modMessage return code.
  200. ***************************************************************************/
  201. MMRESULT FAR midiOpen
  202. (
  203. LPDEVICEINFO DeviceInfo,
  204. DWORD_PTR dwUser,
  205. LPMIDIOPENDESC pmod,
  206. DWORD dwParam2
  207. )
  208. {
  209. LPDEVICEINFO pClient; // pointer to client information structure
  210. MMRESULT mmr;
  211. #ifndef UNDER_NT
  212. DWORD dwCallback16;
  213. #else
  214. ULONG BufferCount;
  215. #endif
  216. // pmod contains a pointer to a MIDIOPENDESC
  217. // dwParam2 contains midi driver specific flags in the LOWORD
  218. // and generic driver flags in the HIWORD
  219. //
  220. // allocate my per-client structure
  221. //
  222. pClient = GlobalAllocDeviceInfo(DeviceInfo->wstrDeviceInterface);
  223. if (NULL == pClient)
  224. {
  225. MMRRETURN( MMSYSERR_NOMEM );
  226. }
  227. pClient->DeviceState = (LPVOID) GlobalAllocPtr( GPTR, sizeof( DEVICESTATE ) );
  228. if (NULL == pClient->DeviceState)
  229. {
  230. GlobalFreeDeviceInfo( pClient );
  231. MMRRETURN( MMSYSERR_NOMEM );
  232. }
  233. #ifdef UNDER_NT
  234. //
  235. // Allocate memory for our critical section
  236. //
  237. pClient->DeviceState->csQueue = (LPVOID) GlobalAllocPtr( GPTR, sizeof( CRITICAL_SECTION ) );
  238. if (NULL == pClient->DeviceState->csQueue)
  239. {
  240. GlobalFreePtr( pClient->DeviceState );
  241. GlobalFreeDeviceInfo( pClient );
  242. MMRRETURN( MMSYSERR_NOMEM );
  243. }
  244. try
  245. {
  246. InitializeCriticalSection( (LPCRITICAL_SECTION)pClient->DeviceState->csQueue );
  247. }
  248. except(EXCEPTION_EXECUTE_HANDLER)
  249. {
  250. GlobalFreePtr( pClient->DeviceState->csQueue );
  251. GlobalFreePtr( pClient->DeviceState );
  252. GlobalFreeDeviceInfo( pClient );
  253. MMRRETURN( MMSYSERR_NOMEM );
  254. }
  255. #endif
  256. //
  257. // fill out context data
  258. //
  259. pClient->DeviceNumber= DeviceInfo->DeviceNumber;
  260. pClient->DeviceType = DeviceInfo->DeviceType;
  261. pClient->dwInstance = pmod->dwInstance;
  262. pClient->dwCallback = pmod->dwCallback;
  263. #ifdef UNDER_NT
  264. pClient->DeviceHandle= (HANDLE32)pmod->hMidi;
  265. #else
  266. pClient->DeviceHandle= (HANDLE32)MAKELONG(pmod->hMidi,0);
  267. _asm
  268. {
  269. mov ax, offset MidiEventDeviceCallback
  270. mov word ptr [dwCallback16], ax
  271. mov ax, seg MidiEventDeviceCallback
  272. mov word ptr [dwCallback16+2], ax
  273. }
  274. pClient->dwCallback16= dwCallback16;
  275. #endif
  276. pClient->dwFlags = dwParam2;
  277. //
  278. // initialize the device state
  279. //
  280. DPF(DL_TRACE|FA_SYNC,("DI=%08X New DeviceState",pClient) );
  281. pClient->DeviceState->lpMidiInQueue= NULL;
  282. pClient->DeviceState->fPaused = FALSE;
  283. pClient->DeviceState->fRunning = FALSE;
  284. pClient->DeviceState->fExit = FALSE;
  285. pClient->DeviceState->bMidiStatus = 0;
  286. pClient->DeviceState->lpNoteOnMap = NULL;
  287. #ifdef DEBUG
  288. pClient->DeviceState->dwSig = DEVICESTATE_SIGNATURE;
  289. #endif
  290. if (pClient->DeviceType == MidiOutDevice)
  291. {
  292. //
  293. // For MIDI out, allocate one byte per note per channel to track
  294. // what's been played. This is used to avoid doing a brute-force
  295. // all notes off on MODM_RESET.
  296. //
  297. pClient->DeviceState->lpNoteOnMap = GlobalAllocPtr( GPTR, MIDI_NOTE_MAP_SIZE );
  298. if (NULL == pClient->DeviceState->lpNoteOnMap)
  299. {
  300. #ifdef UNDER_NT
  301. GlobalFreePtr( pClient->DeviceState->csQueue );
  302. #endif
  303. GlobalFreePtr( pClient->DeviceState );
  304. GlobalFreeDeviceInfo( pClient );
  305. MMRRETURN( MMSYSERR_NOMEM );
  306. }
  307. }
  308. //
  309. // See if we can open our device
  310. //
  311. mmr = wdmaudOpenDev( pClient, NULL );
  312. if (mmr != MMSYSERR_NOERROR)
  313. {
  314. if ( pClient->DeviceState->lpNoteOnMap )
  315. {
  316. GlobalFreePtr( pClient->DeviceState->lpNoteOnMap );
  317. }
  318. #ifdef UNDER_NT
  319. DeleteCriticalSection( (LPCRITICAL_SECTION)pClient->DeviceState->csQueue );
  320. GlobalFreePtr( pClient->DeviceState->csQueue );
  321. #endif
  322. GlobalFreePtr( pClient->DeviceState );
  323. GlobalFreeDeviceInfo( pClient ) ;
  324. return mmr;
  325. }
  326. //
  327. // Add instance to chain of devices
  328. //
  329. EnterCriticalSection(&wdmaudCritSec);
  330. pClient->Next = pMidiDeviceList;
  331. pMidiDeviceList = pClient;
  332. LeaveCriticalSection(&wdmaudCritSec);
  333. //
  334. // give the client my driver dw
  335. //
  336. {
  337. LPDEVICEINFO FAR *pUserHandle;
  338. pUserHandle = (LPDEVICEINFO FAR *)dwUser;
  339. *pUserHandle = pClient;
  340. }
  341. #ifndef UNDER_NT
  342. // If this is a MIDI output device, page lock the memory because it can
  343. // be accessed at interrupt time.
  344. //
  345. GlobalSmartPageLock( (HGLOBAL)HIWORD( pClient ));
  346. GlobalSmartPageLock( (HGLOBAL)HIWORD( pClient->DeviceState ));
  347. GlobalSmartPageLock( (HGLOBAL)HIWORD( pClient->DeviceState->lpNoteOnMap ));
  348. #endif
  349. #ifdef UNDER_NT
  350. //
  351. // If this is a MIDI input device on NT, send some buffers
  352. // down to the device in order so that once recording starts
  353. // we can get some data back. The pin is paused after
  354. // the call to wdmaudOpenDev.
  355. //
  356. if ( MidiInDevice == pClient->DeviceType )
  357. {
  358. for (BufferCount = 0; BufferCount < STREAM_BUFFERS; BufferCount++)
  359. {
  360. mmr = wdmaudGetMidiData( pClient, NULL );
  361. if ( MMSYSERR_NOERROR != mmr )
  362. {
  363. //
  364. // We hope that this doesn't happen, but if it does
  365. // we need to try to close down the device.
  366. //
  367. if ( MMSYSERR_NOERROR == wdmaudCloseDev( pClient ) )
  368. {
  369. wdmaudDestroyCompletionThread ( pClient );
  370. midiCleanUp( pClient );
  371. }
  372. DPF( 2, ("midiInOpen failed: returning mmr = %d", mmr ) );
  373. return mmr;
  374. }
  375. }
  376. }
  377. #endif
  378. //
  379. // sent client his OPEN callback message
  380. //
  381. midiCallback(pClient, DeviceInfo->DeviceType == MidiOutDevice ? MOM_OPEN : MIM_OPEN,
  382. 0L, 0L);
  383. return MMSYSERR_NOERROR;
  384. }
  385. /****************************************************************************
  386. * @doc INTERNAL
  387. *
  388. * @api void | midiCleanUp | Free resources for a midi device
  389. *
  390. * @parm LPDEVICEINFO | pClient | Pointer to a DEVICEINFO structure describing
  391. * resources to be freed.
  392. *
  393. * @rdesc There is no return value.
  394. *
  395. * @comm If the pointer to the resource is NULL then the resource has not
  396. * been allocated.
  397. ***************************************************************************/
  398. VOID FAR midiCleanUp
  399. (
  400. LPDEVICEINFO pClient
  401. )
  402. {
  403. LPDEVICEINFO FAR *ppCur ;
  404. //
  405. // remove from device chain
  406. //
  407. EnterCriticalSection(&wdmaudCritSec);
  408. for (ppCur = &pMidiDeviceList;
  409. *ppCur != NULL;
  410. ppCur = &(*ppCur)->Next)
  411. {
  412. if (*ppCur == pClient)
  413. {
  414. *ppCur = (*ppCur)->Next;
  415. break;
  416. }
  417. }
  418. LeaveCriticalSection(&wdmaudCritSec);
  419. DPF(DL_TRACE|FA_SYNC,("DI=%08X Freed DeviceState",pClient) );
  420. #ifdef UNDER_NT
  421. DeleteCriticalSection( (LPCRITICAL_SECTION)pClient->DeviceState->csQueue );
  422. GlobalFreePtr( pClient->DeviceState->csQueue );
  423. #endif
  424. if (pClient->DeviceState->lpNoteOnMap)
  425. {
  426. #ifndef UNDER_NT
  427. GlobalSmartPageUnlock( (HGLOBAL)HIWORD( pClient->DeviceState->lpNoteOnMap ));
  428. #endif
  429. GlobalFreePtr( pClient->DeviceState->lpNoteOnMap );
  430. }
  431. #ifndef UNDER_NT
  432. GlobalSmartPageUnlock( (HGLOBAL)HIWORD( pClient->DeviceState ));
  433. GlobalSmartPageUnlock( (HGLOBAL)HIWORD( pClient ));
  434. #endif
  435. #ifdef DEBUG
  436. //
  437. // In debug, let's set all the values in the DEVICESTATE structure to bad
  438. // values.
  439. //
  440. pClient->DeviceState->cSampleBits=0xDEADBEEF;
  441. pClient->DeviceState->hThread=NULL;
  442. pClient->DeviceState->dwThreadId=0xDEADBEEF;
  443. pClient->DeviceState->lpWaveQueue=NULL;
  444. pClient->DeviceState->csQueue=NULL;
  445. pClient->DeviceState->hevtQueue=NULL;
  446. pClient->DeviceState->hevtExitThread=NULL;
  447. #endif
  448. GlobalFreePtr( pClient->DeviceState );
  449. pClient->DeviceState=NULL;
  450. #ifdef DEBUG
  451. //
  452. // Now set all the values in the DEVICEINFO structure to bad values.
  453. //
  454. // pClient->Next=(LPDEVICEINFO)0xDEADBEEF;
  455. pClient->DeviceNumber=-1;
  456. pClient->DeviceType=0xDEADBEEF;
  457. pClient->DeviceHandle=NULL;
  458. pClient->dwInstance=(DWORD_PTR)NULL;
  459. pClient->dwCallback=(DWORD_PTR)NULL;
  460. pClient->dwCallback16=0xDEADBEEF;
  461. pClient->dwFlags=0xDEADBEEF;
  462. pClient->DataBuffer=NULL;
  463. pClient->HardwareCallbackEventHandle=NULL;
  464. pClient->dwCallbackType=0xDEADBEEF;
  465. pClient->dwLineID=0xDEADBEEF;
  466. pClient->dwFormat=0xDEADBEEF;
  467. // pClient->DeviceState=(LPDEVICESTATE)0xDEADBEEF;
  468. #endif
  469. GlobalFreeDeviceInfo( pClient ) ;
  470. pClient=NULL;
  471. }
  472. /****************************************************************************
  473. * @doc INTERNAL
  474. *
  475. * @api DWORD | midiInRead | Pass a new buffer to the Auxiliary thread for
  476. * a midi device.
  477. *
  478. * @parm LPDEVICEINFO | pClient | The data associated with the logical midi
  479. * device.
  480. *
  481. * @parm LPMIDIHDR | pHdr | Pointer to a midi buffer
  482. *
  483. * @rdesc A MMSYS... type return code for the application.
  484. *
  485. * @comm The buffer flags are set and the buffer is passed to the auxiliary
  486. * device task for processing.
  487. ***************************************************************************/
  488. MMRESULT midiInRead
  489. (
  490. LPDEVICEINFO DeviceInfo,
  491. LPMIDIHDR pHdr
  492. )
  493. {
  494. MMRESULT mmr = MMSYSERR_NOERROR;
  495. LPMIDIHDR pTemp;
  496. DWORD dwCallback16;
  497. //
  498. // Put the request at the end of our queue.
  499. //
  500. pHdr->dwFlags |= MHDR_INQUEUE;
  501. pHdr->dwFlags &= ~MHDR_DONE;
  502. pHdr->dwBytesRecorded = 0;
  503. pHdr->lpNext = NULL;
  504. //
  505. // Store the context for this write in the header so that
  506. // we know which client to send this back to on completion.
  507. //
  508. pHdr->reserved = (DWORD_PTR)DeviceInfo;
  509. #ifndef UNDER_NT
  510. //
  511. // Put the long message callback handler into the
  512. // DeviceInfo structure.
  513. //
  514. _asm
  515. {
  516. mov ax, offset MidiInDeviceCallback
  517. mov word ptr [dwCallback16], ax
  518. mov ax, seg MidiInDeviceCallback
  519. mov word ptr [dwCallback16+2], ax
  520. }
  521. DeviceInfo->dwCallback16 = dwCallback16;
  522. #endif
  523. //
  524. // Add the MIDI header to the queue
  525. //
  526. CRITENTER ;
  527. if (!DeviceInfo->DeviceState->lpMidiInQueue)
  528. {
  529. DeviceInfo->DeviceState->lpMidiInQueue = pHdr;
  530. pTemp = NULL;
  531. #ifdef UNDER_NT
  532. if( (DeviceInfo->DeviceState->hevtQueue) &&
  533. (DeviceInfo->DeviceState->hevtQueue != (HANDLE)FOURTYTHREE) &&
  534. (DeviceInfo->DeviceState->hevtQueue != (HANDLE)FOURTYTWO) )
  535. {
  536. DPF(DL_TRACE|FA_SYNC,("REMOVED: SetEvent on hevtQueue") );
  537. // SetEvent( DeviceInfo->DeviceState->hevtQueue );
  538. }
  539. #endif
  540. }
  541. else
  542. {
  543. for (pTemp = DeviceInfo->DeviceState->lpMidiInQueue;
  544. pTemp->lpNext != NULL;
  545. pTemp = pTemp->lpNext);
  546. pTemp->lpNext = pHdr;
  547. }
  548. CRITLEAVE ;
  549. #ifndef UNDER_NT
  550. //
  551. // Call the 16 routine to send the buffer down
  552. // to the kernel. On NT, do all the processing
  553. // of the MIDI data in User mode.
  554. //
  555. mmr = wdmaudSubmitMidiInHeader(DeviceInfo, pHdr);
  556. if (mmr != MMSYSERR_NOERROR)
  557. {
  558. // Unlink...
  559. GlobalFreePtr( pHdr );
  560. if (pTemp)
  561. {
  562. pTemp->lpNext = NULL;
  563. }
  564. else
  565. DeviceInfo->DeviceState->lpMidiInQueue = NULL;
  566. pHdr->dwFlags &= ~WHDR_INQUEUE;
  567. DbgBreak();
  568. MMRRETURN( mmr ); // used to return MMSYSERR_INVALPARAM for all errors!
  569. }
  570. #endif
  571. return mmr;
  572. }
  573. /****************************************************************************
  574. * @doc INTERNAL
  575. *
  576. * @api VOID | midiInCompleteHeader |
  577. *
  578. * @parm LPDEVICEINFO | DeviceInfo | The data associated with the logical midi
  579. * device.
  580. *
  581. * @comm The buffer flags are set and the buffer is passed to the auxiliary
  582. * device task for processing.
  583. ****************************************************************************/
  584. VOID midiInCompleteHeader
  585. (
  586. LPDEVICEINFO DeviceInfo,
  587. DWORD dwTimeStamp,
  588. WORD wDataType
  589. )
  590. {
  591. LPMIDIHDR pHdr;
  592. DPFASSERT(DeviceInfo);
  593. //
  594. // Only remove headers from the front of the queue
  595. // so that order is maintained.
  596. //
  597. if (pHdr = DeviceInfo->DeviceState->lpMidiInQueue)
  598. {
  599. DeviceInfo->DeviceState->lpMidiInQueue = DeviceInfo->DeviceState->lpMidiInQueue->lpNext;
  600. DPF(DL_TRACE|FA_MIDI, ("Pulling header out of queue") );
  601. pHdr->dwFlags &= ~MHDR_INQUEUE;
  602. pHdr->dwFlags |= MHDR_DONE;
  603. pHdr->lpNext = NULL;
  604. midiCallback((LPDEVICEINFO)pHdr->reserved,
  605. wDataType, // MIM_LONGDATA or MIM_LONGERROR
  606. (DWORD_PTR)pHdr,
  607. dwTimeStamp);
  608. }
  609. }