Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1950 lines
52 KiB

//==========================================================================;
//
// 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 bad for some Media Vision things...
//
// 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 );
}