private void LoadAudioMeterInformation() { if (_audioMeterInformation?.IsValueCreated == true) { return; } _audioMeterInformation = new ThreadLocal <IAudioMeterInformation>(() => { return(ComThread.Invoke(() => { Exception ex; //Need to catch here, as there is a chance that unauthorized is thrown. //It's not an HR exception, but bubbles up through the .net call stack try { var clsGuid = new Guid(ComInterfaceIds.AUDIO_METER_INFORMATION_IID); object result; ex = Marshal.GetExceptionForHR(Device.Activate(ref clsGuid, ClassContext.Inproc, IntPtr.Zero, out result)); if (ex != null) { return null; } _audioMeterInformationPtr = Marshal.GetIUnknownForObject(result); return Marshal.GetUniqueObjectForIUnknown(_audioMeterInformationPtr) as IAudioMeterInformation; } catch (Exception e) { ex = e; } return null; })); }); }
/// <summary> /// Indexer - get a specific channel /// </summary> public AudioEndpointVolumeChannel this[int index] { get { return(ComThread.Invoke(() => _channels[index])); } }
public CoreAudioController() { // ReSharper disable once SuspiciousTypeConversion.Global var innerEnumerator = ComObjectFactory.GetDeviceEnumerator(); _innerEnumeratorPtr = Marshal.GetIUnknownForObject(innerEnumerator); if (innerEnumerator == null) { throw new InvalidComObjectException("No Device Enumerator"); } _innerEnumerator = new ThreadLocal <IMultimediaDeviceEnumerator>(() => Marshal.GetUniqueObjectForIUnknown(_innerEnumeratorPtr) as IMultimediaDeviceEnumerator); ComThread.Invoke(() => { _systemEvents = new SystemEventNotifcationClient(() => InnerEnumerator); _systemEvents.DeviceAdded.Subscribe(x => OnDeviceAdded(x.DeviceId)); _systemEvents.DeviceRemoved.Subscribe(x => OnDeviceRemoved(x.DeviceId)); _deviceCache = new HashSet <CoreAudioDevice>(); IMultimediaDeviceCollection collection; InnerEnumerator.EnumAudioEndpoints(EDataFlow.All, EDeviceState.All, out collection); using (var coll = new MultimediaDeviceCollection(collection)) { foreach (var mDev in coll) { CacheDevice(mDev); } } }); }
/// <summary> /// Switch the audio endpoint of the given process /// </summary> /// <param name="deviceId">Id of the device</param> /// <param name="role">Which role to switch</param> /// <param name="flow">Which flow to switch</param> /// <param name="processId">ProcessID of the process</param> public void SwitchProcessTo(string deviceId, ERole role, EDataFlow flow, uint processId) { var roles = new[] { ERole.eConsole, ERole.eCommunications, ERole.eMultimedia }; if (role != ERole.ERole_enum_count) { roles = new[] { role }; } ComThread.Invoke((() => { var currentEndpoint = roles.Select(eRole => ExtendPolicyClient.GetDefaultEndPoint(flow, eRole, processId)).FirstOrDefault(endpoint => !string.IsNullOrEmpty(endpoint)); if (deviceId.Equals(currentEndpoint)) { Trace.WriteLine($"Default endpoint for {processId} already {deviceId}"); return; } ExtendPolicyClient.SetDefaultEndPoint(deviceId, flow, roles, processId); })); }
public DeviceInfo?GetDefaultAudioEndpoint(EDataFlow flow, ERole role) => ComThread.Invoke(() => { var defaultEndpoint = EnumeratorClient.GetDefaultEndpoint(flow, role); if (defaultEndpoint == null) { return(null); } return(new DeviceFullInfo(defaultEndpoint)); });
public WindowMonitor() { _foregroundWindowChanged = (hook, type, hwnd, idObject, child, thread, time) => { // ignore any event not pertaining directly to the window if (idObject != User32.NativeMethods.OBJID_WINDOW) { return; } // Ignore if this is a bogus hwnd (shouldn't happen) if (hwnd == IntPtr.Zero) { return; } var(processId, windowText, windowClass) = ProcessWindowInformation(hwnd); //Couldn't find the processId of the window if (processId == 0) { return; } Task.Factory.StartNew(() => { try { var process = Process.GetProcessById((int)processId); var processName = process.MainModule?.FileName ?? "N/A"; ForegroundChanged?.Invoke(this, new Event(processId, processName, windowText, windowClass, hwnd)); } catch (Exception e) { Log.Warning(e, "Couldn't get info about foreground process"); } }); }; ComThread.Invoke(() => { User32.NativeMethods.SetWinEventHook(User32.NativeMethods.EVENT_SYSTEM_MINIMIZEEND, User32.NativeMethods.EVENT_SYSTEM_MINIMIZEEND, IntPtr.Zero, _foregroundWindowChanged, 0, 0, User32.NativeMethods.WINEVENT_OUTOFCONTEXT); User32.NativeMethods.SetWinEventHook(User32.NativeMethods.EVENT_SYSTEM_FOREGROUND, User32.NativeMethods.EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, _foregroundWindowChanged, 0, 0, User32.NativeMethods.WINEVENT_OUTOFCONTEXT); }); }
private void ReloadAudioEndpointVolume() { ComThread.Invoke(() => { LoadAudioEndpointVolume(); if (AudioEndpointVolume != null) { AudioEndpointVolume.OnVolumeNotification += AudioEndpointVolume_OnVolumeNotification; } }); }
/// <summary> /// Get device by index /// </summary> /// <param name="index">Device index</param> /// <returns>Device at the specified index</returns> public IMMDevice this[int index] { get { return(ComThread.Invoke(() => { IMMDevice result; _mmDeviceCollection.Item(Convert.ToUInt32(index), out result); return result; })); } }
/// <summary> /// Switch the default audio device to the one given /// </summary> /// <param name="deviceId"></param> /// <param name="role"></param> public void SwitchTo(string deviceId, ERole role) { if (role != ERole.ERole_enum_count) { ComThread.Invoke((() => _policyClient.SetDefaultEndpoint(deviceId, role))); return; } SwitchTo(deviceId, ERole.eConsole); SwitchTo(deviceId, ERole.eMultimedia); SwitchTo(deviceId, ERole.eCommunications); }
private void AddDeviceFromRealId(string deviceId) { ComThread.Invoke(() => { IMMDevice mDevice; _innerEnumerator.GetDevice(deviceId, out mDevice); if (mDevice != null) { CacheDevice(mDevice); } }); }
/// <summary> /// Get Peak value /// </summary> /// <param name="index">Channel index</param> /// <returns>Peak value</returns> public float this[int index] { get { return(ComThread.Invoke(() => { var peakValues = new float[Count]; Marshal.ThrowExceptionForHR( _audioMeterInformation.GetChannelsPeakValues(Convert.ToUInt32(peakValues.Length), peakValues)); return peakValues[index]; })); } }
public async Task <bool> SetMuteAsync(bool muted, CancellationToken cancellationToken) { ThrowIfDisposed(); if (_isMuted == muted) { return(_isMuted); } ComThread.Invoke(() => SimpleAudioVolume.SetMute(muted, Guid.Empty)); await _muteResetEvent.WaitOneAsync(cancellationToken); return(_isMuted); }
public async Task <double> SetVolumeAsync(double volume, CancellationToken cancellationToken) { ThrowIfDisposed(); if (Math.Abs(_volume - volume) < 0.1) { return(_volume); } var normalizedVolume = volume.NormalizeVolume(); ComThread.Invoke(() => SimpleAudioVolume.SetMasterVolume(normalizedVolume, Guid.Empty)); await _volumeResetEvent.WaitOneAsync(cancellationToken); return(_volume); }
public ForegroundProcess() { _winEventDelegate = (hook, type, hwnd, idObject, child, thread, time) => { var windowProcessId = ComThread.Invoke(() => { try { User32.NativeMethods.GetWindowThreadProcessId(hwnd, out var processId); return(processId); } catch { return((uint)0); } }); if (windowProcessId == 0) { return; } Task.Factory.StartNew(() => { var process = Process.GetProcessById((int)windowProcessId); var processName = process.MainModule?.FileName ?? "N/A"; Changed?.Invoke(this, new Event(windowProcessId, processName)); }); }; ComThread.Invoke(() => { User32.NativeMethods.SetWinEventHook(User32.NativeMethods.EVENT_SYSTEM_MINIMIZEEND, User32.NativeMethods.EVENT_SYSTEM_MINIMIZEEND, IntPtr.Zero, _winEventDelegate, 0, 0, User32.NativeMethods.WINEVENT_OUTOFCONTEXT); User32.NativeMethods.SetWinEventHook(User32.NativeMethods.EVENT_SYSTEM_FOREGROUND, User32.NativeMethods.EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, _winEventDelegate, 0, 0, User32.NativeMethods.WINEVENT_OUTOFCONTEXT); }); }
private void RefreshSystemDevices() { ComThread.Invoke(() => { _deviceCache = new HashSet <CoreAudioDevice>(); IMMDeviceCollection collection; _innerEnumerator.EnumAudioEndpoints(EDataFlow.All, EDeviceState.All, out collection); using (var coll = new MMDeviceCollection(collection)) { foreach (var mDev in coll) { CacheDevice(mDev); } } }); }
public CoreAudioController() { ComThread.Invoke(() => { // ReSharper disable once SuspiciousTypeConversion.Global _innerEnumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator; if (_innerEnumerator == null) { return; } _notificationClient = new MMNotificationClient(this); _innerEnumerator.RegisterEndpointNotificationCallback(_notificationClient); }); RefreshSystemDevices(); }
private void RefreshVolume() { if (_isDisposed) { return; } ComThread.Invoke(() => { float vol; SimpleAudioVolume.GetMasterVolume(out vol); _volume = vol * 100; bool isMuted; SimpleAudioVolume.GetMute(out isMuted); _isMuted = isMuted; }); }
/// <summary> /// Switch the audio endpoint of the given process /// </summary> /// <param name="deviceId">Id of the device</param> /// <param name="role">Which role to switch</param> /// <param name="flow">Which flow to switch</param> /// <param name="processId">ProcessID of the process</param> public void SwitchProcessTo(string deviceId, ERole role, EDataFlow flow, uint processId) { var roles = new ERole[] { ERole.eConsole, ERole.eCommunications, ERole.eMultimedia }; if (role != ERole.ERole_enum_count) { roles = new ERole[] { role }; } ComThread.Invoke((() => ExtendPolicyClient.SetDefaultEndPoint(deviceId, flow, roles, processId))); }
private void LoadAudioSessionController() { if (_sessionController?.IsValueCreated == true) { return; } _sessionController = new Lazy <CoreAudioSessionController>(() => { return(ComThread.Invoke(() => { //Need to catch here, as there is a chance that unauthorized is thrown. //It's not an HR exception, but bubbles up through the .net call stack try { var clsGuid = new Guid(ComInterfaceIds.AUDIO_SESSION_MANAGER2_IID); object result; Marshal.GetExceptionForHR(Device.Activate(ref clsGuid, ClassContext.Inproc, IntPtr.Zero, out result)); //This is scoped into the managed object, so disposal is taken care of there. var audioSessionManager = result as IAudioSessionManager2; if (audioSessionManager != null) { return new CoreAudioSessionController(this, audioSessionManager); } } catch (Exception) { if (_sessionController?.IsValueCreated == true) { _sessionController?.Value?.Dispose(); } _sessionController = null; } return null; })); }); }
private void EnumeratorOnAudioDeviceChanged(object sender, AudioDeviceChangedEventArgs audioDeviceChangedEventArgs) { if (audioDeviceChangedEventArgs.Device.Id != Id) { return; } ComThread.Invoke(() => { LoadProperties(_device); }); switch (audioDeviceChangedEventArgs.EventType) { case AudioDeviceEventType.Volume: case AudioDeviceEventType.Level: case AudioDeviceEventType.StateChanged: case AudioDeviceEventType.PropertyChanged: OnPropertyChanged("DeviceType"); OnPropertyChanged("InterfaceName"); OnPropertyChanged("FullName"); OnPropertyChanged("IconPath"); OnPropertyChanged("Id"); OnPropertyChanged("IsCaptureDevice"); OnPropertyChanged("IsMuted"); OnPropertyChanged("IsPlaybackDevice"); OnPropertyChanged("Name"); OnPropertyChanged("State"); OnPropertyChanged("FullName"); break; case AudioDeviceEventType.DefaultDevice: OnPropertyChanged("IsDefaultDevice"); break; case AudioDeviceEventType.DefaultCommunicationsDevice: OnPropertyChanged("IsDefaultCommunicationsDevice"); break; } }
/// <summary> /// Switch the default audio device to the one given /// </summary> /// <param name="deviceId"></param> /// <param name="role"></param> public void SwitchTo(string deviceId, ERole role) { if (role != ERole.ERole_enum_count) { ComThread.Invoke((() => { if (_enumerator.IsDefault(deviceId, EDataFlow.eRender, role) || _enumerator.IsDefault(deviceId, EDataFlow.eCapture, role)) { Trace.WriteLine($"Default endpoint already {deviceId}"); return; } _policyClient.SetDefaultEndpoint(deviceId, role); })); return; } SwitchTo(deviceId, ERole.eConsole); SwitchTo(deviceId, ERole.eMultimedia); SwitchTo(deviceId, ERole.eCommunications); }
/// <summary> /// Switch the default audio device to the one given /// </summary> /// <param name="deviceId"></param> /// <param name="role"></param> public void SwitchTo(string deviceId, Role role) { if (role != Role.All) { ComThread.Invoke((() => { if (_enumerator.IsDefault(deviceId, EDataFlow.Render, role) || _enumerator.IsDefault(deviceId, EDataFlow.Capture, role)) { System.Diagnostics.Trace.WriteLine($"Default endpoint already {deviceId}"); return; } _policyClient.SetDefaultEndpoint(deviceId, role); })); return; } SwitchTo(deviceId, Role.Console); SwitchTo(deviceId, Role.Multimedia); SwitchTo(deviceId, Role.Communications); }
private void RefreshProperties() { if (_isDisposed) { return; } ComThread.Invoke(() => { _isSystemSession = AudioSessionControl.IsSystemSoundsSession() == 0; AudioSessionControl.GetDisplayName(out _displayName); AudioSessionControl.GetIconPath(out _iconPath); EAudioSessionState state; AudioSessionControl.GetState(out state); _state = state.AsAudioSessionState(); uint processId; AudioSessionControl.GetProcessId(out processId); _processId = (int)processId; AudioSessionControl.GetSessionIdentifier(out _id); try { if (ProcessId > 0) { var proc = Process.GetProcessById(ProcessId); _executablePath = proc.MainModule.FileName; _fileDescription = proc.MainModule.FileVersionInfo.FileDescription; } } catch { _fileDescription = ""; } }); }
public void LoadDevices(bool loadMeter = true, bool loadEndpoint = true, bool loadSession = true) { ComThread.Invoke(() => { _systemEvents = new SystemEventNotifcationClient(() => InnerEnumerator); _systemEvents.DeviceAdded.Subscribe(x => OnDeviceAdded(x.DeviceId)); _systemEvents.DeviceRemoved.Subscribe(x => OnDeviceRemoved(x.DeviceId)); _deviceCache = new HashSet <CoreAudioDevice>(); IMultimediaDeviceCollection collection; InnerEnumerator.EnumAudioEndpoints(EDataFlow.All, EDeviceState.All, out collection); using (var coll = new MultimediaDeviceCollection(collection)) { foreach (var mDev in coll) { CacheDevice(mDev, loadMeter, loadEndpoint, loadSession); } } }); }
private CoreAudioDevice GetOrAddDeviceFromRealId(string deviceId) { //This pre-check here may prevent more com objects from being created var device = GetDevice(deviceId); if (device != null) { return(device); } return(ComThread.Invoke(() => { IMultimediaDevice mDevice; InnerEnumerator.GetDevice(deviceId, out mDevice); if (mDevice == null) { return null; } return CacheDevice(mDevice); })); }
/// <summary> /// Reset Windows configuration for the process that had their audio device changed /// </summary> public void ResetProcessDeviceConfiguration() { ComThread.Invoke(() => ExtendPolicyClient.ResetAllSetEndpoint()); }
/// <summary> /// Get the device used by the given process /// </summary> /// <param name="flow"></param> /// <param name="role"></param> /// <param name="processId"></param> /// <returns></returns> public string GetUsedDevice(EDataFlow flow, ERole role, uint processId) { return(ComThread.Invoke(() => ExtendPolicyClient.GetDefaultEndPoint(flow, role, processId))); }
/// <summary> /// Is the given deviceId the default audio device in the system /// </summary> /// <param name="deviceId"></param> /// <param name="flow"></param> /// <param name="role"></param> /// <returns></returns> public bool IsDefault(string deviceId, EDataFlow flow, ERole role) { return(ComThread.Invoke(() => _enumerator.IsDefault(deviceId, flow, role))); }
/// <summary> /// Switch the audio device of the Foreground Process /// </summary> /// <param name="deviceId">Id of the device</param> /// <param name="role">Which role to switch</param> /// <param name="flow">Which flow to switch</param> public void SwitchProcessTo(string deviceId, ERole role, EDataFlow flow) { var processId = ComThread.Invoke(() => User32.ForegroundProcessId); SwitchProcessTo(deviceId, role, flow, processId); }
/// <summary> /// VolumeChanged Step Down /// </summary> public void VolumeStepDown() { ComThread.Invoke(() => Marshal.ThrowExceptionForHR(_audioEndPointVolume.VolumeStepDown(Guid.Empty))); }