mirror of
https://github.com/reactos/reactos.git
synced 2024-09-18 08:42:34 +00:00
285 lines
8.1 KiB
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;
|
|
}
|