예제 #1
0
        private static T GetCoreAudioObject <T>(int pid)
        {
            IMMDevice             speakers = VolumeMixer.GetOutputDevice();
            IAudioSessionManager2 mgr      = VolumeMixer.GetOutputDeviceSessionManager(speakers);

            IAudioSessionEnumerator sessionEnumerator = VolumeMixer.GetOutputDeviceSessionEnumerator(mgr);
            int count;

            sessionEnumerator.GetCount(out count);

            dynamic 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 = (T)ctl;
                    break;
                }

                Marshal.ReleaseComObject(ctl);
            }

            Marshal.ReleaseComObject(sessionEnumerator);
            Marshal.ReleaseComObject(mgr);
            Marshal.ReleaseComObject(speakers);
            return(volumeControl);
        }
예제 #2
0
        public static float?GetApplicationPeak(int pid)
        {
            IAudioMeterInformation meter = VolumeMixer.GetCoreAudioObject <IAudioMeterInformation>(pid);

            if (meter == null)
            {
                return(null);
            }

            float peak;

            meter.GetPeakValue(out peak);
            return(peak);
        }
예제 #3
0
        public static void SetApplicationMute(int pid, bool mute)
        {
            ISimpleAudioVolume volume = VolumeMixer.GetCoreAudioObject <ISimpleAudioVolume>(pid);

            if (volume == null)
            {
                return;
            }

            Guid guid = Guid.Empty;

            volume.SetMute(mute, ref guid);
            Marshal.ReleaseComObject(volume);
        }
예제 #4
0
        public static void SetApplicationVolume(int pid, float level)
        {
            ISimpleAudioVolume volume = VolumeMixer.GetCoreAudioObject <ISimpleAudioVolume>(pid);

            if (volume == null)
            {
                return;
            }

            Guid guid = Guid.Empty;

            volume.SetMasterVolume(level / 100, ref guid);
            Marshal.ReleaseComObject(volume);
        }
예제 #5
0
        public static bool?GetApplicationMute(int pid)
        {
            ISimpleAudioVolume volume = VolumeMixer.GetCoreAudioObject <ISimpleAudioVolume>(pid);

            if (volume == null)
            {
                return(null);
            }

            bool mute;

            volume.GetMute(out mute);
            Marshal.ReleaseComObject(volume);
            return(mute);
        }
예제 #6
0
        public static float?GetApplicationVolume(int pid)
        {
            ISimpleAudioVolume volume = VolumeMixer.GetCoreAudioObject <ISimpleAudioVolume>(pid);

            if (volume == null)
            {
                return(null);
            }

            float level;

            volume.GetMasterVolume(out level);
            Marshal.ReleaseComObject(volume);
            return(level * 100);
        }
예제 #7
0
        /**
         * Resets all reduced applications to the stored volume level
         */
        public void RemoveReduction()
        {
            if (!this._ReductionApplied)
            {
                return;
            }

            this._WriteIfDebugging("Restoring volume levels");
            foreach (AppVolume appVolume in this.GetStoredVolumeLevels())
            {
                if (!this._IsWhitelisted(appVolume))
                {
                    VolumeMixer.SetApplicationVolume(appVolume.ProcessID, appVolume.Volume);
                }
            }

            this._ReductionApplied = false;
        }
예제 #8
0
        /**
         * Stores the current volume level of all applications and reduces their volumes by the reduction percent
         */
        public void ApplyReduction()
        {
            this._LastReductionAttemptMicroTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();

            if (this._ReductionApplied)
            {
                this._WriteIfDebugging("Already reduced volume levels");
                return;
            }

            this._ReductionApplied = true;
            this.StoreCurrentVolumeLevels();
            this._WriteIfDebugging("Reducing volume levels");

            foreach (AppVolume appVolume in this.GetStoredVolumeLevels())
            {
                if (!this._IsWhitelisted(appVolume))
                {
                    double newVolume = appVolume.Volume - (appVolume.Volume * this._Reduction);
                    this._WriteIfDebugging("Setting " + appVolume.Name + " from " + appVolume.Volume + " to " + newVolume);

                    if (!this._Debug)
                    {
                        VolumeMixer.SetApplicationVolume(appVolume.ProcessID, (float)newVolume);
                    }
                }
            }

            //Wait for X to reset the timers
            var resetTimer = new Timer();

            resetTimer.Interval  = 100;
            resetTimer.AutoReset = true;
            resetTimer.Elapsed  += (object sender, ElapsedEventArgs e) =>
            {
                if (DateTimeOffset.Now.ToUnixTimeMilliseconds() - this._LastReductionAttemptMicroTime >= 1000 * this._RestoreVolumeAfter)
                {
                    this.RemoveReduction();
                    resetTimer.Stop();
                    resetTimer.Dispose();
                }
            };
            resetTimer.Start();
        }
예제 #9
0
        /**
         * Gets the volume levels for all current processes
         */
        public static List <AppVolume> GetAppVolumes()
        {
            List <AppVolume> appVolumes = new List <AppVolume>();

            foreach (Process process in Process.GetProcesses())
            {
                float?processVolume = VolumeMixer.GetApplicationVolume(process.Id);

                if (processVolume != null)
                {
                    appVolumes.Add(new AppVolume
                    {
                        ProcessID = process.Id,
                        Path      = PathFinder.GetProcessFilename(process),
                        Name      = process.ProcessName,
                        Volume    = (float)processVolume
                    });
                }
            }

            return(appVolumes);
        }
예제 #10
0
        /**
         * Listens for audio coming out of known voip applications
         */
        public void ListenForIncomingVOIP()
        {
            int msSincePidCheck = AudioReducer._PIDRecheckInterval;
            int msSinceCheck    = 0;

            List <float>             valuesSinceCheck = new List <float>();
            Dictionary <int, string> voipPids         = new Dictionary <int, string>();

            Timer voipChecker = new Timer();

            voipChecker.AutoReset = true;
            voipChecker.Interval  = AudioReducer._VolumeRecheckInterval;
            voipChecker.Elapsed  += (sender, e) =>
            {
                msSinceCheck    += (int)voipChecker.Interval;
                msSincePidCheck += (int)voipChecker.Interval;

                //Re-check voip apps for new/removed processes
                if (msSincePidCheck > AudioReducer._PIDRecheckInterval)
                {
                    msSincePidCheck = 0;
                    Process[] currentProcesses = Process.GetProcesses();

                    //Remove pids which are no longer valid
                    foreach (KeyValuePair <int, string> voipPid in voipPids.ToList())
                    {
                        if (!currentProcesses.Any(process => process.Id == voipPid.Key))
                        {
                            voipPids.Remove(voipPid.Key);
                            this._WriteIfDebugging("Voip app " + voipPid.Value + " (" + voipPid.Key + ") process lost");
                        }
                    }

                    //Load the pid by scanning the process list
                    foreach (String voipAppPath in this._VoipApps)
                    {
                        foreach (Process process in currentProcesses)
                        {
                            if (!voipPids.ContainsKey(process.Id))
                            {
                                String processPath = PathFinder.GetProcessFilename(process);

                                if (this._DoesPathWildcardMatch(processPath, voipAppPath))
                                {
                                    voipPids[process.Id] = voipAppPath;
                                    this._WriteIfDebugging("Voip app " + voipAppPath + " found as process " + process.Id);
                                }
                            }
                        }
                    }
                }

                //Update average value lists
                foreach (KeyValuePair <int, string> voipPid in voipPids)
                {
                    float?currentVolume = VolumeMixer.GetApplicationPeak(voipPid.Key);
                    if (currentVolume.HasValue)
                    {
                        valuesSinceCheck.Add(currentVolume.Value);
                    }
                }

                //If we've reached our check threshold check what the values have been
                if (msSinceCheck >= this._MinimumNoiseLength * 1000)
                {
                    double average = 0;
                    if (valuesSinceCheck.Count() > 0)
                    {
                        average = valuesSinceCheck.Average();
                    }

                    if (average > this._MinimumAppVolume)
                    {
                        this._WriteIfDebugging("Heard apps at qualifying average volume: " + average);
                        this.ApplyReductionIfNoisy();
                    }

                    valuesSinceCheck.Clear();
                    msSinceCheck = 0;
                }
            };
            voipChecker.Start();
        }