diff --git a/DS4Windows/DS4Library/DS4Audio.cs b/DS4Windows/DS4Library/DS4Audio.cs
new file mode 100644
index 0000000..74ba536
--- /dev/null
+++ b/DS4Windows/DS4Library/DS4Audio.cs
@@ -0,0 +1,244 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using DS4Windows.DS4Library.CoreAudio;
+
+namespace DS4Windows.DS4Library
+{
+ public class DS4Audio
+ {
+ private IAudioEndpointVolume endpointVolume;
+
+ private static Guid IID_IAudioEndpointVolume = new Guid("5CDF2C82-841E-4546-9722-0CF74078229A");
+ private static readonly PropertyKey PKEY_Device_FriendlyName =
+ new PropertyKey(new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), 14);
+
+ public uint Volume
+ {
+ get
+ {
+ float pfLevel = 0;
+
+ if (endpointVolume != null)
+ endpointVolume.GetMasterVolumeLevelScalar(out pfLevel);
+
+ return Convert.ToUInt32(pfLevel * 100);
+ }
+ }
+
+ public DS4Audio()
+ {
+ var audioEnumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
+ IMMDeviceCollection audioDevices;
+ audioEnumerator.EnumAudioEndpoints(DataFlow.Render, DeviceState.Active, out audioDevices);
+
+ int numAudioDevices;
+ Marshal.ThrowExceptionForHR(audioDevices.GetCount(out numAudioDevices));
+
+ for (int deviceNumber = 0; deviceNumber < numAudioDevices; ++deviceNumber)
+ {
+ IMMDevice audioDevice;
+ Marshal.ThrowExceptionForHR(audioDevices.Item(deviceNumber, out audioDevice));
+ string deviceName = GetAudioDeviceName(ref audioDevice);
+
+ if (deviceName.Contains("DUALSHOCK®4 USB Wireless Adaptor"))
+ {
+ object interfacePointer;
+ Marshal.ThrowExceptionForHR(audioDevice.Activate(ref IID_IAudioEndpointVolume, ClsCtx.ALL, IntPtr.Zero, out interfacePointer));
+ endpointVolume = interfacePointer as IAudioEndpointVolume;
+ }
+
+ Marshal.ReleaseComObject(audioDevice);
+ }
+
+ Marshal.ReleaseComObject(audioDevices);
+ Marshal.ReleaseComObject(audioEnumerator);
+ }
+
+ ~DS4Audio()
+ {
+ if (endpointVolume != null)
+ {
+ Marshal.ReleaseComObject(endpointVolume);
+ endpointVolume = null;
+ }
+ }
+
+ private string GetAudioDeviceName(ref IMMDevice audioDevice)
+ {
+ IPropertyStore propertyStore;
+ Marshal.ThrowExceptionForHR(audioDevice.OpenPropertyStore(StorageAccessMode.Read, out propertyStore));
+
+ int numProperties;
+ Marshal.ThrowExceptionForHR(propertyStore.GetCount(out numProperties));
+
+ string deviceName = String.Empty;
+
+ for (int propertyNum = 0; propertyNum < numProperties; ++propertyNum)
+ {
+ PropertyKey propertyKey;
+ Marshal.ThrowExceptionForHR(propertyStore.GetAt(propertyNum, out propertyKey));
+
+ if ((propertyKey.formatId == PKEY_Device_FriendlyName.formatId) && (propertyKey.propertyId == PKEY_Device_FriendlyName.propertyId))
+ {
+ PropVariant propertyValue;
+ Marshal.ThrowExceptionForHR(propertyStore.GetValue(ref propertyKey, out propertyValue));
+ deviceName = Marshal.PtrToStringUni(propertyValue.pointerValue);
+ break;
+ }
+ }
+
+ Marshal.ReleaseComObject(propertyStore);
+ return deviceName;
+ }
+ }
+}
+
+namespace DS4Windows.DS4Library.CoreAudio
+{
+ public enum DataFlow
+ {
+ Render,
+ Capture,
+ All
+ };
+
+ [Flags]
+ public enum DeviceState
+ {
+ Active = 0x00000001,
+ Disabled = 0x00000002,
+ NotPresent = 0x00000004,
+ Unplugged = 0x00000008,
+ All = 0x0000000F
+ }
+
+ enum StorageAccessMode
+ {
+ Read,
+ Write,
+ ReadWrite
+ }
+
+ [Flags]
+ public enum ClsCtx
+ {
+ INPROC_SERVER = 0x1,
+ INPROC_HANDLER = 0x2,
+ LOCAL_SERVER = 0x4,
+ INPROC_SERVER16 = 0x8,
+ REMOTE_SERVER = 0x10,
+ INPROC_HANDLER16 = 0x20,
+ NO_CODE_DOWNLOAD = 0x400,
+ NO_CUSTOM_MARSHAL = 0x1000,
+ ENABLE_CODE_DOWNLOAD = 0x2000,
+ NO_FAILURE_LOG = 0x4000,
+ DISABLE_AAA = 0x8000,
+ ENABLE_AAA = 0x10000,
+ FROM_DEFAULT_CONTEXT = 0x20000,
+ ACTIVATE_32_BIT_SERVER = 0x40000,
+ ACTIVATE_64_BIT_SERVER = 0x80000,
+ ENABLE_CLOAKING = 0x100000,
+ PS_DLL = unchecked((int)0x80000000),
+ INPROC = INPROC_SERVER | INPROC_HANDLER,
+ SERVER = INPROC_SERVER | LOCAL_SERVER | REMOTE_SERVER,
+ ALL = SERVER | INPROC_HANDLER
+ }
+
+ public struct PropertyKey
+ {
+ public Guid formatId;
+ public int propertyId;
+ public PropertyKey(Guid formatId, int propertyId)
+ {
+ this.formatId = formatId;
+ this.propertyId = propertyId;
+ }
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct PropVariant
+ {
+ [FieldOffset(0)] private short vt;
+ [FieldOffset(2)] private short wReserved1;
+ [FieldOffset(4)] private short wReserved2;
+ [FieldOffset(6)] private short wReserved3;
+ [FieldOffset(8)] public IntPtr pointerValue;
+ }
+
+ [Guid("886d8eeb-8cf2-4446-8d02-cdba1dbdcf99"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ interface IPropertyStore
+ {
+ int GetCount(out int propCount);
+ int GetAt(int property, out PropertyKey key);
+ int GetValue(ref PropertyKey key, out PropVariant value);
+ int SetValue(ref PropertyKey key, ref PropVariant value);
+ int Commit();
+ }
+
+ [Guid("D666063F-1587-4E43-81F1-B948E807363F"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ interface IMMDevice
+ {
+ int Activate(ref Guid id, ClsCtx clsCtx, IntPtr activationParams,
+ [MarshalAs(UnmanagedType.IUnknown)] out object interfacePointer);
+
+ int OpenPropertyStore(StorageAccessMode stgmAccess, out IPropertyStore properties);
+
+ int GetId([MarshalAs(UnmanagedType.LPWStr)] out string id);
+ }
+
+ [Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ interface IMMDeviceCollection
+ {
+ int GetCount(out int numDevices);
+ int Item(int deviceNumber, out IMMDevice device);
+ }
+
+ [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ interface IMMDeviceEnumerator
+ {
+ int EnumAudioEndpoints(DataFlow dataFlow, DeviceState stateMask, out IMMDeviceCollection devices);
+ }
+
+ [ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
+ class MMDeviceEnumeratorComObject
+ {
+ }
+
+ [Guid("657804FA-D6AD-4496-8A60-352752AF4F89"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface IAudioEndpointVolumeCallback
+ {
+ void OnNotify(IntPtr notifyData);
+ };
+
+ [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface IAudioEndpointVolume
+ {
+ int RegisterControlChangeNotify(IAudioEndpointVolumeCallback pNotify);
+ int UnregisterControlChangeNotify(IAudioEndpointVolumeCallback pNotify);
+ int GetChannelCount(out int pnChannelCount);
+ int SetMasterVolumeLevel(float fLevelDB, ref Guid pguidEventContext);
+ int SetMasterVolumeLevelScalar(float fLevel, ref Guid pguidEventContext);
+ int GetMasterVolumeLevel(out float pfLevelDB);
+ int GetMasterVolumeLevelScalar(out float pfLevel);
+ int SetChannelVolumeLevel(uint nChannel, float fLevelDB, ref Guid pguidEventContext);
+ int SetChannelVolumeLevelScalar(uint nChannel, float fLevel, ref Guid pguidEventContext);
+ int GetChannelVolumeLevel(uint nChannel, out float pfLevelDB);
+ int GetChannelVolumeLevelScalar(uint nChannel, out float pfLevel);
+ int SetMute([MarshalAs(UnmanagedType.Bool)] Boolean bMute, ref Guid pguidEventContext);
+ int GetMute(out bool pbMute);
+ int GetVolumeStepInfo(out uint pnStep, out uint pnStepCount);
+ int VolumeStepUp(ref Guid pguidEventContext);
+ int VolumeStepDown(ref Guid pguidEventContext);
+ int QueryHardwareSupport(out uint pdwHardwareSupportMask);
+ int GetVolumeRange(out float pflVolumeMindB, out float pflVolumeMaxdB, out float pflVolumeIncrementdB);
+ }
+}
\ No newline at end of file
diff --git a/DS4Windows/DS4Library/DS4Device.cs b/DS4Windows/DS4Library/DS4Device.cs
index 216ac3d..6967218 100644
--- a/DS4Windows/DS4Library/DS4Device.cs
+++ b/DS4Windows/DS4Library/DS4Device.cs
@@ -14,6 +14,7 @@ using System.Text;
using System.IO;
using System.Collections;
using System.Drawing;
+using DS4Windows.DS4Library;
namespace DS4Windows
{
@@ -138,6 +139,7 @@ namespace DS4Windows
private byte ledFlashOn, ledFlashOff;
private Thread ds4Input, ds4Output;
private int battery;
+ private DS4Audio audio = new DS4Audio();
public DateTime lastActive = DateTime.UtcNow;
public DateTime firstActive = DateTime.UtcNow;
private bool charging;
@@ -647,6 +649,7 @@ namespace DS4Windows
outputReportBuffer[8] = LightBarColor.blue; //blue
outputReportBuffer[9] = ledFlashOn; //flash on duration
outputReportBuffer[10] = ledFlashOff; //flash off duration
+ outputReportBuffer[19] = outputReportBuffer[20] = Convert.ToByte(audio.Volume);
}
lock (outputReport)
{
diff --git a/DS4Windows/DS4Windows.csproj b/DS4Windows/DS4Windows.csproj
index 618c91b..12e42b7 100644
--- a/DS4Windows/DS4Windows.csproj
+++ b/DS4Windows/DS4Windows.csproj
@@ -119,6 +119,7 @@
X360Device.cs
+
@@ -1138,6 +1139,7 @@
+