mirror of
https://github.com/reactos/reactos.git
synced 2024-07-13 08:05:12 +00:00
[MMEBUDDY]
- Merge from audio branch - Handle mixers identified by id, not by handle - Fix opening of mixer devices - Waveformat struct is only provided when type is wave device - Implement wave reset routine, fixes audio recording on ReactOS SndRec, AudaCity etc. Also fixes random hang in WinAmp when skipping audio bytes - Implement wave pausing / restarting, should lead to smoother playback [MMIXER] - Merge from audio branch - Tons of fixes to enumeration of mixerlines, controls / etc - Fix mixer event notification callbacks - For more info, read audio-bringup log svn path=/trunk/; revision=50528
This commit is contained in:
commit
269e92c794
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
MMRESULT
|
MMRESULT
|
||||||
MmeGetLineInfo(
|
MmeGetLineInfo(
|
||||||
|
IN UINT DeviceId,
|
||||||
IN UINT Message,
|
IN UINT Message,
|
||||||
IN DWORD_PTR PrivateHandle,
|
IN DWORD_PTR PrivateHandle,
|
||||||
IN DWORD_PTR Parameter1,
|
IN DWORD_PTR Parameter1,
|
||||||
|
@ -32,6 +33,21 @@ MmeGetLineInfo(
|
||||||
|
|
||||||
//SND_TRACE(L"Getting mixer info %u\n", Message);
|
//SND_TRACE(L"Getting mixer info %u\n", Message);
|
||||||
|
|
||||||
|
if ( PrivateHandle == 0 )
|
||||||
|
{
|
||||||
|
Result = GetSoundDevice(MIXER_DEVICE_TYPE, DeviceId, &SoundDevice);
|
||||||
|
|
||||||
|
if ( ! MMSUCCESS(Result) )
|
||||||
|
return TranslateInternalMmResult(Result);
|
||||||
|
|
||||||
|
Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
|
||||||
|
if ( ! MMSUCCESS(Result) )
|
||||||
|
return TranslateInternalMmResult(Result);
|
||||||
|
|
||||||
|
Result = FunctionTable->QueryMixerInfo(NULL, DeviceId, Message, (LPVOID)Parameter1, Parameter2);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
VALIDATE_MMSYS_PARAMETER( PrivateHandle );
|
VALIDATE_MMSYS_PARAMETER( PrivateHandle );
|
||||||
SoundDeviceInstance = (PSOUND_DEVICE_INSTANCE) PrivateHandle;
|
SoundDeviceInstance = (PSOUND_DEVICE_INSTANCE) PrivateHandle;
|
||||||
|
|
||||||
|
@ -46,7 +62,7 @@ MmeGetLineInfo(
|
||||||
if ( ! FunctionTable->QueryMixerInfo )
|
if ( ! FunctionTable->QueryMixerInfo )
|
||||||
return MMSYSERR_NOTSUPPORTED;
|
return MMSYSERR_NOTSUPPORTED;
|
||||||
|
|
||||||
Result = FunctionTable->QueryMixerInfo(SoundDeviceInstance, Message, (LPVOID)Parameter1, Parameter2);
|
Result = FunctionTable->QueryMixerInfo(SoundDeviceInstance, DeviceId, Message, (LPVOID)Parameter1, Parameter2);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +116,7 @@ mxdMessage(
|
||||||
(LPWAVEOPENDESC) Parameter1, /* unused */
|
(LPWAVEOPENDESC) Parameter1, /* unused */
|
||||||
Parameter2,
|
Parameter2,
|
||||||
(DWORD*) PrivateHandle);
|
(DWORD*) PrivateHandle);
|
||||||
|
VALIDATE_MMSYS_PARAMETER(*(DWORD_PTR*)PrivateHandle);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +129,8 @@ mxdMessage(
|
||||||
|
|
||||||
case MXDM_GETCONTROLDETAILS :
|
case MXDM_GETCONTROLDETAILS :
|
||||||
{
|
{
|
||||||
Result = MmeGetLineInfo(Message,
|
Result = MmeGetLineInfo(DeviceId,
|
||||||
|
Message,
|
||||||
PrivateHandle,
|
PrivateHandle,
|
||||||
Parameter1,
|
Parameter1,
|
||||||
Parameter2);
|
Parameter2);
|
||||||
|
@ -123,7 +140,8 @@ mxdMessage(
|
||||||
|
|
||||||
case MXDM_SETCONTROLDETAILS :
|
case MXDM_SETCONTROLDETAILS :
|
||||||
{
|
{
|
||||||
Result = MmeGetLineInfo(Message,
|
Result = MmeGetLineInfo(DeviceId,
|
||||||
|
Message,
|
||||||
PrivateHandle,
|
PrivateHandle,
|
||||||
Parameter1,
|
Parameter1,
|
||||||
Parameter2);
|
Parameter2);
|
||||||
|
@ -133,7 +151,8 @@ mxdMessage(
|
||||||
|
|
||||||
case MXDM_GETLINECONTROLS :
|
case MXDM_GETLINECONTROLS :
|
||||||
{
|
{
|
||||||
Result = MmeGetLineInfo(Message,
|
Result = MmeGetLineInfo(DeviceId,
|
||||||
|
Message,
|
||||||
PrivateHandle,
|
PrivateHandle,
|
||||||
Parameter1,
|
Parameter1,
|
||||||
Parameter2);
|
Parameter2);
|
||||||
|
@ -143,7 +162,8 @@ mxdMessage(
|
||||||
|
|
||||||
case MXDM_GETLINEINFO :
|
case MXDM_GETLINEINFO :
|
||||||
{
|
{
|
||||||
Result = MmeGetLineInfo(Message,
|
Result = MmeGetLineInfo(DeviceId,
|
||||||
|
Message,
|
||||||
PrivateHandle,
|
PrivateHandle,
|
||||||
Parameter1,
|
Parameter1,
|
||||||
Parameter2);
|
Parameter2);
|
||||||
|
|
|
@ -130,11 +130,11 @@ MmeOpenDevice(
|
||||||
UINT Message;
|
UINT Message;
|
||||||
PSOUND_DEVICE SoundDevice;
|
PSOUND_DEVICE SoundDevice;
|
||||||
PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
|
PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
|
||||||
LPWAVEFORMATEX Format;
|
LPWAVEFORMATEX Format = NULL;
|
||||||
|
|
||||||
SND_TRACE(L"Opening device");
|
SND_TRACE(L"Opening device");
|
||||||
|
|
||||||
VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType) ); /* FIXME? wave in too? */
|
VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType) || IS_MIXER_DEVICE_TYPE(DeviceType) || IS_MIDI_DEVICE_TYPE(DeviceType) ); /* FIXME? wave in too? */
|
||||||
VALIDATE_MMSYS_PARAMETER( OpenParameters );
|
VALIDATE_MMSYS_PARAMETER( OpenParameters );
|
||||||
|
|
||||||
Result = GetSoundDevice(DeviceType, DeviceId, &SoundDevice);
|
Result = GetSoundDevice(DeviceType, DeviceId, &SoundDevice);
|
||||||
|
|
|
@ -65,8 +65,6 @@ SetWaveDeviceFormat(
|
||||||
SND_TRACE(L"Setting wave format\n");
|
SND_TRACE(L"Setting wave format\n");
|
||||||
|
|
||||||
VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
|
VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
|
||||||
VALIDATE_MMSYS_PARAMETER( Format );
|
|
||||||
VALIDATE_MMSYS_PARAMETER( FormatSize >= sizeof(WAVEFORMATEX) );
|
|
||||||
|
|
||||||
Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
|
Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
|
||||||
if ( ! MMSUCCESS(Result) )
|
if ( ! MMSUCCESS(Result) )
|
||||||
|
@ -74,9 +72,14 @@ SetWaveDeviceFormat(
|
||||||
|
|
||||||
Result = GetSoundDeviceType(SoundDevice, &DeviceType);
|
Result = GetSoundDeviceType(SoundDevice, &DeviceType);
|
||||||
SND_ASSERT( Result == MMSYSERR_NOERROR );
|
SND_ASSERT( Result == MMSYSERR_NOERROR );
|
||||||
|
if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE)
|
||||||
|
{
|
||||||
|
VALIDATE_MMSYS_PARAMETER( Format );
|
||||||
|
VALIDATE_MMSYS_PARAMETER( FormatSize >= sizeof(WAVEFORMATEX) );
|
||||||
|
}
|
||||||
|
|
||||||
/* Ensure we have a wave device (TODO: check if this applies to wavein as well) */
|
/* Ensure we have a wave device (TODO: check if this applies to wavein as well) */
|
||||||
VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType) );
|
VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType) || IS_MIDI_DEVICE_TYPE(DeviceType) || IS_MIXER_DEVICE_TYPE(DeviceType));
|
||||||
|
|
||||||
/* Obtain the function table */
|
/* Obtain the function table */
|
||||||
Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
|
Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
|
||||||
|
|
|
@ -232,6 +232,8 @@ CompleteIO(
|
||||||
|
|
||||||
}while(dwNumberOfBytesTransferred);
|
}while(dwNumberOfBytesTransferred);
|
||||||
|
|
||||||
|
// AUDIO-BRANCH DIFF
|
||||||
|
// completion callback is performed in a thread
|
||||||
DoWaveStreaming(SoundDeviceInstance);
|
DoWaveStreaming(SoundDeviceInstance);
|
||||||
|
|
||||||
//CompleteWavePortion(SoundDeviceInstance, dwNumberOfBytesTransferred);
|
//CompleteWavePortion(SoundDeviceInstance, dwNumberOfBytesTransferred);
|
||||||
|
@ -277,8 +279,62 @@ StopStreamingInSoundThread(
|
||||||
IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
|
IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
|
||||||
IN PVOID Parameter)
|
IN PVOID Parameter)
|
||||||
{
|
{
|
||||||
/* TODO */
|
MMDEVICE_TYPE DeviceType;
|
||||||
return MMSYSERR_NOTSUPPORTED;
|
PMMFUNCTION_TABLE FunctionTable;
|
||||||
|
MMRESULT Result;
|
||||||
|
PSOUND_DEVICE SoundDevice;
|
||||||
|
|
||||||
|
/* set state reset in progress */
|
||||||
|
SoundDeviceInstance->ResetInProgress = TRUE;
|
||||||
|
|
||||||
|
/* Get sound device */
|
||||||
|
Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
|
||||||
|
SND_ASSERT( Result == MMSYSERR_NOERROR );
|
||||||
|
|
||||||
|
/* Obtain the function table */
|
||||||
|
Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
|
||||||
|
SND_ASSERT( Result == MMSYSERR_NOERROR );
|
||||||
|
|
||||||
|
/* Obtain device instance type */
|
||||||
|
Result = GetSoundDeviceType(SoundDevice, &DeviceType);
|
||||||
|
SND_ASSERT( Result == MMSYSERR_NOERROR );
|
||||||
|
|
||||||
|
/* Check if reset function is supported */
|
||||||
|
if (FunctionTable->ResetStream)
|
||||||
|
{
|
||||||
|
/* cancel all current audio buffers */
|
||||||
|
FunctionTable->ResetStream(SoundDeviceInstance, DeviceType, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* complete all current headers */
|
||||||
|
while( SoundDeviceInstance->HeadWaveHeader )
|
||||||
|
{
|
||||||
|
SND_TRACE(L"StopStreamingInSoundThread: Completing Header %p\n", SoundDeviceInstance->HeadWaveHeader);
|
||||||
|
CompleteWaveHeader( SoundDeviceInstance, SoundDeviceInstance->HeadWaveHeader );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* there should be no oustanding buffers now */
|
||||||
|
SND_ASSERT(SoundDeviceInstance->OutstandingBuffers == 0);
|
||||||
|
|
||||||
|
while(SoundDeviceInstance->OutstandingBuffers)
|
||||||
|
{
|
||||||
|
SND_ERR("StopStreamingInSoundThread OutStandingBufferCount %lu\n", SoundDeviceInstance->OutstandingBuffers);
|
||||||
|
/* my hack of doom */
|
||||||
|
Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if reset function is supported */
|
||||||
|
if (FunctionTable->ResetStream)
|
||||||
|
{
|
||||||
|
/* finish the reset */
|
||||||
|
FunctionTable->ResetStream(SoundDeviceInstance, DeviceType, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear state reset in progress */
|
||||||
|
SoundDeviceInstance->ResetInProgress = FALSE;
|
||||||
|
|
||||||
|
|
||||||
|
return MMSYSERR_NOERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
MMRESULT
|
MMRESULT
|
||||||
|
|
|
@ -109,6 +109,13 @@ wodMessage(
|
||||||
case WODM_RESTART :
|
case WODM_RESTART :
|
||||||
{
|
{
|
||||||
/* Continue playback when paused */
|
/* Continue playback when paused */
|
||||||
|
Result = MmeSetState(PrivateHandle, TRUE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WODM_PAUSE :
|
||||||
|
{
|
||||||
|
/* pause playback */
|
||||||
|
Result = MmeSetState(PrivateHandle, FALSE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
reactos/lib/drivers/sound/mmixer/TODO
Normal file
6
reactos/lib/drivers/sound/mmixer/TODO
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
=== MMIXER TASKS ===
|
||||||
|
|
||||||
|
- Add hacks for source lines, such that Wave Mixer line always has a volume control
|
||||||
|
- Support custom mixer controls
|
||||||
|
- Assign mixer controls after all controls have been assigned (starting on the destination lines)
|
||||||
|
- TESTING & BUGFIXING
|
File diff suppressed because it is too large
Load diff
|
@ -11,7 +11,7 @@
|
||||||
MIXER_STATUS
|
MIXER_STATUS
|
||||||
MMixerGetPinDataFlowAndCommunication(
|
MMixerGetPinDataFlowAndCommunication(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
IN LPMIXER_DATA MixerData,
|
IN HANDLE hDevice,
|
||||||
IN ULONG PinId,
|
IN ULONG PinId,
|
||||||
OUT PKSPIN_DATAFLOW DataFlow,
|
OUT PKSPIN_DATAFLOW DataFlow,
|
||||||
OUT PKSPIN_COMMUNICATION Communication)
|
OUT PKSPIN_COMMUNICATION Communication)
|
||||||
|
@ -28,7 +28,7 @@ MMixerGetPinDataFlowAndCommunication(
|
||||||
Pin.Property.Set = KSPROPSETID_Pin;
|
Pin.Property.Set = KSPROPSETID_Pin;
|
||||||
|
|
||||||
/* get pin dataflow */
|
/* get pin dataflow */
|
||||||
Status = MixerContext->Control(MixerData->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
|
Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
|
||||||
if (Status != MM_STATUS_SUCCESS)
|
if (Status != MM_STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
/* failed to retrieve dataflow */
|
/* failed to retrieve dataflow */
|
||||||
|
@ -39,7 +39,7 @@ MMixerGetPinDataFlowAndCommunication(
|
||||||
Pin.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
|
Pin.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
|
||||||
|
|
||||||
/* get pin communication */
|
/* get pin communication */
|
||||||
Status = MixerContext->Control(MixerData->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
|
Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ MMixerCheckFilterPinMidiSupport(
|
||||||
IsEqualGUIDAligned(&DataRange->Specifier, &KSDATAFORMAT_SPECIFIER_NONE))
|
IsEqualGUIDAligned(&DataRange->Specifier, &KSDATAFORMAT_SPECIFIER_NONE))
|
||||||
{
|
{
|
||||||
/* pin supports midi datarange */
|
/* pin supports midi datarange */
|
||||||
if (MMixerGetPinDataFlowAndCommunication(MixerContext, MixerData, PinId, &DataFlow, &Communication) == MM_STATUS_SUCCESS)
|
if (MMixerGetPinDataFlowAndCommunication(MixerContext, MixerData->hDevice, PinId, &DataFlow, &Communication) == MM_STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
if (DataFlow == KSPIN_DATAFLOW_IN && Communication == KSPIN_COMMUNICATION_SINK)
|
if (DataFlow == KSPIN_DATAFLOW_IN && Communication == KSPIN_COMMUNICATION_SINK)
|
||||||
{
|
{
|
||||||
|
|
|
@ -89,6 +89,7 @@ MMixerOpen(
|
||||||
if (Status != MM_STATUS_SUCCESS)
|
if (Status != MM_STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
/* invalid context passed */
|
/* invalid context passed */
|
||||||
|
DPRINT1("invalid context\n");
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +98,7 @@ MMixerOpen(
|
||||||
if (!MixerInfo)
|
if (!MixerInfo)
|
||||||
{
|
{
|
||||||
/* invalid mixer id */
|
/* invalid mixer id */
|
||||||
|
DPRINT1("invalid mixer id %lu\n", MixerId);
|
||||||
return MM_STATUS_INVALID_PARAMETER;
|
return MM_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +108,6 @@ MMixerOpen(
|
||||||
|
|
||||||
/* store result */
|
/* store result */
|
||||||
*MixerHandle = (HANDLE)MixerInfo;
|
*MixerHandle = (HANDLE)MixerInfo;
|
||||||
|
|
||||||
return MM_STATUS_SUCCESS;
|
return MM_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,12 +115,14 @@ MIXER_STATUS
|
||||||
MMixerGetLineInfo(
|
MMixerGetLineInfo(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
IN HANDLE MixerHandle,
|
IN HANDLE MixerHandle,
|
||||||
|
IN ULONG MixerId,
|
||||||
IN ULONG Flags,
|
IN ULONG Flags,
|
||||||
OUT LPMIXERLINEW MixerLine)
|
OUT LPMIXERLINEW MixerLine)
|
||||||
{
|
{
|
||||||
MIXER_STATUS Status;
|
MIXER_STATUS Status;
|
||||||
LPMIXER_INFO MixerInfo;
|
LPMIXER_INFO MixerInfo;
|
||||||
LPMIXERLINE_EXT MixerLineSrc;
|
LPMIXERLINE_EXT MixerLineSrc;
|
||||||
|
ULONG DestinationLineID;
|
||||||
|
|
||||||
/* verify mixer context */
|
/* verify mixer context */
|
||||||
Status = MMixerVerifyContext(MixerContext);
|
Status = MMixerVerifyContext(MixerContext);
|
||||||
|
@ -129,25 +132,54 @@ MMixerGetLineInfo(
|
||||||
/* invalid context passed */
|
/* invalid context passed */
|
||||||
return Status;
|
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 */
|
/* clear hmixer from flags */
|
||||||
Flags &=~MIXER_OBJECTF_HMIXER;
|
Flags &=~MIXER_OBJECTF_HMIXER;
|
||||||
|
|
||||||
|
DPRINT("MMixerGetLineInfo MixerId %lu Flags %lu\n", MixerId, Flags);
|
||||||
|
|
||||||
if (Flags == MIXER_GETLINEINFOF_DESTINATION)
|
if (Flags == MIXER_GETLINEINFOF_DESTINATION)
|
||||||
{
|
{
|
||||||
/* cast to mixer info */
|
/* cast to mixer info */
|
||||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||||
|
|
||||||
if (MixerLine->dwDestination != 0)
|
/* calculate destination line id */
|
||||||
{
|
DestinationLineID = (MixerLine->dwDestination + DESTINATION_LINE);
|
||||||
/* destination line member must be zero */
|
|
||||||
return MM_STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
|
/* get destination line */
|
||||||
ASSERT(MixerLineSrc);
|
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));
|
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;
|
return MM_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
else if (Flags == MIXER_GETLINEINFOF_SOURCE)
|
else if (Flags == MIXER_GETLINEINFOF_SOURCE)
|
||||||
|
@ -155,41 +187,75 @@ MMixerGetLineInfo(
|
||||||
/* cast to mixer info */
|
/* cast to mixer info */
|
||||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||||
|
|
||||||
|
/* calculate destination line id */
|
||||||
|
DestinationLineID = (MixerLine->dwDestination + DESTINATION_LINE);
|
||||||
|
|
||||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
|
/* get destination line */
|
||||||
ASSERT(MixerLineSrc);
|
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)
|
if (MixerLine->dwSource >= MixerLineSrc->Line.cConnections)
|
||||||
{
|
{
|
||||||
DPRINT("dwSource %u > Destinations %u\n", 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);
|
||||||
|
|
||||||
/* invalid parameter */
|
|
||||||
return MM_STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwSource * 0x10000);
|
|
||||||
if (MixerLineSrc)
|
|
||||||
{
|
|
||||||
DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
|
|
||||||
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
|
|
||||||
return MM_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
return MM_STATUS_UNSUCCESSFUL;
|
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)
|
else if (Flags == MIXER_GETLINEINFOF_LINEID)
|
||||||
{
|
{
|
||||||
/* cast to mixer info */
|
/* cast to mixer info */
|
||||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||||
|
|
||||||
|
/* try to find line */
|
||||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwLineID);
|
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwLineID);
|
||||||
if (!MixerLineSrc)
|
if (!MixerLineSrc)
|
||||||
{
|
{
|
||||||
/* invalid parameter */
|
/* invalid parameter */
|
||||||
|
DPRINT1("MMixerGetLineInfo: MixerName %S Line not found 0x%lx\n", MixerInfo->MixCaps.szPname, MixerLine->dwLineID);
|
||||||
return MM_STATUS_INVALID_PARAMETER;
|
return MM_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy cached data */
|
DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
|
||||||
|
|
||||||
|
/* copy mixer line*/
|
||||||
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
|
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;
|
return MM_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
else if (Flags == MIXER_GETLINEINFOF_COMPONENTTYPE)
|
else if (Flags == MIXER_GETLINEINFOF_COMPONENTTYPE)
|
||||||
|
@ -197,6 +263,7 @@ MMixerGetLineInfo(
|
||||||
/* cast to mixer info */
|
/* cast to mixer info */
|
||||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||||
|
|
||||||
|
/* find mixer line by component type */
|
||||||
MixerLineSrc = MMixerGetSourceMixerLineByComponentType(MixerInfo, MixerLine->dwComponentType);
|
MixerLineSrc = MMixerGetSourceMixerLineByComponentType(MixerInfo, MixerLine->dwComponentType);
|
||||||
if (!MixerLineSrc)
|
if (!MixerLineSrc)
|
||||||
{
|
{
|
||||||
|
@ -204,12 +271,25 @@ MMixerGetLineInfo(
|
||||||
return MM_STATUS_UNSUCCESSFUL;
|
return MM_STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(MixerLineSrc);
|
/* copy mixer line */
|
||||||
|
|
||||||
/* copy cached data */
|
|
||||||
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
|
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;
|
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;
|
return MM_STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
@ -218,13 +298,15 @@ MIXER_STATUS
|
||||||
MMixerGetLineControls(
|
MMixerGetLineControls(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
IN HANDLE MixerHandle,
|
IN HANDLE MixerHandle,
|
||||||
|
IN ULONG MixerId,
|
||||||
IN ULONG Flags,
|
IN ULONG Flags,
|
||||||
OUT LPMIXERLINECONTROLSW MixerLineControls)
|
OUT LPMIXERLINECONTROLSW MixerLineControls)
|
||||||
{
|
{
|
||||||
LPMIXER_INFO MixerInfo;
|
LPMIXER_INFO MixerInfo;
|
||||||
LPMIXERLINE_EXT MixerLineSrc;
|
LPMIXERLINE_EXT MixerLineSrc;
|
||||||
LPMIXERCONTROLW MixerControl;
|
LPMIXERCONTROL_EXT MixerControl;
|
||||||
MIXER_STATUS Status;
|
MIXER_STATUS Status;
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
ULONG Index;
|
ULONG Index;
|
||||||
|
|
||||||
/* verify mixer context */
|
/* verify mixer context */
|
||||||
|
@ -236,23 +318,75 @@ MMixerGetLineControls(
|
||||||
return Status;
|
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->cbStruct, sizeof(MIXERLINECONTROLSW));
|
||||||
|
/* 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;
|
Flags &= ~MIXER_OBJECTF_HMIXER;
|
||||||
|
|
||||||
|
DPRINT("MMixerGetLineControls MixerId %lu Flags %lu\n", MixerId, Flags);
|
||||||
|
|
||||||
if (Flags == MIXER_GETLINECONTROLSF_ALL)
|
if (Flags == MIXER_GETLINECONTROLSF_ALL)
|
||||||
{
|
{
|
||||||
/* cast to mixer info */
|
/* cast to mixer info */
|
||||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||||
|
|
||||||
|
/* get mixer line */
|
||||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
|
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
|
||||||
|
|
||||||
if (!MixerLineSrc)
|
if (!MixerLineSrc)
|
||||||
{
|
{
|
||||||
/* invalid line id */
|
/* invalid line id */
|
||||||
|
DPRINT("MMixerGetLineControls Line not found %lx\n", MixerLineControls->dwLineID);
|
||||||
return MM_STATUS_INVALID_PARAMETER;
|
return MM_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
/* copy line control(s) */
|
|
||||||
MixerContext->Copy(MixerLineControls->pamxctrl, MixerLineSrc->LineControls, min(MixerLineSrc->Line.cControls, MixerLineControls->cControls) * sizeof(MIXERCONTROLW));
|
|
||||||
|
|
||||||
|
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;
|
return MM_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
else if (Flags == MIXER_GETLINECONTROLSF_ONEBYTYPE)
|
else if (Flags == MIXER_GETLINECONTROLSF_ONEBYTYPE)
|
||||||
|
@ -260,27 +394,36 @@ MMixerGetLineControls(
|
||||||
/* cast to mixer info */
|
/* cast to mixer info */
|
||||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||||
|
|
||||||
|
/* get mixer line */
|
||||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
|
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
|
||||||
|
|
||||||
if (!MixerLineSrc)
|
if (!MixerLineSrc)
|
||||||
{
|
{
|
||||||
/* invalid line id */
|
/* invalid line id */
|
||||||
|
DPRINT1("MMixerGetLineControls Line not found %lx\n", MixerLineControls->dwLineID);
|
||||||
return MM_STATUS_INVALID_PARAMETER;
|
return MM_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(MixerLineSrc);
|
/* sanity checks */
|
||||||
|
ASSERT(MixerLineControls->cControls == 1);
|
||||||
|
ASSERT(MixerLineControls->cbmxctrl == sizeof(MIXERCONTROLW));
|
||||||
|
ASSERT(MixerLineControls->pamxctrl != NULL);
|
||||||
|
|
||||||
Index = 0;
|
Entry = MixerLineSrc->ControlsList.Flink;
|
||||||
for(Index = 0; Index < MixerLineSrc->Line.cControls; Index++)
|
while(Entry != &MixerLineSrc->ControlsList)
|
||||||
{
|
{
|
||||||
DPRINT("dwControlType %x\n", MixerLineSrc->LineControls[Index].dwControlType);
|
MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
|
||||||
if (MixerLineControls->dwControlType == MixerLineSrc->LineControls[Index].dwControlType)
|
if (MixerLineControls->dwControlType == MixerControl->Control.dwControlType)
|
||||||
{
|
{
|
||||||
/* found a control with that type */
|
/* found a control with that type */
|
||||||
MixerContext->Copy(MixerLineControls->pamxctrl, &MixerLineSrc->LineControls[Index], sizeof(MIXERCONTROLW));
|
MixerContext->Copy(MixerLineControls->pamxctrl, &MixerControl->Control, sizeof(MIXERCONTROLW));
|
||||||
return MM_STATUS_SUCCESS;
|
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);
|
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;
|
return MM_STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
@ -294,15 +437,24 @@ MMixerGetLineControls(
|
||||||
if (Status != MM_STATUS_SUCCESS)
|
if (Status != MM_STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
/* invalid parameter */
|
/* invalid parameter */
|
||||||
|
DPRINT("MMixerGetLineControls ControlID not found %lx\n", MixerLineControls->dwLineID);
|
||||||
return MM_STATUS_INVALID_PARAMETER;
|
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 */
|
/* copy the controls */
|
||||||
MixerContext->Copy(MixerLineControls->pamxctrl, MixerControl, sizeof(MIXERCONTROLW));
|
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;
|
return MM_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
UNIMPLEMENTED
|
||||||
|
|
||||||
return MM_STATUS_NOT_IMPLEMENTED;
|
return MM_STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,6 +462,7 @@ MIXER_STATUS
|
||||||
MMixerSetControlDetails(
|
MMixerSetControlDetails(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
IN HANDLE MixerHandle,
|
IN HANDLE MixerHandle,
|
||||||
|
IN ULONG MixerId,
|
||||||
IN ULONG Flags,
|
IN ULONG Flags,
|
||||||
OUT LPMIXERCONTROLDETAILS MixerControlDetails)
|
OUT LPMIXERCONTROLDETAILS MixerControlDetails)
|
||||||
{
|
{
|
||||||
|
@ -317,7 +470,7 @@ MMixerSetControlDetails(
|
||||||
ULONG NodeId;
|
ULONG NodeId;
|
||||||
LPMIXER_INFO MixerInfo;
|
LPMIXER_INFO MixerInfo;
|
||||||
LPMIXERLINE_EXT MixerLine;
|
LPMIXERLINE_EXT MixerLine;
|
||||||
LPMIXERCONTROLW MixerControl;
|
LPMIXERCONTROL_EXT MixerControl;
|
||||||
|
|
||||||
/* verify mixer context */
|
/* verify mixer context */
|
||||||
Status = MMixerVerifyContext(MixerContext);
|
Status = MMixerVerifyContext(MixerContext);
|
||||||
|
@ -325,9 +478,23 @@ MMixerSetControlDetails(
|
||||||
if (Status != MM_STATUS_SUCCESS)
|
if (Status != MM_STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
/* invalid context passed */
|
/* invalid context passed */
|
||||||
|
DPRINT1("invalid context\n");
|
||||||
return Status;
|
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 */
|
/* get mixer info */
|
||||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||||
|
|
||||||
|
@ -338,16 +505,21 @@ MMixerSetControlDetails(
|
||||||
if (Status != MM_STATUS_SUCCESS)
|
if (Status != MM_STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
/* failed to find control id */
|
/* failed to find control id */
|
||||||
|
DPRINT1("invalid control id %lu\n", MixerControlDetails->dwControlID);
|
||||||
return MM_STATUS_INVALID_PARAMETER;
|
return MM_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(MixerControl->dwControlType)
|
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:
|
case MIXERCONTROL_CONTROLTYPE_MUTE:
|
||||||
Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo->hMixer, NodeId, MixerLine->Line.dwLineID, MixerControlDetails, TRUE);
|
Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, MixerControl, MixerLine->Line.dwLineID, MixerControlDetails, TRUE);
|
||||||
break;
|
break;
|
||||||
case MIXERCONTROL_CONTROLTYPE_VOLUME:
|
case MIXERCONTROL_CONTROLTYPE_VOLUME:
|
||||||
Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo->hMixer, NodeId, TRUE, MixerControl, MixerControlDetails, MixerLine);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
Status = MM_STATUS_NOT_IMPLEMENTED;
|
Status = MM_STATUS_NOT_IMPLEMENTED;
|
||||||
|
@ -360,6 +532,7 @@ MIXER_STATUS
|
||||||
MMixerGetControlDetails(
|
MMixerGetControlDetails(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
IN HANDLE MixerHandle,
|
IN HANDLE MixerHandle,
|
||||||
|
IN ULONG MixerId,
|
||||||
IN ULONG Flags,
|
IN ULONG Flags,
|
||||||
OUT LPMIXERCONTROLDETAILS MixerControlDetails)
|
OUT LPMIXERCONTROLDETAILS MixerControlDetails)
|
||||||
{
|
{
|
||||||
|
@ -367,7 +540,7 @@ MMixerGetControlDetails(
|
||||||
ULONG NodeId;
|
ULONG NodeId;
|
||||||
LPMIXER_INFO MixerInfo;
|
LPMIXER_INFO MixerInfo;
|
||||||
LPMIXERLINE_EXT MixerLine;
|
LPMIXERLINE_EXT MixerLine;
|
||||||
LPMIXERCONTROLW MixerControl;
|
LPMIXERCONTROL_EXT MixerControl;
|
||||||
|
|
||||||
/* verify mixer context */
|
/* verify mixer context */
|
||||||
Status = MMixerVerifyContext(MixerContext);
|
Status = MMixerVerifyContext(MixerContext);
|
||||||
|
@ -378,6 +551,18 @@ MMixerGetControlDetails(
|
||||||
return Status;
|
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 */
|
/* get mixer info */
|
||||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||||
|
|
||||||
|
@ -391,21 +576,162 @@ MMixerGetControlDetails(
|
||||||
return MM_STATUS_INVALID_PARAMETER;
|
return MM_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(MixerControl->dwControlType)
|
switch(MixerControl->Control.dwControlType)
|
||||||
{
|
{
|
||||||
case MIXERCONTROL_CONTROLTYPE_MUTE:
|
case MIXERCONTROL_CONTROLTYPE_MUTE:
|
||||||
Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, NodeId, MixerLine->Line.dwLineID, MixerControlDetails, FALSE);
|
Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, MixerControl, MixerLine->Line.dwLineID, MixerControlDetails, FALSE);
|
||||||
break;
|
break;
|
||||||
case MIXERCONTROL_CONTROLTYPE_VOLUME:
|
case MIXERCONTROL_CONTROLTYPE_VOLUME:
|
||||||
Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, FALSE, MixerControl, MixerControlDetails, MixerLine);
|
Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, FALSE, MixerControl, MixerControlDetails, MixerLine);
|
||||||
break;
|
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:
|
default:
|
||||||
Status = MM_STATUS_NOT_IMPLEMENTED;
|
Status = MM_STATUS_NOT_IMPLEMENTED;
|
||||||
|
DPRINT1("ControlType %lx not implemented\n", MixerControl->Control.dwControlType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
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
|
MIXER_STATUS
|
||||||
MMixerInitialize(
|
MMixerInitialize(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
|
@ -507,6 +833,18 @@ MMixerInitialize(
|
||||||
Entry = Entry->Flink;
|
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 */
|
/* done */
|
||||||
return MM_STATUS_SUCCESS;
|
return MM_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ typedef MIXER_STATUS(*PMIXER_CLOSE)(
|
||||||
typedef MIXER_STATUS(*PMIXER_CLOSEKEY)(
|
typedef MIXER_STATUS(*PMIXER_CLOSEKEY)(
|
||||||
IN HANDLE hKey);
|
IN HANDLE hKey);
|
||||||
|
|
||||||
typedef VOID (*PMIXER_EVENT)(
|
typedef VOID (CALLBACK *PMIXER_EVENT)(
|
||||||
IN PVOID MixerEventContext,
|
IN PVOID MixerEventContext,
|
||||||
IN HANDLE hMixer,
|
IN HANDLE hMixer,
|
||||||
IN ULONG NotificationType,
|
IN ULONG NotificationType,
|
||||||
|
@ -150,6 +150,7 @@ MIXER_STATUS
|
||||||
MMixerGetLineInfo(
|
MMixerGetLineInfo(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
IN HANDLE MixerHandle,
|
IN HANDLE MixerHandle,
|
||||||
|
IN ULONG MixerId,
|
||||||
IN ULONG Flags,
|
IN ULONG Flags,
|
||||||
OUT LPMIXERLINEW MixerLine);
|
OUT LPMIXERLINEW MixerLine);
|
||||||
|
|
||||||
|
@ -157,6 +158,7 @@ MIXER_STATUS
|
||||||
MMixerGetLineControls(
|
MMixerGetLineControls(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
IN HANDLE MixerHandle,
|
IN HANDLE MixerHandle,
|
||||||
|
IN ULONG MixerId,
|
||||||
IN ULONG Flags,
|
IN ULONG Flags,
|
||||||
OUT LPMIXERLINECONTROLSW MixerLineControls);
|
OUT LPMIXERLINECONTROLSW MixerLineControls);
|
||||||
|
|
||||||
|
@ -164,6 +166,7 @@ MIXER_STATUS
|
||||||
MMixerSetControlDetails(
|
MMixerSetControlDetails(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
IN HANDLE MixerHandle,
|
IN HANDLE MixerHandle,
|
||||||
|
IN ULONG MixerId,
|
||||||
IN ULONG Flags,
|
IN ULONG Flags,
|
||||||
OUT LPMIXERCONTROLDETAILS MixerControlDetails);
|
OUT LPMIXERCONTROLDETAILS MixerControlDetails);
|
||||||
|
|
||||||
|
@ -171,6 +174,7 @@ MIXER_STATUS
|
||||||
MMixerGetControlDetails(
|
MMixerGetControlDetails(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
IN HANDLE MixerHandle,
|
IN HANDLE MixerHandle,
|
||||||
|
IN ULONG MixerId,
|
||||||
IN ULONG Flags,
|
IN ULONG Flags,
|
||||||
OUT LPMIXERCONTROLDETAILS MixerControlDetails);
|
OUT LPMIXERCONTROLDETAILS MixerControlDetails);
|
||||||
|
|
||||||
|
@ -202,6 +206,12 @@ MMixerSetWaveStatus(
|
||||||
IN HANDLE PinHandle,
|
IN HANDLE PinHandle,
|
||||||
IN KSSTATE State);
|
IN KSSTATE State);
|
||||||
|
|
||||||
|
MIXER_STATUS
|
||||||
|
MMixerSetWaveResetState(
|
||||||
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
|
IN HANDLE PinHandle,
|
||||||
|
IN ULONG bBegin);
|
||||||
|
|
||||||
MIXER_STATUS
|
MIXER_STATUS
|
||||||
MMixerGetWaveDevicePath(
|
MMixerGetWaveDevicePath(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
|
|
|
@ -27,6 +27,7 @@ typedef struct __TOPOLOGY_NODE__
|
||||||
|
|
||||||
ULONG NodeConnectedFromCount;
|
ULONG NodeConnectedFromCount;
|
||||||
struct __TOPOLOGY_NODE__ ** NodeConnectedFrom;
|
struct __TOPOLOGY_NODE__ ** NodeConnectedFrom;
|
||||||
|
PULONG LogicalPinNodeConnectedFrom;
|
||||||
|
|
||||||
ULONG PinConnectedFromCount;
|
ULONG PinConnectedFromCount;
|
||||||
PULONG PinConnectedFrom;
|
PULONG PinConnectedFrom;
|
||||||
|
@ -55,6 +56,7 @@ typedef struct
|
||||||
PULONG PinConnectedTo;
|
PULONG PinConnectedTo;
|
||||||
|
|
||||||
ULONG Visited;
|
ULONG Visited;
|
||||||
|
ULONG Reserved;
|
||||||
}PIN, *PPIN;
|
}PIN, *PPIN;
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,7 +74,6 @@ typedef struct
|
||||||
{
|
{
|
||||||
LIST_ENTRY Entry;
|
LIST_ENTRY Entry;
|
||||||
MIXERCAPSW MixCaps;
|
MIXERCAPSW MixCaps;
|
||||||
HANDLE hMixer;
|
|
||||||
LIST_ENTRY LineList;
|
LIST_ENTRY LineList;
|
||||||
ULONG ControlId;
|
ULONG ControlId;
|
||||||
LIST_ENTRY EventList;
|
LIST_ENTRY EventList;
|
||||||
|
@ -81,12 +82,19 @@ typedef struct
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
LIST_ENTRY Entry;
|
LIST_ENTRY Entry;
|
||||||
ULONG PinId;
|
MIXERCONTROLW Control;
|
||||||
|
ULONG NodeID;
|
||||||
HANDLE hDevice;
|
HANDLE hDevice;
|
||||||
|
PVOID ExtraData;
|
||||||
|
}MIXERCONTROL_EXT, *LPMIXERCONTROL_EXT;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
LIST_ENTRY Entry;
|
||||||
|
ULONG PinId;
|
||||||
MIXERLINEW Line;
|
MIXERLINEW Line;
|
||||||
LPMIXERCONTROLW LineControls;
|
LIST_ENTRY ControlsList;
|
||||||
PULONG NodeIds;
|
|
||||||
LIST_ENTRY LineControlsExtraData;
|
|
||||||
}MIXERLINE_EXT, *LPMIXERLINE_EXT;
|
}MIXERLINE_EXT, *LPMIXERLINE_EXT;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -114,6 +122,7 @@ typedef struct
|
||||||
HANDLE hDeviceInterfaceKey;
|
HANDLE hDeviceInterfaceKey;
|
||||||
LPWSTR DeviceName;
|
LPWSTR DeviceName;
|
||||||
PTOPOLOGY Topology;
|
PTOPOLOGY Topology;
|
||||||
|
LPMIXER_INFO MixerInfo;
|
||||||
}MIXER_DATA, *LPMIXER_DATA;
|
}MIXER_DATA, *LPMIXER_DATA;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -170,8 +179,8 @@ typedef struct
|
||||||
|
|
||||||
}EVENT_NOTIFICATION_ENTRY, *PEVENT_NOTIFICATION_ENTRY;
|
}EVENT_NOTIFICATION_ENTRY, *PEVENT_NOTIFICATION_ENTRY;
|
||||||
|
|
||||||
#define DESTINATION_LINE 0xFFFF0000
|
#define DESTINATION_LINE (0xFFFF0000)
|
||||||
|
#define SOURCE_LINE (0x10000)
|
||||||
ULONG
|
ULONG
|
||||||
MMixerGetFilterPinCount(
|
MMixerGetFilterPinCount(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
|
@ -270,14 +279,14 @@ MMixerGetMixerControlById(
|
||||||
LPMIXER_INFO MixerInfo,
|
LPMIXER_INFO MixerInfo,
|
||||||
DWORD dwControlID,
|
DWORD dwControlID,
|
||||||
LPMIXERLINE_EXT *MixerLine,
|
LPMIXERLINE_EXT *MixerLine,
|
||||||
LPMIXERCONTROLW *MixerControl,
|
LPMIXERCONTROL_EXT *MixerControl,
|
||||||
PULONG NodeId);
|
PULONG NodeId);
|
||||||
|
|
||||||
MIXER_STATUS
|
MIXER_STATUS
|
||||||
MMixerSetGetMuteControlDetails(
|
MMixerSetGetMuteControlDetails(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
IN LPMIXER_INFO MixerInfo,
|
IN LPMIXER_INFO MixerInfo,
|
||||||
IN ULONG NodeId,
|
IN LPMIXERCONTROL_EXT MixerControl,
|
||||||
IN ULONG dwLineID,
|
IN ULONG dwLineID,
|
||||||
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
||||||
IN ULONG bSet);
|
IN ULONG bSet);
|
||||||
|
@ -288,10 +297,22 @@ MMixerSetGetVolumeControlDetails(
|
||||||
IN LPMIXER_INFO MixerInfo,
|
IN LPMIXER_INFO MixerInfo,
|
||||||
IN ULONG NodeId,
|
IN ULONG NodeId,
|
||||||
IN ULONG bSet,
|
IN ULONG bSet,
|
||||||
LPMIXERCONTROLW MixerControl,
|
LPMIXERCONTROL_EXT MixerControl,
|
||||||
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
||||||
LPMIXERLINE_EXT MixerLine);
|
LPMIXERLINE_EXT MixerLine);
|
||||||
|
|
||||||
|
MIXER_STATUS
|
||||||
|
MMixerSetGetMuxControlDetails(
|
||||||
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
|
IN LPMIXER_INFO MixerInfo,
|
||||||
|
IN ULONG NodeId,
|
||||||
|
IN ULONG bSet,
|
||||||
|
IN ULONG Flags,
|
||||||
|
LPMIXERCONTROL_EXT MixerControl,
|
||||||
|
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
||||||
|
LPMIXERLINE_EXT MixerLine);
|
||||||
|
|
||||||
|
|
||||||
MIXER_STATUS
|
MIXER_STATUS
|
||||||
MMixerSetGetControlDetails(
|
MMixerSetGetControlDetails(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
|
@ -349,6 +370,26 @@ MMixerInitializePinConnect(
|
||||||
IN OUT PKSPIN_CONNECT PinConnect,
|
IN OUT PKSPIN_CONNECT PinConnect,
|
||||||
IN ULONG PinId);
|
IN ULONG PinId);
|
||||||
|
|
||||||
|
MIXER_STATUS
|
||||||
|
MMixerGetPinDataFlowAndCommunication(
|
||||||
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
|
IN HANDLE hDevice,
|
||||||
|
IN ULONG PinId,
|
||||||
|
OUT PKSPIN_DATAFLOW DataFlow,
|
||||||
|
OUT PKSPIN_COMMUNICATION Communication);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MMixerHandleAlternativeMixers(
|
||||||
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
|
IN PMIXER_LIST MixerList,
|
||||||
|
IN LPMIXER_DATA MixerData,
|
||||||
|
IN PTOPOLOGY Topology);
|
||||||
|
|
||||||
|
MIXER_STATUS
|
||||||
|
MMixerGetMixerByName(
|
||||||
|
IN PMIXER_LIST MixerList,
|
||||||
|
IN LPWSTR MixerName,
|
||||||
|
OUT LPMIXER_INFO *MixerInfo);
|
||||||
|
|
||||||
/* topology.c */
|
/* topology.c */
|
||||||
|
|
||||||
|
@ -462,8 +503,25 @@ MMixerIsTopologyNodeReserved(
|
||||||
IN ULONG NodeIndex,
|
IN ULONG NodeIndex,
|
||||||
OUT PULONG bReserved);
|
OUT PULONG bReserved);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MMixerSetTopologyPinReserved(
|
||||||
|
IN PTOPOLOGY Topology,
|
||||||
|
IN ULONG PinId);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MMixerIsTopologyPinReserved(
|
||||||
|
IN PTOPOLOGY Topology,
|
||||||
|
IN ULONG PinId,
|
||||||
|
OUT PULONG bReserved);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
MMixerGetTopologyPinCount(
|
MMixerGetTopologyPinCount(
|
||||||
IN PTOPOLOGY Topology,
|
IN PTOPOLOGY Topology,
|
||||||
OUT PULONG PinCount);
|
OUT PULONG PinCount);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MMixerGetConnectedFromLogicalTopologyPins(
|
||||||
|
IN PTOPOLOGY Topology,
|
||||||
|
IN ULONG NodeIndex,
|
||||||
|
OUT PULONG OutPinCount,
|
||||||
|
OUT PULONG OutPins);
|
||||||
|
|
|
@ -54,6 +54,63 @@ MMixerVerifyContext(
|
||||||
return MM_STATUS_SUCCESS;
|
return MM_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LPMIXERLINE_EXT
|
||||||
|
MMixerGetMixerLineContainingNodeId(
|
||||||
|
IN LPMIXER_INFO MixerInfo,
|
||||||
|
IN ULONG NodeID)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY Entry, ControlEntry;
|
||||||
|
LPMIXERLINE_EXT MixerLineSrc;
|
||||||
|
LPMIXERCONTROL_EXT MixerControl;
|
||||||
|
|
||||||
|
/* get first entry */
|
||||||
|
Entry = MixerInfo->LineList.Flink;
|
||||||
|
|
||||||
|
while(Entry != &MixerInfo->LineList)
|
||||||
|
{
|
||||||
|
MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry);
|
||||||
|
|
||||||
|
ControlEntry = MixerLineSrc->ControlsList.Flink;
|
||||||
|
while(ControlEntry != &MixerLineSrc->ControlsList)
|
||||||
|
{
|
||||||
|
MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(ControlEntry, MIXERCONTROL_EXT, Entry);
|
||||||
|
if (MixerControl->NodeID == NodeID)
|
||||||
|
{
|
||||||
|
return MixerLineSrc;
|
||||||
|
}
|
||||||
|
ControlEntry = ControlEntry->Flink;
|
||||||
|
}
|
||||||
|
Entry = Entry->Flink;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MMixerGetLowestLogicalTopologyPinOffsetFromArray(
|
||||||
|
IN ULONG LogicalPinArrayCount,
|
||||||
|
IN PULONG LogicalPinArray,
|
||||||
|
OUT PULONG PinOffset)
|
||||||
|
{
|
||||||
|
ULONG Index;
|
||||||
|
ULONG LowestId = 0;
|
||||||
|
|
||||||
|
for(Index = 1; Index < LogicalPinArrayCount; Index++)
|
||||||
|
{
|
||||||
|
if (LogicalPinArray[Index] != MAXULONG)
|
||||||
|
{
|
||||||
|
/* sanity check: logical pin id must be unique */
|
||||||
|
ASSERT(LogicalPinArray[Index] != LogicalPinArray[LowestId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LogicalPinArray[Index] < LogicalPinArray[LowestId])
|
||||||
|
LowestId = Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store result */
|
||||||
|
*PinOffset = LowestId;
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
MMixerFreeMixerInfo(
|
MMixerFreeMixerInfo(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
|
@ -67,6 +124,38 @@ MMixerFreeMixerInfo(
|
||||||
MixerContext->Free((PVOID)MixerInfo);
|
MixerContext->Free((PVOID)MixerInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LPMIXER_DATA
|
||||||
|
MMixerGetMixerDataByDeviceHandle(
|
||||||
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
|
IN HANDLE hDevice)
|
||||||
|
{
|
||||||
|
LPMIXER_DATA MixerData;
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
|
PMIXER_LIST MixerList;
|
||||||
|
|
||||||
|
/* get mixer list */
|
||||||
|
MixerList = (PMIXER_LIST)MixerContext->MixerContext;
|
||||||
|
|
||||||
|
if (!MixerList->MixerDataCount)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
Entry = MixerList->MixerData.Flink;
|
||||||
|
|
||||||
|
while(Entry != &MixerList->MixerData)
|
||||||
|
{
|
||||||
|
MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
|
||||||
|
|
||||||
|
if (MixerData->hDevice == hDevice)
|
||||||
|
return MixerData;
|
||||||
|
|
||||||
|
/* move to next mixer entry */
|
||||||
|
Entry = Entry->Flink;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LPMIXER_INFO
|
LPMIXER_INFO
|
||||||
MMixerGetMixerInfoByIndex(
|
MMixerGetMixerInfoByIndex(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
|
@ -100,27 +189,31 @@ MMixerGetMixerInfoByIndex(
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
LPMIXERCONTROL_DATA
|
MIXER_STATUS
|
||||||
MMixerGetMixerControlDataById(
|
MMixerGetMixerByName(
|
||||||
PLIST_ENTRY ListHead,
|
IN PMIXER_LIST MixerList,
|
||||||
DWORD dwControlId)
|
IN LPWSTR MixerName,
|
||||||
|
OUT LPMIXER_INFO *OutMixerInfo)
|
||||||
{
|
{
|
||||||
|
LPMIXER_INFO MixerInfo;
|
||||||
PLIST_ENTRY Entry;
|
PLIST_ENTRY Entry;
|
||||||
LPMIXERCONTROL_DATA Control;
|
|
||||||
|
|
||||||
/* get first entry */
|
Entry = MixerList->MixerList.Flink;
|
||||||
Entry = ListHead->Flink;
|
while(Entry != &MixerList->MixerList)
|
||||||
|
|
||||||
while(Entry != ListHead)
|
|
||||||
{
|
{
|
||||||
Control = (LPMIXERCONTROL_DATA)CONTAINING_RECORD(Entry, MIXERCONTROL_DATA, Entry);
|
MixerInfo = (LPMIXER_INFO)CONTAINING_RECORD(Entry, MIXER_INFO, Entry);
|
||||||
DPRINT("dwSource %x dwSource %x\n", Control->dwControlID, dwControlId);
|
|
||||||
if (Control->dwControlID == dwControlId)
|
|
||||||
return Control;
|
|
||||||
|
|
||||||
|
DPRINT1("MixerName %S MixerName %S\n", MixerInfo->MixCaps.szPname, MixerName);
|
||||||
|
if (wcsicmp(MixerInfo->MixCaps.szPname, MixerName) == 0)
|
||||||
|
{
|
||||||
|
*OutMixerInfo = MixerInfo;
|
||||||
|
return MM_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
/* move to next mixer entry */
|
||||||
Entry = Entry->Flink;
|
Entry = Entry->Flink;
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
|
return MM_STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
LPMIXERLINE_EXT
|
LPMIXERLINE_EXT
|
||||||
|
@ -187,13 +280,13 @@ MIXER_STATUS
|
||||||
MMixerGetMixerControlById(
|
MMixerGetMixerControlById(
|
||||||
LPMIXER_INFO MixerInfo,
|
LPMIXER_INFO MixerInfo,
|
||||||
DWORD dwControlID,
|
DWORD dwControlID,
|
||||||
LPMIXERLINE_EXT *MixerLine,
|
LPMIXERLINE_EXT *OutMixerLine,
|
||||||
LPMIXERCONTROLW *MixerControl,
|
LPMIXERCONTROL_EXT *OutMixerControl,
|
||||||
PULONG NodeId)
|
PULONG NodeId)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY Entry;
|
PLIST_ENTRY Entry, ControlEntry;
|
||||||
LPMIXERLINE_EXT MixerLineSrc;
|
LPMIXERLINE_EXT MixerLineSrc;
|
||||||
ULONG Index;
|
LPMIXERCONTROL_EXT MixerControl;
|
||||||
|
|
||||||
/* get first entry */
|
/* get first entry */
|
||||||
Entry = MixerInfo->LineList.Flink;
|
Entry = MixerInfo->LineList.Flink;
|
||||||
|
@ -202,18 +295,21 @@ MMixerGetMixerControlById(
|
||||||
{
|
{
|
||||||
MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry);
|
MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry);
|
||||||
|
|
||||||
for(Index = 0; Index < MixerLineSrc->Line.cControls; Index++)
|
ControlEntry = MixerLineSrc->ControlsList.Flink;
|
||||||
|
while(ControlEntry != &MixerLineSrc->ControlsList)
|
||||||
{
|
{
|
||||||
if (MixerLineSrc->LineControls[Index].dwControlID == dwControlID)
|
MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(ControlEntry, MIXERCONTROL_EXT, Entry);
|
||||||
|
if (MixerControl->Control.dwControlID == dwControlID)
|
||||||
{
|
{
|
||||||
if (MixerLine)
|
if (OutMixerLine)
|
||||||
*MixerLine = MixerLineSrc;
|
*OutMixerLine = MixerLineSrc;
|
||||||
if (MixerControl)
|
if (OutMixerControl)
|
||||||
*MixerControl = &MixerLineSrc->LineControls[Index];
|
*OutMixerControl = MixerControl;
|
||||||
if (NodeId)
|
if (NodeId)
|
||||||
*NodeId = MixerLineSrc->NodeIds[Index];
|
*NodeId = MixerControl->NodeID;
|
||||||
return MM_STATUS_SUCCESS;
|
return MM_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
ControlEntry = ControlEntry->Flink;
|
||||||
}
|
}
|
||||||
Entry = Entry->Flink;
|
Entry = Entry->Flink;
|
||||||
}
|
}
|
||||||
|
@ -248,8 +344,8 @@ MMixerNotifyControlChange(
|
||||||
PLIST_ENTRY Entry;
|
PLIST_ENTRY Entry;
|
||||||
PEVENT_NOTIFICATION_ENTRY NotificationEntry;
|
PEVENT_NOTIFICATION_ENTRY NotificationEntry;
|
||||||
|
|
||||||
/* enumerate list and add a notification entry */
|
/* enumerate list and perform notification */
|
||||||
Entry = MixerInfo->LineList.Flink;
|
Entry = MixerInfo->EventList.Flink;
|
||||||
while(Entry != &MixerInfo->EventList)
|
while(Entry != &MixerInfo->EventList)
|
||||||
{
|
{
|
||||||
/* get notification entry offset */
|
/* get notification entry offset */
|
||||||
|
@ -270,7 +366,7 @@ MIXER_STATUS
|
||||||
MMixerSetGetMuteControlDetails(
|
MMixerSetGetMuteControlDetails(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
IN LPMIXER_INFO MixerInfo,
|
IN LPMIXER_INFO MixerInfo,
|
||||||
IN ULONG NodeId,
|
IN LPMIXERCONTROL_EXT MixerControl,
|
||||||
IN ULONG dwLineID,
|
IN ULONG dwLineID,
|
||||||
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
||||||
IN ULONG bSet)
|
IN ULONG bSet)
|
||||||
|
@ -290,7 +386,7 @@ MMixerSetGetMuteControlDetails(
|
||||||
Value = Input->fValue;
|
Value = Input->fValue;
|
||||||
|
|
||||||
/* set control details */
|
/* set control details */
|
||||||
Status = MMixerSetGetControlDetails(MixerContext, MixerInfo->hMixer, NodeId, bSet, KSPROPERTY_AUDIO_MUTE, 0, &Value);
|
Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, MixerControl->NodeID, bSet, KSPROPERTY_AUDIO_MUTE, 0, &Value);
|
||||||
|
|
||||||
if (Status != MM_STATUS_SUCCESS)
|
if (Status != MM_STATUS_SUCCESS)
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -310,13 +406,262 @@ MMixerSetGetMuteControlDetails(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MIXER_STATUS
|
||||||
|
MMixerSetGetMuxControlDetails(
|
||||||
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
|
IN LPMIXER_INFO MixerInfo,
|
||||||
|
IN ULONG NodeId,
|
||||||
|
IN ULONG bSet,
|
||||||
|
IN ULONG Flags,
|
||||||
|
IN LPMIXERCONTROL_EXT MixerControl,
|
||||||
|
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
||||||
|
IN LPMIXERLINE_EXT MixerLine)
|
||||||
|
{
|
||||||
|
MIXER_STATUS Status;
|
||||||
|
PULONG LogicalNodes, ConnectedNodes;
|
||||||
|
ULONG LogicalNodesCount, ConnectedNodesCount, Index, CurLogicalPinOffset, BytesReturned, OldLogicalPinOffset;
|
||||||
|
LPMIXER_DATA MixerData;
|
||||||
|
LPMIXERCONTROLDETAILS_LISTTEXTW ListText;
|
||||||
|
LPMIXERCONTROLDETAILS_BOOLEAN Values;
|
||||||
|
LPMIXERLINE_EXT SourceLine;
|
||||||
|
KSNODEPROPERTY Request;
|
||||||
|
|
||||||
|
DPRINT("MixerControlDetails %p\n", MixerControlDetails);
|
||||||
|
DPRINT("bSet %lx\n", bSet);
|
||||||
|
DPRINT("Flags %lx\n", Flags);
|
||||||
|
DPRINT("NodeId %lu\n", MixerControl->NodeID);
|
||||||
|
DPRINT("MixerControlDetails dwControlID %lu\n", MixerControlDetails->dwControlID);
|
||||||
|
DPRINT("MixerControlDetails cChannels %lu\n", MixerControlDetails->cChannels);
|
||||||
|
DPRINT("MixerControlDetails cMultipleItems %lu\n", MixerControlDetails->cMultipleItems);
|
||||||
|
DPRINT("MixerControlDetails cbDetails %lu\n", MixerControlDetails->cbDetails);
|
||||||
|
DPRINT("MixerControlDetails paDetails %p\n", MixerControlDetails->paDetails);
|
||||||
|
|
||||||
|
if (MixerControl->Control.fdwControl & MIXERCONTROL_CONTROLF_UNIFORM)
|
||||||
|
{
|
||||||
|
/* control acts uniform */
|
||||||
|
if (MixerControlDetails->cChannels != 1)
|
||||||
|
{
|
||||||
|
/* expected 1 channel */
|
||||||
|
DPRINT1("Expected 1 channel but got %lu\n", MixerControlDetails->cChannels);
|
||||||
|
return MM_STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if multiple items match */
|
||||||
|
if (MixerControlDetails->cMultipleItems != MixerControl->Control.cMultipleItems)
|
||||||
|
{
|
||||||
|
DPRINT1("MultipleItems mismatch %lu expected %lu\n", MixerControlDetails->cMultipleItems, MixerControl->Control.cMultipleItems);
|
||||||
|
return MM_STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bSet)
|
||||||
|
{
|
||||||
|
if ((Flags & MIXER_SETCONTROLDETAILSF_QUERYMASK) == MIXER_SETCONTROLDETAILSF_CUSTOM)
|
||||||
|
{
|
||||||
|
/* tell me when this is hit */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
else if ((Flags & (MIXER_SETCONTROLDETAILSF_VALUE | MIXER_SETCONTROLDETAILSF_CUSTOM)) == MIXER_SETCONTROLDETAILSF_VALUE)
|
||||||
|
{
|
||||||
|
/* sanity check */
|
||||||
|
ASSERT(bSet == TRUE);
|
||||||
|
ASSERT(MixerControlDetails->cbDetails == sizeof(MIXERCONTROLDETAILS_BOOLEAN));
|
||||||
|
|
||||||
|
Values = (LPMIXERCONTROLDETAILS_BOOLEAN)MixerControlDetails->paDetails;
|
||||||
|
CurLogicalPinOffset = MAXULONG;
|
||||||
|
for(Index = 0; Index < MixerControlDetails->cMultipleItems; Index++)
|
||||||
|
{
|
||||||
|
if (Values[Index].fValue)
|
||||||
|
{
|
||||||
|
/* mux can only activate one line at a time */
|
||||||
|
ASSERT(CurLogicalPinOffset == MAXULONG);
|
||||||
|
CurLogicalPinOffset = Index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup request */
|
||||||
|
Request.NodeId = NodeId;
|
||||||
|
Request.Reserved = 0;
|
||||||
|
Request.Property.Flags = KSPROPERTY_TYPE_TOPOLOGY | KSPROPERTY_TYPE_GET;
|
||||||
|
Request.Property.Id = KSPROPERTY_AUDIO_MUX_SOURCE;
|
||||||
|
Request.Property.Set = KSPROPSETID_Audio;
|
||||||
|
|
||||||
|
/* perform getting source */
|
||||||
|
Status = MixerContext->Control(MixerControl->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSNODEPROPERTY), &OldLogicalPinOffset, sizeof(ULONG), &BytesReturned);
|
||||||
|
if (Status != MM_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* failed to get source */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("OldLogicalPinOffset %lu CurLogicalPinOffset %lu\n", OldLogicalPinOffset, CurLogicalPinOffset);
|
||||||
|
|
||||||
|
if (OldLogicalPinOffset == CurLogicalPinOffset)
|
||||||
|
{
|
||||||
|
/* cannot be unselected */
|
||||||
|
return MM_STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* perform setting source */
|
||||||
|
Request.Property.Flags = KSPROPERTY_TYPE_TOPOLOGY | KSPROPERTY_TYPE_SET;
|
||||||
|
Status = MixerContext->Control(MixerControl->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSNODEPROPERTY), &CurLogicalPinOffset, sizeof(ULONG), &BytesReturned);
|
||||||
|
if (Status != MM_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* failed to set source */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* notify control change */
|
||||||
|
MMixerNotifyControlChange(MixerContext, MixerInfo, MM_MIXM_CONTROL_CHANGE, MixerControl->Control.dwControlID );
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((Flags & MIXER_GETCONTROLDETAILSF_QUERYMASK) == MIXER_GETCONTROLDETAILSF_VALUE)
|
||||||
|
{
|
||||||
|
/* setup request */
|
||||||
|
Request.NodeId = NodeId;
|
||||||
|
Request.Reserved = 0;
|
||||||
|
Request.Property.Flags = KSPROPERTY_TYPE_TOPOLOGY | KSPROPERTY_TYPE_GET;
|
||||||
|
Request.Property.Id = KSPROPERTY_AUDIO_MUX_SOURCE;
|
||||||
|
Request.Property.Set = KSPROPSETID_Audio;
|
||||||
|
|
||||||
|
/* perform getting source */
|
||||||
|
Status = MixerContext->Control(MixerControl->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSNODEPROPERTY), &OldLogicalPinOffset, sizeof(ULONG), &BytesReturned);
|
||||||
|
if (Status != MM_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* failed to get source */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* gets the corresponding mixer data */
|
||||||
|
MixerData = MMixerGetMixerDataByDeviceHandle(MixerContext, MixerControl->hDevice);
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
ASSERT(MixerData);
|
||||||
|
ASSERT(MixerData->Topology);
|
||||||
|
ASSERT(MixerData->MixerInfo == MixerInfo);
|
||||||
|
|
||||||
|
/* get logical pin nodes */
|
||||||
|
MMixerGetConnectedFromLogicalTopologyPins(MixerData->Topology, MixerControl->NodeID, &LogicalNodesCount, LogicalNodes);
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
ASSERT(LogicalNodesCount == MixerControlDetails->cMultipleItems);
|
||||||
|
ASSERT(LogicalNodesCount == MixerControl->Control.Metrics.dwReserved[0]);
|
||||||
|
|
||||||
|
Values = (LPMIXERCONTROLDETAILS_BOOLEAN)MixerControlDetails->paDetails;
|
||||||
|
for(Index = 0; Index < ConnectedNodesCount; Index++)
|
||||||
|
{
|
||||||
|
/* getting logical pin offset */
|
||||||
|
MMixerGetLowestLogicalTopologyPinOffsetFromArray(LogicalNodesCount, LogicalNodes, &CurLogicalPinOffset);
|
||||||
|
|
||||||
|
if (CurLogicalPinOffset == OldLogicalPinOffset)
|
||||||
|
{
|
||||||
|
/* mark index as active */
|
||||||
|
Values[Index].fValue = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* index not active */
|
||||||
|
Values[Index].fValue = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mark offset as consumed */
|
||||||
|
LogicalNodes[CurLogicalPinOffset] = MAXULONG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
|
MixerContext->Free(LogicalNodes);
|
||||||
|
|
||||||
|
/* done */
|
||||||
|
return MM_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else if ((Flags & MIXER_GETCONTROLDETAILSF_QUERYMASK) == MIXER_GETCONTROLDETAILSF_LISTTEXT)
|
||||||
|
{
|
||||||
|
/* sanity check */
|
||||||
|
ASSERT(bSet == FALSE);
|
||||||
|
|
||||||
|
/* gets the corresponding mixer data */
|
||||||
|
MixerData = MMixerGetMixerDataByDeviceHandle(MixerContext, MixerControl->hDevice);
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
ASSERT(MixerData);
|
||||||
|
ASSERT(MixerData->Topology);
|
||||||
|
ASSERT(MixerData->MixerInfo == MixerInfo);
|
||||||
|
|
||||||
|
/* now allocate logical pin array */
|
||||||
|
Status = MMixerAllocateTopologyNodeArray(MixerContext, MixerData->Topology, &LogicalNodes);
|
||||||
|
if (Status != MM_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* no memory */
|
||||||
|
return MM_STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate connected node array */
|
||||||
|
Status = MMixerAllocateTopologyNodeArray(MixerContext, MixerData->Topology, &ConnectedNodes);
|
||||||
|
if (Status != MM_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* no memory */
|
||||||
|
MixerContext->Free(LogicalNodes);
|
||||||
|
return MM_STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get logical pin nodes */
|
||||||
|
MMixerGetConnectedFromLogicalTopologyPins(MixerData->Topology, MixerControl->NodeID, &LogicalNodesCount, LogicalNodes);
|
||||||
|
|
||||||
|
/* get connected nodes */
|
||||||
|
MMixerGetNextNodesFromNodeIndex(MixerContext, MixerData->Topology, MixerControl->NodeID, TRUE, &ConnectedNodesCount, ConnectedNodes);
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
ASSERT(ConnectedNodesCount == LogicalNodesCount);
|
||||||
|
ASSERT(ConnectedNodesCount == MixerControlDetails->cMultipleItems);
|
||||||
|
ASSERT(ConnectedNodesCount == MixerControl->Control.Metrics.dwReserved[0]);
|
||||||
|
|
||||||
|
ListText = (LPMIXERCONTROLDETAILS_LISTTEXTW)MixerControlDetails->paDetails;
|
||||||
|
|
||||||
|
for(Index = 0; Index < ConnectedNodesCount; Index++)
|
||||||
|
{
|
||||||
|
/* getting logical pin offset */
|
||||||
|
MMixerGetLowestLogicalTopologyPinOffsetFromArray(LogicalNodesCount, LogicalNodes, &CurLogicalPinOffset);
|
||||||
|
|
||||||
|
/* get mixer line with that node */
|
||||||
|
SourceLine = MMixerGetMixerLineContainingNodeId(MixerInfo, ConnectedNodes[CurLogicalPinOffset]);
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
ASSERT(SourceLine);
|
||||||
|
|
||||||
|
DPRINT1("PinOffset %lu LogicalPin %lu NodeId %lu LineName %S\n", CurLogicalPinOffset, LogicalNodes[CurLogicalPinOffset], ConnectedNodes[CurLogicalPinOffset], SourceLine->Line.szName);
|
||||||
|
|
||||||
|
/* copy details */
|
||||||
|
ListText[Index].dwParam1 = SourceLine->Line.dwLineID;
|
||||||
|
ListText[Index].dwParam2 = SourceLine->Line.dwComponentType;
|
||||||
|
MixerContext->Copy(ListText[Index].szName, SourceLine->Line.szName, (wcslen(SourceLine->Line.szName) + 1) * sizeof(WCHAR));
|
||||||
|
|
||||||
|
/* mark offset as consumed */
|
||||||
|
LogicalNodes[CurLogicalPinOffset] = MAXULONG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
|
MixerContext->Free(LogicalNodes);
|
||||||
|
MixerContext->Free(ConnectedNodes);
|
||||||
|
|
||||||
|
/* done */
|
||||||
|
return MM_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MM_STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
MIXER_STATUS
|
MIXER_STATUS
|
||||||
MMixerSetGetVolumeControlDetails(
|
MMixerSetGetVolumeControlDetails(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
IN LPMIXER_INFO MixerInfo,
|
IN LPMIXER_INFO MixerInfo,
|
||||||
IN ULONG NodeId,
|
IN ULONG NodeId,
|
||||||
IN ULONG bSet,
|
IN ULONG bSet,
|
||||||
LPMIXERCONTROLW MixerControl,
|
LPMIXERCONTROL_EXT MixerControl,
|
||||||
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
||||||
LPMIXERLINE_EXT MixerLine)
|
LPMIXERLINE_EXT MixerLine)
|
||||||
{
|
{
|
||||||
|
@ -329,7 +674,7 @@ MMixerSetGetVolumeControlDetails(
|
||||||
if (MixerControlDetails->cbDetails != sizeof(MIXERCONTROLDETAILS_SIGNED))
|
if (MixerControlDetails->cbDetails != sizeof(MIXERCONTROLDETAILS_SIGNED))
|
||||||
return MM_STATUS_INVALID_PARAMETER;
|
return MM_STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
VolumeData = (LPMIXERVOLUME_DATA)MMixerGetMixerControlDataById(&MixerLine->LineControlsExtraData, MixerControl->dwControlID);
|
VolumeData = (LPMIXERVOLUME_DATA)MixerControl->ExtraData;
|
||||||
if (!VolumeData)
|
if (!VolumeData)
|
||||||
return MM_STATUS_UNSUCCESSFUL;
|
return MM_STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
@ -355,12 +700,12 @@ MMixerSetGetVolumeControlDetails(
|
||||||
if (bSet)
|
if (bSet)
|
||||||
{
|
{
|
||||||
/* TODO */
|
/* TODO */
|
||||||
Status = MMixerSetGetControlDetails(MixerContext, MixerInfo->hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 0, &Value);
|
Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 0, &Value);
|
||||||
Status = MMixerSetGetControlDetails(MixerContext, MixerInfo->hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 1, &Value);
|
Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 1, &Value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Status = MMixerSetGetControlDetails(MixerContext, MixerInfo->hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, Channel, &Value);
|
Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, Channel, &Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bSet)
|
if (!bSet)
|
||||||
|
@ -372,7 +717,7 @@ MMixerSetGetVolumeControlDetails(
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* notify clients of a line change MM_MIXM_CONTROL_CHANGE with MixerControl->dwControlID */
|
/* notify clients of a line change MM_MIXM_CONTROL_CHANGE with MixerControl->dwControlID */
|
||||||
MMixerNotifyControlChange(MixerContext, MixerInfo, MM_MIXM_CONTROL_CHANGE, MixerControl->dwControlID);
|
MMixerNotifyControlChange(MixerContext, MixerInfo, MM_MIXM_CONTROL_CHANGE, MixerControl->Control.dwControlID);
|
||||||
}
|
}
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -264,7 +264,9 @@ MMixerHandleNodeToNodeConnection(
|
||||||
{
|
{
|
||||||
PTOPOLOGY_NODE InNode, OutNode;
|
PTOPOLOGY_NODE InNode, OutNode;
|
||||||
PTOPOLOGY_NODE * NewNodes;
|
PTOPOLOGY_NODE * NewNodes;
|
||||||
|
PULONG NewLogicalPinNodeConnectedFrom;
|
||||||
ULONG Count;
|
ULONG Count;
|
||||||
|
ULONG LogicalPinId;
|
||||||
|
|
||||||
/* sanity checks */
|
/* sanity checks */
|
||||||
ASSERT(Topology->TopologyNodesCount > Connection->ToNode);
|
ASSERT(Topology->TopologyNodesCount > Connection->ToNode);
|
||||||
|
@ -274,6 +276,9 @@ MMixerHandleNodeToNodeConnection(
|
||||||
InNode = &Topology->TopologyNodes[Connection->FromNode];
|
InNode = &Topology->TopologyNodes[Connection->FromNode];
|
||||||
OutNode = &Topology->TopologyNodes[Connection->ToNode];
|
OutNode = &Topology->TopologyNodes[Connection->ToNode];
|
||||||
|
|
||||||
|
/* get logical pin node id */
|
||||||
|
LogicalPinId = Connection->ToNodePin;
|
||||||
|
|
||||||
/* get existing count */
|
/* get existing count */
|
||||||
Count = OutNode->NodeConnectedFromCount;
|
Count = OutNode->NodeConnectedFromCount;
|
||||||
|
|
||||||
|
@ -286,21 +291,42 @@ MMixerHandleNodeToNodeConnection(
|
||||||
return MM_STATUS_NO_MEMORY;
|
return MM_STATUS_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* allocate logical pin nodes array */
|
||||||
|
NewLogicalPinNodeConnectedFrom = MixerContext->Alloc((Count + 1) * sizeof(ULONG));
|
||||||
|
if (!NewLogicalPinNodeConnectedFrom)
|
||||||
|
{
|
||||||
|
/* out of memory */
|
||||||
|
MixerContext->Free(NewNodes);
|
||||||
|
return MM_STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
if (Count)
|
if (Count)
|
||||||
{
|
{
|
||||||
/* copy existing nodes */
|
/* copy existing nodes */
|
||||||
MixerContext->Copy(NewNodes, OutNode->NodeConnectedFrom, sizeof(PTOPOLOGY) * Count);
|
MixerContext->Copy(NewNodes, OutNode->NodeConnectedFrom, sizeof(PTOPOLOGY) * Count);
|
||||||
|
|
||||||
|
/* copy existing logical pin node array */
|
||||||
|
MixerContext->Copy(NewLogicalPinNodeConnectedFrom, OutNode->LogicalPinNodeConnectedFrom, sizeof(ULONG) * Count);
|
||||||
|
|
||||||
/* release old nodes array */
|
/* release old nodes array */
|
||||||
MixerContext->Free(OutNode->NodeConnectedFrom);
|
MixerContext->Free(OutNode->NodeConnectedFrom);
|
||||||
|
|
||||||
|
/* release old logical pin node array */
|
||||||
|
MixerContext->Free(OutNode->LogicalPinNodeConnectedFrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add new topology node */
|
/* add new topology node */
|
||||||
NewNodes[OutNode->NodeConnectedFromCount] = InNode;
|
NewNodes[OutNode->NodeConnectedFromCount] = InNode;
|
||||||
|
|
||||||
|
/* add logical node id */
|
||||||
|
NewLogicalPinNodeConnectedFrom[OutNode->NodeConnectedFromCount] = LogicalPinId;
|
||||||
|
|
||||||
/* replace old nodes array */
|
/* replace old nodes array */
|
||||||
OutNode->NodeConnectedFrom = NewNodes;
|
OutNode->NodeConnectedFrom = NewNodes;
|
||||||
|
|
||||||
|
/* replace old logical pin node array */
|
||||||
|
OutNode->LogicalPinNodeConnectedFrom = NewLogicalPinNodeConnectedFrom;
|
||||||
|
|
||||||
/* increment nodes count */
|
/* increment nodes count */
|
||||||
OutNode->NodeConnectedFromCount++;
|
OutNode->NodeConnectedFromCount++;
|
||||||
|
|
||||||
|
@ -745,16 +771,15 @@ MMixerGetUpOrDownstreamNodes(
|
||||||
/* node should not have been visited */
|
/* node should not have been visited */
|
||||||
ASSERT(Node->Visited == FALSE);
|
ASSERT(Node->Visited == FALSE);
|
||||||
|
|
||||||
|
/* mark node as visited */
|
||||||
|
TopologyNode->Visited = TRUE;
|
||||||
|
|
||||||
/* add them to node array */
|
/* add them to node array */
|
||||||
MMixerAddPinIndexToArray(MixerContext, Node->NodeIndex, Topology->TopologyNodesCount, OutNodeCount, OutNodes);
|
MMixerAddPinIndexToArray(MixerContext, Node->NodeIndex, Topology->TopologyNodesCount, OutNodeCount, OutNodes);
|
||||||
|
|
||||||
/* recursively visit them */
|
/* recursively visit them */
|
||||||
MMixerGetUpOrDownstreamNodes(MixerContext, Topology, TopologyNodes[Index], bUpStream, OutNodeCount, OutNodes);
|
MMixerGetUpOrDownstreamNodes(MixerContext, Topology, TopologyNodes[Index], bUpStream, OutNodeCount, OutNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mark node as visited */
|
|
||||||
TopologyNode->Visited = TRUE;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MIXER_STATUS
|
MIXER_STATUS
|
||||||
|
@ -1137,6 +1162,32 @@ MMixerIsNodeConnectedToPin(
|
||||||
return MM_STATUS_SUCCESS;
|
return MM_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MMixerGetConnectedFromLogicalTopologyPins(
|
||||||
|
IN PTOPOLOGY Topology,
|
||||||
|
IN ULONG NodeIndex,
|
||||||
|
OUT PULONG OutPinCount,
|
||||||
|
OUT PULONG OutPins)
|
||||||
|
{
|
||||||
|
ULONG Index;
|
||||||
|
PTOPOLOGY_NODE Node;
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
ASSERT(NodeIndex < Topology->TopologyNodesCount);
|
||||||
|
|
||||||
|
/* get node */
|
||||||
|
Node = &Topology->TopologyNodes[NodeIndex];
|
||||||
|
|
||||||
|
for(Index = 0; Index < Node->NodeConnectedFromCount; Index++)
|
||||||
|
{
|
||||||
|
/* copy logical pin id */
|
||||||
|
OutPins[Index] = Node->LogicalPinNodeConnectedFrom[Index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store pin count */
|
||||||
|
*OutPinCount = Node->NodeConnectedFromCount;
|
||||||
|
}
|
||||||
|
|
||||||
LPGUID
|
LPGUID
|
||||||
MMixerGetNodeTypeFromTopology(
|
MMixerGetNodeTypeFromTopology(
|
||||||
IN PTOPOLOGY Topology,
|
IN PTOPOLOGY Topology,
|
||||||
|
@ -1148,6 +1199,31 @@ MMixerGetNodeTypeFromTopology(
|
||||||
return &Topology->TopologyNodes[NodeIndex].NodeType;
|
return &Topology->TopologyNodes[NodeIndex].NodeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MMixerSetTopologyPinReserved(
|
||||||
|
IN PTOPOLOGY Topology,
|
||||||
|
IN ULONG PinId)
|
||||||
|
{
|
||||||
|
/* sanity check */
|
||||||
|
ASSERT(PinId < Topology->TopologyPinsCount);
|
||||||
|
|
||||||
|
/* set reserved */
|
||||||
|
Topology->TopologyPins[PinId].Reserved = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MMixerIsTopologyPinReserved(
|
||||||
|
IN PTOPOLOGY Topology,
|
||||||
|
IN ULONG PinId,
|
||||||
|
OUT PULONG bReserved)
|
||||||
|
{
|
||||||
|
/* sanity check */
|
||||||
|
ASSERT(PinId < Topology->TopologyPinsCount);
|
||||||
|
|
||||||
|
/* get reserved status */
|
||||||
|
*bReserved = Topology->TopologyPins[PinId].Reserved;
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
MMixerSetTopologyNodeReserved(
|
MMixerSetTopologyNodeReserved(
|
||||||
IN PTOPOLOGY Topology,
|
IN PTOPOLOGY Topology,
|
||||||
|
|
|
@ -608,6 +608,16 @@ MMixerSetWaveStatus(
|
||||||
{
|
{
|
||||||
KSPROPERTY Property;
|
KSPROPERTY Property;
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
|
MIXER_STATUS Status;
|
||||||
|
|
||||||
|
/* verify mixer context */
|
||||||
|
Status = MMixerVerifyContext(MixerContext);
|
||||||
|
|
||||||
|
if (Status != MM_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* invalid context passed */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
/* setup property request */
|
/* setup property request */
|
||||||
Property.Set = KSPROPSETID_Connection;
|
Property.Set = KSPROPSETID_Connection;
|
||||||
|
@ -617,6 +627,31 @@ MMixerSetWaveStatus(
|
||||||
return MixerContext->Control(PinHandle, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &State, sizeof(KSSTATE), &Length);
|
return MixerContext->Control(PinHandle, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &State, sizeof(KSSTATE), &Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MIXER_STATUS
|
||||||
|
MMixerSetWaveResetState(
|
||||||
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
|
IN HANDLE PinHandle,
|
||||||
|
IN ULONG bBegin)
|
||||||
|
{
|
||||||
|
ULONG Length;
|
||||||
|
MIXER_STATUS Status;
|
||||||
|
KSRESET Reset;
|
||||||
|
|
||||||
|
/* verify mixer context */
|
||||||
|
Status = MMixerVerifyContext(MixerContext);
|
||||||
|
|
||||||
|
if (Status != MM_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* invalid context passed */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* begin / stop reset */
|
||||||
|
Reset = (bBegin ? KSRESET_BEGIN : KSRESET_END);
|
||||||
|
|
||||||
|
return MixerContext->Control(PinHandle, IOCTL_KS_RESET_STATE, &Reset, sizeof(KSRESET), NULL, 0, &Length);
|
||||||
|
}
|
||||||
|
|
||||||
MIXER_STATUS
|
MIXER_STATUS
|
||||||
MMixerGetWaveDevicePath(
|
MMixerGetWaveDevicePath(
|
||||||
IN PMIXER_CONTEXT MixerContext,
|
IN PMIXER_CONTEXT MixerContext,
|
||||||
|
|
Loading…
Reference in a new issue