reactos/sdk/lib/drivers/sound/mmixer/mixer.c
Serge Gautherie 60b0afc3af
[BDASUP][KMIXER][MMIXER][STREAM] Replace meaningless YDEBUG (#5818)
bdasup: Addendum to 40c15ec (r46632).
kmixer: Addendum to 3e489bf (r42143).
mmixer: Addendum to c42d9f2 (r44872).
stream: Addendum to 4a0debf (r41662).
Serge plans a follow up that will remove all other remaining YDEBUG in the source tree.
The ones covered here he considered to be the most trivial ones.
2023-10-31 12:04:24 +00:00

883 lines
30 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: lib/drivers/sound/mmixer/mmixer.c
* PURPOSE: Mixer Handling Functions
* PROGRAMMER: Johannes Anderwald
*/
#include "precomp.h"
// #define NDEBUG
#include <debug.h>
ULONG
MMixerGetCount(
IN PMIXER_CONTEXT MixerContext)
{
PMIXER_LIST MixerList;
MIXER_STATUS Status;
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
/* invalid context passed */
return Status;
}
/* grab mixer list */
MixerList = (PMIXER_LIST)MixerContext->MixerContext;
// return number of mixers
return MixerList->MixerListCount;
}
MIXER_STATUS
MMixerGetCapabilities(
IN PMIXER_CONTEXT MixerContext,
IN ULONG MixerIndex,
OUT LPMIXERCAPSW MixerCaps)
{
MIXER_STATUS Status;
LPMIXER_INFO MixerInfo;
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
/* invalid context passed */
return Status;
}
/* get mixer info */
MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, MixerIndex);
if (!MixerInfo)
{
// invalid device index
return MM_STATUS_INVALID_PARAMETER;
}
MixerCaps->wMid = MixerInfo->MixCaps.wMid;
MixerCaps->wPid = MixerInfo->MixCaps.wPid;
MixerCaps->vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
MixerCaps->fdwSupport = MixerInfo->MixCaps.fdwSupport;
MixerCaps->cDestinations = MixerInfo->MixCaps.cDestinations;
ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == 0);
wcscpy(MixerCaps->szPname, MixerInfo->MixCaps.szPname);
return MM_STATUS_SUCCESS;
}
MIXER_STATUS
MMixerOpen(
IN PMIXER_CONTEXT MixerContext,
IN ULONG MixerId,
IN PVOID MixerEventContext,
IN PMIXER_EVENT MixerEventRoutine,
OUT PHANDLE MixerHandle)
{
MIXER_STATUS Status;
LPMIXER_INFO MixerInfo;
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
/* invalid context passed */
DPRINT1("invalid context\n");
return Status;
}
/* get mixer info */
MixerInfo = (LPMIXER_INFO)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
if (!MixerInfo)
{
/* invalid mixer id */
DPRINT1("invalid mixer id %lu\n", MixerId);
return MM_STATUS_INVALID_PARAMETER;
}
/* add the event */
Status = MMixerAddEvent(MixerContext, MixerInfo, MixerEventContext, MixerEventRoutine);
/* store result */
*MixerHandle = (HANDLE)MixerInfo;
return MM_STATUS_SUCCESS;
}
MIXER_STATUS
MMixerClose(
IN PMIXER_CONTEXT MixerContext,
IN ULONG MixerId,
IN PVOID MixerEventContext,
IN PMIXER_EVENT MixerEventRoutine)
{
MIXER_STATUS Status;
LPMIXER_INFO MixerInfo;
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
/* invalid context passed */
DPRINT1("invalid context\n");
return Status;
}
/* get mixer info */
MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, MixerId);
if (!MixerInfo)
{
/* invalid mixer id */
DPRINT1("invalid mixer id %lu\n", MixerId);
return MM_STATUS_INVALID_PARAMETER;
}
/* remove event from list */
return MMixerRemoveEvent(MixerContext, MixerInfo, MixerEventContext, MixerEventRoutine);
}
MIXER_STATUS
MMixerGetLineInfo(
IN PMIXER_CONTEXT MixerContext,
IN HANDLE MixerHandle,
IN ULONG MixerId,
IN ULONG Flags,
OUT LPMIXERLINEW MixerLine)
{
MIXER_STATUS Status;
LPMIXER_INFO MixerInfo;
LPMIXERLINE_EXT MixerLineSrc;
ULONG DestinationLineID;
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
/* invalid context passed */
return Status;
}
if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
{
/* caller passed mixer id */
MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
if (!MixerHandle)
{
/* invalid parameter */
return MM_STATUS_INVALID_PARAMETER;
}
}
if (MixerLine->cbStruct != sizeof(MIXERLINEW))
{
DPRINT1("MixerLine Expected %lu but got %lu\n", sizeof(MIXERLINEW), MixerLine->cbStruct);
return MM_STATUS_INVALID_PARAMETER;
}
/* clear hmixer from flags */
Flags &=~MIXER_OBJECTF_HMIXER;
DPRINT("MMixerGetLineInfo MixerId %lu Flags %lu\n", MixerId, Flags);
if (Flags == MIXER_GETLINEINFOF_DESTINATION)
{
/* cast to mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
/* calculate destination line id */
DestinationLineID = (MixerLine->dwDestination + DESTINATION_LINE);
/* get destination line */
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
if (MixerLineSrc == NULL)
{
DPRINT1("MixerCaps Name %S DestinationLineCount %lu dwDestination %lu not found\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations, MixerLine->dwDestination);
return MM_STATUS_UNSUCCESSFUL;
}
/* copy mixer line */
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
/* make sure it is null terminated */
MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
/* done */
return MM_STATUS_SUCCESS;
}
else if (Flags == MIXER_GETLINEINFOF_SOURCE)
{
/* cast to mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
/* calculate destination line id */
DestinationLineID = (MixerLine->dwDestination + DESTINATION_LINE);
/* get destination line */
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
if (MixerLineSrc == NULL)
{
DPRINT1("MixerCaps Name %S DestinationLineCount %lu dwDestination %lu not found\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations, MixerLine->dwDestination);
return MM_STATUS_UNSUCCESSFUL;
}
/* check if dwSource is out of bounds */
if (MixerLine->dwSource >= MixerLineSrc->Line.cConnections)
{
DPRINT1("MixerCaps Name %S MixerLineName %S Connections %lu dwSource %lu not found\n", MixerInfo->MixCaps.szPname, MixerLineSrc->Line.szName, MixerLineSrc->Line.cConnections, MixerLine->dwSource);
return MM_STATUS_UNSUCCESSFUL;
}
/* calculate destination line id */
DestinationLineID = (MixerLine->dwSource * SOURCE_LINE) + MixerLine->dwDestination;
DPRINT("MixerName %S cDestinations %lu MixerLineName %S cConnections %lu dwSource %lu dwDestination %lu ID %lx\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations,
MixerLineSrc->Line.szName, MixerLineSrc->Line.cConnections,
MixerLine->dwSource, MixerLine->dwDestination,
DestinationLineID);
/* get target destination line id */
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
/* sanity check */
ASSERT(MixerLineSrc);
DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
/* copy mixer line */
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
/* make sure it is null terminated */
MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
/* done */
return MM_STATUS_SUCCESS;
}
else if (Flags == MIXER_GETLINEINFOF_LINEID)
{
/* cast to mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
/* try to find line */
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwLineID);
if (!MixerLineSrc)
{
/* invalid parameter */
DPRINT1("MMixerGetLineInfo: MixerName %S Line not found 0x%lx\n", MixerInfo->MixCaps.szPname, MixerLine->dwLineID);
return MM_STATUS_INVALID_PARAMETER;
}
DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
/* copy mixer line*/
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
/* make sure it is null terminated */
MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
return MM_STATUS_SUCCESS;
}
else if (Flags == MIXER_GETLINEINFOF_COMPONENTTYPE)
{
/* cast to mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
/* find mixer line by component type */
MixerLineSrc = MMixerGetSourceMixerLineByComponentType(MixerInfo, MixerLine->dwComponentType);
if (!MixerLineSrc)
{
DPRINT1("Failed to find component type %x\n", MixerLine->dwComponentType);
return MM_STATUS_UNSUCCESSFUL;
}
/* copy mixer line */
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
/* make sure it is null terminated */
MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
/* done */
return MM_STATUS_SUCCESS;
}
else if (Flags == MIXER_GETLINEINFOF_TARGETTYPE)
{
DPRINT1("MIXER_GETLINEINFOF_TARGETTYPE handling is unimplemented\n");
}
else
{
DPRINT1("Unknown Flags %lx handling is unimplemented\n", Flags);
}
return MM_STATUS_NOT_IMPLEMENTED;
}
MIXER_STATUS
MMixerGetLineControls(
IN PMIXER_CONTEXT MixerContext,
IN HANDLE MixerHandle,
IN ULONG MixerId,
IN ULONG Flags,
OUT LPMIXERLINECONTROLSW MixerLineControls)
{
LPMIXER_INFO MixerInfo;
LPMIXERLINE_EXT MixerLineSrc;
LPMIXERCONTROL_EXT MixerControl;
MIXER_STATUS Status;
PLIST_ENTRY Entry;
ULONG Index;
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
/* invalid context passed */
return Status;
}
if (MixerLineControls->cbStruct != sizeof(MIXERLINECONTROLSW))
{
DPRINT1("Invalid MixerLineControls cbStruct passed %lu expected %lu\n", MixerLineControls->cbStruct, sizeof(MIXERLINECONTROLSW));
/* invalid parameter */
return MM_STATUS_INVALID_PARAMETER;
}
if (MixerLineControls->cbmxctrl != sizeof(MIXERCONTROLW))
{
DPRINT1("Invalid MixerLineControls cbmxctrl passed %lu expected %lu\n", MixerLineControls->cbmxctrl, sizeof(MIXERCONTROLW));
/* invalid parameter */
return MM_STATUS_INVALID_PARAMETER;
}
if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
{
/* caller passed mixer id */
MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
if (!MixerHandle)
{
/* invalid parameter */
return MM_STATUS_INVALID_PARAMETER;
}
}
Flags &= ~MIXER_OBJECTF_HMIXER;
DPRINT("MMixerGetLineControls MixerId %lu Flags %lu\n", MixerId, Flags);
if (Flags == MIXER_GETLINECONTROLSF_ALL)
{
/* cast to mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
/* get mixer line */
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
if (!MixerLineSrc)
{
/* invalid line id */
DPRINT("MMixerGetLineControls Line not found %lx\n", MixerLineControls->dwLineID);
return MM_STATUS_INVALID_PARAMETER;
}
if (MixerLineSrc->Line.cControls != MixerLineControls->cControls)
{
/* invalid parameter */
DPRINT1("Invalid control count %lu expected %lu\n", MixerLineControls->cControls, MixerLineSrc->Line.cControls);
return MM_STATUS_INVALID_PARAMETER;
}
/* copy line control(s) */
Entry = MixerLineSrc->ControlsList.Flink;
Index = 0;
while(Entry != &MixerLineSrc->ControlsList)
{
/* get mixer control */
MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
/* copy mixer control */
MixerContext->Copy(&MixerLineControls->pamxctrl[Index], &MixerControl->Control, sizeof(MIXERCONTROLW));
/* move to next */
Entry = Entry->Flink;
/* increment mixer control offset */
Index++;
}
return MM_STATUS_SUCCESS;
}
else if (Flags == MIXER_GETLINECONTROLSF_ONEBYTYPE)
{
/* cast to mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
/* get mixer line */
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
if (!MixerLineSrc)
{
/* invalid line id */
DPRINT1("MMixerGetLineControls Line not found %lx\n", MixerLineControls->dwLineID);
return MM_STATUS_INVALID_PARAMETER;
}
/* sanity checks */
ASSERT(MixerLineControls->cControls == 1);
ASSERT(MixerLineControls->cbmxctrl == sizeof(MIXERCONTROLW));
ASSERT(MixerLineControls->pamxctrl != NULL);
Entry = MixerLineSrc->ControlsList.Flink;
while(Entry != &MixerLineSrc->ControlsList)
{
MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
if (MixerLineControls->dwControlType == MixerControl->Control.dwControlType)
{
/* found a control with that type */
MixerContext->Copy(MixerLineControls->pamxctrl, &MixerControl->Control, sizeof(MIXERCONTROLW));
return MM_STATUS_SUCCESS;
}
/* move to next entry */
Entry = Entry->Flink;
}
DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls->dwControlType, MixerLineControls->dwLineID, MixerLineSrc->Line.cControls);
return MM_STATUS_UNSUCCESSFUL;
}
else if (Flags == MIXER_GETLINECONTROLSF_ONEBYID)
{
/* cast to mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
Status = MMixerGetMixerControlById(MixerInfo, MixerLineControls->dwControlID, NULL, &MixerControl, NULL);
if (Status != MM_STATUS_SUCCESS)
{
/* invalid parameter */
DPRINT("MMixerGetLineControls ControlID not found %lx\n", MixerLineControls->dwLineID);
return MM_STATUS_INVALID_PARAMETER;
}
ASSERT(MixerLineControls->cControls == 1);
ASSERT(MixerLineControls->cbmxctrl == sizeof(MIXERCONTROLW));
ASSERT(MixerLineControls->pamxctrl != NULL);
DPRINT("MMixerGetLineControls ControlID %lx ControlType %lx Name %S\n", MixerControl->Control.dwControlID, MixerControl->Control.dwControlType, MixerControl->Control.szName);
/* copy the controls */
MixerContext->Copy(MixerLineControls->pamxctrl, &MixerControl->Control, sizeof(MIXERCONTROLW));
MixerLineControls->pamxctrl->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
MixerLineControls->pamxctrl->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
return MM_STATUS_SUCCESS;
}
UNIMPLEMENTED;
return MM_STATUS_NOT_IMPLEMENTED;
}
MIXER_STATUS
MMixerSetControlDetails(
IN PMIXER_CONTEXT MixerContext,
IN HANDLE MixerHandle,
IN ULONG MixerId,
IN ULONG Flags,
OUT LPMIXERCONTROLDETAILS MixerControlDetails)
{
MIXER_STATUS Status;
ULONG NodeId;
LPMIXER_INFO MixerInfo;
LPMIXERLINE_EXT MixerLine;
LPMIXERCONTROL_EXT MixerControl;
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
/* invalid context passed */
DPRINT1("invalid context\n");
return Status;
}
if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
{
/* caller passed mixer id */
MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
if (!MixerHandle)
{
/* invalid parameter */
DPRINT1("invalid handle\n");
return MM_STATUS_INVALID_PARAMETER;
}
}
/* get mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
/* get mixer control */
Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId);
/* check for success */
if (Status != MM_STATUS_SUCCESS)
{
/* failed to find control id */
DPRINT1("invalid control id %lu\n", MixerControlDetails->dwControlID);
return MM_STATUS_INVALID_PARAMETER;
}
DPRINT("MMixerSetControlDetails ControlType %lx MixerControlName %S MixerLineName %S NodeID %lu\n", MixerControl->Control.dwControlType, MixerControl->Control.szName, MixerLine->Line.szName, NodeId);
switch(MixerControl->Control.dwControlType)
{
case MIXERCONTROL_CONTROLTYPE_MUTE:
Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, MixerControl, MixerLine->Line.dwLineID, MixerControlDetails, TRUE);
break;
case MIXERCONTROL_CONTROLTYPE_VOLUME:
Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, TRUE, MixerControl, MixerControlDetails, MixerLine);
break;
case MIXERCONTROL_CONTROLTYPE_MUX:
Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, TRUE, Flags, MixerControl, MixerControlDetails, MixerLine);
break;
default:
Status = MM_STATUS_NOT_IMPLEMENTED;
}
return Status;
}
MIXER_STATUS
MMixerGetControlDetails(
IN PMIXER_CONTEXT MixerContext,
IN HANDLE MixerHandle,
IN ULONG MixerId,
IN ULONG Flags,
OUT LPMIXERCONTROLDETAILS MixerControlDetails)
{
MIXER_STATUS Status;
ULONG NodeId;
LPMIXER_INFO MixerInfo;
LPMIXERLINE_EXT MixerLine;
LPMIXERCONTROL_EXT MixerControl;
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
/* invalid context passed */
return Status;
}
if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
{
/* caller passed mixer id */
MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
if (!MixerHandle)
{
/* invalid parameter */
return MM_STATUS_INVALID_PARAMETER;
}
}
/* get mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
/* get mixer control */
Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId);
/* check for success */
if (Status != MM_STATUS_SUCCESS)
{
/* failed to find control id */
return MM_STATUS_INVALID_PARAMETER;
}
switch(MixerControl->Control.dwControlType)
{
case MIXERCONTROL_CONTROLTYPE_MUTE:
Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, MixerControl, MixerLine->Line.dwLineID, MixerControlDetails, FALSE);
break;
case MIXERCONTROL_CONTROLTYPE_VOLUME:
Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, FALSE, MixerControl, MixerControlDetails, MixerLine);
break;
case MIXERCONTROL_CONTROLTYPE_ONOFF:
DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_ONOFF\n");
break;
case MIXERCONTROL_CONTROLTYPE_MUX:
Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, FALSE, Flags, MixerControl, MixerControlDetails, MixerLine);
break;
default:
Status = MM_STATUS_NOT_IMPLEMENTED;
DPRINT1("ControlType %lx not implemented\n", MixerControl->Control.dwControlType);
}
return Status;
}
VOID
MMixerPrintMixerLineControls(
IN LPMIXERLINE_EXT MixerLine)
{
PLIST_ENTRY Entry;
LPMIXERCONTROL_EXT MixerControl;
ULONG Index = 0;
Entry = MixerLine->ControlsList.Flink;
while(Entry != &MixerLine->ControlsList)
{
MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
DPRINT1("\n");
DPRINT1("Control Index: %lu\n", Index);
DPRINT("\n");
DPRINT1("cbStruct %u\n", MixerControl->Control.cbStruct);
DPRINT1("dwControlID %lu\n", MixerControl->Control.dwControlID);
DPRINT1("dwControlType %lx\n", MixerControl->Control.dwControlType);
DPRINT1("fdwControl %lu\n", MixerControl->Control.fdwControl);
DPRINT1("cMultipleItems %lu\n", MixerControl->Control.cMultipleItems);
DPRINT1("szShortName %S\n", MixerControl->Control.szShortName);
DPRINT1("szName %S\n", MixerControl->Control.szName);
DPRINT1("Bounds.dwMinimum %lu\n", MixerControl->Control.Bounds.dwMinimum);
DPRINT1("Bounds.dwMaximum %lu\n", MixerControl->Control.Bounds.dwMaximum);
DPRINT1("Metrics.Reserved[0] %lu\n", MixerControl->Control.Metrics.dwReserved[0]);
DPRINT1("Metrics.Reserved[1] %lu\n", MixerControl->Control.Metrics.dwReserved[1]);
DPRINT1("Metrics.Reserved[2] %lu\n", MixerControl->Control.Metrics.dwReserved[2]);
DPRINT1("Metrics.Reserved[3] %lu\n", MixerControl->Control.Metrics.dwReserved[3]);
DPRINT1("Metrics.Reserved[4] %lu\n", MixerControl->Control.Metrics.dwReserved[4]);
DPRINT1("Metrics.Reserved[5] %lu\n", MixerControl->Control.Metrics.dwReserved[5]);
Entry = Entry->Flink;
Index++;
}
}
VOID
MMixerPrintMixers(
IN PMIXER_CONTEXT MixerContext,
IN PMIXER_LIST MixerList)
{
ULONG Index, SubIndex, DestinationLineID, SrcIndex;
LPMIXER_INFO MixerInfo;
LPMIXERLINE_EXT DstMixerLine, SrcMixerLine;
DPRINT1("MixerList %p\n", MixerList);
DPRINT1("MidiInCount %lu\n", MixerList->MidiInListCount);
DPRINT1("MidiOutCount %lu\n", MixerList->MidiOutListCount);
DPRINT1("WaveInCount %lu\n", MixerList->WaveInListCount);
DPRINT1("WaveOutCount %lu\n", MixerList->WaveOutListCount);
DPRINT1("MixerCount %p\n", MixerList->MixerListCount);
for(Index = 0; Index < MixerList->MixerListCount; Index++)
{
/* get mixer info */
MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, Index);
ASSERT(MixerInfo);
DPRINT1("\n");
DPRINT1("Name :%S\n", MixerInfo->MixCaps.szPname);
DPRINT1("cDestinations: %lu\n", MixerInfo->MixCaps.cDestinations);
DPRINT1("fdwSupport %lu\n", MixerInfo->MixCaps.fdwSupport);
DPRINT1("vDriverVersion %lx\n", MixerInfo->MixCaps.vDriverVersion);
DPRINT1("wMid %lx\n", MixerInfo->MixCaps.wMid);
DPRINT1("wPid %lx\n", MixerInfo->MixCaps.wPid);
for(SubIndex = 0; SubIndex < MixerInfo->MixCaps.cDestinations; SubIndex++)
{
/* calculate destination line id */
DestinationLineID = (SubIndex + DESTINATION_LINE);
/* get destination line */
DstMixerLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
DPRINT1("//----------------------------------------------------------------------------------------------\n");
DPRINT1("\n");
DPRINT1("Destination Index %lu\n", SubIndex);
DPRINT1("\n");
DPRINT1("cChannels %lu\n", DstMixerLine->Line.cChannels);
DPRINT1("cConnections %lu\n", DstMixerLine->Line.cConnections);
DPRINT1("cControls %lu\n", DstMixerLine->Line.cControls);
DPRINT1("dwComponentType %lx\n", DstMixerLine->Line.dwComponentType);
DPRINT1("dwDestination %lu\n", DstMixerLine->Line.dwDestination);
DPRINT1("dwLineID %lx\n", DstMixerLine->Line.dwLineID);
DPRINT1("dwSource %lx\n", DstMixerLine->Line.dwSource);
DPRINT1("dwUser %lu\n", DstMixerLine->Line.dwUser);
DPRINT1("fdwLine %lu\n", DstMixerLine->Line.fdwLine);
DPRINT1("szName %S\n", DstMixerLine->Line.szName);
DPRINT1("szShortName %S\n", DstMixerLine->Line.szShortName);
DPRINT1("Target.dwDeviceId %lu\n", DstMixerLine->Line.Target.dwDeviceID);
DPRINT1("Target.dwType %lu\n", DstMixerLine->Line.Target.dwType);
DPRINT1("Target.szName %S\n", DstMixerLine->Line.Target.szPname);
DPRINT1("Target.vDriverVersion %lx\n", DstMixerLine->Line.Target.vDriverVersion);
DPRINT1("Target.wMid %lx\n", DstMixerLine->Line.Target.wMid );
DPRINT1("Target.wPid %lx\n", DstMixerLine->Line.Target.wPid);
MMixerPrintMixerLineControls(DstMixerLine);
for(SrcIndex = 0; SrcIndex < DstMixerLine->Line.cConnections; SrcIndex++)
{
/* calculate destination line id */
DestinationLineID = (SOURCE_LINE * SrcIndex) + SubIndex;
/* get source line */
SrcMixerLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
DPRINT1("//==============================================================================================\n");
DPRINT1("\n");
DPRINT1("SrcLineIndex : %lu\n", SrcIndex);
DPRINT1("\n");
DPRINT1("cChannels %lu\n", SrcMixerLine->Line.cChannels);
DPRINT1("cConnections %lu\n", SrcMixerLine->Line.cConnections);
DPRINT1("cControls %lu\n", SrcMixerLine->Line.cControls);
DPRINT1("dwComponentType %lx\n", SrcMixerLine->Line.dwComponentType);
DPRINT1("dwDestination %lu\n", SrcMixerLine->Line.dwDestination);
DPRINT1("dwLineID %lx\n", SrcMixerLine->Line.dwLineID);
DPRINT1("dwSource %lx\n", SrcMixerLine->Line.dwSource);
DPRINT1("dwUser %lu\n", SrcMixerLine->Line.dwUser);
DPRINT1("fdwLine %lu\n", SrcMixerLine->Line.fdwLine);
DPRINT1("szName %S\n", SrcMixerLine->Line.szName);
DPRINT1("szShortName %S\n", SrcMixerLine->Line.szShortName);
DPRINT1("Target.dwDeviceId %lu\n", SrcMixerLine->Line.Target.dwDeviceID);
DPRINT1("Target.dwType %lu\n", SrcMixerLine->Line.Target.dwType);
DPRINT1("Target.szName %S\n", SrcMixerLine->Line.Target.szPname);
DPRINT1("Target.vDriverVersion %lx\n", SrcMixerLine->Line.Target.vDriverVersion);
DPRINT1("Target.wMid %lx\n", SrcMixerLine->Line.Target.wMid );
DPRINT1("Target.wPid %lx\n", SrcMixerLine->Line.Target.wPid);
MMixerPrintMixerLineControls(SrcMixerLine);
}
}
}
}
MIXER_STATUS
MMixerInitialize(
IN PMIXER_CONTEXT MixerContext,
IN PMIXER_ENUM EnumFunction,
IN PVOID EnumContext)
{
MIXER_STATUS Status;
HANDLE hMixer, hKey;
ULONG DeviceIndex, Count;
LPWSTR DeviceName;
LPMIXER_DATA MixerData;
PMIXER_LIST MixerList;
PLIST_ENTRY Entry;
if (!MixerContext || !EnumFunction || !EnumContext)
{
/* invalid parameter */
return MM_STATUS_INVALID_PARAMETER;
}
if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free || !MixerContext->Open ||
!MixerContext->AllocEventData || !MixerContext->FreeEventData ||
!MixerContext->Close || !MixerContext->OpenKey || !MixerContext->QueryKeyValue || !MixerContext->CloseKey)
{
/* invalid parameter */
return MM_STATUS_INVALID_PARAMETER;
}
/* allocate a mixer list */
MixerList = (PMIXER_LIST)MixerContext->Alloc(sizeof(MIXER_LIST));
if (!MixerList)
{
/* no memory */
return MM_STATUS_NO_MEMORY;
}
/* initialize mixer list */
MixerList->MixerListCount = 0;
MixerList->MixerDataCount = 0;
MixerList->WaveInListCount = 0;
MixerList->WaveOutListCount = 0;
MixerList->MidiInListCount = 0;
MixerList->MidiOutListCount = 0;
InitializeListHead(&MixerList->MixerList);
InitializeListHead(&MixerList->MixerData);
InitializeListHead(&MixerList->WaveInList);
InitializeListHead(&MixerList->WaveOutList);
InitializeListHead(&MixerList->MidiInList);
InitializeListHead(&MixerList->MidiOutList);
/* store mixer list */
MixerContext->MixerContext = (PVOID)MixerList;
/* start enumerating all available devices */
Count = 0;
DeviceIndex = 0;
do
{
/* enumerate a device */
Status = EnumFunction(EnumContext, DeviceIndex, &DeviceName, &hMixer, &hKey);
if (Status != MM_STATUS_SUCCESS)
{
/* check error code */
if (Status == MM_STATUS_NO_MORE_DEVICES)
{
/* enumeration has finished */
break;
}
else
{
DPRINT1("Failed to enumerate device %lu\n", DeviceIndex);
/* TODO cleanup */
return Status;
}
}
else
{
/* create a mixer data entry */
Status = MMixerCreateMixerData(MixerContext, MixerList, DeviceIndex, DeviceName, hMixer, hKey);
if (Status != MM_STATUS_SUCCESS)
break;
}
/* increment device index */
DeviceIndex++;
}while(TRUE);
/* now all filters have been pre-opened
* lets enumerate the filters
*/
Entry = MixerList->MixerData.Flink;
while(Entry != &MixerList->MixerData)
{
MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
MMixerSetupFilter(MixerContext, MixerList, MixerData, &Count);
Entry = Entry->Flink;
}
Entry = MixerList->MixerData.Flink;
while(Entry != &MixerList->MixerData)
{
MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
/* now handle alternative mixer types */
MMixerHandleAlternativeMixers(MixerContext, MixerList, MixerData, MixerData->Topology);
Entry = Entry->Flink;
}
//MMixerPrintMixers(MixerContext, MixerList);
/* done */
return MM_STATUS_SUCCESS;
}