Skip to content

Commit

Permalink
implement #105
Browse files Browse the repository at this point in the history
  • Loading branch information
radj307 committed Nov 4, 2023
1 parent f86f189 commit 721464e
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 0 deletions.
4 changes: 4 additions & 0 deletions VolumeControl.Core/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,10 @@ private void PropertyWithCollectionChangedEvents_CollectionChanged(object? sende
/// Gets or sets the list of (process names of) hidden audio sessions.
/// </summary>
public ObservableImmutableList<string> HiddenSessionProcessNames { get; set; } = new();
/// <summary>
/// Gets or sets whether selected audio sessions have synchronized volume levels &amp; mute states or not.
/// </summary>
public bool EnableSessionSync { get; set; } = false;
#endregion Audio

#region Log
Expand Down
17 changes: 17 additions & 0 deletions VolumeControl/ViewModels/AudioDeviceManagerVM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ public AudioDeviceManagerVM()
LockCurrentIndexOnLockSelection = true
};

// setup the session synchronizer
SessionSync = new(this);
SessionSync.PropertyChanged += this.SessionSync_PropertyChanged;

// populate the sessions lists
Devices.Select(d => d.AudioDevice.SessionManager).ForEach(AudioSessionManager.AddSessionManager);

Expand Down Expand Up @@ -126,6 +130,7 @@ public AudioDeviceManagerVM()
public AudioDeviceSelector AudioDeviceSelector { get; }
public AudioDeviceVM? SelectedDevice { get; set; }
public AudioSessionMultiSelector AudioSessionMultiSelector { get; }
public SessionSyncVM SessionSync { get; }
public bool? AllSessionsSelected
{
get
Expand Down Expand Up @@ -279,6 +284,18 @@ private void AudioDeviceSelector_PropertyChanged(object? sender, PropertyChanged
}
#endregion AudioDeviceSelector

#region SessionSync
private void SessionSync_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == null) return;

if (e.PropertyName.Equals(nameof(SessionSyncVM.IsEnabled), StringComparison.Ordinal))
{
Settings.EnableSessionSync = SessionSync.IsEnabled;
}
}
#endregion SessionSync

#endregion EventHandlers
}
}
121 changes: 121 additions & 0 deletions VolumeControl/ViewModels/SessionSyncVM.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
using VolumeControl.Core;
using VolumeControl.CoreAudio;

namespace VolumeControl.ViewModels
{
public class SessionSyncVM : INotifyPropertyChanged
{
#region Constructor
public SessionSyncVM(AudioDeviceManagerVM audioAPI)
{
AudioAPI = audioAPI;

AudioSessionMultiSelector.SessionSelected += this.AudioSessionMultiSelector_SessionSelected;
AudioSessionMultiSelector.SessionDeselected += this.AudioSessionMultiSelector_SessionDeselected;
Settings.PropertyChanged += this.Settings_PropertyChanged;
}
#endregion Constructor

#region Properties
private static Config Settings => Config.Default;
private AudioSessionMultiSelector AudioSessionMultiSelector => AudioAPI.AudioSessionMultiSelector;
private AudioDeviceManagerVM AudioAPI { get; }
public bool IsEnabled
{
get => _isEnabled;
set
{
_isEnabled = value;
NotifyPropertyChanged();
}
}
private bool _isEnabled;
public AudioSession? BaselineSession { get; private set; }
#endregion Properties

#region Events
public event PropertyChangedEventHandler? PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") => PropertyChanged?.Invoke(this, new(propertyName));
#endregion Events

#region Methods
/// <summary>
/// Syncs the volume levels & mute states of the specified <paramref name="sessions"/> with the <paramref name="baseline"/> session.
/// </summary>
/// <param name="baseline">The session to set the volume &amp; mute state of the <paramref name="sessions"/> to.</param>
/// <param name="sessions">Any number of audio sessions to sync the volume &amp; mute state of.</param>
public static void SyncSessions(AudioSession baseline, params AudioSession[] sessions)
{
foreach (var session in sessions)
{
session.Volume = baseline.Volume;
session.Mute = baseline.Mute;
}
}
#endregion Methods

#region EventHandlers

#region AudioSession
private void AudioSession_VolumeChanged(CoreAudio.Interfaces.IAudioControl? sender, CoreAudio.Events.VolumeChangedEventArgs e)
{
foreach (var session in AudioSessionMultiSelector.SelectedSessions)
{
if (session.Volume != sender!.Volume)
{
session.Volume = e.Volume;
}
else if (session.Mute != sender!.Mute)
{
session.Mute = e.Mute;
}
}
}
#endregion AudioSession

#region AudioSessionMultiSelector
private void AudioSessionMultiSelector_SessionSelected(object? sender, AudioSession e)
{
e.VolumeChanged += this.AudioSession_VolumeChanged;

if (!IsEnabled) return;

if (BaselineSession != null)
{
SyncSessions(BaselineSession, e);
}
else BaselineSession = e;
}
private void AudioSessionMultiSelector_SessionDeselected(object? sender, AudioSession e)
{
e.VolumeChanged -= this.AudioSession_VolumeChanged;

if (!AudioSessionMultiSelector.HasSelectedSessions)
{
BaselineSession = null;
}
else if (e.Equals(BaselineSession))
{
BaselineSession = AudioSessionMultiSelector.SelectedSessions[0];
}
}
#endregion AudioSessionMultiSelector

#region Settings
private void Settings_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == null) return;

if (e.PropertyName.Equals(nameof(Config.EnableSessionSync), System.StringComparison.Ordinal))
{
_isEnabled = Settings.EnableSessionSync;
NotifyPropertyChanged(nameof(IsEnabled));
}
}
#endregion Settings

#endregion EventHandlers
}
}
1 change: 1 addition & 0 deletions VolumeControl/ViewModels/VolumeControlVM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public VolumeControlVM() : base()
if (Settings.CheckForUpdates) Updater.CheckForUpdateNow();

this.AudioAPI = new();
AudioAPI.SessionSync.IsEnabled = true;

TargetBoxVM = new(AudioAPI.AudioSessionManager, AudioAPI.AudioSessionMultiSelector);

Expand Down

0 comments on commit 721464e

Please sign in to comment.