reactos/sdk/lib/drivers/sound/mment4/control.c

247 lines
6.9 KiB
C

/*
* PROJECT: ReactOS Sound System "MME Buddy" NT4 Library
* LICENSE: GPL - See COPYING in the top level directory
* FILE: lib/drivers/sound/mment4/control.c
*
* PURPOSE: Device control for NT4 audio devices
*
* PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
*/
#include "precomp.h"
#include <winioctl.h>
#include <ntddsnd.h>
#include <mmebuddy_debug.h>
/*
Convenience routine for getting the path of a device and opening it.
*/
MMRESULT
OpenNt4KernelSoundDevice(
IN PSOUND_DEVICE SoundDevice,
IN BOOLEAN ReadOnly,
OUT PHANDLE Handle)
{
PWSTR Path;
MMRESULT Result;
VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice) );
VALIDATE_MMSYS_PARAMETER( Handle );
Result = GetSoundDeviceIdentifier(SoundDevice, (PVOID*) &Path);
if ( ! MMSUCCESS(Result) )
{
SND_ERR(L"Unable to get sound device path");
return TranslateInternalMmResult(Result);
}
SND_ASSERT( Path );
return OpenKernelSoundDeviceByName(Path, ReadOnly, Handle);
}
/*
Device open/close. These are basically wrappers for the MME-Buddy
open and close routines, which provide a Windows device handle.
These may seem simple but as you can return pretty much anything
as the handle, we could just as easily return a structure etc.
*/
MMRESULT
OpenNt4SoundDevice(
IN PSOUND_DEVICE SoundDevice,
OUT PVOID* Handle)
{
SND_TRACE(L"Opening NT4 style sound device\n");
VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice) );
VALIDATE_MMSYS_PARAMETER( Handle );
return OpenNt4KernelSoundDevice(SoundDevice, FALSE, Handle);
}
MMRESULT
CloseNt4SoundDevice(
IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
IN PVOID Handle)
{
SND_TRACE(L"Closing NT4 style sound device\n");
VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
return CloseKernelSoundDevice((HANDLE) Handle);
}
/*
Provides an implementation for the "get capabilities" request,
using the standard IOCTLs used by NT4 sound drivers.
*/
MMRESULT
GetNt4SoundDeviceCapabilities(
IN PSOUND_DEVICE SoundDevice,
OUT PVOID Capabilities,
IN DWORD CapabilitiesSize)
{
MMRESULT Result;
MMDEVICE_TYPE DeviceType;
DWORD IoCtl;
HANDLE DeviceHandle;
/* If these are bad there's an internal error with MME-Buddy! */
SND_ASSERT( SoundDevice );
SND_ASSERT( Capabilities );
SND_ASSERT( CapabilitiesSize > 0 );
SND_TRACE(L"NT4 get-capabilities routine called\n");
/* Get the device type */
Result = GetSoundDeviceType(SoundDevice, &DeviceType);
SND_ASSERT( Result == MMSYSERR_NOERROR );
if ( ! MMSUCCESS(Result) )
return TranslateInternalMmResult(Result);
/* Choose the appropriate IOCTL */
if ( IS_WAVE_DEVICE_TYPE(DeviceType) )
{
IoCtl = IOCTL_WAVE_GET_CAPABILITIES;
}
else if ( IS_MIDI_DEVICE_TYPE(DeviceType) )
{
IoCtl = IOCTL_MIDI_GET_CAPABILITIES;
}
else
{
/* FIXME - need to support AUX and mixer devices */
SND_ASSERT( FALSE );
IoCtl = 0;
}
/* Get the capabilities information from the driver */
Result = OpenNt4KernelSoundDevice(SoundDevice, TRUE, &DeviceHandle);
if ( ! MMSUCCESS(Result) )
{
SND_ERR(L"Failed to open device");
return TranslateInternalMmResult(Result);
}
Result = SyncOverlappedDeviceIoControl(DeviceHandle,
IoCtl,
Capabilities,
CapabilitiesSize,
NULL,
0,
NULL);
CloseKernelSoundDevice(DeviceHandle);
if ( ! MMSUCCESS(Result) )
{
SND_ERR(L"Retrieval of capabilities information failed\n");
Result = TranslateInternalMmResult(Result);
}
return Result;
}
/*
Querying/setting the format of a wave device. Querying format support
requires us to first open the device, whereas setting format is done
on an already opened device.
*/
MMRESULT
QueryNt4WaveDeviceFormatSupport(
IN PSOUND_DEVICE SoundDevice,
IN LPWAVEFORMATEX Format,
IN DWORD FormatSize)
{
MMRESULT Result;
HANDLE Handle;
SND_TRACE(L"NT4 wave format support querying routine called\n");
VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice) );
VALIDATE_MMSYS_PARAMETER( Format );
VALIDATE_MMSYS_PARAMETER( FormatSize >= sizeof(WAVEFORMATEX) );
/* Get the device path */
Result = OpenNt4KernelSoundDevice(SoundDevice,
FALSE,
&Handle);
if ( ! MMSUCCESS(Result) )
{
SND_ERR(L"Unable to open kernel sound device\n");
return TranslateInternalMmResult(Result);
}
Result = SyncOverlappedDeviceIoControl(Handle,
IOCTL_WAVE_QUERY_FORMAT,
(LPVOID) Format,
FormatSize,
NULL,
0,
NULL);
if ( ! MMSUCCESS(Result) )
{
SND_ERR(L"Sync overlapped I/O failed - MMSYS_ERROR %d\n", Result);
Result = TranslateInternalMmResult(Result);
}
CloseKernelSoundDevice(Handle);
return MMSYSERR_NOERROR;
}
MMRESULT
SetNt4WaveDeviceFormat(
IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
IN DWORD DeviceId,
IN LPWAVEFORMATEX Format,
IN DWORD FormatSize)
{
MMRESULT Result;
HANDLE Handle;
VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
VALIDATE_MMSYS_PARAMETER( Format );
VALIDATE_MMSYS_PARAMETER( FormatSize >= sizeof(WAVEFORMATEX) );
Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
if ( ! MMSUCCESS(Result) )
return TranslateInternalMmResult(Result);
SND_TRACE(L"Setting wave device format on handle %x\n", Handle);
Result = SyncOverlappedDeviceIoControl(Handle,
IOCTL_WAVE_SET_FORMAT,
(LPVOID) Format,
FormatSize,
NULL,
0,
NULL);
if ( ! MMSUCCESS(Result) )
return TranslateInternalMmResult(Result);
return MMSYSERR_NOERROR;
}
#if 0
MMRESULT
SubmitNt4WaveHeader(
IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
IN PWAVEHDR WaveHeader)
{
VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
VALIDATE_MMSYS_PARAMETER( WaveHeader );
SND_TRACE(L"Submitting wave header %p (in sound thread)\n", WaveHeader);
/* TODO: This should only submit the header to the device, nothing more! */
}
#endif