From f45bd7617ae380ce5b26b3ac158c5f41b562642d Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Sun, 20 Dec 2009 00:55:55 +0000 Subject: [PATCH] [MMIXER] - Add support for enumerating wave in/out devices. Based on the wdmaud driver code svn path=/trunk/; revision=44664 --- reactos/lib/drivers/sound/mmixer/controls.c | 12 + reactos/lib/drivers/sound/mmixer/filter.c | 24 + reactos/lib/drivers/sound/mmixer/mixer.c | 7 +- reactos/lib/drivers/sound/mmixer/mmixer.h | 31 +- .../lib/drivers/sound/mmixer/mmixer.rbuild | 1 + reactos/lib/drivers/sound/mmixer/priv.h | 25 + reactos/lib/drivers/sound/mmixer/wave.c | 578 ++++++++++++++++++ 7 files changed, 676 insertions(+), 2 deletions(-) create mode 100644 reactos/lib/drivers/sound/mmixer/wave.c diff --git a/reactos/lib/drivers/sound/mmixer/controls.c b/reactos/lib/drivers/sound/mmixer/controls.c index adc8187b93e..b879da41061 100644 --- a/reactos/lib/drivers/sound/mmixer/controls.c +++ b/reactos/lib/drivers/sound/mmixer/controls.c @@ -827,6 +827,7 @@ MMixerInitializeFilter( ULONG BytesReturned; KSP_PIN Pin; LPWSTR Buffer = NULL; + ULONG PinId; // allocate a mixer info struct MixerInfo = (LPMIXER_INFO) MixerContext->Alloc(sizeof(MIXER_INFO)); @@ -864,10 +865,15 @@ MMixerInitializeFilter( // now get the target pins of the ADC / DAC node Status = MMixerGetTargetPins(MixerContext, NodeTypes, NodeConnections, NodeIndex, !bInputMixer, Pins, PinCount); + // find a target pin with a name + PinId = PinCount +1; for(Index = 0; Index < PinCount; Index++) { if (Pins[Index]) { + // store index of pin + PinId = Index; + /* retrieve pin name */ Pin.PinId = Index; Pin.Reserved = 0; @@ -900,6 +906,12 @@ MMixerInitializeFilter( } } + if (PinId < PinCount) + { + // create an wave info struct + MMixerInitializeWaveInfo(MixerContext, MixerList, MixerData, MixerInfo->MixCaps.szPname, bInputMixer, PinId); + } + Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInputMixer, Buffer); if (Buffer) diff --git a/reactos/lib/drivers/sound/mmixer/filter.c b/reactos/lib/drivers/sound/mmixer/filter.c index d3abfb82051..5e1ff8b05f9 100644 --- a/reactos/lib/drivers/sound/mmixer/filter.c +++ b/reactos/lib/drivers/sound/mmixer/filter.c @@ -251,3 +251,27 @@ MMixerSetGetControlDetails( 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; +} + diff --git a/reactos/lib/drivers/sound/mmixer/mixer.c b/reactos/lib/drivers/sound/mmixer/mixer.c index 94c3a2a093a..d66116ae593 100644 --- a/reactos/lib/drivers/sound/mmixer/mixer.c +++ b/reactos/lib/drivers/sound/mmixer/mixer.c @@ -215,7 +215,7 @@ MMixerGetLineControls( IN PMIXER_CONTEXT MixerContext, IN HANDLE MixerHandle, IN ULONG Flags, - OUT LPMIXERLINECONTROLS MixerLineControls) + OUT LPMIXERLINECONTROLSW MixerLineControls) { LPMIXER_INFO MixerInfo; LPMIXERLINE_EXT MixerLineSrc; @@ -440,8 +440,13 @@ MMixerInitialize( //initialize mixer list MixerList->MixerListCount = 0; MixerList->MixerDataCount = 0; + MixerList->WaveInListCount = 0; + MixerList->WaveOutListCount = 0; InitializeListHead(&MixerList->MixerList); InitializeListHead(&MixerList->MixerData); + InitializeListHead(&MixerList->WaveInList); + InitializeListHead(&MixerList->WaveOutList); + // store mixer list MixerContext->MixerContext = (PVOID)MixerList; diff --git a/reactos/lib/drivers/sound/mmixer/mmixer.h b/reactos/lib/drivers/sound/mmixer/mmixer.h index bb272f3f2ec..1965613693f 100644 --- a/reactos/lib/drivers/sound/mmixer/mmixer.h +++ b/reactos/lib/drivers/sound/mmixer/mmixer.h @@ -95,6 +95,15 @@ ULONG MMixerGetCount( IN PMIXER_CONTEXT MixerContext); +ULONG +MMixerGetWaveInCount( + IN PMIXER_CONTEXT MixerContext); + +ULONG +MMixerGetWaveOutCount( + IN PMIXER_CONTEXT MixerContext); + + MIXER_STATUS MMixerGetCapabilities( IN PMIXER_CONTEXT MixerContext, @@ -121,7 +130,7 @@ MMixerGetLineControls( IN PMIXER_CONTEXT MixerContext, IN HANDLE MixerHandle, IN ULONG Flags, - OUT LPMIXERLINECONTROLS MixerLineControls); + OUT LPMIXERLINECONTROLSW MixerLineControls); MIXER_STATUS MMixerSetControlDetails( @@ -137,4 +146,24 @@ MMixerGetControlDetails( IN ULONG Flags, OUT LPMIXERCONTROLDETAILS MixerControlDetails); +MIXER_STATUS +MMixerWaveOutCapabilities( + IN PMIXER_CONTEXT MixerContext, + IN ULONG DeviceIndex, + OUT LPWAVEOUTCAPSW Caps); + +MIXER_STATUS +MMixerWaveInCapabilities( + IN PMIXER_CONTEXT MixerContext, + IN ULONG DeviceIndex, + OUT LPWAVEINCAPSW Caps); + +MIXER_STATUS +MMixerOpenWave( + IN PMIXER_CONTEXT MixerContext, + IN ULONG DeviceIndex, + IN ULONG bWaveIn, + IN LPWAVEFORMATEX WaveFormat, + OUT PHANDLE PinHandle); + #endif diff --git a/reactos/lib/drivers/sound/mmixer/mmixer.rbuild b/reactos/lib/drivers/sound/mmixer/mmixer.rbuild index 86644eb6b4b..582868ab1d6 100644 --- a/reactos/lib/drivers/sound/mmixer/mmixer.rbuild +++ b/reactos/lib/drivers/sound/mmixer/mmixer.rbuild @@ -7,4 +7,5 @@ filter.c mixer.c sup.c + wave.c diff --git a/reactos/lib/drivers/sound/mmixer/priv.h b/reactos/lib/drivers/sound/mmixer/priv.h index 0f91f443436..0cdbd8ce353 100644 --- a/reactos/lib/drivers/sound/mmixer/priv.h +++ b/reactos/lib/drivers/sound/mmixer/priv.h @@ -64,12 +64,28 @@ typedef struct LPWSTR DeviceName; }MIXER_DATA, *LPMIXER_DATA; +typedef struct +{ + LIST_ENTRY Entry; + ULONG DeviceId; + ULONG PinId; + union + { + WAVEOUTCAPSW OutCaps; + WAVEINCAPSW InCaps; + }u; +}WAVE_INFO, *LPWAVE_INFO; + typedef struct { ULONG MixerListCount; LIST_ENTRY MixerList; ULONG MixerDataCount; LIST_ENTRY MixerData; + ULONG WaveInListCount; + LIST_ENTRY WaveInList; + ULONG WaveOutListCount; + LIST_ENTRY WaveOutList; }MIXER_LIST, *PMIXER_LIST; #define DESTINATION_LINE 0xFFFF0000 @@ -243,4 +259,13 @@ MMixerGetDeviceName( IN LPMIXER_INFO MixerInfo, IN HANDLE hKey); +MIXER_STATUS +MMixerInitializeWaveInfo( + IN PMIXER_CONTEXT MixerContext, + IN PMIXER_LIST MixerList, + IN LPMIXER_DATA MixerData, + IN LPWSTR DeviceName, + IN ULONG bWaveIn, + IN ULONG PinId); + #endif diff --git a/reactos/lib/drivers/sound/mmixer/wave.c b/reactos/lib/drivers/sound/mmixer/wave.c new file mode 100644 index 00000000000..7e3ff340229 --- /dev/null +++ b/reactos/lib/drivers/sound/mmixer/wave.c @@ -0,0 +1,578 @@ +/* + * 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 "priv.h" + +const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}}; +const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +const GUID KSINTERFACESETID_Standard = {0x1A8766A0L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; +const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; + +typedef struct +{ + ULONG SampleRate; + ULONG Bit8Mono; + ULONG Bit8Stereo; + ULONG Bit16Mono; + ULONG Bit16Stereo; +}AUDIO_RANGE; + +#define AUDIO_TEST_RANGE (5) + +static AUDIO_RANGE TestRange[AUDIO_TEST_RANGE] = +{ + { + 11025, + WAVE_FORMAT_1M08, + WAVE_FORMAT_1S08, + WAVE_FORMAT_1M16, + WAVE_FORMAT_1S16 + }, + { + 22050, + WAVE_FORMAT_2M08, + WAVE_FORMAT_2S08, + WAVE_FORMAT_2M16, + WAVE_FORMAT_2S16 + }, + { + 44100, + WAVE_FORMAT_4M08, + WAVE_FORMAT_4S08, + WAVE_FORMAT_4M16, + WAVE_FORMAT_4S16 + }, + { + 48000, + WAVE_FORMAT_48M08, + WAVE_FORMAT_48S08, + WAVE_FORMAT_48M16, + WAVE_FORMAT_48S16 + }, + { + 96000, + WAVE_FORMAT_96M08, + WAVE_FORMAT_96S08, + WAVE_FORMAT_96M16, + WAVE_FORMAT_96S16 + } +}; + +PKSPIN_CONNECT +MMixerAllocatePinConnect( + IN PMIXER_CONTEXT MixerContext, + ULONG DataFormatSize) +{ + return MixerContext->Alloc(sizeof(KSPIN_CONNECT) + DataFormatSize); +} + +MIXER_STATUS +MMixerGetWaveInfoByIndexAndType( + IN PMIXER_LIST MixerList, + IN ULONG DeviceIndex, + IN ULONG bWaveInType, + OUT LPWAVE_INFO *OutWaveInfo) +{ + ULONG Index = 0; + PLIST_ENTRY Entry, ListHead; + LPWAVE_INFO WaveInfo; + + if (bWaveInType) + ListHead = &MixerList->WaveInList; + else + ListHead = &MixerList->WaveOutList; + + /* get first entry */ + Entry = ListHead->Flink; + + while(Entry != ListHead) + { + WaveInfo = (LPWAVE_INFO)CONTAINING_RECORD(Entry, WAVE_INFO, Entry); + + if (Index == DeviceIndex) + { + *OutWaveInfo = WaveInfo; + return MM_STATUS_SUCCESS; + } + Index++; + Entry = Entry->Flink; + } + + return MM_STATUS_INVALID_PARAMETER; +} + + +VOID +MMixerInitializePinConnect( + IN OUT PKSPIN_CONNECT PinConnect, + IN ULONG PinId) +{ + PinConnect->Interface.Set = KSINTERFACESETID_Standard; + PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING; + PinConnect->Interface.Flags = 0; + PinConnect->Medium.Set = KSMEDIUMSETID_Standard; + PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE; + PinConnect->Medium.Flags = 0; + PinConnect->PinToHandle = NULL; + PinConnect->PinId = PinId; + PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; + PinConnect->Priority.PrioritySubClass = 1; +} + +VOID +MMixerInitializeDataFormat( + IN PKSDATAFORMAT_WAVEFORMATEX DataFormat, + LPWAVEFORMATEX WaveFormatEx) +{ + + DataFormat->WaveFormatEx.wFormatTag = WaveFormatEx->wFormatTag; + DataFormat->WaveFormatEx.nChannels = WaveFormatEx->nChannels; + DataFormat->WaveFormatEx.nSamplesPerSec = WaveFormatEx->nSamplesPerSec; + DataFormat->WaveFormatEx.nBlockAlign = WaveFormatEx->nBlockAlign; + DataFormat->WaveFormatEx.nAvgBytesPerSec = WaveFormatEx->nAvgBytesPerSec; + DataFormat->WaveFormatEx.wBitsPerSample = WaveFormatEx->wBitsPerSample; + DataFormat->WaveFormatEx.cbSize = 0; + DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX); + DataFormat->DataFormat.Flags = 0; + DataFormat->DataFormat.Reserved = 0; + DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; + + DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; + DataFormat->DataFormat.SampleSize = 4; +} + + +MIXER_STATUS +MMixerGetAudioPinDataRanges( + IN PMIXER_CONTEXT MixerContext, + IN HANDLE hDevice, + IN ULONG PinId, + IN OUT PKSMULTIPLE_ITEM * OutMultipleItem) +{ + KSP_PIN PinProperty; + ULONG BytesReturned = 0; + MIXER_STATUS Status; + PKSMULTIPLE_ITEM MultipleItem; + + /* retrieve size of data ranges buffer */ + PinProperty.Reserved = 0; + PinProperty.PinId = PinId; + PinProperty.Property.Set = KSPROPSETID_Pin; + PinProperty.Property.Id = KSPROPERTY_PIN_DATARANGES; + PinProperty.Property.Flags = KSPROPERTY_TYPE_GET; + + Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)NULL, 0, &BytesReturned); + if (Status != MM_STATUS_MORE_ENTRIES) + { + return Status; + } + + MultipleItem = MixerContext->Alloc(BytesReturned); + if (!MultipleItem) + { + /* not enough memory */ + return MM_STATUS_NO_MEMORY; + } + + Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned); + if (Status != MM_STATUS_SUCCESS) + { + /* failed */ + MixerContext->Free(MultipleItem); + return Status; + } + + /* save result */ + *OutMultipleItem = MultipleItem; + return Status; +} + +MIXER_STATUS +MMixerFindAudioDataRange( + PKSMULTIPLE_ITEM MultipleItem, + PKSDATARANGE_AUDIO * OutDataRangeAudio) +{ + ULONG Index; + PKSDATARANGE_AUDIO DataRangeAudio; + PKSDATARANGE DataRange; + + DataRange = (PKSDATARANGE) (MultipleItem + 1); + for(Index = 0; Index < MultipleItem->Count; Index++) + { + if (DataRange->FormatSize == sizeof(KSDATARANGE_AUDIO)) + { + DataRangeAudio = (PKSDATARANGE_AUDIO)DataRange; + if (IsEqualGUIDAligned(&DataRangeAudio->DataRange.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO) && + IsEqualGUIDAligned(&DataRangeAudio->DataRange.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) && + IsEqualGUIDAligned(&DataRangeAudio->DataRange.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)) + { + DPRINT("Min Sample %u Max Sample %u Min Bits %u Max Bits %u Max Channel %u\n", DataRangeAudio->MinimumSampleFrequency, DataRangeAudio->MaximumSampleFrequency, + DataRangeAudio->MinimumBitsPerSample, DataRangeAudio->MaximumBitsPerSample, DataRangeAudio->MaximumChannels); + *OutDataRangeAudio = DataRangeAudio; + return MM_STATUS_SUCCESS; + } + } + DataRange = (PKSDATARANGE)((ULONG_PTR)DataRange + DataRange->FormatSize); + } + return MM_STATUS_UNSUCCESSFUL; +} + +MIXER_STATUS +MMixerOpenWavePin( + IN PMIXER_CONTEXT MixerContext, + IN PMIXER_LIST MixerList, + IN ULONG DeviceId, + IN ULONG PinId, + IN LPWAVEFORMATEX WaveFormatEx, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE PinHandle) +{ + PKSPIN_CONNECT PinConnect; + PKSDATAFORMAT_WAVEFORMATEX DataFormat; + LPMIXER_DATA MixerData; + NTSTATUS Status; + + MixerData = MMixerGetDataByDeviceId(MixerList, DeviceId); + if (!MixerData) + return MM_STATUS_INVALID_PARAMETER; + + /* allocate pin connect */ + PinConnect = MMixerAllocatePinConnect(MixerContext, sizeof(KSDATAFORMAT_WAVEFORMATEX)); + if (!PinConnect) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + + /* initialize pin connect struct */ + MMixerInitializePinConnect(PinConnect, PinId); + + /* get offset to dataformat */ + DataFormat = (PKSDATAFORMAT_WAVEFORMATEX) (PinConnect + 1); + /* initialize with requested wave format */ + MMixerInitializeDataFormat(DataFormat, WaveFormatEx); + + /* now create the pin */ + Status = KsCreatePin(MixerData->hDevice, PinConnect, DesiredAccess, PinHandle); + + /* free create info */ + MixerContext->Free(PinConnect); + + if (Status == STATUS_SUCCESS) + return MM_STATUS_SUCCESS; + else + return MM_STATUS_UNSUCCESSFUL; +} + +VOID +MMixerCheckFormat( + IN PKSDATARANGE_AUDIO DataRangeAudio, + IN LPWAVE_INFO WaveInfo, + IN ULONG bInput) +{ + ULONG Index, SampleFrequency; + ULONG Result = 0; + + for(Index = 0; Index < AUDIO_TEST_RANGE; Index++) + { + SampleFrequency = TestRange[Index].SampleRate; + + if (DataRangeAudio->MinimumSampleFrequency <= SampleFrequency && DataRangeAudio->MaximumSampleFrequency >= SampleFrequency) + { + /* the audio adapter supports the sample frequency */ + if (DataRangeAudio->MinimumBitsPerSample <= 8 && DataRangeAudio->MaximumBitsPerSample >= 8) + { + Result |= TestRange[Index].Bit8Mono; + + if (DataRangeAudio->MaximumChannels > 1) + { + /* check if pin supports the sample rate in 8-Bit Stereo */ + Result |= TestRange[Index].Bit8Stereo; + } + } + + if (DataRangeAudio->MinimumBitsPerSample <= 16 && DataRangeAudio->MaximumBitsPerSample >= 16) + { + /* check if pin supports the sample rate in 16-Bit Mono */ + Result |= TestRange[Index].Bit16Mono; + + + if (DataRangeAudio->MaximumChannels > 1) + { + /* check if pin supports the sample rate in 16-Bit Stereo */ + Result |= TestRange[Index].Bit16Stereo; + } + } + } + } + + + if (bInput) + WaveInfo->u.InCaps.dwFormats = Result; + else + WaveInfo->u.OutCaps.dwFormats = Result; + + DPRINT("Format %lx bInput %u\n", Result, bInput); +} + +MIXER_STATUS +MMixerInitializeWaveInfo( + IN PMIXER_CONTEXT MixerContext, + IN PMIXER_LIST MixerList, + IN LPMIXER_DATA MixerData, + IN LPWSTR DeviceName, + IN ULONG bWaveIn, + IN ULONG PinId) +{ + MIXER_STATUS Status; + PKSMULTIPLE_ITEM MultipleItem; + PKSDATARANGE_AUDIO DataRangeAudio; + LPWAVE_INFO WaveInfo; + + WaveInfo = (LPWAVE_INFO)MixerContext->Alloc(sizeof(WAVE_INFO)); + if (!WaveInfo) + return MM_STATUS_NO_MEMORY; + + /* initialize wave info */ + WaveInfo->DeviceId = MixerData->DeviceId; + WaveInfo->PinId = PinId; + + /* FIXME determine manufacturer / product id */ + if (bWaveIn) + { + WaveInfo->u.InCaps.wMid = MM_MICROSOFT; + WaveInfo->u.InCaps.wPid = MM_PID_UNMAPPED; + WaveInfo->u.InCaps.vDriverVersion = 1; + } + else + { + WaveInfo->u.OutCaps.wMid = MM_MICROSOFT; + WaveInfo->u.OutCaps.wPid = MM_PID_UNMAPPED; + WaveInfo->u.OutCaps.vDriverVersion = 1; + } + + /* get audio pin data ranges */ + Status = MMixerGetAudioPinDataRanges(MixerContext, MixerData->hDevice, PinId, &MultipleItem); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to get audio pin data ranges */ + MixerContext->Free(WaveInfo); + return MM_STATUS_UNSUCCESSFUL; + } + + /* find an KSDATARANGE_AUDIO range */ + Status = MMixerFindAudioDataRange(MultipleItem, &DataRangeAudio); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to find audio pin data range */ + MixerContext->Free(MultipleItem); + MixerContext->Free(WaveInfo); + return MM_STATUS_UNSUCCESSFUL; + } + + /* store channel count */ + if (bWaveIn) + { + WaveInfo->u.InCaps.wChannels = DataRangeAudio->MaximumChannels; + } + else + { + WaveInfo->u.OutCaps.wChannels = DataRangeAudio->MaximumChannels; + } + + /* get all supported formats */ + MMixerCheckFormat(DataRangeAudio, WaveInfo, bWaveIn); + + /* free dataranges buffer */ + MixerContext->Free(MultipleItem); + + + if (bWaveIn) + { + InsertTailList(&MixerList->WaveInList, &WaveInfo->Entry); + MixerList->WaveInListCount++; + } + else + { + InsertTailList(&MixerList->WaveOutList, &WaveInfo->Entry); + MixerList->WaveOutListCount++; + } + + return MM_STATUS_SUCCESS; +} + +MIXER_STATUS +MMixerOpenWave( + IN PMIXER_CONTEXT MixerContext, + IN ULONG DeviceIndex, + IN ULONG bWaveIn, + IN LPWAVEFORMATEX WaveFormat, + OUT PHANDLE PinHandle) +{ + PMIXER_LIST MixerList; + MIXER_STATUS Status; + LPWAVE_INFO WaveInfo; + ACCESS_MASK DesiredAccess = 0; + + // verify mixer context + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + // invalid context passed + return Status; + } + + // grab mixer list + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + + if (WaveFormat->wFormatTag != WAVE_FORMAT_PCM) + { + // not implemented + return MM_STATUS_NOT_IMPLEMENTED; + } + + /* find destination wave */ + Status = MMixerGetWaveInfoByIndexAndType(MixerList, DeviceIndex, bWaveIn, &WaveInfo); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to find wave info */ + return MM_STATUS_INVALID_PARAMETER; + } + + /* get desired access */ + if (bWaveIn) + { + DesiredAccess |= GENERIC_READ; + } + else + { + DesiredAccess |= GENERIC_WRITE; + } + + /* now try open the pin */ + return MMixerOpenWavePin(MixerContext, MixerList, WaveInfo->DeviceId, WaveInfo->PinId, WaveFormat, DesiredAccess, PinHandle); +} + +MIXER_STATUS +MMixerWaveInCapabilities( + IN PMIXER_CONTEXT MixerContext, + IN ULONG DeviceIndex, + OUT LPWAVEINCAPSW Caps) +{ + PMIXER_LIST MixerList; + MIXER_STATUS Status; + LPWAVE_INFO WaveInfo; + + // verify mixer context + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + // invalid context passed + return Status; + } + + // grab mixer list + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + + /* find destination wave */ + Status = MMixerGetWaveInfoByIndexAndType(MixerList, DeviceIndex, TRUE, &WaveInfo); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to find wave info */ + return MM_STATUS_UNSUCCESSFUL; + } + + //copy capabilities + MixerContext->Copy(Caps, &WaveInfo->u.InCaps, sizeof(WAVEINCAPSW)); + + return MM_STATUS_SUCCESS; +} + +MIXER_STATUS +MMixerWaveOutCapabilities( + IN PMIXER_CONTEXT MixerContext, + IN ULONG DeviceIndex, + OUT LPWAVEOUTCAPSW Caps) +{ + PMIXER_LIST MixerList; + MIXER_STATUS Status; + LPWAVE_INFO WaveInfo; + + // verify mixer context + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + // invalid context passed + return Status; + } + + // grab mixer list + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + + /* find destination wave */ + Status = MMixerGetWaveInfoByIndexAndType(MixerList, DeviceIndex, FALSE, &WaveInfo); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to find wave info */ + return MM_STATUS_UNSUCCESSFUL; + } + + //copy capabilities + MixerContext->Copy(Caps, &WaveInfo->u.OutCaps, sizeof(WAVEOUTCAPSW)); + + return MM_STATUS_SUCCESS; +} + +ULONG +MMixerGetWaveInCount( + 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 0; + } + + // grab mixer list + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + + return MixerList->WaveInListCount; +} + +ULONG +MMixerGetWaveOutCount( + 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 0; + } + + // grab mixer list + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + + return MixerList->WaveOutListCount; +} -- 2.17.1