reactos/sdk/lib/drivers/sound/mmixer/filter.c

285 lines
8.1 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: lib/drivers/sound/mmixer/filter.c
* PURPOSE: Mixer Filter Functions
* PROGRAMMER: Johannes Anderwald
*/
#include "precomp.h"
#define YDEBUG
#include <debug.h>
ULONG
MMixerGetFilterPinCount(
IN PMIXER_CONTEXT MixerContext,
IN HANDLE hMixer)
{
KSPROPERTY Pin;
MIXER_STATUS Status;
ULONG NumPins, BytesReturned;
/* setup property request */
Pin.Flags = KSPROPERTY_TYPE_GET;
Pin.Set = KSPROPSETID_Pin;
Pin.Id = KSPROPERTY_PIN_CTYPES;
/* query pin count */
Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&NumPins, sizeof(ULONG), (PULONG)&BytesReturned);
/* check for success */
if (Status != MM_STATUS_SUCCESS)
return 0;
return NumPins;
}
MIXER_STATUS
MMixerGetFilterTopologyProperty(
IN PMIXER_CONTEXT MixerContext,
IN HANDLE hMixer,
IN ULONG PropertyId,
OUT PKSMULTIPLE_ITEM * OutMultipleItem)
{
KSPROPERTY Property;
PKSMULTIPLE_ITEM MultipleItem;
MIXER_STATUS Status;
ULONG BytesReturned;
/* setup property request */
Property.Id = PropertyId;
Property.Flags = KSPROPERTY_TYPE_GET;
Property.Set = KSPROPSETID_Topology;
/* query for the size */
Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &BytesReturned);
if (Status != MM_STATUS_MORE_ENTRIES)
return Status;
/* sanity check */
ASSERT(BytesReturned);
/* allocate an result buffer */
MultipleItem = (PKSMULTIPLE_ITEM)MixerContext->Alloc(BytesReturned);
if (!MultipleItem)
{
/* not enough memory */
return MM_STATUS_NO_MEMORY;
}
/* query again with allocated buffer */
Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
if (Status != MM_STATUS_SUCCESS)
{
/* failed */
MixerContext->Free((PVOID)MultipleItem);
return Status;
}
/* store result */
*OutMultipleItem = MultipleItem;
/* done */
return Status;
}
MIXER_STATUS
MMixerGetPhysicalConnection(
IN PMIXER_CONTEXT MixerContext,
IN HANDLE hMixer,
IN ULONG PinId,
OUT PKSPIN_PHYSICALCONNECTION *OutConnection)
{
KSP_PIN Pin;
MIXER_STATUS Status;
ULONG BytesReturned;
PKSPIN_PHYSICALCONNECTION Connection;
/* setup the request */
Pin.Property.Flags = KSPROPERTY_TYPE_GET;
Pin.Property.Id = KSPROPERTY_PIN_PHYSICALCONNECTION;
Pin.Property.Set = KSPROPSETID_Pin;
Pin.PinId = PinId;
/* query the pin for the physical connection */
Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
if (Status == MM_STATUS_UNSUCCESSFUL)
{
/* pin does not have a physical connection */
return Status;
}
DPRINT("Status %u BytesReturned %lu\n", Status, BytesReturned);
Connection = (PKSPIN_PHYSICALCONNECTION)MixerContext->Alloc(BytesReturned);
if (!Connection)
{
/* not enough memory */
return MM_STATUS_NO_MEMORY;
}
/* query the pin for the physical connection */
Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Connection, BytesReturned, &BytesReturned);
if (Status != MM_STATUS_SUCCESS)
{
/* failed to query the physical connection */
MixerContext->Free(Connection);
return Status;
}
// store connection
*OutConnection = Connection;
return Status;
}
ULONG
MMixerGetControlTypeFromTopologyNode(
IN LPGUID NodeType)
{
if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_AGC))
{
/* automatic gain control */
return MIXERCONTROL_CONTROLTYPE_ONOFF;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_LOUDNESS))
{
/* loudness control */
return MIXERCONTROL_CONTROLTYPE_LOUDNESS;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUTE))
{
/* mute control */
return MIXERCONTROL_CONTROLTYPE_MUTE;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_TONE))
{
/* tone control
* FIXME
* MIXERCONTROL_CONTROLTYPE_ONOFF if KSPROPERTY_AUDIO_BASS_BOOST is supported
* MIXERCONTROL_CONTROLTYPE_BASS if KSPROPERTY_AUDIO_BASS is supported
* MIXERCONTROL_CONTROLTYPE_TREBLE if KSPROPERTY_AUDIO_TREBLE is supported
*/
UNIMPLEMENTED;
return MIXERCONTROL_CONTROLTYPE_ONOFF;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_VOLUME))
{
/* volume control */
return MIXERCONTROL_CONTROLTYPE_VOLUME;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_PEAKMETER))
{
/* peakmeter control */
return MIXERCONTROL_CONTROLTYPE_PEAKMETER;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUX))
{
/* mux control */
return MIXERCONTROL_CONTROLTYPE_MUX;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUX))
{
/* mux control */
return MIXERCONTROL_CONTROLTYPE_MUX;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_STEREO_WIDE))
{
/* stero wide control */
return MIXERCONTROL_CONTROLTYPE_FADER;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_CHORUS))
{
/* chorus control */
return MIXERCONTROL_CONTROLTYPE_FADER;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_REVERB))
{
/* reverb control */
return MIXERCONTROL_CONTROLTYPE_FADER;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_SUPERMIX))
{
/* supermix control
* MIXERCONTROL_CONTROLTYPE_MUTE if KSPROPERTY_AUDIO_MUTE is supported
*/
UNIMPLEMENTED;
return MIXERCONTROL_CONTROLTYPE_VOLUME;
}
/* TODO
* check for other supported node types
*/
//UNIMPLEMENTED;
return 0;
}
MIXER_STATUS
MMixerSetGetControlDetails(
IN PMIXER_CONTEXT MixerContext,
IN HANDLE hMixer,
IN ULONG NodeId,
IN ULONG bSet,
IN ULONG PropertyId,
IN ULONG Channel,
IN PLONG InputValue)
{
KSNODEPROPERTY_AUDIO_CHANNEL Property;
MIXER_STATUS Status;
LONG Value;
ULONG BytesReturned;
if (bSet)
Value = *InputValue;
/* setup the request */
RtlZeroMemory(&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL));
Property.NodeProperty.NodeId = NodeId;
Property.NodeProperty.Property.Id = PropertyId;
Property.NodeProperty.Property.Flags = KSPROPERTY_TYPE_TOPOLOGY;
Property.NodeProperty.Property.Set = KSPROPSETID_Audio;
Property.Channel = Channel;
Property.Reserved = 0;
if (bSet)
Property.NodeProperty.Property.Flags |= KSPROPERTY_TYPE_SET;
else
Property.NodeProperty.Property.Flags |= KSPROPERTY_TYPE_GET;
/* send the request */
Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), (PVOID)&Value, sizeof(LONG), &BytesReturned);
if (!bSet && Status == MM_STATUS_SUCCESS)
{
*InputValue = Value;
}
DPRINT("Status %x bSet %u NodeId %u Value %d PropertyId %u\n", Status, bSet, NodeId, Value, PropertyId);
return Status;
}
ULONG
MMixerGetPinInstanceCount(
PMIXER_CONTEXT MixerContext,
HANDLE hFilter,
ULONG PinId)
{
KSP_PIN PinRequest;
KSPIN_CINSTANCES PinInstances;
ULONG BytesReturned;
MIXER_STATUS Status;
/* query the instance count */
PinRequest.Reserved = 0;
PinRequest.PinId = PinId;
PinRequest.Property.Set = KSPROPSETID_Pin;
PinRequest.Property.Flags = KSPROPERTY_TYPE_GET;
PinRequest.Property.Id = KSPROPERTY_PIN_CINSTANCES;
Status = MixerContext->Control(hFilter, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&PinInstances, sizeof(KSPIN_CINSTANCES), &BytesReturned);
ASSERT(Status == MM_STATUS_SUCCESS);
return PinInstances.CurrentCount;
}