private static ISimpleAudioVolume GetVolumeObject(int pid) { // get the speakers (1st render + multimedia) device IMmDeviceEnumerator deviceEnumerator = (IMmDeviceEnumerator)(new MMDeviceEnumerator()); IMmDevice speakers; deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.ERender, ERole.EMultimedia, out speakers); string defaultDeviceId; speakers.GetId(out defaultDeviceId); ISimpleAudioVolume volumeControl = GetVolumeObject(pid, speakers); Marshal.ReleaseComObject(speakers); if (volumeControl == null) { // If volumeControl is null, then the process's volume object might be on a different device. // This happens if the process doesn't use the default device. // // As far as Spotify is concerned, if using the "--enable-audio-graph" command line argument, // a new option becomes available in the Settings that makes it possible to change the playback device. IMmDeviceCollection deviceCollection; deviceEnumerator.EnumAudioEndpoints(EDataFlow.ERender, EDeviceState.Active, out deviceCollection); int count; deviceCollection.GetCount(out count); for (int i = 0; i < count; i++) { IMmDevice device; deviceCollection.Item(i, out device); string deviceId; device.GetId(out deviceId); try { if (deviceId == defaultDeviceId) { continue; } volumeControl = GetVolumeObject(pid, device); if (volumeControl != null) { break; } } finally { Marshal.ReleaseComObject(device); } } } Marshal.ReleaseComObject(deviceEnumerator); return(volumeControl); }
private static ISimpleAudioVolume GetVolumeObject(int pid) { // get the speakers (1st render + multimedia) device IMmDeviceEnumerator deviceEnumerator = (IMmDeviceEnumerator)(new MMDeviceEnumerator()); IMmDevice speakers; deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.ERender, ERole.EMultimedia, out speakers); // activate the session manager. we need the enumerator Guid iidIAudioSessionManager2 = typeof(IAudioSessionManager2).GUID; object o; speakers.Activate(ref iidIAudioSessionManager2, 0, IntPtr.Zero, out o); IAudioSessionManager2 mgr = (IAudioSessionManager2)o; // enumerate sessions for on this device IAudioSessionEnumerator sessionEnumerator; mgr.GetSessionEnumerator(out sessionEnumerator); int count; sessionEnumerator.GetCount(out count); // search for an audio session with the required name // NOTE: we could also use the process id instead of the app name (with IAudioSessionControl2) ISimpleAudioVolume volumeControl = null; for (int i = 0; i < count; i++) { IAudioSessionControl2 ctl; sessionEnumerator.GetSession(i, out ctl); int cpid; ctl.GetProcessId(out cpid); if (cpid == pid) { volumeControl = (ISimpleAudioVolume)ctl; break; } Marshal.ReleaseComObject(ctl); } Marshal.ReleaseComObject(sessionEnumerator); Marshal.ReleaseComObject(mgr); Marshal.ReleaseComObject(speakers); Marshal.ReleaseComObject(deviceEnumerator); return(volumeControl); }