Added default device selection
This commit is contained in:
@@ -70,6 +70,7 @@ namespace EonaCat.VolumeMixer.Tester.WPF
|
|||||||
await RefreshSessions();
|
await RefreshSessions();
|
||||||
_refreshTimer.Start();
|
_refreshTimer.Start();
|
||||||
_pollTimer.Start();
|
_pollTimer.Start();
|
||||||
|
_currentDevice.SetDefaultDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RefreshSessions()
|
private async Task RefreshSessions()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using EonaCat.VolumeMixer.Managers;
|
using EonaCat.VolumeMixer.Managers;
|
||||||
using EonaCat.VolumeMixer.Models;
|
using EonaCat.VolumeMixer.Models;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
class Program
|
class Program
|
||||||
@@ -15,16 +16,6 @@ class Program
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
var devicesTest = await volumeMixer.GetAudioDevicesAsync(DataFlow.Output);
|
|
||||||
var micrphonesTest = await volumeMixer.GetMicrophonesAsync();
|
|
||||||
Console.WriteLine($"Found {devicesTest.Count} playback devices");
|
|
||||||
Console.WriteLine($"Found {micrphonesTest.Count} microphones");
|
|
||||||
await Task.Delay(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Get all audio PLAYBACK devices
|
// Get all audio PLAYBACK devices
|
||||||
var devices = await volumeMixer.GetAudioDevicesAsync(DataFlow.Output);
|
var devices = await volumeMixer.GetAudioDevicesAsync(DataFlow.Output);
|
||||||
Console.WriteLine($"Found {devices.Count} playback devices:");
|
Console.WriteLine($"Found {devices.Count} playback devices:");
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
<PackageTags>EonaCat, Audio, Volume, Mixer .NET Standard, Jeroen, Saey</PackageTags>
|
<PackageTags>EonaCat, Audio, Volume, Mixer .NET Standard, Jeroen, Saey</PackageTags>
|
||||||
<PackageReleaseNotes></PackageReleaseNotes>
|
<PackageReleaseNotes></PackageReleaseNotes>
|
||||||
<Description>EonaCat VolumeMixer</Description>
|
<Description>EonaCat VolumeMixer</Description>
|
||||||
<Version>1.0.6</Version>
|
<Version>1.0.7</Version>
|
||||||
<AssemblyVersion>1.0.0.6</AssemblyVersion>
|
<AssemblyVersion>1.0.0.7</AssemblyVersion>
|
||||||
<FileVersion>1.0.0.6</FileVersion>
|
<FileVersion>1.0.0.7</FileVersion>
|
||||||
<PackageIcon>icon.png</PackageIcon>
|
<PackageIcon>icon.png</PackageIcon>
|
||||||
<RepositoryUrl>https://git.saey.me/EonaCat/EonaCat.VolumeMixer</RepositoryUrl>
|
<RepositoryUrl>https://git.saey.me/EonaCat/EonaCat.VolumeMixer</RepositoryUrl>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
@@ -51,4 +51,8 @@
|
|||||||
<PackagePath>\</PackagePath>
|
<PackagePath>\</PackagePath>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace EonaCat.VolumeMixer.Helpers
|
|
||||||
{
|
|
||||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
|
||||||
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
|
||||||
internal static class ComHelper
|
|
||||||
{
|
|
||||||
public static T GetInterface<T>(IntPtr ptr) where T : class
|
|
||||||
{
|
|
||||||
if (ptr == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return Marshal.GetObjectForIUnknown(ptr) as T;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (ptr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
Marshal.Release(ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ReleaseComObject(object comObj)
|
|
||||||
{
|
|
||||||
if (comObj == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (Marshal.ReleaseComObject(comObj) > 0)
|
|
||||||
{
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Marshal.FinalReleaseComObject(comObj);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -41,7 +41,10 @@ namespace EonaCat.VolumeMixer.Managers
|
|||||||
return await Task.Run(() =>
|
return await Task.Run(() =>
|
||||||
{
|
{
|
||||||
var devices = new List<AudioDevice>();
|
var devices = new List<AudioDevice>();
|
||||||
if (_isDisposed || _deviceEnumerator == null) return devices;
|
if (_isDisposed || _deviceEnumerator == null)
|
||||||
|
{
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
lock (_syncLock)
|
lock (_syncLock)
|
||||||
{
|
{
|
||||||
@@ -51,10 +54,16 @@ namespace EonaCat.VolumeMixer.Managers
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
int hr = _deviceEnumerator.EnumAudioEndpoints(dataFlow, DeviceState.Active, out collection);
|
int hr = _deviceEnumerator.EnumAudioEndpoints(dataFlow, DeviceState.Active, out collection);
|
||||||
if (hr != 0 || collection == null) return devices;
|
if (hr != 0 || collection == null)
|
||||||
|
{
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
hr = collection.GetCount(out var count);
|
hr = collection.GetCount(out var count);
|
||||||
if (hr != 0) return devices;
|
if (hr != 0)
|
||||||
|
{
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
// Get default device
|
// Get default device
|
||||||
string defaultId = string.Empty;
|
string defaultId = string.Empty;
|
||||||
@@ -77,9 +86,15 @@ namespace EonaCat.VolumeMixer.Managers
|
|||||||
IMultiMediaDevice device = null;
|
IMultiMediaDevice device = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (collection.Item(i, out device) != 0 || device == null) continue;
|
if (collection.Item(i, out device) != 0 || device == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (device.GetId(out var id) != 0 || string.IsNullOrEmpty(id)) continue;
|
if (device.GetId(out var id) != 0 || string.IsNullOrEmpty(id))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
string name = GetDeviceName(device);
|
string name = GetDeviceName(device);
|
||||||
DeviceType type = GetDeviceType(device);
|
DeviceType type = GetDeviceType(device);
|
||||||
@@ -131,7 +146,10 @@ namespace EonaCat.VolumeMixer.Managers
|
|||||||
|
|
||||||
public async Task<AudioDevice> GetDefaultAudioDeviceAsync(DataFlow dataFlow = DataFlow.Output)
|
public async Task<AudioDevice> GetDefaultAudioDeviceAsync(DataFlow dataFlow = DataFlow.Output)
|
||||||
{
|
{
|
||||||
if (_isDisposed || _deviceEnumerator == null) return null;
|
if (_isDisposed || _deviceEnumerator == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return await Task.Run(() =>
|
return await Task.Run(() =>
|
||||||
{
|
{
|
||||||
@@ -165,7 +183,11 @@ namespace EonaCat.VolumeMixer.Managers
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (device.OpenPropertyStore(0, out store) != 0 || store == null) return "Unknown Device";
|
if (device.OpenPropertyStore(0, out store) != 0 || store == null)
|
||||||
|
{
|
||||||
|
return "Unknown Device";
|
||||||
|
}
|
||||||
|
|
||||||
if (store.GetValue(ref PKEY_Device_FriendlyName, out prop) == 0 &&
|
if (store.GetValue(ref PKEY_Device_FriendlyName, out prop) == 0 &&
|
||||||
prop.vt == VarEnumConstants.VT_LPWSTR && prop.pointerValue != IntPtr.Zero)
|
prop.vt == VarEnumConstants.VT_LPWSTR && prop.pointerValue != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
@@ -190,7 +212,11 @@ namespace EonaCat.VolumeMixer.Managers
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (device.OpenPropertyStore(0, out store) != 0 || store == null) return DeviceType.Unknown;
|
if (device.OpenPropertyStore(0, out store) != 0 || store == null)
|
||||||
|
{
|
||||||
|
return DeviceType.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
if (store.GetValue(ref PKEY_AudioEndpoint_FormFactor, out prop) == 0 && prop.vt == VarEnumConstants.VT_UI4)
|
if (store.GetValue(ref PKEY_AudioEndpoint_FormFactor, out prop) == 0 && prop.vt == VarEnumConstants.VT_UI4)
|
||||||
{
|
{
|
||||||
return prop.uintValue switch
|
return prop.uintValue switch
|
||||||
@@ -425,7 +451,11 @@ namespace EonaCat.VolumeMixer.Managers
|
|||||||
{
|
{
|
||||||
lock (_syncLock)
|
lock (_syncLock)
|
||||||
{
|
{
|
||||||
if (_isDisposed) return;
|
if (_isDisposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_isDisposed = true;
|
_isDisposed = true;
|
||||||
SafeRelease(ref _deviceEnumerator);
|
SafeRelease(ref _deviceEnumerator);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,7 +110,10 @@ namespace EonaCat.VolumeMixer.Models
|
|||||||
|
|
||||||
public async Task<bool> SetMasterVolumeAsync(float volume)
|
public async Task<bool> SetMasterVolumeAsync(float volume)
|
||||||
{
|
{
|
||||||
if (_isDisposed || _endpointVolume == null || volume < 0f || volume > 1f) return false;
|
if (_isDisposed || _endpointVolume == null || volume < 0f || volume > 1f)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var guid = Guid.Empty;
|
var guid = Guid.Empty;
|
||||||
lock (_syncLock)
|
lock (_syncLock)
|
||||||
@@ -123,7 +126,11 @@ namespace EonaCat.VolumeMixer.Models
|
|||||||
{
|
{
|
||||||
lock (_syncLock)
|
lock (_syncLock)
|
||||||
{
|
{
|
||||||
if (_isDisposed || _endpointVolume == null) return Task.FromResult(false);
|
if (_isDisposed || _endpointVolume == null)
|
||||||
|
{
|
||||||
|
return Task.FromResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int hr = _endpointVolume.GetMute(out bool mute);
|
int hr = _endpointVolume.GetMute(out bool mute);
|
||||||
@@ -135,7 +142,10 @@ namespace EonaCat.VolumeMixer.Models
|
|||||||
|
|
||||||
public Task<bool> SetMasterMuteAsync(bool mute)
|
public Task<bool> SetMasterMuteAsync(bool mute)
|
||||||
{
|
{
|
||||||
if (_isDisposed || _endpointVolume == null) return Task.FromResult(false);
|
if (_isDisposed || _endpointVolume == null)
|
||||||
|
{
|
||||||
|
return Task.FromResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
var guid = Guid.Empty;
|
var guid = Guid.Empty;
|
||||||
lock (_syncLock)
|
lock (_syncLock)
|
||||||
@@ -147,19 +157,28 @@ namespace EonaCat.VolumeMixer.Models
|
|||||||
public async Task<List<AudioSession>> GetAudioSessionsAsync()
|
public async Task<List<AudioSession>> GetAudioSessionsAsync()
|
||||||
{
|
{
|
||||||
var sessions = new List<AudioSession>();
|
var sessions = new List<AudioSession>();
|
||||||
if (_isDisposed || _sessionManager == null) return sessions;
|
if (_isDisposed || _sessionManager == null)
|
||||||
|
{
|
||||||
|
return sessions;
|
||||||
|
}
|
||||||
|
|
||||||
lock (_syncLock)
|
lock (_syncLock)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int hr = _sessionManager.GetSessionEnumerator(out var sessionEnum);
|
int hr = _sessionManager.GetSessionEnumerator(out var sessionEnum);
|
||||||
if (hr != 0 || sessionEnum == null) return sessions;
|
if (hr != 0 || sessionEnum == null)
|
||||||
|
{
|
||||||
|
return sessions;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
hr = sessionEnum.GetCount(out int count);
|
hr = sessionEnum.GetCount(out int count);
|
||||||
if (hr != 0) return sessions;
|
if (hr != 0)
|
||||||
|
{
|
||||||
|
return sessions;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
@@ -195,7 +214,10 @@ namespace EonaCat.VolumeMixer.Models
|
|||||||
|
|
||||||
private IAudioSessionControlExtended GetSessionControl2(object sessionControl)
|
private IAudioSessionControlExtended GetSessionControl2(object sessionControl)
|
||||||
{
|
{
|
||||||
if (sessionControl == null) return null;
|
if (sessionControl == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
IntPtr unknownPtr = IntPtr.Zero;
|
IntPtr unknownPtr = IntPtr.Zero;
|
||||||
IntPtr sessionControl2Ptr = IntPtr.Zero;
|
IntPtr sessionControl2Ptr = IntPtr.Zero;
|
||||||
@@ -211,8 +233,15 @@ namespace EonaCat.VolumeMixer.Models
|
|||||||
catch (Exception ex) { Debug.WriteLine($"GetSessionControl2 failed: {ex}"); }
|
catch (Exception ex) { Debug.WriteLine($"GetSessionControl2 failed: {ex}"); }
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (sessionControl2Ptr != IntPtr.Zero) Marshal.Release(sessionControl2Ptr);
|
if (sessionControl2Ptr != IntPtr.Zero)
|
||||||
if (unknownPtr != IntPtr.Zero) Marshal.Release(unknownPtr);
|
{
|
||||||
|
Marshal.Release(sessionControl2Ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unknownPtr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Marshal.Release(unknownPtr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -273,7 +302,11 @@ namespace EonaCat.VolumeMixer.Models
|
|||||||
{
|
{
|
||||||
lock (_syncLock)
|
lock (_syncLock)
|
||||||
{
|
{
|
||||||
if (_isDisposed) return;
|
if (_isDisposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_isDisposed = true;
|
_isDisposed = true;
|
||||||
|
|
||||||
SafeRelease(ref _endpointVolume);
|
SafeRelease(ref _endpointVolume);
|
||||||
@@ -282,6 +315,28 @@ namespace EonaCat.VolumeMixer.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool SetDefaultDevice()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var policyConfig = new PolicyConfigClient();
|
||||||
|
policyConfig.SetDefaultEndpoint(Id, Role.Multimedia);
|
||||||
|
policyConfig.SetDefaultEndpoint(Id, Role.Console);
|
||||||
|
|
||||||
|
if (DeviceType == DeviceType.Microphone)
|
||||||
|
{
|
||||||
|
policyConfig.SetDefaultEndpoint(Id, Role.Communications);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error setting default device: {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void SafeRelease<T>(ref T comObj) where T : class
|
private static void SafeRelease<T>(ref T comObj) where T : class
|
||||||
{
|
{
|
||||||
if (comObj != null)
|
if (comObj != null)
|
||||||
@@ -290,5 +345,66 @@ namespace EonaCat.VolumeMixer.Models
|
|||||||
comObj = null;
|
comObj = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void SendException(Exception exception)
|
||||||
|
{
|
||||||
|
OnException?.Invoke(this, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("F8679F50-850A-41CF-9C72-430F290290C8")]
|
||||||
|
internal interface IPolicyConfig
|
||||||
|
{
|
||||||
|
[PreserveSig]
|
||||||
|
int GetMixFormat(string pstrDeviceName, IntPtr ppFormat);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetDeviceFormat(string pstrDeviceName, bool bDefault, IntPtr ppFormat);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int ResetDeviceFormat(string pstrDeviceName);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int SetDeviceFormat(string pstrDeviceName, IntPtr pEndpointFormat, IntPtr MixFormat);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetProcessingPeriod(string pstrDeviceName, bool bDefault, IntPtr pmftDefaultPeriod, IntPtr pmftMinimumPeriod);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int SetProcessingPeriod(string pstrDeviceName, IntPtr pmftPeriod);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetShareMode(string pstrDeviceName, IntPtr pMode);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int SetShareMode(string pstrDeviceName, IntPtr mode);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetPropertyValue(string pstrDeviceName, bool bFxStore, ref PropertyKey key, IntPtr pv);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int SetPropertyValue(string pstrDeviceName, bool bFxStore, ref PropertyKey key, IntPtr pv);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int SetDefaultEndpoint(string pstrDeviceName, Role role);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int SetEndpointVisibility(string pstrDeviceName, bool bVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
//[ComImport, Guid("870AF99C-171D-4F9E-AF0D-E63DF40C2BC9")]
|
||||||
|
internal class PolicyConfigClient
|
||||||
|
{
|
||||||
|
private readonly IPolicyConfig policyConfig;
|
||||||
|
|
||||||
|
public PolicyConfigClient()
|
||||||
|
{
|
||||||
|
policyConfig = (IPolicyConfig)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("870AF99C-171D-4F9E-AF0D-E63DF40C2BC9")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetDefaultEndpoint(string deviceId, Role role)
|
||||||
|
{
|
||||||
|
policyConfig.SetDefaultEndpoint(deviceId, role);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ namespace EonaCat.VolumeMixer.Models
|
|||||||
{
|
{
|
||||||
lock (_syncLock)
|
lock (_syncLock)
|
||||||
{
|
{
|
||||||
if (_sessionControl == null) return;
|
if (_sessionControl == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
IntPtr unknownPtr = IntPtr.Zero;
|
IntPtr unknownPtr = IntPtr.Zero;
|
||||||
try
|
try
|
||||||
@@ -48,7 +51,10 @@ namespace EonaCat.VolumeMixer.Models
|
|||||||
catch { _audioVolume = null; }
|
catch { _audioVolume = null; }
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (unknownPtr != IntPtr.Zero) Marshal.Release(unknownPtr);
|
if (unknownPtr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Marshal.Release(unknownPtr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -255,7 +261,11 @@ namespace EonaCat.VolumeMixer.Models
|
|||||||
{
|
{
|
||||||
lock (_syncLock)
|
lock (_syncLock)
|
||||||
{
|
{
|
||||||
if (_isDisposed) return;
|
if (_isDisposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_isDisposed = true;
|
_isDisposed = true;
|
||||||
|
|
||||||
SafeRelease(ref _audioVolume);
|
SafeRelease(ref _audioVolume);
|
||||||
|
|||||||
Reference in New Issue
Block a user