//Returns array of soundsourceinfos (which should be converted to json and sent as http response public static SoundSourceInfo[] PerformOperation(object operationRequest) { SoundSourceInfo[] soundSourceInfos = new SoundSourceInfo[0]; string operation = ""; //TODO: should get parameters from the request which ideally would be a dictionary switch (operation) { case "mute": case "unmute": case "setvol": case "getinfo": //TODO: implement these break; case "getallinfo": soundSourceInfos = GetCurrentSoundSourceStatus(); break; } return(soundSourceInfos); }
static void Main(string[] args) { MMDeviceEnumerator DevEnum = new MMDeviceEnumerator(); SoundSourceInfo[] oldSoundSourceInfos = new SoundSourceInfo[] { }; Dictionary <string, SoundSourceInfo> oldSoundSourceDict = new Dictionary <string, SoundSourceInfo>(); DeviceForMasterVolume = DevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia); DeviceForMasterVolume.AudioEndpointVolume.OnVolumeNotification += new AudioEndpointVolumeNotificationDelegate(AudioEndpointVolume_OnVolumeNotification); long i = 0; while (true) { if (Device != null) { IntPtr pointer = Marshal.GetIUnknownForObject(Device); Marshal.Release(pointer); } Device = DevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia); SoundSourceInfo[] latestSoundSourceInfos = GetCurrentSoundSourceStatus(); bool changeMade = false; if (oldSoundSourceInfos.Length != latestSoundSourceInfos.Length) { changeMade = true; } string latestIdentifier = ""; DateTime latestIdentifierStartDateTime = DateTime.MinValue; // expected logic: // // * intermittent sounds are always allowed to play (including bg sounds that we don't know if they are intermittent or not until they last longer than n seconds) // * mute all nonintermittent sounds except for the one that started most recently // * if a sound source plays nothing for m seconds straight then treat is as stopped. if it starts playing sound again, give it a newer start date/time for (int latestSoundSourceIndex = 0; latestSoundSourceIndex < latestSoundSourceInfos.Length; latestSoundSourceIndex++) { SoundSourceInfo prevInfo = null; SoundSourceInfo latestInfo = latestSoundSourceInfos[latestSoundSourceIndex]; if (oldSoundSourceDict.TryGetValue(latestInfo.SessionInstanceIdentifier, out prevInfo)) { if (latestInfo.IsSilentRightNow() != prevInfo.IsSilentRightNow()) { changeMade = true; } // Copy over state variables from prevInfo in smart way if (!latestInfo.IsSilentRightNow()) { latestInfo.SilentDateTime = DateTime.MaxValue; latestInfo.StartDateTime = new DateTime(Math.Min(latestInfo.StartDateTime.Ticks, prevInfo.StartDateTime.Ticks)); } else { latestInfo.SilentDateTime = prevInfo.IsSilentRightNow() ? prevInfo.SilentDateTime : DateTime.Now; latestInfo.StartDateTime = latestInfo.IsActive() ? new DateTime(Math.Min(latestInfo.StartDateTime.Ticks, prevInfo.StartDateTime.Ticks)) : DateTime.MaxValue; } //latestInfo.StartDateTime = (prevInfo.IsActive()) ? prevInfo.StartDateTime : prevInfo.StartDateTime; //TODO: is this correct here? if ((latestInfo.IsActive()) && (!latestInfo.IsIntermittent())) { DateTime maxDateTime = new DateTime(Math.Max(latestInfo.StartDateTime.Ticks, latestIdentifierStartDateTime.Ticks)); if (maxDateTime != latestIdentifierStartDateTime) { latestIdentifierStartDateTime = maxDateTime; latestIdentifier = latestInfo.SessionInstanceIdentifier; } } if (latestInfo.IsActive() != prevInfo.IsActive()) { changeMade = true; } if (latestInfo.IsIntermittent() != prevInfo.IsIntermittent()) { changeMade = true; } if (latestInfo.Pid != prevInfo.Pid) { changeMade = true; } if (latestInfo.IconPath != prevInfo.IconPath) { changeMade = true; } if (latestInfo.ChannelVolume != prevInfo.ChannelVolume) { changeMade = true; } if (latestInfo.ProcessName != prevInfo.ProcessName) { changeMade = true; } if (latestInfo.ProcessTitle != prevInfo.ProcessTitle) { changeMade = true; } if (latestInfo.Muted != prevInfo.Muted) { changeMade = true; } if (latestInfo.DisplayName != prevInfo.DisplayName) { changeMade = true; } if (latestInfo.SessionIdentifier != prevInfo.SessionIdentifier) { changeMade = true; } if (latestInfo.IsSystemIsSystemSoundsSession != prevInfo.IsSystemIsSystemSoundsSession) { changeMade = true; } } else { changeMade = true; // is new sound source } //TODO - if doing trends, find what was in old struct and is not in new struct and record that as a change; otherwise already know if changeismade } oldSoundSourceInfos = latestSoundSourceInfos; // Figure out what should be played for (int z = 0; z < latestSoundSourceInfos.Length; z++) { if (latestSoundSourceInfos[z].SessionInstanceIdentifier == latestIdentifier) { if (latestSoundSourceInfos[z].ChannelVolume == 0) { latestSoundSourceInfos[z].Session.SimpleAudioVolume.MasterVolume = 0.5f; //TODO: should load from saved volume settings (i.e. when we mute something record old volume) } } else { if ((!latestSoundSourceInfos[z].IsIntermittent()) && (latestSoundSourceInfos[z].IsActive())) { latestSoundSourceInfos[z].Session.SimpleAudioVolume.MasterVolume = 0; } } } // Initialize dictionary and clear out sessions oldSoundSourceDict = new Dictionary <string, SoundSourceInfo>(); for (int dictUpdateIndex = 0; dictUpdateIndex < oldSoundSourceInfos.Length; dictUpdateIndex++) { oldSoundSourceInfos[dictUpdateIndex].Session = null; oldSoundSourceDict[oldSoundSourceInfos[dictUpdateIndex].SessionInstanceIdentifier] = oldSoundSourceInfos[dictUpdateIndex]; } if (changeMade) { //TODO: forward on info } if (changeMade) { System.Console.WriteLine("Change made!"); } // Show what is active here. for (int soundSourceIndex = 0; soundSourceIndex < latestSoundSourceInfos.Length; soundSourceIndex++) { System.Console.WriteLine(DateTime.Now + " " + latestSoundSourceInfos[soundSourceIndex].ToString()); } System.Console.WriteLine(""); System.Threading.Thread.Sleep(500); //hopefully everything can get done in this time. maybe set to 1 s. also maybe make user configurable and allow disabling if (i % 10 == 0) { GC.Collect(); } i++; } // TODO: start up a listener that will allow performing operations in a background thread. When we receive data, call PerformOperation() // TODO: Register some events and pass along info when event occurs //Device.AudioEndpointVolume.Channels[0].VolumeLevel //RegisterAudioSessionNotification??? //TODO: mute toggled //TODO: new active session //TODO: session is no longer active ///////////////////////////////////////////////////////////////////////////////////////////// }
public static SoundSourceInfo[] GetCurrentSoundSourceStatus() { /* #region temporary * bool foundActive = false; #endregion */ List <SoundSourceInfo> soundSourceInfoList = new List <SoundSourceInfo>(); SoundSourceInfo soundSourceInfo = null; // Note the AudioSession manager did not have a method to enumerate all sessions in windows Vista // this will only work on Win7 and newer. for (int i = 0; i < Device.AudioSessionManager.Sessions.Count; i++) { AudioSessionControl session = Device.AudioSessionManager.Sessions[i]; soundSourceInfo = new SoundSourceInfo(); soundSourceInfo.Session = session; soundSourceInfo.StartDateTime = DateTime.Now; // might be overwritten in calling method /* #region temporarys * if (foundActive) * { * session.SimpleAudioVolume.MasterVolume = 0; // TODO: mute it * continue; * } #endregion */ if (session.State == AudioSessionState.AudioSessionStateActive) //TODO: include everything regardless of state? { /* #region temporary * foundActive = true; * if (session.SimpleAudioVolume.MasterVolume == 0) * session.SimpleAudioVolume.MasterVolume = 1.0f; #endregion */ soundSourceInfo.Pid = (int)session.ProcessID; soundSourceInfo.IconPath = session.IconPath; soundSourceInfo.DisplayName = session.DisplayName; soundSourceInfo.SessionIdentifier = session.SessionIdentifier; soundSourceInfo.SessionInstanceIdentifier = session.SessionInstanceIdentifier; soundSourceInfo.IsSystemIsSystemSoundsSession = session.IsSystemIsSystemSoundsSession; //soundSourceInfo.State = session.State; Process p = Process.GetProcessById((int)session.ProcessID); soundSourceInfo.ProcessName = p.ProcessName; soundSourceInfo.ProcessTitle = p.MainWindowTitle; AudioMeterInformation mi = session.AudioMeterInformation; SimpleAudioVolume vol = session.SimpleAudioVolume; soundSourceInfo.Muted = vol.Mute; soundSourceInfo.ChannelVolume = session.SimpleAudioVolume.MasterVolume; soundSourceInfo.CurrentVolume = session.AudioMeterInformation.MasterPeakValue; soundSourceInfoList.Add(soundSourceInfo); } } SoundSourceInfo[] soundSourceInfos = soundSourceInfoList.ToArray(); Array.Sort(soundSourceInfos, delegate(SoundSourceInfo info1, SoundSourceInfo info2) { return(info1.CompareTo(info2)); } ); return(soundSourceInfos); }
static void Main(string[] args) { MMDeviceEnumerator DevEnum = new MMDeviceEnumerator(); SoundSourceInfo[] oldSoundSourceInfos = new SoundSourceInfo[] { }; Dictionary<string, SoundSourceInfo> oldSoundSourceDict = new Dictionary<string, SoundSourceInfo>(); DeviceForMasterVolume = DevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia); DeviceForMasterVolume.AudioEndpointVolume.OnVolumeNotification += new AudioEndpointVolumeNotificationDelegate(AudioEndpointVolume_OnVolumeNotification); long i = 0; while (true) { if (Device != null) { IntPtr pointer = Marshal.GetIUnknownForObject(Device); Marshal.Release(pointer); } Device = DevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia); SoundSourceInfo[] latestSoundSourceInfos = GetCurrentSoundSourceStatus(); bool changeMade = false; if (oldSoundSourceInfos.Length != latestSoundSourceInfos.Length) changeMade = true; string latestIdentifier = ""; DateTime latestIdentifierStartDateTime = DateTime.MinValue; // expected logic: // // * intermittent sounds are always allowed to play (including bg sounds that we don't know if they are intermittent or not until they last longer than n seconds) // * mute all nonintermittent sounds except for the one that started most recently // * if a sound source plays nothing for m seconds straight then treat is as stopped. if it starts playing sound again, give it a newer start date/time for (int latestSoundSourceIndex = 0; latestSoundSourceIndex < latestSoundSourceInfos.Length; latestSoundSourceIndex++) { SoundSourceInfo prevInfo = null; SoundSourceInfo latestInfo = latestSoundSourceInfos[latestSoundSourceIndex]; if (oldSoundSourceDict.TryGetValue(latestInfo.SessionInstanceIdentifier, out prevInfo)) { if (latestInfo.IsSilentRightNow() != prevInfo.IsSilentRightNow()) changeMade = true; // Copy over state variables from prevInfo in smart way if (!latestInfo.IsSilentRightNow()) { latestInfo.SilentDateTime = DateTime.MaxValue; latestInfo.StartDateTime = new DateTime(Math.Min(latestInfo.StartDateTime.Ticks, prevInfo.StartDateTime.Ticks)); } else { latestInfo.SilentDateTime = prevInfo.IsSilentRightNow() ? prevInfo.SilentDateTime : DateTime.Now; latestInfo.StartDateTime = latestInfo.IsActive() ? new DateTime(Math.Min(latestInfo.StartDateTime.Ticks, prevInfo.StartDateTime.Ticks)) : DateTime.MaxValue; } //latestInfo.StartDateTime = (prevInfo.IsActive()) ? prevInfo.StartDateTime : prevInfo.StartDateTime; //TODO: is this correct here? if ((latestInfo.IsActive()) && (!latestInfo.IsIntermittent())) { DateTime maxDateTime = new DateTime(Math.Max(latestInfo.StartDateTime.Ticks, latestIdentifierStartDateTime.Ticks)); if (maxDateTime != latestIdentifierStartDateTime) { latestIdentifierStartDateTime = maxDateTime; latestIdentifier = latestInfo.SessionInstanceIdentifier; } } if (latestInfo.IsActive() != prevInfo.IsActive()) changeMade = true; if (latestInfo.IsIntermittent() != prevInfo.IsIntermittent()) changeMade = true; if (latestInfo.Pid != prevInfo.Pid) changeMade = true; if (latestInfo.IconPath != prevInfo.IconPath) changeMade = true; if (latestInfo.ChannelVolume != prevInfo.ChannelVolume) changeMade = true; if (latestInfo.ProcessName != prevInfo.ProcessName) changeMade = true; if (latestInfo.ProcessTitle != prevInfo.ProcessTitle) changeMade = true; if (latestInfo.Muted != prevInfo.Muted) changeMade = true; if (latestInfo.DisplayName != prevInfo.DisplayName) changeMade = true; if (latestInfo.SessionIdentifier != prevInfo.SessionIdentifier) changeMade = true; if (latestInfo.IsSystemIsSystemSoundsSession != prevInfo.IsSystemIsSystemSoundsSession) changeMade = true; } else { changeMade = true; // is new sound source } //TODO - if doing trends, find what was in old struct and is not in new struct and record that as a change; otherwise already know if changeismade } oldSoundSourceInfos = latestSoundSourceInfos; // Figure out what should be played for (int z = 0; z < latestSoundSourceInfos.Length; z++) { if (latestSoundSourceInfos[z].SessionInstanceIdentifier == latestIdentifier) { if (latestSoundSourceInfos[z].ChannelVolume == 0) { latestSoundSourceInfos[z].Session.SimpleAudioVolume.MasterVolume = 0.5f; //TODO: should load from saved volume settings (i.e. when we mute something record old volume) } } else { if ((!latestSoundSourceInfos[z].IsIntermittent()) && (latestSoundSourceInfos[z].IsActive())) { latestSoundSourceInfos[z].Session.SimpleAudioVolume.MasterVolume = 0; } } } // Initialize dictionary and clear out sessions oldSoundSourceDict = new Dictionary<string, SoundSourceInfo>(); for (int dictUpdateIndex = 0; dictUpdateIndex < oldSoundSourceInfos.Length; dictUpdateIndex++) { oldSoundSourceInfos[dictUpdateIndex].Session = null; oldSoundSourceDict[oldSoundSourceInfos[dictUpdateIndex].SessionInstanceIdentifier] = oldSoundSourceInfos[dictUpdateIndex]; } if (changeMade) { //TODO: forward on info } if (changeMade) System.Console.WriteLine("Change made!"); // Show what is active here. for (int soundSourceIndex = 0; soundSourceIndex < latestSoundSourceInfos.Length; soundSourceIndex++) { System.Console.WriteLine(DateTime.Now + " " + latestSoundSourceInfos[soundSourceIndex].ToString()); } System.Console.WriteLine(""); System.Threading.Thread.Sleep(500); //hopefully everything can get done in this time. maybe set to 1 s. also maybe make user configurable and allow disabling if (i % 10 == 0) GC.Collect(); i++; } // TODO: start up a listener that will allow performing operations in a background thread. When we receive data, call PerformOperation() // TODO: Register some events and pass along info when event occurs //Device.AudioEndpointVolume.Channels[0].VolumeLevel //RegisterAudioSessionNotification??? //TODO: mute toggled //TODO: new active session //TODO: session is no longer active ///////////////////////////////////////////////////////////////////////////////////////////// }
//Returns array of soundsourceinfos (which should be converted to json and sent as http response public static SoundSourceInfo[] PerformOperation(object operationRequest) { SoundSourceInfo[] soundSourceInfos = new SoundSourceInfo[0]; string operation = ""; //TODO: should get parameters from the request which ideally would be a dictionary switch (operation) { case "mute": case "unmute": case "setvol": case "getinfo": //TODO: implement these break; case "getallinfo": soundSourceInfos = GetCurrentSoundSourceStatus(); break; } return soundSourceInfos; }
public static SoundSourceInfo[] GetCurrentSoundSourceStatus() { /* #region temporary bool foundActive = false; #endregion */ List<SoundSourceInfo> soundSourceInfoList = new List<SoundSourceInfo>(); SoundSourceInfo soundSourceInfo = null; // Note the AudioSession manager did not have a method to enumerate all sessions in windows Vista // this will only work on Win7 and newer. for (int i = 0; i < Device.AudioSessionManager.Sessions.Count; i++) { AudioSessionControl session = Device.AudioSessionManager.Sessions[i]; soundSourceInfo = new SoundSourceInfo(); soundSourceInfo.Session = session; soundSourceInfo.StartDateTime = DateTime.Now; // might be overwritten in calling method /* #region temporarys if (foundActive) { session.SimpleAudioVolume.MasterVolume = 0; // TODO: mute it continue; } #endregion */ if (session.State == AudioSessionState.AudioSessionStateActive) //TODO: include everything regardless of state? { /* #region temporary foundActive = true; if (session.SimpleAudioVolume.MasterVolume == 0) session.SimpleAudioVolume.MasterVolume = 1.0f; #endregion */ soundSourceInfo.Pid = (int)session.ProcessID; soundSourceInfo.IconPath = session.IconPath; soundSourceInfo.DisplayName = session.DisplayName; soundSourceInfo.SessionIdentifier = session.SessionIdentifier; soundSourceInfo.SessionInstanceIdentifier = session.SessionInstanceIdentifier; soundSourceInfo.IsSystemIsSystemSoundsSession = session.IsSystemIsSystemSoundsSession; //soundSourceInfo.State = session.State; Process p = Process.GetProcessById((int)session.ProcessID); soundSourceInfo.ProcessName = p.ProcessName; soundSourceInfo.ProcessTitle = p.MainWindowTitle; AudioMeterInformation mi = session.AudioMeterInformation; SimpleAudioVolume vol = session.SimpleAudioVolume; soundSourceInfo.Muted = vol.Mute; soundSourceInfo.ChannelVolume = session.SimpleAudioVolume.MasterVolume; soundSourceInfo.CurrentVolume = session.AudioMeterInformation.MasterPeakValue; soundSourceInfoList.Add(soundSourceInfo); } } SoundSourceInfo[] soundSourceInfos = soundSourceInfoList.ToArray(); Array.Sort(soundSourceInfos, delegate(SoundSourceInfo info1, SoundSourceInfo info2) { return info1.CompareTo(info2); } ); return soundSourceInfos; }