Windows NT 4.0 source code leak
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.

4556 lines
161 KiB

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