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.

4544 lines
161 KiB

  1. //==========================================================================;
  2. //
  3. // mixer.c
  4. //
  5. // Copyright (c) 1992-2001 Microsoft Corporation
  6. //
  7. // Description:
  8. //
  9. //
  10. // History:
  11. // 6/27/93 cjp [curtisp]
  12. //
  13. //==========================================================================;
  14. #define UNICODE
  15. #include "winmmi.h"
  16. #include "mixer.h" // This file drags in a ton of stuff to support the mixers
  17. PMIXERDEV gpMixerDevHeader = NULL; /* A LL of open devices */
  18. UINT guTotalMixerDevs; // total mixer devices
  19. //
  20. // mixer device driver list--add one to accomodate the MIXER_MAPPER. note
  21. // that even if we are not compiling with mapper support we need to add
  22. // one because other code relies on it (for other device mappers).
  23. //
  24. MIXERDRV mixerdrvZ;
  25. char gszMxdMessage[] = "mxdMessage";
  26. TCHAR gszMixer[] = TEXT("mixer");
  27. #ifdef MIXER_MAPPER
  28. TCHAR gszMixerMapper[] = TEXT("mixermapper");
  29. #endif
  30. #ifdef MIXER_MAPPER
  31. #define MMDRVI_MAPPER 0x8000 // install this driver as the mapper
  32. #endif
  33. //#define MMDRVI_MIXER 0x0006
  34. #define MMDRVI_HDRV 0x4000 // hdrvr is an installable driver
  35. #define MMDRVI_REMOVE 0x2000 // remove the driver
  36. //--------------------------------------------------------------------------;
  37. //
  38. // BOOL MixerCallbackFunc
  39. //
  40. // Description:
  41. //
  42. // NOTE! we document that a mixer must NEVER call this function at
  43. // interrupt time! we don't want to fix our code or data segments.
  44. //
  45. // Arguments:
  46. // HMIXER hmx:
  47. //
  48. // UINT uMsg:
  49. //
  50. // DWORD dwInstance:
  51. //
  52. // DWORD dwParam1:
  53. //
  54. // DWORD dwParam2:
  55. //
  56. // Return (BOOL):
  57. //
  58. // History:
  59. // 07/21/93 cjp [curtisp]
  60. //
  61. //--------------------------------------------------------------------------;
  62. BOOL CALLBACK MixerCallbackFunc(
  63. HMIXER hmx,
  64. UINT uMsg,
  65. DWORD_PTR dwInstance,
  66. DWORD_PTR dwParam1,
  67. DWORD_PTR dwParam2
  68. )
  69. {
  70. PMIXERDEV pmxdev;
  71. //
  72. // step through all open handles and do callbacks to the appropriate
  73. // clients...
  74. //
  75. //
  76. // Serialize access to hande list - only necessary for Win32
  77. //
  78. MIXMGR_ENTER;
  79. for (pmxdev = gpMixerDevHeader; pmxdev; pmxdev = pmxdev->pmxdevNext)
  80. {
  81. //
  82. // same device? (could also use hmx->uDeviceID)
  83. //
  84. if (pmxdev->uDeviceID != dwInstance)
  85. continue;
  86. DriverCallback(pmxdev->dwCallback,
  87. (HIWORD(pmxdev->fdwOpen) | DCB_NOSWITCH),
  88. GetWOWHandle((HANDLE)pmxdev)
  89. ? (HANDLE)(UINT_PTR)GetWOWHandle((HANDLE)pmxdev)
  90. : (HANDLE)pmxdev,
  91. uMsg,
  92. pmxdev->dwInstance,
  93. dwParam1,
  94. dwParam2);
  95. }
  96. MIXMGR_LEAVE;
  97. return (TRUE);
  98. } // MixerCallbackFunc()
  99. //--------------------------------------------------------------------------;
  100. //
  101. // MMRESULT mixerReferenceDriveryById
  102. //
  103. // Description:
  104. // This function maps a logical id to a device driver and physical id.
  105. //
  106. // Arguments:
  107. // IN UINT uId: The logical id to be mapped.
  108. //
  109. // OUT PMIXERDRV* OPTIONAL ppmixerdrv: Pointer to the MIXERDRV structure
  110. // describing describing the driver supporing the id.
  111. //
  112. // OUT UINT* OPTIONAL pport: The driverj-relative device number. If the
  113. // caller supplies this buffer then it must also supply ppmixerdrv.
  114. //
  115. // Return (MMRESULT):
  116. // The return value is zero if successful, MMSYSERR_BADDEVICEID if the id
  117. // is out of range.
  118. //
  119. // Comments:
  120. // If the caller specifies ppmixerdrv then this function increments the
  121. // mixerdrv's usage before returning. The caller must ensure the usage
  122. // is eventually decremented.
  123. //
  124. // History:
  125. // 03/17/93 cjp [curtisp]
  126. //
  127. //--------------------------------------------------------------------------;
  128. MMRESULT mixerReferenceDriverById(
  129. IN UINT id,
  130. OUT PMIXERDRV *ppdrv OPTIONAL,
  131. OUT UINT *pport OPTIONAL
  132. )
  133. {
  134. PMIXERDRV pdrv;
  135. MMRESULT mmr;
  136. // Should not be called asking for port but not mixerdrv
  137. WinAssert(!(pport && !ppdrv));
  138. EnterNumDevs("mixerReferenceDriverById");
  139. #ifdef MIXER_MAPPER
  140. if (MIXER_MAPPER == id)
  141. {
  142. id = 0;
  143. for (pdrv = mixerdrvZ.Next; pdrv != &mixerdrvZ; pdrv = pdrv->Next)
  144. {
  145. if (pdrv->fdwDriver & MMDRV_MAPPER) break;
  146. }
  147. }
  148. else
  149. #endif
  150. {
  151. for (pdrv = mixerdrvZ.Next; pdrv != &mixerdrvZ; pdrv = pdrv->Next)
  152. {
  153. if (pdrv->fdwDriver & MMDRV_MAPPER) continue;
  154. if (pdrv->NumDevs > id) break;
  155. id -= pdrv->NumDevs;
  156. }
  157. }
  158. if (pdrv != &mixerdrvZ)
  159. {
  160. if (ppdrv)
  161. {
  162. mregIncUsagePtr(pdrv);
  163. *ppdrv = pdrv;
  164. if (pport) *pport = id;
  165. }
  166. mmr = MMSYSERR_NOERROR;
  167. } else {
  168. mmr = MMSYSERR_BADDEVICEID;
  169. }
  170. LeaveNumDevs("mixerReferenceDriverById");
  171. return mmr;
  172. ;
  173. } // IMixerMapId()
  174. PCWSTR mixerReferenceDevInterfaceById(UINT_PTR id)
  175. {
  176. PMIXERDRV pdrv;
  177. PCWSTR DevInterface;
  178. if (ValidateHandle((HANDLE)id, TYPE_MIXER))
  179. {
  180. DevInterface = ((PMIXERDEV)id)->pmxdrv->cookie;
  181. if (DevInterface) wdmDevInterfaceInc(DevInterface);
  182. return DevInterface;
  183. }
  184. if (!mixerReferenceDriverById((UINT)id, &pdrv, NULL))
  185. {
  186. DevInterface = pdrv->cookie;
  187. if (DevInterface) wdmDevInterfaceInc(DevInterface);
  188. mregDecUsagePtr(pdrv);
  189. return DevInterface;
  190. }
  191. return NULL;
  192. }
  193. //--------------------------------------------------------------------------;
  194. //
  195. // DWORD IMixerMessageHandle
  196. //
  197. // Description:
  198. //
  199. //
  200. // Arguments:
  201. // HMIXER hmx:
  202. //
  203. // UINT uMsg:
  204. //
  205. // DWORD dwP1:
  206. //
  207. // DWORD dwP2:
  208. //
  209. // Return (DWORD):
  210. //
  211. // History:
  212. // 03/17/93 cjp [curtisp]
  213. //
  214. //--------------------------------------------------------------------------;
  215. DWORD NEAR PASCAL IMixerMessageHandle(
  216. HMIXER hmx,
  217. UINT uMsg,
  218. DWORD_PTR dwP1,
  219. DWORD_PTR dwP2
  220. )
  221. {
  222. PMIXERDEV pmxd;
  223. DWORD dwRc;
  224. pmxd = (PMIXERDEV)hmx;
  225. ENTER_MM_HANDLE(hmx);
  226. ReleaseHandleListResource();
  227. // Is handle deserted?
  228. if (IsHandleDeserted(hmx))
  229. {
  230. LEAVE_MM_HANDLE(hmx);
  231. return (MMSYSERR_NODRIVER);
  232. }
  233. if (IsHandleBusy(hmx))
  234. {
  235. LEAVE_MM_HANDLE(hmx);
  236. return (MMSYSERR_HANDLEBUSY);
  237. }
  238. EnterCriticalSection(&pmxd->pmxdrv->MixerCritSec);
  239. if (BAD_HANDLE(hmx, TYPE_MIXER))
  240. {
  241. // Do we still need to check for this?
  242. WinAssert(!"Bad Handle within IMixerMessageHandle");
  243. dwRc = MMSYSERR_INVALHANDLE;
  244. }
  245. else
  246. {
  247. dwRc = ((*(pmxd->pmxdrv->drvMessage))
  248. (pmxd->wDevice, uMsg, pmxd->dwDrvUser, dwP1, dwP2));
  249. }
  250. LeaveCriticalSection(&pmxd->pmxdrv->MixerCritSec);
  251. LEAVE_MM_HANDLE(hmx);
  252. return dwRc;
  253. } // IMixerMessageHandle()
  254. //--------------------------------------------------------------------------;
  255. //
  256. // DWORD IMixerMessageId
  257. //
  258. // Description:
  259. //
  260. //
  261. // Arguments:
  262. // PMIXERDRV pmxdrv:
  263. //
  264. // UINT uTotalNumDevs:
  265. //
  266. // UINT uDeviceID:
  267. //
  268. // UINT uMsg:
  269. //
  270. // DWORD dwParam1:
  271. //
  272. // DWORD dwParam2:
  273. //
  274. // Return (DWORD):
  275. //
  276. // History:
  277. // 03/17/93 cjp [curtisp]
  278. //
  279. //--------------------------------------------------------------------------;
  280. extern void lstrncpyW (LPWSTR pszTarget, LPCWSTR pszSource, size_t cch);
  281. DWORD NEAR PASCAL IMixerMessageId(
  282. UINT uDeviceID,
  283. UINT uMsg,
  284. DWORD_PTR dwParam1,
  285. DWORD_PTR dwParam2
  286. )
  287. {
  288. PMIXERDRV pmxdrv;
  289. UINT port;
  290. DWORD dwRc;
  291. HMIXER hmx;
  292. PMIXERDEV pmxdev;
  293. MMRESULT mmr;
  294. mmr = mixerReferenceDriverById(uDeviceID, &pmxdrv, &port);
  295. if (mmr)
  296. {
  297. return mmr;
  298. }
  299. if (mregHandleInternalMessages(pmxdrv, TYPE_MIXER, port, uMsg, dwParam1, dwParam2, &mmr))
  300. {
  301. mregDecUsagePtr(pmxdrv);
  302. return mmr;
  303. }
  304. dwRc = mixerOpen(&hmx, uDeviceID, 0L, 0L, MIXER_OBJECTF_MIXER);
  305. // Should we go through IMixerMessageHandle???
  306. if (MMSYSERR_NOERROR == dwRc)
  307. {
  308. pmxdev = (PMIXERDEV)hmx;
  309. pmxdrv = pmxdev->pmxdrv;
  310. if (!pmxdrv->drvMessage)
  311. {
  312. dwRc = MMSYSERR_NODRIVER;
  313. }
  314. else
  315. {
  316. EnterCriticalSection( &pmxdrv->MixerCritSec);
  317. dwRc = ((*(pmxdrv->drvMessage))
  318. (port, uMsg, pmxdev->dwDrvUser, dwParam1, dwParam2));
  319. LeaveCriticalSection( &pmxdrv->MixerCritSec);
  320. }
  321. mixerClose(hmx);
  322. }
  323. mregDecUsagePtr(pmxdrv);
  324. return dwRc;
  325. } // IMixerMessageId()
  326. //==========================================================================;
  327. //
  328. //
  329. //
  330. //
  331. //==========================================================================;
  332. /*--------------------------------------------------------------------------;
  333. *
  334. * @doc EXTERNAL MIXER SDK API
  335. *
  336. * @api UINT | mixerGetNumDevs | The <f mixerGetNumDevs> function retrieves
  337. * the number of audio mixer devices present in the system.
  338. *
  339. * @rdesc Returns the number of audio mixer devices present in the system.
  340. * If no audio mixer devices are available, zero is returned.
  341. *
  342. * @xref <f mixerGetDevCaps>, <f mixerOpen>
  343. *
  344. **/
  345. UINT APIENTRY mixerGetNumDevs(
  346. void
  347. )
  348. {
  349. UINT cDevs;
  350. ClientUpdatePnpInfo();
  351. EnterNumDevs("mixerGetNumDevs");
  352. cDevs = guTotalMixerDevs;
  353. LeaveNumDevs("mixerGetNumDevs");
  354. return cDevs;
  355. } // mixerGetNumDevs()
  356. /*--------------------------------------------------------------------------;
  357. *
  358. * @doc EXTERNAL MIXER SDK STRUCTURE
  359. *
  360. * @types MIXERCAPS | The <t MIXERCAPS> structure describes the capabilities
  361. * of a mixer device.
  362. *
  363. * @field WORD | wMid | Specifies a manufacturer identifier for the mixer
  364. * device driver. Manufacturer identifiers are defined in Appendix B,
  365. * <lq>Manufacturer ID and Product ID Lists.<rq>
  366. *
  367. * @field WORD | wPid | Specifies a product identifier for the mixer device
  368. * driver. Product identifiers are defined in Appendix B,
  369. * <lq>Manufacturer ID and Product ID Lists.<rq>
  370. *
  371. * @field MMVERSION | vDriverVersion | Specifies the version number of the
  372. * mixer device driver. The high-order byte is the major version
  373. * number, and the low-order byte is the minor version number.
  374. *
  375. * @field char | szPname[MAXPNAMELEN] | Specifies the name of the product.
  376. * If the mixer device driver supports multiple cards, this string must
  377. * uniquely and easily identify (potentially to a user) this specific
  378. * card. For example, szPname = <lq>Sound Card Mixer, I/O address 200<rq>
  379. * would uniquely identify (to the user) this particular card as a
  380. * Sound Card Mixer for the physical card based at I/O address 200. If
  381. * only one device is installed, it is recommended that only the base
  382. * name be returned. For example, szPname should be <lq>Sound Card Mixer<rq>
  383. * if only one device is present.
  384. *
  385. * @field DWORD | fdwSupport | Specifies various support information for
  386. * the mixer device driver. No extended support bits are currently
  387. * defined.
  388. *
  389. * @field DWORD | cDestinations | The number of audio mixer line destinations
  390. * available through the mixer. All mixer devices must support at least
  391. * one destination line, so this member can never be zero. Destination
  392. * indexes used in the <e MIXERLINE.dwDestination> member of the
  393. * <t MIXERLINE> structure range from zero to the value specified in the
  394. * <e MIXERCAPS.cDestinations> member minus one.
  395. *
  396. * @tagname tMIXERCAPS
  397. *
  398. * @othertype MIXERCAPS FAR * | LPMIXERCAPS | A pointer to a <t MIXERCAPS>
  399. * structure.
  400. *
  401. * @othertype MIXERCAPS * | PMIXERCAPS | A pointer to a <t MIXERCAPS>
  402. * structure.
  403. *
  404. * @xref <f mixerGetDevCaps>, <f mixerOpen>, <f mixerGetLineInfo>
  405. *
  406. **/
  407. /*--------------------------------------------------------------------------;
  408. *
  409. * @doc EXTERNAL MIXER SDK API
  410. *
  411. * @api MMRESULT | mixerGetDevCaps | The <f mixerGetDevCaps> function
  412. * queries a specified audio mixer device to determine its capabilities.
  413. *
  414. * @parm UINT | uMxId | Identifies the audio mixer device with either
  415. * an audio mixer device identifier or a handle to an opened audio mixer
  416. * device.
  417. *
  418. * @parm LPMIXERCAPS | pmxcaps | Pointer to a <t MIXERCAPS> structure that
  419. * receives information about the capabilities of the device.
  420. *
  421. * @parm UINT | cbmxcaps | Specifies the size, in bytes, of the <t MIXERCAPS>
  422. * structure.
  423. *
  424. * @rdesc The return value is zero if the function is successful. Otherwise,
  425. * it returns a non-zero error number. Possible error returns include
  426. * the following:
  427. *
  428. * @flag <c MMSYSERR_BADDEVICEID> | The specified device identifier is
  429. * out of range.
  430. *
  431. * @flag <c MMSYSERR_INVALHANDLE> | The audio mixer device handle passed
  432. * is invalid.
  433. *
  434. * @flag <c MMSYSERR_INVALPARAM> | One or more arguments passed is
  435. * invalid.
  436. *
  437. * @comm Use the <f mixerGetNumDevs> function to determine the number of
  438. * audio mixer devices present in the system. The device identifier
  439. * specified by <p uMxId> varies from zero to one less than the number
  440. * of mixer devices present.
  441. *
  442. * Only <p cbmxcaps> bytes (or less) of information is copied to the
  443. * location pointed to by <p pmxcaps>. If <p cbmxcaps> is zero, nothing
  444. * is copied, and the function returns success.
  445. *
  446. * This function also accepts an audio mixer device handle returned by
  447. * the <f mixerOpen> function as the <p uMxId> argument. The calling
  448. * application should cast the <c HMIXER> handle to a UINT.
  449. *
  450. * @xref <f mixerGetNumDevs>, <t MIXERCAPS>, <f mixerOpen>
  451. *
  452. **/
  453. MMRESULT APIENTRY mixerGetDevCapsA(
  454. UINT_PTR uMxId,
  455. LPMIXERCAPSA pmxcapsA,
  456. UINT cbmxcaps
  457. )
  458. {
  459. MIXERCAPS2W mxcaps2W;
  460. MIXERCAPS2A mxcaps2A;
  461. MMRESULT mmr;
  462. if (0 == cbmxcaps)
  463. return (MMSYSERR_NOERROR);
  464. V_WPOINTER(pmxcapsA, cbmxcaps, MMSYSERR_INVALPARAM);
  465. memset(&mxcaps2W, 0, sizeof(mxcaps2W));
  466. mmr = mixerGetDevCaps(uMxId, (LPMIXERCAPSW)&mxcaps2W, sizeof(mxcaps2W));
  467. if (mmr != MMSYSERR_NOERROR) {
  468. return mmr;
  469. }
  470. //
  471. // Copy the structure back as cleanly as possible. This would
  472. // Be a little easier if all the strings were at the end of structures.
  473. // Things would be a LOT more sensible if they could ONLY ask for the
  474. // whole structure (then we could copy the result direct to the
  475. // caller's memory).
  476. //
  477. // Because of all this it's easiest to get the whole UNICODE structure,
  478. // massage it into an ASCII stucture then (for the 0.001% of such apps)
  479. // copy back the part they actually asked for. The definition of the
  480. // API means that, far from these apps going faster, everyone goes slow.
  481. //
  482. Iwcstombs(mxcaps2A.szPname, mxcaps2W.szPname, MAXPNAMELEN);
  483. mxcaps2A.wMid = mxcaps2W.wMid;
  484. mxcaps2A.wPid = mxcaps2W.wPid;
  485. mxcaps2A.vDriverVersion = mxcaps2W.vDriverVersion;
  486. mxcaps2A.fdwSupport = mxcaps2W.fdwSupport;
  487. mxcaps2A.cDestinations = mxcaps2W.cDestinations;
  488. mxcaps2A.ManufacturerGuid = mxcaps2W.ManufacturerGuid;
  489. mxcaps2A.ProductGuid = mxcaps2W.ProductGuid;
  490. mxcaps2A.NameGuid = mxcaps2W.NameGuid;
  491. CopyMemory((PVOID)pmxcapsA, &mxcaps2A, min(sizeof(mxcaps2A), cbmxcaps));
  492. return mmr;
  493. } // mixerGetDevCapsA()
  494. MMRESULT APIENTRY mixerGetDevCaps(
  495. UINT_PTR uMxId,
  496. LPMIXERCAPS pmxcaps,
  497. UINT cbmxcaps
  498. )
  499. {
  500. DWORD_PTR dwParam1, dwParam2;
  501. MDEVICECAPSEX mdCaps;
  502. PCWSTR DevInterface;
  503. MMRESULT mmr;
  504. if (0 == cbmxcaps)
  505. return (MMSYSERR_NOERROR);
  506. V_WPOINTER(pmxcaps, cbmxcaps, MMSYSERR_INVALPARAM);
  507. ClientUpdatePnpInfo();
  508. DevInterface = mixerReferenceDevInterfaceById(uMxId);
  509. dwParam2 = (DWORD_PTR)DevInterface;
  510. if (0 == dwParam2)
  511. {
  512. dwParam1 = (DWORD_PTR)pmxcaps;
  513. dwParam2 = (DWORD)cbmxcaps;
  514. }
  515. else
  516. {
  517. mdCaps.cbSize = (DWORD)cbmxcaps;
  518. mdCaps.pCaps = pmxcaps;
  519. dwParam1 = (DWORD_PTR)&mdCaps;
  520. }
  521. AcquireHandleListResourceShared();
  522. if ((uMxId >= guTotalMixerDevs) && !BAD_HANDLE((HMIXER)uMxId, TYPE_MIXER))
  523. {
  524. mmr = (MMRESULT)IMixerMessageHandle((HMIXER)uMxId,
  525. MXDM_GETDEVCAPS,
  526. dwParam1,
  527. dwParam2);
  528. }
  529. else
  530. {
  531. ReleaseHandleListResource();
  532. mmr = (MMRESULT)IMixerMessageId((UINT)uMxId,
  533. MXDM_GETDEVCAPS,
  534. (DWORD_PTR)dwParam1,
  535. (DWORD_PTR)dwParam2);
  536. }
  537. if (DevInterface) wdmDevInterfaceDec(DevInterface);
  538. return (mmr);
  539. } // mixerGetDevCaps()
  540. /*--------------------------------------------------------------------------;
  541. *
  542. * @doc EXTERNAL MIXER SDK API
  543. *
  544. * @api MMRESULT | mixerGetID | The <f mixerGetID> function gets the device
  545. * identifier for an audio mixer device that corresponds to audio mixer
  546. * object handle <p hmxobj>.
  547. *
  548. * @parm <c HMIXEROBJ> | hmxobj | Identifies the audio mixer object handle
  549. * to map to an audio mixer device identifier.
  550. *
  551. * @parm UINT FAR * | puMxId | Points to a UINT-sized variable that will
  552. * receive the audio mixer device identifier. If no mixer device is
  553. * available for the <p hmxobj> object, then '-1' is placed in this
  554. * location (an error code of <c MMSYSERR_NODRIVER> is also returned).
  555. *
  556. * @parm DWORD | fdwId | Specifies flags for how to map the audio mixer
  557. * object <p hmxobj>.
  558. *
  559. * @flag <c MIXER_OBJECTF_MIXER> | Specifies that <p hmxobj> is an audio
  560. * mixer device identifier in the range of zero to one less than the
  561. * number of devices returned by <f mixerGetNumDevs>. This flag is
  562. * optional.
  563. *
  564. * @flag <c MIXER_OBJECTF_HMIXER> | Specifies that <p hmxobj> is a mixer
  565. * device handle returned by <f mixerOpen>. This flag is optional.
  566. *
  567. * @flag <c MIXER_OBJECTF_WAVEOUT> | Specifies that <p hmxobj> is a
  568. * waveform output device identifier in the range of zero to one less
  569. * than the number of devices returned by <f waveOutGetNumDevs>.
  570. *
  571. * @flag <c MIXER_OBJECTF_HWAVEOUT> | Specifies that <p hmxobj> is a
  572. * waveform output handle returned by <f waveOutOpen>.
  573. *
  574. * @flag <c MIXER_OBJECTF_WAVEIN> | Specifies that <p hmxobj> is a
  575. * waveform input device identifier in the range of zero to one less
  576. * than the number of devices returned by <f waveInGetNumDevs>.
  577. *
  578. * @flag <c MIXER_OBJECTF_HWAVEIN> | Specifies that <p hmxobj> is a
  579. * waveform input handle returned by <f midiInOpen>.
  580. *
  581. * @flag <c MIXER_OBJECTF_MIDIOUT> | Specifies that <p hmxobj> is a MIDI
  582. * output device identifier in the range of zero to one less than the
  583. * number of devices returned by <f midiOutGetNumDevs>.
  584. *
  585. * @flag <c MIXER_OBJECTF_HMIDIOUT> | Specifies that <p hmxobj> is a
  586. * MIDI output handle returned by <f midiOutOpen>.
  587. *
  588. * @flag <c MIXER_OBJECTF_MIDIIN> | Specifies that <p hmxobj> is a MIDI
  589. * input device identifier in the range of zero to one less than the
  590. * number of devices returned by <f midiInGetNumDevs>.
  591. *
  592. * @flag <c MIXER_OBJECTF_HMIDIIN> | Specifies that <p hmxobj> is a MIDI
  593. * input handle returned by <f midiInOpen>.
  594. *
  595. * @flag <c MIXER_OBJECTF_AUX> | Specifies that <p hmxobj> is an
  596. * auxiliary device identifier in the range of zero to one less than the
  597. * number of devices returned by <f auxGetNumDevs>.
  598. *
  599. * @rdesc The return value is zero if the function is successful. Otherwise,
  600. * it returns a non-zero error number. Possible error returns include
  601. * the following:
  602. *
  603. * @flag <c MMSYSERR_BADDEVICEID> | The <p hmxobj> argument specifies an
  604. * invalid device identifier.
  605. *
  606. * @flag <c MMSYSERR_INVALHANDLE> | The <p hmxobj> argument specifies an
  607. * invalid handle.
  608. *
  609. * @flag <c MMSYSERR_INVALFLAG> | One or more flags are invalid.
  610. *
  611. * @flag <c MMSYSERR_INVALPARAM> | One or more arguments passed is
  612. * invalid.
  613. *
  614. * @flag <c MMSYSERR_NODRIVER> | No audio mixer device is available for
  615. * the object specified by <p hmxobj>. Note that the location referenced
  616. * by <p puMxId> will also contain the value '-1'.
  617. *
  618. * @comm Use the <f mixerGetID> function to determine what audio mixer
  619. * device (if any) is responsible for performing mixing functions on a
  620. * media device. For example, an application can use <f mixerGetID> to
  621. * get the mixer device identifier responsible for setting the volume
  622. * on a waveform output handle. Or the application may want to display
  623. * a peak meter for waveform input device.
  624. *
  625. * @xref <f mixerGetNumDevs>, <f mixerGetDevCaps>, <f mixerOpen>
  626. *
  627. **/
  628. MMRESULT APIENTRY mixerGetID(
  629. HMIXEROBJ hmxobj,
  630. UINT FAR *puMxId,
  631. DWORD fdwId
  632. )
  633. {
  634. ClientUpdatePnpInfo();
  635. return IMixerGetID( hmxobj, (PUINT)puMxId, NULL, fdwId );
  636. } // mixerGetID()
  637. //--------------------------------------------------------------------------;
  638. //
  639. // MMRESULT IMixerGetID
  640. //
  641. // Description:
  642. //
  643. //
  644. // Arguments:
  645. // HMIXEROBJ hmxobj:
  646. //
  647. // UINT FAR *puMxId:
  648. //
  649. // DWORD fdwId:
  650. //
  651. // Return (MMRESULT):
  652. //
  653. // History:
  654. // 06/27/93 cjp [curtisp]
  655. //
  656. //--------------------------------------------------------------------------;
  657. MMRESULT IMixerGetID(
  658. HMIXEROBJ hmxobj,
  659. PUINT puMxId,
  660. LPMIXERLINE pmxl,
  661. DWORD fdwId
  662. )
  663. {
  664. MMRESULT mmr;
  665. MIXERLINE mxl;
  666. UINT u;
  667. V_DFLAGS(fdwId, MIXER_GETIDF_VALID, IMixerGetID, MMSYSERR_INVALFLAG);
  668. V_WPOINTER(puMxId, sizeof(UINT), MMSYSERR_INVALPARAM);
  669. //
  670. // set to '-1' which would be the mixer mapper (if there was one)
  671. // this way we will definitely fail any calls made on this id if
  672. // this function fails and the caller doesn't check his return value.
  673. //
  674. *puMxId = (UINT)-1;
  675. //
  676. //
  677. //
  678. switch (MIXER_OBJECTF_TYPEMASK & fdwId)
  679. {
  680. case MIXER_OBJECTF_MIXER:
  681. case MIXER_OBJECTF_HMIXER:
  682. {
  683. mmr = (fdwId & MIXER_OBJECTF_HANDLE) ? MMSYSERR_INVALHANDLE : MMSYSERR_BADDEVICEID;
  684. if ((UINT_PTR)hmxobj >= guTotalMixerDevs)
  685. {
  686. V_HANDLE_ACQ(hmxobj, TYPE_MIXER, mmr);
  687. *puMxId = ((PMIXERDEV)hmxobj)->uDeviceID;
  688. ReleaseHandleListResource();
  689. } else {
  690. *puMxId = PtrToUint(hmxobj);
  691. }
  692. return (MMSYSERR_NOERROR);
  693. }
  694. case MIXER_OBJECTF_HWAVEOUT:
  695. {
  696. UINT uId;
  697. DWORD dwId;
  698. mmr = waveOutGetID((HWAVEOUT)hmxobj, &uId);
  699. if (MMSYSERR_NOERROR != mmr)
  700. {
  701. return (MMSYSERR_INVALHANDLE);
  702. }
  703. if (WAVE_MAPPER == uId)
  704. {
  705. mmr = (MMRESULT)waveOutMessage((HWAVEOUT)hmxobj,
  706. WODM_MAPPER_STATUS,
  707. WAVEOUT_MAPPER_STATUS_DEVICE,
  708. (DWORD_PTR)(LPVOID)&dwId);
  709. if (MMSYSERR_NOERROR == mmr)
  710. {
  711. uId = (UINT)dwId;
  712. }
  713. }
  714. hmxobj = (HMIXEROBJ)(UINT_PTR)uId;
  715. }
  716. case MIXER_OBJECTF_WAVEOUT:
  717. {
  718. WAVEOUTCAPS woc;
  719. mmr = waveOutGetDevCaps((UINT_PTR)hmxobj, &woc, sizeof(woc));
  720. if (MMSYSERR_NOERROR != mmr)
  721. return (MMSYSERR_BADDEVICEID);
  722. woc.szPname[SIZEOF(woc.szPname) - 1] = '\0';
  723. mxl.Target.dwType = MIXERLINE_TARGETTYPE_WAVEOUT;
  724. mxl.Target.dwDeviceID = PtrToUlong(hmxobj);
  725. mxl.Target.wMid = woc.wMid;
  726. mxl.Target.wPid = woc.wPid;
  727. mxl.Target.vDriverVersion = woc.vDriverVersion;
  728. lstrcpy(mxl.Target.szPname, woc.szPname);
  729. break;
  730. }
  731. case MIXER_OBJECTF_HWAVEIN:
  732. {
  733. UINT uId;
  734. DWORD dwId;
  735. mmr = waveInGetID((HWAVEIN)hmxobj, &uId);
  736. if (MMSYSERR_NOERROR != mmr)
  737. {
  738. return (MMSYSERR_INVALHANDLE);
  739. }
  740. if (WAVE_MAPPER == uId)
  741. {
  742. mmr = (MMRESULT)waveInMessage((HWAVEIN)hmxobj,
  743. WIDM_MAPPER_STATUS,
  744. WAVEIN_MAPPER_STATUS_DEVICE,
  745. (DWORD_PTR)(LPVOID)&dwId);
  746. if (MMSYSERR_NOERROR == mmr)
  747. {
  748. uId = (UINT)dwId;
  749. }
  750. }
  751. hmxobj = (HMIXEROBJ)(UINT_PTR)uId;
  752. }
  753. case MIXER_OBJECTF_WAVEIN:
  754. {
  755. WAVEINCAPS wic;
  756. mmr = waveInGetDevCaps((UINT_PTR)hmxobj, &wic, sizeof(wic));
  757. if (MMSYSERR_NOERROR != mmr)
  758. return (MMSYSERR_BADDEVICEID);
  759. wic.szPname[SIZEOF(wic.szPname) - 1] = '\0';
  760. mxl.Target.dwType = MIXERLINE_TARGETTYPE_WAVEIN;
  761. mxl.Target.dwDeviceID = PtrToUlong(hmxobj);
  762. mxl.Target.wMid = wic.wMid;
  763. mxl.Target.wPid = wic.wPid;
  764. mxl.Target.vDriverVersion = wic.vDriverVersion;
  765. lstrcpy(mxl.Target.szPname, wic.szPname);
  766. break;
  767. }
  768. case MIXER_OBJECTF_HMIDIOUT:
  769. mmr = midiOutGetID((HMIDIOUT)hmxobj, (UINT FAR *)&hmxobj);
  770. if (MMSYSERR_NOERROR != mmr)
  771. return (MMSYSERR_INVALHANDLE);
  772. case MIXER_OBJECTF_MIDIOUT:
  773. {
  774. MIDIOUTCAPS moc;
  775. mmr = midiOutGetDevCaps((UINT_PTR)hmxobj, &moc, sizeof(moc));
  776. if (MMSYSERR_NOERROR != mmr)
  777. return (MMSYSERR_BADDEVICEID);
  778. moc.szPname[SIZEOF(moc.szPname) - 1] = '\0';
  779. mxl.Target.dwType = MIXERLINE_TARGETTYPE_MIDIOUT;
  780. mxl.Target.dwDeviceID = PtrToUlong(hmxobj);
  781. mxl.Target.wMid = moc.wMid;
  782. mxl.Target.wPid = moc.wPid;
  783. mxl.Target.vDriverVersion = moc.vDriverVersion;
  784. lstrcpy(mxl.Target.szPname, moc.szPname);
  785. break;
  786. }
  787. case MIXER_OBJECTF_HMIDIIN:
  788. mmr = midiInGetID((HMIDIIN)hmxobj, (UINT FAR *)&hmxobj);
  789. if (MMSYSERR_NOERROR != mmr)
  790. return (MMSYSERR_INVALHANDLE);
  791. case MIXER_OBJECTF_MIDIIN:
  792. {
  793. MIDIINCAPS mic;
  794. mmr = midiInGetDevCaps((UINT_PTR)hmxobj, &mic, sizeof(mic));
  795. if (MMSYSERR_NOERROR != mmr)
  796. return (MMSYSERR_BADDEVICEID);
  797. mic.szPname[SIZEOF(mic.szPname) - 1] = '\0';
  798. mxl.Target.dwType = MIXERLINE_TARGETTYPE_MIDIIN;
  799. mxl.Target.dwDeviceID = PtrToUlong(hmxobj);
  800. mxl.Target.wMid = mic.wMid;
  801. mxl.Target.wPid = mic.wPid;
  802. mxl.Target.vDriverVersion = mic.vDriverVersion;
  803. lstrcpy(mxl.Target.szPname, mic.szPname);
  804. break;
  805. }
  806. case MIXER_OBJECTF_AUX:
  807. {
  808. AUXCAPS ac;
  809. mmr = auxGetDevCaps((UINT_PTR)hmxobj, &ac, sizeof(ac));
  810. if (MMSYSERR_NOERROR != mmr)
  811. return (MMSYSERR_BADDEVICEID);
  812. ac.szPname[SIZEOF(ac.szPname) - 1] = '\0';
  813. mxl.Target.dwType = MIXERLINE_TARGETTYPE_AUX;
  814. mxl.Target.dwDeviceID = PtrToUlong(hmxobj);
  815. mxl.Target.wMid = ac.wMid;
  816. mxl.Target.wPid = ac.wPid;
  817. mxl.Target.vDriverVersion = ac.vDriverVersion;
  818. lstrcpy(mxl.Target.szPname, ac.szPname);
  819. break;
  820. }
  821. default:
  822. DebugErr1(DBF_ERROR,
  823. "mixerGetID: unknown mixer object flag (%.08lXh).",
  824. MIXER_OBJECTF_TYPEMASK & fdwId);
  825. return (MMSYSERR_INVALFLAG);
  826. }
  827. //
  828. //
  829. //
  830. //
  831. mxl.cbStruct = sizeof(mxl);
  832. mxl.dwDestination = (DWORD)-1L;
  833. mxl.dwSource = (DWORD)-1L;
  834. mxl.dwLineID = (DWORD)-1L;
  835. mxl.fdwLine = 0;
  836. mxl.dwUser = 0;
  837. mxl.dwComponentType = (DWORD)-1L;
  838. mxl.cChannels = 0;
  839. mxl.cConnections = 0;
  840. mxl.cControls = 0;
  841. mxl.szShortName[0] = '\0';
  842. mxl.szName[0] = '\0';
  843. for (u = 0; u < guTotalMixerDevs; u++)
  844. {
  845. mmr = (MMRESULT)IMixerMessageId(u,
  846. MXDM_GETLINEINFO,
  847. (DWORD_PTR)(LPVOID)&mxl,
  848. MIXER_GETLINEINFOF_TARGETTYPE);
  849. if (MMSYSERR_NOERROR == mmr)
  850. {
  851. *puMxId = u;
  852. if (NULL != pmxl)
  853. {
  854. DWORD cbStruct;
  855. cbStruct = pmxl->cbStruct;
  856. CopyMemory(pmxl, &mxl, (UINT)cbStruct);
  857. pmxl->cbStruct = cbStruct;
  858. }
  859. return (mmr);
  860. }
  861. }
  862. return (MMSYSERR_NODRIVER);
  863. } // IMixerGetID()
  864. /*--------------------------------------------------------------------------;
  865. *
  866. * @doc EXTERNAL MIXER SDK API
  867. *
  868. * @api MMRESULT | mixerOpen | The <f mixerOpen> function opens a specified
  869. * audio mixer device for use. An application must open a mixer device
  870. * if it wishes to receive notifications of mixer line and control
  871. * changes. This function also ensures that the device will not be
  872. * removed until the application closes the handle.
  873. *
  874. * @parm LPHMIXER | phmx | Points to a variable that will receive a handle
  875. * that identifies the opened audio mixer device. Use this handle to
  876. * identify the device when calling other audio mixer functions. This
  877. * argument may not be NULL. If an application wishes to query for
  878. * audio mixer support on a media device, the <f mixerGetID> function
  879. * may be used.
  880. *
  881. * @parm UINT | uMxId | Identifies the audio mixer device to open. Use a
  882. * valid device identifier or any <c HMIXEROBJ> (see <f mixerGetID> for
  883. * a description of mixer object handles). Note that there is currently
  884. * no 'mapper' for audio mixer devices, so a mixer device identifier of
  885. * '-1' is not valid.
  886. *
  887. * @parm DWORD | dwCallback | Specifies a handle to a window called when the
  888. * state of an audio mixer line and/or control associated with the
  889. * device being opened is changed. Specify zero for this argument
  890. * if no callback mechanism is to be used.
  891. *
  892. * @parm DWORD | dwInstance | This parameter is currently not used and
  893. * should be set to zero.
  894. *
  895. * @parm DWORD | fdwOpen | Specifies flags for opening the device.
  896. *
  897. * @flag CALLBACK_WINDOW | If this flag is specified, <p dwCallback> is
  898. * assumed to be a window handle.
  899. *
  900. * @flag <c MIXER_OBJECTF_MIXER> | Specifies that <p uMxId> is an audio
  901. * mixer device identifier in the range of zero to one less than the
  902. * number of devices returned by <f mixerGetNumDevs>. This flag is
  903. * optional.
  904. *
  905. * @flag <c MIXER_OBJECTF_HMIXER> | Specifies that <p uMxId> is a mixer
  906. * device handle returned by <f mixerOpen>. This flag is optional.
  907. *
  908. * @flag <c MIXER_OBJECTF_WAVEOUT> | Specifies that <p uMxId> is a
  909. * waveform output device identifier in the range of zero to one less
  910. * than the number of devices returned by <f waveOutGetNumDevs>.
  911. *
  912. * @flag <c MIXER_OBJECTF_HWAVEOUT> | Specifies that <p uMxId> is a
  913. * waveform output handle returned by <f waveOutOpen>.
  914. *
  915. * @flag <c MIXER_OBJECTF_WAVEIN> | Specifies that <p uMxId> is a
  916. * waveform input device identifier in the range of zero to one less
  917. * than the number of devices returned by <f waveInGetNumDevs>.
  918. *
  919. * @flag <c MIXER_OBJECTF_HWAVEIN> | Specifies that <p uMxId> is a
  920. * waveform input handle returned by <f midiInOpen>.
  921. *
  922. * @flag <c MIXER_OBJECTF_MIDIOUT> | Specifies that <p uMxId> is a MIDI
  923. * output device identifier in the range of zero to one less than the
  924. * number of devices returned by <f midiOutGetNumDevs>.
  925. *
  926. * @flag <c MIXER_OBJECTF_HMIDIOUT> | Specifies that <p uMxId> is a
  927. * MIDI output handle returned by <f midiOutOpen>.
  928. *
  929. * @flag <c MIXER_OBJECTF_MIDIIN> | Specifies that <p uMxId> is a MIDI
  930. * input device identifier in the range of zero to one less than the
  931. * number of devices returned by <f midiInGetNumDevs>.
  932. *
  933. * @flag <c MIXER_OBJECTF_HMIDIIN> | Specifies that <p uMxId> is a MIDI
  934. * input handle returned by <f midiInOpen>.
  935. *
  936. * @flag <c MIXER_OBJECTF_AUX> | Specifies that <p uMxId> is an
  937. * auxiliary device identifier in the range of zero to one less than the
  938. * number of devices returned by <f auxGetNumDevs>.
  939. *
  940. * @rdesc The return value is zero if the function is successful. Otherwise,
  941. * it returns a non-zero error number. Possible error returns include
  942. * the following:
  943. *
  944. * @flag <c MMSYSERR_BADDEVICEID> | The <p uMxId> argument specifies an
  945. * invalid device identifier.
  946. *
  947. * @flag <c MMSYSERR_INVALHANDLE> | The <p uMxId> argument specifies an
  948. * invalid handle.
  949. *
  950. * @flag <c MMSYSERR_INVALFLAG> | One or more flags are invalid.
  951. *
  952. * @flag <c MMSYSERR_INVALPARAM> | One or more arguments passed is
  953. * invalid.
  954. *
  955. * @flag <c MMSYSERR_NODRIVER> | No audio mixer device is available for
  956. * the object specified by <p uMxId>. Note that the location referenced
  957. * by <p uMxId> will also contain the value '-1'.
  958. *
  959. * @flag <c MMSYSERR_ALLOCATED> | The specified resource is already
  960. * allocated by the maximum number of clients possible.
  961. *
  962. * @flag <c MMSYSERR_NOMEM> | Unable to allocate resources.
  963. *
  964. * @comm Use the <f mixerGetNumDevs> function to determine the number of
  965. * audio mixer devices present in the system. The device identifier
  966. * specified by <p uMxId> varies from zero to one less than the number
  967. * of devices present.
  968. *
  969. * If a window is chosen to receive callback information, the following
  970. * messages are sent to the window procedure function to indicate when
  971. * a line or control state changes: <m MM_MIXM_LINE_CHANGE>,
  972. * <m MM_MIXM_CONTROL_CHANGE>. <p wParam> is the handle to the mixer
  973. * device. <p lParam> is the line identifier for <m MM_MIXM_LINE_CHANGE>
  974. * or the control identifier for <m MM_MIXM_CONTROL_CHANGE> that
  975. * changed state.
  976. *
  977. * @xref <f mixerClose>, <f mixerGetNumDevs>, <f mixerGetID>,
  978. * <f mixerGetLineInfo>
  979. *
  980. **/
  981. MMRESULT APIENTRY mixerOpen(
  982. LPHMIXER phmx,
  983. UINT uMxId,
  984. DWORD_PTR dwCallback,
  985. DWORD_PTR dwInstance,
  986. DWORD fdwOpen
  987. )
  988. {
  989. MMRESULT mmr;
  990. PMIXERDRV pmxdrv;
  991. UINT port;
  992. PMIXERDEV pmxdev;
  993. PMIXERDEV pmxdevRunList;
  994. MIXEROPENDESC mxod;
  995. DWORD_PTR dwDrvUser;
  996. //
  997. //
  998. //
  999. V_WPOINTER(phmx, sizeof(HMIXER), MMSYSERR_INVALPARAM);
  1000. ClientUpdatePnpInfo();
  1001. *phmx = NULL;
  1002. //
  1003. // Don't allow callback functions - they're not useful and they
  1004. // cause headaches. Specifically for Windows NT the only way
  1005. // to cause an asynchronous callback to 16-bit land from a 32-bit DLL
  1006. // is to cause an interrupt but we don't want to require mixer stuff
  1007. // to be locked down to allow for this.
  1008. //
  1009. if ((fdwOpen & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION)
  1010. {
  1011. DebugErr(DBF_ERROR, "mixerOpen: CALLBACK_FUNCTION is not supported");
  1012. return MMSYSERR_INVALFLAG;
  1013. }
  1014. V_DCALLBACK(dwCallback, HIWORD(fdwOpen & CALLBACK_TYPEMASK), MMSYSERR_INVALPARAM);
  1015. V_DFLAGS(fdwOpen, MIXER_OPENF_VALID, mixerOpen, MMSYSERR_INVALFLAG);
  1016. mmr = IMixerGetID((HMIXEROBJ)(UINT_PTR)uMxId, &uMxId, NULL, (MIXER_OBJECTF_TYPEMASK & fdwOpen));
  1017. if (MMSYSERR_NOERROR != mmr)
  1018. return (mmr);
  1019. //
  1020. //
  1021. //
  1022. //
  1023. mmr = mixerReferenceDriverById(uMxId, &pmxdrv, &port);
  1024. if (mmr)
  1025. {
  1026. return mmr;
  1027. }
  1028. #ifdef MIXER_MAPPER
  1029. //
  1030. // Default Mixer Mapper:
  1031. //
  1032. // If a mixer mapper is installed as a separate DLL then all mixer
  1033. // mapper messages are routed to it. If no mixer mapper is installed,
  1034. // simply loop through the mixer devices looking for a match.
  1035. //
  1036. if ((MIXER_MAPPER == uMxId) && (NULL == pmxdrv->drvMessage))
  1037. {
  1038. for (uMxId = 0; uMxId < guTotalMixerDevs; uMxId++)
  1039. {
  1040. // try to open it
  1041. if (MMSYSERR_NOERROR == mmr)
  1042. break;
  1043. }
  1044. mregDecUsagePtr(pmxdrv);
  1045. return (mmr);
  1046. }
  1047. #endif
  1048. //
  1049. // Get some memory for the dev structure
  1050. //
  1051. pmxdev = (PMIXERDEV)NewHandle(TYPE_MIXER, pmxdrv->cookie, sizeof(MIXERDEV));
  1052. if (NULL == pmxdev)
  1053. {
  1054. mregDecUsagePtr(pmxdrv);
  1055. return (MMSYSERR_NOMEM);
  1056. }
  1057. ENTER_MM_HANDLE(pmxdev);
  1058. SetHandleFlag(pmxdev, MMHANDLE_BUSY);
  1059. ReleaseHandleListResource();
  1060. //
  1061. // initialize our open instance struct for the client
  1062. //
  1063. pmxdev->uHandleType = TYPE_MIXER;
  1064. pmxdev->pmxdrv = pmxdrv;
  1065. pmxdev->wDevice = port;
  1066. pmxdev->uDeviceID = uMxId;
  1067. pmxdev->fdwHandle = 0;
  1068. //
  1069. // save the client's callback info
  1070. //
  1071. pmxdev->dwCallback = dwCallback;
  1072. pmxdev->dwInstance = dwInstance;
  1073. pmxdev->fdwOpen = fdwOpen;
  1074. MIXMGR_ENTER;
  1075. //
  1076. // Check to see if we already have this device open
  1077. //
  1078. for (pmxdevRunList = gpMixerDevHeader; pmxdevRunList; pmxdevRunList = pmxdevRunList->pmxdevNext)
  1079. {
  1080. if (pmxdevRunList->pmxdrv != pmxdrv) continue;
  1081. if (pmxdevRunList->wDevice != port) continue;
  1082. break;
  1083. }
  1084. //
  1085. // Have we found a match?
  1086. //
  1087. if (NULL != pmxdevRunList)
  1088. {
  1089. //
  1090. // Set the driver's dwUser to the value we got before.
  1091. //
  1092. pmxdev->dwDrvUser = pmxdevRunList->dwDrvUser;
  1093. //
  1094. // We have a match, add the caller to the devlist chain (next in
  1095. // line AFTER the one we just found).
  1096. //
  1097. pmxdev->pmxdevNext = pmxdevRunList->pmxdevNext;
  1098. pmxdevRunList->pmxdevNext = pmxdev;
  1099. ClearHandleFlag(pmxdev, MMHANDLE_BUSY);
  1100. MIXMGR_LEAVE;
  1101. LEAVE_MM_HANDLE(pmxdev);
  1102. //
  1103. // Tell the caller the good news
  1104. //
  1105. *phmx = (HMIXER)pmxdev;
  1106. //
  1107. // All done. Note we don't dec usage on pmxdrv.
  1108. //
  1109. return (MMSYSERR_NOERROR);
  1110. }
  1111. //
  1112. // If we get here, no one has the device currently open. Let's
  1113. // go open it, then.
  1114. //
  1115. //
  1116. // Load up our local MIXEROPENDESC struct
  1117. //
  1118. mxod.hmx = (HMIXER)pmxdev;
  1119. mxod.pReserved0 = (LPVOID)NULL;
  1120. mxod.dwCallback = (DWORD_PTR)MixerCallbackFunc;
  1121. mxod.dwInstance = (DWORD_PTR)uMxId;
  1122. mxod.dnDevNode = (DWORD_PTR)pmxdev->pmxdrv->cookie;
  1123. EnterCriticalSection(&pmxdrv->MixerCritSec);
  1124. mmr = (MMRESULT)((*(pmxdrv->drvMessage))(port,
  1125. MXDM_OPEN,
  1126. (DWORD_PTR)(LPDWORD)&dwDrvUser,
  1127. (DWORD_PTR)(LPVOID)&mxod,
  1128. CALLBACK_FUNCTION));
  1129. LeaveCriticalSection(&pmxdrv->MixerCritSec);
  1130. if (MMSYSERR_NOERROR != mmr)
  1131. {
  1132. // Should we do this after the MIXMGR_LEAVE???
  1133. LEAVE_MM_HANDLE(pmxdev);
  1134. MIXMGR_LEAVE;
  1135. FreeHandle((HMIXER)pmxdev);
  1136. }
  1137. else
  1138. {
  1139. MIXERCAPS mxcaps;
  1140. DWORD_PTR dwParam1, dwParam2;
  1141. MDEVICECAPSEX mdCaps;
  1142. mregIncUsagePtr(pmxdrv);
  1143. dwParam2 = (DWORD_PTR)pmxdev->pmxdrv->cookie;
  1144. if (0 == dwParam2)
  1145. {
  1146. dwParam1 = (DWORD_PTR)&mxcaps;
  1147. dwParam2 = (DWORD)sizeof(mxcaps);
  1148. }
  1149. else
  1150. {
  1151. mdCaps.cbSize = (DWORD)sizeof(mxcaps);
  1152. mdCaps.pCaps = &mxcaps;
  1153. dwParam1 = (DWORD_PTR)&mdCaps;
  1154. }
  1155. // Calling manually since we don't have the HandleList resource...
  1156. EnterCriticalSection(&pmxdrv->MixerCritSec);
  1157. (*(pmxdrv->drvMessage))(port, MXDM_GETDEVCAPS, dwDrvUser, dwParam1, dwParam2);
  1158. LeaveCriticalSection(&pmxdrv->MixerCritSec);
  1159. //
  1160. // cache some stuff for parameter validation
  1161. //
  1162. pmxdev->fdwSupport = mxcaps.fdwSupport;
  1163. pmxdev->cDestinations = mxcaps.cDestinations;
  1164. pmxdev->dwDrvUser = dwDrvUser;
  1165. *phmx = (HMIXER)pmxdev;
  1166. //
  1167. // Put this new device into the devlist chain.
  1168. //
  1169. pmxdev->pmxdevNext = gpMixerDevHeader;
  1170. gpMixerDevHeader = pmxdev;
  1171. ClearHandleFlag(pmxdev, MMHANDLE_BUSY);
  1172. LEAVE_MM_HANDLE(pmxdev);
  1173. MIXMGR_LEAVE;
  1174. }
  1175. mregDecUsagePtr(pmxdrv);
  1176. return (mmr);
  1177. } // mixerOpen()
  1178. /*--------------------------------------------------------------------------;
  1179. *
  1180. * @doc EXTERNAL MIXER SDK API
  1181. *
  1182. * @api MMRESULT | mixerClose | The <f mixerClose> function closes the
  1183. * specified audio mixer device. An application must close all mixer
  1184. * handles before exiting (or when the application is finished using
  1185. * the device).
  1186. *
  1187. * @parm <c HMIXER> | hmx | Specifies a handle to the audio mixer device.
  1188. * This handle must have been returned successfully by <f mixerOpen>. If
  1189. * <f mixerClose> is successful, <p hmx> is no longer valid.
  1190. *
  1191. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1192. * a non-zero error number. Possible error returns are:
  1193. *
  1194. * @flag <c MMSYSERR_INVALHANDLE> | Specified device handle is invalid.
  1195. *
  1196. * @xref <f mixerOpen>
  1197. *
  1198. **/
  1199. MMRESULT APIENTRY mixerClose(
  1200. HMIXER hmx
  1201. )
  1202. {
  1203. MMRESULT mmr;
  1204. PMIXERDEV pmxdev;
  1205. PMIXERDRV pmxdrv;
  1206. BOOL closemixerdriver;
  1207. ClientUpdatePnpInfo();
  1208. V_HANDLE_ACQ(hmx, TYPE_MIXER, MMSYSERR_INVALHANDLE);
  1209. ENTER_MM_HANDLE(hmx);
  1210. ReleaseHandleListResource();
  1211. if (IsHandleDeserted(hmx))
  1212. {
  1213. // This handle has been deserted. Let's just free it.
  1214. LEAVE_MM_HANDLE(hmx);
  1215. FreeHandle(hmx);
  1216. return MMSYSERR_NOERROR;
  1217. }
  1218. //
  1219. // remove the mixer handle from the linked list
  1220. //
  1221. // BUGBUG: We're removing the driver from the list BEFORE we know if
  1222. // the close is successful (for the last handle).
  1223. //
  1224. MIXMGR_ENTER;
  1225. pmxdev = (PMIXERDEV)hmx;
  1226. pmxdrv = pmxdev->pmxdrv;
  1227. if (pmxdev == gpMixerDevHeader)
  1228. {
  1229. gpMixerDevHeader = pmxdev->pmxdevNext;
  1230. }
  1231. else
  1232. {
  1233. PMIXERDEV pmxdevT;
  1234. for (pmxdevT = gpMixerDevHeader;
  1235. pmxdevT && (pmxdevT->pmxdevNext != pmxdev);
  1236. pmxdevT = pmxdevT->pmxdevNext)
  1237. ;
  1238. if (NULL == pmxdevT)
  1239. {
  1240. DebugErr1(DBF_ERROR,
  1241. "mixerClose: invalid mixer handle (%.04Xh).",
  1242. hmx);
  1243. MIXMGR_LEAVE;
  1244. LEAVE_MM_HANDLE(hmx);
  1245. return (MMSYSERR_INVALHANDLE);
  1246. }
  1247. pmxdevT->pmxdevNext = pmxdev->pmxdevNext;
  1248. }
  1249. //
  1250. // see if this is the last handle on this open instance
  1251. //
  1252. closemixerdriver = TRUE;
  1253. if (gpMixerDevHeader)
  1254. {
  1255. PMIXERDEV pmxdevT;
  1256. for (pmxdevT = gpMixerDevHeader; pmxdevT; pmxdevT = pmxdevT->pmxdevNext)
  1257. {
  1258. if (pmxdevT->pmxdrv != pmxdev->pmxdrv) continue;
  1259. if (pmxdevT->wDevice != pmxdev->wDevice) continue;
  1260. closemixerdriver = FALSE;
  1261. break;
  1262. }
  1263. }
  1264. MIXMGR_LEAVE;
  1265. // handle should be marked as "busy" even if we don't send the driver
  1266. // message.
  1267. SetHandleFlag(hmx, MMHANDLE_BUSY);
  1268. //
  1269. // if last open instance, then close it
  1270. //
  1271. mmr = MMSYSERR_NOERROR;
  1272. if (closemixerdriver)
  1273. {
  1274. EnterCriticalSection(&pmxdrv->MixerCritSec);
  1275. mmr = (MMRESULT)(*(pmxdrv->drvMessage))(pmxdev->wDevice, MXDM_CLOSE, pmxdev->dwDrvUser, 0L, 0L);
  1276. LeaveCriticalSection(&pmxdrv->MixerCritSec);
  1277. if (MMSYSERR_NOERROR != mmr)
  1278. {
  1279. // Should we put the handle back in the list???
  1280. ClearHandleFlag(hmx, MMHANDLE_BUSY);
  1281. }
  1282. }
  1283. LEAVE_MM_HANDLE(hmx);
  1284. mregDecUsagePtr(pmxdev->pmxdrv);
  1285. if (MMSYSERR_NOERROR == mmr)
  1286. {
  1287. //
  1288. // we're done with the memory block. now free the memory and return.
  1289. //
  1290. FreeHandle(hmx);
  1291. }
  1292. return (mmr);
  1293. } // mixerClose()
  1294. /*--------------------------------------------------------------------------;
  1295. *
  1296. * @doc EXTERNAL MIXER SDK API
  1297. *
  1298. * @api DWORD | mixerMessage | The <f mixerMessage> function sends a user
  1299. * defined audio mixer driver message directly to a mixer driver.
  1300. *
  1301. * @parm <c HMIXER> | hmx | Specifies a handle to an open instance of a
  1302. * mixer device. This handle is returned by <f mixerOpen>.
  1303. *
  1304. * @parm UINT | uMsg | Specifies the user defined mixer driver message to
  1305. * send to the mixer driver. This message must be above or equal to
  1306. * the <m MXDM_USER> message.
  1307. *
  1308. * @parm DWORD | dwParam1 | Contains the first argument associated with the
  1309. * message being sent.
  1310. *
  1311. * @parm DWORD | dwParam2 | Contains the second argument associated with the
  1312. * message being sent.
  1313. *
  1314. * @rdesc The return value is specific to the user defined mixer driver
  1315. * message <p uMsg> sent. However, the following return values are
  1316. * possible:
  1317. *
  1318. * @flag <c MMSYSERR_INVALHANDLE> | Specified device handle is invalid.
  1319. *
  1320. * @flag <c MMSYSERR_INVALPARAM> | <p uMsg> is not in the <m MXDM_USER>
  1321. * range.
  1322. *
  1323. * @flag <c MMSYSERR_NOTSUPPORTED> | The mixer device did not process
  1324. * the message.
  1325. *
  1326. * @comm The <f mixerMessage> function is provided to allow audio mixer
  1327. * driver specific messages to be sent to a mixer device. The messages
  1328. * that may be sent through this function must be above or equal to the
  1329. * <m MXDM_USER> message.
  1330. *
  1331. * User defined messages must only be sent to a mixer driver that
  1332. * specifically supports the messages. The caller should verify that
  1333. * the mixer driver is in fact the correct driver by getting the
  1334. * mixer capabilities and checking the <e MIXERCAPS.wMid>,
  1335. * <e MIXERCAPS.wPid>, <e MIXERCAPS.vDriverVersion> and
  1336. * <e MIXERCAPS.szPname> members of the <t MIXERCAPS> structure.
  1337. *
  1338. * It is important for an application to verify all members specified
  1339. * above due to many driver writers releasing drivers with improper
  1340. * or unregistered manufacturer and product identifiers.
  1341. *
  1342. * Never send user defined messages to an unknown audio mixer driver.
  1343. *
  1344. * @xref <f mixerOpen>, <f mixerGetDevCaps>
  1345. *
  1346. **/
  1347. DWORD APIENTRY mixerMessage(
  1348. HMIXER hmx,
  1349. UINT uMsg,
  1350. DWORD_PTR dwParam1,
  1351. DWORD_PTR dwParam2
  1352. )
  1353. {
  1354. DWORD dw;
  1355. ClientUpdatePnpInfo();
  1356. AcquireHandleListResourceShared();
  1357. if (BAD_HANDLE(hmx, TYPE_MIXER))
  1358. {
  1359. ReleaseHandleListResource();
  1360. return IMixerMessageId (PtrToUint(hmx), uMsg, dwParam1, dwParam2);
  1361. }
  1362. //
  1363. // don't allow any non-user range messages through this API
  1364. //
  1365. if (MXDM_USER > uMsg)
  1366. {
  1367. DebugErr1(DBF_ERROR, "mixerMessage: message must be in MXDM_USER range--what's this (%u)?", uMsg);
  1368. ReleaseHandleListResource();
  1369. return (MMSYSERR_INVALPARAM);
  1370. }
  1371. dw = IMixerMessageHandle(hmx, uMsg, dwParam1, dwParam2);
  1372. return (dw);
  1373. } // mixerMessage()
  1374. //--------------------------------------------------------------------------;
  1375. //
  1376. // BOOL IMixerIsValidComponentType
  1377. //
  1378. // Description:
  1379. //
  1380. //
  1381. // Arguments:
  1382. // DWORD dwComponentType:
  1383. //
  1384. // UINT uSrcDst:
  1385. //
  1386. // Return (BOOL):
  1387. //
  1388. // History:
  1389. // 10/06/93 cjp [curtisp]
  1390. //
  1391. //--------------------------------------------------------------------------;
  1392. BOOL IMixerIsValidComponentType
  1393. (
  1394. DWORD dwComponentType,
  1395. DWORD fdwLine
  1396. )
  1397. {
  1398. if (0 == (MIXERLINE_LINEF_SOURCE & fdwLine))
  1399. {
  1400. if (dwComponentType > MIXERLINE_COMPONENTTYPE_DST_LAST)
  1401. return (FALSE);
  1402. return (TRUE);
  1403. }
  1404. else
  1405. {
  1406. if (dwComponentType < MIXERLINE_COMPONENTTYPE_SRC_FIRST)
  1407. return (FALSE);
  1408. if (dwComponentType > MIXERLINE_COMPONENTTYPE_SRC_LAST)
  1409. return (FALSE);
  1410. return (TRUE);
  1411. }
  1412. } // IMixerIsValidComponentType()
  1413. /*--------------------------------------------------------------------------;
  1414. *
  1415. * @doc EXTERNAL MIXER SDK STRUCTURE
  1416. *
  1417. * @types MIXERLINE | The <t MIXERLINE> structure describes the state
  1418. * and metrics of an audio mixer device line.
  1419. *
  1420. * @syntaxex
  1421. * typedef struct tMIXERLINE
  1422. * {
  1423. * DWORD cbStruct;
  1424. * DWORD dwDestination;
  1425. * DWORD dwSource;
  1426. * DWORD dwLineID;
  1427. * DWORD fdwLine;
  1428. * DWORD dwUser;
  1429. * DWORD dwComponentType;
  1430. * DWORD cChannels;
  1431. * DWORD cConnections;
  1432. * DWORD cControls;
  1433. * char szShortName[MIXER_SHORT_NAME_CHARS];
  1434. * char szName[MIXER_LONG_NAME_CHARS];
  1435. * struct
  1436. * {
  1437. * DWORD dwType;
  1438. * DWORD dwDeviceID;
  1439. * WORD wMid;
  1440. * WORD wPid;
  1441. * MMVERSION vDriverVersion;
  1442. * char szPname[MAXPNAMELEN];
  1443. * } Target;
  1444. * } MIXERLINE;
  1445. *
  1446. * @field DWORD | cbStruct | Specifies the size, in bytes, of the
  1447. * <t MIXERLINE> structure. This member must be initialized before
  1448. * calling the <f mixerGetLineInfo> function. The size specified in this
  1449. * member must be large enough to contain the base <t MIXERLINE>
  1450. * structure. When the <f mixerGetLineInfo> function returns, this
  1451. * member contains the actual size of the information returned. The
  1452. * returned information will never exceed the requested size.
  1453. *
  1454. * @field DWORD | dwDestination | Specifies the destination line index.
  1455. * This member ranges from zero to one less than the value specified
  1456. * in the <e MIXERCAPS.cDestinations> member of the <t MIXERCAPS>
  1457. * structure retrieved by the <f mixerGetDevCaps> function. When the
  1458. * <f mixerGetLineInfo> function is called with the
  1459. * <c MIXER_GETLINEINFOF_DESTINATION> flag specified, the details for
  1460. * the destination line are returned. Note that the
  1461. * <e MIXERLINE.dwSource> member must be set to zero in this case. When
  1462. * called with the <c MIXER_GETLINEINFOF_SOURCE> flag specified, the
  1463. * details for the source given by the <e MIXERLINE.dwSource> member
  1464. * associated with the <e MIXERLINE.dwDestination> member are returned.
  1465. *
  1466. * @field DWORD | dwSource | Specifies the source line index for the source
  1467. * line associated with the <e MIXERLINE.dwDestination> member. That
  1468. * is, this member specifies the nth source line associated with the
  1469. * specified destination line. This member is not used for destination
  1470. * lines and must be set to zero when <c MIXER_GETLINEINFOF_DESTINATION>
  1471. * is specified for <f mixerGetLineInfo>. When the
  1472. * <c MIXER_GETLINEINFOF_SOURCE> flag is specified, this member ranges
  1473. * from zero to one less than the value specified in the
  1474. * <e MIXERLINE.cConnections> of the <t MIXERLINE> structure for the
  1475. * destination line given in the <e MIXERLINE.dwDestination> member.
  1476. *
  1477. * @field DWORD | dwLineID | Specifies an audio mixer defined identifier
  1478. * that uniquely refers to the line described by the <t MIXERLINE>
  1479. * structure. This identifier is unique only to a single mixer device
  1480. * and may be of any format that the mixer device wishes. An application
  1481. * should only use this identifier as an abstract handle. No two
  1482. * lines for a single mixer device will have the same line identifier
  1483. * under any circumstances.
  1484. *
  1485. * @field DWORD | fdwLine | Specifies status and support flags for the
  1486. * audio mixer line. This member is always returned to the application
  1487. * and requires no initialization.
  1488. *
  1489. * @flag <c MIXERLINE_LINEF_SOURCE> | Specifies that this audio mixer
  1490. * line is a source line associated with a single destination line. If
  1491. * this flag is not set, then this line is a destination line associated
  1492. * with zero or more source lines.
  1493. *
  1494. * @flag <c MIXERLINE_LINEF_DISCONNECTED> | Specifies that this audio
  1495. * mixer line is disconnected. A disconnected line's associated controls
  1496. * can still be modified but the changes will have no effect until the
  1497. * line becomes connected. An application may want to modify its
  1498. * behavior if a mixer line is disconnected.
  1499. *
  1500. * @flag <c MIXERLINE_LINEF_ACTIVE> | Specifies that this audio mixer
  1501. * line is active. An active line specifies that a signal is (probably)
  1502. * passing through the line. For example, if a waveform output device
  1503. * is not in use by an application, then the line associated with that
  1504. * device would not be active (the <c MIXERLINE_LINEF_ACTIVE> flag would
  1505. * not be set). If the waveform output device is opened, then the
  1506. * the line is considered active and the <c MIXERLINE_LINEF_ACTIVE> flag
  1507. * will be set. Note that a 'paused' or 'starved' waveform output device
  1508. * is still considered active. In other words, if the waveform output
  1509. * device is opened by an application regardless of whether data is
  1510. * being played, the associated line is considered active. If a line
  1511. * cannot be strictly defined as 'active' verses 'inactive', then the
  1512. * audio mixer device will always set the <c MIXERLINE_LINEF_ACTIVE>
  1513. * flag. An example of where this information can be used by an
  1514. * application is displaying a 'peak meter.' Peak meters are polled
  1515. * meters. An application may want to disable its polling timer while
  1516. * the line is inactive to improve system performance. Note that the
  1517. * <c MIXERLINE_LINEF_ACTIVE> flag is also affected by the status of
  1518. * the mixer line's mute control. Muted mixer lines are never active.
  1519. *
  1520. * @field DWORD | dwUser | Specifies 32-bits of audio mixer device defined
  1521. * instance data for the line. This member is intended for custom
  1522. * audio mixer applications designed specifically for the mixer device
  1523. * returning this information. An application that is not specifically
  1524. * tailored to understand this member should simply ignore this data.
  1525. *
  1526. * @field DWORD | dwComponentType | Specifies the component type for this
  1527. * line. An application may use this information to display tailored
  1528. * graphics or search for a particular component. If an application
  1529. * does not know about a component type, then this member should be
  1530. * ignored. Currently, this member may be one of the following values:
  1531. *
  1532. * @flag <c MIXERLINE_COMPONENTTYPE_DST_UNDEFINED> | Specifies that the
  1533. * line is a destination that cannot be defined by one of the standard
  1534. * component types. An audio mixer device is required to use this
  1535. * component type for line component types that have not been defined
  1536. * by Microsoft.
  1537. *
  1538. * @flag <c MIXERLINE_COMPONENTTYPE_DST_DIGITAL> | Specifies that the
  1539. * line is a digital destination (for example, digital input to a DAT
  1540. * or CD Audio Disc).
  1541. *
  1542. * @flag <c MIXERLINE_COMPONENTTYPE_DST_LINE> | Specifies that the line
  1543. * is a line level destination (for example, line level input from
  1544. * a CD Audio Disc) that will be the final recording source for the
  1545. * ADC. Most audio cards for the PC provide some sort of gain for the
  1546. * recording source line, so the mixer device will use the
  1547. * <c MIXERLINE_COMPONENTTYPE_DST_WAVEIN> type.
  1548. *
  1549. * @flag <c MIXERLINE_COMPONENTTYPE_DST_MONITOR> | Specifies that the
  1550. * line is a destination used for a monitor.
  1551. *
  1552. * @flag <c MIXERLINE_COMPONENTTYPE_DST_SPEAKERS> | Specifies that the
  1553. * line is an adjustable (gain and/or attenuation) destination intended
  1554. * to drive speakers. This is the normal component type for the audio
  1555. * output of most audio cards for the PC.
  1556. *
  1557. * @flag <c MIXERLINE_COMPONENTTYPE_DST_HEADPHONES> | Specifies that the
  1558. * line is an adjustable (gain and/or attenuation) destination intended
  1559. * to driver headphones. Most audio cards use the same destination
  1560. * line for speakers and headphones--in which case the mixer device
  1561. * will simply use the <c MIXERLINE_COMPONENTTYPE_DST_SPEAKERS> type.
  1562. *
  1563. * @flag <c MIXERLINE_COMPONENTTYPE_DST_TELEPHONE> | Specifies that the
  1564. * line is a destination that will be routed to the telephone line.
  1565. *
  1566. * @flag <c MIXERLINE_COMPONENTTYPE_DST_WAVEIN> | Specifies that the
  1567. * line is a destination that will be the final recording source for the
  1568. * waveform input (ADC). This line will normally provide some sort of
  1569. * gain or attenuation. This is the normal component type for the
  1570. * recording line of most audio cards for the PC.
  1571. *
  1572. * @flag <c MIXERLINE_COMPONENTTYPE_DST_VOICEIN> | Specifies that the
  1573. * line is a destination that will be the final recording source for
  1574. * voice input. This component type is exactly like
  1575. * <c MIXERLINE_COMPONENTTYPE_DST_WAVEIN> but is intended specifically
  1576. * for settings used during voice recording/recognition. This line
  1577. * is entirely optional for a mixer device to support--many mixer
  1578. * devices may only provide <c MIXERLINE_COMPONENTTYPE_DST_WAVEIN>.
  1579. *
  1580. *
  1581. * @flag <c MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED> | Specifies that the
  1582. * line is a source that cannot be defined by one of the standard
  1583. * component types. An audio mixer device is required to use this
  1584. * component type for line component types that have not been defined
  1585. * by Microsoft.
  1586. *
  1587. * @flag <c MIXERLINE_COMPONENTTYPE_SRC_DIGITAL> | Specifies that the
  1588. * line is a digital source (for example, digital output from a DAT or
  1589. * CD Audio Disc).
  1590. *
  1591. * @flag <c MIXERLINE_COMPONENTTYPE_SRC_LINE> | Specifies that the line
  1592. * is a line level source (for example, line level input from
  1593. * an external stereo) that will be used as a, perhaps, optional source
  1594. * for recording. Most audio cards for the PC provide some sort of gain
  1595. * for the recording source line, so the mixer device will use the
  1596. * <c MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY> type.
  1597. *
  1598. * @flag <c MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE> | Specifies that the
  1599. * line is a microphone recording source. Most audio cards for the
  1600. * PC provide at least two types of recording sources: an auxiliary
  1601. * line and microphone input. A microphone line normally provides
  1602. * some sort of gain. Audio cards that use a single input for use
  1603. * with a microphone or auxiliary line should use the
  1604. * <c MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE> component type.
  1605. *
  1606. * @flag <c MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER> | Specifies that
  1607. * the line is a source originating from the output of an internal
  1608. * synthesizer. Most audio cards for the PC provide some sort of
  1609. * MIDI synthesizer (for example, an Ad Lib compatible or OPL/3 FM
  1610. * synthesizer).
  1611. *
  1612. * @flag <c MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC> | Specifies that
  1613. * the line is a source originating from the output of an internal audio
  1614. * compact disc. This component type is provided for those audio cards
  1615. * that provide a source line solely intended to be connected to an
  1616. * audio compact disc (or CD-ROM playing a Redbook Audio CD).
  1617. *
  1618. * @flag <c MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE> | Specifies that the
  1619. * line is a source originating from an incoming telephone line.
  1620. *
  1621. * @flag <c MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER> | Specifies that the
  1622. * line is a source originating from the PC speaker. Several audio cards
  1623. * for the PC provide the ability to mix what would normally be played
  1624. * on the internal speaker with the output of an audio card. The
  1625. * ability to use this output as a source for recording has also been
  1626. * exploited by some audio cards.
  1627. *
  1628. * @flag <c MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT> | Specifies that the
  1629. * line is a source originating from the waveform output (DAC). Most
  1630. * cards for the PC provide this component type as a source to the
  1631. * <c MIXERLINE_COMPONENTTYPE_DST_SPEAKERS> destination. Some cards will
  1632. * also allow this source to be routed to the
  1633. * <c MIXERLINE_COMPONENTTYPE_DST_WAVEIN> destination.
  1634. *
  1635. * @flag <c MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY> | Specifies that the
  1636. * line is a source originating from the auxiliary line. This line type
  1637. * is intended as a source with gain or attenuation that can be routed
  1638. * to the <c MIXERLINE_COMPONENTTYPE_DST_SPEAKERS> destination and/or
  1639. * recorded from through the <c MIXERLINE_COMPONENTTYPE_DST_WAVEIN>
  1640. * destination.
  1641. *
  1642. * @flag <c MIXERLINE_COMPONENTTYPE_SRC_ANALOG> | Specifies that the
  1643. * line is a source originating from one or more lines. This line type
  1644. * is intended for audio mixers that can mix multiple lines into a
  1645. * single source for that can be routed to the
  1646. * <c MIXERLINE_COMPONENTTYPE_DST_SPEAKERS> destination and/or
  1647. * recorded from through the <c MIXERLINE_COMPONENTTYPE_DST_WAVEIN>
  1648. * destination.
  1649. *
  1650. * @field DWORD | cChannels | Specifies the maximum number of separate
  1651. * channels that can be manipulated independantly for the line. Most
  1652. * of the modern audio cards for the PC are stereo devices, so this
  1653. * member will be two. Channel one is assumed to be the left channel;
  1654. * channel two is assumed to be the right channel. Note that a
  1655. * multi-channel line may have one or more uniform controls (controls
  1656. * that affect all channels of a line uniformly) associated with it.
  1657. * An example of a uniform control is a Mute that mutes all channels
  1658. * of a line simultaneously. A line must have at least one channel--
  1659. * this member will never be zero.
  1660. *
  1661. * @field DWORD | cConnections | Specifies the number of connections that
  1662. * are associated with the line. Currently, this member is used only
  1663. * for destination lines and specifies the number of source lines
  1664. * that are associated with it. This number may be zero. For source
  1665. * lines, this member is always zero.
  1666. *
  1667. * @field DWORD | cControls | Specifies the number of controls associated
  1668. * with the line. This value may be zero. If no controls are associated
  1669. * with the line, then the line is probably (but not always) just a
  1670. * source that may be selected in a MUX or Mixer but allows no
  1671. * manipulation of the signal. For example, a digital source may have
  1672. * this attribute.
  1673. *
  1674. * @field char | szShortName[<c MIXER_SHORT_NAME_CHARS>] | Specifies a short
  1675. * string that describes the <e MIXERLINE.dwLineID> audio mixer line.
  1676. * This description is appropriate for using as a displayable label for
  1677. * the line that can fit in small spaces.
  1678. *
  1679. * @field char | szName[<c MIXER_LONG_NAME_CHARS>] | Specifies a string
  1680. * that describes the <e MIXERLINE.dwLineID> audio mixer line. This
  1681. * description is appropriate for using as a displayable description
  1682. * for the line that is not limited by screen space.
  1683. *
  1684. * @field struct | Target | Contains the target media information.
  1685. *
  1686. * @field2 DWORD | dwType | Specifies the target media device type
  1687. * associated with the audio mixer line described in the <t MIXERLINE>
  1688. * structure. An application must ignore target information for media
  1689. * device types that it does not understand. Currently, this member may
  1690. * be one of the following:
  1691. *
  1692. * @flag <c MIXERLINE_TARGETTYPE_UNDEFINED> | Specifies that the line
  1693. * described by this <t MIXERLINE> structure is not strictly bound
  1694. * to a defined media type. All remaining <e MIXERLINE.Target> structure
  1695. * members of the <t MIXERLINE> structure should be ignored. Note that
  1696. * an application may not use the <c MIXERLINE_TARGETTYPE_UNDEFINED>
  1697. * target type when calling the <f mixerGetLineInfo> function with the
  1698. * <c MIXER_GETLINEINFOF_TARGETTYPE> flag.
  1699. *
  1700. * @flag <c MIXERLINE_TARGETTYPE_WAVEOUT> | Specifies that the line
  1701. * described by this <t MIXERLINE> structure is strictly bound to
  1702. * the waveform output device detailed in the remaining members of
  1703. * the <e MIXERLINE.Target> structure member of the <t MIXERLINE>
  1704. * structure.
  1705. *
  1706. * @flag <c MIXERLINE_TARGETTYPE_WAVEIN> | Specifies that the line
  1707. * described by this <t MIXERLINE> structure is strictly bound to
  1708. * the waveform input device detailed in the remaining members of
  1709. * the <e MIXERLINE.Target> structure member of the <t MIXERLINE>
  1710. * structure.
  1711. *
  1712. * @flag <c MIXERLINE_TARGETTYPE_MIDIOUT> | Specifies that the line
  1713. * described by this <t MIXERLINE> structure is strictly bound to
  1714. * the MIDI output device detailed in the remaining members of
  1715. * the <e MIXERLINE.Target> structure member of the <t MIXERLINE>
  1716. * structure.
  1717. *
  1718. * @flag <c MIXERLINE_TARGETTYPE_MIDIIN> | Specifies that the line
  1719. * described by this <t MIXERLINE> structure is strictly bound to
  1720. * the MIDI input device detailed in the remaining members of
  1721. * the <e MIXERLINE.Target> structure member of the <t MIXERLINE>
  1722. * structure.
  1723. *
  1724. * @flag <c MIXERLINE_TARGETTYPE_AUX> | Specifies that the line
  1725. * described by this <t MIXERLINE> structure is strictly bound to
  1726. * the auxiliary device detailed in the remaining members of
  1727. * the <e MIXERLINE.Target> structure member of the <t MIXERLINE>
  1728. * structure.
  1729. *
  1730. * @field2 DWORD | dwDeviceID | In the case of the
  1731. * <e MIXERLINE.dwType> member being a target type other than
  1732. * <c MIXERLINE_TARGETTYPE_UNDEFINED>, this member is the current device
  1733. * identifier of the target media device. This identifier is identical
  1734. * to the current media device index of the associated media device.
  1735. * Note that when calling the <f mixerGetLineInfo> function with
  1736. * the <c MIXER_GETLINEINFOF_TARGETTYPE> flag, this member is ignored on
  1737. * input and will be returned to the caller by the audio mixer manager.
  1738. *
  1739. * @field2 WORD | wMid | In the case of the <e MIXERLINE.dwType>
  1740. * member being a target type other than <c MIXERLINE_TARGETTYPE_UNDEFINED>,
  1741. * this member is the manufacturer identifier of the target media device.
  1742. * This identifier is identical to the wMid member of the associated
  1743. * media device capabilities structure.
  1744. *
  1745. * @field WORD | wPid | In the case of the <e MIXERLINE.dwType>
  1746. * member being a target type other than <c MIXERLINE_TARGETTYPE_UNDEFINED>,
  1747. * this member is the product identifier of the target media device.
  1748. * This identifier is identical to the wPid member of the associated
  1749. * media device capabilities structure.
  1750. *
  1751. * @field2 MMVERSION | vDriverVersion | In the case of the
  1752. * <e MIXERLINE.dwType> member being a target type other than
  1753. * <c MIXERLINE_TARGETTYPE_UNDEFINED>, this member is the driver version
  1754. * of the target media device. This version is identical to the
  1755. * vDriverVersion member of the associated media device capabilities
  1756. * structure.
  1757. *
  1758. * @field char | szPname[MAXPNAMELEN] | In the case of the
  1759. * <e MIXERLINE.dwType> member being a target type other than
  1760. * <c MIXERLINE_TARGETTYPE_UNDEFINED>, this member is the product
  1761. * name of the target media device. This name is identical to the
  1762. * szPname member of the associated media device capabilities structure.
  1763. *
  1764. * @tagname tMIXERLINE
  1765. *
  1766. * @othertype MIXERLINE FAR * | LPMIXERLINE | A pointer to a <t MIXERLINE>
  1767. * structure.
  1768. *
  1769. * @othertype MIXERLINE * | PMIXERLINE | A pointer to a <t MIXERLINE>
  1770. * structure.
  1771. *
  1772. * @xref <f mixerGetLineInfo>, <f mixerGetDevCaps>
  1773. *
  1774. **/
  1775. /*--------------------------------------------------------------------------;
  1776. *
  1777. * @doc EXTERNAL MIXER SDK API
  1778. *
  1779. * @api MMRESULT | mixerGetLineInfo | The <f mixerGetLineInfo> function
  1780. * retrieves information about a specified audio mixer devices 'line'.
  1781. *
  1782. * @parm <c HMIXEROBJ> | hmxobj | Specifies a handle to the audio mixer
  1783. * device object to get line information from.
  1784. *
  1785. * @parm LPMIXERLINE | pmxl | Points to a <t MIXERLINE> structure. This
  1786. * structure is filled with information about the mixer line for the
  1787. * audio mixer device. See the comments for each query flag passed
  1788. * through <p fdwInfo> for details on what members of the <t MIXERLINE>
  1789. * structure must be initialized before calling <f mixerGetLineInfo>.
  1790. * Note that in all cases, <e MIXERLINE.cbStruct> must be initialized
  1791. * to be the size, in bytes, of the <t MIXERLINE> structure.
  1792. *
  1793. * @parm DWORD | fdwInfo | Specifies flags for getting information on a
  1794. * mixer line.
  1795. *
  1796. * @flag <c MIXER_GETLINEINFOF_DESTINATION> | If this flag is specified,
  1797. * <p pmxl> is to receive information on the destination line
  1798. * specified by the <e MIXERLINE.dwDestination> member of the
  1799. * <t MIXERLINE> structure. This index ranges from zero to one less
  1800. * than <e MIXERCAPS.cDestinations> of the <t MIXERCAPS> structure.
  1801. * All remaining structure members except <e MIXERLINE.cbStruct> require
  1802. * no further initialization.
  1803. *
  1804. * @flag <c MIXER_GETLINEINFOF_SOURCE> | If this flag is specified,
  1805. * <p pmxl> is to receive information on the source line specified by
  1806. * the <e MIXERLINE.dwDestination> and <e MIXERLINE.dwSource> members
  1807. * of the <t MIXERLINE> structure. The index specified by
  1808. * <e MIXERLINE.dwDestination> ranges from zero to one less than
  1809. * <e MIXERCAPS.cDestinations> of the <t MIXERCAPS> structure. The
  1810. * index specified by for <e MIXERLINE.dwSource> ranges from
  1811. * zero to one less than the <e MIXERLINE.cConnections> member of the
  1812. * <t MIXERLINE> structure returned for the <e MIXERLINE.dwDestination>
  1813. * line. All remaining structure members except <e MIXERLINE.cbStruct>
  1814. * require no further initialization.
  1815. *
  1816. * @flag <c MIXER_GETLINEINFOF_LINEID> | If this flag is specified,
  1817. * <p pmxl> is to receive information on the line specified by the
  1818. * <e MIXERLINE.dwLineID> member of the <t MIXERLINE> structure. This
  1819. * is usually used to retrieve updated information on a line's state.
  1820. * All remaining structure members except <e MIXERLINE.cbStruct> require
  1821. * no further initialization.
  1822. *
  1823. * @flag <c MIXER_GETLINEINFOF_COMPONENTTYPE> | If this flag is
  1824. * specified, <p pmxl> is to receive information on the first line of
  1825. * the type specified in the <e MIXERLINE.dwComponentType> member of the
  1826. * <t MIXERLINE> structure. This is used to retrieve information
  1827. * on a line that is of a specific component type (for example, an
  1828. * application could specify <c MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE>
  1829. * to retrieve information on the first Microphone input associated
  1830. * with the specified <p hmxobj>). All remaining structure members
  1831. * except <e MIXERLINE.cbStruct> require no further initialization.
  1832. *
  1833. * @flag <c MIXER_GETLINEINFOF_TARGETTYPE> | If this flag is specified,
  1834. * <p pmxl> is to receive information on the line that is for the
  1835. * <e MIXERLINE.dwType> of the <t MIXERLINE> structure. This is
  1836. * used to retrieve information on a line that handles the target
  1837. * type (<c MIXERLINE_TARGETTYPE_WAVEOUT> for example). An application
  1838. * must initialize <e MIXERLINE.dwType>, <e MIXERLINE.wMid>,
  1839. * <e MIXERLINE.wPid>, <e MIXERLINE.vDriverVersion> and
  1840. * <e MIXERLINE.szPname> of the <t MIXERLINE> structure before
  1841. * calling <f mixerGetLineInfo>. All of these values can be retrieved
  1842. * from the device capabilities structures for all media devices. All
  1843. * remaining structure members except <e MIXERLINE.cbStruct> require
  1844. * no further initialization.
  1845. *
  1846. * @flag <c MIXER_OBJECTF_MIXER> | Specifies that <p hmxobj> is an audio
  1847. * mixer device identifier in the range of zero to one less than the
  1848. * number of devices returned by <f mixerGetNumDevs>. This flag is
  1849. * optional.
  1850. *
  1851. * @flag <c MIXER_OBJECTF_HMIXER> | Specifies that <p hmxobj> is a mixer
  1852. * device handle returned by <f mixerOpen>. This flag is optional.
  1853. *
  1854. * @flag <c MIXER_OBJECTF_WAVEOUT> | Specifies that <p hmxobj> is a
  1855. * waveform output device identifier in the range of zero to one less
  1856. * than the number of devices returned by <f waveOutGetNumDevs>.
  1857. *
  1858. * @flag <c MIXER_OBJECTF_HWAVEOUT> | Specifies that <p hmxobj> is a
  1859. * waveform output handle returned by <f waveOutOpen>.
  1860. *
  1861. * @flag <c MIXER_OBJECTF_WAVEIN> | Specifies that <p hmxobj> is a
  1862. * waveform input device identifier in the range of zero to one less
  1863. * than the number of devices returned by <f waveInGetNumDevs>.
  1864. *
  1865. * @flag <c MIXER_OBJECTF_HWAVEIN> | Specifies that <p hmxobj> is a
  1866. * waveform input handle returned by <f midiInOpen>.
  1867. *
  1868. * @flag <c MIXER_OBJECTF_MIDIOUT> | Specifies that <p hmxobj> is a MIDI
  1869. * output device identifier in the range of zero to one less than the
  1870. * number of devices returned by <f midiOutGetNumDevs>.
  1871. *
  1872. * @flag <c MIXER_OBJECTF_HMIDIOUT> | Specifies that <p hmxobj> is a
  1873. * MIDI output handle returned by <f midiOutOpen>.
  1874. *
  1875. * @flag <c MIXER_OBJECTF_MIDIIN> | Specifies that <p hmxobj> is a MIDI
  1876. * input device identifier in the range of zero to one less than the
  1877. * number of devices returned by <f midiInGetNumDevs>.
  1878. *
  1879. * @flag <c MIXER_OBJECTF_HMIDIIN> | Specifies that <p hmxobj> is a MIDI
  1880. * input handle returned by <f midiInOpen>.
  1881. *
  1882. * @flag <c MIXER_OBJECTF_AUX> | Specifies that <p hmxobj> is an
  1883. * auxiliary device identifier in the range of zero to one less than the
  1884. * number of devices returned by <f auxGetNumDevs>.
  1885. *
  1886. * @rdesc The return value is zero if the function is successful. Otherwise,
  1887. * it returns a non-zero error number. Possible error returns include
  1888. * the following:
  1889. *
  1890. * @flag <c MMSYSERR_BADDEVICEID> | The <p hmxobj> argument specifies an
  1891. * invalid device identifier.
  1892. *
  1893. * @flag <c MMSYSERR_INVALHANDLE> | The <p hmxobj> argument specifies an
  1894. * invalid handle.
  1895. *
  1896. * @flag <c MMSYSERR_INVALFLAG> | One or more flags are invalid.
  1897. *
  1898. * @flag <c MMSYSERR_INVALPARAM> | One or more arguments passed is
  1899. * invalid.
  1900. *
  1901. * @flag <c MMSYSERR_NODRIVER> | No audio mixer device is available for
  1902. * the object specified by <p hmxobj>.
  1903. *
  1904. * @flag <c MIXERR_INVALLINE> | The audio mixer device line reference is
  1905. * invalid.
  1906. *
  1907. * @xref <t MIXERLINE>, <f mixerOpen>, <f mixerGetDevCaps>, <t MIXERCAPS>,
  1908. * <f mixerGetLineControls>
  1909. *
  1910. **/
  1911. MMRESULT APIENTRY mixerGetLineInfoA(
  1912. HMIXEROBJ hmxobj,
  1913. LPMIXERLINEA pmxlA,
  1914. DWORD fdwInfo
  1915. )
  1916. {
  1917. MIXERLINEW mxlW;
  1918. MMRESULT mmr;
  1919. //
  1920. // Validate the mixer line info pointer
  1921. //
  1922. V_WPOINTER(pmxlA, sizeof(DWORD), MMSYSERR_INVALPARAM);
  1923. if (pmxlA->cbStruct < sizeof(MIXERLINEA)) {
  1924. return MMSYSERR_INVALPARAM;
  1925. }
  1926. V_WPOINTER(pmxlA, pmxlA->cbStruct, MMSYSERR_INVALPARAM);
  1927. //
  1928. // Call the UNICODE version to get the full set of data
  1929. //
  1930. CopyMemory((PVOID)&mxlW, (PVOID)pmxlA, FIELD_OFFSET(MIXERLINE, cChannels));
  1931. mxlW.cbStruct = sizeof(mxlW);
  1932. //
  1933. // If target stuff wanted we must set the target data
  1934. //
  1935. if ((fdwInfo & MIXER_GETLINEINFOF_QUERYMASK) ==
  1936. MIXER_GETLINEINFOF_TARGETTYPE) {
  1937. CopyMemory((PVOID)&mxlW.Target.dwType, (PVOID)&pmxlA->Target.dwType,
  1938. FIELD_OFFSET(MIXERLINE, Target.szPname[0]) -
  1939. FIELD_OFFSET(MIXERLINE, Target.dwType));
  1940. Imbstowcs(mxlW.Target.szPname, pmxlA->Target.szPname, MAXPNAMELEN);
  1941. }
  1942. //
  1943. // Set the relevant values
  1944. //
  1945. mmr = mixerGetLineInfo(hmxobj, &mxlW, fdwInfo);
  1946. if (mmr != MMSYSERR_NOERROR) {
  1947. return mmr;
  1948. }
  1949. //
  1950. // Massage the return data to ASCII
  1951. //
  1952. ConvertMIXERLINEWToMIXERLINEA(pmxlA, &mxlW);
  1953. return mmr;
  1954. } // mixerGetLineInfoA()
  1955. MMRESULT APIENTRY mixerGetLineInfo(
  1956. HMIXEROBJ hmxobj,
  1957. LPMIXERLINE pmxl,
  1958. DWORD fdwInfo
  1959. )
  1960. {
  1961. DWORD fdwMxObjType;
  1962. MMRESULT mmr;
  1963. PMIXERDEV pmxdev;
  1964. // UINT cb;
  1965. UINT uMxId;
  1966. BOOL fSourceLine, fResource;
  1967. V_DFLAGS(fdwInfo, MIXER_GETLINEINFOF_VALID, mixerGetLineInfo, MMSYSERR_INVALFLAG);
  1968. V_WPOINTER(pmxl, sizeof(DWORD), MMSYSERR_INVALPARAM);
  1969. if (sizeof(MIXERLINE) > pmxl->cbStruct)
  1970. {
  1971. DebugErr1(DBF_ERROR, "mixerGetLineInfo: structure size too small or cbStruct not initialized (%lu).", pmxl->cbStruct);
  1972. return (MMSYSERR_INVALPARAM);
  1973. }
  1974. V_WPOINTER(pmxl, pmxl->cbStruct, MMSYSERR_INVALPARAM);
  1975. ClientUpdatePnpInfo();
  1976. //
  1977. //
  1978. //
  1979. fSourceLine = FALSE;
  1980. switch (fdwInfo & MIXER_GETLINEINFOF_QUERYMASK)
  1981. {
  1982. case MIXER_GETLINEINFOF_DESTINATION:
  1983. pmxl->dwSource = (DWORD)-1L;
  1984. pmxl->dwLineID = (DWORD)-1L;
  1985. pmxl->dwComponentType = (DWORD)-1L;
  1986. break;
  1987. case MIXER_GETLINEINFOF_SOURCE:
  1988. fSourceLine = TRUE;
  1989. pmxl->dwLineID = (DWORD)-1L;
  1990. pmxl->dwComponentType = (DWORD)-1L;
  1991. break;
  1992. case MIXER_GETLINEINFOF_LINEID:
  1993. pmxl->dwSource = (DWORD)-1L;
  1994. pmxl->dwDestination = (DWORD)-1L;
  1995. pmxl->dwComponentType = (DWORD)-1L;
  1996. break;
  1997. case MIXER_GETLINEINFOF_COMPONENTTYPE:
  1998. pmxl->dwSource = (DWORD)-1L;
  1999. pmxl->dwDestination = (DWORD)-1L;
  2000. pmxl->dwLineID = (DWORD)-1L;
  2001. if (!IMixerIsValidComponentType(pmxl->dwComponentType, 0) &&
  2002. !IMixerIsValidComponentType(pmxl->dwComponentType, MIXERLINE_LINEF_SOURCE))
  2003. {
  2004. DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid dwComponentType (%lu).", pmxl->dwComponentType);
  2005. return (MMSYSERR_INVALPARAM);
  2006. }
  2007. break;
  2008. case MIXER_GETLINEINFOF_TARGETTYPE:
  2009. pmxl->dwSource = (DWORD)-1L;
  2010. pmxl->dwDestination = (DWORD)-1L;
  2011. pmxl->dwLineID = (DWORD)-1L;
  2012. pmxl->dwComponentType = (DWORD)-1L;
  2013. if (MIXERLINE_TARGETTYPE_AUX < pmxl->Target.dwType)
  2014. {
  2015. DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid Target.dwType (%lu).", pmxl->Target.dwType);
  2016. return (MMSYSERR_INVALPARAM);
  2017. }
  2018. break;
  2019. default:
  2020. DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid query flag (%.08lXh).",
  2021. fdwInfo & MIXER_GETLINEINFOF_QUERYMASK);
  2022. return (MMSYSERR_INVALFLAG);
  2023. }
  2024. //
  2025. //
  2026. //
  2027. fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwInfo);
  2028. fResource = FALSE;
  2029. AcquireHandleListResourceShared();
  2030. // Checking for the type of mixer object. If it is a non-mixer type
  2031. // calling IMixerMesssageID (called by IMixerGetID) with the shared
  2032. // resource will deadlock.
  2033. if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
  2034. (MIXER_OBJECTF_HMIXER == fdwMxObjType))
  2035. {
  2036. if (BAD_HANDLE(hmxobj, TYPE_MIXER))
  2037. {
  2038. ReleaseHandleListResource();
  2039. }
  2040. else
  2041. {
  2042. fResource = TRUE;
  2043. }
  2044. }
  2045. else
  2046. {
  2047. ReleaseHandleListResource();
  2048. }
  2049. mmr = IMixerGetID(hmxobj, &uMxId, pmxl, fdwMxObjType);
  2050. if (MMSYSERR_NOERROR != mmr)
  2051. {
  2052. dprintf(( "!IMixerGetLineInfo: IMixerGetID() failed!" ));
  2053. if (fResource)
  2054. ReleaseHandleListResource();
  2055. return (mmr);
  2056. }
  2057. if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
  2058. (MIXER_OBJECTF_HMIXER == fdwMxObjType))
  2059. {
  2060. //
  2061. // if a mixer device id was passed, then null hmx so we use the
  2062. // correct message sender below
  2063. //
  2064. if ((UINT_PTR)hmxobj == uMxId)
  2065. hmxobj = NULL;
  2066. }
  2067. else
  2068. {
  2069. return (MMSYSERR_NOERROR);
  2070. }
  2071. //
  2072. // clear all fields before calling driver
  2073. //
  2074. if (NULL != hmxobj)
  2075. {
  2076. //
  2077. //
  2078. //
  2079. pmxdev = (PMIXERDEV)hmxobj;
  2080. #if 0
  2081. if (pmxdev->cDestinations <= pmxl->dwDestination)
  2082. {
  2083. ReleaseHandleListResource();
  2084. DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid destination index (%lu).", pmxl->dwDestination);
  2085. return (MMSYSERR_INVALPARAM);
  2086. }
  2087. #endif
  2088. mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj,
  2089. MXDM_GETLINEINFO,
  2090. (DWORD_PTR)(LPVOID)pmxl,
  2091. fdwInfo);
  2092. }
  2093. else
  2094. {
  2095. #pragma message("----IMixerGetLineInfo: dwDestination not validated for ID's!!")
  2096. mmr = (MMRESULT)IMixerMessageId(uMxId,
  2097. MXDM_GETLINEINFO,
  2098. (DWORD_PTR)(LPVOID)pmxl,
  2099. fdwInfo);
  2100. }
  2101. if (MMSYSERR_NOERROR != mmr)
  2102. return (mmr);
  2103. #pragma message("----IMixerGetLineInfo: should validate mixer driver didn't hose us!")
  2104. //
  2105. // validate the driver's returned stuff...
  2106. //
  2107. //
  2108. if (sizeof(MIXERLINE) != pmxl->cbStruct)
  2109. {
  2110. DebugErr1(DBF_ERROR, "mixerGetLineInfo: buggy driver returned invalid cbStruct (%lu).", pmxl->cbStruct);
  2111. pmxl->cbStruct = sizeof(MIXERLINE);
  2112. }
  2113. if ((DWORD)-1L == pmxl->dwDestination)
  2114. {
  2115. DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to init dwDestination member.");
  2116. }
  2117. if (fSourceLine)
  2118. {
  2119. if (0 == (MIXERLINE_LINEF_SOURCE & pmxl->fdwLine))
  2120. {
  2121. DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to set MIXERLINE_LINEF_SOURCE.");
  2122. pmxl->fdwLine |= MIXERLINE_LINEF_SOURCE;
  2123. }
  2124. if ((DWORD)-1L == pmxl->dwSource)
  2125. {
  2126. DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to init dwSource member.");
  2127. }
  2128. }
  2129. if ((DWORD)-1L == pmxl->dwLineID)
  2130. {
  2131. DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to init dwLineID member.");
  2132. }
  2133. if (pmxl->fdwLine & ~0x80008001L)
  2134. {
  2135. DebugErr1(DBF_ERROR, "mixerGetLineInfo: buggy driver set reserved line flags (%.08lXh)!", pmxl->fdwLine);
  2136. pmxl->fdwLine &= 0x80008001L;
  2137. }
  2138. if (!IMixerIsValidComponentType(pmxl->dwComponentType, pmxl->fdwLine))
  2139. {
  2140. DebugErr1(DBF_ERROR, "mixerGetLineInfo: buggy driver returned invalid dwComponentType (%.08lXh).", pmxl->dwComponentType);
  2141. pmxl->dwComponentType = MIXERLINE_TARGETTYPE_UNDEFINED;
  2142. }
  2143. if (0 == pmxl->cChannels)
  2144. {
  2145. DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver returned zero channels?!?");
  2146. pmxl->cChannels = 1;
  2147. }
  2148. if (fSourceLine)
  2149. {
  2150. if (0 != pmxl->cConnections)
  2151. {
  2152. DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver returned non-zero connections on source?!?");
  2153. pmxl->cConnections = 0;
  2154. }
  2155. }
  2156. pmxl->szShortName[SIZEOF(pmxl->szShortName) - 1] = '\0';
  2157. pmxl->szName[SIZEOF(pmxl->szName) - 1] = '\0';
  2158. //
  2159. // Does this really need to be done if TARGETTYPE was requested?
  2160. //
  2161. //
  2162. //
  2163. //
  2164. if (MIXERLINE_TARGETTYPE_UNDEFINED != pmxl->Target.dwType)
  2165. {
  2166. UINT u;
  2167. pmxl->Target.dwDeviceID = (DWORD)-1L;
  2168. //
  2169. // we have a wMid, wPid and szPname (supposedly) of type dwType
  2170. // so let's go find it...
  2171. //
  2172. switch (pmxl->Target.dwType)
  2173. {
  2174. case MIXERLINE_TARGETTYPE_WAVEOUT:
  2175. u = waveOutGetNumDevs();
  2176. while (u--)
  2177. {
  2178. WAVEOUTCAPS woc;
  2179. mmr = waveOutGetDevCaps(u, &woc, sizeof(woc));
  2180. if (MMSYSERR_NOERROR != mmr)
  2181. continue;
  2182. woc.szPname[SIZEOF(woc.szPname) - 1] = '\0';
  2183. if (woc.wMid != pmxl->Target.wMid)
  2184. continue;
  2185. if (woc.wPid != pmxl->Target.wPid)
  2186. continue;
  2187. if (woc.vDriverVersion != pmxl->Target.vDriverVersion)
  2188. continue;
  2189. if (lstrcmp(woc.szPname, pmxl->Target.szPname))
  2190. continue;
  2191. pmxl->Target.dwDeviceID = u;
  2192. break;
  2193. }
  2194. break;
  2195. case MIXERLINE_TARGETTYPE_WAVEIN:
  2196. u = waveInGetNumDevs();
  2197. while (u--)
  2198. {
  2199. WAVEINCAPS wic;
  2200. mmr = waveInGetDevCaps(u, &wic, sizeof(wic));
  2201. if (MMSYSERR_NOERROR != mmr)
  2202. continue;
  2203. wic.szPname[SIZEOF(wic.szPname) - 1] = '\0';
  2204. if (wic.wMid != pmxl->Target.wMid)
  2205. continue;
  2206. if (wic.wPid != pmxl->Target.wPid)
  2207. continue;
  2208. if (wic.vDriverVersion != pmxl->Target.vDriverVersion)
  2209. continue;
  2210. if (lstrcmp(wic.szPname, pmxl->Target.szPname))
  2211. continue;
  2212. pmxl->Target.dwDeviceID = u;
  2213. break;
  2214. }
  2215. break;
  2216. case MIXERLINE_TARGETTYPE_MIDIOUT:
  2217. u = midiOutGetNumDevs();
  2218. while (u--)
  2219. {
  2220. MIDIOUTCAPS moc;
  2221. mmr = midiOutGetDevCaps(u, &moc, sizeof(moc));
  2222. if (MMSYSERR_NOERROR != mmr)
  2223. continue;
  2224. moc.szPname[SIZEOF(moc.szPname) - 1] = '\0';
  2225. if (moc.wMid != pmxl->Target.wMid)
  2226. continue;
  2227. if (moc.wPid != pmxl->Target.wPid)
  2228. continue;
  2229. if (moc.vDriverVersion != pmxl->Target.vDriverVersion)
  2230. continue;
  2231. if (lstrcmp(moc.szPname, pmxl->Target.szPname))
  2232. continue;
  2233. pmxl->Target.dwDeviceID = u;
  2234. break;
  2235. }
  2236. break;
  2237. case MIXERLINE_TARGETTYPE_MIDIIN:
  2238. u = midiInGetNumDevs();
  2239. while (u--)
  2240. {
  2241. MIDIINCAPS mic;
  2242. mmr = midiInGetDevCaps(u, &mic, sizeof(mic));
  2243. if (MMSYSERR_NOERROR != mmr)
  2244. continue;
  2245. mic.szPname[SIZEOF(mic.szPname) - 1] = '\0';
  2246. if (mic.wMid != pmxl->Target.wMid)
  2247. continue;
  2248. if (mic.wPid != pmxl->Target.wPid)
  2249. continue;
  2250. if (mic.vDriverVersion != pmxl->Target.vDriverVersion)
  2251. continue;
  2252. if (lstrcmp(mic.szPname, pmxl->Target.szPname))
  2253. continue;
  2254. pmxl->Target.dwDeviceID = u;
  2255. break;
  2256. }
  2257. break;
  2258. case MIXERLINE_TARGETTYPE_AUX:
  2259. u = auxGetNumDevs();
  2260. while (u--)
  2261. {
  2262. AUXCAPS ac;
  2263. mmr = auxGetDevCaps(u, &ac, sizeof(ac));
  2264. if (MMSYSERR_NOERROR != mmr)
  2265. continue;
  2266. ac.szPname[SIZEOF(ac.szPname) - 1] = '\0';
  2267. if (ac.wMid != pmxl->Target.wMid)
  2268. continue;
  2269. if (ac.wPid != pmxl->Target.wPid)
  2270. continue;
  2271. if (ac.vDriverVersion != pmxl->Target.vDriverVersion)
  2272. continue;
  2273. if (lstrcmp(ac.szPname, pmxl->Target.szPname))
  2274. continue;
  2275. pmxl->Target.dwDeviceID = u;
  2276. break;
  2277. }
  2278. break;
  2279. default:
  2280. pmxl->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
  2281. break;
  2282. }
  2283. }
  2284. return (mmr);
  2285. } // mixerGetLineInfo()
  2286. //
  2287. // Abstract converting the complex mixerline structure
  2288. //
  2289. void ConvertMIXERLINEWToMIXERLINEA(
  2290. PMIXERLINEA pmxlA,
  2291. PMIXERLINEW pmxlW
  2292. )
  2293. {
  2294. //
  2295. // Don't copy cbStruct
  2296. //
  2297. CopyMemory((PVOID)((PBYTE)pmxlA + sizeof(DWORD)),
  2298. (PVOID)((PBYTE)pmxlW + sizeof(DWORD)),
  2299. FIELD_OFFSET(MIXERLINEA, szShortName[0]) - sizeof(DWORD));
  2300. Iwcstombs(pmxlA->szShortName, pmxlW->szShortName,
  2301. sizeof(pmxlA->szShortName));
  2302. Iwcstombs(pmxlA->szName, pmxlW->szName,
  2303. sizeof(pmxlA->szName));
  2304. CopyMemory((PVOID)&pmxlA->Target, (PVOID)&pmxlW->Target,
  2305. FIELD_OFFSET(MIXERLINEA, Target.szPname[0]) -
  2306. FIELD_OFFSET(MIXERLINEA, Target.dwType));
  2307. Iwcstombs(pmxlA->Target.szPname, pmxlW->Target.szPname,
  2308. sizeof(pmxlA->Target.szPname));
  2309. }
  2310. /*--------------------------------------------------------------------------;
  2311. *
  2312. * @doc EXTERNAL MIXER SDK STRUCTURE
  2313. *
  2314. * @types MIXERCONTROL | The <t MIXERCONTROL> structure describes the state
  2315. * and metrics of a single control for an audio mixer line.
  2316. *
  2317. * @syntaxex
  2318. * typedef struct tMIXERCONTROL
  2319. * {
  2320. * DWORD cbStruct;
  2321. * DWORD dwControlID;
  2322. * DWORD dwControlType;
  2323. * DWORD fdwControl;
  2324. * DWORD cMultipleItems;
  2325. * char szShortName[MIXER_SHORT_NAME_CHARS];
  2326. * char szName[MIXER_LONG_NAME_CHARS];
  2327. * union
  2328. * {
  2329. * struct
  2330. * {
  2331. * LONG lMinimum;
  2332. * LONG lMaximum;
  2333. * };
  2334. * struct
  2335. * {
  2336. * DWORD dwMinimum;
  2337. * DWORD dwMaximum;
  2338. * };
  2339. * DWORD dwReserved[6];
  2340. * } Bounds;
  2341. * union
  2342. * {
  2343. * DWORD cSteps;
  2344. * DWORD cbCustomData;
  2345. * DWORD dwReserved[6];
  2346. * } Metrics;
  2347. * } MIXERCONTROL;
  2348. *
  2349. * @field DWORD | cbStruct | Specifies the size, in bytes, of the
  2350. * <t MIXERCONTROL> structure. Since the <t MIXERCONTROL> structure
  2351. * is only passed as a receiving buffer referenced and described by
  2352. * the <t MIXERLINECONTROLS> structure passed to the
  2353. * <f mixerGetLineControls> function, it is not necessary for the
  2354. * calling application to initialize this member (or any other members
  2355. * of this structure). When the <f mixerGetLineControls> function
  2356. * returns, this member contains the actual size of the information
  2357. * returned by the mixer device. The returned information will never
  2358. * exceed the requested size and will never be smaller than the
  2359. * base <t MIXERCONTROL> structure.
  2360. *
  2361. * @field DWORD | dwControlID | Specifies an audio mixer defined identifier
  2362. * that uniquely refers to the control described by the <t MIXERCONTROL>
  2363. * structure. This identifier is unique only to a single mixer device
  2364. * and may be of any format that the mixer device wishes. An application
  2365. * should only use this identifier as an abstract handle. No two
  2366. * controls for a single mixer device will have the same control
  2367. * identifier under any circumstances.
  2368. *
  2369. * @field DWORD | dwControlType | Specifies the control type for this
  2370. * control. An application must use this information to display the
  2371. * appropriate control for input from the user. An application may
  2372. * also wish to display tailored graphics based on the control type or
  2373. * search for a particular control type on a specific line. If an
  2374. * application does not know about a control type, then this control
  2375. * must be ignored. There are currently seven different control type
  2376. * classifications.
  2377. *
  2378. * The control type class <cl MIXERCONTROL_CT_CLASS_CUSTOM> consists of
  2379. * the following standard control types.
  2380. *
  2381. * <c MIXERCONTROL_CONTROLTYPE_CUSTOM><nl>
  2382. *
  2383. * The control type class <cl MIXERCONTROL_CT_CLASS_METER> consists of
  2384. * the following standard control types.
  2385. *
  2386. * <c MIXERCONTROL_CONTROLTYPE_BOOLEANMETER><nl>
  2387. * <c MIXERCONTROL_CONTROLTYPE_SIGNEDMETER><nl>
  2388. * <c MIXERCONTROL_CONTROLTYPE_PEAKMETER><nl>
  2389. * <c MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER><nl>
  2390. *
  2391. * The control type class <cl MIXERCONTROL_CT_CLASS_SWITCH> consists of
  2392. * the following standard control types.
  2393. *
  2394. * <c MIXERCONTROL_CONTROLTYPE_BUTTON><nl>
  2395. *
  2396. * <c MIXERCONTROL_CONTROLTYPE_BOOLEAN><nl>
  2397. * <c MIXERCONTROL_CONTROLTYPE_ONOFF><nl>
  2398. * <c MIXERCONTROL_CONTROLTYPE_MUTE><nl>
  2399. * <c MIXERCONTROL_CONTROLTYPE_MONO><nl>
  2400. * <c MIXERCONTROL_CONTROLTYPE_LOUDNESS><nl>
  2401. * <c MIXERCONTROL_CONTROLTYPE_STEREOENH><nl>
  2402. *
  2403. * The control type class <cl MIXERCONTROL_CT_CLASS_NUMBER> consists of
  2404. * the following standard control types.
  2405. *
  2406. * <c MIXERCONTROL_CONTROLTYPE_SIGNED><nl>
  2407. * <c MIXERCONTROL_CONTROLTYPE_DECIBELS><nl>
  2408. * <c MIXERCONTROL_CONTROLTYPE_UNSIGNED><nl>
  2409. * <c MIXERCONTROL_CONTROLTYPE_PERCENT><nl>
  2410. *
  2411. * The control type class <cl MIXERCONTROL_CT_CLASS_SLIDER> consists of
  2412. * the following standard control types.
  2413. *
  2414. * <c MIXERCONTROL_CONTROLTYPE_SLIDER><nl>
  2415. * <c MIXERCONTROL_CONTROLTYPE_PAN><nl>
  2416. * <c MIXERCONTROL_CONTROLTYPE_QSOUNDPAN><nl>
  2417. *
  2418. * The control type class <cl MIXERCONTROL_CT_CLASS_FADER> consists of
  2419. * the following standard control types.
  2420. *
  2421. * <c MIXERCONTROL_CONTROLTYPE_FADER><nl>
  2422. * <c MIXERCONTROL_CONTROLTYPE_VOLUME><nl>
  2423. * <c MIXERCONTROL_CONTROLTYPE_BASS><nl>
  2424. * <c MIXERCONTROL_CONTROLTYPE_TREBLE><nl>
  2425. * <c MIXERCONTROL_CONTROLTYPE_EQUALIZER><nl>
  2426. *
  2427. * The control type class <cl MIXERCONTROL_CT_CLASS_TIME> consists of
  2428. * the following standard control types.
  2429. *
  2430. * <c MIXERCONTROL_CONTROLTYPE_MICROTIME><nl>
  2431. * <c MIXERCONTROL_CONTROLTYPE_MILLITIME><nl>
  2432. *
  2433. * The control type class <cl MIXERCONTROL_CT_CLASS_LIST> consists of
  2434. * the following standard control types.
  2435. *
  2436. * <c MIXERCONTROL_CONTROLTYPE_SINGLESELECT><nl>
  2437. * <c MIXERCONTROL_CONTROLTYPE_MUX><nl>
  2438. * <c MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT><nl>
  2439. * <c MIXERCONTROL_CONTROLTYPE_MIXER><nl>
  2440. *
  2441. * @field DWORD | fdwControl | Specifies status and support flags for the
  2442. * audio mixer line control.
  2443. *
  2444. * @flag <c MIXERCONTROL_CONTROLF_UNIFORM> | Specifies that the control
  2445. * acts on all channels of a multi-channel line in a uniform fashion.
  2446. * For example, a Mute control that mutes both channels of a stereo
  2447. * line would set this flag. Most MUX and Mixer controls will also
  2448. * specify the <c MIXERCONTROL_CONTROLF_UNIFORM> flag.
  2449. *
  2450. * @flag <c MIXERCONTROL_CONTROLF_MULTIPLE> | Specifies that the control
  2451. * has two or more settings per channel. An example of a control
  2452. * that requires the multiple flag is an equalizer--each frequency
  2453. * band can be set to different values. Note that an equalizer that
  2454. * affects both channels of a stereo line in a uniform fashion will
  2455. * also set the <c MIXERCONTROL_CONTROLF_UNIFORM> flag.
  2456. *
  2457. * @flag <c MIXERCONTROL_CONTROLF_DISABLED> | Specifies that the control
  2458. * is disabled (perhaps due to other settings for the mixer hardware)
  2459. * and cannot be used. An application can read current settings from
  2460. * a disabled control, but cannot apply settings.
  2461. *
  2462. * @field DWORD | cMultipleItems | Specifies the number of items per
  2463. * channel that a <c MIXERCONTROL_CONTROLF_MULTIPLE> control contains.
  2464. * This number will always be two or greater for multiple item
  2465. * controls. If the control is not a multiple item control, this
  2466. * member will be zero and should be ignored.
  2467. *
  2468. * @field char | szShortName[<c MIXER_SHORT_NAME_CHARS>] | Specifies a short
  2469. * string that describes the <e MIXERCONTROL.dwControlID> audio mixer
  2470. * line control. This description is appropriate for using as a
  2471. * displayable label for the control that can fit in small spaces.
  2472. *
  2473. * @field char | szName[<c MIXER_LONG_NAME_CHARS>] | Specifies a string
  2474. * that describes the <e MIXERCONTROL.dwControlID> audio mixer line
  2475. * control. This description is appropriate for using as a displayable
  2476. * description for the control that is not limited by screen space.
  2477. *
  2478. * @field union | Bounds | Contains the union of boundary types.
  2479. *
  2480. * @field2 DWORD | dwMinimum | Specifies the minimum unsigned value
  2481. * for a control that has an unsigned boundary nature. Refer to the
  2482. * description for each control type to determine if this member is
  2483. * appropriate for the control. This member overlaps with the
  2484. * <e MIXERCONTROL.lMinimum> member and cannot be used in
  2485. * conjunction with that member.
  2486. *
  2487. * @field2 DWORD | dwMaximum | Specifies the maximum unsigned value
  2488. * for a control that has an unsigned boundary nature. Refer to the
  2489. * description for each control type to determine if this member is
  2490. * appropriate for the control. This member overlaps with the
  2491. * <e MIXERCONTROL.lMaximum> member and cannot be used in
  2492. * conjunction with that member.
  2493. *
  2494. * @field2 DWORD | lMinimum | Specifies the minimum signed value
  2495. * for a control that has a signed boundary nature. Refer to the
  2496. * description for each control type to determine if this member is
  2497. * appropriate for the control. This member overlaps with the
  2498. * <e MIXERCONTROL.dwMinimum> member and cannot be used in
  2499. * conjunction with that member.
  2500. *
  2501. * @field2 DWORD | lMaximum | Specifies the maximum signed value
  2502. * for a control that has a signed boundary nature. Refer to the
  2503. * description for each control type to determine if this member is
  2504. * appropriate for the control. This member overlaps with the
  2505. * <e MIXERCONTROL.dwMaximum> member and cannot be used in
  2506. * conjunction with that member.
  2507. *
  2508. * @field union | Metrics | Contains the union of boundary metrics.
  2509. *
  2510. * @field2 DWORD | cSteps | Specifies the number of discrete
  2511. * ranges within the specified <e MIXERCONTROL.Bounds> for a control.
  2512. * Refer to the description for each control type to determine if this
  2513. * member is appropriate for the control. This member overlaps with the
  2514. * other members of the <e MIXERCONTROL.Metrics> structure member and
  2515. * cannot be used in conjunction with those members.
  2516. *
  2517. * @field2 DWORD | cbCustomData | Specifies the size, in bytes,
  2518. * required to hold the state of a custom control type. This member
  2519. * is only appropriate for the <c MIXERCONTROL_CONTROLTYPE_CUSTOM>
  2520. * control type. See the description for custom control types for more
  2521. * information on the use of this member.
  2522. *
  2523. * @tagname tMIXERCONTROL
  2524. *
  2525. * @othertype MIXERCONTROL FAR * | LPMIXERCONTROL | A pointer to a
  2526. * <t MIXERCONTROL> structure.
  2527. *
  2528. * @othertype MIXERCONTROL * | PMIXERCONTROL | A pointer to a
  2529. * <t MIXERCONTROL> structure.
  2530. *
  2531. * @xref <t MIXERLINECONTROLS>, <f mixerGetLineControls>, <f mixerGetLineInfo>,
  2532. * <f mixerGetControlDetails>, <f mixerSetControlDetails>,
  2533. * <t MIXERCONTROLDETAILS>
  2534. *
  2535. **/
  2536. /*--------------------------------------------------------------------------;
  2537. *
  2538. * @doc EXTERNAL MIXER SDK STRUCTURE
  2539. *
  2540. * @types MIXERLINECONTROLS | The <t MIXERLINECONTROLS> structure references
  2541. * what controls to retrieve information on from an audio mixer line.
  2542. *
  2543. * @field DWORD | cbStruct | Specifies the size, in bytes, of the
  2544. * <t MIXERLINECONTROLS> structure. This member must be initialized
  2545. * before calling the <f mixerGetLineControls> function. The size
  2546. * specified in this member must be large enough to contain the base
  2547. * <t MIXERLINECONTROLS> structure. When the <f mixerGetLineControls>
  2548. * function returns, this member contains the actual size of the
  2549. * information returned. The returned information will never exceed
  2550. * the requested size and will never be smaller than the base
  2551. * <t MIXERLINECONTROLS> structure.
  2552. *
  2553. * @field DWORD | dwLineID | Specifies the line identifier to retrieve
  2554. * one or all controls for. This member is not used if the
  2555. * <c MIXER_GETLINECONTROLSF_ONEBYID> flag is specified for the
  2556. * <f mixerGetLineControls> function--but the mixer device will return
  2557. * this member in this case. The <e MIXERLINECONTROLS.dwControlID>
  2558. * and <e MIXERLINECONTROLS.dwControlType> members are not used when
  2559. * <c MIXER_GETLINECONTROLSF_ALL> is specified.
  2560. *
  2561. * @field DWORD | dwControlID | Specifies the control identifier of the
  2562. * control desired. This member is used with the
  2563. * <c MIXER_GETLINECONTROLSF_ONEBYID> flag for <f mixerGetLineControls>
  2564. * to retrieve the control information of the specified control.
  2565. * Note that the <e MIXERLINECONTROLS.dwLineID> member of the
  2566. * <t MIXERLINECONTROLS> structure will be returned by the mixer device
  2567. * and is not required as an input parameter. This member overlaps with
  2568. * the <e MIXERLINECONTROLS.dwControlType> member and cannot be used in
  2569. * conjunction with the <c MIXER_GETLINECONTROLSF_ONEBYTYPE> query type.
  2570. *
  2571. * @field DWORD | dwControlType | Specifies the control type of the
  2572. * control desired. This member is used with the
  2573. * <c MIXER_GETLINECONTROLSF_ONEBYTYPE> flag for <f mixerGetLineControls>
  2574. * to retrieve the first control of the specified type on the line
  2575. * specified by the <e MIXERLINECONTROLS.dwLineID> member of the
  2576. * <t MIXERLINECONTROLS> structure. This member overlaps with the
  2577. * <e MIXERLINECONTROLS.dwControlID> member and cannot be used in
  2578. * conjunction with the <c MIXER_GETLINECONTROLSF_ONEBYID> query type.
  2579. *
  2580. * @field DWORD | cControls | Specifies the number of <t MIXERCONTROL>
  2581. * structure elements to retrieve. This member must be initialized by
  2582. * the application before calling the <f mixerGetLineControls> function.
  2583. * This member may only be one (if <c MIXER_GETLINECONTROLSF_ONEBYID> or
  2584. * <c MIXER_GETLINECONTROLSF_ONEBYTYPE> is specified) or the value
  2585. * returned in the <e MIXERLINE.cControls> member of the <t MIXERLINE>
  2586. * structure returned for a line. This member cannot be zero. If a
  2587. * line specifies that it has no controls, then <f mixerGetLineControls>
  2588. * should not be called.
  2589. *
  2590. * @field DWORD | cbmxctrl | Specifies the size, in bytes, of a single
  2591. * <t MIXERCONTROL> structure. This must be at least large enough
  2592. * to hold the base <t MIXERCONTROL> structure. The total size, in
  2593. * bytes, required for the buffer pointed to by <e MIXERLINECONTROLS.pamxctrl>
  2594. * member is the product of the <e MIXERLINECONTROLS.cbmxctrl> and
  2595. * <e MIXERLINECONTROLS.cControls> members of the <t MIXERLINECONTROLS>
  2596. * structure.
  2597. *
  2598. * @field LPMIXERCONTROL | pamxctrl | Points to one or more <t MIXERCONTROL>
  2599. * structures to receive the details on the requested audio mixer line
  2600. * controls. This member may never be NULL and must be initialized before
  2601. * calling the <f mixerGetLineControls> function. Each element of the
  2602. * array of controls must be at least large enough to hold a base
  2603. * <t MIXERCONTROL> structure. The <e MIXERLINECONTROLS.cbmxctrl> member
  2604. * must specify the size, in bytes, of each element in this array. No
  2605. * initialization of the buffer pointed to by this member needs to be
  2606. * initialized by the application. All members will be filled in by
  2607. * the mixer device (including the <e MIXERCONTROL.cbStruct> member
  2608. * of each <t MIXERCONTROL> structure) upon returning successfully to
  2609. * the application.
  2610. *
  2611. * @tagname tMIXERLINECONTROLS
  2612. *
  2613. * @othertype MIXERLINECONTROLS FAR * | LPMIXERLINECONTROLS | A pointer to a
  2614. * <t MIXERLINECONTROLS> structure.
  2615. *
  2616. * @othertype MIXERLINECONTROLS * | PMIXERLINECONTROLS | A pointer to a
  2617. * <t MIXERLINECONTROLS> structure.
  2618. *
  2619. * @xref <t MIXERCONTROL>, <f mixerGetLineControls>, <f mixerGetLineInfo>,
  2620. * <f mixerGetControlDetails>, <f mixerSetControlDetails>
  2621. *
  2622. **/
  2623. /*--------------------------------------------------------------------------;
  2624. *
  2625. * @doc EXTERNAL MIXER SDK API
  2626. *
  2627. * @api MMRESULT | mixerGetLineControls | The <f mixerGetLineControls>
  2628. * function is used to retrieve one or more controls associated with
  2629. * an audio mixer device line.
  2630. *
  2631. * @parm <c HMIXEROBJ> | hmxobj | Specifies a handle to the audio mixer
  2632. * device object to get line control information from.
  2633. *
  2634. * @parm LPMIXERLINECONTROLS | pmxlc | Points to a <t MIXERLINECONTROLS>
  2635. * structure. This structure is used to reference one or more
  2636. * <t MIXERCONTROL> structures to be filled with information about the
  2637. * controls associated with a mixer line.
  2638. * See the comments for each query flag passed through <p fdwControls>
  2639. * for details on what members of the <t MIXERLINECONTROLS> structure
  2640. * that must be initialized. Note that in all cases, the
  2641. * <e MIXERLINECONTROLS.cbStruct> member of the <t MIXERLINECONTROLS>
  2642. * structure must be initialized to be the size, in bytes, of the
  2643. * <t MIXERLINECONTROLS> structure.
  2644. *
  2645. * @parm DWORD | fdwControls | Specifies flags for getting information on
  2646. * one or more control associated with a mixer line.
  2647. *
  2648. * @flag <c MIXER_GETLINECONTROLSF_ALL> | If this flag is specified,
  2649. * <p pmxlc> references a list of <t MIXERCONTROL> structures that
  2650. * will receive information on all controls associated with the
  2651. * line identified by the <e MIXERLINECONTROLS.dwLineID> member of
  2652. * the <t MIXERLINECONTROLS> structure. <e MIXERLINECONTROLS.cControls>
  2653. * must be initialized to the number of controls associated with the
  2654. * line. This number is retrieved from the <e MIXERLINE.cControls>
  2655. * member of the <t MIXERLINE> structure returned by the
  2656. * <f mixerGetLineInfo> function. <e MIXERLINECONTROLS.cbmxctrl> must
  2657. * be initialized to the size, in bytes, of a single <t MIXERCONTROL>
  2658. * structure. <e MIXERLINECONTROLS.pamxctrl> must point to
  2659. * the first <t MIXERCONTROL> structure to be filled in. Both the
  2660. * <e MIXERLINECONTROLS.dwControlID> and <e MIXERLINECONTROLS.dwControlType>
  2661. * members are ignored for this query.
  2662. *
  2663. * @flag <c MIXER_GETLINECONTROLSF_ONEBYID> | If this flag is specified,
  2664. * <p pmxlc> references a single <t MIXERCONTROL> structure that
  2665. * will receive information on the control identified by the
  2666. * <e MIXERLINECONTROLS.dwControlID> member of the <t MIXERLINECONTROLS>
  2667. * structure. <e MIXERLINECONTROLS.cControls> must be initialized to one.
  2668. * <e MIXERLINECONTROLS.cbmxctrl> must be initialized to the size, in
  2669. * bytes, of a single <t MIXERCONTROL> structure.
  2670. * <e MIXERLINECONTROLS.pamxctrl> must point to a <t MIXERCONTROL>
  2671. * structure to be filled in. Both the <e MIXERLINECONTROLS.dwLineID>
  2672. * and <e MIXERLINECONTROLS.dwControlType> members are ignored for this
  2673. * query. This query is usually used to refresh a control after
  2674. * receiving a <m MM_MIXM_CONTROL_CHANGE> control change notification
  2675. * message by the user-specified callback (see <f mixerOpen>).
  2676. *
  2677. * @flag <c MIXER_GETLINECONTROLSF_ONEBYTYPE> | If this flag is specified,
  2678. * <p pmxlc> references a single <t MIXERCONTROL> structure that
  2679. * will receive information on the fist control associated with the
  2680. * line identified by <e MIXERLINECONTROLS.dwLineID> of the type
  2681. * specified in the <e MIXERLINECONTROLS.dwControlType> member of the
  2682. * <t MIXERLINECONTROLS> structure.
  2683. * <e MIXERLINECONTROLS.cControls> must be
  2684. * initialized to one. <e MIXERLINECONTROLS.cbmxctrl> must be initialized
  2685. * to the size, in bytes, of a single <t MIXERCONTROL> structure.
  2686. * <e MIXERLINECONTROLS.pamxctrl> must point to a <t MIXERCONTROL>
  2687. * structure to be filled in. The <e MIXERLINECONTROLS.dwControlID>
  2688. * member is ignored for this query. This query can be used by an
  2689. * application to get information on single control associated with
  2690. * a line. For example, an application may only want to use a peak
  2691. * meter from a waveform output line.
  2692. *
  2693. * @flag <c MIXER_OBJECTF_MIXER> | Specifies that <p hmxobj> is an audio
  2694. * mixer device identifier in the range of zero to one less than the
  2695. * number of devices returned by <f mixerGetNumDevs>. This flag is
  2696. * optional.
  2697. *
  2698. * @flag <c MIXER_OBJECTF_HMIXER> | Specifies that <p hmxobj> is a mixer
  2699. * device handle returned by <f mixerOpen>. This flag is optional.
  2700. *
  2701. * @flag <c MIXER_OBJECTF_WAVEOUT> | Specifies that <p hmxobj> is a
  2702. * waveform output device identifier in the range of zero to one less
  2703. * than the number of devices returned by <f waveOutGetNumDevs>.
  2704. *
  2705. * @flag <c MIXER_OBJECTF_HWAVEOUT> | Specifies that <p hmxobj> is a
  2706. * waveform output handle returned by <f waveOutOpen>.
  2707. *
  2708. * @flag <c MIXER_OBJECTF_WAVEIN> | Specifies that <p hmxobj> is a
  2709. * waveform input device identifier in the range of zero to one less
  2710. * than the number of devices returned by <f waveInGetNumDevs>.
  2711. *
  2712. * @flag <c MIXER_OBJECTF_HWAVEIN> | Specifies that <p hmxobj> is a
  2713. * waveform input handle returned by <f midiInOpen>.
  2714. *
  2715. * @flag <c MIXER_OBJECTF_MIDIOUT> | Specifies that <p hmxobj> is a MIDI
  2716. * output device identifier in the range of zero to one less than the
  2717. * number of devices returned by <f midiOutGetNumDevs>.
  2718. *
  2719. * @flag <c MIXER_OBJECTF_HMIDIOUT> | Specifies that <p hmxobj> is a
  2720. * MIDI output handle returned by <f midiOutOpen>.
  2721. *
  2722. * @flag <c MIXER_OBJECTF_MIDIIN> | Specifies that <p hmxobj> is a MIDI
  2723. * input device identifier in the range of zero to one less than the
  2724. * number of devices returned by <f midiInGetNumDevs>.
  2725. *
  2726. * @flag <c MIXER_OBJECTF_HMIDIIN> | Specifies that <p hmxobj> is a MIDI
  2727. * input handle returned by <f midiInOpen>.
  2728. *
  2729. * @flag <c MIXER_OBJECTF_AUX> | Specifies that <p hmxobj> is an
  2730. * auxiliary device identifier in the range of zero to one less than the
  2731. * number of devices returned by <f auxGetNumDevs>.
  2732. *
  2733. * @rdesc The return value is zero if the function is successful. Otherwise,
  2734. * it returns a non-zero error number. Possible error returns include
  2735. * the following:
  2736. *
  2737. * @flag <c MMSYSERR_BADDEVICEID> | The <p hmxobj> argument specifies an
  2738. * invalid device identifier.
  2739. *
  2740. * @flag <c MMSYSERR_INVALHANDLE> | The <p hmxobj> argument specifies an
  2741. * invalid handle.
  2742. *
  2743. * @flag <c MMSYSERR_INVALFLAG> | One or more flags are invalid.
  2744. *
  2745. * @flag <c MMSYSERR_INVALPARAM> | One or more arguments passed is
  2746. * invalid.
  2747. *
  2748. * @flag <c MMSYSERR_NODRIVER> | No audio mixer device is available for
  2749. * the object specified by <p hmxobj>.
  2750. *
  2751. * @flag <c MIXERR_INVALLINE> | The audio mixer device line reference is
  2752. * invalid.
  2753. *
  2754. * @flag <c MIXERR_INVALCONTROL> | The control reference is invalid.
  2755. *
  2756. * @xref <t MIXERLINECONTROLS>, <t MIXERCONTROL>, <f mixerGetLineInfo>,
  2757. * <f mixerOpen>, <f mixerGetControlDetails>, <f mixerSetControlDetails>
  2758. *
  2759. **/
  2760. MMRESULT APIENTRY mixerGetLineControlsA(
  2761. HMIXEROBJ hmxobj,
  2762. LPMIXERLINECONTROLSA pmxlcA,
  2763. DWORD fdwControls
  2764. )
  2765. {
  2766. MIXERLINECONTROLSW mxlcW;
  2767. MMRESULT mmr;
  2768. DWORD cControls;
  2769. V_WPOINTER(pmxlcA, sizeof(DWORD), MMSYSERR_INVALPARAM);
  2770. V_WPOINTER(pmxlcA, (UINT)pmxlcA->cbStruct, MMSYSERR_INVALPARAM);
  2771. if (sizeof(MIXERLINECONTROLSA) > pmxlcA->cbStruct) {
  2772. DebugErr1(DBF_ERROR, "mixerGetLineControls: structure size too small or cbStruct not initialized (%lu).", pmxlcA->cbStruct);
  2773. return (MMSYSERR_INVALPARAM);
  2774. }
  2775. //
  2776. // Set up a MIXERCONTROLW structure and allocate space for the
  2777. // returned data
  2778. //
  2779. CopyMemory((PVOID)&mxlcW, (PVOID)pmxlcA,
  2780. FIELD_OFFSET(MIXERLINECONTROLSA, pamxctrl));
  2781. mxlcW.cbmxctrl = mxlcW.cbmxctrl + sizeof(MIXERCONTROLW) -
  2782. sizeof(MIXERCONTROLA);
  2783. //
  2784. // Work out how many controls (what a mess - why isn't the count
  2785. // ALWAYS required)!
  2786. //
  2787. switch (MIXER_GETLINECONTROLSF_QUERYMASK & fdwControls)
  2788. {
  2789. case MIXER_GETLINECONTROLSF_ONEBYID:
  2790. case MIXER_GETLINECONTROLSF_ONEBYTYPE:
  2791. cControls = 1;
  2792. break;
  2793. default:
  2794. cControls = mxlcW.cControls;
  2795. break;
  2796. }
  2797. if (cControls != 0) {
  2798. mxlcW.pamxctrl = (LPMIXERCONTROLW)
  2799. LocalAlloc(LPTR, cControls * mxlcW.cbmxctrl);
  2800. if (mxlcW.pamxctrl == NULL) {
  2801. return MMSYSERR_NOMEM;
  2802. }
  2803. } else {
  2804. mxlcW.pamxctrl = NULL;
  2805. }
  2806. //
  2807. // Call the real function
  2808. //
  2809. mmr = mixerGetLineControls(hmxobj, &mxlcW, fdwControls);
  2810. if (mmr != MMSYSERR_NOERROR) {
  2811. if (mxlcW.pamxctrl != NULL) {
  2812. LocalFree((HLOCAL)mxlcW.pamxctrl);
  2813. }
  2814. return mmr;
  2815. }
  2816. //
  2817. // The INPUT line id can be changed !!
  2818. //
  2819. pmxlcA->dwLineID = mxlcW.dwLineID;
  2820. //
  2821. // The control id can be changed !!
  2822. //
  2823. pmxlcA->dwControlID = mxlcW.dwControlID;
  2824. //
  2825. // Copy and massage the data back for the application
  2826. //
  2827. {
  2828. UINT i;
  2829. LPMIXERCONTROLA pamxctrlA;
  2830. LPMIXERCONTROLW pamxctrlW;
  2831. for (i = 0, pamxctrlA = pmxlcA->pamxctrl, pamxctrlW = mxlcW.pamxctrl;
  2832. i < cControls;
  2833. i++,
  2834. *(LPBYTE *)&pamxctrlA += pmxlcA->cbmxctrl,
  2835. *(LPBYTE *)&pamxctrlW += mxlcW.cbmxctrl
  2836. ) {
  2837. CopyMemory((PVOID)pamxctrlA,
  2838. (PVOID)pamxctrlW,
  2839. FIELD_OFFSET(MIXERCONTROLA, szShortName[0]));
  2840. /*
  2841. ** Set the size
  2842. */
  2843. pamxctrlA->cbStruct = sizeof(MIXERCONTROLA);
  2844. Iwcstombs(pamxctrlA->szShortName,
  2845. pamxctrlW->szShortName,
  2846. sizeof(pamxctrlA->szShortName));
  2847. Iwcstombs(pamxctrlA->szName,
  2848. pamxctrlW->szName,
  2849. sizeof(pamxctrlA->szName));
  2850. CopyMemory((PVOID)((PBYTE)pamxctrlA +
  2851. FIELD_OFFSET(MIXERCONTROLA, Bounds.lMinimum)),
  2852. (PVOID)((PBYTE)pamxctrlW +
  2853. FIELD_OFFSET(MIXERCONTROLW, Bounds.lMinimum)),
  2854. sizeof(MIXERCONTROLW) -
  2855. FIELD_OFFSET(MIXERCONTROLW, Bounds.lMinimum));
  2856. }
  2857. }
  2858. if (mxlcW.pamxctrl != NULL) {
  2859. LocalFree((HLOCAL)mxlcW.pamxctrl);
  2860. }
  2861. return mmr;
  2862. } // mixerGetLineControlsA()
  2863. MMRESULT APIENTRY mixerGetLineControls(
  2864. HMIXEROBJ hmxobj,
  2865. LPMIXERLINECONTROLS pmxlc,
  2866. DWORD fdwControls
  2867. )
  2868. {
  2869. DWORD fdwMxObjType;
  2870. UINT uMxId;
  2871. BOOL fResource;
  2872. MMRESULT mmr;
  2873. V_DFLAGS(fdwControls, MIXER_GETLINECONTROLSF_VALID, mixerGetLineControls, MMSYSERR_INVALFLAG);
  2874. V_WPOINTER(pmxlc, sizeof(DWORD), MMSYSERR_INVALPARAM);
  2875. //
  2876. // the structure header for MIXERLINECONTROLS must be at least the
  2877. // minimum size
  2878. //
  2879. if (sizeof(MIXERLINECONTROLS) > pmxlc->cbStruct)
  2880. {
  2881. DebugErr1(DBF_ERROR, "mixerGetLineControls: structure size too small or cbStruct not initialized (%lu).", pmxlc->cbStruct);
  2882. return (MMSYSERR_INVALPARAM);
  2883. }
  2884. V_WPOINTER(pmxlc, pmxlc->cbStruct, MMSYSERR_INVALPARAM);
  2885. if (sizeof(MIXERCONTROL) > pmxlc->cbmxctrl)
  2886. {
  2887. DebugErr1(DBF_ERROR, "mixerGetLineControls: structure size too small or cbmxctrl not initialized (%lu).", pmxlc->cbmxctrl);
  2888. return (MMSYSERR_INVALPARAM);
  2889. }
  2890. ClientUpdatePnpInfo();
  2891. //
  2892. //
  2893. //
  2894. switch (MIXER_GETLINECONTROLSF_QUERYMASK & fdwControls)
  2895. {
  2896. case MIXER_GETLINECONTROLSF_ALL:
  2897. if (0 == pmxlc->cControls)
  2898. {
  2899. DebugErr(DBF_ERROR, "mixerGetLineControls: cControls cannot be zero.");
  2900. return (MMSYSERR_INVALPARAM);
  2901. }
  2902. pmxlc->dwControlID = (DWORD)-1L;
  2903. break;
  2904. case MIXER_GETLINECONTROLSF_ONEBYID:
  2905. pmxlc->dwLineID = (DWORD)-1L;
  2906. // -- fall through --
  2907. case MIXER_GETLINECONTROLSF_ONEBYTYPE:
  2908. pmxlc->cControls = (DWORD)1;
  2909. break;
  2910. default:
  2911. DebugErr1(DBF_ERROR, "mixerGetLineControls: invalid query flags (%.08lXh).",
  2912. MIXER_GETLINECONTROLSF_QUERYMASK & fdwControls);
  2913. return (MMSYSERR_INVALFLAG);
  2914. }
  2915. V_WPOINTER(pmxlc->pamxctrl, pmxlc->cControls * pmxlc->cbmxctrl, MMSYSERR_INVALPARAM);
  2916. //
  2917. //
  2918. //
  2919. fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwControls);
  2920. fResource = FALSE;
  2921. AcquireHandleListResourceShared();
  2922. // Checking for the type of mixer object. If it is a non-mixer type
  2923. // calling IMixerMesssageID (called by IMixerGetID) with the shared
  2924. // resource will deadlock.
  2925. if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
  2926. (MIXER_OBJECTF_HMIXER == fdwMxObjType))
  2927. {
  2928. if (BAD_HANDLE(hmxobj, TYPE_MIXER))
  2929. {
  2930. ReleaseHandleListResource();
  2931. }
  2932. else
  2933. {
  2934. fResource = TRUE;
  2935. }
  2936. }
  2937. else
  2938. {
  2939. ReleaseHandleListResource();
  2940. }
  2941. mmr = IMixerGetID(hmxobj, &uMxId, NULL, fdwMxObjType);
  2942. if (MMSYSERR_NOERROR != mmr)
  2943. {
  2944. if (fResource)
  2945. ReleaseHandleListResource();
  2946. return (mmr);
  2947. }
  2948. if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
  2949. (MIXER_OBJECTF_HMIXER == fdwMxObjType))
  2950. {
  2951. //
  2952. // if a mixer device id was passed, then null hmx so we use the
  2953. // correct message sender below
  2954. //
  2955. if ((UINT_PTR)hmxobj == uMxId)
  2956. hmxobj = NULL;
  2957. }
  2958. else
  2959. {
  2960. hmxobj = NULL;
  2961. }
  2962. //
  2963. //
  2964. //
  2965. //
  2966. if (NULL != hmxobj)
  2967. {
  2968. mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj,
  2969. MXDM_GETLINECONTROLS,
  2970. (DWORD_PTR)pmxlc,
  2971. fdwControls);
  2972. }
  2973. else
  2974. {
  2975. mmr = (MMRESULT)IMixerMessageId(uMxId,
  2976. MXDM_GETLINECONTROLS,
  2977. (DWORD_PTR)pmxlc,
  2978. fdwControls);
  2979. }
  2980. return (mmr);
  2981. } // mixerGetLineControls()
  2982. /*--------------------------------------------------------------------------;
  2983. *
  2984. * @doc EXTERNAL MIXER SDK STRUCTURE
  2985. *
  2986. * @types MIXERCONTROLDETAILS_LISTTEXT | The <t MIXERCONTROLDETAILS_LISTTEXT>
  2987. * structure is used to get list text, label text, and/or band range
  2988. * information for multiple item controls. This structure is only used
  2989. * in conjunction with the <c MIXER_GETCONTROLDETAILSF_LISTTEXT> flag
  2990. * on the <f mixerGetControlDetails> function.
  2991. *
  2992. * @field DWORD | dwParam1 | Specifies the first 32 bit control type
  2993. * specific value. Refer to the description of the multiple item control
  2994. * type for information on what this value represents for the given
  2995. * control.
  2996. *
  2997. * @field DWORD | dwParam1 | Specifies the second 32 bit control type
  2998. * specific value. Refer to the description of the multiple item control
  2999. * type for information on what this value represents for the given
  3000. * control.
  3001. *
  3002. * @field char | szName[<c MIXER_LONG_NAME_CHARS>] | Specifies a name that
  3003. * describes a single item in a multiple item control. This text can
  3004. * be used as a label or item text depending on the specific control
  3005. * type.
  3006. *
  3007. * @comm The following standard control types use the
  3008. * <t MIXERCONTROLDETAILS_LISTTEXT> structure for getting the item text
  3009. * descriptions on multiple item controls:
  3010. *
  3011. * <c MIXERCONTROL_CONTROLTYPE_EQUALIZER><nl>
  3012. *
  3013. * <c MIXERCONTROL_CONTROLTYPE_SINGLESELECT><nl>
  3014. * <c MIXERCONTROL_CONTROLTYPE_MUX><nl>
  3015. * <c MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT><nl>
  3016. * <c MIXERCONTROL_CONTROLTYPE_MIXER><nl>
  3017. *
  3018. * @tagname tMIXERCONTROLDETAILS_LISTTEXT
  3019. *
  3020. * @othertype MIXERCONTROLDETAILS_LISTTEXT FAR * | LPMIXERCONTROLDETAILS_LISTTEXT |
  3021. * A pointer to a <t MIXERCONTROLDETAILS_LISTTEXT> structure.
  3022. *
  3023. * @othertype MIXERCONTROLDETAILS_LISTTEXT * | PMIXERCONTROLDETAILS_LISTTEXT |
  3024. * A pointer to a <t MIXERCONTROLDETAILS_LISTTEXT> structure.
  3025. *
  3026. * @xref <t MIXERCONTROLDETAILS_UNSIGNED>, <t MIXERCONTROLDETAILS_SIGNED>,
  3027. * <t MIXERCONTROLDETAILS_BOOLEAN>, <f mixerGetControlDetails>,
  3028. * <f mixerSetControlDetails>, <t MIXERCONTROL>
  3029. *
  3030. **/
  3031. /*--------------------------------------------------------------------------;
  3032. *
  3033. * @doc EXTERNAL MIXER SDK STRUCTURE
  3034. *
  3035. * @types MIXERCONTROLDETAILS_BOOLEAN | The <t MIXERCONTROLDETAILS_BOOLEAN>
  3036. * structure is used to get and set Boolean type control details for
  3037. * an audio mixer control. Refer to the control type description for
  3038. * the desired control to determine what details structure to use.
  3039. *
  3040. * @field LONG | fValue | Specifies the Boolean value for a single item
  3041. * or channel. This value is assumed to zero for a 'FALSE' state (for
  3042. * example, off or disabled). This value is assumed to be non-zero
  3043. * for a 'TRUE' state (for example, on or enabled).
  3044. *
  3045. * @comm The following standard control types use the
  3046. * <t MIXERCONTROLDETAILS_BOOLEAN> structure for getting and setting
  3047. * details:
  3048. *
  3049. * <c MIXERCONTROL_CONTROLTYPE_BOOLEANMETER><nl>
  3050. *
  3051. * <c MIXERCONTROL_CONTROLTYPE_BUTTON><nl>
  3052. *
  3053. * <c MIXERCONTROL_CONTROLTYPE_BOOLEAN><nl>
  3054. * <c MIXERCONTROL_CONTROLTYPE_ONOFF><nl>
  3055. * <c MIXERCONTROL_CONTROLTYPE_MUTE><nl>
  3056. * <c MIXERCONTROL_CONTROLTYPE_MONO><nl>
  3057. * <c MIXERCONTROL_CONTROLTYPE_LOUDNESS><nl>
  3058. * <c MIXERCONTROL_CONTROLTYPE_STEREOENH><nl>
  3059. *
  3060. * <c MIXERCONTROL_CONTROLTYPE_SINGLESELECT><nl>
  3061. * <c MIXERCONTROL_CONTROLTYPE_MUX><nl>
  3062. * <c MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT><nl>
  3063. * <c MIXERCONTROL_CONTROLTYPE_MIXER><nl>
  3064. *
  3065. * @tagname tMIXERCONTROLDETAILS_BOOLEAN
  3066. *
  3067. * @othertype MIXERCONTROLDETAILS_BOOLEAN FAR * | LPMIXERCONTROLDETAILS_BOOLEAN |
  3068. * A pointer to a <t MIXERCONTROLDETAILS_BOOLEAN> structure.
  3069. *
  3070. * @othertype MIXERCONTROLDETAILS_BOOLEAN * | PMIXERCONTROLDETAILS_BOOLEAN |
  3071. * A pointer to a <t MIXERCONTROLDETAILS_BOOLEAN> structure.
  3072. *
  3073. * @xref <t MIXERCONTROLDETAILS_UNSIGNED>, <t MIXERCONTROLDETAILS_SIGNED>,
  3074. * <t MIXERCONTROLDETAILS_LISTTEXT>, <f mixerGetControlDetails>,
  3075. * <f mixerSetControlDetails>, <t MIXERCONTROL>
  3076. *
  3077. **/
  3078. /*--------------------------------------------------------------------------;
  3079. *
  3080. * @doc EXTERNAL MIXER SDK STRUCTURE
  3081. *
  3082. * @types MIXERCONTROLDETAILS_SIGNED | The <t MIXERCONTROLDETAILS_SIGNED>
  3083. * structure is used to get and set signed type control details for
  3084. * an audio mixer control. Refer to the control type description for
  3085. * the desired control to determine what details structure to use.
  3086. *
  3087. * @field LONG | lValue | Specifies a signed integer value for a single
  3088. * item or channel. This value must be inclusively within the bounds
  3089. * given in the <e MIXERCONTROL.Bounds> structure member of the
  3090. * <t MIXERCONTROL> structure for signed integer controls.
  3091. *
  3092. * @comm The following standard control types use the
  3093. * <t MIXERCONTROLDETAILS_SIGNED> structure for getting and setting
  3094. * details:
  3095. *
  3096. * <c MIXERCONTROL_CONTROLTYPE_SIGNEDMETER><nl>
  3097. * <c MIXERCONTROL_CONTROLTYPE_PEAKMETER><nl>
  3098. *
  3099. * <c MIXERCONTROL_CONTROLTYPE_SIGNED><nl>
  3100. * <c MIXERCONTROL_CONTROLTYPE_DECIBELS><nl>
  3101. *
  3102. * <c MIXERCONTROL_CONTROLTYPE_SLIDER><nl>
  3103. * <c MIXERCONTROL_CONTROLTYPE_PAN><nl>
  3104. * <c MIXERCONTROL_CONTROLTYPE_QSOUNDPAN><nl>
  3105. *
  3106. * @tagname tMIXERCONTROLDETAILS_SIGNED
  3107. *
  3108. * @othertype MIXERCONTROLDETAILS_SIGNED FAR * | LPMIXERCONTROLDETAILS_SIGNED |
  3109. * A pointer to a <t MIXERCONTROLDETAILS_SIGNED> structure.
  3110. *
  3111. * @othertype MIXERCONTROLDETAILS_SIGNED * | PMIXERCONTROLDETAILS_SIGNED |
  3112. * A pointer to a <t MIXERCONTROLDETAILS_SIGNED> structure.
  3113. *
  3114. * @xref <t MIXERCONTROLDETAILS_UNSIGNED>, <t MIXERCONTROLDETAILS_BOOLEAN>,
  3115. * <t MIXERCONTROLDETAILS_LISTTEXT>, <f mixerGetControlDetails>,
  3116. * <f mixerSetControlDetails>, <t MIXERCONTROL>
  3117. *
  3118. **/
  3119. /*--------------------------------------------------------------------------;
  3120. *
  3121. * @doc EXTERNAL MIXER SDK STRUCTURE
  3122. *
  3123. * @types MIXERCONTROLDETAILS_UNSIGNED | The <t MIXERCONTROLDETAILS_UNSIGNED>
  3124. * structure is used to get and set unsigned type control details for
  3125. * an audio mixer control. Refer to the control type description for
  3126. * the desired control to determine what details structure to use.
  3127. *
  3128. * @field DWORD | dwValue | Specifies an unsigned integer value for a single
  3129. * item or channel. This value must be inclusively within the bounds
  3130. * given in the <e MIXERCONTROL.Bounds> structure member of the
  3131. * <t MIXERCONTROL> structure for unsigned integer controls.
  3132. *
  3133. * @comm The following standard control types use the
  3134. * <t MIXERCONTROLDETAILS_UNSIGNED> structure for getting and setting
  3135. * details:
  3136. *
  3137. * <c MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER><nl>
  3138. *
  3139. * <c MIXERCONTROL_CONTROLTYPE_UNSIGNED><nl>
  3140. * <c MIXERCONTROL_CONTROLTYPE_PERCENT><nl>
  3141. *
  3142. * <c MIXERCONTROL_CONTROLTYPE_FADER><nl>
  3143. * <c MIXERCONTROL_CONTROLTYPE_VOLUME><nl>
  3144. * <c MIXERCONTROL_CONTROLTYPE_BASS><nl>
  3145. * <c MIXERCONTROL_CONTROLTYPE_TREBLE><nl>
  3146. * <c MIXERCONTROL_CONTROLTYPE_EQUALIZER><nl>
  3147. *
  3148. * <c MIXERCONTROL_CONTROLTYPE_MICROTIME><nl>
  3149. * <c MIXERCONTROL_CONTROLTYPE_MILLITIME><nl>
  3150. *
  3151. * @tagname tMIXERCONTROLDETAILS_UNSIGNED
  3152. *
  3153. * @othertype MIXERCONTROLDETAILS_UNSIGNED FAR * | LPMIXERCONTROLDETAILS_UNSIGNED |
  3154. * A pointer to a <t MIXERCONTROLDETAILS_UNSIGNED> structure.
  3155. *
  3156. * @othertype MIXERCONTROLDETAILS_UNSIGNED * | PMIXERCONTROLDETAILS_UNSIGNED |
  3157. * A pointer to a <t MIXERCONTROLDETAILS_UNSIGNED> structure.
  3158. *
  3159. * @xref <t MIXERCONTROLDETAILS_SIGNED>, <t MIXERCONTROLDETAILS_BOOLEAN>,
  3160. * <t MIXERCONTROLDETAILS_LISTTEXT>, <f mixerGetControlDetails>,
  3161. * <f mixerSetControlDetails>, <t MIXERCONTROL>
  3162. *
  3163. **/
  3164. /*--------------------------------------------------------------------------;
  3165. *
  3166. * @doc EXTERNAL MIXER SDK STRUCTURE
  3167. *
  3168. * @types MIXERCONTROLDETAILS | The <t MIXERCONTROLDETAILS> structure
  3169. * references control detail structures to retrieve or set state
  3170. * information of an audio mixer control. All members of this structure
  3171. * must be initialized before calling the <f mixerGetControlDetails>
  3172. * and <f mixerSetControlDetails> functions.
  3173. *
  3174. * @field DWORD | cbStruct | Specifies the size, in bytes, of the
  3175. * <t MIXERCONTROLDETAILS> structure. This member must be initialized
  3176. * before calling the <f mixerGetControlDetails> and
  3177. * <f mixerSetControlDetails> functions. The size specified in this
  3178. * member must be large enough to contain the base
  3179. * <t MIXERCONTROLDETAILS> structure. When the <f mixerGetControlDetails>
  3180. * function returns, this member contains the actual size of the
  3181. * information returned. The returned information will never exceed
  3182. * the requested size and will never be smaller than the base
  3183. * <t MIXERCONTROLDETAILS> structure.
  3184. *
  3185. * @field DWORD | dwControlID | Specifies the control identifier to get or
  3186. * set details on. This member must always be initialized before calling
  3187. * the <f mixerGetControlDetails> and <f mixerSetControlDetails>
  3188. * functions.
  3189. *
  3190. * @field DWORD | cChannels | Specifies the number of channels to get or
  3191. * set details for. This member can be one of the following values for a
  3192. * control.
  3193. *
  3194. * 1. If the details for the control are expected on all channels for
  3195. * a line, then this member must be equal the <e MIXERLINE.cChannels>
  3196. * member of the <t MIXERLINE> structure.
  3197. *
  3198. * 2. If the control is a <c MIXERCONTROL_CONTROLF_UNIFORM> control, then
  3199. * this member must be set to one.
  3200. *
  3201. * 3. If the control is not uniform, but the application wishes to
  3202. * get and set all channels as if they were uniform, then this member
  3203. * should be set to one.
  3204. *
  3205. * 4. If the control is a <c MIXERCONTROL_CONTROLTYPE_CUSTOM> control,
  3206. * then this member must be zero.
  3207. *
  3208. * An application is not allowed to specify any value that comes
  3209. * between one and the number of channels for the line. For example,
  3210. * specifying two or three for a four channel line is not valid.
  3211. * This member can never be zero for non-custom control types.
  3212. *
  3213. * @field DWORD | cMultipleItems | Specifies the number of multiple items
  3214. * per channel to get or set details for. This member can be one of
  3215. * the following values for a control.
  3216. *
  3217. * 1. If the control is not a <c MIXERCONTROL_CONTROLF_MULTIPLE> control,
  3218. * then this member must be zero.
  3219. *
  3220. * 2. If the control is a <c MIXERCONTROL_CONTROLF_MULTIPLE> control,
  3221. * then this member must be equal to the <e MIXERCONTROL.cMultipleItems>
  3222. * member of the <t MIXERCONTROL> structure.
  3223. *
  3224. * 3. If the control is a <c MIXERCONTROL_CONTROLTYPE_CUSTOM> control,
  3225. * then this member must be zero unless the
  3226. * <c MIXER_SETCONTROLDETAILSF_CUSTOM> flag is specified for the
  3227. * <f mixerSetControlDetails> function. In this case, the
  3228. * <e MIXERCONTROLDETAILS.cMultipleItems> member overlaps with the
  3229. * <e MIXERCONTROLDETAILS.hwndOwner> member and is therefore the value
  3230. * of the window handle.
  3231. *
  3232. * An application is not allowed to specify any value other than the
  3233. * value specified in the <e MIXERCONTROL.cMultipleItems> member of
  3234. * the <t MIXERCONTROL> structure for a <c MIXERCONTROL_CONTROLF_MULTIPLE>
  3235. * control.
  3236. *
  3237. * @field DWORD | cbDetails | Specifies the size, in bytes, of a single
  3238. * details structure. This size must be the exact size of the correct
  3239. * details structure. There are currently four different details
  3240. * structures:
  3241. *
  3242. * @flag <t MIXERCONTROLDETAILS_UNSIGNED> | Defines an unsigned
  3243. * value for a mixer line control.
  3244. *
  3245. * @flag <t MIXERCONTROLDETAILS_SIGNED> | Defines an signed
  3246. * value for a mixer line control.
  3247. *
  3248. * @flag <t MIXERCONTROLDETAILS_BOOLEAN> | Defines a Boolean
  3249. * value for a mixer line control.
  3250. *
  3251. * @flag <t MIXERCONTROLDETAILS_LISTTEXT> | Defines a list text
  3252. * buffer for a mixer line control.
  3253. *
  3254. * Refer to the description of the control type for information on what
  3255. * details structure is appropriate for a specific control.
  3256. *
  3257. * If the control is a <c MIXERCONTROL_CONTROLTYPE_CUSTOM> control,
  3258. * then this member must be equal to the <e MIXERCONTROL.cbCustomData>
  3259. * member of the <t MIXERCONTROL> structure.
  3260. *
  3261. * @field LPVOID | paDetails | Points to an array of one or more details
  3262. * structures to get or set details for the specified control in. The
  3263. * required size for this buffer is computed as follows:
  3264. *
  3265. * 1. For controls that are not <c MIXERCONTROL_CONTROLF_MULTIPLE> types,
  3266. * the size of this buffer is the product of the
  3267. * <e MIXERCONTROLDETAILS.cChannels> and <e MIXERCONTROLDETAILS.cbDetails>
  3268. * members of the <t MIXERCONTROLDETAILS> structure.
  3269. *
  3270. * 2. For controls that are <c MIXERCONTROL_CONTROLF_MULTIPLE> types,
  3271. * the size of this buffer is the product of the
  3272. * <e MIXERCONTROLDETAILS.cChannels>, <e MIXERCONTROLDETAILS.cMultipleItems>
  3273. * and <e MIXERCONTROLDETAILS.cbDetails> members of the
  3274. * <t MIXERCONTROLDETAILS> structure.
  3275. *
  3276. * The layout of the details elements in this array are as follows:
  3277. *
  3278. * 1. For controls that are not <c MIXERCONTROL_CONTROLF_MULTIPLE> types,
  3279. * each element index is equivalent to the zero based channel that it
  3280. * affects. That is, <e MIXERCONTROLDETAILS.paDetails>[0] is for the
  3281. * left channel, <e MIXERCONTROLDETAILS.paDetails>[1] is for the
  3282. * right channel.
  3283. *
  3284. * 2. For controls that are <c MIXERCONTROL_CONTROLF_MULTIPLE> types,
  3285. * the array can be thought of as a two dimensional array that is
  3286. * 'channel major'. That is, all multiple items for the left channel
  3287. * are given, then all multiple items for the right channel, etc.
  3288. *
  3289. * If the control is a <c MIXERCONTROL_CONTROLTYPE_CUSTOM> control,
  3290. * then this member must point to a buffer that is at least large
  3291. * enough to hold the size, in bytes, specified by the
  3292. * <e MIXERCONTROL.cbCustomData> member of the <t MIXERCONTROL>
  3293. * structure.
  3294. *
  3295. * @tagname tMIXERCONTROLDETAILS
  3296. *
  3297. * @othertype MIXERCONTROLDETAILS FAR * | LPMIXERCONTROLDETAILS | A pointer
  3298. * to a <t MIXERCONTROLDETAILS> structure.
  3299. *
  3300. * @othertype MIXERCONTROLDETAILS * | PMIXERCONTROLDETAILS | A pointer
  3301. * to a <t MIXERCONTROLDETAILS> structure.
  3302. *
  3303. * @ex So the following example shows how to address a single item in a
  3304. * multiple item control for using the <t MIXERCONTROLDETAILS_SIGNED>
  3305. * details structure. |
  3306. * {
  3307. * MIXERCONTROLDETAILS mxcd;
  3308. * PMIXERCONTROLDETAILS_SIGNED pamxcd_s;
  3309. * PMIXERCONTROLDETAILS_SIGNED pmxcd_s;
  3310. *
  3311. * //
  3312. * // 'mxcd' is assumed to be a valid MIXERCONTROLDETAILS
  3313. * // structure.
  3314. * //
  3315. * // 'channel' is assumed to be a valid channel ranging from zero
  3316. * // to one less than the number of channels available for the
  3317. * // signed control.
  3318. * //
  3319. * // 'item' is assumed to be a valid item index ranging from zero
  3320. * // to one less than the number of 'multiple items' stored in
  3321. * // the variable called 'cMultipleItems'.
  3322. * //
  3323. * pamxcd_s = (PMIXERCONTROLDETAILS_SIGNED)mxcd.paDetails;
  3324. * pmxcd_s = &pamxcd_s[(channel * cMultipleItems) + item];
  3325. * }
  3326. *
  3327. * @xref <f mixerGetLineControls>, <f mixerGetControlDetails>,
  3328. * <f mixerSetControlDetails>, <t MIXERCONTROL>
  3329. *
  3330. **/
  3331. /*--------------------------------------------------------------------------;
  3332. *
  3333. * @doc EXTERNAL MIXER SDK API
  3334. *
  3335. * @api MMRESULT | mixerGetControlDetails | The <f mixerGetControlDetails>
  3336. * function is used to retrieve details on a single control associated
  3337. * with an audio mixer device line.
  3338. *
  3339. * @parm <c HMIXEROBJ> | hmxobj | Specifies a handle to the audio mixer
  3340. * device object to get control details for.
  3341. *
  3342. * @parm LPMIXERCONTROLDETAILS | pmxcd | Points to a <t MIXERCONTROLDETAILS>
  3343. * structure. This structure is used to reference control detail
  3344. * structures to be filled with state information about the control.
  3345. * See the comments for each query flag passed through <p fdwDetails>
  3346. * for details on what members of the <t MIXERCONTROLDETAILS> structure
  3347. * must be initialized before calling the <f mixerGetControlDetails>
  3348. * function. Note that in all cases, the <e MIXERCONTROLDETAILS.cbStruct>
  3349. * member of the <t MIXERCONTROLDETAILS> structure must be initialized
  3350. * to be the size, in bytes, of the <t MIXERCONTROLDETAILS> structure.
  3351. *
  3352. * @parm DWORD | fdwDetails | Specifies flags for getting details on
  3353. * a control.
  3354. *
  3355. * @flag <c MIXER_GETCONTROLDETAILSF_VALUE> | If this flag is specified,
  3356. * the application is interested in getting the current value(s) for a
  3357. * control. The <e MIXERCONTROLDETAILS.paDetails> member of the
  3358. * <t MIXERCONTROLDETAILS> points to one or more details structures of
  3359. * the correct type for the control type. Refer to the description of the
  3360. * <t MIXERCONTROLDETAILS> structure for information on what each member
  3361. * of this structure must be initialized before calling the
  3362. * <f mixerGetControlDetails> function.
  3363. *
  3364. * @flag <c MIXER_GETCONTROLDETAILSF_LISTTEXT> | If this flag is specified,
  3365. * the <e MIXERCONTROLDETAILS.paDetails> member of the <t MIXERCONTROLDETAILS>
  3366. * structure points to one or more <t MIXERCONTROLDETAILS_LISTTEXT>
  3367. * structures to receive text labels for multiple item controls. Note
  3368. * that an application must get all list text items for a multiple item
  3369. * control at once. Refer to the description of the <t MIXERCONTROLDETAILS>
  3370. * structure for information on what each member of this structure must
  3371. * be initialized before calling the <f mixerGetControlDetails> function.
  3372. * This flag cannot be used with <c MIXERCONTROL_CONTROLTYPE_CUSTOM>
  3373. * controls.
  3374. *
  3375. * @flag <c MIXER_OBJECTF_MIXER> | Specifies that <p hmxobj> is an audio
  3376. * mixer device identifier in the range of zero to one less than the
  3377. * number of devices returned by <f mixerGetNumDevs>. This flag is
  3378. * optional.
  3379. *
  3380. * @flag <c MIXER_OBJECTF_HMIXER> | Specifies that <p hmxobj> is a mixer
  3381. * device handle returned by <f mixerOpen>. This flag is optional.
  3382. *
  3383. * @flag <c MIXER_OBJECTF_WAVEOUT> | Specifies that <p hmxobj> is a
  3384. * waveform output device identifier in the range of zero to one less
  3385. * than the number of devices returned by <f waveOutGetNumDevs>.
  3386. *
  3387. * @flag <c MIXER_OBJECTF_HWAVEOUT> | Specifies that <p hmxobj> is a
  3388. * waveform output handle returned by <f waveOutOpen>.
  3389. *
  3390. * @flag <c MIXER_OBJECTF_WAVEIN> | Specifies that <p hmxobj> is a
  3391. * waveform input device identifier in the range of zero to one less
  3392. * than the number of devices returned by <f waveInGetNumDevs>.
  3393. *
  3394. * @flag <c MIXER_OBJECTF_HWAVEIN> | Specifies that <p hmxobj> is a
  3395. * waveform input handle returned by <f midiInOpen>.
  3396. *
  3397. * @flag <c MIXER_OBJECTF_MIDIOUT> | Specifies that <p hmxobj> is a MIDI
  3398. * output device identifier in the range of zero to one less than the
  3399. * number of devices returned by <f midiOutGetNumDevs>.
  3400. *
  3401. * @flag <c MIXER_OBJECTF_HMIDIOUT> | Specifies that <p hmxobj> is a
  3402. * MIDI output handle returned by <f midiOutOpen>.
  3403. *
  3404. * @flag <c MIXER_OBJECTF_MIDIIN> | Specifies that <p hmxobj> is a MIDI
  3405. * input device identifier in the range of zero to one less than the
  3406. * number of devices returned by <f midiInGetNumDevs>.
  3407. *
  3408. * @flag <c MIXER_OBJECTF_HMIDIIN> | Specifies that <p hmxobj> is a MIDI
  3409. * input handle returned by <f midiInOpen>.
  3410. *
  3411. * @flag <c MIXER_OBJECTF_AUX> | Specifies that <p hmxobj> is an
  3412. * auxiliary device identifier in the range of zero to one less than the
  3413. * number of devices returned by <f auxGetNumDevs>.
  3414. *
  3415. * @rdesc The return value is zero if the function is successful. Otherwise,
  3416. * it returns a non-zero error number. Possible error returns include
  3417. * the following:
  3418. *
  3419. * @flag <c MMSYSERR_BADDEVICEID> | The <p hmxobj> argument specifies an
  3420. * invalid device identifier.
  3421. *
  3422. * @flag <c MMSYSERR_INVALHANDLE> | The <p hmxobj> argument specifies an
  3423. * invalid handle.
  3424. *
  3425. * @flag <c MMSYSERR_INVALFLAG> | One or more flags are invalid.
  3426. *
  3427. * @flag <c MMSYSERR_INVALPARAM> | One or more arguments passed is
  3428. * invalid.
  3429. *
  3430. * @flag <c MMSYSERR_NODRIVER> | No audio mixer device is available for
  3431. * the object specified by <p hmxobj>.
  3432. *
  3433. * @flag <c MIXERR_INVALCONTROL> | The control reference is invalid.
  3434. *
  3435. * @xref <t MIXERCONTROLDETAILS>, <t MIXERCONTROL>, <f mixerGetLineControls>,
  3436. * <f mixerOpen>, <f mixerSetControlDetails>
  3437. *
  3438. **/
  3439. MMRESULT APIENTRY mixerGetControlDetailsA(
  3440. HMIXEROBJ hmxobj,
  3441. LPMIXERCONTROLDETAILS pmxcd,
  3442. DWORD fdwDetails
  3443. )
  3444. {
  3445. MIXERCONTROLDETAILS mxcd;
  3446. MMRESULT mmr;
  3447. int cDetails;
  3448. //
  3449. // Everything is OK unless it's MIXER_GETCONTROLDETAILSF_LISTTEXT
  3450. //
  3451. if ((MIXER_GETCONTROLDETAILSF_QUERYMASK & fdwDetails) !=
  3452. MIXER_GETCONTROLDETAILSF_LISTTEXT) {
  3453. return mixerGetControlDetails(hmxobj, pmxcd, fdwDetails);
  3454. }
  3455. V_WPOINTER(pmxcd, sizeof(DWORD), MMSYSERR_INVALPARAM);
  3456. //
  3457. // the structure header for MIXERCONTROLDETAILS must be at least the
  3458. // minimum size
  3459. //
  3460. if (sizeof(MIXERCONTROLDETAILS) > pmxcd->cbStruct)
  3461. {
  3462. DebugErr1(DBF_ERROR, "mixerGetControlDetails: structure size too small or cbStruct not initialized (%lu).", pmxcd->cbStruct);
  3463. return (MMSYSERR_INVALPARAM);
  3464. }
  3465. V_WPOINTER(pmxcd, pmxcd->cbStruct, MMSYSERR_INVALPARAM);
  3466. if (sizeof(MIXERCONTROLDETAILS_LISTTEXTA) < pmxcd->cbDetails) {
  3467. DebugErr1(DBF_ERROR, "mixerGetControlDetails: structure size too small or cbDetails not initialized for _LISTTEXT (%lu).", pmxcd->cbDetails);
  3468. return (MMSYSERR_INVALPARAM);
  3469. }
  3470. //
  3471. // Allocate space for the return structure.
  3472. //
  3473. mxcd = *pmxcd;
  3474. cDetails = pmxcd->cChannels * pmxcd->cMultipleItems;
  3475. mxcd.paDetails =
  3476. (PVOID)LocalAlloc(LPTR, cDetails *
  3477. sizeof(MIXERCONTROLDETAILS_LISTTEXTW));
  3478. mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXTW);
  3479. if (mxcd.paDetails == NULL) {
  3480. return MMSYSERR_NOMEM;
  3481. }
  3482. //
  3483. // Call the UNICODE version
  3484. //
  3485. mmr = mixerGetControlDetails(hmxobj, &mxcd, fdwDetails);
  3486. if (mmr != MMSYSERR_NOERROR) {
  3487. LocalFree((HLOCAL)(mxcd.paDetails));
  3488. return mmr;
  3489. }
  3490. //
  3491. // Copy the return data back
  3492. //
  3493. {
  3494. int i;
  3495. PMIXERCONTROLDETAILS_LISTTEXTW pDetailsW;
  3496. PMIXERCONTROLDETAILS_LISTTEXTA pDetailsA;
  3497. for (i = 0,
  3498. pDetailsW = (PMIXERCONTROLDETAILS_LISTTEXTW)mxcd.paDetails,
  3499. pDetailsA = (PMIXERCONTROLDETAILS_LISTTEXTA)pmxcd->paDetails;
  3500. i < cDetails;
  3501. i++,
  3502. pDetailsW++,
  3503. *(LPBYTE *)&pDetailsA += pmxcd->cbDetails)
  3504. {
  3505. pDetailsA->dwParam1 = pDetailsW->dwParam1;
  3506. pDetailsA->dwParam2 = pDetailsW->dwParam2;
  3507. Iwcstombs(pDetailsA->szName, pDetailsW->szName,
  3508. sizeof(pDetailsA->szName));
  3509. }
  3510. }
  3511. LocalFree((HLOCAL)mxcd.paDetails);
  3512. return mmr;
  3513. } // mixerGetControlDetailsA()
  3514. MMRESULT APIENTRY mixerGetControlDetails(
  3515. HMIXEROBJ hmxobj,
  3516. LPMIXERCONTROLDETAILS pmxcd,
  3517. DWORD fdwDetails
  3518. )
  3519. {
  3520. DWORD fdwMxObjType;
  3521. MMRESULT mmr;
  3522. UINT uMxId;
  3523. UINT cDetails;
  3524. BOOL fResource;
  3525. V_DFLAGS(fdwDetails, MIXER_GETCONTROLDETAILSF_VALID, mixerGetControlDetails, MMSYSERR_INVALFLAG);
  3526. V_WPOINTER(pmxcd, sizeof(DWORD), MMSYSERR_INVALPARAM);
  3527. //
  3528. // the structure header for MIXERCONTROLDETAILS must be at least the
  3529. // minimum size
  3530. //
  3531. if (sizeof(MIXERCONTROLDETAILS) > pmxcd->cbStruct)
  3532. {
  3533. DebugErr1(DBF_ERROR, "mixerGetControlDetails: structure size too small or cbStruct not initialized (%lu).", pmxcd->cbStruct);
  3534. return (MMSYSERR_INVALPARAM);
  3535. }
  3536. V_WPOINTER(pmxcd, pmxcd->cbStruct, MMSYSERR_INVALPARAM);
  3537. switch (MIXER_GETCONTROLDETAILSF_QUERYMASK & fdwDetails)
  3538. {
  3539. case MIXER_GETCONTROLDETAILSF_VALUE:
  3540. //
  3541. // if both cChannels and cMultipleItems are zero, it is a
  3542. // custom control
  3543. //
  3544. if ((0 == pmxcd->cChannels) && (0 == pmxcd->cMultipleItems))
  3545. {
  3546. if (0 == pmxcd->cbDetails)
  3547. {
  3548. DebugErr(DBF_ERROR, "mixerGetControlDetails: cbDetails cannot be zero.");
  3549. return (MMSYSERR_INVALPARAM);
  3550. }
  3551. V_WPOINTER(pmxcd->paDetails, pmxcd->cbDetails, MMSYSERR_INVALPARAM);
  3552. }
  3553. else
  3554. {
  3555. if (0 == pmxcd->cChannels)
  3556. {
  3557. DebugErr(DBF_ERROR, "mixerGetControlDetails: cChannels for _VALUE cannot be zero.");
  3558. return (MMSYSERR_INVALPARAM);
  3559. }
  3560. if (pmxcd->cbDetails < sizeof(MIXERCONTROLDETAILS_SIGNED))
  3561. {
  3562. DebugErr1(DBF_ERROR, "mixerGetControlDetails: structure size too small or cbDetails not initialized (%lu).", pmxcd->cbDetails);
  3563. return (MMSYSERR_INVALPARAM);
  3564. }
  3565. //
  3566. //
  3567. //
  3568. cDetails = (UINT)pmxcd->cChannels;
  3569. if (0 != pmxcd->cMultipleItems)
  3570. {
  3571. cDetails *= (UINT)pmxcd->cMultipleItems;
  3572. }
  3573. V_WPOINTER(pmxcd->paDetails, cDetails * pmxcd->cbDetails, MMSYSERR_INVALPARAM);
  3574. }
  3575. break;
  3576. case MIXER_GETCONTROLDETAILSF_LISTTEXT:
  3577. if (0 == pmxcd->cChannels)
  3578. {
  3579. DebugErr(DBF_ERROR, "mixerGetControlDetails: cChannels for _LISTTEXT cannot be zero.");
  3580. return (MMSYSERR_INVALPARAM);
  3581. }
  3582. if (2 > pmxcd->cMultipleItems)
  3583. {
  3584. DebugErr(DBF_ERROR, "mixerGetControlDetails: cMultipleItems for _LISTTEXT must be 2 or greater.");
  3585. return (MMSYSERR_INVALPARAM);
  3586. }
  3587. if (pmxcd->cbDetails < sizeof(MIXERCONTROLDETAILS_LISTTEXT))
  3588. {
  3589. DebugErr1(DBF_ERROR, "mixerGetControlDetails: structure size too small or cbDetails not initialized (%lu).", pmxcd->cbDetails);
  3590. return (MMSYSERR_INVALPARAM);
  3591. }
  3592. cDetails = (UINT)pmxcd->cChannels * (UINT)pmxcd->cMultipleItems;
  3593. V_WPOINTER(pmxcd->paDetails, cDetails * pmxcd->cbDetails, MMSYSERR_INVALPARAM);
  3594. break;
  3595. default:
  3596. DebugErr1(DBF_ERROR, "mixerGetControlDetails: invalid query flags (%.08lXh).",
  3597. MIXER_GETCONTROLDETAILSF_QUERYMASK & fdwDetails);
  3598. return (MMSYSERR_INVALFLAG);
  3599. }
  3600. ClientUpdatePnpInfo();
  3601. //
  3602. //
  3603. //
  3604. fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwDetails);
  3605. fResource = FALSE;
  3606. AcquireHandleListResourceShared();
  3607. // Checking for the type of mixer object. If it is a non-mixer type
  3608. // calling IMixerMesssageID (called by IMixerGetID) with the shared
  3609. // resource will deadlock.
  3610. if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
  3611. (MIXER_OBJECTF_HMIXER == fdwMxObjType))
  3612. {
  3613. if (BAD_HANDLE(hmxobj, TYPE_MIXER))
  3614. {
  3615. ReleaseHandleListResource();
  3616. }
  3617. else
  3618. {
  3619. fResource = TRUE;
  3620. }
  3621. }
  3622. else
  3623. {
  3624. ReleaseHandleListResource();
  3625. }
  3626. mmr = IMixerGetID(hmxobj, &uMxId, NULL, fdwMxObjType);
  3627. if (MMSYSERR_NOERROR != mmr)
  3628. {
  3629. if (fResource)
  3630. ReleaseHandleListResource();
  3631. return (mmr);
  3632. }
  3633. if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
  3634. (MIXER_OBJECTF_HMIXER == fdwMxObjType))
  3635. {
  3636. //
  3637. // if a mixer device id was passed, then null hmx so we use the
  3638. // correct message sender below
  3639. //
  3640. if ((UINT_PTR)hmxobj == uMxId)
  3641. hmxobj = NULL;
  3642. }
  3643. else
  3644. {
  3645. hmxobj = NULL;
  3646. }
  3647. //
  3648. //
  3649. //
  3650. //
  3651. if (NULL != hmxobj)
  3652. {
  3653. mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj,
  3654. MXDM_GETCONTROLDETAILS,
  3655. (DWORD_PTR)pmxcd,
  3656. fdwDetails);
  3657. }
  3658. else
  3659. {
  3660. mmr = (MMRESULT)IMixerMessageId(uMxId,
  3661. MXDM_GETCONTROLDETAILS,
  3662. (DWORD_PTR)pmxcd,
  3663. fdwDetails);
  3664. }
  3665. return (mmr);
  3666. } // mixerGetControlDetails()
  3667. /*--------------------------------------------------------------------------;
  3668. *
  3669. * @doc EXTERNAL MIXER SDK API
  3670. *
  3671. * @api MMRESULT | mixerSetControlDetails | The <f mixerSetControlDetails>
  3672. * function is used to set details on a single control associated
  3673. * with an audio mixer device line.
  3674. *
  3675. * @parm <c HMIXEROBJ> | hmxobj | Specifies a handle to the audio mixer
  3676. * device object to set control details for.
  3677. *
  3678. * @parm LPMIXERCONTROLDETAILS | pmxcd | Points to a <t MIXERCONTROLDETAILS>
  3679. * structure. This structure is used to reference control detail
  3680. * structures to that contain the desired state for the control.
  3681. * See the description for the <t MIXERCONTROLDETAILS> structure
  3682. * to determine what members of this structure must be initialized
  3683. * before calling the <f mixerSetControlDetails> function. Note that
  3684. * in all cases, the <e MIXERCONTROLDETAILS.cbStruct> member of the
  3685. * <t MIXERCONTROLDETAILS> structure must be initialized
  3686. * to be the size, in bytes, of the <t MIXERCONTROLDETAILS> structure.
  3687. *
  3688. * @parm DWORD | fdwDetails | Specifies flags for setting details for
  3689. * a control.
  3690. *
  3691. * @flag <c MIXER_SETCONTROLDETAILSF_VALUE> | If this flag is specified,
  3692. * the application is interested in setting the current value(s) for a
  3693. * control. The <e MIXERCONTROLDETAILS.paDetails> member of the
  3694. * <t MIXERCONTROLDETAILS> points to one or more details structures of
  3695. * the correct type for the control type. Refer to the description of the
  3696. * <t MIXERCONTROLDETAILS> structure for information on what each member
  3697. * of this structure must be initialized before calling the
  3698. * <f mixerSetControlDetails> function.
  3699. *
  3700. * @flag <c MIXER_SETCONTROLDETAILSF_CUSTOM> | If this flag is specified,
  3701. * the application is asking the mixer device to display a custom
  3702. * dialog for the specified custom mixer control. The handle for the
  3703. * owning window is specified in the <e MIXERCONTROLDETAILS.hwndOwner>
  3704. * member (this handle may, validly, be NULL). The mixer device will
  3705. * gather the required information from the user and return the data
  3706. * in the specified buffer. This data may then be saved by the
  3707. * application and later set back to the same state using the
  3708. * <c MIXER_SETCONTROLDETAILSF_VALUE> flag. If an application only
  3709. * needs to get the current state of a custom mixer control without
  3710. * displaying a dialog, then the <f mixerGetControlDetails> function
  3711. * can be used with the <c MIXER_GETCONTROLDETAILSF_VALUE> flag.
  3712. *
  3713. * @flag <c MIXER_OBJECTF_MIXER> | Specifies that <p hmxobj> is an audio
  3714. * mixer device identifier in the range of zero to one less than the
  3715. * number of devices returned by <f mixerGetNumDevs>. This flag is
  3716. * optional.
  3717. *
  3718. * @flag <c MIXER_OBJECTF_HMIXER> | Specifies that <p hmxobj> is a mixer
  3719. * device handle returned by <f mixerOpen>. This flag is optional.
  3720. *
  3721. * @flag <c MIXER_OBJECTF_WAVEOUT> | Specifies that <p hmxobj> is a
  3722. * waveform output device identifier in the range of zero to one less
  3723. * than the number of devices returned by <f waveOutGetNumDevs>.
  3724. *
  3725. * @flag <c MIXER_OBJECTF_HWAVEOUT> | Specifies that <p hmxobj> is a
  3726. * waveform output handle returned by <f waveOutOpen>.
  3727. *
  3728. * @flag <c MIXER_OBJECTF_WAVEIN> | Specifies that <p hmxobj> is a
  3729. * waveform input device identifier in the range of zero to one less
  3730. * than the number of devices returned by <f waveInGetNumDevs>.
  3731. *
  3732. * @flag <c MIXER_OBJECTF_HWAVEIN> | Specifies that <p hmxobj> is a
  3733. * waveform input handle returned by <f midiInOpen>.
  3734. *
  3735. * @flag <c MIXER_OBJECTF_MIDIOUT> | Specifies that <p hmxobj> is a MIDI
  3736. * output device identifier in the range of zero to one less than the
  3737. * number of devices returned by <f midiOutGetNumDevs>.
  3738. *
  3739. * @flag <c MIXER_OBJECTF_HMIDIOUT> | Specifies that <p hmxobj> is a
  3740. * MIDI output handle returned by <f midiOutOpen>.
  3741. *
  3742. * @flag <c MIXER_OBJECTF_MIDIIN> | Specifies that <p hmxobj> is a MIDI
  3743. * input device identifier in the range of zero to one less than the
  3744. * number of devices returned by <f midiInGetNumDevs>.
  3745. *
  3746. * @flag <c MIXER_OBJECTF_HMIDIIN> | Specifies that <p hmxobj> is a MIDI
  3747. * input handle returned by <f midiInOpen>.
  3748. *
  3749. * @flag <c MIXER_OBJECTF_AUX> | Specifies that <p hmxobj> is an
  3750. * auxiliary device identifier in the range of zero to one less than the
  3751. * number of devices returned by <f auxGetNumDevs>.
  3752. *
  3753. * @rdesc The return value is zero if the function is successful. Otherwise,
  3754. * it returns a non-zero error number. Possible error returns include
  3755. * the following:
  3756. *
  3757. * @flag <c MMSYSERR_BADDEVICEID> | The <p hmxobj> argument specifies an
  3758. * invalid device identifier.
  3759. *
  3760. * @flag <c MMSYSERR_INVALHANDLE> | The <p hmxobj> argument specifies an
  3761. * invalid handle.
  3762. *
  3763. * @flag <c MMSYSERR_INVALFLAG> | One or more flags are invalid.
  3764. *
  3765. * @flag <c MMSYSERR_INVALPARAM> | One or more arguments passed is
  3766. * invalid.
  3767. *
  3768. * @flag <c MMSYSERR_NODRIVER> | No audio mixer device is available for
  3769. * the object specified by <p hmxobj>.
  3770. *
  3771. * @flag <c MIXERR_INVALCONTROL> | The control reference is invalid.
  3772. *
  3773. * @xref <t MIXERCONTROLDETAILS>, <t MIXERCONTROL>, <f mixerGetLineControls>,
  3774. * <f mixerOpen>, <f mixerGetControlDetails>
  3775. *
  3776. **/
  3777. MMRESULT APIENTRY mixerSetControlDetails(
  3778. HMIXEROBJ hmxobj,
  3779. LPMIXERCONTROLDETAILS pmxcd,
  3780. DWORD fdwDetails
  3781. )
  3782. {
  3783. DWORD fdwMxObjType;
  3784. MMRESULT mmr;
  3785. UINT uMxId;
  3786. UINT cDetails;
  3787. BOOL fResource;
  3788. V_DFLAGS(fdwDetails, MIXER_SETCONTROLDETAILSF_VALID, mixerSetControlDetails, MMSYSERR_INVALFLAG);
  3789. V_WPOINTER(pmxcd, sizeof(DWORD), MMSYSERR_INVALPARAM);
  3790. //
  3791. // the structure header for MIXERCONTROLDETAILS must be at least the
  3792. // minimum size
  3793. //
  3794. if (sizeof(MIXERCONTROLDETAILS) > pmxcd->cbStruct)
  3795. {
  3796. DebugErr1(DBF_ERROR, "mixerSetControlDetails: structure size too small or cbStruct not initialized (%lu).", pmxcd->cbStruct);
  3797. return (MMSYSERR_INVALPARAM);
  3798. }
  3799. V_WPOINTER(pmxcd, pmxcd->cbStruct, MMSYSERR_INVALPARAM);
  3800. switch (MIXER_SETCONTROLDETAILSF_QUERYMASK & fdwDetails)
  3801. {
  3802. case MIXER_SETCONTROLDETAILSF_VALUE:
  3803. //
  3804. // cChannels is zero for custom controls
  3805. //
  3806. if (0 == pmxcd->cChannels)
  3807. {
  3808. if (0 == pmxcd->cbDetails)
  3809. {
  3810. DebugErr(DBF_ERROR, "mixerSetControlDetails: cbDetails cannot be zero.");
  3811. return (MMSYSERR_INVALPARAM);
  3812. }
  3813. V_WPOINTER(pmxcd->paDetails, pmxcd->cbDetails, MMSYSERR_INVALPARAM);
  3814. //
  3815. //
  3816. //
  3817. if (0 != pmxcd->cMultipleItems)
  3818. {
  3819. DebugErr(DBF_ERROR, "mixerSetControlDetails: cMultipleItems must be zero for custom controls.");
  3820. return (MMSYSERR_INVALPARAM);
  3821. }
  3822. }
  3823. else
  3824. {
  3825. if (pmxcd->cbDetails < sizeof(MIXERCONTROLDETAILS_SIGNED))
  3826. {
  3827. DebugErr1(DBF_ERROR, "mixerSetControlDetails: structure size too small or cbDetails not initialized (%lu).", pmxcd->cbDetails);
  3828. return (MMSYSERR_INVALPARAM);
  3829. }
  3830. cDetails = (UINT)pmxcd->cChannels;
  3831. //
  3832. //
  3833. //
  3834. if (0 != pmxcd->cMultipleItems)
  3835. {
  3836. cDetails *= (UINT)(pmxcd->cMultipleItems);
  3837. }
  3838. V_WPOINTER(pmxcd->paDetails, cDetails * pmxcd->cbDetails, MMSYSERR_INVALPARAM);
  3839. }
  3840. break;
  3841. case MIXER_SETCONTROLDETAILSF_CUSTOM:
  3842. if (0 == pmxcd->cbDetails)
  3843. {
  3844. DebugErr(DBF_ERROR, "mixerSetControlDetails: cbDetails cannot be zero for custom controls.");
  3845. return (MMSYSERR_INVALPARAM);
  3846. }
  3847. if (0 != pmxcd->cChannels)
  3848. {
  3849. DebugErr(DBF_ERROR, "mixerSetControlDetails: cChannels must be zero for custom controls.");
  3850. return (MMSYSERR_INVALPARAM);
  3851. }
  3852. V_WPOINTER(pmxcd->paDetails, pmxcd->cbDetails, MMSYSERR_INVALPARAM);
  3853. //
  3854. //
  3855. //
  3856. if ((NULL != pmxcd->hwndOwner) && !IsWindow(pmxcd->hwndOwner))
  3857. {
  3858. DebugErr1(DBF_ERROR, "mixerSetControlDetails: hwndOwner must be a valid window handle (%.04Xh).", pmxcd->hwndOwner);
  3859. return (MMSYSERR_INVALHANDLE);
  3860. }
  3861. break;
  3862. default:
  3863. DebugErr1(DBF_ERROR, "mixerSetControlDetails: invalid query flags (%.08lXh).",
  3864. MIXER_SETCONTROLDETAILSF_QUERYMASK & fdwDetails);
  3865. return (MMSYSERR_INVALFLAG);
  3866. }
  3867. ClientUpdatePnpInfo();
  3868. //
  3869. //
  3870. //
  3871. fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwDetails);
  3872. fResource = FALSE;
  3873. AcquireHandleListResourceShared();
  3874. // Checking for the type of mixer object. If it is a non-mixer type
  3875. // calling IMixerMesssageID (called by IMixerGetID) with the shared
  3876. // resource will deadlock.
  3877. if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
  3878. (MIXER_OBJECTF_HMIXER == fdwMxObjType))
  3879. {
  3880. if (BAD_HANDLE(hmxobj, TYPE_MIXER))
  3881. {
  3882. ReleaseHandleListResource();
  3883. }
  3884. else
  3885. {
  3886. fResource = TRUE;
  3887. }
  3888. }
  3889. else
  3890. {
  3891. ReleaseHandleListResource();
  3892. }
  3893. mmr = IMixerGetID(hmxobj, &uMxId, NULL, fdwMxObjType);
  3894. if (MMSYSERR_NOERROR != mmr)
  3895. {
  3896. if (fResource)
  3897. ReleaseHandleListResource();
  3898. return (mmr);
  3899. }
  3900. if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
  3901. (MIXER_OBJECTF_HMIXER == fdwMxObjType))
  3902. {
  3903. //
  3904. // if a mixer device id was passed, then null hmx so we use the
  3905. // correct message sender below
  3906. //
  3907. if ((UINT_PTR)hmxobj == uMxId)
  3908. hmxobj = NULL;
  3909. }
  3910. else
  3911. {
  3912. hmxobj = NULL;
  3913. }
  3914. //
  3915. //
  3916. //
  3917. //
  3918. if (NULL != hmxobj)
  3919. {
  3920. mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj,
  3921. MXDM_SETCONTROLDETAILS,
  3922. (DWORD_PTR)pmxcd,
  3923. fdwDetails);
  3924. }
  3925. else
  3926. {
  3927. mmr = (MMRESULT)IMixerMessageId(uMxId,
  3928. MXDM_SETCONTROLDETAILS,
  3929. (DWORD_PTR)pmxcd,
  3930. fdwDetails);
  3931. }
  3932. return (mmr);
  3933. } // mixerSetControlDetails()
  3934. //--------------------------------------------------------------------------;
  3935. //
  3936. // MMRESULT mixerDesertHandle
  3937. //
  3938. // Description:
  3939. // Cleans up the mixer handle and marks it as deserted.
  3940. //
  3941. // Arguments:
  3942. // HMIXER hmx: Mixer handle.
  3943. //
  3944. // Return (MMRESULT): Error code.
  3945. //
  3946. // History:
  3947. // 01/25/99 Fwong Adding Pnp Support.
  3948. //
  3949. //--------------------------------------------------------------------------;
  3950. MMRESULT mixerDesertHandle
  3951. (
  3952. HMIXER hmx
  3953. )
  3954. {
  3955. MMRESULT mmr;
  3956. PMIXERDEV pmxdev;
  3957. PMIXERDEV pmxdevT;
  3958. PMIXERDRV pmxdrv;
  3959. BOOL fClose;
  3960. V_HANDLE_ACQ(hmx, TYPE_MIXER, MMSYSERR_INVALHANDLE);
  3961. ENTER_MM_HANDLE(hmx);
  3962. ReleaseHandleListResource();
  3963. if (IsHandleDeserted(hmx))
  3964. {
  3965. // Handle has already been deserted...
  3966. LEAVE_MM_HANDLE(hmx);
  3967. return (MMSYSERR_NOERROR);
  3968. }
  3969. // Marking handle as deserted
  3970. SetHandleFlag(hmx, MMHANDLE_DESERTED);
  3971. //
  3972. // remove the mixer handle from the linked list
  3973. //
  3974. MIXMGR_ENTER;
  3975. pmxdev = (PMIXERDEV)hmx;
  3976. pmxdrv = pmxdev->pmxdrv;
  3977. if (pmxdev == gpMixerDevHeader)
  3978. {
  3979. gpMixerDevHeader = pmxdev->pmxdevNext;
  3980. }
  3981. else
  3982. {
  3983. for (pmxdevT = gpMixerDevHeader;
  3984. pmxdevT && (pmxdevT->pmxdevNext != pmxdev);
  3985. pmxdevT = pmxdevT->pmxdevNext)
  3986. ;
  3987. if (NULL == pmxdevT)
  3988. {
  3989. DebugErr1(DBF_ERROR,
  3990. "mixerDesertHandle: invalid mixer handle (%.04Xh).",
  3991. hmx);
  3992. MIXMGR_LEAVE;
  3993. LEAVE_MM_HANDLE(hmx);
  3994. return (MMSYSERR_INVALHANDLE);
  3995. }
  3996. pmxdevT->pmxdevNext = pmxdev->pmxdevNext;
  3997. }
  3998. //
  3999. // see if this is the last handle on this open instance
  4000. //
  4001. fClose = TRUE;
  4002. if (gpMixerDevHeader)
  4003. {
  4004. PMIXERDEV pmxdevT2;
  4005. for (pmxdevT2 = gpMixerDevHeader; pmxdevT2; pmxdevT2 = pmxdevT2->pmxdevNext)
  4006. {
  4007. if (pmxdevT2->pmxdrv != pmxdev->pmxdrv) continue;
  4008. if (pmxdevT2->wDevice != pmxdev->wDevice) continue;
  4009. fClose = FALSE;
  4010. break;
  4011. }
  4012. }
  4013. MIXMGR_LEAVE;
  4014. if (fClose)
  4015. {
  4016. EnterCriticalSection(&pmxdev->pmxdrv->MixerCritSec);
  4017. mmr = (*(pmxdrv->drvMessage))(pmxdev->wDevice, MXDM_CLOSE, pmxdev->dwDrvUser, 0L, 0L);
  4018. LeaveCriticalSection(&pmxdev->pmxdrv->MixerCritSec);
  4019. if (MMSYSERR_NOERROR != mmr)
  4020. {
  4021. // Close message failed.
  4022. // Should we put the handle back in the list???
  4023. LEAVE_MM_HANDLE(hmx);
  4024. return mmr;
  4025. }
  4026. }
  4027. LEAVE_MM_HANDLE(hmx);
  4028. mregDecUsage(PTtoH(HMD, pmxdev->pmxdrv));
  4029. return MMSYSERR_NOERROR;
  4030. } // mixerDesertHandle()