/* * 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 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; }