mirror of
https://github.com/cemu-project/DS4Windows.git
synced 2024-11-23 09:49:16 +01:00
Fix disappearing audio with DS4 wireless dongle
This commit is contained in:
parent
031efa2b0c
commit
2a0cc058e7
244
DS4Windows/DS4Library/DS4Audio.cs
Normal file
244
DS4Windows/DS4Library/DS4Audio.cs
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ using System.Text;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using DS4Windows.DS4Library;
|
||||||
|
|
||||||
namespace DS4Windows
|
namespace DS4Windows
|
||||||
{
|
{
|
||||||
@ -131,6 +132,7 @@ namespace DS4Windows
|
|||||||
private byte ledFlashOn, ledFlashOff;
|
private byte ledFlashOn, ledFlashOff;
|
||||||
private Thread ds4Input, ds4Output;
|
private Thread ds4Input, ds4Output;
|
||||||
private int battery;
|
private int battery;
|
||||||
|
private DS4Audio audio = new DS4Audio();
|
||||||
public DateTime lastActive = DateTime.UtcNow;
|
public DateTime lastActive = DateTime.UtcNow;
|
||||||
public DateTime firstActive = DateTime.UtcNow;
|
public DateTime firstActive = DateTime.UtcNow;
|
||||||
private bool charging;
|
private bool charging;
|
||||||
@ -564,6 +566,7 @@ namespace DS4Windows
|
|||||||
outputReportBuffer[8] = LightBarColor.blue; //blue
|
outputReportBuffer[8] = LightBarColor.blue; //blue
|
||||||
outputReportBuffer[9] = ledFlashOn; //flash on duration
|
outputReportBuffer[9] = ledFlashOn; //flash on duration
|
||||||
outputReportBuffer[10] = ledFlashOff; //flash off duration
|
outputReportBuffer[10] = ledFlashOff; //flash off duration
|
||||||
|
outputReportBuffer[19] = outputReportBuffer[20] = Convert.ToByte(audio.Volume);
|
||||||
}
|
}
|
||||||
lock (outputReport)
|
lock (outputReport)
|
||||||
{
|
{
|
||||||
|
@ -98,6 +98,7 @@
|
|||||||
<Compile Include="DS4Control\X360Device.designer.cs">
|
<Compile Include="DS4Control\X360Device.designer.cs">
|
||||||
<DependentUpon>X360Device.cs</DependentUpon>
|
<DependentUpon>X360Device.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="DS4Library\DS4Audio.cs" />
|
||||||
<Compile Include="DS4Library\DS4Device.cs" />
|
<Compile Include="DS4Library\DS4Device.cs" />
|
||||||
<Compile Include="DS4Library\DS4Devices.cs" />
|
<Compile Include="DS4Library\DS4Devices.cs" />
|
||||||
<Compile Include="DS4Library\DS4Sixaxis.cs" />
|
<Compile Include="DS4Library\DS4Sixaxis.cs" />
|
||||||
@ -1117,6 +1118,7 @@
|
|||||||
<Content Include="Resources\xbox_360_controller.png" />
|
<Content Include="Resources\xbox_360_controller.png" />
|
||||||
<Content Include="Resources\Y.png" />
|
<Content Include="Resources\Y.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup />
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
Loading…
Reference in New Issue
Block a user