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.
716 lines
19 KiB
716 lines
19 KiB
/////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
|
|
//
|
|
// Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
|
|
//
|
|
// Other brand and product names used herein are trademarks of their respective owners.
|
|
//
|
|
// The entire program and user interface including the structure, sequence, selection,
|
|
// and arrangement of the dialog, the exclusively "yes" and "no" choices represented
|
|
// by "1" and "2," and each dialog message are protected by copyrights registered in
|
|
// the United States and by international treaties.
|
|
//
|
|
// Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
|
|
// 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
|
|
//
|
|
// Active Voice Corporation
|
|
// Seattle, Washington
|
|
// USA
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////
|
|
// wavmixer.c - wav mixer functions
|
|
////
|
|
|
|
#include "winlocal.h"
|
|
|
|
#include <mmsystem.h>
|
|
|
|
#include "wavmixer.h"
|
|
#include "calc.h"
|
|
#include "mem.h"
|
|
#include "trace.h"
|
|
|
|
////
|
|
// private definitions
|
|
////
|
|
|
|
// wavmixer control struct
|
|
//
|
|
typedef struct WAVMIXER
|
|
{
|
|
DWORD dwVersion;
|
|
HINSTANCE hInst;
|
|
HTASK hTask;
|
|
HMIXER hMixer;
|
|
UINT nLastError;
|
|
DWORD dwFlags;
|
|
} WAVMIXER, FAR *LPWAVMIXER;
|
|
|
|
#define VOLUME_MINLEVEL 0
|
|
#define VOLUME_MAXLEVEL 100
|
|
#define VOLUME_POSITIONS (VOLUME_MAXLEVEL - VOLUME_MINLEVEL)
|
|
|
|
#define WAVMIXER_SUPPORTSVOLUME 0x00000001
|
|
#define WAVMIXER_GETVOLUME 0x00000002
|
|
#define WAVMIXER_SETVOLUME 0x00000004
|
|
|
|
#define LEVEL_MINLEVEL 0
|
|
#define LEVEL_MAXLEVEL 100
|
|
#define LEVEL_POSITIONS (LEVEL_MAXLEVEL - LEVEL_MINLEVEL)
|
|
|
|
#define WAVMIXER_SUPPORTSLEVEL 0x00000001
|
|
#define WAVMIXER_GETLEVEL 0x00000002
|
|
|
|
// helper functions
|
|
//
|
|
static int WINAPI WavMixerVolume(HWAVMIXER hWavMixer, LPINT lpnLevel, DWORD dwFlags);
|
|
static int WINAPI WavMixerLevel(HWAVMIXER hWavMixer, LPINT lpnLevel, DWORD dwFlags);
|
|
static LPWAVMIXER WavMixerGetPtr(HWAVMIXER hWavMixer);
|
|
static HWAVMIXER WavMixerGetHandle(LPWAVMIXER lpWavMixer);
|
|
|
|
////
|
|
// public functions
|
|
////
|
|
|
|
// WavMixerInit - initialize wav mixer device
|
|
// <dwVersion> (i) must be WAVMIXER_VERSION
|
|
// <hInst> (i) instance handle of calling module
|
|
// <lParam> (i) device id or handle, as specified by <dwFlags>
|
|
// <dwReserved1> (i) reserved; must be 0;
|
|
// <dwReserved2> (i) reserved; must be 0;
|
|
// <dwFlags> (i) control flags
|
|
// WAVMIXER_HWAVEIN <lParam> contains an HWAVEIN
|
|
// WAVMIXER_HWAVEOUT <lParam> contains an HWAVEOUT
|
|
// WAVMIXER_WAVEIN <lParam> contains a wav input device id
|
|
// WAVMIXER_WAVEOUT <lParam> contains a wav output device id
|
|
// return handle (NULL if error)
|
|
//
|
|
HWAVMIXER WINAPI WavMixerInit(DWORD dwVersion, HINSTANCE hInst,
|
|
LPARAM lParam, DWORD dwReserved1, DWORD dwReserved2, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPWAVMIXER lpWavMixer = NULL;
|
|
|
|
if (dwVersion != WAVMIXER_VERSION)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (hInst == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((lpWavMixer = (LPWAVMIXER) MemAlloc(NULL, sizeof(WAVMIXER), 0)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else
|
|
{
|
|
UINT uMxId = (UINT) lParam;
|
|
DWORD fdwOpen = 0;
|
|
UINT nLastError;
|
|
|
|
lpWavMixer->dwVersion = dwVersion;
|
|
lpWavMixer->hInst = hInst;
|
|
lpWavMixer->hTask = GetCurrentTask();
|
|
lpWavMixer->hMixer = NULL;
|
|
lpWavMixer->nLastError = 0;
|
|
lpWavMixer->dwFlags = dwFlags;
|
|
|
|
if (dwFlags & WAVMIXER_HWAVEIN)
|
|
fdwOpen |= MIXER_OBJECTF_HWAVEIN;
|
|
if (dwFlags & WAVMIXER_HWAVEOUT)
|
|
fdwOpen |= MIXER_OBJECTF_HWAVEOUT;
|
|
if (dwFlags & WAVMIXER_WAVEIN)
|
|
fdwOpen |= MIXER_OBJECTF_WAVEIN;
|
|
if (dwFlags & WAVMIXER_WAVEOUT)
|
|
fdwOpen |= MIXER_OBJECTF_WAVEOUT;
|
|
|
|
// open the mixer device
|
|
//
|
|
if ((nLastError = mixerOpen(&lpWavMixer->hMixer, uMxId, 0L, 0L, fdwOpen)) != MMSYSERR_NOERROR)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("mixerOpen failed (%u)\n"),
|
|
(unsigned) nLastError);
|
|
}
|
|
}
|
|
|
|
if (!fSuccess)
|
|
{
|
|
WavMixerTerm(WavMixerGetHandle(lpWavMixer));
|
|
lpWavMixer = NULL;
|
|
}
|
|
|
|
return fSuccess ? WavMixerGetHandle(lpWavMixer) : NULL;
|
|
}
|
|
|
|
// WavMixerTerm - shut down wave mixer device
|
|
// <hWavMixer> (i) handle returned from WavMixerInit
|
|
// return 0 if success
|
|
//
|
|
int WINAPI WavMixerTerm(HWAVMIXER hWavMixer)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPWAVMIXER lpWavMixer;
|
|
|
|
if ((lpWavMixer = WavMixerGetPtr(hWavMixer)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else
|
|
{
|
|
if (lpWavMixer->hMixer != NULL)
|
|
{
|
|
UINT nLastError;
|
|
|
|
if ((nLastError = mixerClose(lpWavMixer->hMixer)) != MMSYSERR_NOERROR)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("mixerClose failed (%u)\n"),
|
|
(unsigned) nLastError);
|
|
}
|
|
else
|
|
lpWavMixer->hMixer = NULL;
|
|
}
|
|
|
|
if ((lpWavMixer = MemFree(NULL, lpWavMixer)) != NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
return fSuccess ? 0 : -1;
|
|
}
|
|
|
|
// WavMixerSupportsVolume - return TRUE if device supports volume control
|
|
// <hWavMixer> (i) handle returned from WavMixerInit
|
|
// <dwFlags> (i) control flags
|
|
// 0 reserved; must be zero
|
|
// return TRUE if device supports volume control
|
|
//
|
|
BOOL WINAPI WavMixerSupportsVolume(HWAVMIXER hWavMixer, DWORD dwFlags)
|
|
{
|
|
if (WavMixerVolume(hWavMixer, NULL, WAVMIXER_SUPPORTSVOLUME) != 0)
|
|
return FALSE;
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
// WavMixerGetVolume - get current volume level
|
|
// <hWavMixer> (i) handle returned from WavMixerInit
|
|
// <dwFlags> (i) control flags
|
|
// 0 reserved; must be zero
|
|
// return volume level (0 minimum through 100 maximum, -1 if error)
|
|
//
|
|
int WINAPI WavMixerGetVolume(HWAVMIXER hWavMixer, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
int nLevel;
|
|
|
|
if (WavMixerVolume(hWavMixer, &nLevel, WAVMIXER_GETVOLUME) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
return fSuccess ? nLevel : -1;
|
|
}
|
|
|
|
// WavMixerSetVolume - set current volume level
|
|
// <hWavMixer> (i) handle returned from WavMixerInit
|
|
// <nLevel> (i) volume level
|
|
// 0 minimum volume
|
|
// 100 maximum volume
|
|
// <dwFlags> (i) control flags
|
|
// 0 reserved; must be zero
|
|
// return new volume level (0 minimum through 100 maximum, -1 if error)
|
|
//
|
|
int WINAPI WavMixerSetVolume(HWAVMIXER hWavMixer, int nLevel, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
|
|
if (WavMixerVolume(hWavMixer, &nLevel, WAVMIXER_SETVOLUME) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
return fSuccess ? nLevel : -1;
|
|
}
|
|
|
|
static int WINAPI WavMixerVolume(HWAVMIXER hWavMixer, LPINT lpnLevel, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPWAVMIXER lpWavMixer;
|
|
LPMIXERCONTROL lpmxc = NULL;
|
|
|
|
//
|
|
// We have to initialize local variable
|
|
//
|
|
UINT nLastError;
|
|
MIXERLINE mxlDst;
|
|
MIXERLINE mxlSrc;
|
|
BOOL fWaveIn = FALSE;
|
|
|
|
if ((lpWavMixer = WavMixerGetPtr(hWavMixer)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((lpmxc = (LPMIXERCONTROL) MemAlloc(NULL, sizeof(MIXERCONTROL), 0)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// get info for the destination line
|
|
//
|
|
if (fSuccess)
|
|
{
|
|
if ((lpWavMixer->dwFlags & WAVMIXER_WAVEIN) ||
|
|
(lpWavMixer->dwFlags & WAVMIXER_HWAVEIN))
|
|
fWaveIn = TRUE;
|
|
|
|
mxlDst.cbStruct = sizeof(mxlDst);
|
|
mxlDst.dwComponentType = fWaveIn ?
|
|
MIXERLINE_COMPONENTTYPE_DST_WAVEIN :
|
|
MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
|
|
|
|
if ((nLastError = mixerGetLineInfo((HMIXEROBJ) lpWavMixer->hMixer, &mxlDst,
|
|
MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE)) != MMSYSERR_NOERROR)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("mixerGetLineInfo failed (%u)\n"),
|
|
(unsigned) nLastError);
|
|
}
|
|
}
|
|
|
|
// find appropriate source line connected to this destination line
|
|
//
|
|
if (fSuccess)
|
|
{
|
|
DWORD dwSource;
|
|
|
|
for (dwSource = 0; fSuccess && dwSource < mxlDst.cConnections; ++dwSource)
|
|
{
|
|
mxlSrc.cbStruct = sizeof(mxlSrc);
|
|
mxlSrc.dwSource = dwSource;
|
|
mxlSrc.dwDestination = mxlDst.dwDestination;
|
|
|
|
if ((nLastError = mixerGetLineInfo((HMIXEROBJ) lpWavMixer->hMixer, &mxlSrc,
|
|
MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_SOURCE)) != MMSYSERR_NOERROR)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("mixerGetLineInfo failed (%u)\n"),
|
|
(unsigned) nLastError);
|
|
}
|
|
|
|
else if (mxlSrc.dwComponentType == (DWORD) (fWaveIn ?
|
|
MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE :
|
|
MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT))
|
|
{
|
|
// source line found
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dwSource == mxlDst.cConnections)
|
|
{
|
|
// unable to find source line
|
|
//
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
}
|
|
|
|
// find volume control, if any, of the appropriate line
|
|
//
|
|
if (fSuccess)
|
|
{
|
|
MIXERLINECONTROLS mxlc;
|
|
|
|
mxlc.cbStruct = sizeof(mxlc);
|
|
mxlc.dwLineID = (fWaveIn ? mxlSrc.dwLineID : mxlDst.dwLineID);
|
|
mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
|
|
mxlc.cControls = 1;
|
|
mxlc.cbmxctrl = sizeof(MIXERCONTROL);
|
|
mxlc.pamxctrl = lpmxc;
|
|
|
|
if ((nLastError = mixerGetLineControls((HMIXEROBJ) lpWavMixer->hMixer, &mxlc,
|
|
MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE)) != MMSYSERR_NOERROR)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("mixerGetLineControls failed (%u)\n"),
|
|
(unsigned) nLastError);
|
|
}
|
|
}
|
|
|
|
// get and/or set current volume level
|
|
//
|
|
if (fSuccess &&
|
|
((dwFlags & WAVMIXER_GETVOLUME) || (dwFlags & WAVMIXER_SETVOLUME)))
|
|
{
|
|
LPMIXERCONTROLDETAILS_UNSIGNED lpmxcdu = NULL;
|
|
MIXERCONTROLDETAILS mxcd;
|
|
DWORD cChannels = mxlSrc.cChannels;
|
|
DWORD dwVolume;
|
|
int nLevel;
|
|
|
|
if (lpmxc->fdwControl & MIXERCONTROL_CONTROLF_UNIFORM)
|
|
cChannels = 1;
|
|
|
|
if ((lpmxcdu = (LPMIXERCONTROLDETAILS_UNSIGNED) MemAlloc(NULL,
|
|
cChannels * sizeof(MIXERCONTROLDETAILS_UNSIGNED), 0)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else
|
|
{
|
|
mxcd.cbStruct = sizeof(mxcd);
|
|
mxcd.dwControlID = lpmxc->dwControlID;
|
|
mxcd.cChannels = cChannels;
|
|
mxcd.hwndOwner = (HWND) NULL;
|
|
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
|
|
mxcd.paDetails = (LPVOID) lpmxcdu;
|
|
|
|
if ((nLastError = mixerGetControlDetails((HMIXEROBJ) lpWavMixer->hMixer, &mxcd,
|
|
MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE)) != MMSYSERR_NOERROR)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("mixerGetControlDetails failed (%u)\n"),
|
|
(unsigned) nLastError);
|
|
}
|
|
else
|
|
dwVolume = lpmxcdu[0].dwValue;
|
|
}
|
|
|
|
if (fSuccess && (dwFlags & WAVMIXER_SETVOLUME))
|
|
{
|
|
if (lpnLevel != NULL)
|
|
nLevel = *lpnLevel;
|
|
|
|
// convert signed level (0 - 100) to unsigned volume (0 - 65535)
|
|
//
|
|
dwVolume = nLevel * (0xFFFF / VOLUME_POSITIONS);
|
|
|
|
lpmxcdu[0].dwValue = lpmxcdu[cChannels - 1].dwValue = dwVolume;
|
|
|
|
TracePrintf_2(NULL, 5,
|
|
TEXT("WavMixerSetVolume() = %d, 0x%08lX\n"),
|
|
(int) nLevel,
|
|
(unsigned long) dwVolume);
|
|
|
|
if ((nLastError = mixerSetControlDetails((HMIXEROBJ) lpWavMixer->hMixer, &mxcd,
|
|
MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE)) != MMSYSERR_NOERROR)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("mixerSetControlDetails failed (%u)\n"),
|
|
(unsigned) nLastError);
|
|
}
|
|
#if 1
|
|
// save new volume to pass back
|
|
//
|
|
else if ((nLastError = mixerGetControlDetails((HMIXEROBJ) lpWavMixer->hMixer, &mxcd,
|
|
MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE)) != MMSYSERR_NOERROR)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("mixerGetControlDetails failed (%u)\n"),
|
|
(unsigned) nLastError);
|
|
}
|
|
else
|
|
dwVolume = lpmxcdu[0].dwValue;
|
|
#endif
|
|
}
|
|
|
|
if (fSuccess &&
|
|
#if 1
|
|
((dwFlags & WAVMIXER_GETVOLUME) || (dwFlags & WAVMIXER_SETVOLUME)))
|
|
#else
|
|
(dwFlags & WAVMIXER_GETVOLUME))
|
|
#endif
|
|
{
|
|
// convert unsigned volume (0 - 65535) to signed level (0 - 100)
|
|
//
|
|
nLevel = LOWORD(dwVolume) / (0xFFFF / VOLUME_POSITIONS);
|
|
|
|
if (lpnLevel != NULL)
|
|
*lpnLevel = nLevel;
|
|
|
|
TracePrintf_2(NULL, 5,
|
|
TEXT("WavMixerGetVolume() = %d, 0x%08lX\n"),
|
|
(int) nLevel,
|
|
(unsigned long) dwVolume);
|
|
}
|
|
|
|
if (lpmxcdu != NULL && (lpmxcdu = MemFree(NULL, lpmxcdu)) != NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// clean up
|
|
//
|
|
if (lpmxc != NULL && (lpmxc = MemFree(NULL, lpmxc)) != NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hWavMixer != NULL && lpWavMixer != NULL)
|
|
lpWavMixer->nLastError = nLastError;
|
|
|
|
return fSuccess ? 0 : -1;
|
|
}
|
|
|
|
// WavMixerSupportsLevel - return TRUE if device supports peak meter level
|
|
// <hWavMixer> (i) handle returned from WavMixerInit
|
|
// <dwFlags> (i) control flags
|
|
// 0 reserved; must be zero
|
|
// return TRUE if device supports peak meter level
|
|
//
|
|
BOOL WINAPI WavMixerSupportsLevel(HWAVMIXER hWavMixer, DWORD dwFlags)
|
|
{
|
|
if (WavMixerLevel(hWavMixer, NULL, WAVMIXER_SUPPORTSLEVEL) != 0)
|
|
return FALSE;
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
// WavMixerGetLevel - get current peak meter level
|
|
// <hWavMixer> (i) handle returned from WavMixerInit
|
|
// <dwFlags> (i) control flags
|
|
// 0 reserved; must be zero
|
|
// return peak meter level (0 minimum through 100 maximum, -1 if error)
|
|
//
|
|
int WINAPI WavMixerGetLevel(HWAVMIXER hWavMixer, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
int nLevel;
|
|
|
|
if (WavMixerLevel(hWavMixer, &nLevel, WAVMIXER_GETLEVEL) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
return fSuccess ? nLevel : -1;
|
|
}
|
|
|
|
static int WINAPI WavMixerLevel(HWAVMIXER hWavMixer, LPINT lpnLevel, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPWAVMIXER lpWavMixer;
|
|
LPMIXERCONTROL lpmxc = NULL;
|
|
|
|
//
|
|
// Initialize local variable
|
|
//
|
|
|
|
UINT nLastError = 0;
|
|
MIXERLINE mxlDst;
|
|
MIXERLINE mxlSrc;
|
|
BOOL fWaveIn = FALSE;
|
|
|
|
if ((lpWavMixer = WavMixerGetPtr(hWavMixer)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((lpmxc = (LPMIXERCONTROL) MemAlloc(NULL, sizeof(MIXERCONTROL), 0)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// get info for the destination line
|
|
//
|
|
if (fSuccess)
|
|
{
|
|
if ((lpWavMixer->dwFlags & WAVMIXER_WAVEIN) ||
|
|
(lpWavMixer->dwFlags & WAVMIXER_HWAVEIN))
|
|
fWaveIn = TRUE;
|
|
|
|
mxlDst.cbStruct = sizeof(mxlDst);
|
|
mxlDst.dwComponentType = fWaveIn ?
|
|
MIXERLINE_COMPONENTTYPE_DST_WAVEIN :
|
|
MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
|
|
|
|
if ((nLastError = mixerGetLineInfo((HMIXEROBJ) lpWavMixer->hMixer, &mxlDst,
|
|
MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE)) != MMSYSERR_NOERROR)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("mixerGetLineInfo failed (%u)\n"),
|
|
(unsigned) nLastError);
|
|
}
|
|
}
|
|
|
|
// find appropriate source line connected to this destination line
|
|
//
|
|
if (fSuccess)
|
|
{
|
|
DWORD dwSource;
|
|
|
|
for (dwSource = 0; fSuccess && dwSource < mxlDst.cConnections; ++dwSource)
|
|
{
|
|
mxlSrc.cbStruct = sizeof(mxlSrc);
|
|
mxlSrc.dwSource = dwSource;
|
|
mxlSrc.dwDestination = mxlDst.dwDestination;
|
|
|
|
if ((nLastError = mixerGetLineInfo((HMIXEROBJ) lpWavMixer->hMixer, &mxlSrc,
|
|
MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_SOURCE)) != MMSYSERR_NOERROR)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("mixerGetLineInfo failed (%u)\n"),
|
|
(unsigned) nLastError);
|
|
}
|
|
|
|
else if (mxlSrc.dwComponentType == (DWORD) (fWaveIn ?
|
|
MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE :
|
|
MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT))
|
|
{
|
|
// source line found
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dwSource == mxlDst.cConnections)
|
|
{
|
|
// unable to find source line
|
|
//
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
}
|
|
|
|
// find peak meter control, if any, of the appropriate line
|
|
//
|
|
if (fSuccess)
|
|
{
|
|
MIXERLINECONTROLS mxlc;
|
|
|
|
mxlc.cbStruct = sizeof(mxlc);
|
|
mxlc.dwLineID = (fWaveIn ? mxlDst.dwLineID : mxlSrc.dwLineID);
|
|
mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_PEAKMETER;
|
|
mxlc.cControls = 1;
|
|
mxlc.cbmxctrl = sizeof(MIXERCONTROL);
|
|
mxlc.pamxctrl = lpmxc;
|
|
|
|
if ((nLastError = mixerGetLineControls((HMIXEROBJ) lpWavMixer->hMixer, &mxlc,
|
|
MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE)) != MMSYSERR_NOERROR)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("mixerGetLineControls failed (%u)\n"),
|
|
(unsigned) nLastError);
|
|
}
|
|
}
|
|
|
|
// get current peak meter level
|
|
//
|
|
if (fSuccess && (dwFlags & WAVMIXER_GETLEVEL))
|
|
{
|
|
LPMIXERCONTROLDETAILS_SIGNED lpmxcds = NULL;
|
|
MIXERCONTROLDETAILS mxcd;
|
|
DWORD cChannels = mxlDst.cChannels;
|
|
DWORD dwLevel;
|
|
int nLevel;
|
|
|
|
if (lpmxc->fdwControl & MIXERCONTROL_CONTROLF_UNIFORM)
|
|
cChannels = 1;
|
|
|
|
if ((lpmxcds = (LPMIXERCONTROLDETAILS_SIGNED) MemAlloc(NULL,
|
|
cChannels * sizeof(MIXERCONTROLDETAILS_SIGNED), 0)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else
|
|
{
|
|
mxcd.cbStruct = sizeof(mxcd);
|
|
mxcd.dwControlID = lpmxc->dwControlID;
|
|
mxcd.cChannels = cChannels;
|
|
mxcd.hwndOwner = (HWND) NULL;
|
|
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_SIGNED);
|
|
mxcd.paDetails = (LPVOID) lpmxcds;
|
|
|
|
if ((nLastError = mixerGetControlDetails((HMIXEROBJ) lpWavMixer->hMixer, &mxcd,
|
|
MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE)) != MMSYSERR_NOERROR)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("mixerGetControlDetails failed (%u)\n"),
|
|
(unsigned) nLastError);
|
|
}
|
|
else
|
|
{
|
|
// convert signed level to unsigned level
|
|
//
|
|
dwLevel = lpmxcds[0].lValue - 0; // lpmxc->Bounds.lMinimum;
|
|
dwLevel *= 2;
|
|
}
|
|
}
|
|
|
|
// convert unsigned level (0 - 65535) to signed level (0 - 100)
|
|
//
|
|
nLevel = LOWORD(dwLevel) / (0xFFFF / LEVEL_POSITIONS);
|
|
|
|
if (lpnLevel != NULL)
|
|
*lpnLevel = nLevel;
|
|
|
|
//
|
|
// We have to verify lpmxcds pointer
|
|
//
|
|
TracePrintf_3(NULL, 5,
|
|
TEXT("WavMixerGetLevel() = %d, %ld, 0x%08lX\n"),
|
|
(int) nLevel,
|
|
lpmxcds ? lpmxcds[0].lValue : 0,
|
|
(unsigned long) dwLevel);
|
|
|
|
if (lpmxcds != NULL && (lpmxcds = MemFree(NULL, lpmxcds)) != NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// clean up
|
|
//
|
|
if (lpmxc != NULL && (lpmxc = MemFree(NULL, lpmxc)) != NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hWavMixer != NULL && lpWavMixer != NULL)
|
|
lpWavMixer->nLastError = nLastError;
|
|
|
|
return fSuccess ? 0 : -1;
|
|
}
|
|
|
|
////
|
|
// helper functions
|
|
////
|
|
|
|
// WavMixerGetPtr - verify that wavmixer handle is valid,
|
|
// <hWavMixer> (i) handle returned from WavMixerInit
|
|
// return corresponding wavmixer pointer (NULL if error)
|
|
//
|
|
static LPWAVMIXER WavMixerGetPtr(HWAVMIXER hWavMixer)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPWAVMIXER lpWavMixer;
|
|
|
|
if ((lpWavMixer = (LPWAVMIXER) hWavMixer) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (IsBadWritePtr(lpWavMixer, sizeof(WAVMIXER)))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
#ifdef CHECKTASK
|
|
// make sure current task owns the wavmixer handle
|
|
//
|
|
else if (lpWavMixer->hTask != GetCurrentTask())
|
|
fSuccess = TraceFALSE(NULL);
|
|
#endif
|
|
|
|
return fSuccess ? lpWavMixer : NULL;
|
|
}
|
|
|
|
// WavMixerGetHandle - verify that wavmixer pointer is valid,
|
|
// <lpWavMixer> (i) pointer to WAVMIXER struct
|
|
// return corresponding wavmixer handle (NULL if error)
|
|
//
|
|
static HWAVMIXER WavMixerGetHandle(LPWAVMIXER lpWavMixer)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
|
|
//
|
|
// we have to initialize local variable
|
|
//
|
|
|
|
HWAVMIXER hWavMixer = NULL;
|
|
|
|
if ((hWavMixer = (HWAVMIXER) lpWavMixer) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
return fSuccess ? hWavMixer : NULL;
|
|
}
|
|
|