diff options
| author | Girish Pattabiraman <[email protected]> | 2017-05-03 15:02:49 -0700 |
|---|---|---|
| committer | Girish Pattabiraman <[email protected]> | 2017-05-03 17:20:15 -0700 |
| commit | b9027f2b8124f5853dac4355ff4d9e85379e0e56 (patch) | |
| tree | 33487ba551e9e53ba5a000afc2ad8860892ef2fa | |
| parent | 32dc5459e78107ce48412eef3653370f32274561 (diff) | |
Audio Modules Example
Delay APO
Package Project
Stream Position Bug Fix
SAL
58 files changed, 6310 insertions, 287 deletions
diff --git a/audio/sysvad/EndpointsCommon/AudioModule0.h b/audio/sysvad/EndpointsCommon/AudioModule0.h new file mode 100644 index 00000000..c1f07557 --- /dev/null +++ b/audio/sysvad/EndpointsCommon/AudioModule0.h @@ -0,0 +1,297 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + AudioModule0.h + +Abstract: + + Declaration of Audio Module 0 (system module). + +--*/ + +#ifndef _SYSVAD_AUDIOMODULE0_H_ +#define _SYSVAD_AUDIOMODULE0_H_ + +#include "AudioModuleHelper.h" + +#define AUDIOMODULE0_MAJOR 0x1 +#define AUDIOMODULE0_MINOR 0X0 + +static const GUID AudioModule0Id = +{ 0xe24c8b6f, 0xede7, 0x4255, 0x8b, 0x39, 0x77, 0x97, 0x60, 0x15, 0xd5, 0x93 }; + +enum AudioModule0_Parameter { + AudioModule0Parameter1 = 0, + AudioModule0Parameter2 +}; + +typedef struct _AUDIOMODULE0_CUSTOM_COMMAND { + ULONG Verb; // get, set and support + AudioModule0_Parameter ParameterId; +} AUDIOMODULE0_CUSTOM_COMMAND, *PAUDIOMODULE0_CUSTOM_COMMAND; + +enum AudioModule0_Notification_Type { + AudioModule0ParameterChanged = 0, +}; + +typedef struct _AUDIOMODULE0_CUSTOM_NOTIFICATION { + ULONG Type; + union { + struct { + ULONG ParameterId; + } ParameterChanged; + }; +} AUDIOMODULE0_CUSTOM_NOTIFICATION, *PAUDIOMODULE0_CUSTOM_NOTIFICATION; + +typedef struct _AUDIOMODULE0_NOTIFICATION { + KSAUDIOMODULE_NOTIFICATION Header; + AUDIOMODULE0_CUSTOM_NOTIFICATION CustomNotification; +} AUDIOMODULE0_NOTIFICATION, *PAUDIOMODULE0_NOTIFICATION; + +typedef struct _AUDIOMODULE0_CONTEXT { + ULONG Parameter1; + BYTE Parameter2; + ULONG InstanceId; + AUDIOMODULE0_NOTIFICATION Notification; + PPORTCLSNOTIFICATIONS PortNotifications; +} AUDIOMODULE0_CONTEXT, *PAUDIOMODULE0_CONTEXT; + +static +ULONG AudioModule0_ValidParameter1List[] = +{ + 1, 2, 5 +}; + +static +AUDIOMODULE_PARAMETER_INFO AudioModule0_ParameterInfo[] = +{ + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION, + (ULONG)RTL_FIELD_SIZE(AUDIOMODULE0_CONTEXT, Parameter1), + VT_UI4, + AudioModule0_ValidParameter1List, + SIZEOF_ARRAY(AudioModule0_ValidParameter1List) + }, + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + 0, + (ULONG)RTL_FIELD_SIZE(AUDIOMODULE0_CONTEXT, Parameter2), + VT_UI1, + NULL, + 0 + }, +}; + +inline +#pragma code_seg("PAGE") +NTSTATUS +AudioModule0_InitClass( + _In_ const AUDIOMODULE_DESCRIPTOR * Module, + _Inout_opt_ PVOID Context, + _In_ size_t Size, + _In_ KSAUDIOMODULE_NOTIFICATION * NotificationHeader, + _In_opt_ PPORTCLSNOTIFICATIONS PortNotifications + ) +{ + PAUDIOMODULE0_CONTEXT ctx = (PAUDIOMODULE0_CONTEXT)Context; + + UNREFERENCED_PARAMETER(Module); + + PAGED_CODE(); + + if (Context == NULL) + { + ASSERT(FALSE); // this should not happen. + return STATUS_INTERNAL_ERROR; + } + + ASSERT(Size != 0); + RtlZeroMemory(Context, Size); + + ctx->Notification.Header = *NotificationHeader; + ctx->PortNotifications = PortNotifications; + if (ctx->PortNotifications != NULL) + { + ctx->PortNotifications->AddRef(); + } + + return STATUS_SUCCESS; +} + +inline +#pragma code_seg("PAGE") +NTSTATUS +AudioModule0_InitInstance( + _In_ const AUDIOMODULE_DESCRIPTOR * Module, + _In_opt_ PVOID TemplateContext, + _Inout_opt_ PVOID Context, + _In_ size_t Size, + _In_ ULONG InstanceId + ) +{ + PAUDIOMODULE0_CONTEXT ctx = (PAUDIOMODULE0_CONTEXT)Context; + + UNREFERENCED_PARAMETER(Module); + + PAGED_CODE(); + + if (Context == NULL) + { + ASSERT(FALSE); // this should not happen. + return STATUS_INTERNAL_ERROR; + } + + ASSERT(TemplateContext != NULL); + ASSERT(Size != 0); + + RtlCopyMemory(Context, TemplateContext, Size); + + ctx->InstanceId = InstanceId; + ctx->Notification.Header.ProviderId.InstanceId = InstanceId; + if (ctx->PortNotifications != NULL) + { + ctx->PortNotifications->AddRef(); + } + + return STATUS_SUCCESS; +} + +inline +#pragma code_seg("PAGE") +VOID +AudioModule0_Cleanup( + _In_ PVOID Context + ) +{ + PAUDIOMODULE0_CONTEXT ctx = (PAUDIOMODULE0_CONTEXT)Context; + + PAGED_CODE(); + + if (Context == NULL) + { + ASSERT(FALSE); // this should not happen. + return; + } + + SAFE_RELEASE(ctx->PortNotifications); +} + +inline +#pragma code_seg("PAGE") +NTSTATUS +AudioModule0_Handler( + _Inout_opt_ PVOID Context, + _In_reads_bytes_(InBufferCb) PVOID InBuffer, + _In_ ULONG InBufferCb, + _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer, + _Inout_ ULONG * OutBufferCb + ) +{ + NTSTATUS status = STATUS_SUCCESS; + BOOL fNewValue = FALSE; + PVOID currentValue; + PVOID inBuffer = NULL; + ULONG inBufferCb = 0; + + PAUDIOMODULE0_CONTEXT ctx = (PAUDIOMODULE0_CONTEXT)Context; + AUDIOMODULE_PARAMETER_INFO * parameterInfo = NULL; + AUDIOMODULE0_CUSTOM_COMMAND * command = NULL; + + PAGED_CODE(); + + if (ctx == NULL) + { + ASSERT(FALSE); // this should not happen. + status = STATUS_INTERNAL_ERROR; + goto exit; + } + + // + // Basic parameter validation (module specific). + // + if (InBuffer == NULL || InBufferCb == 0) + { + return STATUS_INVALID_PARAMETER; + } + + if (InBufferCb < sizeof(AUDIOMODULE0_CUSTOM_COMMAND)) + { + return STATUS_INVALID_PARAMETER; + } + + command = (AUDIOMODULE0_CUSTOM_COMMAND*)InBuffer; + + // + // Validate the parameter referenced in the command. + // + switch (command->ParameterId) + { + case AudioModule0Parameter1: + currentValue = &ctx->Parameter1; + parameterInfo = &AudioModule0_ParameterInfo[AudioModule0Parameter1]; + break; + + case AudioModule0Parameter2: + currentValue = &ctx->Parameter2; + parameterInfo = &AudioModule0_ParameterInfo[AudioModule0Parameter2]; + break; + + default: + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + // + // Update input buffer ptr/size. + // + inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE0_CUSTOM_COMMAND)); + inBufferCb = InBufferCb - sizeof(AUDIOMODULE0_CUSTOM_COMMAND); + + if (inBufferCb == 0) + { + inBuffer = NULL; + } + + status = AudioModule_GenericHandler( + command->Verb, + command->ParameterId, + parameterInfo, + currentValue, + inBuffer, + inBufferCb, + OutBuffer, + OutBufferCb, + &fNewValue); + + if (!NT_SUCCESS(status)) + { + goto exit; + } + + if (fNewValue && ctx->PortNotifications && + (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION)) + { + // This logic assumes that access to this function is serialized. + ctx->Notification.CustomNotification.Type = AudioModule0ParameterChanged; + ctx->Notification.CustomNotification.ParameterChanged.ParameterId = + command->ParameterId; + + AudioModule_SendNotification(ctx->PortNotifications, + (PVOID)&ctx->Notification, + (USHORT)sizeof(ctx->Notification)); + } + + // Normalize error code. + status = STATUS_SUCCESS; + +exit: + return status; +} + +#endif // _SYSVAD_AUDIOMODULE0_H_ + + diff --git a/audio/sysvad/EndpointsCommon/AudioModule1.h b/audio/sysvad/EndpointsCommon/AudioModule1.h new file mode 100644 index 00000000..9f01eaed --- /dev/null +++ b/audio/sysvad/EndpointsCommon/AudioModule1.h @@ -0,0 +1,312 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + AudioModule1.h + +Abstract: + + Declaration of Audio Module 1. + +--*/ + +#ifndef _SYSVAD_AUDIOMODULE1_H_ +#define _SYSVAD_AUDIOMODULE1_H_ + +#include "AudioModuleHelper.h" + +#define AUDIOMODULE1_MAJOR 0x2 +#define AUDIOMODULE1_MINOR 0X1 + +static const GUID AudioModule1Id = +{ 0x5ce55c8e, 0x84df, 0x4317, 0x98, 0xc7, 0x79, 0x2d, 0xe8, 0x33, 0x66, 0xcc }; + +enum AudioModule1_Parameter { + AudioModule1Parameter1 = 0, + AudioModule1Parameter2, + AudioModule1Parameter3 +}; + +typedef struct _AUDIOMODULE1_CUSTOM_COMMAND { + ULONG Verb; // get, set and support + AudioModule1_Parameter ParameterId; +} AUDIOMODULE1_CUSTOM_COMMAND, *PAUDIOMODULE1_CUSTOM_COMMAND; + +enum AudioModule1_Notification_Type { + AudioModule1ParameterChanged = 0, +}; + +typedef struct _AUDIOMODULE1_CUSTOM_NOTIFICATION { + ULONG Type; + union { + struct { + ULONG ParameterId; + } ParameterChanged; + }; +} AUDIOMODULE1_CUSTOM_NOTIFICATION, *PAUDIOMODULE1_CUSTOM_NOTIFICATION; + +typedef struct _AUDIOMODULE1_NOTIFICATION { + KSAUDIOMODULE_NOTIFICATION Header; + AUDIOMODULE1_CUSTOM_NOTIFICATION CustomNotification; +} AUDIOMODULE1_NOTIFICATION, *PAUDIOMODULE1_NOTIFICATION; + +typedef struct _AUDIOMODULE1_CONTEXT { + BYTE Parameter1; + ULONGLONG Parameter2; + DWORD Parameter3; + ULONG InstanceId; + AUDIOMODULE1_NOTIFICATION Notification; + PPORTCLSNOTIFICATIONS PortNotifications; +} AUDIOMODULE1_CONTEXT, *PAUDIOMODULE1_CONTEXT; + +static +BYTE AudioModule1_ValidParameter1List[] = +{ + 0, 1, 2 +}; + +static +AUDIOMODULE_PARAMETER_INFO AudioModule1_ParameterInfo[] = +{ + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION, + (ULONG)RTL_FIELD_SIZE(AUDIOMODULE1_CONTEXT, Parameter1), + VT_UI1, + AudioModule1_ValidParameter1List, + SIZEOF_ARRAY(AudioModule1_ValidParameter1List) + }, + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + 0, + (ULONG)RTL_FIELD_SIZE(AUDIOMODULE1_CONTEXT, Parameter2), + VT_UI8, + NULL, + 0 + }, + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION, + (ULONG)RTL_FIELD_SIZE(AUDIOMODULE1_CONTEXT, Parameter3), + VT_UI4, + NULL, + 0 + }, +}; + +inline +#pragma code_seg("PAGE") +NTSTATUS +AudioModule1_InitClass( + _In_ const AUDIOMODULE_DESCRIPTOR * Module, + _Inout_opt_ PVOID Context, + _In_ size_t Size, + _In_ KSAUDIOMODULE_NOTIFICATION * NotificationHeader, + _In_opt_ PPORTCLSNOTIFICATIONS PortNotifications + ) +{ + PAUDIOMODULE1_CONTEXT ctx = (PAUDIOMODULE1_CONTEXT)Context; + + UNREFERENCED_PARAMETER(Module); + + PAGED_CODE(); + + if (Context == NULL) + { + ASSERT(FALSE); // this should not happen. + return STATUS_INTERNAL_ERROR; + } + + ASSERT(Size != 0); + RtlZeroMemory(Context, Size); + + ctx->Notification.Header = *NotificationHeader; + ctx->PortNotifications = PortNotifications; + if (ctx->PortNotifications != NULL) + { + ctx->PortNotifications->AddRef(); + } + + return STATUS_SUCCESS; +} + +inline +#pragma code_seg("PAGE") +NTSTATUS +AudioModule1_InitInstance( + _In_ const AUDIOMODULE_DESCRIPTOR * Module, + _In_opt_ PVOID TemplateContext, + _Inout_opt_ PVOID Context, + _In_ size_t Size, + _In_ ULONG InstanceId + ) +{ + PAUDIOMODULE1_CONTEXT ctx = (PAUDIOMODULE1_CONTEXT)Context; + + UNREFERENCED_PARAMETER(Module); + + PAGED_CODE(); + + if (Context == NULL) + { + ASSERT(FALSE); // this should not happen. + return STATUS_INTERNAL_ERROR; + } + + ASSERT(TemplateContext != NULL); + ASSERT(Size != 0); + + RtlCopyMemory(Context, TemplateContext, Size); + + ctx->InstanceId = InstanceId; + ctx->Notification.Header.ProviderId.InstanceId = InstanceId; + if (ctx->PortNotifications != NULL) + { + ctx->PortNotifications->AddRef(); + } + + return STATUS_SUCCESS; +} + +inline +#pragma code_seg("PAGE") +VOID +AudioModule1_Cleanup( + _In_ PVOID Context + ) +{ + PAUDIOMODULE1_CONTEXT ctx = (PAUDIOMODULE1_CONTEXT)Context; + + PAGED_CODE(); + + if (Context == NULL) + { + ASSERT(FALSE); // this should not happen. + return; + } + + SAFE_RELEASE(ctx->PortNotifications); +} + +inline +#pragma code_seg("PAGE") +NTSTATUS +AudioModule1_Handler( + _Inout_opt_ PVOID Context, + _In_reads_bytes_(InBufferCb) PVOID InBuffer, + _In_ ULONG InBufferCb, + _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer, + _Inout_ ULONG * OutBufferCb + ) +{ + NTSTATUS status = STATUS_SUCCESS; + BOOL fNewValue = FALSE; + PVOID currentValue; + PVOID inBuffer = NULL; + ULONG inBufferCb = 0; + + PAUDIOMODULE1_CONTEXT ctx = (PAUDIOMODULE1_CONTEXT)Context; + AUDIOMODULE_PARAMETER_INFO * parameterInfo = NULL; + AUDIOMODULE1_CUSTOM_COMMAND * command = NULL; + + PAGED_CODE(); + + if (ctx == NULL) + { + ASSERT(FALSE); // this should not happen. + status = STATUS_INTERNAL_ERROR; + goto exit; + } + + // + // Basic parameter validation (module specific). + // + if (InBuffer == NULL || InBufferCb == 0) + { + return STATUS_INVALID_PARAMETER; + } + + if (InBufferCb < sizeof(AUDIOMODULE1_CUSTOM_COMMAND)) + { + return STATUS_INVALID_PARAMETER; + } + + command = (AUDIOMODULE1_CUSTOM_COMMAND*)InBuffer; + + // + // Validate the parameter referenced in the command. + // + switch (command->ParameterId) + { + case AudioModule1Parameter1: + currentValue = &ctx->Parameter1; + parameterInfo = &AudioModule1_ParameterInfo[AudioModule1Parameter1]; + break; + + case AudioModule1Parameter2: + currentValue = &ctx->Parameter2; + parameterInfo = &AudioModule1_ParameterInfo[AudioModule1Parameter2]; + break; + + case AudioModule1Parameter3: + currentValue = &ctx->Parameter3; + parameterInfo = &AudioModule1_ParameterInfo[AudioModule1Parameter3]; + break; + + default: + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + // + // Update input buffer ptr/size. + // + inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE1_CUSTOM_COMMAND)); + inBufferCb = InBufferCb - sizeof(AUDIOMODULE1_CUSTOM_COMMAND); + + if (inBufferCb == 0) + { + inBuffer = NULL; + } + + status = AudioModule_GenericHandler( + command->Verb, + command->ParameterId, + parameterInfo, + currentValue, + inBuffer, + inBufferCb, + OutBuffer, + OutBufferCb, + &fNewValue); + + if (!NT_SUCCESS(status)) + { + goto exit; + } + + if (fNewValue && ctx->PortNotifications && + (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION)) + { + // This logic assumes that access to this function is serialized. + ctx->Notification.CustomNotification.Type = AudioModule1ParameterChanged; + ctx->Notification.CustomNotification.ParameterChanged.ParameterId = + command->ParameterId; + + AudioModule_SendNotification(ctx->PortNotifications, + (PVOID)&ctx->Notification, + (USHORT)sizeof(ctx->Notification)); + } + + // Normalize error code. + status = STATUS_SUCCESS; + +exit: + return status; +} + +#endif // _SYSVAD_AUDIOMODULE1_H_ + + diff --git a/audio/sysvad/EndpointsCommon/AudioModule2.h b/audio/sysvad/EndpointsCommon/AudioModule2.h new file mode 100644 index 00000000..93d3fdf3 --- /dev/null +++ b/audio/sysvad/EndpointsCommon/AudioModule2.h @@ -0,0 +1,296 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + AudioModule2.h + +Abstract: + + Declaration of Audio Module 2. + +--*/ + +#ifndef _SYSVAD_AUDIOMODULE2_H_ +#define _SYSVAD_AUDIOMODULE2_H_ + +#include "AudioModuleHelper.h" + +#define AUDIOMODULE2_MAJOR 0x2 +#define AUDIOMODULE2_MINOR 0X0 + +static const GUID AudioModule2Id = +{ 0xcc2a9527, 0x19d9, 0x4784, 0x8d, 0xd4, 0x6c, 0x1f, 0xe0, 0x1e, 0x37, 0x26 }; + +enum AudioModule2_Parameter { + AudioModule2Parameter1 = 0, + AudioModule2Parameter2 +}; + +typedef struct _AUDIOMODULE2_CUSTOM_COMMAND { + ULONG Verb; // get, set and support + AudioModule2_Parameter ParameterId; +} AUDIOMODULE2_CUSTOM_COMMAND, *PAUDIOMODULE2_CUSTOM_COMMAND; + +enum AudioModule2_Notification_Type { + AudioModule2ParameterChanged = 0, +}; + +typedef struct _AUDIOMODULE2_CUSTOM_NOTIFICATION { + ULONG Type; + union { + struct { + ULONG ParameterId; + } ParameterChanged; + }; +} AUDIOMODULE2_CUSTOM_NOTIFICATION, *PAUDIOMODULE2_CUSTOM_NOTIFICATION; + +typedef struct _AUDIOMODULE2_NOTIFICATION { + KSAUDIOMODULE_NOTIFICATION Header; + AUDIOMODULE2_CUSTOM_NOTIFICATION CustomNotification; +} AUDIOMODULE2_NOTIFICATION, *PAUDIOMODULE2_NOTIFICATION; + +typedef struct _AUDIOMODULE2_CONTEXT { + ULONG Parameter1; + USHORT Parameter2; + ULONG InstanceId; + AUDIOMODULE2_NOTIFICATION Notification; + PPORTCLSNOTIFICATIONS PortNotifications; +} AUDIOMODULE2_CONTEXT, *PAUDIOMODULE2_CONTEXT; + +static +ULONG AudioModule2_ValidParameter1List[] = +{ + 1, 0xfffffffe +}; + +static +AUDIOMODULE_PARAMETER_INFO AudioModule2_ParameterInfo[] = +{ + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION, + (ULONG)RTL_FIELD_SIZE(AUDIOMODULE2_CONTEXT, Parameter1), + VT_UI4, + AudioModule2_ValidParameter1List, + SIZEOF_ARRAY(AudioModule2_ValidParameter1List) + }, + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + 0, + (ULONG)RTL_FIELD_SIZE(AUDIOMODULE2_CONTEXT, Parameter2), + VT_UI2, + NULL, + 0 + }, +}; + +inline +#pragma code_seg("PAGE") +NTSTATUS +AudioModule2_InitClass( + _In_ const AUDIOMODULE_DESCRIPTOR * Module, + _Inout_opt_ PVOID Context, + _In_ size_t Size, + _In_ KSAUDIOMODULE_NOTIFICATION * NotificationHeader, + _In_opt_ PPORTCLSNOTIFICATIONS PortNotifications + ) +{ + PAUDIOMODULE2_CONTEXT ctx = (PAUDIOMODULE2_CONTEXT)Context; + + UNREFERENCED_PARAMETER(Module); + + PAGED_CODE(); + + if (Context == NULL) + { + ASSERT(FALSE); // this should not happen. + return STATUS_INTERNAL_ERROR; + } + + ASSERT(Size != 0); + RtlZeroMemory(Context, Size); + + ctx->Notification.Header = *NotificationHeader; + ctx->PortNotifications = PortNotifications; + if (ctx->PortNotifications != NULL) + { + ctx->PortNotifications->AddRef(); + } + + return STATUS_SUCCESS; +} + +inline +#pragma code_seg("PAGE") +NTSTATUS +AudioModule2_InitInstance( + _In_ const AUDIOMODULE_DESCRIPTOR * Module, + _In_opt_ PVOID TemplateContext, + _Inout_opt_ PVOID Context, + _In_ size_t Size, + _In_ ULONG InstanceId + ) +{ + PAUDIOMODULE2_CONTEXT ctx = (PAUDIOMODULE2_CONTEXT)Context; + + UNREFERENCED_PARAMETER(Module); + + PAGED_CODE(); + + if (Context == NULL) + { + ASSERT(FALSE); // this should not happen. + return STATUS_INTERNAL_ERROR; + } + + ASSERT(TemplateContext != NULL); + ASSERT(Size != 0); + + RtlCopyMemory(Context, TemplateContext, Size); + + ctx->InstanceId = InstanceId; + ctx->Notification.Header.ProviderId.InstanceId = InstanceId; + if (ctx->PortNotifications != NULL) + { + ctx->PortNotifications->AddRef(); + } + + return STATUS_SUCCESS; +} + +inline +#pragma code_seg("PAGE") +VOID +AudioModule2_Cleanup( + _In_ PVOID Context + ) +{ + PAUDIOMODULE2_CONTEXT ctx = (PAUDIOMODULE2_CONTEXT)Context; + + PAGED_CODE(); + + if (Context == NULL) + { + ASSERT(FALSE); // this should not happen. + return; + } + + SAFE_RELEASE(ctx->PortNotifications); +} + +inline +#pragma code_seg("PAGE") +NTSTATUS +AudioModule2_Handler( + _Inout_opt_ PVOID Context, + _In_reads_bytes_(InBufferCb) PVOID InBuffer, + _In_ ULONG InBufferCb, + _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer, + _Inout_ ULONG * OutBufferCb + ) +{ + NTSTATUS status = STATUS_SUCCESS; + BOOL fNewValue = FALSE; + PVOID currentValue; + PVOID inBuffer = NULL; + ULONG inBufferCb = 0; + + PAUDIOMODULE2_CONTEXT ctx = (PAUDIOMODULE2_CONTEXT)Context; + AUDIOMODULE_PARAMETER_INFO * parameterInfo = NULL; + AUDIOMODULE2_CUSTOM_COMMAND * command = NULL; + + PAGED_CODE(); + + if (ctx == NULL) + { + ASSERT(FALSE); // this should not happen. + status = STATUS_INTERNAL_ERROR; + goto exit; + } + + // + // Basic parameter validation (module specific). + // + if (InBuffer == NULL || InBufferCb == 0) + { + return STATUS_INVALID_PARAMETER; + } + + if (InBufferCb < sizeof(AUDIOMODULE2_CUSTOM_COMMAND)) + { + return STATUS_INVALID_PARAMETER; + } + + command = (AUDIOMODULE2_CUSTOM_COMMAND*)InBuffer; + + // + // Validate the parameter referenced in the command. + // + switch (command->ParameterId) + { + case AudioModule2Parameter1: + currentValue = &ctx->Parameter1; + parameterInfo = &AudioModule2_ParameterInfo[AudioModule0Parameter1]; + break; + + case AudioModule2Parameter2: + currentValue = &ctx->Parameter2; + parameterInfo = &AudioModule2_ParameterInfo[AudioModule2Parameter2]; + break; + + default: + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + // + // Update input buffer ptr/size. + // + inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE2_CUSTOM_COMMAND)); + inBufferCb = InBufferCb - sizeof(AUDIOMODULE2_CUSTOM_COMMAND); + + if (inBufferCb == 0) + { + inBuffer = NULL; + } + + status = AudioModule_GenericHandler( + command->Verb, + command->ParameterId, + parameterInfo, + currentValue, + inBuffer, + inBufferCb, + OutBuffer, + OutBufferCb, + &fNewValue); + + if (!NT_SUCCESS(status)) + { + goto exit; + } + + if (fNewValue && ctx->PortNotifications && + (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION)) + { + // This logic assumes that access to this function is serialized. + ctx->Notification.CustomNotification.Type = AudioModule2ParameterChanged; + ctx->Notification.CustomNotification.ParameterChanged.ParameterId = + command->ParameterId; + + AudioModule_SendNotification(ctx->PortNotifications, + (PVOID)&ctx->Notification, + (USHORT)sizeof(ctx->Notification)); + } + + // Normalize error code. + status = STATUS_SUCCESS; + +exit: + return status; +} + +#endif // _SYSVAD_AUDIOMODULE2_H_ + diff --git a/audio/sysvad/EndpointsCommon/AudioModuleHelper.cpp b/audio/sysvad/EndpointsCommon/AudioModuleHelper.cpp new file mode 100644 index 00000000..f93c2bff --- /dev/null +++ b/audio/sysvad/EndpointsCommon/AudioModuleHelper.cpp @@ -0,0 +1,644 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + AudioModuleHelper.cpp + +Abstract: + + Simple helper for Audio Modules logic. + +--*/ + +#pragma warning (disable : 4127) + +#include <sysvad.h> +#include <limits.h> +#include <ntintsafe.h> +#include "SysVadShared.h" +#include "AudioModuleHelper.h" + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +AudioModule_GenericHandler_BasicSupport( + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _Out_writes_bytes_opt_(*BufferCb) PVOID Buffer, + _Inout_ ULONG * BufferCb + ) +{ + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG cbFullProperty = 0; + ULONG cbDataListSize = 0; + + DPF_ENTER(("[AudioModule_GenericHandler_BasicSupport]")); + + PAGED_CODE(); + + ASSERT(ParameterInfo); + ASSERT(BufferCb); + + // + // Compute total size of property. + // + ntStatus = RtlULongMult(ParameterInfo->Size, + ParameterInfo->ValidSetCount, + &cbDataListSize); + if (!NT_SUCCESS(ntStatus)) + { + ASSERT(FALSE); + *BufferCb = 0; + return ntStatus; + } + + ntStatus = RtlULongAdd(cbDataListSize, + (ULONG)(sizeof(KSPROPERTY_DESCRIPTION) + + sizeof(KSPROPERTY_MEMBERSHEADER)), + &cbFullProperty); + + if (!NT_SUCCESS(ntStatus)) + { + ASSERT(FALSE); + *BufferCb = 0; + return ntStatus; + } + + // + // Return the info the caller is asking for. + // + if (*BufferCb == 0) + { + // caller wants to know the size of the buffer. + *BufferCb = cbFullProperty; + ntStatus = STATUS_BUFFER_OVERFLOW; + } + else if (*BufferCb >= (sizeof(KSPROPERTY_DESCRIPTION))) + { + PKSPROPERTY_DESCRIPTION propDesc = PKSPROPERTY_DESCRIPTION(Buffer); + + propDesc->AccessFlags = ParameterInfo->AccessFlags; + propDesc->DescriptionSize = cbFullProperty; + propDesc->PropTypeSet.Set = KSPROPTYPESETID_General; + propDesc->PropTypeSet.Id = ParameterInfo->VtType; + propDesc->PropTypeSet.Flags = 0; + propDesc->MembersListCount = 1; + propDesc->Reserved = 0; + + // if return buffer can also hold a list description, return it too + if(*BufferCb >= cbFullProperty) + { + // fill in the members header + PKSPROPERTY_MEMBERSHEADER members = + PKSPROPERTY_MEMBERSHEADER(propDesc + 1); + + members->MembersFlags = KSPROPERTY_MEMBER_VALUES; + members->MembersSize = ParameterInfo->Size; + members->MembersCount = ParameterInfo->ValidSetCount; + members->Flags = KSPROPERTY_MEMBER_FLAG_DEFAULT; + + // fill in valid array. + BYTE* array = (BYTE*)(members + 1); + + RtlCopyMemory(array, ParameterInfo->ValidSet, cbDataListSize); + + // set the return value size + *BufferCb = cbFullProperty; + } + else + { + *BufferCb = sizeof(KSPROPERTY_DESCRIPTION); + } + } + else if(*BufferCb >= sizeof(ULONG)) + { + // if return buffer can hold a ULONG, return the access flags + PULONG accessFlags = PULONG(Buffer); + + *BufferCb = sizeof(ULONG); + *accessFlags = ParameterInfo->AccessFlags; + } + else + { + *BufferCb = 0; + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + + return ntStatus; +} // PropertyHandlerBasicSupportVolume + +//============================================================================= +#pragma code_seg("PAGE") +BOOLEAN +IsAudioModuleParameterValid( + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _In_reads_bytes_opt_(BufferCb) PVOID Buffer, + _In_ ULONG BufferCb + ) +{ + PAGED_CODE(); + + DPF_ENTER(("[IsAudioModuleParameterValid]")); + + ULONG i = 0; + ULONG j = 0; + BOOLEAN validParam = FALSE; + + // + // Validate buffer ptr and size. + // + if (Buffer == NULL || BufferCb == 0) + { + validParam = FALSE; + goto exit; + } + + // + // Check its size. + // + if (BufferCb < ParameterInfo->Size) + { + validParam = FALSE; + goto exit; + } + + // + // Check the valid list. + // + if (ParameterInfo->ValidSet && ParameterInfo->ValidSetCount) + { + BYTE* buffer = (BYTE*)ParameterInfo->ValidSet; + BYTE* pattern = (BYTE*)Buffer; + + // + // Scan the valid list. + // + for (i = 0; i < ParameterInfo->ValidSetCount; ++i) + { + for (j=0; j < ParameterInfo->Size; ++j) + { + if (buffer[j] != pattern[j]) + { + break; + } + } + + if (j == ParameterInfo->Size) + { + // got a match. + break; + } + + buffer += ParameterInfo->Size; + } + + // + // If end of list, we didn't find the value. + // + if (i == ParameterInfo->ValidSetCount) + { + validParam = FALSE; + goto exit; + } + } + else + { + // + // Negative-testing support. Fail request if value is -1. + // + BYTE* buffer = (BYTE*)Buffer; + + for (i = 0; i < ParameterInfo->Size; ++i) + { + if (buffer[i] != 0xFF) + { + break; + } + } + + // + // If value is -1, return error. + // + if (i == ParameterInfo->Size) + { + validParam = FALSE; + goto exit; + } + } + + validParam = TRUE; + +exit: + return validParam; +} + +//============================================================================= +#pragma code_seg("PAGE") +AUDIOMODULE * +AudioModule_FindModuleInList( + _In_ AUDIOMODULE * AudioModules, + _In_ ULONG AudioModuleCount, + _In_ GUID * ClassId, + _In_ ULONG InstanceId + ) +{ + for (ULONG i=0; i<AudioModuleCount; ++i) + { + AUDIOMODULE * module = &AudioModules[i]; + + if (IsEqualGUIDAligned(*(module->Descriptor->ClassId), *ClassId) && + module->InstanceId == InstanceId) + { + return module; + } + } + + return NULL; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +AudioModule_GenericHandler( + _In_ ULONG Verb, + _In_ ULONG ParameterId, + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _Inout_updates_bytes_(ParameterInfo->Size) PVOID CurrentValue, + _In_reads_bytes_opt_(InBufferCb) PVOID InBuffer, + _In_ ULONG InBufferCb, + _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer, + _Inout_ ULONG * OutBufferCb, + _In_ BOOL * ParameterChanged + ) +{ + PAGED_CODE(); + + DPF_ENTER(("[AudioModule_GenericHandler]")); + + UNREFERENCED_PARAMETER(ParameterId); + + *ParameterChanged = FALSE; + + // Handle KSPROPERTY_TYPE_BASICSUPPORT query + if (Verb & KSPROPERTY_TYPE_BASICSUPPORT) + { + return AudioModule_GenericHandler_BasicSupport(ParameterInfo, OutBuffer, OutBufferCb); + } + + ULONG cbMinSize = ParameterInfo->Size; + + if (Verb & KSPROPERTY_TYPE_GET) + { + // Verify module parameter supports 'get'. + if (!(ParameterInfo->AccessFlags & KSPROPERTY_TYPE_GET)) + { + *OutBufferCb = 0; + return STATUS_INVALID_DEVICE_REQUEST; + } + + // Verify value size + if (*OutBufferCb == 0) + { + *OutBufferCb = cbMinSize; + return STATUS_BUFFER_OVERFLOW; + } + if (*OutBufferCb < cbMinSize) + { + *OutBufferCb = 0; + return STATUS_BUFFER_TOO_SMALL; + } + else + { + RtlCopyMemory(OutBuffer, CurrentValue, ParameterInfo->Size); + *OutBufferCb = cbMinSize; + return STATUS_SUCCESS; + } + } + else if (Verb & KSPROPERTY_TYPE_SET) + { + *OutBufferCb = 0; + + // Verify it is a write prop. + if (!(ParameterInfo->AccessFlags & KSPROPERTY_TYPE_SET)) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + + // Validate parameter. + if (!IsAudioModuleParameterValid(ParameterInfo, InBuffer, InBufferCb)) + { + return STATUS_INVALID_PARAMETER; + } + + if (ParameterInfo->Size != + RtlCompareMemory(CurrentValue, InBuffer, ParameterInfo->Size)) + { + RtlCopyMemory(CurrentValue, InBuffer, ParameterInfo->Size); + *ParameterChanged = TRUE; + } + + return STATUS_SUCCESS; + } + + return STATUS_INVALID_DEVICE_REQUEST; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +AudioModule_GenericHandler_ModulesListRequest( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ AUDIOMODULE * AudioModules, + _In_ ULONG AudioModuleCount + ) +{ + NTSTATUS ntStatus; + + // This specific APO->driver communication example is mainly added to show how this communication is done. + // The module list only lives on the wave filter and it can have modules that are for all pins and some that + // are only on specific pins. + + PAGED_CODE(); + + DPF_ENTER(("[AudioModule_PropertyHandlerModulesListRequest]")); + + // + // Note: return an empty list when no modules are present. + // + + // Handle KSPROPERTY_TYPE_BASICSUPPORT query + if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) + { + ULONG flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT; + return PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL); + } + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) + { + PKSMULTIPLE_ITEM ksMultipleItem; + ULONG cbMinSize = 0; + PKSAUDIOMODULE_DESCRIPTOR modules = NULL; + + // + // Compute min value size requirements + // + ntStatus = RtlULongMult(AudioModuleCount, + (ULONG)sizeof(KSAUDIOMODULE_DESCRIPTOR), + &cbMinSize); + if (!NT_SUCCESS(ntStatus)) + { + ASSERT(FALSE); + return ntStatus; + } + + ntStatus = RtlULongAdd(cbMinSize, sizeof(KSMULTIPLE_ITEM), &cbMinSize); + if (!NT_SUCCESS(ntStatus)) + { + ASSERT(FALSE); + return ntStatus; + } + + // Verify value size + if (PropertyRequest->ValueSize == 0) + { + PropertyRequest->ValueSize = cbMinSize; + return STATUS_BUFFER_OVERFLOW; + } + if (PropertyRequest->ValueSize < cbMinSize) + { + return STATUS_BUFFER_TOO_SMALL; + } + + // Value is a KSMULTIPLE_ITEM followed by list of modules. + ksMultipleItem = (PKSMULTIPLE_ITEM)PropertyRequest->Value; + modules = (PKSAUDIOMODULE_DESCRIPTOR)(ksMultipleItem + 1); + + // Copy modules + for (ULONG i = 0; i<AudioModuleCount; ++i, ++modules) + { + const AUDIOMODULE_DESCRIPTOR * moduleDesc = AudioModules[i].Descriptor; + + modules->ClassId = *moduleDesc->ClassId; + modules->InstanceId = AudioModules[i].InstanceId; + + modules->VersionMajor = moduleDesc->VersionMajor; + modules->VersionMinor = moduleDesc->VersionMinor; + + + RtlStringCchCopyW(modules->Name, + AUDIOMODULE_MAX_NAME_CCH_SIZE, // includes null char + moduleDesc->Name); + } + + // Miniport filled in the list of modules. Fill in the KSMULTIPLE_ITEM header. + ksMultipleItem->Size = cbMinSize; + ksMultipleItem->Count = AudioModuleCount; + + PropertyRequest->ValueSize = ksMultipleItem->Size; + return STATUS_SUCCESS; + } + + return STATUS_INVALID_DEVICE_REQUEST; +} // AudioModule_GenericHandler_ModulesListRequest + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +AudioModule_GenericHandler_ModuleCommand( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ AUDIOMODULE * AudioModules, + _In_ ULONG AudioModuleCount + ) +{ + AUDIOMODULE * module = NULL; + + PAGED_CODE(); + + DPF_ENTER(("[AudioModule_GenericHandler_ModuleCommand]")); + + // + // Basic parameter validation. + // + if (AudioModules == NULL || AudioModuleCount == 0) + { + // endpoint/stream doesn't have any modules. + return STATUS_INVALID_DEVICE_REQUEST; + } + + // Verify instance data stores at least KSAUDIOMODULE_PROPERTY fields + // beyond KSPPROPERTY. + if (PropertyRequest->InstanceSize < (sizeof(KSAUDIOMODULE_PROPERTY) - + RTL_SIZEOF_THROUGH_FIELD(KSAUDIOMODULE_PROPERTY, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + // Extract property descriptor from property request instance data + PKSAUDIOMODULE_PROPERTY moduleProperty = CONTAINING_RECORD( + PropertyRequest->Instance, KSAUDIOMODULE_PROPERTY, ClassId); + + // Get a ptr to the module. + module = AudioModule_FindModuleInList(AudioModules, + AudioModuleCount, + &moduleProperty->ClassId, + moduleProperty->InstanceId); + // + // Invoke the handler. + // + if (module == NULL || + module->Descriptor == NULL || + module->Descriptor->Handler == NULL) + { + return STATUS_INVALID_PARAMETER; + } + + // Handle KSPROPERTY_TYPE_BASICSUPPORT query + if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) + { + ULONG flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT; + + return PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL); + } + + // Only KS-get is supported. + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) + { + NTSTATUS status; + ULONG inBufferCb = 0; + ULONG outBufferCb = 0; + PVOID inBuffer = NULL; + PVOID outBuffer = NULL; + + outBufferCb = PropertyRequest->ValueSize; + outBuffer = PropertyRequest->Value; + + ASSERT((outBufferCb != 0 && outBuffer != NULL) || + (outBufferCb == 0 && outBuffer == NULL)); + + // this is guaranteed to work b/c of the validation above. + inBufferCb = PropertyRequest->InstanceSize + + sizeof(KSPROPERTY) - + sizeof(KSAUDIOMODULE_PROPERTY); + + if (inBufferCb != 0) + { + inBuffer = (PVOID)(moduleProperty+1); + } + + status = module->Descriptor->Handler(module->Context, + inBuffer, + inBufferCb, + outBuffer, + &outBufferCb); + // + // Set the size of the returned output data, or in the case of + // buffer overflow error, return the expected buffer length. + // + PropertyRequest->ValueSize = outBufferCb; + return status; + } + + PropertyRequest->ValueSize = 0; + return STATUS_INVALID_DEVICE_REQUEST; +} // AudioModule_GenericHandler_ModuleCommand + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +AudioModule_GenericHandler_ModuleNotificationDeviceId( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ const GUID * NotificationDeviceId + ) +{ + PAGED_CODE(); + + DPF_ENTER(("[AudioModule_GenericHandler_ModuleNotificationDeviceId]")); + + // + // Basic parameter validation. + // + if (NotificationDeviceId == NULL) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + + // Handle KSPROPERTY_TYPE_BASICSUPPORT query + if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) + { + ULONG flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT; + + return PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL); + } + + ULONG cbMinSize = sizeof(GUID); + GUID *dataPtr = static_cast<GUID*>(PropertyRequest->Value); + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) + { + // Verify value size + if (PropertyRequest->ValueSize == 0) + { + PropertyRequest->ValueSize = cbMinSize; + return STATUS_BUFFER_OVERFLOW; + } + if (PropertyRequest->ValueSize < cbMinSize) + { + return STATUS_BUFFER_TOO_SMALL; + } + else + { + *dataPtr = *NotificationDeviceId; + PropertyRequest->ValueSize = cbMinSize; + + return STATUS_SUCCESS; + } + } + + return STATUS_INVALID_DEVICE_REQUEST; +} + +//============================================================================= +#pragma code_seg("PAGE") +VOID +AudioModule_SendNotification( + _In_ PPORTCLSNOTIFICATIONS PortNotifications, + _In_ PVOID NotificationBuffer, + _In_ USHORT NotificationBufferCb + ) +{ + NTSTATUS status = STATUS_SUCCESS; + PPCNOTIFICATION_BUFFER buffer = NULL; + + PAGED_CODE(); + + DPF_ENTER(("[AudioModule_SendNotification]")); + + // Allocate a notification buffer. + status = PortNotifications->AllocNotificationBuffer(PagedPool, + NotificationBufferCb, + &buffer); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + // Notification buffer is only guaranteed to be LONG aligned, + // it is received as ULONGLONG aligned on the receiving end. + RtlCopyMemory(buffer, NotificationBuffer, NotificationBufferCb); + + // + // Generate notification (async). + // + PortNotifications->SendNotification(&KSNOTIFICATIONID_AudioModule, buffer); + +exit: + if (buffer != NULL) + { + // Free notification buffer. + PortNotifications->FreeNotificationBuffer(buffer); + buffer = NULL; + } +} + + diff --git a/audio/sysvad/EndpointsCommon/AudioModuleHelper.h b/audio/sysvad/EndpointsCommon/AudioModuleHelper.h new file mode 100644 index 00000000..fa7a2c23 --- /dev/null +++ b/audio/sysvad/EndpointsCommon/AudioModuleHelper.h @@ -0,0 +1,95 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + AudioModuleHelper.h + +Abstract: + + Simple helper for Audio Modules logic. + +--*/ + +#ifndef _SYSVAD_AUDIOMODULEHELPER_H_ +#define _SYSVAD_AUDIOMODULEHELPER_H_ + +// +// Module helper functions. +// +#pragma code_seg("PAGE") +NTSTATUS +AudioModule_GenericHandler_BasicSupport( + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _Out_writes_bytes_opt_(*BufferCb) PVOID Buffer, + _Inout_ ULONG * BufferCb + ); + +#pragma code_seg("PAGE") +BOOLEAN +IsAudioModuleParameterValid( + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _In_reads_bytes_opt_(BufferCb) PVOID Buffer, + _In_ ULONG BufferCb + ); + +#pragma code_seg("PAGE") +AUDIOMODULE * +AudioModule_FindModuleInList( + _In_ AUDIOMODULE * AudioModules, + _In_ ULONG AudioModuleCount, + _In_ GUID * ClassId, + _In_ ULONG InstanceId + ); + +#pragma code_seg("PAGE") +NTSTATUS +AudioModule_GenericHandler( + _In_ ULONG Verb, + _In_ ULONG ParameterId, + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _Inout_updates_bytes_(ParameterInfo->Size) PVOID CurrentValue, + _In_reads_bytes_opt_(InBufferCb) PVOID InBuffer, + _In_ ULONG InBufferCb, + _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer, + _Inout_ ULONG * OutBufferCb, + _In_ BOOL * ParameterChanged + ); + +// +// Miniport/Stream helper functions. +// +#pragma code_seg("PAGE") +NTSTATUS +AudioModule_GenericHandler_ModulesListRequest( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ AUDIOMODULE * AudioModules, + _In_ ULONG AudioModuleCount + ); + +#pragma code_seg("PAGE") +NTSTATUS +AudioModule_GenericHandler_ModuleCommand( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ AUDIOMODULE * AudioModules, + _In_ ULONG AudioModuleCount + ); + +#pragma code_seg("PAGE") +NTSTATUS +AudioModule_GenericHandler_ModuleNotificationDeviceId( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ const GUID * NotificationDeviceId + ); + +#pragma code_seg("PAGE") +VOID +AudioModule_SendNotification( + _In_ PPORTCLSNOTIFICATIONS PortNotifications, + _In_ PVOID NotificationBuffer, + _In_ USHORT NotificationBufferCb + ); +#endif // _SYSVAD_AUDIOMODULEHELPER_H_ + + diff --git a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj index 1956d106..4fb3fda6 100644 --- a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj +++ b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj @@ -157,6 +157,7 @@ </Midl> </ItemDefinitionGroup> <ItemGroup> + <ClCompile Include="AudioModuleHelper.cpp" /> <ClCompile Include="bthhfpmictopo.cpp" /> <ClCompile Include="bthhfpminwavert.cpp" /> <ClCompile Include="bthhfpspeakertopo.cpp" /> diff --git a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj.Filters b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj.Filters new file mode 100644 index 00000000..0579c299 --- /dev/null +++ b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj.Filters @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{CDBBEDA3-98E9-4C7A-BDB1-25EC47D0B087}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{FA3DF57E-BA19-4783-831B-CF9D4D594F70}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{CB830E4F-01DA-4D35-9789-E7DB0D02A79C}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{49F92783-3B39-4D0C-A153-8C346F754749}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="AudioModuleHelper.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="bthhfpmictopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="bthhfpminwavert.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="bthhfpspeakertopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="bthhfptopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="micarraytopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="MiniportAudioEngineNode.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="MiniportStreamAudioEngineNode.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="mintopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="minwavert.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="minwavertstream.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="speakerhptopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="speakertopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp b/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp index a210f77b..0f772155 100644 --- a/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp +++ b/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp @@ -996,3 +996,4 @@ NTSTATUS CMiniportWaveRTStream::SetStreamCurrentWritePositionForLastBuffer(_In_ return ntStatus; } + diff --git a/audio/sysvad/EndpointsCommon/minwavert.cpp b/audio/sysvad/EndpointsCommon/minwavert.cpp index 53fcfac2..35923619 100644 --- a/audio/sysvad/EndpointsCommon/minwavert.cpp +++ b/audio/sysvad/EndpointsCommon/minwavert.cpp @@ -22,6 +22,8 @@ Abstract: #include "minwavert.h" #include "minwavertstream.h" #include "IHVPrivatePropertySet.h" +#include "AudioModuleHelper.h" + //============================================================================= // CMiniportWaveRT @@ -37,7 +39,7 @@ CreateMiniportWaveRTSYSVAD _In_opt_ PUNKNOWN UnknownOuter, _When_((PoolType & NonPagedPoolMustSucceed) != 0, __drv_reportError("Must succeed pool allocations are forbidden. " - "Allocation failures cause a system crash")) + "Allocation failures cause a system crash")) _In_ POOL_TYPE PoolType, _In_ PUNKNOWN UnknownAdapter, _In_opt_ PVOID DeviceContext, @@ -161,6 +163,12 @@ Return Value: m_pPortEvents = NULL; } + if (m_pPortClsNotifications) + { + m_pPortClsNotifications->Release(); + m_pPortClsNotifications = NULL; + } + if (m_SystemStreams) { ExFreePoolWithTag( m_SystemStreams, MINWAVERT_POOLTAG ); @@ -178,7 +186,13 @@ Return Value: ExFreePoolWithTag( m_LoopbackStreams, MINWAVERT_POOLTAG ); m_LoopbackStreams = NULL; } - + + if (m_pAudioModules) + { + FreeStreamAudioModules(m_pAudioModules, GetAudioModuleListCount()); + m_pAudioModules = NULL; + } + #ifdef SYSVAD_BTH_BYPASS if (IsBthHfpDevice()) { @@ -392,6 +406,80 @@ Return Value: m_LoopbackProtection = CONSTRICTOR_OPTION_DISABLE; RtlZeroMemory(&m_MixDrmRights, sizeof(m_MixDrmRights)); + // + // For port notification support. + // + if (!NT_SUCCESS(Port_->QueryInterface(IID_IPortClsNotifications, (PVOID *)&m_pPortClsNotifications))) + { + m_pPortClsNotifications = NULL; + } + + // + // Init all the modules associated to this miniport. + // + ULONG cModules = GetAudioModuleListCount(); + if (cModules) + { + // + // Module list size. + // + size = cModules * sizeof(AUDIOMODULE); + m_pAudioModules = (AUDIOMODULE *)ExAllocatePoolWithTag(NonPagedPoolNx, size, MINWAVERT_POOLTAG); + if (m_pAudioModules == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + RtlZeroMemory(m_pAudioModules, size); + + for (ULONG i=0; i<cModules; ++i) + { + PAUDIOMODULE_DESCRIPTOR moduleDesc = &m_pMiniportPair->ModuleList[i]; + + // + // Init run-time module element. + // + m_pAudioModules[i].Descriptor = moduleDesc; + m_pAudioModules[i].Context = NULL; + m_pAudioModules[i].InstanceId = moduleDesc->InstanceId; + m_pAudioModules[i].Enabled = TRUE; + // + // Module context size. + // + size = moduleDesc->ContextSize; + if (size) + { + m_pAudioModules[i].Context = + ExAllocatePoolWithTag(NonPagedPoolNx, size, MINWAVERT_POOLTAG); + + if (m_pAudioModules[i].Context == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + RtlZeroMemory(m_pAudioModules[i].Context, size); + } + + + if (moduleDesc->InitClass) + { + KSAUDIOMODULE_NOTIFICATION NotificationHeader; + NotificationHeader.ProviderId.DeviceId = *GetAudioModuleNotificationDeviceId(); + NotificationHeader.ProviderId.ClassId = *moduleDesc->ClassId; + NotificationHeader.ProviderId.InstanceId = moduleDesc->InstanceId; + + ntStatus = moduleDesc->InitClass(moduleDesc, + m_pAudioModules[i].Context, + size, + &NotificationHeader, + m_pPortClsNotifications); + if (!NT_SUCCESS(ntStatus)) + { + ASSERT(FALSE); + return ntStatus; + } + } + } + } + // // Init the audio-engine used by the render devices. // @@ -1294,6 +1382,63 @@ CMiniportWaveRT::PropertyHandlerProposedFormat return ntStatus; } // PropertyHandlerProposedFormat +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CMiniportWaveRT::PropertyHandlerModulesListRequest +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +{ + // This specific APO->driver communication example is mainly added to show how this communication is done. + // The module list only lives on the wave filter and it can have modules that are for all pins and some that + // are only on specific pins. + + PAGED_CODE(); + + DPF_ENTER(("[CMiniportWaveRT::PropertyHandlerModulesListRequest]")); + + return AudioModule_GenericHandler_ModulesListRequest( + PropertyRequest, + GetAudioModuleList(), + GetAudioModuleListCount()); +} // PropertyHandlerModulesListRequest + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CMiniportWaveRT::PropertyHandlerModuleCommand +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +{ + PAGED_CODE(); + + DPF_ENTER(("[CMiniportWaveRT::PropertyHandlerModuleCommand]")); + + return AudioModule_GenericHandler_ModuleCommand( + PropertyRequest, + GetAudioModuleList(), + GetAudioModuleListCount()); +} // PropertyHandlerModuleCommand + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CMiniportWaveRT::PropertyHandlerModuleNotificationDeviceId +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +{ + PAGED_CODE(); + + DPF_ENTER(("[CMiniportWaveRT::PropertyHandlerModuleNotificationDeviceId]")); + + return AudioModule_GenericHandler_ModuleNotificationDeviceId( + PropertyRequest, + GetAudioModuleNotificationDeviceId()); +} // PropertyHandlerModuleNotificationDeviceId + //============================================================================= #pragma code_seg("PAGE") @@ -1677,6 +1822,203 @@ Return Value: //============================================================================= #pragma code_seg("PAGE") +NTSTATUS +CMiniportWaveRT::AllocStreamAudioModules +( + _In_ const GUID * SignalProcessingMode, + _Out_ AUDIOMODULE ** ppAudioModules, + _Out_ ULONG * pAudioModuleCount +) +{ + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_STATE; + AUDIOMODULE * pAudioModules = NULL; + ULONG cModules = 0; + ULONG i, j; + size_t size; + + PAGED_CODE(); + + // + // Init out parameters. + // + *ppAudioModules = NULL; + *pAudioModuleCount = 0; + + // + // Nothing to do if there are no modules. + // + if (m_pAudioModules == NULL) + { + ntStatus = STATUS_SUCCESS; + goto exit; + } + + // + // Find the # of modules associated with this stream. + // + for (i=0; i<GetAudioModuleListCount(); ++i) + { + const AUDIOMODULE_DESCRIPTOR * moduleDesc = m_pAudioModules[i].Descriptor; + + if (IsEqualGUIDAligned(*moduleDesc->ProcessingMode, *SignalProcessingMode) || + IsEqualGUIDAligned(*moduleDesc->ProcessingMode, NULL_GUID)) + { + cModules++; + } + } + + // + // All done if module count is zero. + // + if (cModules == 0) + { + ntStatus = STATUS_SUCCESS; + goto exit; + } + + // + // Alloc modules infrastructure. + // + size = cModules * sizeof(AUDIOMODULE); +#pragma prefast(suppress:__WARNING_MEMORY_LEAK,"No leaking, stream obj dtor calls FreeStreamAudioModules") + pAudioModules = (AUDIOMODULE *)ExAllocatePoolWithTag(NonPagedPoolNx, size, MINWAVERT_POOLTAG); + if (pAudioModules == NULL) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + RtlZeroMemory(pAudioModules, size); + + for (i=0, j=0; i<GetAudioModuleListCount() && j<cModules; ++i) + { + const AUDIOMODULE_DESCRIPTOR * moduleDesc = m_pAudioModules[i].Descriptor; + + if (IsEqualGUIDAligned(*moduleDesc->ProcessingMode, *SignalProcessingMode) || + IsEqualGUIDAligned(*moduleDesc->ProcessingMode, NULL_GUID)) + { + ULONG CfgInstanceId; + + // + // Init run-time module element. + // + pAudioModules[j].Descriptor = moduleDesc; + pAudioModules[j].Context = NULL; + + // + // Create a unique InstanceId for this module instance. + // This sample uses 24bits index which wraps around after 16M + // module instances for a specific class ID/Class config id. + // A real driver should reuse instance ids of deleted module + // instances, i.e., the driver should use a mapping between + // index <--> module info. + // + CfgInstanceId = InterlockedIncrement((LONG*)&m_pAudioModules[i].NextCfgInstanceId); + + pAudioModules[j].InstanceId = + AUDIOMODULE_INSTANCE_ID(AUDIOMODULE_GET_CLASSCFGID(m_pAudioModules[i].InstanceId), + CfgInstanceId); + + pAudioModules[j].Enabled = m_pAudioModules[i].Enabled; + + // + // Alloc context for module instance. + // + size = moduleDesc->ContextSize; + if (size) + { +#pragma prefast(suppress:__WARNING_MEMORY_LEAK,"No leaking, stream obj dtor calls FreeStreamAudioModules") + pAudioModules[j].Context = + ExAllocatePoolWithTag(NonPagedPoolNx, size, MINWAVERT_POOLTAG); + + if (pAudioModules[j].Context == NULL) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + RtlZeroMemory(pAudioModules[j].Context, size); + } + + // + // Init this module instance. + // + if (moduleDesc->InitInstance) + { + ntStatus = moduleDesc->InitInstance(moduleDesc, + m_pAudioModules[i].Context, + pAudioModules[j].Context, + size, + pAudioModules[j].InstanceId); + if (!NT_SUCCESS(ntStatus)) + { + ASSERT(FALSE); + goto exit; + } + } + + // + // Update stream module array index. + // + j++; + } + } + + // + // Return the list of modules. + // + *ppAudioModules = pAudioModules; + *pAudioModuleCount = cModules; + + ntStatus = STATUS_SUCCESS; + +exit: + + if (!NT_SUCCESS(ntStatus)) + { + if (pAudioModules != NULL) + { + FreeStreamAudioModules(pAudioModules, cModules); + pAudioModules = NULL; + cModules = 0; + } + } + + return ntStatus; +} + +#pragma code_seg("PAGE") +VOID +CMiniportWaveRT::FreeStreamAudioModules +( + _In_ AUDIOMODULE * pAudioModules, + _In_ ULONG AudioModuleCount +) +{ + PAGED_CODE(); + + if (pAudioModules != NULL) + { + ASSERT(AudioModuleCount); + + for (ULONG i=0; i<AudioModuleCount; ++i) + { + if (pAudioModules[i].Context) + { + if (pAudioModules[i].Descriptor->Cleanup) + { + pAudioModules[i].Descriptor->Cleanup(pAudioModules[i].Context); + } + + ExFreePoolWithTag(pAudioModules[i].Context, MINWAVERT_POOLTAG); + pAudioModules[i].Context = NULL; + } + } + + ExFreePoolWithTag(pAudioModules, MINWAVERT_POOLTAG); + } +} + +//============================================================================= +#pragma code_seg("PAGE") DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorSupportedPatterns) { @@ -1937,6 +2279,24 @@ Return Value: DPF(D_TERSE, ("[PropertyHandler_WaveFilter: Invalid Device Request]")); } } + else if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_AudioModule)) + { + switch (PropertyRequest->PropertyItem->Id) + { + case KSPROPERTY_AUDIOMODULE_DESCRIPTORS: + ntStatus = pWaveHelper->PropertyHandlerModulesListRequest(PropertyRequest); + break; + case KSPROPERTY_AUDIOMODULE_COMMAND: + ntStatus = pWaveHelper->PropertyHandlerModuleCommand(PropertyRequest); + break; + case KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID: + ntStatus = pWaveHelper->PropertyHandlerModuleNotificationDeviceId(PropertyRequest); + break; + + default: + DPF(D_TERSE, ("[PropertyHandler_WaveFilter: Invalid Device Request]")); + } + } else if ((pWaveHelper->m_DeviceType == eHdmiRenderDevice || pWaveHelper->m_DeviceType == eCellularDevice || pWaveHelper->m_DeviceType == eHandsetSpeakerDevice) && @@ -2061,6 +2421,69 @@ PropertyHandler_OffloadPin return ntStatus; } +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_GenericPin +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +{ + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + CMiniportWaveRT* pWave = NULL; + CMiniportWaveRTStream * pStream = NULL; + + PAGED_CODE(); + + if (PropertyRequest->MajorTarget == NULL || + PropertyRequest->MinorTarget == NULL) + { + ntStatus = STATUS_INVALID_PARAMETER; + goto exit; + } + + // + // Get a ref to the miniport. + // + pWave = MajorTarget_to_Obj(PropertyRequest->MajorTarget); + pWave->AddRef(); + + // + // Get a ref to the stream. + // + pStream = MinorTarget_to_Obj(PropertyRequest->MinorTarget); + pStream->AddRef(); + + // + // Invoke appropriate handle. + // + if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_AudioModule)) + { + switch (PropertyRequest->PropertyItem->Id) + { + case KSPROPERTY_AUDIOMODULE_DESCRIPTORS: + ntStatus = pStream->PropertyHandlerModulesListRequest(PropertyRequest); + break; + case KSPROPERTY_AUDIOMODULE_COMMAND: + ntStatus = pStream->PropertyHandlerModuleCommand(PropertyRequest); + break; + case KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID: + // Filter handles this prop. + ntStatus = pWave->PropertyHandlerModuleNotificationDeviceId(PropertyRequest); + break; + + default: + DPF(D_TERSE, ("[PropertyHandler_GenericPin: Invalid Device Request]")); + } + } + +exit: + + SAFE_RELEASE(pStream); + SAFE_RELEASE(pWave); + + return ntStatus; +} // ISSUE-2014/10/20 Add synchronization mechanism throughout this class // ISSUE-2014/10/20 Add comment headers and commenting throughout diff --git a/audio/sysvad/EndpointsCommon/minwavert.h b/audio/sysvad/EndpointsCommon/minwavert.h index 4660cfa1..da31f172 100644 --- a/audio/sysvad/EndpointsCommon/minwavert.h +++ b/audio/sysvad/EndpointsCommon/minwavert.h @@ -148,11 +148,14 @@ private: #endif // SYSVAD_BTH_BYPASS }; + AUDIOMODULE * m_pAudioModules; + protected: PADAPTERCOMMON m_pAdapterCommon; ULONG m_DeviceFlags; eDeviceType m_DeviceType; PPORTEVENTS m_pPortEvents; + PPORTCLSNOTIFICATIONS m_pPortClsNotifications; PENDPOINT_MINIPAIR m_pMiniportPair; @@ -231,7 +234,9 @@ public: m_DeviceFormatsAndModes(MiniportPair->PinDeviceFormatsAndModes), m_DeviceFormatsAndModesCount(MiniportPair->PinDeviceFormatsAndModesCount), m_DeviceFlags(MiniportPair->DeviceFlags), - m_pMiniportPair(MiniportPair) + m_pMiniportPair(MiniportPair), + m_pAudioModules(NULL), + m_pPortClsNotifications(NULL) { PAGED_CODE(); @@ -266,7 +271,6 @@ public: } } - #ifdef SYSVAD_BTH_BYPASS if (IsBthHfpDevice()) { @@ -316,6 +320,22 @@ public: ( _In_ PPCPROPERTY_REQUEST PropertyRequest ); + + NTSTATUS PropertyHandlerModulesListRequest + ( + _In_ PPCPROPERTY_REQUEST PropertyRequest + ); + + NTSTATUS PropertyHandlerModuleCommand + ( + _In_ PPCPROPERTY_REQUEST PropertyRequest + ); + + NTSTATUS PropertyHandlerModuleNotificationDeviceId + ( + _In_ PPCPROPERTY_REQUEST PropertyRequest + ); + PADAPTERCOMMON GetAdapterCommObj() { @@ -629,8 +649,70 @@ protected: ASSERT(!IsCellularDevice()); return KSPIN_WAVE_RENDER_SINK_OFFLOAD; } + #pragma code_seg() + ULONG + GetAudioModuleDescriptorListCount() + { + return m_pMiniportPair->ModuleListCount; + } + + const PAUDIOMODULE_DESCRIPTOR + GetAudioModuleDescriptor( + _In_ ULONG Index + ) + { + ASSERT(Index < GetAudioModuleDescriptorListCount()); + return &m_pMiniportPair->ModuleList[Index]; + } + + const PAUDIOMODULE_DESCRIPTOR + GetAudioModuleDescriptorList() + { + return m_pMiniportPair->ModuleList; + } + + ULONG + GetAudioModuleListCount() + { + return GetAudioModuleDescriptorListCount(); + } + + AUDIOMODULE * + GetAudioModule( + _In_ ULONG Index + ) + { + ASSERT(Index < GetAudioModuleListCount()); + return &m_pAudioModules[Index]; + } + + AUDIOMODULE * + GetAudioModuleList() + { + return m_pAudioModules; + } + + const GUID * + GetAudioModuleNotificationDeviceId() + { + return m_pMiniportPair->ModuleNotificationDeviceId; + } + + NTSTATUS + AllocStreamAudioModules( + _In_ const GUID * SignalProcessingMode, + _Out_ AUDIOMODULE ** AudioModule, + _Out_ ULONG * AudioModuleCount + ); + + VOID + FreeStreamAudioModules( + _In_ AUDIOMODULE * AudioModule, + _In_ ULONG AudioModuleCount + ); + #ifdef SYSVAD_BTH_BYPASS public: #pragma code_seg("PAGE") diff --git a/audio/sysvad/EndpointsCommon/minwavertstream.cpp b/audio/sysvad/EndpointsCommon/minwavertstream.cpp index 58382639..1661b5fb 100644 --- a/audio/sysvad/EndpointsCommon/minwavertstream.cpp +++ b/audio/sysvad/EndpointsCommon/minwavertstream.cpp @@ -5,6 +5,7 @@ #include "minwavert.h" #include "minwavertstream.h" #include "UnittestData.h" +#include "AudioModuleHelper.h" #define MINWAVERTSTREAM_POOLTAG 'SRWM' #pragma warning (disable : 4127) @@ -34,8 +35,16 @@ Return Value: --*/ { PAGED_CODE(); + if (NULL != m_pMiniport) { + if (m_pAudioModules) + { + m_pMiniport->FreeStreamAudioModules(m_pAudioModules, m_AudioModuleCount); + m_pAudioModules = NULL; + m_AudioModuleCount = 0; + } + if (m_bUnregisterStream) { m_pMiniport->StreamClosed(m_ulPin, this); @@ -181,6 +190,8 @@ Return Value: m_SignalProcessingMode = SignalProcessingMode; m_bEoSReceived = FALSE; m_bLastBufferRendered = FALSE; + m_pAudioModules = NULL; + m_AudioModuleCount = 0; #ifdef SYSVAD_BTH_BYPASS m_ScoOpen = FALSE; @@ -268,6 +279,17 @@ Return Value: } RtlZeroMemory(m_plPeakMeter, m_pWfExt->Format.nChannels * sizeof(LONG)); + // + // Allocate stream audio module resources. + // + ntStatus = m_pMiniport->AllocStreamAudioModules(&SignalProcessingMode, + &m_pAudioModules, + &m_AudioModuleCount); + if (!NT_SUCCESS(ntStatus)) + { + return ntStatus; + } + if (m_bCapture) { DWORD toneFrequency = 0; @@ -784,6 +806,7 @@ Done: // // ISSUE-2014/10/4 Will this work correctly across pause/play? #pragma code_seg() +_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS CMiniportWaveRTStream::GetReadPacket ( _Out_ ULONG *PacketNumber, @@ -854,7 +877,7 @@ NTSTATUS CMiniportWaveRTStream::GetReadPacket // Compute and return timestamp corresponding to start of the available packet. In a real hardware // driver, the timestamp would be computed in a driver and hardware specific manner. In this sample - // driver, it is extrapolated from the sample driver's internal simulated position corrleation + // driver, it is extrapolated from the sample driver's internal simulated position correlation // [m_ullLinearPosition @ m_ullDmaTimeStamp] and the sample's internal 64-bit packet counter, subtracting // 1 from the packet counter to compute the time at the start of that last completed packet. ULONGLONG linearPositionOfAvailablePacket = (packetCounter - 1) * (m_ulDmaBufferSize / m_ulNotificationsPerBuffer); @@ -895,6 +918,7 @@ NTSTATUS CMiniportWaveRTStream::GetReadPacket } #pragma code_seg() +_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS CMiniportWaveRTStream::SetWritePacket ( _In_ ULONG PacketNumber, @@ -987,6 +1011,7 @@ NTSTATUS CMiniportWaveRTStream::SetWritePacket //============================================================================= #pragma code_seg() +_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS CMiniportWaveRTStream::GetOutputStreamPresentationPosition ( _Out_ KSAUDIO_PRESENTATION_POSITION *pPresentationPosition @@ -1005,6 +1030,7 @@ NTSTATUS CMiniportWaveRTStream::GetOutputStreamPresentationPosition //============================================================================= #pragma code_seg() +_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS CMiniportWaveRTStream::GetPacketCount ( _Out_ ULONG *pPacketCount @@ -1506,6 +1532,47 @@ Return Value: #endif // SYSVAD_BTH_BYPASS //============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CMiniportWaveRTStream::PropertyHandlerModulesListRequest +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +{ + // This specific APO->driver communication example is mainly added to show + // how this communication is done. The instance module list lives on the + // stream object and it can only have modules associated with the underline + // stream's pin. + + PAGED_CODE(); + + DPF_ENTER(("[CMiniportWaveRTStream::PropertyHandlerModulesListRequest]")); + + return AudioModule_GenericHandler_ModulesListRequest( + PropertyRequest, + GetAudioModuleList(), + GetAudioModuleListCount()); +} // PropertyHandlerModulesListRequest + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CMiniportWaveRTStream::PropertyHandlerModuleCommand +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +{ + PAGED_CODE(); + + DPF_ENTER(("[CMiniportWaveRTStream::PropertyHandlerModuleCommand]")); + + return AudioModule_GenericHandler_ModuleCommand( + PropertyRequest, + GetAudioModuleList(), + GetAudioModuleListCount()); +} // PropertyHandlerModuleCommand + +//============================================================================= #pragma code_seg() void TimerNotifyRT @@ -1550,10 +1617,10 @@ TimerNotifyRT goto End; } - // Carry forward the remainder of this division - _this->m_hnsDPCTimeCarryForward = (hnsCurrentTime - _this->m_ullLastDPCTimeStamp + _this->m_hnsDPCTimeCarryForward) % 10000; + // Carry forward the time greater than notification interval to adjust time to signal next buffer completion event accordingly. + _this->m_hnsDPCTimeCarryForward = hnsCurrentTime - _this->m_ullLastDPCTimeStamp + _this->m_hnsDPCTimeCarryForward - (_this->m_ulNotificationIntervalMs * 10000); // Save the last time DPC ran at notification interval - _this->m_ullLastDPCTimeStamp = (ULONG)hnsCurrentTime; + _this->m_ullLastDPCTimeStamp = hnsCurrentTime; _this->UpdatePosition(qpc); diff --git a/audio/sysvad/EndpointsCommon/minwavertstream.h b/audio/sysvad/EndpointsCommon/minwavertstream.h index 405ae35e..3034d630 100644 --- a/audio/sysvad/EndpointsCommon/minwavertstream.h +++ b/audio/sysvad/EndpointsCommon/minwavertstream.h @@ -125,6 +125,8 @@ protected: BOOLEAN m_bEoSReceived; BOOLEAN m_bLastBufferRendered; KSPIN_LOCK m_PositionSpinLock; + AUDIOMODULE * m_pAudioModules; + ULONG m_AudioModuleCount; #ifdef SYSVAD_BTH_BYPASS BOOLEAN m_ScoOpen; @@ -227,10 +229,45 @@ public: { return m_SignalProcessingMode; } + + NTSTATUS PropertyHandlerModulesListRequest + ( + _In_ PPCPROPERTY_REQUEST PropertyRequest + ); + + NTSTATUS PropertyHandlerModuleCommand + ( + _In_ PPCPROPERTY_REQUEST PropertyRequest + ); private: + // // Helper functions. + // + +#pragma code_seg() + ULONG + GetAudioModuleListCount() + { + return m_AudioModuleCount; + } + + AUDIOMODULE * + GetAudioModule( + _In_ ULONG Index + ) + { + ASSERT(Index < GetAudioModuleListCount()); + return &m_pAudioModules[Index]; + } + + AUDIOMODULE * + GetAudioModuleList() + { + return m_pAudioModules; + } + VOID WriteBytes ( _In_ ULONG ByteDisplacement diff --git a/audio/sysvad/EndpointsCommon/sources b/audio/sysvad/EndpointsCommon/sources new file mode 100644 index 00000000..ab930dbd --- /dev/null +++ b/audio/sysvad/EndpointsCommon/sources @@ -0,0 +1,46 @@ + +# Copyright (c) Microsoft Corporation. All rights reserved. + + +TARGETNAME=EndpointsCommon +TARGETTYPE=LIBRARY +KM_LIBRARY=1 + +INCLUDES= \ + $(DDK_INC_PATH); \ + .. + + +C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ -DSYSVAD_BTH_BYPASS +#C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ + +DDK_TARGET_PLATFORM=Universal + +# +# Indicate to the WDK that this sample only supports Win10[+] +# +MINIMUM_NT_TARGET_VERSION=$(_NT_TARGET_VERSION_WINTHRESHOLD) + +# +# Audio driver is a KMDF miniport. +# +KMDF_VERSION_MAJOR=1 + + +SOURCES=$(SOURCES) \ + mintopo.cpp \ + minwavert.cpp \ + minwavertstream.cpp \ + MiniportAudioEngineNode.cpp\ + MiniportStreamAudioEngineNode.cpp\ + micarraytopo.cpp \ + speakertopo.cpp \ + speakerhptopo.cpp \ + bthhfptopo.cpp \ + bthhfpmictopo.cpp \ + bthhfpspeakertopo.cpp \ + bthhfpminwavert.cpp \ + AudioModuleHelper.cpp \ + + + diff --git a/audio/sysvad/EndpointsCommon/speakerhpwavtable.h b/audio/sysvad/EndpointsCommon/speakerhpwavtable.h index 2f36ac06..66fc9c8a 100644 --- a/audio/sysvad/EndpointsCommon/speakerhpwavtable.h +++ b/audio/sysvad/EndpointsCommon/speakerhpwavtable.h @@ -15,6 +15,9 @@ Abstract: #ifndef _SYSVAD_SPEAKERHPWAVTABLE_H_ #define _SYSVAD_SPEAKERHPWAVTABLE_H_ +#include "AudioModule0.h" +#include "AudioModule1.h" +#include "AudioModule2.h" // To keep the code simple assume device supports only 48KHz, 16-bit, stereo (PCM and NON-PCM) @@ -579,6 +582,33 @@ PKSDATARANGE SpeakerHpPinDataRangePointersBridge[] = //============================================================================= static +PCPROPERTY_ITEM PropertiesSpeakerHpHostPin[] = +{ + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_DESCRIPTORS, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_GenericPin + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_COMMAND, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_GenericPin + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_GenericPin + }, +}; + +DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerHpHostPin, PropertiesSpeakerHpHostPin); + +//============================================================================= + +static PCPROPERTY_ITEM PropertiesSpeakerHpOffloadPin[] = { { @@ -592,7 +622,25 @@ PCPROPERTY_ITEM PropertiesSpeakerHpOffloadPin[] = KSPROPERTY_OFFLOAD_PIN_VERIFY_STREAM_OBJECT_POINTER, // define properties KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, PropertyHandler_OffloadPin - } + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_DESCRIPTORS, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_GenericPin + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_COMMAND, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_GenericPin + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_GenericPin + }, }; DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerHpOffloadPin, PropertiesSpeakerHpOffloadPin); @@ -606,7 +654,7 @@ PCPIN_DESCRIPTOR SpeakerHpWaveMiniportPins[] = SPEAKERHP_MAX_INPUT_SYSTEM_STREAMS, SPEAKERHP_MAX_INPUT_SYSTEM_STREAMS, 0, - NULL, + &AutomationSpeakerHpHostPin, // AutomationTable { 0, NULL, @@ -722,9 +770,84 @@ PCPROPERTY_ITEM PropertiesSpeakerHpWaveFilter[] = KSPROPERTY_PIN_PROPOSEDATAFORMAT, KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, PropertyHandler_WaveFilter + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_DESCRIPTORS, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_WaveFilter + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_COMMAND, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_WaveFilter + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_WaveFilter + }, +}; + +// +// Endpoint audio module list. +// +static +AUDIOMODULE_DESCRIPTOR SpeakerHpModulesWaveFilter[] = +{ + { // 0 + &AudioModule0Id, // class id. + &NULL_GUID, // generic, mode independent. + L"Generic system module", + AUDIOMODULE_INSTANCE_ID(0,0), + AUDIOMODULE0_MAJOR, + AUDIOMODULE0_MINOR, + AUDIOMODULE_DESCRIPTOR_FLAG_NONE, + sizeof(AUDIOMODULE0_CONTEXT), + AudioModule0_InitClass, + AudioModule0_InitInstance, + AudioModule0_Cleanup, + AudioModule0_Handler + }, + { // 1 + &AudioModule1Id, // class id. + &AUDIO_SIGNALPROCESSINGMODE_MOVIE, + L"Speaker HP endpoint, EQ effect module, Movie mode", + AUDIOMODULE_INSTANCE_ID(0,0), + AUDIOMODULE1_MAJOR, + AUDIOMODULE1_MINOR, + AUDIOMODULE_DESCRIPTOR_FLAG_NONE, + sizeof(AUDIOMODULE1_CONTEXT), + AudioModule1_InitClass, + AudioModule1_InitInstance, + AudioModule1_Cleanup, + AudioModule1_Handler + }, + { // 2 + &AudioModule2Id, // class id. + &AUDIO_SIGNALPROCESSINGMODE_DEFAULT, + L"Speaker HP endpoint, Echo Cancellation effect module, Default mode", + AUDIOMODULE_INSTANCE_ID(0,0), + AUDIOMODULE2_MAJOR, + AUDIOMODULE2_MINOR, + AUDIOMODULE_DESCRIPTOR_FLAG_NONE, + sizeof(AUDIOMODULE2_CONTEXT), + AudioModule2_InitClass, + AudioModule2_InitInstance, + AudioModule2_Cleanup, + AudioModule2_Handler } }; +// +// Audio module notification device id. +// NOTE: do not use this guid for real driver, generate a new one. +// +const GUID SpeakerHpModuleNotificationDeviceId = +{0x3A66BE17,0x5440,0x48E7,0x83,0x76,0xB7,0x5A,0x0B,0x1A,0x92,0x2D}; + DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerHpWaveFilter, PropertiesSpeakerHpWaveFilter); //============================================================================= diff --git a/audio/sysvad/EndpointsCommon/speakerwavtable.h b/audio/sysvad/EndpointsCommon/speakerwavtable.h index cb2c2481..94f7863b 100644 --- a/audio/sysvad/EndpointsCommon/speakerwavtable.h +++ b/audio/sysvad/EndpointsCommon/speakerwavtable.h @@ -16,6 +16,8 @@ Abstract: #define _SYSVAD_SPEAKERWAVTABLE_H_ #include "SysVadShared.h" +#include "AudioModule0.h" +#include "AudioModule1.h" // To keep the code simple assume device supports only 48KHz, 16-bit, stereo (PCM and NON-PCM) @@ -581,6 +583,33 @@ PKSDATARANGE SpeakerPinDataRangePointersBridge[] = //============================================================================= static +PCPROPERTY_ITEM PropertiesSpeakerHostPin[] = +{ + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_DESCRIPTORS, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_GenericPin + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_COMMAND, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_GenericPin + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_GenericPin + }, +}; + +DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerHostPin, PropertiesSpeakerHostPin); + +//============================================================================= + +static PCPROPERTY_ITEM PropertiesSpeakerOffloadPin[] = { { @@ -594,7 +623,25 @@ PCPROPERTY_ITEM PropertiesSpeakerOffloadPin[] = KSPROPERTY_OFFLOAD_PIN_VERIFY_STREAM_OBJECT_POINTER, // define properties KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, PropertyHandler_OffloadPin - } + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_DESCRIPTORS, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_GenericPin + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_COMMAND, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_GenericPin + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_GenericPin + }, }; DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerOffloadPin, PropertiesSpeakerOffloadPin); @@ -608,7 +655,7 @@ PCPIN_DESCRIPTOR SpeakerWaveMiniportPins[] = SPEAKER_MAX_INPUT_SYSTEM_STREAMS, SPEAKER_MAX_INPUT_SYSTEM_STREAMS, 0, - NULL, + &AutomationSpeakerHostPin, // AutomationTable { 0, NULL, @@ -730,9 +777,84 @@ PCPROPERTY_ITEM PropertiesSpeakerWaveFilter[] = KSPROPERTY_SYSVAD_DEFAULTSTREAMEFFECTS, KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, PropertyHandler_WaveFilter + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_DESCRIPTORS, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_WaveFilter + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_COMMAND, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_WaveFilter + }, + { + &KSPROPSETID_AudioModule, + KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_WaveFilter + }, +}; + +// +// Endpoint audio module list. +// +static +AUDIOMODULE_DESCRIPTOR SpeakerModulesWaveFilter[] = +{ + { // 0 + &AudioModule0Id, // class id. + &NULL_GUID, // generic, mode independent. + L"Generic system module", + AUDIOMODULE_INSTANCE_ID(0,0), + AUDIOMODULE0_MAJOR, + AUDIOMODULE0_MINOR, + AUDIOMODULE_DESCRIPTOR_FLAG_NONE, + sizeof(AUDIOMODULE0_CONTEXT), + AudioModule0_InitClass, + AudioModule0_InitInstance, + AudioModule0_Cleanup, + AudioModule0_Handler + }, + { // 1 + &AudioModule1Id, // class id. + &AUDIO_SIGNALPROCESSINGMODE_MOVIE, + L"Speaker endpoint, EQ effect module, Movie mode", + AUDIOMODULE_INSTANCE_ID(0,0), + AUDIOMODULE1_MAJOR, + AUDIOMODULE1_MINOR, + AUDIOMODULE_DESCRIPTOR_FLAG_NONE, + sizeof(AUDIOMODULE1_CONTEXT), + AudioModule1_InitClass, + AudioModule1_InitInstance, + AudioModule1_Cleanup, + AudioModule1_Handler + }, + { // 2 + &AudioModule1Id, // class id. + &AUDIO_SIGNALPROCESSINGMODE_DEFAULT, + L"Speaker endpoint, EQ effect module, Default mode", + AUDIOMODULE_INSTANCE_ID(1,0), + AUDIOMODULE1_MAJOR, + AUDIOMODULE1_MINOR, + AUDIOMODULE_DESCRIPTOR_FLAG_NONE, + sizeof(AUDIOMODULE1_CONTEXT), + AudioModule1_InitClass, + AudioModule1_InitInstance, + AudioModule1_Cleanup, + AudioModule1_Handler } }; +// +// Audio module notification device id. +// NOTE: do not use this guid for real driver, generate a new one. +// +const GUID SpeakerModuleNotificationDeviceId = +{0xC01C987A,0x30A9,0x4DB7,0x8D,0x69,0x69,0x6C,0xFF,0x41,0xE4,0xB9}; + DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerWaveFilter, PropertiesSpeakerWaveFilter); //============================================================================= diff --git a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj index fdf37a5d..fc459cfa 100644 --- a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj +++ b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj @@ -115,8 +115,8 @@ </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ClCompile> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreadedDLL</RuntimeLibrary> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> @@ -139,8 +139,8 @@ </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ClCompile> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreadedDLL</RuntimeLibrary> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> @@ -163,8 +163,8 @@ </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreadedDLL</RuntimeLibrary> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> @@ -187,8 +187,8 @@ </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreadedDLL</RuntimeLibrary> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> diff --git a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj.Filters b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj.Filters new file mode 100644 index 00000000..f0f2001a --- /dev/null +++ b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj.Filters @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{75C3E63D-04EA-4EB3-B9F1-505497C51F71}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{5E8F8D4C-2886-4109-9E78-CE5EA6DB4AC4}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{75D3016A-4ED8-4FAF-9817-394BE1112534}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="dllmain.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="KeywordDetectorContosoAdapter.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="stdafx.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <Midl Include="KeywordDetectorContosoAdapter.idl"> + <Filter>Source Files</Filter> + </Midl> + <None Include="KeywordDetectorContosoAdapter.def"> + <Filter>Source Files</Filter> + </None> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="KeywordDetectorContosoAdapter.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/audio/sysvad/KeywordDetectorAdapter/sources b/audio/sysvad/KeywordDetectorAdapter/sources new file mode 100644 index 00000000..8b17ac8b --- /dev/null +++ b/audio/sysvad/KeywordDetectorAdapter/sources @@ -0,0 +1,53 @@ +TARGETTYPE=DYNLINK +TARGETNAME=KeywordDetectorContosoAdapter + +DLLENTRY=_DllMainCRTStartup +DLLDEF=KeywordDetectorContosoAdapter.def +#USE_ATL=1 + + +USE_LIBCMT=1 + +MSC_WARNING_LEVEL=-W4 \ + -WX + +C_DEFINES=$(C_DEFINES) \ + -D_WINDLL \ + -D_USRDLL \ + -DUNICODE \ + -D_UNICODE + +# +# Indicate to the WDK that this sample only supports Win10[+] +# +MINIMUM_NT_TARGET_VERSION=$(_NT_TARGET_VERSION_WINTHRESHOLD) + +# Indicate that this DLL must be included in the driver package +DDK_NO_PACKAGE_PROJECT=0 +DDK_INCLUDE_PACKAGE_PROJECT=1 + +INCLUDES= \ + $(DDK_INC_PATH); \ + ..\inc;..\; \ + +SOURCES=KeywordDetectorContosoAdapter.idl \ + KeywordDetectorContosoAdapter.rc \ + dllmain.cpp \ + KeywordDetectorContosoAdapter.cpp \ + stdafx.cpp \ + + +TARGETLIBS= \ + $(SDK_LIB_PATH)\onecore_downlevel.lib \ + $(SDK_LIB_PATH)\onecore_downlevel.lib \ + $(SDK_LIB_PATH)\oleaut32.lib \ + \ + $(ONECORE_PRIV_SDK_LIB_PATH)\OneCore_Forwarder_user32.lib \ + $(INTERNAL_SDK_LIB_PATH)\onecoreuapuuid.lib \ + $(SDK_LIB_PATH)\mfplat.lib \ + $(SDK_LIB_PATH)\runtimeobject.lib \ + + + +MUI_VERIFY_NO_LOC_RESOURCE=1 + diff --git a/audio/sysvad/Package/package.VcxProj b/audio/sysvad/Package/package.VcxProj new file mode 100644 index 00000000..0ea6ab39 --- /dev/null +++ b/audio/sysvad/Package/package.VcxProj @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\KeywordDetectorAdapter\KeywordDetectorContosoAdapter.vcxproj"> + <Project>{E0F02048-78A4-4FE8-B863-66E6CB6A2C37}</Project> + </ProjectReference> + <ProjectReference Include="..\PhoneAudioSample\PhoneAudioSample.vcxproj"> + <Project>{FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}</Project> + </ProjectReference> + <ProjectReference Include="..\SwapAPO\APO\SwapAPO.vcxproj"> + <Project>{691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}</Project> + </ProjectReference> + <ProjectReference Include="..\SwapAPO\DelayAPO\DelayAPO.vcxproj"> + <Project>{8851AB85-70B3-4798-A149-BA366DF9EC25}</Project> + </ProjectReference> + <ProjectReference Include="..\SwapAPO\PropPageExtensions\PropPageExt.vcxproj"> + <Project>{D253C552-154D-49E1-820A-B2CD9D9FF13E}</Project> + </ProjectReference> + <ProjectReference Include="..\TabletAudioSample\TabletAudioSample.vcxproj"> + <Project>{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}</Project> + </ProjectReference> + </ItemGroup> + <PropertyGroup Label="PropertySheets"> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Utility</ConfigurationType> + <DriverType>Package</DriverType> + <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck> + <Configuration>Debug</Configuration> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}</ProjectGuid> + <SampleGuid>{E9D167E6-E633-4284-8F02-FF86DF3B6D7F}</SampleGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup /> + <PropertyGroup> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <ImportToStore>False</ImportToStore> + <InstallMode>None</InstallMode> + <HardwareIdString /> + <CommandLine /> + <ScriptPath /> + <DeployFiles /> + <ScriptName /> + <ScriptDeviceQuery>%PathToInf%</ScriptDeviceQuery> + <EnableVerifier>False</EnableVerifier> + <AllDrivers>False</AllDrivers> + <VerifyProjectOutput>True</VerifyProjectOutput> + <VerifyDrivers /> + <VerifyFlags>133563</VerifyFlags> + </PropertyGroup> + <ItemDefinitionGroup> + </ItemDefinitionGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/audio/sysvad/Package/package.VcxProj.Filters b/audio/sysvad/Package/package.VcxProj.Filters new file mode 100644 index 00000000..63b75548 --- /dev/null +++ b/audio/sysvad/Package/package.VcxProj.Filters @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{0924612D-FBA7-477E-BBB9-B3B6EA7C6B03}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{97311738-0AD8-4F7E-AC88-9C9BEAF53AEE}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{8DC1C4F0-C285-400E-A983-77A339891354}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{9F086F34-79D2-4FAA-87FD-C2DBEFCED0BA}</UniqueIdentifier> + </Filter> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj.Filters b/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj.Filters new file mode 100644 index 00000000..981f44c4 --- /dev/null +++ b/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj.Filters @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{6BC89CB0-7C76-439F-8D55-E3125E355A42}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{02E55FC1-89F6-4E2D-A10B-A6476FF89B86}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{B836489B-8D2E-41DD-A232-0D6C40243B08}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{850E3B99-7C84-454B-9E04-6A7CF9852E6C}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\adapter.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\basetopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\common.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\hw.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\kshelper.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\savedata.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\tonegenerator.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="cellulartopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="cellularwave.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="fmtopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="fmwave.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="handsetmictopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="handsetspeakertopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="michstopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="speakerhstopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="..\sysvad.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/audio/sysvad/PhoneAudioSample/minipairs.h b/audio/sysvad/PhoneAudioSample/minipairs.h index 7f2c5fb8..eaa7a240 100644 --- a/audio/sysvad/PhoneAudioSample/minipairs.h +++ b/audio/sysvad/PhoneAudioSample/minipairs.h @@ -185,7 +185,10 @@ ENDPOINT_MINIPAIR SpeakerMiniports = SIZEOF_ARRAY(SpeakerPinDeviceFormatsAndModes), SpeakerTopologyPhysicalConnections, SIZEOF_ARRAY(SpeakerTopologyPhysicalConnections), - ENDPOINT_OFFLOAD_SUPPORTED + ENDPOINT_OFFLOAD_SUPPORTED, + SpeakerModulesWaveFilter, + SIZEOF_ARRAY(SpeakerModulesWaveFilter), + &SpeakerModuleNotificationDeviceId, }; /********************************************************************* @@ -227,7 +230,8 @@ ENDPOINT_MINIPAIR SpeakerHsMiniports = SIZEOF_ARRAY(SpeakerHsPinDeviceFormatsAndModes), SpeakerHsTopologyPhysicalConnections, SIZEOF_ARRAY(SpeakerHsTopologyPhysicalConnections), - ENDPOINT_OFFLOAD_SUPPORTED + ENDPOINT_OFFLOAD_SUPPORTED, + NULL, 0, NULL, // audio module settings. }; // @@ -271,7 +275,8 @@ ENDPOINT_MINIPAIR MicHsMiniports = SIZEOF_ARRAY(MicHsPinDeviceFormatsAndModes), MicHsTopologyPhysicalConnections, SIZEOF_ARRAY(MicHsTopologyPhysicalConnections), - ENDPOINT_NO_FLAGS + ENDPOINT_NO_FLAGS, + NULL, 0, NULL, // audio module settings. }; @@ -317,7 +322,8 @@ ENDPOINT_MINIPAIR MicArray1Miniports = SIZEOF_ARRAY(MicArrayPinDeviceFormatsAndModes), MicArray1TopologyPhysicalConnections, SIZEOF_ARRAY(MicArray1TopologyPhysicalConnections), - ENDPOINT_SOUNDDETECTOR_SUPPORTED + ENDPOINT_SOUNDDETECTOR_SUPPORTED, + NULL, 0, NULL, // audio module settings. }; /********************************************************************* @@ -370,7 +376,8 @@ ENDPOINT_MINIPAIR CellularMiniports = SIZEOF_ARRAY(CellularPinDeviceFormatsAndModes), CellularTopologyPhysicalConnections, SIZEOF_ARRAY(CellularTopologyPhysicalConnections), - ENDPOINT_CELLULAR_PROVIDER1 + ENDPOINT_CELLULAR_PROVIDER1, + NULL, 0, NULL, // audio module settings. }; @@ -401,7 +408,8 @@ ENDPOINT_MINIPAIR CellularMiniports2 = SIZEOF_ARRAY(CellularPinDeviceFormatsAndModes), CellularTopologyPhysicalConnections2, SIZEOF_ARRAY(CellularTopologyPhysicalConnections2), - ENDPOINT_CELLULAR_PROVIDER2 + ENDPOINT_CELLULAR_PROVIDER2, + NULL, 0, NULL, // audio module settings. }; /********************************************************************* @@ -443,7 +451,8 @@ ENDPOINT_MINIPAIR HandsetSpeakerMiniports = SIZEOF_ARRAY(HandsetSpeakerPinDeviceFormatsAndModes), HandsetSpeakerTopologyPhysicalConnections, SIZEOF_ARRAY(HandsetSpeakerTopologyPhysicalConnections), - ENDPOINT_NO_FLAGS + ENDPOINT_NO_FLAGS, + NULL, 0, NULL, // audio module settings. }; // @@ -487,7 +496,8 @@ ENDPOINT_MINIPAIR HandsetMicMiniports = SIZEOF_ARRAY(HandsetMicPinDeviceFormatsAndModes), HandsetMicTopologyPhysicalConnections, SIZEOF_ARRAY(HandsetMicTopologyPhysicalConnections), - ENDPOINT_NO_FLAGS + ENDPOINT_NO_FLAGS, + NULL, 0, NULL, // audio module settings. }; /********************************************************************* @@ -527,7 +537,8 @@ ENDPOINT_MINIPAIR FmRxMiniports = SIZEOF_ARRAY(FmRxPinDeviceFormatsAndModes), FmRxTopologyPhysicalConnections, SIZEOF_ARRAY(FmRxTopologyPhysicalConnections), - ENDPOINT_NO_FLAGS + ENDPOINT_NO_FLAGS, + NULL, 0, NULL, // audio module settings. }; //============================================================================= diff --git a/audio/sysvad/PhoneAudioSample/sources b/audio/sysvad/PhoneAudioSample/sources new file mode 100644 index 00000000..0d1551ce --- /dev/null +++ b/audio/sysvad/PhoneAudioSample/sources @@ -0,0 +1,58 @@ + +# Copyright (c) Microsoft Corporation. All rights reserved. + + +!include ..\sources.inc + +TARGETNAME=PhoneAudioSample + +TARGETLIBS= \ + $(TARGETLIBS) \ + $(OBJ_PATH)\..\EndpointsCommon\$(O)\EndpointsCommon.lib + + +C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ -DSYSVAD_BTH_BYPASS +#C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ + +# +# Indicate to the WDK that this sample only supports Win10[+] +# +MINIMUM_NT_TARGET_VERSION=$(_NT_TARGET_VERSION_WINTHRESHOLD) + +DDK_TARGET_PLATFORM=Universal + +# +# Audio driver is a KMDF miniport. +# +KMDF_VERSION_MAJOR=1 + +# +# Uncomment one of the following lines to select the right power management. +# Note that the single-component/multi-state feature requires also a registry +# value set via the INF. The name of the registry value is SingleComponentMultiFxStates. +# see INF file for more info. +# +C_DEFINES= $(C_DEFINES) -D_USE_IPortClsRuntimePower +#C_DEFINES= $(C_DEFINES) -D_USE_SingleComponentMultiFxStates + +INCLUDES= \ + $(INCLUDES); \ + ..\EndpointsCommon; \ + +SOURCES=$(SOURCES) \ + cellulartopo.cpp \ + fmtopo.cpp \ + handsetspeakertopo.cpp \ + handsetmictopo.cpp \ + michstopo.cpp \ + speakerhstopo.cpp \ + cellularwave.cpp \ + fmwave.cpp \ + +# Indicate that this module must be included in the driver package +DDK_NO_PACKAGE_PROJECT=0 +DDK_INCLUDE_PACKAGE_PROJECT=1 + + +MUI_VERIFY_NO_LOC_RESOURCE=1 + diff --git a/audio/sysvad/SwapAPO/APO/SwapAPO.h b/audio/sysvad/SwapAPO/APO/SwapAPO.h index 2f687c04..fc279460 100644 --- a/audio/sysvad/SwapAPO/APO/SwapAPO.h +++ b/audio/sysvad/SwapAPO/APO/SwapAPO.h @@ -29,13 +29,6 @@ _Analysis_mode_(_Analysis_code_type_user_driver_) // // {B8EC75BA-00ED-434C-A732-064A0F00788E} DEFINE_GUID(SwapEffectId, 0xb8ec75ba, 0x00ed, 0x434c, 0xa7, 0x32, 0x06, 0x4a, 0x0f, 0x00, 0x78, 0x8e); -// {29FBFBB5-9002-4ABC-DCBC-DD45462478C8} -DEFINE_GUID(DelayEffectId, 0x29FBFBB5, 0x9002, 0x4ABC, 0xDC, 0xBC, 0xDD, 0x45, 0x46, 0x24, 0x78, 0xC8); - -// 1000 ms of delay -#define HNS_DELAY HNS_PER_SECOND - -#define FRAMES_FROM_HNS(hns) (ULONG)(1.0 * hns / HNS_PER_SECOND * GetFramesPerSecond() + 0.5) LONG GetCurrentEffectsSetting(IPropertyStore* properties, PROPERTYKEY pkeyEnable, GUID processingMode); @@ -59,9 +52,6 @@ public: , m_hEffectsChangedEvent(NULL) , m_AudioProcessingMode(AUDIO_SIGNALPROCESSINGMODE_DEFAULT) , m_fEnableSwapMFX(FALSE) - , m_fEnableDelayMFX(FALSE) - , m_nDelayFrames(0) - , m_iDelayIndex(0) { m_pf32Coefficients = NULL; } @@ -141,7 +131,6 @@ public: public: LONG m_fEnableSwapMFX; - LONG m_fEnableDelayMFX; GUID m_AudioProcessingMode; CComPtr<IPropertyStore> m_spAPOSystemEffectsProperties; CComPtr<IMMDeviceEnumerator> m_spEnumerator; @@ -150,10 +139,6 @@ public: // Locked memory FLOAT32 *m_pf32Coefficients; - CComHeapPtr<FLOAT32> m_pf32DelayBuffer; - UINT32 m_nDelayFrames; - UINT32 m_iDelayIndex; - private: CCriticalSection m_EffectsLock; HANDLE m_hEffectsChangedEvent; @@ -182,8 +167,6 @@ public: , m_AudioProcessingMode(AUDIO_SIGNALPROCESSINGMODE_DEFAULT) , m_fEnableSwapSFX(FALSE) , m_fEnableDelaySFX(FALSE) - , m_nDelayFrames(0) - , m_iDelayIndex(0) { } @@ -255,10 +238,6 @@ public: CCriticalSection m_EffectsLock; HANDLE m_hEffectsChangedEvent; - - CComHeapPtr<FLOAT32> m_pf32DelayBuffer; - UINT32 m_nDelayFrames; - UINT32 m_iDelayIndex; }; #pragma AVRT_VTABLES_END @@ -285,22 +264,6 @@ void ProcessSwapScale( FLOAT32 *pf32Coefficients ); // -// Declaration of the ProcessDelay routine. -// -void ProcessDelay( - _Out_writes_(u32ValidFrameCount * u32SamplesPerFrame) - FLOAT32 *pf32OutputFrames, - _In_reads_(u32ValidFrameCount * u32SamplesPerFrame) - const FLOAT32 *pf32InputFrames, - UINT32 u32ValidFrameCount, - UINT32 u32SamplesPerFrame, - _Inout_updates_(u32DelayFrames * u32SamplesPerFrame) - FLOAT32 *pf32DelayBuffer, - UINT32 u32DelayFrames, - _Inout_ - UINT32 *pu32DelayIndex ); - -// // Convenience methods // diff --git a/audio/sysvad/SwapAPO/APO/SwapAPO.vcxproj.Filters b/audio/sysvad/SwapAPO/APO/SwapAPO.vcxproj.Filters new file mode 100644 index 00000000..7cb395b8 --- /dev/null +++ b/audio/sysvad/SwapAPO/APO/SwapAPO.vcxproj.Filters @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{296F0C2A-85AF-4624-97D4-6D3251998382}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{655A91B5-15BB-4151-B3B5-8185B5FA1ABB}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{A9DFA5D3-3035-416E-BBD8-8D0745973136}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="Swap.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="SwapAPODll.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="SwapAPOMFX.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="SwapAPOSFX.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <Midl Include="SwapAPODll.idl"> + <Filter>Source Files</Filter> + </Midl> + <Midl Include="SwapAPOInterface.idl"> + <Filter>Source Files</Filter> + </Midl> + <None Include="SwapAPODll.def"> + <Filter>Source Files</Filter> + </None> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="SwapAPODll.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/audio/sysvad/SwapAPO/APO/makefile b/audio/sysvad/SwapAPO/APO/makefile new file mode 100644 index 00000000..c7837f4f --- /dev/null +++ b/audio/sysvad/SwapAPO/APO/makefile @@ -0,0 +1,36 @@ +############################################################################# +# +# Copyright (c) Microsoft Corporation. +# All Rights Reserved. +# +# Makefile for wdm\audio\sysfx\apo +# +############################################################################# + +## NT BUILD ENVIROMENT + +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT. +# +!if defined(IA64) +!message This sample is not to be built for IA64 targets +!else + +!IF DEFINED(_NT_TARGET_VERSION) +#! IF $(_NT_TARGET_VERSION)>=0x501 +! IF $(_NT_TARGET_VERSION)>=0x600 +! INCLUDE $(NTMAKEENV)\makefile.def +! ELSE +# Only warn once per directory +! INCLUDE $(NTMAKEENV)\makefile.plt +! IF "$(BUILD_PASS)"=="PASS1" +! message BUILDMSG: Warning : Building the sample "$(MAKEDIR)" for downlevel build environments is temporarily disabled in WDK for Beta2. +! ENDIF +! ENDIF +!ELSE +! INCLUDE $(NTMAKEENV)\makefile.def +!ENDIF + +!endif
\ No newline at end of file diff --git a/audio/sysvad/SwapAPO/APO/sources b/audio/sysvad/SwapAPO/APO/sources new file mode 100644 index 00000000..7baf3745 --- /dev/null +++ b/audio/sysvad/SwapAPO/APO/sources @@ -0,0 +1,13 @@ +!include ..\sources.inc + +TARGETNAME=SwapAPO +DLLDEF=SwapAPODll.def + +SOURCES=SwapAPOInterface.idl \ + SwapAPOMFX.cpp \ + SwapAPOSFX.cpp \ + Swap.cpp \ + SwapAPODll.idl \ + SwapAPODll.rc \ + SwapAPODll.cpp \ + diff --git a/audio/sysvad/SwapAPO/APO/swap.cpp b/audio/sysvad/SwapAPO/APO/swap.cpp index 0efe23f7..6fa39fa3 100644 --- a/audio/sysvad/SwapAPO/APO/swap.cpp +++ b/audio/sysvad/SwapAPO/APO/swap.cpp @@ -112,72 +112,3 @@ void ProcessSwapScale( } } #pragma AVRT_CODE_END - - -#pragma AVRT_CODE_BEGIN -void ProcessDelay( - _Out_writes_(u32ValidFrameCount * u32SamplesPerFrame) - FLOAT32 *pf32OutputFrames, - _In_reads_(u32ValidFrameCount * u32SamplesPerFrame) - const FLOAT32 *pf32InputFrames, - UINT32 u32ValidFrameCount, - UINT32 u32SamplesPerFrame, - _Inout_updates_(u32DelayFrames * u32SamplesPerFrame) - FLOAT32 *pf32DelayBuffer, - UINT32 u32DelayFrames, - _Inout_ - UINT32 *pu32DelayIndex ) -{ - ASSERT_REALTIME(); - ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32InputFrames) ); - ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32OutputFrames) ); - - if (u32DelayFrames == 0) - { - CopyFrames( pf32OutputFrames, - pf32InputFrames, - u32ValidFrameCount, - u32SamplesPerFrame ); - } - else - { - - // Invariants: - // 0 <= (*pu32DelayIndex) < u32DelayFrames - // pf32OutputFrames[0 ... u32ValidFrameCount * u32SamplesPerFrame - 1] is writable - // pf32InputFrames[0 ... u32ValidFrameCount * u32SamplesPerFrame - 1] is readable - while (u32ValidFrameCount > 0) - { - // copy either the rest of the input/output buffer, - // or the rest of the delay buffer, - // whichever is smaller - UINT32 framesToCopy = min(u32ValidFrameCount, u32DelayFrames - (*pu32DelayIndex)); - - // delay => output -#pragma prefast(suppress: __WARNING_POTENTIAL_BUFFER_OVERFLOW_HIGH_PRIORITY, "this copy to pf32OutputFrames is in-range") - CopyFrames( pf32OutputFrames, - &pf32DelayBuffer[(*pu32DelayIndex) * u32SamplesPerFrame], - framesToCopy, - u32SamplesPerFrame ); - - // input => delay - CopyFrames( &pf32DelayBuffer[(*pu32DelayIndex) * u32SamplesPerFrame], - pf32InputFrames, - framesToCopy, - u32SamplesPerFrame ); - - pf32OutputFrames += framesToCopy * u32SamplesPerFrame; - pf32InputFrames += framesToCopy * u32SamplesPerFrame; - u32ValidFrameCount -= framesToCopy; - - *pu32DelayIndex += framesToCopy; - if (*pu32DelayIndex == u32DelayFrames) - { - *pu32DelayIndex = 0; - } - } - - } -} -#pragma AVRT_CODE_END - diff --git a/audio/sysvad/SwapAPO/APO/swapapomfx.cpp b/audio/sysvad/SwapAPO/APO/swapapomfx.cpp index 43cd78fb..b4e6e95a 100644 --- a/audio/sysvad/SwapAPO/APO/swapapomfx.cpp +++ b/audio/sysvad/SwapAPO/APO/swapapomfx.cpp @@ -181,36 +181,17 @@ STDMETHODIMP_(void) CSwapAPOMFX::APOProcess( m_u32SamplesPerFrame, m_pf32Coefficients ); } - // copy to the delay buffer - if ( - !IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) && - m_fEnableDelayMFX - ) + // copy the memory only if there is an output connection, and input/output pointers are unequal + if ( (0 != u32NumOutputConnections) && + (ppOutputConnections[0]->pBuffer != ppInputConnections[0]->pBuffer) ) { - ProcessDelay(pf32OutputFrames, pf32InputFrames, - ppInputConnections[0]->u32ValidFrameCount, - GetSamplesPerFrame(), - m_pf32DelayBuffer, - m_nDelayFrames, - &m_iDelayIndex); - - // we don't try to remember silence - ppOutputConnections[0]->u32BufferFlags = BUFFER_VALID; - } - else - { - // copy the memory only if there is an output connection, and input/output pointers are unequal - if ( (0 != u32NumOutputConnections) && - (ppOutputConnections[0]->pBuffer != ppInputConnections[0]->pBuffer) ) - { - CopyFrames( pf32OutputFrames, pf32InputFrames, - ppInputConnections[0]->u32ValidFrameCount, - GetSamplesPerFrame() ); - } - - // pass along buffer flags - ppOutputConnections[0]->u32BufferFlags = ppInputConnections[0]->u32BufferFlags; + CopyFrames( pf32OutputFrames, pf32InputFrames, + ppInputConnections[0]->u32ValidFrameCount, + GetSamplesPerFrame() ); } + + // pass along buffer flags + ppOutputConnections[0]->u32BufferFlags = ppInputConnections[0]->u32BufferFlags; // Set the valid frame count. ppOutputConnections[0]->u32ValidFrameCount = ppInputConnections[0]->u32ValidFrameCount; @@ -247,15 +228,8 @@ STDMETHODIMP CSwapAPOMFX::GetLatency(HNSTIME* pTime) IF_TRUE_ACTION_JUMP(NULL == pTime, hr = E_POINTER, Exit); - if (IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)) - { - *pTime = 0; - } - else - { - *pTime = (m_fEnableDelayMFX ? HNS_DELAY : 0); - } - + *pTime = 0; + Exit: return hr; } @@ -290,29 +264,6 @@ STDMETHODIMP CSwapAPOMFX::LockForProcess(UINT32 u32NumInputConnections, ppInputConnections, u32NumOutputConnections, ppOutputConnections); IF_FAILED_JUMP(hr, Exit); - if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) && m_fEnableDelayMFX) - { - m_nDelayFrames = FRAMES_FROM_HNS(HNS_DELAY); - m_iDelayIndex = 0; - - m_pf32DelayBuffer.Free(); - - // Allocate one second's worth of audio - // - // This allocation is being done using CoTaskMemAlloc because the delay is very large - // This introduces a risk of glitches if the delay buffer gets paged out - // - // A more typical approach would be to allocate the memory using AERT_Allocate, which locks the memory - // But for the purposes of this APO, CoTaskMemAlloc suffices, and the risk of glitches is not important - m_pf32DelayBuffer.Allocate(GetSamplesPerFrame() * m_nDelayFrames); - WriteSilence(m_pf32DelayBuffer, m_nDelayFrames, GetSamplesPerFrame()); - if (nullptr == m_pf32DelayBuffer) - { - hr = E_OUTOFMEMORY; - goto Exit; - } - } - Exit: return hr; } @@ -460,7 +411,6 @@ HRESULT CSwapAPOMFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) if (m_spAPOSystemEffectsProperties != NULL) { m_fEnableSwapMFX = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, PKEY_Endpoint_Enable_Channel_Swap_MFX, m_AudioProcessingMode); - m_fEnableDelayMFX = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, PKEY_Endpoint_Enable_Delay_MFX, m_AudioProcessingMode); } // @@ -549,7 +499,6 @@ STDMETHODIMP CSwapAPOMFX::GetEffectsList(_Outptr_result_buffer_maybenull_(*pcEff EffectControl list[] = { { SwapEffectId, m_fEnableSwapMFX }, - { DelayEffectId, m_fEnableDelayMFX }, }; if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)) @@ -713,7 +662,6 @@ HRESULT CSwapAPOMFX::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERT // If either the master disable or our APO's enable properties changed... if (PK_EQUAL(key, PKEY_Endpoint_Enable_Channel_Swap_MFX) || - PK_EQUAL(key, PKEY_Endpoint_Enable_Delay_MFX) || PK_EQUAL(key, PKEY_AudioEndpoint_Disable_SysFx)) { LONG nChanges = 0; @@ -730,7 +678,6 @@ HRESULT CSwapAPOMFX::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERT KeyControl controls[] = { { PKEY_Endpoint_Enable_Channel_Swap_MFX, &m_fEnableSwapMFX }, - { PKEY_Endpoint_Enable_Delay_MFX, &m_fEnableDelayMFX }, }; for (int i = 0; i < ARRAYSIZE(controls); i++) diff --git a/audio/sysvad/SwapAPO/APO/swapaposfx.cpp b/audio/sysvad/SwapAPO/APO/swapaposfx.cpp index 32ddb7fc..c7bba1e1 100644 --- a/audio/sysvad/SwapAPO/APO/swapaposfx.cpp +++ b/audio/sysvad/SwapAPO/APO/swapaposfx.cpp @@ -128,38 +128,19 @@ STDMETHODIMP_(void) CSwapAPOSFX::APOProcess( ppInputConnections[0]->u32ValidFrameCount, m_u32SamplesPerFrame); } - - // copy to the delay buffer - if ( - !IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) && - m_fEnableDelaySFX - ) - { - ProcessDelay(pf32OutputFrames, pf32InputFrames, - ppInputConnections[0]->u32ValidFrameCount, - GetSamplesPerFrame(), - m_pf32DelayBuffer, - m_nDelayFrames, - &m_iDelayIndex); - // we don't try to remember silence - ppOutputConnections[0]->u32BufferFlags = BUFFER_VALID; - } - else + // copy the memory only if there is an output connection, and input/output pointers are unequal + if ( (0 != u32NumOutputConnections) && + (ppOutputConnections[0]->pBuffer != ppInputConnections[0]->pBuffer) ) { - // copy the memory only if there is an output connection, and input/output pointers are unequal - if ( (0 != u32NumOutputConnections) && - (ppOutputConnections[0]->pBuffer != ppInputConnections[0]->pBuffer) ) - { - CopyFrames( pf32OutputFrames, pf32InputFrames, - ppInputConnections[0]->u32ValidFrameCount, - GetSamplesPerFrame() ); - } - - // pass along buffer flags - ppOutputConnections[0]->u32BufferFlags = ppInputConnections[0]->u32BufferFlags; + CopyFrames( pf32OutputFrames, pf32InputFrames, + ppInputConnections[0]->u32ValidFrameCount, + GetSamplesPerFrame() ); } + // pass along buffer flags + ppOutputConnections[0]->u32BufferFlags = ppInputConnections[0]->u32BufferFlags; + // Set the valid frame count. ppOutputConnections[0]->u32ValidFrameCount = ppInputConnections[0]->u32ValidFrameCount; @@ -195,14 +176,7 @@ STDMETHODIMP CSwapAPOSFX::GetLatency(HNSTIME* pTime) IF_TRUE_ACTION_JUMP(NULL == pTime, hr = E_POINTER, Exit); - if (IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)) - { - *pTime = 0; - } - else - { - *pTime = (m_fEnableDelaySFX ? HNS_DELAY : 0); - } + *pTime = 0; Exit: return hr; @@ -238,30 +212,6 @@ STDMETHODIMP CSwapAPOSFX::LockForProcess(UINT32 u32NumInputConnections, ppInputConnections, u32NumOutputConnections, ppOutputConnections); IF_FAILED_JUMP(hr, Exit); - if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) && m_fEnableDelaySFX) - { - m_nDelayFrames = FRAMES_FROM_HNS(HNS_DELAY); - m_iDelayIndex = 0; - - m_pf32DelayBuffer.Free(); - - // Allocate one second's worth of audio - // - // This allocation is being done using CoTaskMemAlloc because the delay is very large - // This introduces a risk of glitches if the delay buffer gets paged out - // - // A more typical approach would be to allocate the memory using AERT_Allocate, which locks the memory - // But for the purposes of this APO, CoTaskMemAlloc suffices, and the risk of glitches is not important - m_pf32DelayBuffer.Allocate(GetSamplesPerFrame() * m_nDelayFrames); - - WriteSilence(m_pf32DelayBuffer, m_nDelayFrames, GetSamplesPerFrame()); - if (nullptr == m_pf32DelayBuffer) - { - hr = E_OUTOFMEMORY; - goto Exit; - } - } - Exit: return hr; } @@ -417,7 +367,6 @@ HRESULT CSwapAPOSFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) if (m_spAPOSystemEffectsProperties != NULL) { m_fEnableSwapSFX = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, PKEY_Endpoint_Enable_Channel_Swap_SFX, m_AudioProcessingMode); - m_fEnableDelaySFX = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, PKEY_Endpoint_Enable_Delay_SFX, m_AudioProcessingMode); } // @@ -508,7 +457,6 @@ STDMETHODIMP CSwapAPOSFX::GetEffectsList(_Outptr_result_buffer_maybenull_(*pcEff EffectControl list[] = { { SwapEffectId, m_fEnableSwapSFX }, - { DelayEffectId, m_fEnableDelaySFX }, }; if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)) @@ -591,7 +539,6 @@ HRESULT CSwapAPOSFX::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERT // If either the master disable or our APO's enable properties changed... if (PK_EQUAL(key, PKEY_Endpoint_Enable_Channel_Swap_SFX) || - PK_EQUAL(key, PKEY_Endpoint_Enable_Delay_SFX) || PK_EQUAL(key, PKEY_AudioEndpoint_Disable_SysFx)) { LONG nChanges = 0; @@ -608,7 +555,6 @@ HRESULT CSwapAPOSFX::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERT KeyControl controls[] = { { PKEY_Endpoint_Enable_Channel_Swap_SFX, &m_fEnableSwapSFX }, - { PKEY_Endpoint_Enable_Delay_SFX, &m_fEnableDelaySFX }, }; for (int i = 0; i < ARRAYSIZE(controls); i++) diff --git a/audio/sysvad/SwapAPO/DelayAPO/Delay.cpp b/audio/sysvad/SwapAPO/DelayAPO/Delay.cpp new file mode 100644 index 00000000..721de3ef --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/Delay.cpp @@ -0,0 +1,112 @@ +// +// Delay.cpp -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Description: +// +// Implementation of ProcessDelay +// +#include <atlbase.h> +#include <atlcom.h> +#include <atlcoll.h> +#include <atlsync.h> +#include <mmreg.h> + +#include <audioenginebaseapo.h> +#include <baseaudioprocessingobject.h> +#include <resource.h> + +#include <float.h> + +#include "DelayAPO.h" + +#pragma AVRT_CODE_BEGIN +void WriteSilence( + _Out_writes_(u32FrameCount * u32SamplesPerFrame) + FLOAT32 *pf32Frames, + UINT32 u32FrameCount, + UINT32 u32SamplesPerFrame ) +{ + ZeroMemory(pf32Frames, sizeof(FLOAT32) * u32FrameCount * u32SamplesPerFrame); +} +#pragma AVRT_CODE_END + +#pragma AVRT_CODE_BEGIN +void CopyFrames( + _Out_writes_(u32FrameCount * u32SamplesPerFrame) + FLOAT32 *pf32OutFrames, + _In_reads_(u32FrameCount * u32SamplesPerFrame) + const FLOAT32 *pf32InFrames, + UINT32 u32FrameCount, + UINT32 u32SamplesPerFrame ) +{ + CopyMemory(pf32OutFrames, pf32InFrames, sizeof(FLOAT32) * u32FrameCount * u32SamplesPerFrame); +} +#pragma AVRT_CODE_END + +#pragma AVRT_CODE_BEGIN +void ProcessDelay( + _Out_writes_(u32ValidFrameCount * u32SamplesPerFrame) + FLOAT32 *pf32OutputFrames, + _In_reads_(u32ValidFrameCount * u32SamplesPerFrame) + const FLOAT32 *pf32InputFrames, + UINT32 u32ValidFrameCount, + UINT32 u32SamplesPerFrame, + _Inout_updates_(u32DelayFrames * u32SamplesPerFrame) + FLOAT32 *pf32DelayBuffer, + UINT32 u32DelayFrames, + _Inout_ + UINT32 *pu32DelayIndex ) +{ + ASSERT_REALTIME(); + ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32InputFrames) ); + ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32OutputFrames) ); + + if (u32DelayFrames == 0) + { + CopyFrames( pf32OutputFrames, + pf32InputFrames, + u32ValidFrameCount, + u32SamplesPerFrame ); + } + else + { + + // Invariants: + // 0 <= (*pu32DelayIndex) < u32DelayFrames + // pf32OutputFrames[0 ... u32ValidFrameCount * u32SamplesPerFrame - 1] is writable + // pf32InputFrames[0 ... u32ValidFrameCount * u32SamplesPerFrame - 1] is readable + while (u32ValidFrameCount > 0) + { + // copy either the rest of the input/output buffer, + // or the rest of the delay buffer, + // whichever is smaller + UINT32 framesToCopy = min(u32ValidFrameCount, u32DelayFrames - (*pu32DelayIndex)); + + // delay => output +#pragma prefast(suppress: __WARNING_POTENTIAL_BUFFER_OVERFLOW_HIGH_PRIORITY, "this copy to pf32OutputFrames is in-range") + CopyFrames( pf32OutputFrames, + &pf32DelayBuffer[(*pu32DelayIndex) * u32SamplesPerFrame], + framesToCopy, + u32SamplesPerFrame ); + + // input => delay + CopyFrames( &pf32DelayBuffer[(*pu32DelayIndex) * u32SamplesPerFrame], + pf32InputFrames, + framesToCopy, + u32SamplesPerFrame ); + + pf32OutputFrames += framesToCopy * u32SamplesPerFrame; + pf32InputFrames += framesToCopy * u32SamplesPerFrame; + u32ValidFrameCount -= framesToCopy; + + *pu32DelayIndex += framesToCopy; + if (*pu32DelayIndex == u32DelayFrames) + { + *pu32DelayIndex = 0; + } + } + + } +} +#pragma AVRT_CODE_END + diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPO.h b/audio/sysvad/SwapAPO/DelayAPO/DelayAPO.h new file mode 100644 index 00000000..e59fccf7 --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPO.h @@ -0,0 +1,294 @@ +// +// DelayAPO.h -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Description: +// +// Declaration of the CDelayAPO class. +// + +#pragma once + +#include <audioenginebaseapo.h> +#include <BaseAudioProcessingObject.h> +#include <DelayAPOInterface.h> +#include <DelayAPODll.h> + +#include <commonmacros.h> +#include <devicetopology.h> + +_Analysis_mode_(_Analysis_code_type_user_driver_) + +#define PK_EQUAL(x, y) ((x.fmtid == y.fmtid) && (x.pid == y.pid)) + +// +// Define a GUID identifying the type of this APO's custom effect. +// +// APOs generally should not define new GUIDs for types of effects and instead +// should use predefined effect types. Only define a new GUID if the effect is +// truly very different from all predefined types of effects. +// +// {29FBFBB5-9002-4ABC-DCBC-DD45462478C8} +DEFINE_GUID(DelayEffectId, 0x29FBFBB5, 0x9002, 0x4ABC, 0xDC, 0xBC, 0xDD, 0x45, 0x46, 0x24, 0x78, 0xC8); + +// 1000 ms of delay +#define HNS_DELAY HNS_PER_SECOND + +#define FRAMES_FROM_HNS(hns) (ULONG)(1.0 * hns / HNS_PER_SECOND * GetFramesPerSecond() + 0.5) + +LONG GetCurrentEffectsSetting(IPropertyStore* properties, PROPERTYKEY pkeyEnable, GUID processingMode); + +#pragma AVRT_VTABLES_BEGIN +// Delay APO class - MFX +class CDelayAPOMFX : + public CComObjectRootEx<CComMultiThreadModel>, + public CComCoClass<CDelayAPOMFX, &CLSID_DelayAPOMFX>, + public CBaseAudioProcessingObject, + public IMMNotificationClient, + public IAudioSystemEffects2, + // IAudioSystemEffectsCustomFormats may be optionally supported + // by APOs that attach directly to the connector in the DEFAULT mode streaming graph + public IAudioSystemEffectsCustomFormats, + public IDelayAPOMFX +{ +public: + // constructor + CDelayAPOMFX() + : CBaseAudioProcessingObject(sm_RegProperties) + , m_hEffectsChangedEvent(NULL) + , m_AudioProcessingMode(AUDIO_SIGNALPROCESSINGMODE_DEFAULT) + , m_fEnableDelayMFX(FALSE) + , m_nDelayFrames(0) + , m_iDelayIndex(0) + { + m_pf32Coefficients = NULL; + } + + virtual ~CDelayAPOMFX(); // destructor + +DECLARE_REGISTRY_RESOURCEID(IDR_DELAYAPOMFX) + +BEGIN_COM_MAP(CDelayAPOMFX) + COM_INTERFACE_ENTRY(IDelayAPOMFX) + COM_INTERFACE_ENTRY(IAudioSystemEffects) + COM_INTERFACE_ENTRY(IAudioSystemEffects2) + // IAudioSystemEffectsCustomFormats may be optionally supported + // by APOs that attach directly to the connector in the DEFAULT mode streaming graph + COM_INTERFACE_ENTRY(IAudioSystemEffectsCustomFormats) + COM_INTERFACE_ENTRY(IMMNotificationClient) + COM_INTERFACE_ENTRY(IAudioProcessingObjectRT) + COM_INTERFACE_ENTRY(IAudioProcessingObject) + COM_INTERFACE_ENTRY(IAudioProcessingObjectConfiguration) +END_COM_MAP() + +DECLARE_PROTECT_FINAL_CONSTRUCT() + +public: + STDMETHOD_(void, APOProcess)(UINT32 u32NumInputConnections, + APO_CONNECTION_PROPERTY** ppInputConnections, UINT32 u32NumOutputConnections, + APO_CONNECTION_PROPERTY** ppOutputConnections); + + STDMETHOD(GetLatency)(HNSTIME* pTime); + + STDMETHOD(LockForProcess)(UINT32 u32NumInputConnections, + APO_CONNECTION_DESCRIPTOR** ppInputConnections, + UINT32 u32NumOutputConnections, APO_CONNECTION_DESCRIPTOR** ppOutputConnections); + + STDMETHOD(Initialize)(UINT32 cbDataSize, BYTE* pbyData); + + // IAudioSystemEffects2 + STDMETHOD(GetEffectsList)(_Outptr_result_buffer_maybenull_(*pcEffects) LPGUID *ppEffectsIds, _Out_ UINT *pcEffects, _In_ HANDLE Event); + + virtual HRESULT ValidateAndCacheConnectionInfo( + UINT32 u32NumInputConnections, + APO_CONNECTION_DESCRIPTOR** ppInputConnections, + UINT32 u32NumOutputConnections, + APO_CONNECTION_DESCRIPTOR** ppOutputConnections); + + // IMMNotificationClient + STDMETHODIMP OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) + { + UNREFERENCED_PARAMETER(pwstrDeviceId); + UNREFERENCED_PARAMETER(dwNewState); + return S_OK; + } + STDMETHODIMP OnDeviceAdded(LPCWSTR pwstrDeviceId) + { + UNREFERENCED_PARAMETER(pwstrDeviceId); + return S_OK; + } + STDMETHODIMP OnDeviceRemoved(LPCWSTR pwstrDeviceId) + { + UNREFERENCED_PARAMETER(pwstrDeviceId); + return S_OK; + } + STDMETHODIMP OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) + { + UNREFERENCED_PARAMETER(flow); + UNREFERENCED_PARAMETER(role); + UNREFERENCED_PARAMETER(pwstrDefaultDeviceId); + return S_OK; + } + STDMETHODIMP OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key); + + // IAudioSystemEffectsCustomFormats + // This interface may be optionally supported by APOs that attach directly to the connector in the DEFAULT mode streaming graph + STDMETHODIMP GetFormatCount(UINT* pcFormats); + STDMETHODIMP GetFormat(UINT nFormat, IAudioMediaType** ppFormat); + STDMETHODIMP GetFormatRepresentation(UINT nFormat, _Outptr_ LPWSTR* ppwstrFormatRep); + +public: + LONG m_fEnableDelayMFX; + GUID m_AudioProcessingMode; + CComPtr<IPropertyStore> m_spAPOSystemEffectsProperties; + CComPtr<IMMDeviceEnumerator> m_spEnumerator; + static const CRegAPOProperties<1> sm_RegProperties; // registration properties + + // Locked memory + FLOAT32 *m_pf32Coefficients; + + CComHeapPtr<FLOAT32> m_pf32DelayBuffer; + UINT32 m_nDelayFrames; + UINT32 m_iDelayIndex; + +private: + CCriticalSection m_EffectsLock; + HANDLE m_hEffectsChangedEvent; + + HRESULT ProprietaryCommunicationWithDriver(APOInitSystemEffects2 *_pAPOSysFxInit2); + +}; +#pragma AVRT_VTABLES_END + + +#pragma AVRT_VTABLES_BEGIN +// Delay APO class - SFX +class CDelayAPOSFX : + public CComObjectRootEx<CComMultiThreadModel>, + public CComCoClass<CDelayAPOSFX, &CLSID_DelayAPOSFX>, + public CBaseAudioProcessingObject, + public IMMNotificationClient, + public IAudioSystemEffects2, + public IDelayAPOSFX +{ +public: + // constructor + CDelayAPOSFX() + : CBaseAudioProcessingObject(sm_RegProperties) + , m_hEffectsChangedEvent(NULL) + , m_AudioProcessingMode(AUDIO_SIGNALPROCESSINGMODE_DEFAULT) + , m_fEnableDelaySFX(FALSE) + , m_nDelayFrames(0) + , m_iDelayIndex(0) + { + } + + virtual ~CDelayAPOSFX(); // destructor + +DECLARE_REGISTRY_RESOURCEID(IDR_DELAYAPOSFX) + +BEGIN_COM_MAP(CDelayAPOSFX) + COM_INTERFACE_ENTRY(IDelayAPOSFX) + COM_INTERFACE_ENTRY(IAudioSystemEffects) + COM_INTERFACE_ENTRY(IAudioSystemEffects2) + COM_INTERFACE_ENTRY(IMMNotificationClient) + COM_INTERFACE_ENTRY(IAudioProcessingObjectRT) + COM_INTERFACE_ENTRY(IAudioProcessingObject) + COM_INTERFACE_ENTRY(IAudioProcessingObjectConfiguration) +END_COM_MAP() + +DECLARE_PROTECT_FINAL_CONSTRUCT() + +public: + STDMETHOD_(void, APOProcess)(UINT32 u32NumInputConnections, + APO_CONNECTION_PROPERTY** ppInputConnections, UINT32 u32NumOutputConnections, + APO_CONNECTION_PROPERTY** ppOutputConnections); + + STDMETHOD(GetLatency)(HNSTIME* pTime); + + STDMETHOD(LockForProcess)(UINT32 u32NumInputConnections, + APO_CONNECTION_DESCRIPTOR** ppInputConnections, + UINT32 u32NumOutputConnections, APO_CONNECTION_DESCRIPTOR** ppOutputConnections); + + STDMETHOD(Initialize)(UINT32 cbDataSize, BYTE* pbyData); + + // IAudioSystemEffects2 + STDMETHOD(GetEffectsList)(_Outptr_result_buffer_maybenull_(*pcEffects) LPGUID *ppEffectsIds, _Out_ UINT *pcEffects, _In_ HANDLE Event); + + // IMMNotificationClient + STDMETHODIMP OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) + { + UNREFERENCED_PARAMETER(pwstrDeviceId); + UNREFERENCED_PARAMETER(dwNewState); + return S_OK; + } + STDMETHODIMP OnDeviceAdded(LPCWSTR pwstrDeviceId) + { + UNREFERENCED_PARAMETER(pwstrDeviceId); + return S_OK; + } + STDMETHODIMP OnDeviceRemoved(LPCWSTR pwstrDeviceId) + { + UNREFERENCED_PARAMETER(pwstrDeviceId); + return S_OK; + } + STDMETHODIMP OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) + { + UNREFERENCED_PARAMETER(flow); + UNREFERENCED_PARAMETER(role); + UNREFERENCED_PARAMETER(pwstrDefaultDeviceId); + return S_OK; + } + STDMETHODIMP OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key); + +public: + LONG m_fEnableDelaySFX; + GUID m_AudioProcessingMode; + CComPtr<IPropertyStore> m_spAPOSystemEffectsProperties; + CComPtr<IMMDeviceEnumerator> m_spEnumerator; + static const CRegAPOProperties<1> sm_RegProperties; // registration properties + + CCriticalSection m_EffectsLock; + HANDLE m_hEffectsChangedEvent; + + CComHeapPtr<FLOAT32> m_pf32DelayBuffer; + UINT32 m_nDelayFrames; + UINT32 m_iDelayIndex; +}; +#pragma AVRT_VTABLES_END + +OBJECT_ENTRY_AUTO(__uuidof(DelayAPOMFX), CDelayAPOMFX) +OBJECT_ENTRY_AUTO(__uuidof(DelayAPOSFX), CDelayAPOSFX) + +// +// Declaration of the ProcessDelay routine. +// +void ProcessDelay( + _Out_writes_(u32ValidFrameCount * u32SamplesPerFrame) + FLOAT32 *pf32OutputFrames, + _In_reads_(u32ValidFrameCount * u32SamplesPerFrame) + const FLOAT32 *pf32InputFrames, + UINT32 u32ValidFrameCount, + UINT32 u32SamplesPerFrame, + _Inout_updates_(u32DelayFrames * u32SamplesPerFrame) + FLOAT32 *pf32DelayBuffer, + UINT32 u32DelayFrames, + _Inout_ + UINT32 *pu32DelayIndex ); + +// +// Convenience methods +// + +void WriteSilence( + _Out_writes_(u32FrameCount * u32SamplesPerFrame) + FLOAT32 *pf32Frames, + UINT32 u32FrameCount, + UINT32 u32SamplesPerFrame ); + +void CopyFrames( + _Out_writes_(u32FrameCount * u32SamplesPerFrame) + FLOAT32 *pf32OutFrames, + _In_reads_(u32FrameCount * u32SamplesPerFrame) + const FLOAT32 *pf32InFrames, + UINT32 u32FrameCount, + UINT32 u32SamplesPerFrame ); diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPO.vcxproj b/audio/sysvad/SwapAPO/DelayAPO/DelayAPO.vcxproj new file mode 100644 index 00000000..229ce262 --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPO.vcxproj @@ -0,0 +1,250 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{8851ab85-70b3-4798-a149-ba366df9ec25}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <SupportsPackaging>false</SupportsPackaging> + <RequiresPackageProject>true</RequiresPackageProject> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{D5CCDCB1-348E-414E-BB0F-33C773760034}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>DelayAPO</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>DelayAPO</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>DelayAPO</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>DelayAPO</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary /> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>DelayAPODll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary /> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>DelayAPODll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary /> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>DelayAPODll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary /> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>DelayAPODll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="Delay.cpp" /> + <ClCompile Include="DelayAPODll.cpp" /> + <ClCompile Include="DelayAPOMFX.cpp " /> + <ClCompile Include="DelayAPOSFX.cpp" /> + <Midl Include="DelayAPODll.idl" /> + <Midl Include="DelayAPOInterface.idl" /> + <ResourceCompile Include="DelayAPODll.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project> diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.cpp b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.cpp new file mode 100644 index 00000000..032c3c9d --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.cpp @@ -0,0 +1,148 @@ +// +// DelayAPODll.cpp -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Author: +// +// Description: +// +// DelayAPODll.cpp : Implementation of DLL Exports. + +#include <atlbase.h> +#include <atlcom.h> +#include <atlcoll.h> +#include <atlsync.h> +#include <mmreg.h> + +#include "resource.h" +#include "DelayAPODll.h" +#include <DelayAPO.h> + +#include <DelayAPODll_i.c> + +//------------------------------------------------------------------------- +// Array of APO_REG_PROPERTIES structures implemented in this module. +// Each new APO implementation will be added to this array. +// +APO_REG_PROPERTIES const *gCoreAPOs[] = +{ + &CDelayAPOMFX::sm_RegProperties.m_Properties, + &CDelayAPOSFX::sm_RegProperties.m_Properties +}; + +// {secret} +class CDelayAPODllModule : public CAtlDllModuleT< CDelayAPODllModule > +{ +public : + DECLARE_LIBID(LIBID_DelayAPODlllib) + DECLARE_REGISTRY_APPID_RESOURCEID(IDR_DELAYAPODLL, "{0A21D954-674A-4C09-806E-DB4FBE8F199C}") +public: + HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) throw(); + HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE) throw(); +}; + +// {secret} +CDelayAPODllModule _AtlModule; + + +HRESULT CDelayAPODllModule::DllRegisterServer(BOOL bRegTypeLib) throw() +{ + HRESULT hResult; + UINT32 u32APORegIndex = 0; + UINT32 u32APOUnregIndex = 0; + + // Register all APOs implemented in this module. + for (u32APORegIndex = 0; u32APORegIndex < SIZEOF_ARRAY(gCoreAPOs); u32APORegIndex++) + { + hResult = RegisterAPO(gCoreAPOs[u32APORegIndex]); + if (FAILED(hResult)) + { + goto ExitFailed; + } + } + + // Register the module. + hResult = CAtlDllModuleT<CDelayAPODllModule>::DllRegisterServer(bRegTypeLib); + if (FAILED(hResult)) + { + goto ExitFailed; + } + + return hResult; + +ExitFailed: + // Unregister all registered APOs if something failed. + for (u32APOUnregIndex = 0; u32APOUnregIndex < u32APORegIndex; u32APOUnregIndex++) + { + ATLVERIFY(SUCCEEDED(UnregisterAPO(gCoreAPOs[u32APOUnregIndex]->clsid))); + } + + return hResult; +} // DllRegisterServer + +HRESULT CDelayAPODllModule::DllUnregisterServer(BOOL bUnRegTypeLib) throw() +{ + HRESULT hResult; + UINT32 u32APOUnregIndex = 0; + + // Unregister the module. + hResult = CAtlDllModuleT<CDelayAPODllModule>::UnregisterServer(bUnRegTypeLib); + if (FAILED(hResult)) + { + goto Exit; + } + + // Unregister all the APOs that are implemented in this module. + for (u32APOUnregIndex = 0; u32APOUnregIndex < SIZEOF_ARRAY(gCoreAPOs); u32APOUnregIndex++) + { + hResult = UnregisterAPO(gCoreAPOs[u32APOUnregIndex]->clsid); + ATLASSERT(SUCCEEDED(hResult)); + } + +Exit: + return hResult; +} // DllUnregisterServer + +// {secret} +extern "C" BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD dwReason, LPVOID lpReserved) +{ + if (DLL_PROCESS_ATTACH == dwReason) + { + } + // do necessary cleanup only if the DLL is being unloaded dynamically + else if ((DLL_PROCESS_DETACH == dwReason) && (NULL == lpReserved)) + { + } + + return _AtlModule.DllMain(dwReason, lpReserved); +} + + +// {secret} +STDAPI DllCanUnloadNow(void) +{ + return _AtlModule.DllCanUnloadNow(); +} + + +// {secret} +STDAPI DllGetClassObject(_In_ REFCLSID rclsid,_In_ REFIID riid, _Outptr_ LPVOID* ppv) +{ + return _AtlModule.DllGetClassObject(rclsid, riid, ppv); +} + + +// {secret} +STDAPI DllRegisterServer(void) +{ + // registers object, typelib and all interfaces in typelib + HRESULT hr = _AtlModule.DllRegisterServer(); + return hr; +} + + +// {secret} +STDAPI DllUnregisterServer(void) +{ + HRESULT hr = _AtlModule.DllUnregisterServer(); + return hr; +} diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.def b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.def new file mode 100644 index 00000000..722ab4c4 --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.def @@ -0,0 +1,6 @@ + +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.idl b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.idl new file mode 100644 index 00000000..46b4fe5b --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.idl @@ -0,0 +1,54 @@ +// +// DelayAPODll.idl -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Author: +// +// Description: +// +// DelayAPODll.idl : Definition of COM interfaces and coclasses for the DLL. + +import "oaidl.idl"; +import "ocidl.idl"; +import "DelayAPOInterface.idl"; + +//------------------------------------------------------------------------- +// DelayAPODlllib +// +[ + uuid(8009693f-5bc2-42bb-86bf-82cc651f127f), + version(1.0) +] +library DelayAPODlllib +{ + importlib("stdole2.tlb"); + + // for Delay APO - MFX + [ + uuid(b6c7032b-1f17-4cc6-bcdb-fd96deabc8a9) + ] + coclass DelayAPOMFX + { + interface IAudioProcessingObject; + interface IAudioProcessingObjectRT; + interface IAudioProcessingObjectConfiguration; + interface IMMNotificationClient; + interface IAudioSystemEffects; + [default] interface IDelayAPOMFX; + }; + + // for Delay APO - SFX + [ + uuid(77802b45-a5a0-455a-8204-3dba30eee7b4) + ] + coclass DelayAPOSFX + { + interface IAudioProcessingObject; + interface IAudioProcessingObjectRT; + interface IAudioProcessingObjectConfiguration; + interface IMMNotificationClient; + interface IAudioSystemEffects; + [default] interface IDelayAPOSFX; + }; + + +} diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.rc b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.rc new file mode 100644 index 00000000..8cdc8249 --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.rc @@ -0,0 +1,24 @@ +#if 0 +Copyright (c) Microsoft Corporation. All Rights Reserved +#endif + +#include "resource.h" +#include "winres.h" +#include <ntverp.h> +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Delay APO" +#define VER_INTERNALNAME_STR "DELAYAPODll" +#define VER_ORIGINALFILENAME_STR "DelayAPODll.Dll" +#include <Common.ver> + +IDR_DELAYAPODLL REGISTRY "DelayAPODll.rgs" +IDR_DELAYAPOMFX REGISTRY "DelayAPOMFX.rgs" +IDR_DELAYAPOSFX REGISTRY "DelayAPOSFX.rgs" + +// ICON +IDI_EFFECT_ICON RCDATA "DelayApo.png" + +#if 0 +1 TYPELIB "DelayAPODll.tlb" +#endif diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.rgs b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.rgs new file mode 100644 index 00000000..5ccba570 --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.rgs @@ -0,0 +1,11 @@ +HKCR +{ + NoRemove AppID + { + '%APPID%' = s 'DelayAPODll' + 'DelayAPODll.DLL' + { + val AppID = s '%APPID%' + } + } +} diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPOInterface.idl b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOInterface.idl new file mode 100644 index 00000000..f74cd5fb --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOInterface.idl @@ -0,0 +1,29 @@ +// +// DelayAPOInterface.idl -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Description: +// +// The interface and type definitions for Delay APO functionality. +// +import "oaidl.idl"; +import "ocidl.idl"; +import "audioenginebaseapo.idl"; + +[ + object, + uuid(4c0531b4-f2ca-4eae-80cd-020266923bc1), + pointer_default(unique) +] +interface IDelayAPOMFX : IUnknown +{ +}; + +[ + object, + uuid(6269b338-5162-4f14-a94d-8422ee93ec13), + pointer_default(unique) +] +interface IDelayAPOSFX : IUnknown +{ +}; + diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPOMFX.cpp b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOMFX.cpp new file mode 100644 index 00000000..5f5ad2c6 --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOMFX.cpp @@ -0,0 +1,1031 @@ +// +// DelayAPOMFX.cpp -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Description: +// +// Implementation of CDelayAPOMFX +// + +#include <atlbase.h> +#include <atlcom.h> +#include <atlcoll.h> +#include <atlsync.h> +#include <mmreg.h> + +#include <initguid.h> +#include <audioenginebaseapo.h> +#include <baseaudioprocessingobject.h> +#include <resource.h> + +#include <float.h> +#include "DelayAPO.h" +#include "SysVadShared.h" +#include <CustomPropKeys.h> + + + +// Static declaration of the APO_REG_PROPERTIES structure +// associated with this APO. The number in <> brackets is the +// number of IIDs supported by this APO. If more than one, then additional +// IIDs are added at the end +#pragma warning (disable : 4815) +const AVRT_DATA CRegAPOProperties<1> CDelayAPOMFX::sm_RegProperties( + __uuidof(DelayAPOMFX), // clsid of this APO + L"CDelayAPOMFX", // friendly name of this APO + L"Copyright (c) Microsoft Corporation", // copyright info + 1, // major version # + 0, // minor version # + __uuidof(IDelayAPOMFX) // iid of primary interface +// +// If you need to change any of these attributes, uncomment everything up to +// the point that you need to change something. If you need to add IIDs, uncomment +// everything and add additional IIDs at the end. +// +// Enable inplace processing for this APO. +// , DEFAULT_APOREG_FLAGS +// , DEFAULT_APOREG_MININPUTCONNECTIONS +// , DEFAULT_APOREG_MAXINPUTCONNECTIONS +// , DEFAULT_APOREG_MINOUTPUTCONNECTIONS +// , DEFAULT_APOREG_MAXOUTPUTCONNECTIONS +// , DEFAULT_APOREG_MAXINSTANCES +// + ); + +//------------------------------------------------------------------------- +// Description: +// +// GetCurrentEffectsSetting +// Gets the current aggregate effects-enable setting +// +// Parameters: +// +// properties - Property store holding configurable effects settings +// +// pkeyEnable - VT_UI4 property holding an enable/disable setting +// +// processingMode - Audio processing mode +// +// Return values: +// LONG - true if the effect is enabled +// +// Remarks: +// The routine considers the value of the specified property, the well known +// master PKEY_AudioEndpoint_Disable_SysFx property, and the specified +// processing mode.If the processing mode is RAW then the effect is off. If +// PKEY_AudioEndpoint_Disable_SysFx is non-zero then the effect is off. +// +LONG GetCurrentEffectsSetting(IPropertyStore* properties, PROPERTYKEY pkeyEnable, GUID processingMode) +{ + HRESULT hr; + BOOL enabled; + PROPVARIANT var; + + PropVariantInit(&var); + + // Get the state of whether channel swap MFX is enabled or not. + + // Check the master disable property defined by Windows + hr = properties->GetValue(PKEY_AudioEndpoint_Disable_SysFx, &var); + enabled = (SUCCEEDED(hr)) && !((var.vt == VT_UI4) && (var.ulVal != 0)); + + PropVariantClear(&var); + + // Check the APO's enable property, defined by this APO. + hr = properties->GetValue(pkeyEnable, &var); + enabled = enabled && ((SUCCEEDED(hr)) && ((var.vt == VT_UI4) && (var.ulVal != 0))); + + PropVariantClear(&var); + + enabled = enabled && !IsEqualGUID(processingMode, AUDIO_SIGNALPROCESSINGMODE_RAW); + + return (LONG)enabled; +} + +#pragma AVRT_CODE_BEGIN +//------------------------------------------------------------------------- +// Description: +// +// Do the actual processing of data. +// +// Parameters: +// +// u32NumInputConnections - [in] number of input connections +// ppInputConnections - [in] pointer to list of input APO_CONNECTION_PROPERTY pointers +// u32NumOutputConnections - [in] number of output connections +// ppOutputConnections - [in] pointer to list of output APO_CONNECTION_PROPERTY pointers +// +// Return values: +// +// void +// +// Remarks: +// +// This function processes data in a manner dependent on the implementing +// object. This routine can not fail and can not block, or call any other +// routine that blocks, or touch pagable memory. +// +STDMETHODIMP_(void) CDelayAPOMFX::APOProcess( + UINT32 u32NumInputConnections, + APO_CONNECTION_PROPERTY** ppInputConnections, + UINT32 u32NumOutputConnections, + APO_CONNECTION_PROPERTY** ppOutputConnections) +{ + UNREFERENCED_PARAMETER(u32NumInputConnections); + UNREFERENCED_PARAMETER(u32NumOutputConnections); + + FLOAT32 *pf32InputFrames, *pf32OutputFrames; + + ATLASSERT(m_bIsLocked); + + // assert that the number of input and output connectins fits our registration properties + ATLASSERT(m_pRegProperties->u32MinInputConnections <= u32NumInputConnections); + ATLASSERT(m_pRegProperties->u32MaxInputConnections >= u32NumInputConnections); + ATLASSERT(m_pRegProperties->u32MinOutputConnections <= u32NumOutputConnections); + ATLASSERT(m_pRegProperties->u32MaxOutputConnections >= u32NumOutputConnections); + + // check APO_BUFFER_FLAGS. + switch( ppInputConnections[0]->u32BufferFlags ) + { + case BUFFER_INVALID: + { + ATLASSERT(false); // invalid flag - should never occur. don't do anything. + break; + } + case BUFFER_VALID: + case BUFFER_SILENT: + { + // get input pointer to connection buffer + pf32InputFrames = reinterpret_cast<FLOAT32*>(ppInputConnections[0]->pBuffer); + ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32InputFrames) ); + + // get output pointer to connection buffer + pf32OutputFrames = reinterpret_cast<FLOAT32*>(ppOutputConnections[0]->pBuffer); + ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32OutputFrames) ); + + if (BUFFER_SILENT == ppInputConnections[0]->u32BufferFlags) + { + WriteSilence( pf32InputFrames, + ppInputConnections[0]->u32ValidFrameCount, + GetSamplesPerFrame() ); + } + + // copy to the delay buffer + if ( + !IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) && + m_fEnableDelayMFX + ) + { + ProcessDelay(pf32OutputFrames, pf32InputFrames, + ppInputConnections[0]->u32ValidFrameCount, + GetSamplesPerFrame(), + m_pf32DelayBuffer, + m_nDelayFrames, + &m_iDelayIndex); + + // we don't try to remember silence + ppOutputConnections[0]->u32BufferFlags = BUFFER_VALID; + } + else + { + // copy the memory only if there is an output connection, and input/output pointers are unequal + if ( (0 != u32NumOutputConnections) && + (ppOutputConnections[0]->pBuffer != ppInputConnections[0]->pBuffer) ) + { + CopyFrames( pf32OutputFrames, pf32InputFrames, + ppInputConnections[0]->u32ValidFrameCount, + GetSamplesPerFrame() ); + } + + // pass along buffer flags + ppOutputConnections[0]->u32BufferFlags = ppInputConnections[0]->u32BufferFlags; + } + + // Set the valid frame count. + ppOutputConnections[0]->u32ValidFrameCount = ppInputConnections[0]->u32ValidFrameCount; + + break; + } + default: + { + ATLASSERT(false); // invalid flag - should never occur + break; + } + } // switch + +} // APOProcess +#pragma AVRT_CODE_END + +//------------------------------------------------------------------------- +// Description: +// +// Report delay added by the APO between samples given on input +// and samples given on output. +// +// Parameters: +// +// pTime - [out] hundreds-of-nanoseconds of delay added +// +// Return values: +// +// S_OK on success, a failure code on failure +STDMETHODIMP CDelayAPOMFX::GetLatency(HNSTIME* pTime) +{ + ASSERT_NONREALTIME(); + HRESULT hr = S_OK; + + IF_TRUE_ACTION_JUMP(NULL == pTime, hr = E_POINTER, Exit); + + if (IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)) + { + *pTime = 0; + } + else + { + *pTime = (m_fEnableDelayMFX ? HNS_DELAY : 0); + } + +Exit: + return hr; +} + +//------------------------------------------------------------------------- +// Description: +// +// Verifies that the APO is ready to process and locks its state if so. +// +// Parameters: +// +// u32NumInputConnections - [in] number of input connections attached to this APO +// ppInputConnections - [in] connection descriptor of each input connection attached to this APO +// u32NumOutputConnections - [in] number of output connections attached to this APO +// ppOutputConnections - [in] connection descriptor of each output connection attached to this APO +// +// Return values: +// +// S_OK Object is locked and ready to process. +// E_POINTER Invalid pointer passed to function. +// APOERR_INVALID_CONNECTION_FORMAT Invalid connection format. +// APOERR_NUM_CONNECTIONS_INVALID Number of input or output connections is not valid on +// this APO. +STDMETHODIMP CDelayAPOMFX::LockForProcess(UINT32 u32NumInputConnections, + APO_CONNECTION_DESCRIPTOR** ppInputConnections, + UINT32 u32NumOutputConnections, APO_CONNECTION_DESCRIPTOR** ppOutputConnections) +{ + ASSERT_NONREALTIME(); + HRESULT hr = S_OK; + + hr = CBaseAudioProcessingObject::LockForProcess(u32NumInputConnections, + ppInputConnections, u32NumOutputConnections, ppOutputConnections); + IF_FAILED_JUMP(hr, Exit); + + if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) && m_fEnableDelayMFX) + { + m_nDelayFrames = FRAMES_FROM_HNS(HNS_DELAY); + m_iDelayIndex = 0; + + m_pf32DelayBuffer.Free(); + + // Allocate one second's worth of audio + // + // This allocation is being done using CoTaskMemAlloc because the delay is very large + // This introduces a risk of glitches if the delay buffer gets paged out + // + // A more typical approach would be to allocate the memory using AERT_Allocate, which locks the memory + // But for the purposes of this APO, CoTaskMemAlloc suffices, and the risk of glitches is not important + m_pf32DelayBuffer.Allocate(GetSamplesPerFrame() * m_nDelayFrames); + WriteSilence(m_pf32DelayBuffer, m_nDelayFrames, GetSamplesPerFrame()); + if (nullptr == m_pf32DelayBuffer) + { + hr = E_OUTOFMEMORY; + goto Exit; + } + } + +Exit: + return hr; +} + +// The method that this long comment refers to is "Initialize()" +//------------------------------------------------------------------------- +// Description: +// +// Generic initialization routine for APOs. +// +// Parameters: +// +// cbDataSize - [in] the size in bytes of the initialization data. +// pbyData - [in] initialization data specific to this APO +// +// Return values: +// +// S_OK Successful completion. +// E_POINTER Invalid pointer passed to this function. +// E_INVALIDARG Invalid argument +// AEERR_ALREADY_INITIALIZED APO is already initialized +// +// Remarks: +// +// This method initializes the APO. The data is variable length and +// should have the form of: +// +// struct MyAPOInitializationData +// { +// APOInitBaseStruct APOInit; +// ... // add additional fields here +// }; +// +// If the APO needs no initialization or needs no data to initialize +// itself, it is valid to pass NULL as the pbyData parameter and 0 as +// the cbDataSize parameter. +// +// As part of designing an APO, decide which parameters should be +// immutable (set once during initialization) and which mutable (changeable +// during the lifetime of the APO instance). Immutable parameters must +// only be specifiable in the Initialize call; mutable parameters must be +// settable via methods on whichever parameter control interface(s) your +// APO provides. Mutable values should either be set in the initialize +// method (if they are required for proper operation of the APO prior to +// LockForProcess) or default to reasonable values upon initialize and not +// be required to be set before LockForProcess. +// +// Within the mutable parameters, you must also decide which can be changed +// while the APO is locked for processing and which cannot. +// +// All parameters should be considered immutable as a first choice, unless +// there is a specific scenario which requires them to be mutable; similarly, +// no mutable parameters should be changeable while the APO is locked, unless +// a specific scenario requires them to be. Following this guideline will +// simplify the APO's state diagram and implementation and prevent certain +// types of bug. +// +// If a parameter changes the APOs latency or MaxXXXFrames values, it must be +// immutable. +// +// The default version of this function uses no initialization data, but does verify +// the passed parameters and set the m_bIsInitialized member to true. +// +// Note: This method may not be called from a real-time processing thread. +// + +HRESULT CDelayAPOMFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) +{ + HRESULT hr = S_OK; + GUID processingMode; + + IF_TRUE_ACTION_JUMP( ((NULL == pbyData) && (0 != cbDataSize)), hr = E_INVALIDARG, Exit); + IF_TRUE_ACTION_JUMP( ((NULL != pbyData) && (0 == cbDataSize)), hr = E_INVALIDARG, Exit); + + if (cbDataSize == sizeof(APOInitSystemEffects2)) + { + // + // Initialize for mode-specific signal processing + // + APOInitSystemEffects2* papoSysFxInit2 = (APOInitSystemEffects2*)pbyData; + + // Save reference to the effects property store. This saves effects settings + // and is the communication medium between this APO and any associated UI. + m_spAPOSystemEffectsProperties = papoSysFxInit2->pAPOSystemEffectsProperties; + + // Windows should pass a valid collection. + ATLASSERT(papoSysFxInit2->pDeviceCollection != nullptr); + IF_TRUE_ACTION_JUMP(papoSysFxInit2->pDeviceCollection == nullptr, hr = E_INVALIDARG, Exit); + + // Save the processing mode being initialized. + processingMode = papoSysFxInit2->AudioProcessingMode; + + // There is information in the APOInitSystemEffects2 structure that could help facilitate + // proprietary communication between an APO instance and the KS pin that the APO is initialized on + // Eg, in the case that an APO is implemented as an effect proxy for the effect processing hosted inside + // an driver (either host CPU based or offload DSP based), the example below uses a combination of + // IDeviceTopology, IConnector, and IKsControl interfaces to communicate with the underlying audio driver. + // the following following routine demonstrates how to implement how to communicate to an audio driver from a APO. + ProprietaryCommunicationWithDriver(papoSysFxInit2); + } + else if (cbDataSize == sizeof(APOInitSystemEffects)) + { + // + // Initialize for default signal processing + // + APOInitSystemEffects* papoSysFxInit = (APOInitSystemEffects*)pbyData; + + // Save reference to the effects property store. This saves effects settings + // and is the communication medium between this APO and any associated UI. + m_spAPOSystemEffectsProperties = papoSysFxInit->pAPOSystemEffectsProperties; + + // Assume default processing mode + processingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT; + } + else + { + // Invalid initialization size + hr = E_INVALIDARG; + goto Exit; + } + + // Validate then save the processing mode. Note an endpoint effects APO + // does not depend on the mode. Windows sets the APOInitSystemEffects2 + // AudioProcessingMode member to GUID_NULL for an endpoint effects APO. + IF_TRUE_ACTION_JUMP((processingMode != AUDIO_SIGNALPROCESSINGMODE_DEFAULT && + processingMode != AUDIO_SIGNALPROCESSINGMODE_RAW && + processingMode != AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS && + processingMode != AUDIO_SIGNALPROCESSINGMODE_SPEECH && + processingMode != AUDIO_SIGNALPROCESSINGMODE_MEDIA && + processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE), hr = E_INVALIDARG, Exit); + m_AudioProcessingMode = processingMode; + + // + // An APO that implements signal processing more complex than this sample + // would configure its processing for the processingMode determined above. + // If necessary, the APO would also use the IDeviceTopology and IConnector + // interfaces retrieved above to communicate with its counterpart audio + // driver to configure any additional signal processing in the driver and + // associated hardware. + // + + // + // Get current effects settings + // + if (m_spAPOSystemEffectsProperties != NULL) + { + m_fEnableDelayMFX = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, PKEY_Endpoint_Enable_Delay_MFX, m_AudioProcessingMode); + } + + // + // Register for notification of registry updates + // + hr = m_spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator)); + IF_FAILED_JUMP(hr, Exit); + + hr = m_spEnumerator->RegisterEndpointNotificationCallback(this); + IF_FAILED_JUMP(hr, Exit); + + m_bIsInitialized = true; +Exit: + return hr; +} + +//------------------------------------------------------------------------- +// +// GetEffectsList +// +// Retrieves the list of signal processing effects currently active and +// stores an event to be signaled if the list changes. +// +// Parameters +// +// ppEffectsIds - returns a pointer to a list of GUIDs each identifying a +// class of effect. The caller is responsible for freeing this memory by +// calling CoTaskMemFree. +// +// pcEffects - returns a count of GUIDs in the list. +// +// Event - passes an event handle. The APO signals this event when the list +// of effects changes from the list returned from this function. The APO +// uses this event until either this function is called again or the APO +// is destroyed. The passed handle may be NULL. In this case, the APO +// stops using any previous handle and does not signal an event. +// +// Remarks +// +// An APO imlements this method to allow Windows to discover the current +// effects applied by the APO. The list of effects may depend on what signal +// processing mode the APO initialized (see AudioProcessingMode in the +// APOInitSystemEffects2 structure) as well as any end user configuration. +// +// If there are no effects then the function still succeeds, ppEffectsIds +// returns a NULL pointer, and pcEffects returns a count of 0. +// +STDMETHODIMP CDelayAPOMFX::GetEffectsList(_Outptr_result_buffer_maybenull_(*pcEffects) LPGUID *ppEffectsIds, _Out_ UINT *pcEffects, _In_ HANDLE Event) +{ + HRESULT hr; + BOOL effectsLocked = FALSE; + UINT cEffects = 0; + + IF_TRUE_ACTION_JUMP(ppEffectsIds == NULL, hr = E_POINTER, Exit); + IF_TRUE_ACTION_JUMP(pcEffects == NULL, hr = E_POINTER, Exit); + + // Synchronize access to the effects list and effects changed event + m_EffectsLock.Enter(); + effectsLocked = TRUE; + + // Always close existing effects change event handle + if (m_hEffectsChangedEvent != NULL) + { + CloseHandle(m_hEffectsChangedEvent); + m_hEffectsChangedEvent = NULL; + } + + // If an event handle was specified, save it here (duplicated to control lifetime) + if (Event != NULL) + { + if (!DuplicateHandle(GetCurrentProcess(), Event, GetCurrentProcess(), &m_hEffectsChangedEvent, EVENT_MODIFY_STATE, FALSE, 0)) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + goto Exit; + } + } + + // naked scope to force the initialization of list[] to be after we enter the critical section + { + struct EffectControl + { + GUID effect; + BOOL control; + }; + + EffectControl list[] = + { + { DelayEffectId, m_fEnableDelayMFX }, + }; + + if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)) + { + // count the active effects + for (UINT i = 0; i < ARRAYSIZE(list); i++) + { + if (list[i].control) + { + cEffects++; + } + } + } + + if (0 == cEffects) + { + *ppEffectsIds = NULL; + *pcEffects = 0; + } + else + { + GUID *pEffectsIds = (LPGUID)CoTaskMemAlloc(sizeof(GUID) * cEffects); + if (pEffectsIds == nullptr) + { + hr = E_OUTOFMEMORY; + goto Exit; + } + + // pick up the active effects + UINT j = 0; + for (UINT i = 0; i < ARRAYSIZE(list); i++) + { + if (list[i].control) + { + pEffectsIds[j++] = list[i].effect; + } + } + + *ppEffectsIds = pEffectsIds; + *pcEffects = cEffects; + } + + hr = S_OK; + } + +Exit: + if (effectsLocked) + { + m_EffectsLock.Leave(); + } + return hr; +} + +HRESULT CDelayAPOMFX::ProprietaryCommunicationWithDriver(APOInitSystemEffects2 *_pAPOSysFxInit2) +{ + HRESULT hr = S_OK; + CComPtr<IMMDevice> spMyDevice; + CComPtr<IDeviceTopology> spMyDeviceTopology; + CComPtr<IConnector> spMyConnector; + CComPtr<IPart> spMyConnectorPart; + CComPtr<IKsControl> spKsControl; + UINT uKsPinId = 0; + UINT myPartId = 0; + + ULONG ulBytesReturned = 0; + CComHeapPtr<KSMULTIPLE_ITEM> spKsMultipleItem; + KSP_PIN ksPin = {0}; + + UINT nSoftwareIoDeviceInCollection = 0 ; + UINT nSoftwareIoConnectorIndex = 0 ; + + nSoftwareIoDeviceInCollection = _pAPOSysFxInit2->nSoftwareIoDeviceInCollection; + nSoftwareIoConnectorIndex = _pAPOSysFxInit2->nSoftwareIoConnectorIndex; + + // Get the target IMMDevice + hr = _pAPOSysFxInit2->pDeviceCollection->Item(nSoftwareIoDeviceInCollection, &spMyDevice); + IF_FAILED_JUMP(hr, Exit); + + // Instantiate a device topology instance + hr = spMyDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); + IF_FAILED_JUMP(hr, Exit); + + // retrieve connect instance + hr = spMyDeviceTopology->GetConnector(nSoftwareIoConnectorIndex, &spMyConnector); + IF_FAILED_JUMP(hr, Exit); + + // activate IKsControl on the IMMDevice + hr = spMyDevice->Activate(__uuidof(IKsControl), CLSCTX_INPROC_SERVER, NULL, (void**)&spKsControl); + IF_FAILED_JUMP(hr, Exit); + + // get KS pin id + hr = spMyConnector->QueryInterface(__uuidof(IPart), (void**)&spMyConnectorPart); + IF_FAILED_JUMP(hr, Exit); + hr = spMyConnectorPart->GetLocalId(&myPartId); + IF_FAILED_JUMP(hr, Exit); + + uKsPinId = myPartId & 0x0000ffff; + + ksPin.Property.Set = KSPROPSETID_SysVAD; + ksPin.Property.Id = KSPROPERTY_SYSVAD_DEFAULTSTREAMEFFECTS; + ksPin.Property.Flags = KSPROPERTY_TYPE_GET; + ksPin.PinId = uKsPinId; + + // First, get size of array returned by driver + hr = spKsControl->KsProperty( &ksPin.Property, + sizeof(KSP_PIN), + NULL, + 0, + &ulBytesReturned ); + IF_FAILED_JUMP(hr, Exit); + + if( !spKsMultipleItem.AllocateBytes(ulBytesReturned) ) + { + hr = E_OUTOFMEMORY; + IF_FAILED_JUMP(hr, Exit); + } + + // Second, now get the active effects from the driver + hr = spKsControl->KsProperty( &ksPin.Property, + sizeof(KSP_PIN), + spKsMultipleItem, + ulBytesReturned, + &ulBytesReturned ); + IF_FAILED_JUMP(hr, Exit); + + // Upon successful return, effect guids could be found in the memory following (spKsMultipleItem.m_pData + 1) + // and effectcount could be found in spKsMultipleItem->Count; + +Exit: + return hr; +} + +//------------------------------------------------------------------------- +// Description: +// +// Implementation of IMMNotificationClient::OnPropertyValueChanged +// +// Parameters: +// +// pwstrDeviceId - [in] the id of the device whose property has changed +// key - [in] the property that changed +// +// Return values: +// +// Ignored by caller +// +// Remarks: +// +// This method is called asynchronously. No UI work should be done here. +// +HRESULT CDelayAPOMFX::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) +{ + HRESULT hr = S_OK; + + UNREFERENCED_PARAMETER(pwstrDeviceId); + + if (!m_spAPOSystemEffectsProperties) + { + return hr; + } + + // If either the master disable or our APO's enable properties changed... + if (PK_EQUAL(key, PKEY_Endpoint_Enable_Delay_MFX) || + PK_EQUAL(key, PKEY_AudioEndpoint_Disable_SysFx)) + { + LONG nChanges = 0; + + // Synchronize access to the effects list and effects changed event + m_EffectsLock.Enter(); + + struct KeyControl + { + PROPERTYKEY key; + LONG *value; + }; + + KeyControl controls[] = + { + { PKEY_Endpoint_Enable_Delay_MFX, &m_fEnableDelayMFX }, + }; + + for (int i = 0; i < ARRAYSIZE(controls); i++) + { + LONG fOldValue; + LONG fNewValue = true; + + // Get the state of whether channel swap MFX is enabled or not + fNewValue = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, controls[i].key, m_AudioProcessingMode); + + // Delay in the new setting + fOldValue = InterlockedExchange(controls[i].value, fNewValue); + + if (fNewValue != fOldValue) + { + nChanges++; + } + } + + // If anything changed and a change event handle exists + if ((nChanges > 0) && (m_hEffectsChangedEvent != NULL)) + { + SetEvent(m_hEffectsChangedEvent); + } + + m_EffectsLock.Leave(); + } + + return hr; +} + +//------------------------------------------------------------------------- +// Description: +// +// Destructor. +// +// Parameters: +// +// void +// +// Return values: +// +// void +// +// Remarks: +// +// This method deletes whatever was allocated. +// +// This method may not be called from a real-time processing thread. +// +CDelayAPOMFX::~CDelayAPOMFX(void) +{ + if (m_bIsInitialized) + { + // + // unregister for callbacks + // + if (m_spEnumerator != NULL) + { + m_spEnumerator->UnregisterEndpointNotificationCallback(this); + } + } + + if (m_hEffectsChangedEvent != NULL) + { + CloseHandle(m_hEffectsChangedEvent); + } + + // Free locked memory allocations + if (NULL != m_pf32Coefficients) + { + AERT_Free(m_pf32Coefficients); + m_pf32Coefficients = NULL; + } +} // ~CDelayAPOMFX + + +//------------------------------------------------------------------------- +// Description: +// +// Validates input/output format pair during LockForProcess. +// +// Parameters: +// +// u32NumInputConnections - [in] number of input connections attached to this APO +// ppInputConnections - [in] format of each input connection attached to this APO +// u32NumOutputConnections - [in] number of output connections attached to this APO +// ppOutputConnections - [in] format of each output connection attached to this APO +// +// Return values: +// +// S_OK Connections are valid. +// +// See Also: +// +// CBaseAudioProcessingObject::LockForProcess +// +// Remarks: +// +// This method is an internal call that is called by the default implementation of +// CBaseAudioProcessingObject::LockForProcess(). This is called after the connections +// are validated for simple conformance to the APO's registration properties. It may be +// used to verify that the APO is initialized properly and that the connections that are passed +// agree with the data used for initialization. Any failure code passed back from this +// function will get returned by LockForProcess, and cause it to fail. +// +// By default, this routine just ASSERTS and returns S_OK. +// +HRESULT CDelayAPOMFX::ValidateAndCacheConnectionInfo(UINT32 u32NumInputConnections, + APO_CONNECTION_DESCRIPTOR** ppInputConnections, + UINT32 u32NumOutputConnections, + APO_CONNECTION_DESCRIPTOR** ppOutputConnections) +{ + ASSERT_NONREALTIME(); + HRESULT hResult; + CComPtr<IAudioMediaType> pFormat; + UNCOMPRESSEDAUDIOFORMAT UncompInputFormat, UncompOutputFormat; + FLOAT32 f32InverseChannelCount; + + UNREFERENCED_PARAMETER(u32NumInputConnections); + UNREFERENCED_PARAMETER(u32NumOutputConnections); + + _ASSERTE(!m_bIsLocked); + _ASSERTE(((0 == u32NumInputConnections) || (NULL != ppInputConnections)) && + ((0 == u32NumOutputConnections) || (NULL != ppOutputConnections))); + + EnterCriticalSection(&m_CritSec); + + // get the uncompressed formats and channel masks + hResult = ppInputConnections[0]->pFormat->GetUncompressedAudioFormat(&UncompInputFormat); + IF_FAILED_JUMP(hResult, Exit); + + hResult = ppOutputConnections[0]->pFormat->GetUncompressedAudioFormat(&UncompOutputFormat); + IF_FAILED_JUMP(hResult, Exit); + + // Since we haven't overridden the IsIn{Out}putFormatSupported APIs in this example, this APO should + // always have input channel count == output channel count. The sampling rates should also be eqaul, + // and formats 32-bit float. + _ASSERTE(UncompOutputFormat.fFramesPerSecond == UncompInputFormat.fFramesPerSecond); + _ASSERTE(UncompOutputFormat. dwSamplesPerFrame == UncompInputFormat.dwSamplesPerFrame); + + // Allocate some locked memory. We will use these as scaling coefficients during APOProcess->ProcessDelayScale + hResult = AERT_Allocate(sizeof(FLOAT32)*m_u32SamplesPerFrame, (void**)&m_pf32Coefficients); + IF_FAILED_JUMP(hResult, Exit); + + // Set scalars to decrease volume from 1.0 to 1.0/N where N is the number of channels + // starting with the first channel. + f32InverseChannelCount = 1.0f/m_u32SamplesPerFrame; + for (UINT16 u16Index=0; u16Index<m_u32SamplesPerFrame; u16Index++) + { + m_pf32Coefficients[u16Index] = 1.0f - (FLOAT32)(f32InverseChannelCount)*u16Index; + } + + +Exit: + LeaveCriticalSection(&m_CritSec); + return hResult;} + +// ---------------------------------------------------------------------- +// ---------------------------------------------------------------------- +// IAudioSystemEffectsCustomFormats implementation + +// +// For demonstration purposes we will add 44.1KHz, 16-bit stereo and 48KHz, 16-bit +// stereo formats. These formats should already be available in mmsys.cpl. We +// embellish the labels to make it obvious that these formats are coming from +// the APO. +// + +// +// Note that the IAudioSystemEffectsCustomFormats interface, if present, is invoked only on APOs +// that attach directly to the connector in the 'DEFAULT' mode streaming graph. For example: +// - APOs implementing global effects +// - APOs implementing endpoint effects +// - APOs implementing DEFAULT mode effects which attach directly to a connector supporting DEFAULT processing mode + +struct CUSTOM_FORMAT_ITEM +{ + WAVEFORMATEXTENSIBLE wfxFmt; + LPCWSTR pwszRep; +}; + +#define STATIC_KSDATAFORMAT_SUBTYPE_AC3\ + DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_DOLBY_AC3_SPDIF) +DEFINE_GUIDSTRUCT("00000092-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_AC3); +#define KSDATAFORMAT_SUBTYPE_AC3 DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_AC3) + +CUSTOM_FORMAT_ITEM _rgCustomFormats[] = +{ + {{ WAVE_FORMAT_EXTENSIBLE, 2, 44100, 176400, 4, 16, sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX), 16, KSAUDIO_SPEAKER_STEREO, KSDATAFORMAT_SUBTYPE_PCM}, L"Custom #1 (really 44.1 KHz, 16-bit, stereo)"}, + {{ WAVE_FORMAT_EXTENSIBLE, 2, 48000, 192000, 4, 16, sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX), 16, KSAUDIO_SPEAKER_STEREO, KSDATAFORMAT_SUBTYPE_PCM}, L"Custom #2 (really 48 KHz, 16-bit, stereo)"}, + {{ WAVE_FORMAT_EXTENSIBLE, 2, 48000, 192000, 4, 16, sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX), 16, KSAUDIO_SPEAKER_STEREO, KSDATAFORMAT_SUBTYPE_AC3}, L"Custom #3 (really 48 KHz AC-3)"} +}; + +#define _cCustomFormats (ARRAYSIZE(_rgCustomFormats)) + +//------------------------------------------------------------------------- +// Description: +// +// Implementation of IAudioSystemEffectsCustomFormats::GetFormatCount +// +// Parameters: +// +// pcFormats - [out] receives the number of formats to be added +// +// Return values: +// +// S_OK Success +// E_POINTER Null pointer passed +// +// Remarks: +// +STDMETHODIMP CDelayAPOMFX::GetFormatCount +( + UINT* pcFormats +) +{ + if (pcFormats == NULL) + return E_POINTER; + + *pcFormats = _cCustomFormats; + return S_OK; +} + +//------------------------------------------------------------------------- +// Description: +// +// Implementation of IAudioSystemEffectsCustomFormats::GetFormat +// +// Parameters: +// +// nFormat - [in] which format is being requested +// IAudioMediaType - [in] address of a variable that will receive a ptr +// to a new IAudioMediaType object +// +// Return values: +// +// S_OK Success +// E_INVALIDARG nFormat is out of range +// E_POINTER Null pointer passed +// +// Remarks: +// +STDMETHODIMP CDelayAPOMFX::GetFormat +( + UINT nFormat, + IAudioMediaType** ppFormat +) +{ + HRESULT hr; + + IF_TRUE_ACTION_JUMP((nFormat >= _cCustomFormats), hr = E_INVALIDARG, Exit); + IF_TRUE_ACTION_JUMP((ppFormat == NULL), hr = E_POINTER, Exit); + + *ppFormat = NULL; + + hr = CreateAudioMediaType( (const WAVEFORMATEX*)&_rgCustomFormats[nFormat].wfxFmt, + sizeof(_rgCustomFormats[nFormat].wfxFmt), + ppFormat); + +Exit: + return hr; +} + +//------------------------------------------------------------------------- +// Description: +// +// Implementation of IAudioSystemEffectsCustomFormats::GetFormatRepresentation +// +// Parameters: +// +// nFormat - [in] which format is being requested +// ppwstrFormatRep - [in] address of a variable that will receive a ptr +// to a new string description of the requested format +// +// Return values: +// +// S_OK Success +// E_INVALIDARG nFormat is out of range +// E_POINTER Null pointer passed +// +// Remarks: +// +STDMETHODIMP CDelayAPOMFX::GetFormatRepresentation +( + UINT nFormat, + _Outptr_ LPWSTR* ppwstrFormatRep +) +{ + HRESULT hr; + size_t cbRep; + LPWSTR pwstrLocal; + + IF_TRUE_ACTION_JUMP((nFormat >= _cCustomFormats), hr = E_INVALIDARG, Exit); + IF_TRUE_ACTION_JUMP((ppwstrFormatRep == NULL), hr = E_POINTER, Exit); + + cbRep = (wcslen(_rgCustomFormats[nFormat].pwszRep) + 1) * sizeof(WCHAR); + + pwstrLocal = (LPWSTR)CoTaskMemAlloc(cbRep); + IF_TRUE_ACTION_JUMP((pwstrLocal == NULL), hr = E_OUTOFMEMORY, Exit); + + hr = StringCbCopyW(pwstrLocal, cbRep, _rgCustomFormats[nFormat].pwszRep); + if (FAILED(hr)) + { + CoTaskMemFree(pwstrLocal); + } + else + { + *ppwstrFormatRep = pwstrLocal; + } + +Exit: + return hr; +} diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPOMFX.rgs b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOMFX.rgs new file mode 100644 index 00000000..0d1f19e2 --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOMFX.rgs @@ -0,0 +1,13 @@ +HKCR +{ + NoRemove CLSID + { + ForceRemove {b6c7032b-1f17-4cc6-bcdb-fd96deabc8a9} = s 'DelayAPOMFX Class' + { + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Both' + } + } + } +} diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPOSFX.cpp b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOSFX.cpp new file mode 100644 index 00000000..81594bb7 --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOSFX.cpp @@ -0,0 +1,662 @@ +// +// DelayAPOSFX.cpp -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Description: +// +// Implementation of CDelayAPOSFX +// + +#include <atlbase.h> +#include <atlcom.h> +#include <atlcoll.h> +#include <atlsync.h> +#include <mmreg.h> + +#include <audioenginebaseapo.h> +#include <baseaudioprocessingobject.h> +#include <resource.h> + +#include <float.h> + +#include "DelayAPO.h" +#include <devicetopology.h> +#include <CustomPropKeys.h> + + +// Static declaration of the APO_REG_PROPERTIES structure +// associated with this APO. The number in <> brackets is the +// number of IIDs supported by this APO. If more than one, then additional +// IIDs are added at the end +#pragma warning (disable : 4815) +const AVRT_DATA CRegAPOProperties<1> CDelayAPOSFX::sm_RegProperties( + __uuidof(DelayAPOSFX), // clsid of this APO + L"CDelayAPOSFX", // friendly name of this APO + L"Copyright (c) Microsoft Corporation", // copyright info + 1, // major version # + 0, // minor version # + __uuidof(IDelayAPOSFX) // iid of primary interface + +// +// If you need to change any of these attributes, uncomment everything up to +// the point that you need to change something. If you need to add IIDs, uncomment +// everything and add additional IIDs at the end. +// +// , DEFAULT_APOREG_FLAGS +// , DEFAULT_APOREG_MININPUTCONNECTIONS +// , DEFAULT_APOREG_MAXINPUTCONNECTIONS +// , DEFAULT_APOREG_MINOUTPUTCONNECTIONS +// , DEFAULT_APOREG_MAXOUTPUTCONNECTIONS +// , DEFAULT_APOREG_MAXINSTANCES +// + ); + +#pragma AVRT_CODE_BEGIN +//------------------------------------------------------------------------- +// Description: +// +// Do the actual processing of data. +// +// Parameters: +// +// u32NumInputConnections - [in] number of input connections +// ppInputConnections - [in] pointer to list of input APO_CONNECTION_PROPERTY pointers +// u32NumOutputConnections - [in] number of output connections +// ppOutputConnections - [in] pointer to list of output APO_CONNECTION_PROPERTY pointers +// +// Return values: +// +// void +// +// Remarks: +// +// This function processes data in a manner dependent on the implementing +// object. This routine can not fail and can not block, or call any other +// routine that blocks, or touch pagable memory. +// +STDMETHODIMP_(void) CDelayAPOSFX::APOProcess( + UINT32 u32NumInputConnections, + APO_CONNECTION_PROPERTY** ppInputConnections, + UINT32 u32NumOutputConnections, + APO_CONNECTION_PROPERTY** ppOutputConnections) +{ + UNREFERENCED_PARAMETER(u32NumInputConnections); + UNREFERENCED_PARAMETER(u32NumOutputConnections); + + FLOAT32 *pf32InputFrames, *pf32OutputFrames; + + ATLASSERT(m_bIsLocked); + + // assert that the number of input and output connectins fits our registration properties + ATLASSERT(m_pRegProperties->u32MinInputConnections <= u32NumInputConnections); + ATLASSERT(m_pRegProperties->u32MaxInputConnections >= u32NumInputConnections); + ATLASSERT(m_pRegProperties->u32MinOutputConnections <= u32NumOutputConnections); + ATLASSERT(m_pRegProperties->u32MaxOutputConnections >= u32NumOutputConnections); + + // check APO_BUFFER_FLAGS. + switch( ppInputConnections[0]->u32BufferFlags ) + { + case BUFFER_INVALID: + { + ATLASSERT(false); // invalid flag - should never occur. don't do anything. + break; + } + case BUFFER_VALID: + case BUFFER_SILENT: + { + // get input pointer to connection buffer + pf32InputFrames = reinterpret_cast<FLOAT32*>(ppInputConnections[0]->pBuffer); + ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32InputFrames) ); + + // get output pointer to connection buffer + pf32OutputFrames = reinterpret_cast<FLOAT32*>(ppOutputConnections[0]->pBuffer); + ATLASSERT( IS_VALID_TYPED_WRITE_POINTER(pf32OutputFrames) ); + + if (BUFFER_SILENT == ppInputConnections[0]->u32BufferFlags) + { + WriteSilence( pf32InputFrames, + ppInputConnections[0]->u32ValidFrameCount, + GetSamplesPerFrame() ); + } + + // copy to the delay buffer + if ( + !IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) && + m_fEnableDelaySFX + ) + { + ProcessDelay(pf32OutputFrames, pf32InputFrames, + ppInputConnections[0]->u32ValidFrameCount, + GetSamplesPerFrame(), + m_pf32DelayBuffer, + m_nDelayFrames, + &m_iDelayIndex); + + // we don't try to remember silence + ppOutputConnections[0]->u32BufferFlags = BUFFER_VALID; + } + else + { + // copy the memory only if there is an output connection, and input/output pointers are unequal + if ( (0 != u32NumOutputConnections) && + (ppOutputConnections[0]->pBuffer != ppInputConnections[0]->pBuffer) ) + { + CopyFrames( pf32OutputFrames, pf32InputFrames, + ppInputConnections[0]->u32ValidFrameCount, + GetSamplesPerFrame() ); + } + + // pass along buffer flags + ppOutputConnections[0]->u32BufferFlags = ppInputConnections[0]->u32BufferFlags; + } + + // Set the valid frame count. + ppOutputConnections[0]->u32ValidFrameCount = ppInputConnections[0]->u32ValidFrameCount; + + break; + } + default: + { + ATLASSERT(false); // invalid flag - should never occur + break; + } + } // switch + +} // APOProcess +#pragma AVRT_CODE_END + +//------------------------------------------------------------------------- +// Description: +// +// Report delay added by the APO between samples given on input +// and samples given on output. +// +// Parameters: +// +// pTime - [out] hundreds-of-nanoseconds of delay added +// +// Return values: +// +// S_OK on success, a failure code on failure +STDMETHODIMP CDelayAPOSFX::GetLatency(HNSTIME* pTime) +{ + ASSERT_NONREALTIME(); + HRESULT hr = S_OK; + + IF_TRUE_ACTION_JUMP(NULL == pTime, hr = E_POINTER, Exit); + + if (IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)) + { + *pTime = 0; + } + else + { + *pTime = (m_fEnableDelaySFX ? HNS_DELAY : 0); + } + +Exit: + return hr; +} + +//------------------------------------------------------------------------- +// Description: +// +// Verifies that the APO is ready to process and locks its state if so. +// +// Parameters: +// +// u32NumInputConnections - [in] number of input connections attached to this APO +// ppInputConnections - [in] connection descriptor of each input connection attached to this APO +// u32NumOutputConnections - [in] number of output connections attached to this APO +// ppOutputConnections - [in] connection descriptor of each output connection attached to this APO +// +// Return values: +// +// S_OK Object is locked and ready to process. +// E_POINTER Invalid pointer passed to function. +// APOERR_INVALID_CONNECTION_FORMAT Invalid connection format. +// APOERR_NUM_CONNECTIONS_INVALID Number of input or output connections is not valid on +// this APO. +STDMETHODIMP CDelayAPOSFX::LockForProcess(UINT32 u32NumInputConnections, + APO_CONNECTION_DESCRIPTOR** ppInputConnections, + UINT32 u32NumOutputConnections, APO_CONNECTION_DESCRIPTOR** ppOutputConnections) +{ + ASSERT_NONREALTIME(); + HRESULT hr = S_OK; + + hr = CBaseAudioProcessingObject::LockForProcess(u32NumInputConnections, + ppInputConnections, u32NumOutputConnections, ppOutputConnections); + IF_FAILED_JUMP(hr, Exit); + + if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) && m_fEnableDelaySFX) + { + m_nDelayFrames = FRAMES_FROM_HNS(HNS_DELAY); + m_iDelayIndex = 0; + + m_pf32DelayBuffer.Free(); + + // Allocate one second's worth of audio + // + // This allocation is being done using CoTaskMemAlloc because the delay is very large + // This introduces a risk of glitches if the delay buffer gets paged out + // + // A more typical approach would be to allocate the memory using AERT_Allocate, which locks the memory + // But for the purposes of this APO, CoTaskMemAlloc suffices, and the risk of glitches is not important + m_pf32DelayBuffer.Allocate(GetSamplesPerFrame() * m_nDelayFrames); + + WriteSilence(m_pf32DelayBuffer, m_nDelayFrames, GetSamplesPerFrame()); + if (nullptr == m_pf32DelayBuffer) + { + hr = E_OUTOFMEMORY; + goto Exit; + } + } + +Exit: + return hr; +} + +// The method that this long comment refers to is "Initialize()" +//------------------------------------------------------------------------- +// Description: +// +// Generic initialization routine for APOs. +// +// Parameters: +// +// cbDataSize - [in] the size in bytes of the initialization data. +// pbyData - [in] initialization data specific to this APO +// +// Return values: +// +// S_OK Successful completion. +// E_POINTER Invalid pointer passed to this function. +// E_INVALIDARG Invalid argument +// AEERR_ALREADY_INITIALIZED APO is already initialized +// +// Remarks: +// +// This method initializes the APO. The data is variable length and +// should have the form of: +// +// struct MyAPOInitializationData +// { +// APOInitBaseStruct APOInit; +// ... // add additional fields here +// }; +// +// If the APO needs no initialization or needs no data to initialize +// itself, it is valid to pass NULL as the pbyData parameter and 0 as +// the cbDataSize parameter. +// +// As part of designing an APO, decide which parameters should be +// immutable (set once during initialization) and which mutable (changeable +// during the lifetime of the APO instance). Immutable parameters must +// only be specifiable in the Initialize call; mutable parameters must be +// settable via methods on whichever parameter control interface(s) your +// APO provides. Mutable values should either be set in the initialize +// method (if they are required for proper operation of the APO prior to +// LockForProcess) or default to reasonable values upon initialize and not +// be required to be set before LockForProcess. +// +// Within the mutable parameters, you must also decide which can be changed +// while the APO is locked for processing and which cannot. +// +// All parameters should be considered immutable as a first choice, unless +// there is a specific scenario which requires them to be mutable; similarly, +// no mutable parameters should be changeable while the APO is locked, unless +// a specific scenario requires them to be. Following this guideline will +// simplify the APO's state diagram and implementation and prevent certain +// types of bug. +// +// If a parameter changes the APOs latency or MaxXXXFrames values, it must be +// immutable. +// +// The default version of this function uses no initialization data, but does verify +// the passed parameters and set the m_bIsInitialized member to true. +// +// Note: This method may not be called from a real-time processing thread. +// + +HRESULT CDelayAPOSFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) +{ + HRESULT hr = S_OK; + CComPtr<IMMDevice> spMyDevice; + CComPtr<IDeviceTopology> spMyDeviceTopology; + CComPtr<IConnector> spMyConnector; + GUID processingMode; + + IF_TRUE_ACTION_JUMP( ((NULL == pbyData) && (0 != cbDataSize)), hr = E_INVALIDARG, Exit); + IF_TRUE_ACTION_JUMP( ((NULL != pbyData) && (0 == cbDataSize)), hr = E_INVALIDARG, Exit); + + if (cbDataSize == sizeof(APOInitSystemEffects2)) + { + // + // Initialize for mode-specific signal processing + // + APOInitSystemEffects2* papoSysFxInit2 = (APOInitSystemEffects2*)pbyData; + + // Save reference to the effects property store. This saves effects settings + // and is the communication medium between this APO and any associated UI. + m_spAPOSystemEffectsProperties = papoSysFxInit2->pAPOSystemEffectsProperties; + + // Windows should pass a valid collection. + ATLASSERT(papoSysFxInit2->pDeviceCollection != nullptr); + IF_TRUE_ACTION_JUMP(papoSysFxInit2->pDeviceCollection == nullptr, hr = E_INVALIDARG, Exit); + + // Get the IDeviceTopology and IConnector interfaces to communicate with this + // APO's counterpart audio driver. This can be used for any proprietary + // communication. + hr = papoSysFxInit2->pDeviceCollection->Item(papoSysFxInit2->nSoftwareIoDeviceInCollection, &spMyDevice); + IF_FAILED_JUMP(hr, Exit); + + hr = spMyDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); + IF_FAILED_JUMP(hr, Exit); + + hr = spMyDeviceTopology->GetConnector(papoSysFxInit2->nSoftwareIoConnectorIndex, &spMyConnector); + IF_FAILED_JUMP(hr, Exit); + + // Save the processing mode being initialized. + processingMode = papoSysFxInit2->AudioProcessingMode; + + } + else if (cbDataSize == sizeof(APOInitSystemEffects)) + { + // + // Initialize for default signal processing + // + APOInitSystemEffects* papoSysFxInit = (APOInitSystemEffects*)pbyData; + + // Save reference to the effects property store. This saves effects settings + // and is the communication medium between this APO and any associated UI. + m_spAPOSystemEffectsProperties = papoSysFxInit->pAPOSystemEffectsProperties; + + // Assume default processing mode + processingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT; + } + else + { + // Invalid initialization size + hr = E_INVALIDARG; + goto Exit; + } + + // Validate then save the processing mode. Note an endpoint effects APO + // does not depend on the mode. Windows sets the APOInitSystemEffects2 + // AudioProcessingMode member to GUID_NULL for an endpoint effects APO. + IF_TRUE_ACTION_JUMP((processingMode != AUDIO_SIGNALPROCESSINGMODE_DEFAULT && + processingMode != AUDIO_SIGNALPROCESSINGMODE_RAW && + processingMode != AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS && + processingMode != AUDIO_SIGNALPROCESSINGMODE_SPEECH && + processingMode != AUDIO_SIGNALPROCESSINGMODE_MEDIA && + processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE), hr = E_INVALIDARG, Exit); + m_AudioProcessingMode = processingMode; + + // + // An APO that implements signal processing more complex than this sample + // would configure its processing for the processingMode determined above. + // If necessary, the APO would also use the IDeviceTopology and IConnector + // interfaces retrieved above to communicate with its counterpart audio + // driver to configure any additional signal processing in the driver and + // associated hardware. + // + + // + // Get the current values + // + if (m_spAPOSystemEffectsProperties != NULL) + { + m_fEnableDelaySFX = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, PKEY_Endpoint_Enable_Delay_SFX, m_AudioProcessingMode); + } + + // + // Register for notification of registry updates + // + hr = m_spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator)); + IF_FAILED_JUMP(hr, Exit); + + hr = m_spEnumerator->RegisterEndpointNotificationCallback(this); + IF_FAILED_JUMP(hr, Exit); + + m_bIsInitialized = true; + + +Exit: + return hr; +} + +//------------------------------------------------------------------------- +// +// GetEffectsList +// +// Retrieves the list of signal processing effects currently active and +// stores an event to be signaled if the list changes. +// +// Parameters +// +// ppEffectsIds - returns a pointer to a list of GUIDs each identifying a +// class of effect. The caller is responsible for freeing this memory by +// calling CoTaskMemFree. +// +// pcEffects - returns a count of GUIDs in the list. +// +// Event - passes an event handle. The APO signals this event when the list +// of effects changes from the list returned from this function. The APO +// uses this event until either this function is called again or the APO +// is destroyed. The passed handle may be NULL. In this case, the APO +// stops using any previous handle and does not signal an event. +// +// Remarks +// +// An APO imlements this method to allow Windows to discover the current +// effects applied by the APO. The list of effects may depend on what signal +// processing mode the APO initialized (see AudioProcessingMode in the +// APOInitSystemEffects2 structure) as well as any end user configuration. +// +// If there are no effects then the function still succeeds, ppEffectsIds +// returns a NULL pointer, and pcEffects returns a count of 0. +// +STDMETHODIMP CDelayAPOSFX::GetEffectsList(_Outptr_result_buffer_maybenull_(*pcEffects) LPGUID *ppEffectsIds, _Out_ UINT *pcEffects, _In_ HANDLE Event) +{ + HRESULT hr; + BOOL effectsLocked = FALSE; + UINT cEffects = 0; + + IF_TRUE_ACTION_JUMP(ppEffectsIds == NULL, hr = E_POINTER, Exit); + IF_TRUE_ACTION_JUMP(pcEffects == NULL, hr = E_POINTER, Exit); + + // Synchronize access to the effects list and effects changed event + m_EffectsLock.Enter(); + effectsLocked = TRUE; + + // Always close existing effects change event handle + if (m_hEffectsChangedEvent != NULL) + { + CloseHandle(m_hEffectsChangedEvent); + m_hEffectsChangedEvent = NULL; + } + + // If an event handle was specified, save it here (duplicated to control lifetime) + if (Event != NULL) + { + if (!DuplicateHandle(GetCurrentProcess(), Event, GetCurrentProcess(), &m_hEffectsChangedEvent, EVENT_MODIFY_STATE, FALSE, 0)) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + goto Exit; + } + } + + // naked scope to force the initialization of list[] to be after we enter the critical section + { + struct EffectControl + { + GUID effect; + BOOL control; + }; + + EffectControl list[] = + { + { DelayEffectId, m_fEnableDelaySFX }, + }; + + if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)) + { + // count the active effects + for (UINT i = 0; i < ARRAYSIZE(list); i++) + { + if (list[i].control) + { + cEffects++; + } + } + } + + if (0 == cEffects) + { + *ppEffectsIds = NULL; + *pcEffects = 0; + } + else + { + GUID *pEffectsIds = (LPGUID)CoTaskMemAlloc(sizeof(GUID) * cEffects); + if (pEffectsIds == nullptr) + { + hr = E_OUTOFMEMORY; + goto Exit; + } + + // pick up the active effects + UINT j = 0; + for (UINT i = 0; i < ARRAYSIZE(list); i++) + { + if (list[i].control) + { + pEffectsIds[j++] = list[i].effect; + } + } + + *ppEffectsIds = pEffectsIds; + *pcEffects = cEffects; + } + + hr = S_OK; + } + +Exit: + if (effectsLocked) + { + m_EffectsLock.Leave(); + } + return hr; +} + +//------------------------------------------------------------------------- +// Description: +// +// +// +// Parameters: +// +// +// +// Return values: +// +// +// +// Remarks: +// +// +HRESULT CDelayAPOSFX::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) +{ + HRESULT hr = S_OK; + + UNREFERENCED_PARAMETER(pwstrDeviceId); + + if (!m_spAPOSystemEffectsProperties) + { + return hr; + } + + // If either the master disable or our APO's enable properties changed... + if (PK_EQUAL(key, PKEY_Endpoint_Enable_Delay_SFX) || + PK_EQUAL(key, PKEY_AudioEndpoint_Disable_SysFx)) + { + LONG nChanges = 0; + + // Synchronize access to the effects list and effects changed event + m_EffectsLock.Enter(); + + struct KeyControl + { + PROPERTYKEY key; + LONG *value; + }; + + KeyControl controls[] = + { + { PKEY_Endpoint_Enable_Delay_SFX, &m_fEnableDelaySFX }, + }; + + for (int i = 0; i < ARRAYSIZE(controls); i++) + { + LONG fOldValue; + LONG fNewValue = true; + + // Get the state of whether channel swap MFX is enabled or not + fNewValue = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, controls[i].key, m_AudioProcessingMode); + + // Delay in the new setting + fOldValue = InterlockedExchange(controls[i].value, fNewValue); + + if (fNewValue != fOldValue) + { + nChanges++; + } + } + + // If anything changed and a change event handle exists + if ((nChanges > 0) && (m_hEffectsChangedEvent != NULL)) + { + SetEvent(m_hEffectsChangedEvent); + } + + m_EffectsLock.Leave(); + } + + return hr; +} + + +//------------------------------------------------------------------------- +// Description: +// +// Destructor. +// +// Parameters: +// +// void +// +// Return values: +// +// void +// +// Remarks: +// +// This method deletes whatever was allocated. +// +// This method may not be called from a real-time processing thread. +// +CDelayAPOSFX::~CDelayAPOSFX(void) +{ + // + // unregister for callbacks + // + if (m_bIsInitialized) + { + m_spEnumerator->UnregisterEndpointNotificationCallback(this); + } + + if (m_hEffectsChangedEvent != NULL) + { + CloseHandle(m_hEffectsChangedEvent); + } +} // ~CDelayAPOSFX diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPOSFX.rgs b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOSFX.rgs new file mode 100644 index 00000000..1a100539 --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOSFX.rgs @@ -0,0 +1,13 @@ +HKCR +{ + NoRemove CLSID + { + ForceRemove {77802b45-a5a0-455a-8204-3dba30eee7b4} = s 'DelayAPOSFX Class' + { + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Both' + } + } + } +} diff --git a/audio/sysvad/SwapAPO/DelayAPO/Resource.h b/audio/sysvad/SwapAPO/DelayAPO/Resource.h new file mode 100644 index 00000000..eda62a7a --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/Resource.h @@ -0,0 +1,20 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by DelayAPODll.rc +// +#define IDS_PROJNAME 100 +#define IDR_DELAYAPODLL 101 +#define IDR_DELAYAPOMFX 110 +#define IDR_DELAYAPOSFX 111 +#define IDI_EFFECT_ICON 200 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 201 +#define _APS_NEXT_COMMAND_VALUE 32768 +#define _APS_NEXT_CONTROL_VALUE 201 +#define _APS_NEXT_SYMED_VALUE 132 +#endif +#endif diff --git a/audio/sysvad/SwapAPO/DelayAPO/delayapo.png b/audio/sysvad/SwapAPO/DelayAPO/delayapo.png Binary files differnew file mode 100644 index 00000000..055bdc2c --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/delayapo.png diff --git a/audio/sysvad/SwapAPO/DelayAPO/makefile b/audio/sysvad/SwapAPO/DelayAPO/makefile new file mode 100644 index 00000000..593ab379 --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/makefile @@ -0,0 +1,34 @@ +############################################################################# +# +# Copyright (c) Microsoft Corporation. +# All Rights Reserved. +# +############################################################################# + +## NT BUILD ENVIROMENT + +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT. +# +!if defined(IA64) +!message This sample is not to be built for IA64 targets +!else + +!IF DEFINED(_NT_TARGET_VERSION) +#! IF $(_NT_TARGET_VERSION)>=0x501 +! IF $(_NT_TARGET_VERSION)>=0x600 +! INCLUDE $(NTMAKEENV)\makefile.def +! ELSE +# Only warn once per directory +! INCLUDE $(NTMAKEENV)\makefile.plt +! IF "$(BUILD_PASS)"=="PASS1" +! message BUILDMSG: Warning : Building the sample "$(MAKEDIR)" for downlevel build environments is temporarily disabled in WDK for Beta2. +! ENDIF +! ENDIF +!ELSE +! INCLUDE $(NTMAKEENV)\makefile.def +!ENDIF + +!endif diff --git a/audio/sysvad/SwapAPO/DelayAPO/sources b/audio/sysvad/SwapAPO/DelayAPO/sources new file mode 100644 index 00000000..355dc80f --- /dev/null +++ b/audio/sysvad/SwapAPO/DelayAPO/sources @@ -0,0 +1,12 @@ +!include ..\sources.inc + +TARGETNAME=DelayAPO +DLLDEF=DelayAPODll.def + +SOURCES=DelayAPOInterface.idl \ + DelayAPOMFX.cpp \ + DelayAPOSFX.cpp \ + Delay.cpp \ + DelayAPODll.idl \ + DelayAPODll.rc \ + DelayAPODll.cpp \ diff --git a/audio/sysvad/SwapAPO/PropPageExtensions/PropPageExt.vcxproj.Filters b/audio/sysvad/SwapAPO/PropPageExtensions/PropPageExt.vcxproj.Filters new file mode 100644 index 00000000..98832fba --- /dev/null +++ b/audio/sysvad/SwapAPO/PropPageExtensions/PropPageExt.vcxproj.Filters @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{413921B3-AEE4-4E51-B616-E356BEC9E42E}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{0B044B82-EDD8-49A9-ACEE-2E7C98CCA3DC}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{1E3956FB-B7AD-48BF-AD18-28527349BEED}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="AdvEndpointPropPage.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="CplExt.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Parts.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="stdafxsrc.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="SwapPropPage.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="TopologyExaminers.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="UIWidgets.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <Midl Include="CplExt.idl"> + <Filter>Source Files</Filter> + </Midl> + <None Include="PropPageExt.def"> + <Filter>Source Files</Filter> + </None> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="CplExt.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/audio/sysvad/SwapAPO/PropPageExtensions/makefile b/audio/sysvad/SwapAPO/PropPageExtensions/makefile new file mode 100644 index 00000000..c7837f4f --- /dev/null +++ b/audio/sysvad/SwapAPO/PropPageExtensions/makefile @@ -0,0 +1,36 @@ +############################################################################# +# +# Copyright (c) Microsoft Corporation. +# All Rights Reserved. +# +# Makefile for wdm\audio\sysfx\apo +# +############################################################################# + +## NT BUILD ENVIROMENT + +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT. +# +!if defined(IA64) +!message This sample is not to be built for IA64 targets +!else + +!IF DEFINED(_NT_TARGET_VERSION) +#! IF $(_NT_TARGET_VERSION)>=0x501 +! IF $(_NT_TARGET_VERSION)>=0x600 +! INCLUDE $(NTMAKEENV)\makefile.def +! ELSE +# Only warn once per directory +! INCLUDE $(NTMAKEENV)\makefile.plt +! IF "$(BUILD_PASS)"=="PASS1" +! message BUILDMSG: Warning : Building the sample "$(MAKEDIR)" for downlevel build environments is temporarily disabled in WDK for Beta2. +! ENDIF +! ENDIF +!ELSE +! INCLUDE $(NTMAKEENV)\makefile.def +!ENDIF + +!endif
\ No newline at end of file diff --git a/audio/sysvad/SwapAPO/PropPageExtensions/sources b/audio/sysvad/SwapAPO/PropPageExtensions/sources new file mode 100644 index 00000000..898884b6 --- /dev/null +++ b/audio/sysvad/SwapAPO/PropPageExtensions/sources @@ -0,0 +1,60 @@ +TARGETNAME=PropPageExt +TARGETTYPE=DYNLINK + +USE_ATL=1 + +USE_NATIVE_EH=1 + + +DLLENTRY=_DllMainCRTStartup +PRECOMPILED_CXX=1 +PRECOMPILED_INCLUDE=stdafx.h +PRECOMPILED_PCH=stdafx.pch + +MSC_WARNING_LEVEL=-W4 \ + -WX + +# +# stdafx.h defines _ATL_ALL_WARNINGS +# Disabling 4127 is necessary to allow this driver to build in the WDK environment. +# +USER_C_FLAGS=/wd4127 + +C_DEFINES=-DUNICODE \ + -D_UNICODE + +# +# Indicate to the WDK that this sample only supports Win10[+] +# +MINIMUM_NT_TARGET_VERSION=$(_NT_TARGET_VERSION_WINTHRESHOLD) + +# Indicate that this DLL must be included in the driver package +DDK_NO_PACKAGE_PROJECT=0 +DDK_INCLUDE_PACKAGE_PROJECT=1 + +INCLUDES=$(INCLUDES); \ + ..\Inc; \ + $(DDK_INC_PATH); +SOURCES=CplExt.idl \ + CplExt.rc \ + CplExt.cpp \ + SwapPropPage.cpp \ + AdvEndpointPropPage.cpp \ + UIWidgets.cpp \ + TopologyExaminers.cpp \ + Parts.cpp \ + + +TARGETLIBS= \ + \ + $(SDK_LIB_PATH)\onecore_downlevel.lib \ + $(ONECORE_PRIV_SDK_LIB_PATH)\OneCore_Forwarder_user32.lib \ + $(SDK_LIB_PATH)\onecore_downlevel.lib \ + $(SDK_LIB_PATH)\oleaut32.lib \ + $(INTERNAL_SDK_LIB_PATH)\onecoreuapuuid.lib \ + $(SDK_LIB_PATH)\shlwapi.lib \ + $(SDK_LIB_PATH)\comctl32.lib \ + $(SDK_LIB_PATH)\rpcrt4.lib \ + + + diff --git a/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj.Filters b/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj.Filters new file mode 100644 index 00000000..cc7dcd30 --- /dev/null +++ b/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj.Filters @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{7FE326AE-6214-4FE0-A27B-F229A098BDBC}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{64C16D2B-849C-4264-A615-18A8E8AC9505}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{46FAF4E8-F18C-4797-9CFA-2F3473BCB316}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{EE8F0A00-C1F0-4CB4-80E3-5FCC378E0BF4}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\adapter.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\basetopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\common.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\hw.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\kshelper.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\savedata.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\tonegenerator.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="hdmitopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="micintopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="spdiftopo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="..\sysvad.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/audio/sysvad/TabletAudioSample/minipairs.h b/audio/sysvad/TabletAudioSample/minipairs.h index 320aed6f..e955791e 100644 --- a/audio/sysvad/TabletAudioSample/minipairs.h +++ b/audio/sysvad/TabletAudioSample/minipairs.h @@ -177,7 +177,10 @@ ENDPOINT_MINIPAIR SpeakerMiniports = SIZEOF_ARRAY(SpeakerPinDeviceFormatsAndModes), SpeakerTopologyPhysicalConnections, SIZEOF_ARRAY(SpeakerTopologyPhysicalConnections), - ENDPOINT_OFFLOAD_SUPPORTED + ENDPOINT_OFFLOAD_SUPPORTED, + SpeakerModulesWaveFilter, + SIZEOF_ARRAY(SpeakerModulesWaveFilter), + &SpeakerModuleNotificationDeviceId, }; /********************************************************************* @@ -219,7 +222,10 @@ ENDPOINT_MINIPAIR SpeakerHpMiniports = SIZEOF_ARRAY(SpeakerHpPinDeviceFormatsAndModes), SpeakerHpTopologyPhysicalConnections, SIZEOF_ARRAY(SpeakerHpTopologyPhysicalConnections), - ENDPOINT_OFFLOAD_SUPPORTED + ENDPOINT_OFFLOAD_SUPPORTED, + SpeakerHpModulesWaveFilter, + SIZEOF_ARRAY(SpeakerHpModulesWaveFilter), + &SpeakerHpModuleNotificationDeviceId, }; /********************************************************************* @@ -261,7 +267,8 @@ ENDPOINT_MINIPAIR HdmiMiniports = SIZEOF_ARRAY(HdmiPinDeviceFormatsAndModes), HdmiTopologyPhysicalConnections, SIZEOF_ARRAY(HdmiTopologyPhysicalConnections), - ENDPOINT_NO_FLAGS + ENDPOINT_NO_FLAGS, + NULL, 0, NULL, // audio module settings. }; /********************************************************************* @@ -304,7 +311,8 @@ ENDPOINT_MINIPAIR SpdifMiniports = SIZEOF_ARRAY(SpdifPinDeviceFormatsAndModes), SpdifTopologyPhysicalConnections, SIZEOF_ARRAY(SpdifTopologyPhysicalConnections), - ENDPOINT_OFFLOAD_SUPPORTED + ENDPOINT_OFFLOAD_SUPPORTED, + NULL, 0, NULL, // audio module settings. }; // @@ -348,7 +356,8 @@ ENDPOINT_MINIPAIR MicInMiniports = SIZEOF_ARRAY(MicInPinDeviceFormatsAndModes), MicInTopologyPhysicalConnections, SIZEOF_ARRAY(MicInTopologyPhysicalConnections), - ENDPOINT_NO_FLAGS + ENDPOINT_NO_FLAGS, + NULL, 0, NULL, // audio module settings. }; /********************************************************************* @@ -389,7 +398,8 @@ ENDPOINT_MINIPAIR MicArray1Miniports = SIZEOF_ARRAY(MicArrayPinDeviceFormatsAndModes), MicArray1TopologyPhysicalConnections, SIZEOF_ARRAY(MicArray1TopologyPhysicalConnections), - ENDPOINT_SOUNDDETECTOR_SUPPORTED + ENDPOINT_SOUNDDETECTOR_SUPPORTED, + NULL, 0, NULL, // audio module settings. }; /********************************************************************* @@ -429,7 +439,8 @@ ENDPOINT_MINIPAIR MicArray2Miniports = SIZEOF_ARRAY(MicArrayPinDeviceFormatsAndModes), MicArray2TopologyPhysicalConnections, SIZEOF_ARRAY(MicArray2TopologyPhysicalConnections), - ENDPOINT_SOUNDDETECTOR_SUPPORTED + ENDPOINT_SOUNDDETECTOR_SUPPORTED, + NULL, 0, NULL, // audio module settings. }; /********************************************************************* @@ -469,7 +480,8 @@ ENDPOINT_MINIPAIR MicArray3Miniports = SIZEOF_ARRAY(MicArray3PinDeviceFormatsAndModes), MicArray3TopologyPhysicalConnections, SIZEOF_ARRAY(MicArray3TopologyPhysicalConnections), - ENDPOINT_NO_FLAGS + ENDPOINT_NO_FLAGS, + NULL, 0, NULL, // audio module settings. }; //============================================================================= diff --git a/audio/sysvad/TabletAudioSample/sources b/audio/sysvad/TabletAudioSample/sources new file mode 100644 index 00000000..39d0de57 --- /dev/null +++ b/audio/sysvad/TabletAudioSample/sources @@ -0,0 +1,53 @@ + +# Copyright (c) Microsoft Corporation. All rights reserved. + + +!include ..\sources.inc + +TARGETNAME=TabletAudioSample + +TARGETLIBS= \ + $(TARGETLIBS) \ + $(OBJ_PATH)\..\EndpointsCommon\$(O)\EndpointsCommon.lib \ + + +C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ -DSYSVAD_BTH_BYPASS + + +#C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ +# +# Indicate to the WDK that this sample only supports Win10[+] +# +MINIMUM_NT_TARGET_VERSION=$(_NT_TARGET_VERSION_WINTHRESHOLD) + +# +# Audio driver is a KMDF miniport. +# +KMDF_VERSION_MAJOR=1 + +# +# Uncomment one of the following lines to select the right power management. +# Note that the single-component/multi-state feature requires also a registry +# value set via the INF. The name of the registry value is SingleComponentMultiFxStates. +# see INF file for more info. +# +#C_DEFINES= $(C_DEFINES) -D_USE_IPortClsRuntimePower +C_DEFINES= $(C_DEFINES) -D_USE_SingleComponentMultiFxStates + +INCLUDES= \ + $(INCLUDES); \ + ..\EndpointsCommon; \ + +SOURCES=$(SOURCES) \ + hdmitopo.cpp \ + spdiftopo.cpp \ + micintopo.cpp \ + + +# Indicate that this module must be included in the driver package +DDK_NO_PACKAGE_PROJECT=0 +DDK_INCLUDE_PACKAGE_PROJECT=1 + + +MUI_VERIFY_NO_LOC_RESOURCE=1 + diff --git a/audio/sysvad/TabletAudioSample/tabletaudiosample.inf b/audio/sysvad/TabletAudioSample/tabletaudiosample.inf Binary files differindex 0e85d33b..c9f533af 100644 --- a/audio/sysvad/TabletAudioSample/tabletaudiosample.inf +++ b/audio/sysvad/TabletAudioSample/tabletaudiosample.inf diff --git a/audio/sysvad/common.h b/audio/sysvad/common.h index ee37445a..d46a9090 100644 --- a/audio/sysvad/common.h +++ b/audio/sysvad/common.h @@ -187,6 +187,126 @@ typedef struct _PIN_DEVICE_FORMATS_AND_MODES } PIN_DEVICE_FORMATS_AND_MODES, *PPIN_DEVICE_FORMATS_AND_MODES; +// +// Parameter module handler function prototypes. +// +static const GUID NULL_GUID = +{0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}; + +static const GUID MODULETYPE_HWEFFECT = +{0x2608993c,0x361e,0x488c,{0xa0,0xbc,0x8f,0x3d,0xe7,0xba,0x12,0xb4}}; + +// +// Forward declaration. +// +struct AUDIOMODULE_DESCRIPTOR; +typedef AUDIOMODULE_DESCRIPTOR *PAUDIOMODULE_DESCRIPTOR; + +typedef struct _AUDIOMODULE_PARAMETER_INFO +{ + USHORT AccessFlags; // get/set/basic-support attributes. + USHORT Flags; + ULONG Size; + DWORD VtType; + PVOID ValidSet; + ULONG ValidSetCount; +} AUDIOMODULE_PARAMETER_INFO, *PAUDIOMODULE_PARAMETER_INFO; + +#define AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION 0x00000001 + +// +// Module callbacks. +// +typedef +NTSTATUS +(*FN_AUDIOMODULE_INIT_CLASS) +( + _In_ const AUDIOMODULE_DESCRIPTOR * Module, + _Inout_opt_ PVOID Context, + _In_ size_t Size, + _In_ KSAUDIOMODULE_NOTIFICATION * NotificationHeader, + _In_opt_ PPORTCLSNOTIFICATIONS PortNotifications +); + +typedef +NTSTATUS +(*FN_AUDIOMODULE_INIT_INSTANCE) +( + _In_ const AUDIOMODULE_DESCRIPTOR * Module, + _In_opt_ PVOID TemplateContext, + _Inout_opt_ PVOID Context, + _In_ size_t Size, + _In_ ULONG InstanceId +); + +typedef +VOID +(*FN_AUDIOMODULE_CLEANUP) +( + _In_ PVOID Context +); + +typedef +NTSTATUS +(*FN_AUDIOMODULE_HANDLER) +( + _Inout_opt_ PVOID Context, + _In_reads_bytes_(InBufferCb) PVOID InBuffer, + _In_ ULONG InBufferCb, + _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer, + _Inout_ ULONG * OutBufferCb +); + +// +// Module description. +// +struct AUDIOMODULE_DESCRIPTOR +{ + const GUID * ClassId; + const GUID * ProcessingMode; + WCHAR Name[AUDIOMODULE_MAX_NAME_CCH_SIZE]; + ULONG InstanceId; + ULONG VersionMajor; + ULONG VersionMinor; + ULONG Flags; + size_t ContextSize; + FN_AUDIOMODULE_INIT_CLASS InitClass; + FN_AUDIOMODULE_INIT_INSTANCE InitInstance; + FN_AUDIOMODULE_CLEANUP Cleanup; + FN_AUDIOMODULE_HANDLER Handler; +}; + +#define AUDIOMODULE_DESCRIPTOR_FLAG_NONE 0x00000000 + +// +// Audio module instance defintion. +// This sample driver generates an instance id by combinding the +// configuration set # for a class module id with the instance of that +// configuration. Real driver should use a more robust scheme, such as +// an indirect mapping from/to an instance id to/from a configuration set +// + location in the pipeline + any other info the driver needs. +// +#define AUDIOMODULE_CLASS_CFG_ID_MASK 0xFF +#define AUDIOMODULE_CLASS_CFG_INSTANCE_ID_MASK 0xFFFFFF + +#define AUDIOMODULE_INSTANCE_ID(ClassCfgId, ClassCfgInstanceId) \ + ((ULONG(ClassCfgId & AUDIOMODULE_CLASS_CFG_ID_MASK) << 24) | \ + (ULONG(ClassCfgInstanceId & AUDIOMODULE_CLASS_CFG_INSTANCE_ID_MASK))) + +#define AUDIOMODULE_GET_CLASSCFGID(InstanceId) \ + (ULONG(InstanceId) >> 24 & AUDIOMODULE_CLASS_CFG_ID_MASK) + +// +// Used to track run-time audio module changes. +// +struct AUDIOMODULE +{ + const AUDIOMODULE_DESCRIPTOR * Descriptor; + PVOID Context; + ULONG InstanceId; + ULONG NextCfgInstanceId; // used by filter modules + BOOL Enabled; +}; // forward declaration. typedef struct _ENDPOINT_MINIPAIR *PENDPOINT_MINIPAIR; @@ -252,6 +372,11 @@ typedef struct _ENDPOINT_MINIPAIR // General endpoint flags (one of more ENDPOINT_<flag-type>, see above) ULONG DeviceFlags; + + // Static module list description. + AUDIOMODULE_DESCRIPTOR * ModuleList; + ULONG ModuleListCount; + const GUID * ModuleNotificationDeviceId; } ENDPOINT_MINIPAIR; //============================================================================= diff --git a/audio/sysvad/sources.inc b/audio/sysvad/sources.inc new file mode 100644 index 00000000..7396cf46 --- /dev/null +++ b/audio/sysvad/sources.inc @@ -0,0 +1,34 @@ +TARGETTYPE=DRIVER + +TARGETLIBS= \ + $(DDK_LIB_PATH)\portcls.lib\ + $(DDK_LIB_PATH)\stdunk.lib \ + $(SDK_LIB_PATH)\libcntpr.lib + +INCLUDES= \ + $(DDK_INC_PATH); \ + .. + +MSC_WARNING_LEVEL=-W4 -WX + +C_DEFINES= $(C_DEFINES) -D_WIN32 -DUNICODE -D_UNICODE -DPC_IMPLEMENTATION + +# +# Different levels of debug printage. First is nothing but +# catastrophic errors, last is everything under the sun. +# +#C_DEFINES= $(C_DEFINES) -DDEBUG_LEVEL=DEBUGLVL_ERROR +C_DEFINES= $(C_DEFINES) -DDEBUG_LEVEL=DEBUGLVL_TERSE +#C_DEFINES= $(C_DEFINES) -DDEBUG_LEVEL=DEBUGLVL_VERBOSE +#C_DEFINES= $(C_DEFINES) -DDEBUG_LEVEL=DEBUGLVL_BLAB + +SOURCES=\ + ..\adapter.cpp \ + ..\basetopo.cpp \ + ..\common.cpp \ + ..\hw.cpp \ + ..\kshelper.cpp \ + ..\savedata.cpp \ + ..\tonegenerator.cpp \ + ..\sysvad.rc + diff --git a/audio/sysvad/sysvad.h b/audio/sysvad/sysvad.h index 0e35aebd..0065f3e3 100644 --- a/audio/sysvad/sysvad.h +++ b/audio/sysvad/sysvad.h @@ -230,6 +230,15 @@ typedef struct _PortClassDeviceContext // 32 64 Byte off } PortClassDeviceContext; // +// Major/MinorTarget to object casting. +// +#define MajorTarget_to_Obj(ptr) \ + reinterpret_cast<CMiniportWaveRT*>(ptr) + +#define MinorTarget_to_Obj(ptr) \ + static_cast<CMiniportWaveRTStream*>(reinterpret_cast<PMINIPORTWAVERTSTREAM>(ptr)) + +// // Global settings. // extern DWORD g_DoNotCreateDataFiles; @@ -257,6 +266,11 @@ NTSTATUS PropertyHandler_OffloadPin _In_ PPCPROPERTY_REQUEST PropertyRequest ); +NTSTATUS PropertyHandler_GenericPin +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +); + // common.h uses some of the above definitions. #include "common.h" #include "kshelper.h" diff --git a/audio/sysvad/sysvad.sln b/audio/sysvad/sysvad.sln index 026c0790..d504350b 100644 --- a/audio/sysvad/sysvad.sln +++ b/audio/sysvad/sysvad.sln @@ -1,8 +1,10 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +VisualStudioVersion = 14.0.25431.01 MinimumVisualStudioVersion = 12.0 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Package", "Package", "{FA56D96B-290B-4C73-A5E1-02C1861D3224}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "KeywordDetectorAdapter", "KeywordDetectorAdapter", "{DBD14E7B-7F95-4743-86E3-4E16FA43F990}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PropPageExtensions", "PropPageExtensions", "{50D3DF82-019A-4434-B17F-72BBC291415F}" @@ -17,12 +19,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PhoneAudioSample", "PhoneAu EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TabletAudioSample", "TabletAudioSample", "{C06F6070-75EE-4F57-8D35-4AC2AB08D029}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "package", "package\package.VcxProj", "{830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeywordDetectorContosoAdapter", "KeywordDetectorAdapter\KeywordDetectorContosoAdapter.vcxproj", "{E0F02048-78A4-4FE8-B863-66E6CB6A2C37}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PropPageExt", "SwapAPO\PropPageExtensions\PropPageExt.vcxproj", "{D253C552-154D-49E1-820A-B2CD9D9FF13E}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SwapAPO", "SwapAPO\APO\SwapAPO.vcxproj", "{691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DelayAPO", "SwapAPO\DelayAPO\DelayAPO.vcxproj", "{8851AB85-70B3-4798-A149-BA366DF9EC25}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EndpointsCommon", "EndpointsCommon\EndpointsCommon.vcxproj", "{33E61864-6F2C-4F9F-BE70-8F8985A4F283}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PhoneAudioSample", "PhoneAudioSample\PhoneAudioSample.vcxproj", "{FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}" @@ -38,57 +44,73 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|Win32.ActiveCfg = Debug|Win32 + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|Win32.Build.0 = Debug|Win32 + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|Win32.ActiveCfg = Release|Win32 + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|Win32.Build.0 = Release|Win32 + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|x64.ActiveCfg = Debug|x64 + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|x64.Build.0 = Debug|x64 + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.ActiveCfg = Release|x64 + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.Build.0 = Release|x64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|Win32.ActiveCfg = Debug|Win32 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|Win32.Build.0 = Debug|Win32 - {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|x64.ActiveCfg = Debug|x64 - {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|x64.Build.0 = Debug|x64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|Win32.ActiveCfg = Release|Win32 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|Win32.Build.0 = Release|Win32 + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|x64.ActiveCfg = Debug|x64 + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|x64.Build.0 = Debug|x64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|x64.ActiveCfg = Release|x64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|x64.Build.0 = Release|x64 {D253C552-154D-49E1-820A-B2CD9D9FF13E}.Debug|Win32.ActiveCfg = Debug|Win32 {D253C552-154D-49E1-820A-B2CD9D9FF13E}.Debug|Win32.Build.0 = Debug|Win32 - {D253C552-154D-49E1-820A-B2CD9D9FF13E}.Debug|x64.ActiveCfg = Debug|x64 - {D253C552-154D-49E1-820A-B2CD9D9FF13E}.Debug|x64.Build.0 = Debug|x64 {D253C552-154D-49E1-820A-B2CD9D9FF13E}.Release|Win32.ActiveCfg = Release|Win32 {D253C552-154D-49E1-820A-B2CD9D9FF13E}.Release|Win32.Build.0 = Release|Win32 + {D253C552-154D-49E1-820A-B2CD9D9FF13E}.Debug|x64.ActiveCfg = Debug|x64 + {D253C552-154D-49E1-820A-B2CD9D9FF13E}.Debug|x64.Build.0 = Debug|x64 {D253C552-154D-49E1-820A-B2CD9D9FF13E}.Release|x64.ActiveCfg = Release|x64 {D253C552-154D-49E1-820A-B2CD9D9FF13E}.Release|x64.Build.0 = Release|x64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|Win32.ActiveCfg = Debug|Win32 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|Win32.Build.0 = Debug|Win32 - {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|x64.ActiveCfg = Debug|x64 - {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|x64.Build.0 = Debug|x64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|Win32.ActiveCfg = Release|Win32 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|Win32.Build.0 = Release|Win32 + {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|x64.ActiveCfg = Debug|x64 + {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|x64.Build.0 = Debug|x64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|x64.ActiveCfg = Release|x64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|x64.Build.0 = Release|x64 + {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|Win32.ActiveCfg = Debug|Win32 + {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|Win32.Build.0 = Debug|Win32 + {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|Win32.ActiveCfg = Release|Win32 + {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|Win32.Build.0 = Release|Win32 + {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|x64.ActiveCfg = Debug|x64 + {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|x64.Build.0 = Debug|x64 + {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|x64.ActiveCfg = Release|x64 + {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|x64.Build.0 = Release|x64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|Win32.ActiveCfg = Debug|Win32 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|Win32.Build.0 = Debug|Win32 - {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|x64.ActiveCfg = Debug|x64 - {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|x64.Build.0 = Debug|x64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|Win32.ActiveCfg = Release|Win32 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|Win32.Build.0 = Release|Win32 + {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|x64.ActiveCfg = Debug|x64 + {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|x64.Build.0 = Debug|x64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.ActiveCfg = Release|x64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.Build.0 = Release|x64 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|Win32.ActiveCfg = Debug|Win32 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|Win32.Build.0 = Debug|Win32 - {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|x64.ActiveCfg = Debug|x64 - {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|x64.Build.0 = Debug|x64 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|Win32.ActiveCfg = Release|Win32 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|Win32.Build.0 = Release|Win32 + {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|x64.ActiveCfg = Debug|x64 + {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|x64.Build.0 = Debug|x64 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|x64.ActiveCfg = Release|x64 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|x64.Build.0 = Release|x64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|Win32.ActiveCfg = Debug|Win32 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|Win32.Build.0 = Debug|Win32 - {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|x64.ActiveCfg = Debug|x64 - {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|x64.Build.0 = Debug|x64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|Win32.ActiveCfg = Release|Win32 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|Win32.Build.0 = Release|Win32 + {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|x64.ActiveCfg = Debug|x64 + {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|x64.Build.0 = Debug|x64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|x64.ActiveCfg = Release|x64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|x64.Build.0 = Release|x64 EndGlobalSection @@ -96,13 +118,15 @@ Global HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {50D3DF82-019A-4434-B17F-72BBC291415F} = {684FF1CF-64CC-430E-81F7-9D603EF56D59} - {367FF255-7280-48C4-90AC-767124A8D5F7} = {684FF1CF-64CC-430E-81F7-9D603EF56D59} + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A} = {FA56D96B-290B-4C73-A5E1-02C1861D3224} {E0F02048-78A4-4FE8-B863-66E6CB6A2C37} = {DBD14E7B-7F95-4743-86E3-4E16FA43F990} {D253C552-154D-49E1-820A-B2CD9D9FF13E} = {50D3DF82-019A-4434-B17F-72BBC291415F} {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601} = {367FF255-7280-48C4-90AC-767124A8D5F7} + {8851AB85-70B3-4798-A149-BA366DF9EC25} = {367FF255-7280-48C4-90AC-767124A8D5F7} {33E61864-6F2C-4F9F-BE70-8F8985A4F283} = {0B4B8E51-20A8-43A4-A8DA-42FF90D628AC} {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE} = {D0DBEBE9-0DCC-4EA7-966B-C029C1334D9E} {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF} = {C06F6070-75EE-4F57-8D35-4AC2AB08D029} + {50D3DF82-019A-4434-B17F-72BBC291415F} = {684FF1CF-64CC-430E-81F7-9D603EF56D59} + {367FF255-7280-48C4-90AC-767124A8D5F7} = {684FF1CF-64CC-430E-81F7-9D603EF56D59} EndGlobalSection EndGlobal |
