287 lines
9.6 KiB
C
287 lines
9.6 KiB
C
|
/****************************************************************************
|
||
|
*
|
||
|
* waveout.c
|
||
|
*
|
||
|
* WDM Audio support for Wave Output devices
|
||
|
*
|
||
|
* Copyright (C) Microsoft Corporation, 1997 - 1999 All Rights Reserved.
|
||
|
*
|
||
|
* History
|
||
|
* 5-12-97 - Noel Cross (NoelC)
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include "wdmdrv.h"
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
This function conforms to the standard Wave output driver message proc
|
||
|
(wodMessage), which is documented in mmddk.h.
|
||
|
|
||
|
****************************************************************************/
|
||
|
DWORD FAR PASCAL _loadds wodMessage
|
||
|
(
|
||
|
UINT id,
|
||
|
UINT msg,
|
||
|
DWORD_PTR dwUser,
|
||
|
DWORD_PTR dwParam1,
|
||
|
DWORD_PTR dwParam2
|
||
|
)
|
||
|
{
|
||
|
LPDEVICEINFO pOutClient;
|
||
|
LPDEVICEINFO pDeviceInfo;
|
||
|
LPWAVEHDR lpWaveHdr;
|
||
|
MMRESULT mmr;
|
||
|
|
||
|
switch (msg) {
|
||
|
case WODM_INIT:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_INIT") );
|
||
|
return(wdmaudAddRemoveDevNode(WaveOutDevice, (LPCWSTR)dwParam2, TRUE));
|
||
|
|
||
|
case DRVM_EXIT:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("DRVM_EXIT: WaveOut") );
|
||
|
return(wdmaudAddRemoveDevNode(WaveOutDevice, (LPCWSTR)dwParam2, FALSE));
|
||
|
|
||
|
case WODM_GETNUMDEVS:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_GETNUMDEVS") );
|
||
|
return wdmaudGetNumDevs(WaveOutDevice, (LPCWSTR)dwParam1);
|
||
|
|
||
|
case WODM_GETDEVCAPS:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_GETDEVCAPS") );
|
||
|
if (pDeviceInfo = GlobalAllocDeviceInfo((LPCWSTR)dwParam2))
|
||
|
{
|
||
|
pDeviceInfo->DeviceType = WaveOutDevice;
|
||
|
pDeviceInfo->DeviceNumber = id;
|
||
|
mmr = wdmaudGetDevCaps(pDeviceInfo, (MDEVICECAPSEX FAR*)dwParam1);
|
||
|
GlobalFreeDeviceInfo(pDeviceInfo);
|
||
|
return mmr;
|
||
|
} else {
|
||
|
MMRRETURN( MMSYSERR_NOMEM );
|
||
|
}
|
||
|
|
||
|
case WODM_PREFERRED:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_PREFERRED: %d", id) );
|
||
|
return wdmaudSetPreferredDevice(
|
||
|
WaveOutDevice,
|
||
|
id,
|
||
|
dwParam1,
|
||
|
dwParam2);
|
||
|
|
||
|
case WODM_OPEN:
|
||
|
{
|
||
|
LPWAVEOPENDESC pwod = (LPWAVEOPENDESC)dwParam1;
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_OPEN") );
|
||
|
if (pDeviceInfo = GlobalAllocDeviceInfo((LPCWSTR)pwod->dnDevNode))
|
||
|
{
|
||
|
pDeviceInfo->DeviceType = WaveOutDevice;
|
||
|
pDeviceInfo->DeviceNumber = id;
|
||
|
#ifdef UNDER_NT
|
||
|
pDeviceInfo->DeviceHandle = (HANDLE32)pwod->hWave;
|
||
|
#else
|
||
|
pDeviceInfo->DeviceHandle = (HANDLE32)MAKELONG(pwod->hWave,0);
|
||
|
#endif
|
||
|
mmr = waveOpen(pDeviceInfo, dwUser, pwod, (DWORD)dwParam2);
|
||
|
GlobalFreeDeviceInfo(pDeviceInfo);
|
||
|
return mmr;
|
||
|
} else {
|
||
|
MMRRETURN( MMSYSERR_NOMEM );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
case WODM_CLOSE:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_CLOSE") );
|
||
|
pOutClient = (LPDEVICEINFO)dwUser;
|
||
|
|
||
|
if( ((mmr=IsValidDeviceInfo(pOutClient)) != MMSYSERR_NOERROR ) ||
|
||
|
((mmr=IsValidDeviceState(pOutClient->DeviceState,FALSE)) != MMSYSERR_NOERROR) )
|
||
|
{
|
||
|
MMRRETURN( mmr );
|
||
|
}
|
||
|
|
||
|
mmr = wdmaudCloseDev( pOutClient );
|
||
|
if (MMSYSERR_NOERROR == mmr)
|
||
|
{
|
||
|
waveCallback(pOutClient, WOM_CLOSE, 0L);
|
||
|
|
||
|
ISVALIDDEVICEINFO(pOutClient);
|
||
|
ISVALIDDEVICESTATE(pOutClient->DeviceState,FALSE);
|
||
|
|
||
|
waveCleanUp(pOutClient);
|
||
|
}
|
||
|
return mmr;
|
||
|
|
||
|
case WODM_WRITE:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_WRITE") );
|
||
|
lpWaveHdr = (LPWAVEHDR)dwParam1;
|
||
|
pOutClient = (LPDEVICEINFO)dwUser;
|
||
|
|
||
|
//
|
||
|
// Sanity check the parameters and fail bad data!
|
||
|
//
|
||
|
if( ( (mmr=IsValidDeviceInfo(pOutClient)) != MMSYSERR_NOERROR ) ||
|
||
|
( (mmr=IsValidDeviceState(pOutClient->DeviceState,FALSE)) != MMSYSERR_NOERROR ) ||
|
||
|
( (mmr=IsValidWaveHeader(lpWaveHdr)) != MMSYSERR_NOERROR ) )
|
||
|
{
|
||
|
MMRRETURN( mmr );
|
||
|
}
|
||
|
|
||
|
// check if it's been prepared
|
||
|
DPFASSERT(lpWaveHdr->dwFlags & WHDR_PREPARED);
|
||
|
if (!(lpWaveHdr->dwFlags & WHDR_PREPARED))
|
||
|
MMRRETURN( WAVERR_UNPREPARED );
|
||
|
|
||
|
// if it is already in our Q, then we cannot do this
|
||
|
DPFASSERT(!(lpWaveHdr->dwFlags & WHDR_INQUEUE));
|
||
|
if ( lpWaveHdr->dwFlags & WHDR_INQUEUE )
|
||
|
MMRRETURN( WAVERR_STILLPLAYING );
|
||
|
|
||
|
//
|
||
|
// Put the request at the end of our queue.
|
||
|
//
|
||
|
return waveWrite(pOutClient, lpWaveHdr);
|
||
|
|
||
|
case WODM_PAUSE:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_PAUSE") );
|
||
|
pOutClient = (LPDEVICEINFO)dwUser;
|
||
|
return wdmaudSetDeviceState(pOutClient,
|
||
|
IOCTL_WDMAUD_WAVE_OUT_PAUSE);
|
||
|
|
||
|
case WODM_RESTART:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_RESTART") );
|
||
|
pOutClient = (LPDEVICEINFO)dwUser;
|
||
|
return wdmaudSetDeviceState(pOutClient,
|
||
|
IOCTL_WDMAUD_WAVE_OUT_PLAY);
|
||
|
|
||
|
case WODM_RESET:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_RESET") );
|
||
|
pOutClient = (LPDEVICEINFO)dwUser;
|
||
|
return wdmaudSetDeviceState(pOutClient,
|
||
|
IOCTL_WDMAUD_WAVE_OUT_RESET);
|
||
|
|
||
|
case WODM_BREAKLOOP:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_BREAKLOOP") );
|
||
|
pOutClient = (LPDEVICEINFO)dwUser;
|
||
|
return wdmaudSetDeviceState(pOutClient,
|
||
|
IOCTL_WDMAUD_WAVE_OUT_BREAKLOOP);
|
||
|
|
||
|
case WODM_GETPOS:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_GETPOS") );
|
||
|
|
||
|
pOutClient = (LPDEVICEINFO)dwUser;
|
||
|
|
||
|
if( ((mmr=IsValidDeviceInfo(pOutClient)) != MMSYSERR_NOERROR ) ||
|
||
|
((mmr=IsValidDeviceState(pOutClient->DeviceState,FALSE)) != MMSYSERR_NOERROR ) )
|
||
|
{
|
||
|
MMRRETURN( mmr );
|
||
|
}
|
||
|
|
||
|
mmr = wdmaudGetPos(pOutClient,
|
||
|
(LPMMTIME)dwParam1,
|
||
|
(DWORD)dwParam2,
|
||
|
WaveOutDevice);
|
||
|
DPF(DL_TRACE|FA_WAVE, ("GetPos: returned %lu", ((LPMMTIME)(dwParam1))->u.ms));
|
||
|
return mmr;
|
||
|
|
||
|
case WODM_SETVOLUME:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_SETVOLUME") );
|
||
|
|
||
|
pOutClient = GlobalAllocDeviceInfo((LPWSTR)dwParam2);
|
||
|
if (NULL == pOutClient)
|
||
|
{
|
||
|
MMRRETURN( MMSYSERR_NOMEM );
|
||
|
}
|
||
|
|
||
|
pOutClient->DeviceType = WaveOutDevice;
|
||
|
pOutClient->DeviceNumber = id;
|
||
|
pOutClient->OpenDone = 0;
|
||
|
PRESETERROR(pOutClient);
|
||
|
|
||
|
mmr = wdmaudIoControl(pOutClient,
|
||
|
sizeof(DWORD),
|
||
|
(LPBYTE)&dwParam1,
|
||
|
IOCTL_WDMAUD_WAVE_OUT_SET_VOLUME);
|
||
|
POSTEXTRACTERROR(mmr,pOutClient);
|
||
|
GlobalFreeDeviceInfo(pOutClient);
|
||
|
return mmr;
|
||
|
|
||
|
case WODM_GETVOLUME:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_GETVOLUME") );
|
||
|
|
||
|
pOutClient = GlobalAllocDeviceInfo((LPWSTR)dwParam2);
|
||
|
if (pOutClient)
|
||
|
{
|
||
|
LPDWORD pVolume;
|
||
|
|
||
|
pVolume = (LPDWORD) GlobalAllocPtr( GPTR, sizeof(DWORD));
|
||
|
if (pVolume)
|
||
|
{
|
||
|
pOutClient->DeviceType = WaveOutDevice;
|
||
|
pOutClient->DeviceNumber = id;
|
||
|
pOutClient->OpenDone = 0;
|
||
|
|
||
|
mmr = wdmaudIoControl(pOutClient,
|
||
|
sizeof(DWORD),
|
||
|
(LPBYTE)pVolume,
|
||
|
IOCTL_WDMAUD_WAVE_OUT_GET_VOLUME);
|
||
|
//
|
||
|
// Only write back information on success.
|
||
|
//
|
||
|
if( MMSYSERR_NOERROR == mmr )
|
||
|
*((DWORD FAR *) dwParam1) = *pVolume;
|
||
|
|
||
|
GlobalFreePtr(pVolume);
|
||
|
} else {
|
||
|
mmr = MMSYSERR_NOMEM;
|
||
|
}
|
||
|
|
||
|
GlobalFreeDeviceInfo(pOutClient);
|
||
|
} else {
|
||
|
mmr = MMSYSERR_NOMEM;
|
||
|
}
|
||
|
|
||
|
MMRRETURN( mmr );
|
||
|
|
||
|
#ifdef UNDER_NT
|
||
|
case WODM_PREPARE:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_PREPARE") );
|
||
|
pOutClient = (LPDEVICEINFO)dwUser;
|
||
|
|
||
|
if( ((mmr=IsValidDeviceInfo(pOutClient)) != MMSYSERR_NOERROR ) ||
|
||
|
((mmr=IsValidDeviceState(pOutClient->DeviceState,FALSE)) != MMSYSERR_NOERROR ) )
|
||
|
{
|
||
|
MMRRETURN( mmr );
|
||
|
}
|
||
|
|
||
|
return wdmaudPrepareWaveHeader(pOutClient, (LPWAVEHDR)dwParam1);
|
||
|
|
||
|
case WODM_UNPREPARE:
|
||
|
DPF(DL_TRACE|FA_WAVE, ("WODM_UNPREPARE") );
|
||
|
pOutClient = (LPDEVICEINFO)dwUser;
|
||
|
|
||
|
if( ((mmr=IsValidDeviceInfo(pOutClient)) != MMSYSERR_NOERROR ) ||
|
||
|
((mmr=IsValidDeviceState(pOutClient->DeviceState,FALSE)) != MMSYSERR_NOERROR ) )
|
||
|
{
|
||
|
MMRRETURN( mmr );
|
||
|
}
|
||
|
|
||
|
return wdmaudUnprepareWaveHeader(pOutClient, (LPWAVEHDR)dwParam1);
|
||
|
#endif
|
||
|
|
||
|
case WODM_GETPITCH:
|
||
|
case WODM_SETPITCH:
|
||
|
case WODM_GETPLAYBACKRATE:
|
||
|
case WODM_SETPLAYBACKRATE:
|
||
|
MMRRETURN( MMSYSERR_NOTSUPPORTED );
|
||
|
|
||
|
default:
|
||
|
MMRRETURN( MMSYSERR_NOTSUPPORTED );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Should not get here
|
||
|
//
|
||
|
|
||
|
DPFASSERT(0);
|
||
|
MMRRETURN( MMSYSERR_NOTSUPPORTED );
|
||
|
}
|