summaryrefslogtreecommitdiffstats
path: root/private/mvdm/wow16/mmsystem/mixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/wow16/mmsystem/mixer.c')
-rw-r--r--private/mvdm/wow16/mmsystem/mixer.c1950
1 files changed, 1950 insertions, 0 deletions
diff --git a/private/mvdm/wow16/mmsystem/mixer.c b/private/mvdm/wow16/mmsystem/mixer.c
new file mode 100644
index 000000000..36ff0e9f4
--- /dev/null
+++ b/private/mvdm/wow16/mmsystem/mixer.c
@@ -0,0 +1,1950 @@
+//==========================================================================;
+//
+// mixapi.c
+//
+// Copyright (C) 1992-1993 Microsoft Corporation. All Rights Reserved.
+//
+// Description:
+//
+//
+// History:
+// 6/27/93 cjp [curtisp]
+//
+//==========================================================================;
+#define _WINDLL
+#include <windows.h>
+#include <windowsx.h>
+#include <string.h>
+
+#include <mmsystem.h>
+#include <mmddk.h>
+
+#include "mmreg.h"
+#include "mmsysi.h"
+
+//
+// fix a conflict will a bad define in MMREG.H that shipped with NT
+// the define is bogus for some silly Media Vision crap...
+//
+// why not just build MSMIXMGR with a NEW mmreg.h??
+//
+#ifdef MIXERR_BASE
+#undef MIXERR_BASE
+#endif // MIXERR_BASE
+
+
+#define _INC_MMDDK
+#include "msmixmgr.y"
+
+
+#define WODM_MAPPER_STATUS (0x2000)
+#define WAVEOUT_MAPPER_STATUS_DEVICE 0
+#define WIDM_MAPPER_STATUS (0x2000)
+#define WAVEIN_MAPPER_STATUS_DEVICE 0
+
+#include "idrv.h"
+#include "mixmgri.h"
+#include "debug.h"
+
+UINT FAR PASCAL
+mmCallProc32(
+ DWORD uId,
+ DWORD uMsg,
+ DWORD dwInst,
+ DWORD dwP1,
+ DWORD dwP2,
+ DRIVERMSGPROC fp,
+ DWORD dwDirChange );
+
+/* -------------------------------------------------------------------------
+** thunking global variables
+** -------------------------------------------------------------------------
+*/
+DWORD mix32Lib;
+
+BOOL FAR PASCAL
+InitMixerThunks(
+ void
+ );
+
+DWORD CALLBACK
+mxdMessage(
+ UINT uId,
+ UINT uMsg,
+ DWORD dwInstance,
+ DWORD dwParam1,
+ DWORD dwParam2
+ );
+
+#define CHECK_AND_INIT_THUNKS( _x_ ) \
+ if ( (_x_) == 0L ) { \
+ if ( InitMixerThunks() == FALSE ) { \
+ return MMSYSERR_NODRIVER; \
+ } \
+ }
+
+UINT guTotalMixerDevs; // total mixer devices
+DRIVERMSGPROC mix32Message;
+typedef MMDRV MIXERDRV, *PMIXERDRV;
+
+
+//
+//
+//
+typedef struct tMIXERDEV {
+ UINT uHandleType; // for parameter validation
+
+ struct tMIXERDEV *pmxdevNext; /* How quaint, a linked list... */
+ PMIXERDRV pmxdrv;
+ UINT wDevice;
+ DWORD dwDrvUser;
+ UINT uDeviceID;
+
+ DWORD fdwSupport; // from the driver's mixercaps
+ DWORD cDestinations; // from the driver's mixercaps
+
+ DWORD dwCallback; // client's callback and inst data
+ DWORD dwInstance;
+
+ DWORD fdwOpen; /* The open flags the caller used */
+} MIXERDEV, *PMIXERDEV;
+
+PMIXERDEV gpMixerDevHeader = NULL; /* A LL of open devices */
+
+//
+// mixer device driver list--add one to accomodate the MIXER_MAPPER. note
+// that even if we are not compiling with mapper support we need to add
+// one because other code relies on it (for other device mappers).
+//
+MIXERDRV mixerdrv[1];
+
+
+
+
+//==========================================================================;
+//
+// Mixer API's
+//
+//
+//==========================================================================;
+
+//--------------------------------------------------------------------------;
+//
+// DWORD IMixerMapId
+//
+// Description:
+// This function maps a logical id to a device driver table index and
+// physical id.
+//
+// Arguments:
+// PMIXERDRV pmxdrv: The array of mixer drivers.
+//
+// UINT uTotalNumDevs: The total number of mixer devices.
+//
+// UINT uId: The logical id to be mapped.
+//
+// Return (DWORD):
+// The return value contains the dev[] array element id in the high word
+// and the driver physical device number in the low word.
+//
+// Out of range values map to FFFF:FFFF
+//
+// History:
+// 03/17/93 cjp [curtisp]
+//
+//--------------------------------------------------------------------------;
+
+DWORD NEAR PASCAL IMixerMapId(
+ PMIXERDRV pmxdrv,
+ UINT uTotalNumDevs,
+ UINT uId
+)
+{
+ UINT u;
+
+#ifdef MIXER_MAPPER
+ //
+ // the mapper is always the last element of the MIXERDEV array.
+ //
+ if (uId == MIXER_MAPPER)
+ return (MAKELONG(0, MAXMIXERDRIVERS));
+#endif
+
+ if (uId >= uTotalNumDevs)
+ return ((DWORD)-1);
+
+#ifdef DEBUG_RETAIL
+ if (fIdReverse)
+ uId = uTotalNumDevs - 1 - uId;
+#endif
+
+ for (u = 0; u < MAXMIXERDRIVERS; u++)
+ {
+ if (pmxdrv[u].bNumDevs > (BYTE)uId)
+ return (MAKELONG(uId, u));
+
+ uId -= pmxdrv[u].bNumDevs;
+ }
+
+ return ((DWORD)-1);
+} // IMixerMapId()
+
+
+//--------------------------------------------------------------------------;
+//
+// DWORD IMixerMessageHandle
+//
+// Description:
+//
+//
+// Arguments:
+// HMIXER hmx:
+//
+// UINT uMsg:
+//
+// DWORD dwP1:
+//
+// DWORD dwP2:
+//
+// Return (DWORD):
+//
+// History:
+// 03/17/93 cjp [curtisp]
+//
+//--------------------------------------------------------------------------;
+
+DWORD NEAR PASCAL IMixerMessageHandle(
+ HMIXER hmx,
+ UINT uMsg,
+ DWORD dwP1,
+ DWORD dwP2
+)
+{
+ PMIXERDEV pmxd;
+ DWORD dwRc;
+
+ pmxd = (PMIXERDEV)hmx;
+
+ dwRc = ((*(pmxd->pmxdrv->drvMessage))
+ (pmxd->wDevice, uMsg, pmxd->dwDrvUser, dwP1, dwP2));
+
+ return dwRc;
+} // IMixerMessageHandle()
+
+
+//--------------------------------------------------------------------------;
+//
+// DWORD IMixerMessageId
+//
+// Description:
+//
+//
+// Arguments:
+// PMIXERDRV pmxdrv:
+//
+// UINT uTotalNumDevs:
+//
+// UINT uDeviceID:
+//
+// UINT uMsg:
+//
+// DWORD dwParam1:
+//
+// DWORD dwParam2:
+//
+// Return (DWORD):
+//
+// History:
+// 03/17/93 cjp [curtisp]
+//
+//--------------------------------------------------------------------------;
+
+DWORD NEAR PASCAL IMixerMessageId(
+ PMIXERDRV pmxdrv,
+ UINT uTotalNumDevs,
+ UINT uDeviceID,
+ UINT uMsg,
+ DWORD dwParam1,
+ DWORD dwParam2
+)
+{
+ DWORD dwMap;
+ DWORD dwRc;
+
+ dwMap = IMixerMapId(pmxdrv, uTotalNumDevs, uDeviceID);
+
+ if (dwMap == (DWORD)-1)
+ return (MMSYSERR_BADDEVICEID);
+
+ pmxdrv = (PMIXERDRV)&pmxdrv[HIWORD(dwMap)];
+ if (!pmxdrv->drvMessage)
+ return (MMSYSERR_NODRIVER);
+
+ dwRc = ((*(pmxdrv->drvMessage))
+ ((UINT)dwMap, uMsg, 0L, dwParam1, dwParam2));
+
+ return dwRc;
+
+} // IMixerMessageId()
+
+/******************************Public*Routine******************************\
+* mixerGetNumDevs
+*
+*
+*
+* History:
+* dd-mm-93 - StephenE - Created
+*
+\**************************************************************************/
+UINT MIXAPI mixerGetNumDevs(
+ void
+)
+{
+
+ CHECK_AND_INIT_THUNKS(mix32Lib);
+
+ return guTotalMixerDevs;
+}
+
+
+
+/******************************Public*Routine******************************\
+* mixerGetDevCaps
+*
+*
+*
+* History:
+* dd-mm-93 - StephenE - Created
+*
+\**************************************************************************/
+MMRESULT MIXAPI mixerGetDevCaps(
+ UINT uMxId,
+ LPMIXERCAPS pmxcaps,
+ UINT cbmxcaps
+)
+{
+
+ MMRESULT mmr;
+ CHECK_AND_INIT_THUNKS(mix32Lib);
+
+ if (0 == cbmxcaps)
+ return (MMSYSERR_NOERROR);
+
+ V_WPOINTER(pmxcaps, cbmxcaps, MMSYSERR_INVALPARAM);
+
+ if (uMxId >= MAXMIXERDRIVERS)
+ {
+ V_HANDLE((HMIXER)uMxId, TYPE_MIXER, MMSYSERR_INVALHANDLE);
+
+ mmr = (MMRESULT)IMixerMessageHandle((HMIXER)uMxId,
+ MXDM_GETDEVCAPS,
+ (DWORD)pmxcaps,
+ (DWORD)cbmxcaps);
+ }
+ else
+ {
+ if (uMxId >= guTotalMixerDevs)
+ {
+ DebugErr1(DBF_ERROR, "mixerGetDevCaps: mixer device id is out of range (%u).", uMxId);
+ return (MMSYSERR_BADDEVICEID);
+ }
+
+ mmr = (MMRESULT)IMixerMessageId(mixerdrv,
+ guTotalMixerDevs,
+ uMxId,
+ MXDM_GETDEVCAPS,
+ (DWORD)pmxcaps,
+ (DWORD)cbmxcaps);
+ }
+ return mmr;
+}
+
+
+
+/******************************Public*Routine******************************\
+* mixerGetID
+*
+*
+*
+* History:
+* dd-mm-93 - StephenE - Created
+*
+\**************************************************************************/
+MMRESULT MIXAPI mixerGetID(
+ HMIXEROBJ hmxobj,
+ UINT FAR *puMxId,
+ DWORD fdwId
+)
+{
+ CHECK_AND_INIT_THUNKS(mix32Lib);
+ return IMixerGetID( hmxobj, puMxId, NULL, fdwId );
+}
+
+
+/*****************************Private*Routine******************************\
+* IMixerGetID
+*
+*
+*
+* History:
+* dd-mm-93 - StephenE - Created
+*
+\**************************************************************************/
+MMRESULT FNGLOBAL IMixerGetID(
+ HMIXEROBJ hmxobj,
+ UINT FAR *puMxId,
+ LPMIXERLINE pmxl,
+ DWORD fdwId
+)
+{
+ MMRESULT mmr;
+ MIXERLINE mxl;
+ UINT u;
+
+ V_DFLAGS(fdwId, MIXER_GETIDF_VALID, IMixerGetID, MMSYSERR_INVALFLAG);
+ V_WPOINTER(puMxId, sizeof(UINT), MMSYSERR_INVALPARAM);
+
+
+ //
+ // set to '-1' which would be the mixer mapper (if there was one)
+ // this way we will definitely fail any calls made on this id if
+ // this function fails and the caller doesn't check his return value.
+ //
+ *puMxId = (UINT)-1;
+
+
+ //
+ //
+ //
+ switch (MIXER_OBJECTF_TYPEMASK & fdwId)
+ {
+ case MIXER_OBJECTF_MIXER:
+ case MIXER_OBJECTF_HMIXER:
+ if ((UINT)hmxobj > MAXMIXERDRIVERS)
+ {
+ V_HANDLE(hmxobj, TYPE_MIXER, MMSYSERR_INVALHANDLE);
+
+ *puMxId = ((PMIXERDEV)hmxobj)->uDeviceID;
+ return (MMSYSERR_NOERROR);
+ }
+
+ if ((UINT)hmxobj >= guTotalMixerDevs)
+ {
+ DebugErr1(DBF_ERROR, "mixerGetID: mixer device id is out of range (%u).", hmxobj);
+ return (MMSYSERR_BADDEVICEID);
+ }
+
+ *puMxId = (UINT)hmxobj;
+ return (MMSYSERR_NOERROR);
+
+
+ case MIXER_OBJECTF_HWAVEOUT:
+ {
+ UINT uId;
+ DWORD dwId;
+
+ mmr = waveOutGetID((HWAVEOUT)hmxobj, &uId);
+ if (MMSYSERR_NOERROR != mmr)
+ {
+ return (MMSYSERR_INVALHANDLE);
+ }
+
+ if (WAVE_MAPPER == uId)
+ {
+ mmr = (MMRESULT)waveOutMessage((HWAVEOUT)hmxobj,
+ WODM_MAPPER_STATUS,
+ WAVEOUT_MAPPER_STATUS_DEVICE,
+ (DWORD)(LPVOID)&dwId);
+
+ if (MMSYSERR_NOERROR == mmr)
+ {
+ uId = (UINT)dwId;
+ }
+ }
+
+ hmxobj = (HMIXEROBJ)uId;
+ }
+
+ case MIXER_OBJECTF_WAVEOUT:
+ {
+ WAVEOUTCAPS woc;
+
+ mmr = waveOutGetDevCaps((UINT)hmxobj, &woc, sizeof(woc));
+ if (MMSYSERR_NOERROR != mmr)
+ return (MMSYSERR_BADDEVICEID);
+
+ woc.szPname[SIZEOF(woc.szPname) - 1] = '\0';
+
+ mxl.Target.dwType = MIXERLINE_TARGETTYPE_WAVEOUT;
+ mxl.Target.dwDeviceID = (UINT)hmxobj;
+ mxl.Target.wMid = woc.wMid;
+ mxl.Target.wPid = woc.wPid;
+ mxl.Target.vDriverVersion = woc.vDriverVersion;
+ lstrcpy(mxl.Target.szPname, woc.szPname);
+ break;
+ }
+
+
+ case MIXER_OBJECTF_HWAVEIN:
+ {
+ UINT uId;
+ DWORD dwId;
+
+ mmr = waveInGetID((HWAVEIN)hmxobj, &uId);
+ if (MMSYSERR_NOERROR != mmr)
+ {
+ return (MMSYSERR_INVALHANDLE);
+ }
+
+ if (WAVE_MAPPER == uId)
+ {
+ mmr = (MMRESULT)waveInMessage((HWAVEIN)hmxobj,
+ WIDM_MAPPER_STATUS,
+ WAVEIN_MAPPER_STATUS_DEVICE,
+ (DWORD)(LPVOID)&dwId);
+
+ if (MMSYSERR_NOERROR == mmr)
+ {
+ uId = (UINT)dwId;
+ }
+ }
+
+ hmxobj = (HMIXEROBJ)uId;
+ }
+
+ case MIXER_OBJECTF_WAVEIN:
+ {
+ WAVEINCAPS wic;
+
+ mmr = waveInGetDevCaps((UINT)hmxobj, &wic, sizeof(wic));
+ if (MMSYSERR_NOERROR != mmr)
+ return (MMSYSERR_BADDEVICEID);
+
+ wic.szPname[SIZEOF(wic.szPname) - 1] = '\0';
+
+ mxl.Target.dwType = MIXERLINE_TARGETTYPE_WAVEIN;
+ mxl.Target.dwDeviceID = (UINT)hmxobj;
+ mxl.Target.wMid = wic.wMid;
+ mxl.Target.wPid = wic.wPid;
+ mxl.Target.vDriverVersion = wic.vDriverVersion;
+ lstrcpy(mxl.Target.szPname, wic.szPname);
+ break;
+ }
+
+
+ case MIXER_OBJECTF_HMIDIOUT:
+ mmr = midiOutGetID((HMIDIOUT)hmxobj, (UINT FAR *)&hmxobj);
+ if (MMSYSERR_NOERROR != mmr)
+ return (MMSYSERR_INVALHANDLE);
+
+ case MIXER_OBJECTF_MIDIOUT:
+ {
+ MIDIOUTCAPS moc;
+
+ mmr = midiOutGetDevCaps((UINT)hmxobj, &moc, sizeof(moc));
+ if (MMSYSERR_NOERROR != mmr)
+ return (MMSYSERR_BADDEVICEID);
+
+ moc.szPname[SIZEOF(moc.szPname) - 1] = '\0';
+
+ mxl.Target.dwType = MIXERLINE_TARGETTYPE_MIDIOUT;
+ mxl.Target.dwDeviceID = (UINT)hmxobj;
+ mxl.Target.wMid = moc.wMid;
+ mxl.Target.wPid = moc.wPid;
+ mxl.Target.vDriverVersion = moc.vDriverVersion;
+ lstrcpy(mxl.Target.szPname, moc.szPname);
+ break;
+ }
+
+
+ case MIXER_OBJECTF_HMIDIIN:
+ mmr = midiInGetID((HMIDIIN)hmxobj, (UINT FAR *)&hmxobj);
+ if (MMSYSERR_NOERROR != mmr)
+ return (MMSYSERR_INVALHANDLE);
+
+ case MIXER_OBJECTF_MIDIIN:
+ {
+ MIDIINCAPS mic;
+
+ mmr = midiInGetDevCaps((UINT)hmxobj, &mic, sizeof(mic));
+ if (MMSYSERR_NOERROR != mmr)
+ return (MMSYSERR_BADDEVICEID);
+
+ mic.szPname[SIZEOF(mic.szPname) - 1] = '\0';
+
+ mxl.Target.dwType = MIXERLINE_TARGETTYPE_MIDIIN;
+ mxl.Target.dwDeviceID = (UINT)hmxobj;
+ mxl.Target.wMid = mic.wMid;
+ mxl.Target.wPid = mic.wPid;
+ mxl.Target.vDriverVersion = mic.vDriverVersion;
+ lstrcpy(mxl.Target.szPname, mic.szPname);
+ break;
+ }
+
+
+ case MIXER_OBJECTF_AUX:
+ {
+ AUXCAPS ac;
+
+ mmr = auxGetDevCaps((UINT)hmxobj, &ac, sizeof(ac));
+ if (MMSYSERR_NOERROR != mmr)
+ return (MMSYSERR_BADDEVICEID);
+
+ ac.szPname[SIZEOF(ac.szPname) - 1] = '\0';
+
+ mxl.Target.dwType = MIXERLINE_TARGETTYPE_AUX;
+ mxl.Target.dwDeviceID = (UINT)hmxobj;
+ mxl.Target.wMid = ac.wMid;
+ mxl.Target.wPid = ac.wPid;
+ mxl.Target.vDriverVersion = ac.vDriverVersion;
+ lstrcpy(mxl.Target.szPname, ac.szPname);
+ break;
+ }
+
+ default:
+ DebugErr1(DBF_ERROR, "mixerGetID: unknown mixer object flag (%.08lXh).",
+ MIXER_OBJECTF_TYPEMASK & fdwId);
+ return (MMSYSERR_INVALFLAG);
+ }
+
+
+ //
+ //
+ //
+ //
+ mxl.cbStruct = sizeof(mxl);
+ mxl.dwDestination = (DWORD)-1L;
+ mxl.dwSource = (DWORD)-1L;
+ mxl.dwLineID = (DWORD)-1L;
+ mxl.fdwLine = 0;
+ mxl.dwUser = 0;
+ mxl.dwComponentType = (DWORD)-1L;
+ mxl.cChannels = 0;
+ mxl.cConnections = 0;
+ mxl.cControls = 0;
+ mxl.szShortName[0] = '\0';
+ mxl.szName[0] = '\0';
+
+
+ for (u = 0; u < guTotalMixerDevs; u++)
+ {
+ mmr = (MMRESULT)IMixerMessageId(mixerdrv,
+ guTotalMixerDevs,
+ u,
+ MXDM_GETLINEINFO,
+ (DWORD)(LPVOID)&mxl,
+ M_GLINFOF_TARGETTYPE);
+
+ if (MMSYSERR_NOERROR == mmr)
+ {
+ *puMxId = u;
+
+ if (NULL != pmxl)
+ {
+ DWORD cbStruct;
+
+ cbStruct = pmxl->cbStruct;
+
+ _fmemcpy(pmxl, &mxl, (UINT)cbStruct);
+
+ pmxl->cbStruct = cbStruct;
+ }
+
+ return (mmr);
+ }
+ }
+
+ return (MMSYSERR_NODRIVER);
+} // IMixerGetID()
+
+
+/******************************Public*Routine******************************\
+* mixerOpen
+*
+*
+*
+* History:
+* dd-mm-93 - StephenE - Created
+*
+\**************************************************************************/
+MMRESULT MIXAPI mixerOpen(
+ LPHMIXER phmx,
+ UINT uMxId,
+ DWORD dwCallback,
+ DWORD dwInstance,
+ DWORD fdwOpen
+)
+{
+ MMRESULT mmr;
+ DWORD dwMap;
+ PMIXERDRV pmxdrv;
+ PMIXERDEV pmxdev;
+ MIXEROPENDESC mxod;
+ DWORD dwDrvUser;
+ MIXERCAPS mxcaps;
+
+
+ CHECK_AND_INIT_THUNKS(mix32Lib);
+
+ //
+ //
+ //
+ V_WPOINTER(phmx, sizeof(HMIXER), MMSYSERR_INVALPARAM);
+
+ *phmx = NULL;
+
+ //
+ // Don't allow callback functions - they're not useful and they
+ // cause headaches. Specifically for Windows NT the only way
+ // to cause an asynchronous callback to 16-bit land from a 32-bit DLL
+ // is to cause an interrupt but we don't want to require mixer stuff
+ // to be locked down to allow for this.
+ //
+
+ if ((fdwOpen & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION)
+ {
+ DebugErr(DBF_ERROR, "mixerOpen: CALLBACK_FUNCTION is not supported");
+ return MMSYSERR_INVALFLAG;
+ }
+
+ V_DCALLBACK(dwCallback, HIWORD(fdwOpen & CALLBACK_TYPEMASK), MMSYSERR_INVALPARAM);
+ V_DFLAGS(fdwOpen, MIXER_OPENF_VALID, mixerOpen, MMSYSERR_INVALFLAG);
+
+ mmr = IMixerGetID((HMIXEROBJ)uMxId, &uMxId, NULL, (MIXER_OBJECTF_TYPEMASK & fdwOpen));
+ if (MMSYSERR_NOERROR != mmr)
+ return (mmr);
+
+
+ //
+ //
+ //
+ //
+ dwMap = IMixerMapId(mixerdrv, guTotalMixerDevs, uMxId);
+ if ((DWORD)-1 == dwMap)
+ return (MMSYSERR_BADDEVICEID);
+
+ pmxdrv = &mixerdrv[HIWORD(dwMap)];
+
+#ifdef MIXER_MAPPER
+ //
+ // Default Mixer Mapper:
+ //
+ // If a mixer mapper is installed as a separate DLL then all mixer
+ // mapper messages are routed to it. If no mixer mapper is installed,
+ // simply loop through the mixer devices looking for a match.
+ //
+ if ((MIXER_MAPPER == uMxId) && (NULL == pmxdrv->drvMessage))
+ {
+ for (uMxId = 0; uMxId < guTotalMixerDevs; uMxId++)
+ {
+ // try to open it
+ if (MMSYSERR_NOERROR == mmr)
+ break;
+
+ }
+
+ return (mmr);
+ }
+#endif
+
+
+ //
+ // Get some memory for the dev structure
+ //
+ pmxdev = (PMIXERDEV)NewHandle(TYPE_MIXER, sizeof(MIXERDEV));
+ if (NULL == pmxdev)
+ {
+ return (MMSYSERR_NOMEM);
+ }
+
+ //
+ // initialize our open instance struct for the client
+ //
+ pmxdev->uHandleType = TYPE_MIXER;
+ pmxdev->pmxdrv = pmxdrv;
+ pmxdev->wDevice = LOWORD(dwMap);
+ pmxdev->uDeviceID = uMxId;
+
+ //
+ // save the client's callback info
+ //
+ pmxdev->dwCallback = dwCallback;
+ pmxdev->dwInstance = dwInstance;
+ pmxdev->fdwOpen = fdwOpen;
+
+
+ //
+ // this should probably be done when the driver is booted.. can change
+ // this later..
+ //
+ mmr = mixerGetDevCaps(uMxId, &mxcaps, sizeof(mxcaps));
+ if (MMSYSERR_NOERROR != mmr)
+ {
+ DPF((0, "!mixerOpen() failing because mixerGetDevCaps() failed!"));
+
+ FreeHandle((HMIXER)pmxdev);
+ return (mmr);
+ }
+
+ //
+ // cache some stuff for parameter validation
+ //
+ pmxdev->fdwSupport = mxcaps.fdwSupport;
+ pmxdev->cDestinations = mxcaps.cDestinations;
+
+
+ //
+ // If we get here, no one has the device currently open. Let's
+ // go open it, then.
+ //
+
+ //
+ // Load up our local MIXEROPENDESC struct
+ //
+
+ mxod.hmx = (HMIXER)pmxdev;
+ mxod.pReserved0 = (LPVOID)(fdwOpen & ~MIXER_OBJECTF_TYPEMASK);
+ mxod.dwCallback = dwCallback;
+ mxod.dwInstance = dwInstance;
+ mmr = (MMRESULT)((*(pmxdrv->drvMessage))(LOWORD(dwMap),
+ MXDM_OPEN,
+ (DWORD)(LPDWORD)&dwDrvUser,
+ (DWORD)(LPVOID)&mxod,
+ (DWORD)uMxId ));
+
+
+ if (MMSYSERR_NOERROR != mmr)
+ {
+ FreeHandle((HMIXER)pmxdev);
+ }
+ else
+ {
+ pmxdrv->bUsage++;
+ pmxdev->dwDrvUser = dwDrvUser;
+ *phmx = (HMIXER)pmxdev;
+
+ //
+ // Put this new device into the devlist chain.
+ //
+
+ MIXMGR_ENTER;
+
+ pmxdev->pmxdevNext = gpMixerDevHeader;
+ gpMixerDevHeader = pmxdev;
+
+ MIXMGR_LEAVE;
+ }
+ return mmr;
+}
+
+
+/******************************Public*Routine******************************\
+* mixerClose
+*
+*
+*
+* History:
+* dd-mm-93 - StephenE - Created
+*
+\**************************************************************************/
+MMRESULT MIXAPI mixerClose(
+ HMIXER hmx
+)
+{
+ MMRESULT mmr;
+ PMIXERDEV pmxdev;
+ PMIXERDEV pmxdevT;
+
+ CHECK_AND_INIT_THUNKS(mix32Lib);
+ V_HANDLE(hmx, TYPE_MIXER, MMSYSERR_INVALHANDLE);
+
+
+ //
+ // if last open instance, then close it
+ //
+ mmr = (MMRESULT)IMixerMessageHandle(hmx, MXDM_CLOSE, 0L, 0L);
+
+ if (MMSYSERR_NOERROR != mmr)
+ return (mmr);
+
+
+ //
+ // remove the mixer handle from the linked list
+ //
+
+ MIXMGR_ENTER;
+
+ pmxdev = (PMIXERDEV)hmx;
+ if (pmxdev == gpMixerDevHeader)
+ {
+ gpMixerDevHeader = pmxdev->pmxdevNext;
+ }
+ else
+ {
+ for (pmxdevT = gpMixerDevHeader;
+ pmxdevT && (pmxdevT->pmxdevNext != pmxdev);
+ pmxdevT = pmxdevT->pmxdevNext)
+ ;
+
+ if (NULL == pmxdevT)
+ {
+ DebugErr1(DBF_ERROR, "mixerClose: invalid mixer handle (%.04Xh).", hmx);
+ return (MMSYSERR_INVALHANDLE);
+ }
+
+ pmxdevT->pmxdevNext = pmxdev->pmxdevNext;
+ }
+
+ MIXMGR_LEAVE;
+
+ //
+ // dec usage count
+ //
+ pmxdev->pmxdrv->bUsage--;
+
+
+ //
+ // we're done with the memory block. now free the memory and return.
+ //
+ FreeHandle(hmx);
+ return mmr;
+}
+
+
+/******************************Public*Routine******************************\
+* mixerMessage
+*
+*
+*
+* History:
+* dd-mm-93 - StephenE - Created
+*
+\**************************************************************************/
+DWORD MIXAPI mixerMessage(
+ HMIXER hmx,
+ UINT uMsg,
+ DWORD dwParam1,
+ DWORD dwParam2
+)
+{
+ DWORD dw;
+
+ CHECK_AND_INIT_THUNKS(mix32Lib);
+ V_HANDLE(hmx, TYPE_MIXER, MMSYSERR_INVALHANDLE);
+
+ //
+ // don't allow any non-user range messages through this API
+ //
+ if (MXDM_USER > uMsg)
+ {
+ DebugErr1(DBF_ERROR, "mixerMessage: message must be in MXDM_USER range--what's this (%u)?", uMsg);
+ return (MMSYSERR_INVALPARAM);
+ }
+
+
+ dw = IMixerMessageHandle(hmx, uMsg, dwParam1, dwParam2);
+ return dw;
+}
+
+
+//--------------------------------------------------------------------------;
+//
+// BOOL IMixerIsValidComponentType
+//
+// Description:
+//
+//
+// Arguments:
+// DWORD dwComponentType:
+//
+// UINT uSrcDst:
+//
+// Return (BOOL):
+//
+// History:
+// 10/06/93 cjp [curtisp]
+//
+//--------------------------------------------------------------------------;
+
+BOOL FNLOCAL IMixerIsValidComponentType(
+ DWORD dwComponentType,
+ DWORD fdwLine
+)
+{
+
+ if (0L == (MIXERLINE_LINEF_SOURCE & fdwLine))
+ {
+ if (dwComponentType > MLCT_DST_LAST)
+ return (FALSE);
+
+ return (TRUE);
+ }
+ else
+ {
+ if (dwComponentType < MLCT_SRC_FIRST)
+ return (FALSE);
+
+ if (dwComponentType > MLCT_SRC_LAST)
+ return (FALSE);
+
+ return (TRUE);
+ }
+
+ return (FALSE);
+} // IMixerIsValidComponentType()
+
+
+
+/******************************Public*Routine******************************\
+* mixerGetLineInfo
+*
+*
+*
+* History:
+* dd-mm-93 - StephenE - Created
+*
+\**************************************************************************/
+MMRESULT MIXAPI mixerGetLineInfo(
+ HMIXEROBJ hmxobj,
+ LPMIXERLINE pmxl,
+ DWORD fdwInfo
+)
+{
+ DWORD fdwMxObjType;
+ MMRESULT mmr;
+ PMIXERDEV pmxdev;
+ UINT uMxId;
+ BOOL fSourceLine;
+
+ CHECK_AND_INIT_THUNKS(mix32Lib);
+
+ V_DFLAGS(fdwInfo, M_GLINFOF_VALID, mixerGetLineInfo, MMSYSERR_INVALFLAG);
+ V_WPOINTER(pmxl, sizeof(DWORD), MMSYSERR_INVALPARAM);
+ if (sizeof(MIXERLINE) > (UINT)pmxl->cbStruct)
+ {
+ DebugErr1(DBF_ERROR, "mixerGetLineInfo: structure size too small or cbStruct not initialized (%lu).", pmxl->cbStruct);
+ return (MMSYSERR_INVALPARAM);
+ }
+ V_WPOINTER(pmxl, pmxl->cbStruct, MMSYSERR_INVALPARAM);
+
+
+ //
+ //
+ //
+ fSourceLine = FALSE;
+ switch (fdwInfo & M_GLINFOF_QUERYMASK)
+ {
+ case M_GLINFOF_DESTINATION:
+ pmxl->dwSource = (DWORD)-1L;
+ pmxl->dwLineID = (DWORD)-1L;
+ pmxl->dwComponentType = (DWORD)-1L;
+ break;
+
+ case M_GLINFOF_SOURCE:
+ fSourceLine = TRUE;
+ pmxl->dwLineID = (DWORD)-1L;
+ pmxl->dwComponentType = (DWORD)-1L;
+ break;
+
+ case M_GLINFOF_LINEID:
+ pmxl->dwSource = (DWORD)-1L;
+ pmxl->dwDestination = (DWORD)-1L;
+ pmxl->dwComponentType = (DWORD)-1L;
+ break;
+
+ case M_GLINFOF_COMPONENTTYPE:
+ pmxl->dwSource = (DWORD)-1L;
+ pmxl->dwDestination = (DWORD)-1L;
+ pmxl->dwLineID = (DWORD)-1L;
+
+ if (!IMixerIsValidComponentType(pmxl->dwComponentType, 0) &&
+ !IMixerIsValidComponentType(pmxl->dwComponentType, MIXERLINE_LINEF_SOURCE))
+ {
+ DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid dwComponentType (%lu).", pmxl->dwComponentType);
+ return (MMSYSERR_INVALPARAM);
+ }
+ break;
+
+ case M_GLINFOF_TARGETTYPE:
+ pmxl->dwSource = (DWORD)-1L;
+ pmxl->dwDestination = (DWORD)-1L;
+ pmxl->dwLineID = (DWORD)-1L;
+ pmxl->dwComponentType = (DWORD)-1L;
+
+ if ((DWORD)MIXERLINE_TARGETTYPE_AUX < pmxl->Target.dwType)
+ {
+ DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid Target.dwType (%lu).", pmxl->Target.dwType);
+ return (MMSYSERR_INVALPARAM);
+ }
+ break;
+
+ default:
+ DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid query flag (%.08lXh).",
+ fdwInfo & M_GLINFOF_QUERYMASK);
+ return (MMSYSERR_INVALFLAG);
+ }
+
+
+
+ //
+ //
+ //
+ fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwInfo);
+
+ mmr = IMixerGetID(hmxobj, &uMxId, pmxl, fdwMxObjType);
+ if (MMSYSERR_NOERROR != mmr)
+ {
+ DPF((0, "!IMixerGetLineInfo: IMixerGetID() failed!"));
+ return (mmr);
+ }
+
+ if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
+ (MIXER_OBJECTF_HMIXER == fdwMxObjType))
+ {
+ //
+ // if a mixer device id was passed, then null hmx so we use the
+ // correct message sender below
+ //
+ if ((UINT)hmxobj == uMxId)
+ hmxobj = NULL;
+ }
+ else
+ {
+ return (MMSYSERR_NOERROR);
+ }
+
+
+ //
+ // clear all fields before calling driver
+ //
+ if (NULL != hmxobj)
+ {
+ //
+ //
+ //
+ pmxdev = (PMIXERDEV)hmxobj;
+#if 0
+ if (pmxdev->cDestinations <= pmxl->dwDestination)
+ {
+ DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid destination index (%lu).", pmxl->dwDestination);
+ return (MMSYSERR_INVALPARAM);
+ }
+#endif
+
+ mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj,
+ MXDM_GETLINEINFO,
+ (DWORD)(LPVOID)pmxl,
+ fdwInfo);
+ }
+ else
+ {
+#pragma message("----IMixerGetLineInfo: dwDestination not validated for ID's!!")
+ mmr = (MMRESULT)IMixerMessageId(mixerdrv,
+ guTotalMixerDevs,
+ uMxId,
+ MXDM_GETLINEINFO,
+ (DWORD)(LPVOID)pmxl,
+ fdwInfo);
+ }
+
+ if (MMSYSERR_NOERROR != mmr)
+ return (mmr);
+
+#pragma message("----IMixerGetLineInfo: should validate mixer driver didn't hose us!")
+
+
+ //
+ // validate the driver's returned stuff...
+ //
+ //
+ if (sizeof(MIXERLINE) != (UINT)pmxl->cbStruct)
+ {
+ DebugErr1(DBF_ERROR, "mixerGetLineInfo: buggy driver returned invalid cbStruct (%lu).", pmxl->cbStruct);
+ pmxl->cbStruct = sizeof(MIXERLINE);
+ }
+
+ if ((DWORD)-1L == pmxl->dwDestination)
+ {
+ DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to init dwDestination member.");
+ }
+ if (fSourceLine)
+ {
+ if (0L == (MIXERLINE_LINEF_SOURCE & pmxl->fdwLine))
+ {
+ DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to set MIXERLINE_LINEF_SOURCE.");
+ pmxl->fdwLine |= MIXERLINE_LINEF_SOURCE;
+ }
+
+ if ((DWORD)-1L == pmxl->dwSource)
+ {
+ DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to init dwSource member.");
+ }
+ }
+ if ((DWORD)-1L == pmxl->dwLineID)
+ {
+ DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to init dwLineID member.");
+ }
+ if (pmxl->fdwLine & ~0x80008001L)
+ {
+ DebugErr1(DBF_ERROR, "mixerGetLineInfo: buggy driver set reserved line flags (%.08lXh)!", pmxl->fdwLine);
+ pmxl->fdwLine &= 0x80008001L;
+ }
+ if (!IMixerIsValidComponentType(pmxl->dwComponentType, pmxl->fdwLine))
+ {
+ DebugErr1(DBF_ERROR, "mixerGetLineInfo: buggy driver returned invalid dwComponentType (%.08lXh).", pmxl->dwComponentType);
+ pmxl->dwComponentType = MIXERLINE_TARGETTYPE_UNDEFINED;
+ }
+ if (0L == pmxl->cChannels)
+ {
+ DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver returned zero channels?!?");
+ pmxl->cChannels = 1;
+ }
+ if (fSourceLine)
+ {
+ if (0L != pmxl->cConnections)
+ {
+ DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver returned non-zero connections on source?!?");
+ pmxl->cConnections = 0;
+ }
+ }
+
+ pmxl->szShortName[SIZEOF(pmxl->szShortName) - 1] = '\0';
+ pmxl->szName[SIZEOF(pmxl->szName) - 1] = '\0';
+
+
+ //
+ // Does this really need to be done if TARGETTYPE was requested?
+ //
+
+
+ //
+ //
+ //
+ if ((DWORD)MIXERLINE_TARGETTYPE_UNDEFINED != pmxl->Target.dwType)
+ {
+ UINT u;
+
+ pmxl->Target.dwDeviceID = (DWORD)-1L;
+
+
+ //
+ // we have a wMid, wPid and szPname (supposedly) of type dwType
+ // so let's go find it...
+ //
+ switch (pmxl->Target.dwType)
+ {
+ case MIXERLINE_TARGETTYPE_WAVEOUT:
+ u = waveOutGetNumDevs();
+ while (u--)
+ {
+ WAVEOUTCAPS woc;
+
+ mmr = waveOutGetDevCaps(u, &woc, sizeof(woc));
+ if (MMSYSERR_NOERROR != mmr)
+ continue;
+
+ woc.szPname[SIZEOF(woc.szPname) - 1] = '\0';
+
+ if (woc.wMid != pmxl->Target.wMid)
+ continue;
+
+ if (woc.wPid != pmxl->Target.wPid)
+ continue;
+
+ if (woc.vDriverVersion != pmxl->Target.vDriverVersion)
+ continue;
+
+ if (lstrcmp(woc.szPname, pmxl->Target.szPname))
+ continue;
+
+ pmxl->Target.dwDeviceID = u;
+ break;
+ }
+ break;
+
+ case MIXERLINE_TARGETTYPE_WAVEIN:
+ u = waveInGetNumDevs();
+ while (u--)
+ {
+ WAVEINCAPS wic;
+
+ mmr = waveInGetDevCaps(u, &wic, sizeof(wic));
+ if (MMSYSERR_NOERROR != mmr)
+ continue;
+
+ wic.szPname[SIZEOF(wic.szPname) - 1] = '\0';
+
+ if (wic.wMid != pmxl->Target.wMid)
+ continue;
+
+ if (wic.wPid != pmxl->Target.wPid)
+ continue;
+
+ if (wic.vDriverVersion != pmxl->Target.vDriverVersion)
+ continue;
+
+ if (lstrcmp(wic.szPname, pmxl->Target.szPname))
+ continue;
+
+ pmxl->Target.dwDeviceID = u;
+ break;
+ }
+ break;
+
+ case MIXERLINE_TARGETTYPE_MIDIOUT:
+ u = midiOutGetNumDevs();
+ while (u--)
+ {
+ MIDIOUTCAPS moc;
+
+ mmr = midiOutGetDevCaps(u, &moc, sizeof(moc));
+ if (MMSYSERR_NOERROR != mmr)
+ continue;
+
+ moc.szPname[SIZEOF(moc.szPname) - 1] = '\0';
+
+ if (moc.wMid != pmxl->Target.wMid)
+ continue;
+
+ if (moc.wPid != pmxl->Target.wPid)
+ continue;
+
+ if (moc.vDriverVersion != pmxl->Target.vDriverVersion)
+ continue;
+
+ if (lstrcmp(moc.szPname, pmxl->Target.szPname))
+ continue;
+
+ pmxl->Target.dwDeviceID = u;
+ break;
+ }
+ break;
+
+ case MIXERLINE_TARGETTYPE_MIDIIN:
+ u = midiInGetNumDevs();
+ while (u--)
+ {
+ MIDIINCAPS mic;
+
+ mmr = midiInGetDevCaps(u, &mic, sizeof(mic));
+ if (MMSYSERR_NOERROR != mmr)
+ continue;
+
+ mic.szPname[SIZEOF(mic.szPname) - 1] = '\0';
+
+ if (mic.wMid != pmxl->Target.wMid)
+ continue;
+
+ if (mic.wPid != pmxl->Target.wPid)
+ continue;
+
+ if (mic.vDriverVersion != pmxl->Target.vDriverVersion)
+ continue;
+
+ if (lstrcmp(mic.szPname, pmxl->Target.szPname))
+ continue;
+
+ pmxl->Target.dwDeviceID = u;
+ break;
+ }
+ break;
+
+ case MIXERLINE_TARGETTYPE_AUX:
+ u = auxGetNumDevs();
+ while (u--)
+ {
+ AUXCAPS ac;
+
+ mmr = auxGetDevCaps(u, &ac, sizeof(ac));
+ if (MMSYSERR_NOERROR != mmr)
+ continue;
+
+ ac.szPname[SIZEOF(ac.szPname) - 1] = '\0';
+
+ if (ac.wMid != pmxl->Target.wMid)
+ continue;
+
+ if (ac.wPid != pmxl->Target.wPid)
+ continue;
+
+ if (ac.vDriverVersion != pmxl->Target.vDriverVersion)
+ continue;
+
+ if (lstrcmp(ac.szPname, pmxl->Target.szPname))
+ continue;
+
+ pmxl->Target.dwDeviceID = u;
+ break;
+ }
+ break;
+
+ default:
+ pmxl->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
+ break;
+ }
+ }
+
+ return mmr;
+}
+
+
+/******************************Public*Routine******************************\
+* mixerGetLineControls
+*
+*
+*
+* History:
+* dd-mm-93 - StephenE - Created
+*
+\**************************************************************************/
+MMRESULT MIXAPI mixerGetLineControls(
+ HMIXEROBJ hmxobj,
+ LPMIXERLINECONTROLS pmxlc,
+ DWORD fdwControls
+)
+{
+ DWORD fdwMxObjType;
+ UINT uMxId;
+ MMRESULT mmr;
+
+ CHECK_AND_INIT_THUNKS(mix32Lib);
+ V_DFLAGS(fdwControls, M_GLCONTROLSF_VALID, mixerGetLineControls, MMSYSERR_INVALFLAG);
+ V_WPOINTER(pmxlc, sizeof(DWORD), MMSYSERR_INVALPARAM);
+
+ //
+ // the structure header for MIXERLINECONTROLS must be at least the
+ // minimum size
+ //
+ if (sizeof(MIXERLINECONTROLS) > (UINT)pmxlc->cbStruct)
+ {
+ DebugErr1(DBF_ERROR, "mixerGetLineControls: structure size too small or cbStruct not initialized (%lu).", pmxlc->cbStruct);
+ return (MMSYSERR_INVALPARAM);
+ }
+ V_WPOINTER(pmxlc, pmxlc->cbStruct, MMSYSERR_INVALPARAM);
+
+ if (sizeof(MIXERCONTROL) > (UINT)pmxlc->cbmxctrl)
+ {
+ DebugErr1(DBF_ERROR, "mixerGetLineControls: structure size too small or cbmxctrl not initialized (%lu).", pmxlc->cbmxctrl);
+ return (MMSYSERR_INVALPARAM);
+ }
+
+
+ //
+ //
+ //
+ switch (M_GLCONTROLSF_QUERYMASK & fdwControls)
+ {
+ case M_GLCONTROLSF_ALL:
+ if (0L == pmxlc->cControls)
+ {
+ DebugErr(DBF_ERROR, "mixerGetLineControls: cControls cannot be zero.");
+ return (MMSYSERR_INVALPARAM);
+ }
+
+
+ pmxlc->dwControlID = (DWORD)-1L;
+ break;
+
+ case M_GLCONTROLSF_ONEBYID:
+ pmxlc->dwLineID = (DWORD)-1L;
+
+ // -- fall through --
+
+ case M_GLCONTROLSF_ONEBYTYPE:
+ pmxlc->cControls = (DWORD)1;
+ break;
+
+ default:
+ DebugErr1(DBF_ERROR, "mixerGetLineControls: invalid query flags (%.08lXh).",
+ M_GLCONTROLSF_QUERYMASK & fdwControls);
+ return (MMSYSERR_INVALFLAG);
+ }
+
+ V_WPOINTER(pmxlc->pamxctrl, pmxlc->cControls * pmxlc->cbmxctrl, MMSYSERR_INVALPARAM);
+
+
+ //
+ //
+ //
+ fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwControls);
+
+ mmr = IMixerGetID(hmxobj, &uMxId, NULL, fdwMxObjType);
+ if (MMSYSERR_NOERROR != mmr)
+ return (mmr);
+
+ if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
+ (MIXER_OBJECTF_HMIXER == fdwMxObjType))
+ {
+ //
+ // if a mixer device id was passed, then null hmx so we use the
+ // correct message sender below
+ //
+ if ((UINT)hmxobj == uMxId)
+ hmxobj = NULL;
+ }
+ else
+ {
+ hmxobj = NULL;
+ fdwControls &= ~MIXER_OBJECTF_TYPEMASK;
+ fdwControls |= MIXER_OBJECTF_MIXER;
+ }
+
+
+
+ //
+ //
+ //
+ //
+ if (NULL != hmxobj)
+ {
+ mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj,
+ MXDM_GETLINECONTROLS,
+ (DWORD)pmxlc,
+ fdwControls);
+ }
+ else
+ {
+ mmr = (MMRESULT)IMixerMessageId(mixerdrv,
+ guTotalMixerDevs,
+ uMxId,
+ MXDM_GETLINECONTROLS,
+ (DWORD)pmxlc,
+ fdwControls);
+ }
+
+ return mmr;
+}
+
+
+/******************************Public*Routine******************************\
+* mixerGetControlDetails
+*
+*
+*
+* History:
+* dd-mm-93 - StephenE - Created
+*
+\**************************************************************************/
+MMRESULT MIXAPI mixerGetControlDetails(
+ HMIXEROBJ hmxobj,
+ LPMIXERCONTROLDETAILS pmxcd,
+ DWORD fdwDetails
+)
+{
+ DWORD fdwMxObjType;
+ MMRESULT mmr;
+ UINT uMxId;
+ UINT cDetails;
+
+ CHECK_AND_INIT_THUNKS(mix32Lib);
+ V_DFLAGS(fdwDetails, M_GCDSF_VALID, mixerGetControlDetails, MMSYSERR_INVALFLAG);
+ V_WPOINTER(pmxcd, sizeof(DWORD), MMSYSERR_INVALPARAM);
+
+ //
+ // the structure header for MIXERCONTROLDETAILS must be at least the
+ // minimum size
+ //
+ if (sizeof(MIXERCONTROLDETAILS) > (UINT)pmxcd->cbStruct)
+ {
+ DebugErr1(DBF_ERROR, "mixerGetControlDetails: structure size too small or cbStruct not initialized (%lu).", pmxcd->cbStruct);
+ return (MMSYSERR_INVALPARAM);
+ }
+ V_WPOINTER(pmxcd, pmxcd->cbStruct, MMSYSERR_INVALPARAM);
+
+
+ switch (M_GCDSF_QUERYMASK & fdwDetails)
+ {
+ case M_GCDSF_VALUE:
+ //
+ // if both cChannels and cMultipleItems are zero, it is a
+ // custom control
+ //
+ if ((0L == pmxcd->cChannels) && (0L == pmxcd->cMultipleItems))
+ {
+ if (0L == pmxcd->cbDetails)
+ {
+ DebugErr(DBF_ERROR, "mixerGetControlDetails: cbDetails cannot be zero.");
+ return (MMSYSERR_INVALPARAM);
+ }
+
+ V_WPOINTER(pmxcd->paDetails, pmxcd->cbDetails, MMSYSERR_INVALPARAM);
+
+ }
+ else
+ {
+ if (0L == pmxcd->cChannels)
+ {
+ DebugErr(DBF_ERROR, "mixerGetControlDetails: cChannels for _VALUE cannot be zero.");
+ return (MMSYSERR_INVALPARAM);
+ }
+
+
+ if (pmxcd->cbDetails < sizeof(MIXERCONTROLDETAILS_SIGNED))
+ {
+ DebugErr1(DBF_ERROR, "mixerGetControlDetails: structure size too small or cbDetails not initialized (%lu).", pmxcd->cbDetails);
+ return (MMSYSERR_INVALPARAM);
+ }
+
+ //
+ //
+ //
+ cDetails = (UINT)pmxcd->cChannels;
+ if (0L != pmxcd->cMultipleItems)
+ {
+ cDetails *= (UINT)pmxcd->cMultipleItems;
+ }
+
+ V_WPOINTER(pmxcd->paDetails, cDetails * pmxcd->cbDetails, MMSYSERR_INVALPARAM);
+ }
+ break;
+
+ case M_GCDSF_LISTTEXT:
+ if (0L == pmxcd->cChannels)
+ {
+ DebugErr(DBF_ERROR, "mixerGetControlDetails: cChannels for _LISTTEXT cannot be zero.");
+ return (MMSYSERR_INVALPARAM);
+ }
+
+ if (2L > pmxcd->cMultipleItems)
+ {
+ DebugErr(DBF_ERROR, "mixerGetControlDetails: cMultipleItems for _LISTTEXT must be 2 or greater.");
+ return (MMSYSERR_INVALPARAM);
+ }
+
+ if (pmxcd->cbDetails < sizeof(MIXERCONTROLDETAILS_LISTTEXT))
+ {
+ DebugErr1(DBF_ERROR, "mixerGetControlDetails: structure size too small or cbDetails not initialized (%lu).", pmxcd->cbDetails);
+ return (MMSYSERR_INVALPARAM);
+ }
+
+ cDetails = (UINT)pmxcd->cChannels * (UINT)pmxcd->cMultipleItems;
+ V_WPOINTER(pmxcd->paDetails, cDetails * pmxcd->cbDetails, MMSYSERR_INVALPARAM);
+ break;
+
+ default:
+ DebugErr1(DBF_ERROR, "mixerGetControlDetails: invalid query flags (%.08lXh).",
+ M_GCDSF_QUERYMASK & fdwDetails);
+ return (MMSYSERR_INVALFLAG);
+ }
+
+
+
+ //
+ //
+ //
+ fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwDetails);
+
+ mmr = IMixerGetID(hmxobj, &uMxId, NULL, fdwMxObjType);
+ if (MMSYSERR_NOERROR != mmr)
+ return (mmr);
+
+ if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
+ (MIXER_OBJECTF_HMIXER == fdwMxObjType))
+ {
+ //
+ // if a mixer device id was passed, then null hmx so we use the
+ // correct message sender below
+ //
+ if ((UINT)hmxobj == uMxId)
+ hmxobj = NULL;
+ }
+ else
+ {
+ hmxobj = NULL;
+ fdwDetails &= ~MIXER_OBJECTF_TYPEMASK;
+ fdwDetails |= MIXER_OBJECTF_MIXER;
+ }
+
+ //
+ //
+ //
+ //
+ if (NULL != hmxobj)
+ {
+ mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj,
+ MXDM_GETCONTROLDETAILS,
+ (DWORD)pmxcd,
+ fdwDetails);
+ }
+ else
+ {
+ mmr = (MMRESULT)IMixerMessageId(mixerdrv,
+ guTotalMixerDevs,
+ uMxId,
+ MXDM_GETCONTROLDETAILS,
+ (DWORD)pmxcd,
+ fdwDetails);
+ }
+
+ return mmr;
+}
+
+
+/******************************Public*Routine******************************\
+* mixerSetControlDetails
+*
+*
+*
+* History:
+* dd-mm-93 - StephenE - Created
+*
+\**************************************************************************/
+MMRESULT MIXAPI mixerSetControlDetails(
+ HMIXEROBJ hmxobj,
+ LPMIXERCONTROLDETAILS pmxcd,
+ DWORD fdwDetails
+)
+{
+ DWORD fdwMxObjType;
+ MMRESULT mmr;
+ UINT uMxId;
+ UINT cDetails;
+
+ CHECK_AND_INIT_THUNKS(mix32Lib);
+ V_DFLAGS(fdwDetails, M_SCDF_VALID, mixerSetControlDetails, MMSYSERR_INVALFLAG);
+ V_WPOINTER(pmxcd, sizeof(DWORD), MMSYSERR_INVALPARAM);
+
+ //
+ // the structure header for MIXERCONTROLDETAILS must be at least the
+ // minimum size
+ //
+ if (sizeof(MIXERCONTROLDETAILS) > (UINT)pmxcd->cbStruct)
+ {
+ DebugErr1(DBF_ERROR, "mixerSetControlDetails: structure size too small or cbStruct not initialized (%lu).", pmxcd->cbStruct);
+ return (MMSYSERR_INVALPARAM);
+ }
+ V_WPOINTER(pmxcd, pmxcd->cbStruct, MMSYSERR_INVALPARAM);
+
+
+
+ switch (M_SCDF_QUERYMASK & fdwDetails)
+ {
+ case M_SCDF_VALUE:
+ //
+ // cChannels is zero for custom controls
+ //
+ if (0L == pmxcd->cChannels)
+ {
+ if (0L == pmxcd->cbDetails)
+ {
+ DebugErr(DBF_ERROR, "mixerSetControlDetails: cbDetails cannot be zero.");
+ return (MMSYSERR_INVALPARAM);
+ }
+
+ V_WPOINTER(pmxcd->paDetails, pmxcd->cbDetails, MMSYSERR_INVALPARAM);
+
+ //
+ //
+ //
+ if (0L != pmxcd->cMultipleItems)
+ {
+ DebugErr(DBF_ERROR, "mixerSetControlDetails: cMultipleItems must be zero for custom controls.");
+ return (MMSYSERR_INVALPARAM);
+ }
+ }
+ else
+ {
+ if (pmxcd->cbDetails < sizeof(MIXERCONTROLDETAILS_SIGNED))
+ {
+ DebugErr1(DBF_ERROR, "mixerSetControlDetails: structure size too small or cbDetails not initialized (%lu).", pmxcd->cbDetails);
+ return (MMSYSERR_INVALPARAM);
+ }
+
+ cDetails = (UINT)pmxcd->cChannels;
+
+ //
+ //
+ //
+ if (0L != pmxcd->cMultipleItems)
+ {
+ cDetails *= (UINT)(pmxcd->cMultipleItems);
+ }
+
+ V_WPOINTER(pmxcd->paDetails, cDetails * pmxcd->cbDetails, MMSYSERR_INVALPARAM);
+ }
+ break;
+
+ case M_SCDF_CUSTOM:
+ if (0L == pmxcd->cbDetails)
+ {
+ DebugErr(DBF_ERROR, "mixerSetControlDetails: cbDetails cannot be zero for custom controls.");
+ return (MMSYSERR_INVALPARAM);
+ }
+
+ if (0L != pmxcd->cChannels)
+ {
+ DebugErr(DBF_ERROR, "mixerSetControlDetails: cChannels must be zero for custom controls.");
+ return (MMSYSERR_INVALPARAM);
+ }
+
+ V_WPOINTER(pmxcd->paDetails, pmxcd->cbDetails, MMSYSERR_INVALPARAM);
+
+ //
+ //
+ //
+ if ((NULL != pmxcd->hwndOwner) && !IsWindow(pmxcd->hwndOwner))
+ {
+ DebugErr1(DBF_ERROR, "mixerSetControlDetails: hwndOwner must be a valid window handle (%.04Xh).", pmxcd->hwndOwner);
+ return (MMSYSERR_INVALHANDLE);
+ }
+ break;
+
+ default:
+ DebugErr1(DBF_ERROR, "mixerSetControlDetails: invalid query flags (%.08lXh).",
+ M_SCDF_QUERYMASK & fdwDetails);
+ return (MMSYSERR_INVALFLAG);
+ }
+
+
+ //
+ //
+ //
+ fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwDetails);
+
+ mmr = IMixerGetID(hmxobj, &uMxId, NULL, fdwMxObjType);
+ if (MMSYSERR_NOERROR != mmr)
+ return (mmr);
+
+ if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
+ (MIXER_OBJECTF_HMIXER == fdwMxObjType))
+ {
+ //
+ // if a mixer device id was passed, then null hmx so we use the
+ // correct message sender below
+ //
+ if ((UINT)hmxobj == uMxId)
+ hmxobj = NULL;
+ }
+ else
+ {
+ fdwDetails &= ~MIXER_OBJECTF_TYPEMASK;
+ fdwDetails |= MIXER_OBJECTF_MIXER;
+ hmxobj = NULL;
+ }
+
+ //
+ //
+ //
+ //
+ if (NULL != hmxobj)
+ {
+ mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj,
+ MXDM_SETCONTROLDETAILS,
+ (DWORD)pmxcd,
+ fdwDetails);
+ }
+ else
+ {
+ mmr = (MMRESULT)IMixerMessageId(mixerdrv,
+ guTotalMixerDevs,
+ uMxId,
+ MXDM_SETCONTROLDETAILS,
+ (DWORD)pmxcd,
+ fdwDetails);
+ }
+
+ return mmr;
+}
+
+/*****************************Private*Routine******************************\
+* InitMixerThunks
+*
+* Initializes the thunking system.
+*
+* History:
+* dd-mm-93 - StephenE - Created
+*
+\**************************************************************************/
+BOOL FAR PASCAL
+InitMixerThunks(
+ void
+ )
+{
+
+ /*
+ ** For WOW we have a fake device driver (that actually lives inside
+ ** this library). When an applications makes an api call to this
+ ** library we check to see is the WOW thunks are loaded. If they are
+ ** not loaded "InitWOWThunks" is called. This function loads the 32
+ ** bit library and determines the total number of mixer devices
+ ** present in the system. It then sets mixerdrv[0].bUsage
+ ** and guTotalMixerDevs to this value. This appears to the 16 bit code
+ ** that we have one 16 bit device driver that supports all the
+ ** 32 bit devices !!. The entry point to this fake driver is
+ ** mxdMessage, which just passes the message through to the 32 bit
+ ** side.
+ */
+
+ mixerdrv[0].hDriver = NULL;
+ mixerdrv[0].bNumDevs = (BYTE)0;
+ mixerdrv[0].bUsage = 0;
+ mixerdrv[0].drvMessage = mxdMessage;
+ guTotalMixerDevs = 0;
+
+
+ /*
+ ** First try winmm.dll
+ */
+ mix32Lib = LoadLibraryEx32W( "winmm.dll", NULL, 0L );
+ if ( mix32Lib ) {
+ mix32Message = (DRIVERMSGPROC)GetProcAddress32W( mix32Lib,
+ "mxd32Message" );
+ if ( mix32Message ) {
+
+ mxdMessage( 0, MXDM_INIT, 0L, 0L, 0L );
+ guTotalMixerDevs = (UINT)mxdMessage( 0, MXDM_GETNUMDEVS,
+ 0L, 0L, 0L );
+
+ mixerdrv[0].bNumDevs = (BYTE)guTotalMixerDevs;
+ return TRUE;
+ }
+ }
+
+ /*
+ ** Then try msmix32.dll
+ */
+ mix32Lib = LoadLibraryEx32W( "msmix32.dll", NULL, 0L );
+ if ( mix32Lib ) {
+
+ mix32Message = (DRIVERMSGPROC)GetProcAddress32W( mix32Lib,
+ "mxd32Message" );
+ if ( mix32Message ) {
+
+ mxdMessage( 0, MXDM_INIT, 0L, 0L, 0L );
+ guTotalMixerDevs = (UINT)mxdMessage( 0, MXDM_GETNUMDEVS,
+ 0L, 0L, 0L );
+
+ mixerdrv[0].bNumDevs = (BYTE)guTotalMixerDevs;
+ return TRUE;
+ }
+ }
+
+ /*
+ ** Give up !!
+ */
+ return FALSE;
+
+}
+
+
+/*****************************Private*Routine******************************\
+* mxdMessage
+*
+* Entry point for the fake WOW device driver.
+*
+* History:
+* dd-mm-93 - StephenE - Created
+*
+\**************************************************************************/
+DWORD CALLBACK
+mxdMessage(
+ UINT uId,
+ UINT uMsg,
+ DWORD dwInstance,
+ DWORD dwParam1,
+ DWORD dwParam2
+ )
+{
+ return mmCallProc32( (DWORD)uId, (DWORD)uMsg, dwInstance,
+ dwParam1, dwParam2, mix32Message, 0L );
+}