diff --git a/VolumeControl.Core/Config.cs b/VolumeControl.Core/Config.cs
index 013cf5f76..02581fa95 100644
--- a/VolumeControl.Core/Config.cs
+++ b/VolumeControl.Core/Config.cs
@@ -291,6 +291,10 @@ private void PropertyWithCollectionChangedEvents_CollectionChanged(object? sende
///
public TargetInfo TargetSession { get; set; } = TargetInfo.Empty;
///
+ /// Gets or sets the list of selected sessions.
+ ///
+ public ObservableImmutableList SelectedSessions { get; set; } = new();
+ ///
/// Gets or sets whether the target session is locked.
///
public bool LockTargetSession { get; set; } = false;
diff --git a/VolumeControl.Core/HotkeyManager.cs b/VolumeControl.Core/HotkeyManager.cs
index 6fc4d783c..e7a4d3a06 100644
--- a/VolumeControl.Core/HotkeyManager.cs
+++ b/VolumeControl.Core/HotkeyManager.cs
@@ -262,7 +262,7 @@ private void RecheckAllSelected()
{
bool prev = this.Hotkeys.First().Registered;
bool fullLoop = true;
- for (int i = 1; i < this.Hotkeys.Count; ++i)
+ for (int i = 1, max = this.Hotkeys.Count; i < max; ++i)
{
if (this.Hotkeys[i].Registered != prev)
{
diff --git a/VolumeControl.CoreAudio/AudioSessionManager.cs b/VolumeControl.CoreAudio/AudioSessionManager.cs
index eeba2a54a..edb27438a 100644
--- a/VolumeControl.CoreAudio/AudioSessionManager.cs
+++ b/VolumeControl.CoreAudio/AudioSessionManager.cs
@@ -172,14 +172,14 @@ private PreviewSessionIsHiddenEventArgs NotifyPreviewSessionIsHidden(AudioSessio
/// The with the given if found; otherwise .
public AudioSession? FindSessionWithPID(uint processId, bool includeHiddenSessions = false)
{ // don't use FindSession here, this way is more than 2x faster:
- for (int i = 0; i < Sessions.Count; ++i)
+ for (int i = 0, max = Sessions.Count; i < max; ++i)
{
AudioSession session = Sessions[i];
if (session.PID == processId) return session;
}
if (includeHiddenSessions)
{
- for (int i = 0; i < HiddenSessions.Count; ++i)
+ for (int i = 0, max = HiddenSessions.Count; i < max; ++i)
{
AudioSession session = HiddenSessions[i];
if (session.PID == processId) return session;
@@ -205,14 +205,14 @@ private PreviewSessionIsHiddenEventArgs NotifyPreviewSessionIsHidden(AudioSessio
{
if (processName.Length == 0) return null;
- for (int i = 0; i < Sessions.Count; ++i)
+ for (int i = 0, max = Sessions.Count; i < max; ++i)
{
AudioSession session = Sessions[i];
if (session.ProcessName.Equals(processName, stringComparison)) return session;
}
if (includeHiddenSessions)
{
- for (int i = 0; i < HiddenSessions.Count; ++i)
+ for (int i = 0, max = HiddenSessions.Count; i < max; ++i)
{
AudioSession session = HiddenSessions[i];
if (session.ProcessName.Equals(processName, stringComparison)) return session;
@@ -234,7 +234,7 @@ private PreviewSessionIsHiddenEventArgs NotifyPreviewSessionIsHidden(AudioSessio
{
if (sessionName.Length == 0) return null;
- for (int i = 0; i < Sessions.Count; ++i)
+ for (int i = 0, max = Sessions.Count; i < max; ++i)
{
AudioSession session = Sessions[i];
if (session.HasMatchingName(sessionName, stringComparison))
@@ -242,7 +242,7 @@ private PreviewSessionIsHiddenEventArgs NotifyPreviewSessionIsHidden(AudioSessio
}
if (includeHiddenSessions)
{
- for (int i = 0; i < HiddenSessions.Count; ++i)
+ for (int i = 0, max = HiddenSessions.Count; i < max; ++i)
{
AudioSession session = HiddenSessions[i];
if (session.HasMatchingName(sessionName, stringComparison))
@@ -265,14 +265,14 @@ private PreviewSessionIsHiddenEventArgs NotifyPreviewSessionIsHidden(AudioSessio
{
if (processIdentifier.Length == 0) return null;
- for (int i = 0; i < Sessions.Count; ++i)
+ for (int i = 0, max = Sessions.Count; i < max; ++i)
{
AudioSession session = Sessions[i];
if (session.ProcessIdentifier.Equals(processIdentifier, stringComparison)) return session;
}
if (includeHiddenSessions)
{
- for (int i = 0; i < HiddenSessions.Count; ++i)
+ for (int i = 0, max = HiddenSessions.Count; i < max; ++i)
{
AudioSession session = HiddenSessions[i];
if (session.ProcessIdentifier.Equals(processIdentifier, stringComparison)) return session;
@@ -343,14 +343,14 @@ private PreviewSessionIsHiddenEventArgs NotifyPreviewSessionIsHidden(AudioSessio
{
if (sessionIdentifier.Length == 0) return null;
- for (int i = 0; i < Sessions.Count; ++i)
+ for (int i = 0, max = Sessions.Count; i < max; ++i)
{
AudioSession session = Sessions[i];
if (session.SessionIdentifier.Equals(sessionIdentifier, stringComparison)) return session;
}
if (includeHiddenSessions)
{
- for (int i = 0; i < HiddenSessions.Count; ++i)
+ for (int i = 0, max = HiddenSessions.Count; i < max; ++i)
{
AudioSession session = HiddenSessions[i];
if (session.SessionIdentifier.Equals(sessionIdentifier, stringComparison)) return session;
@@ -372,14 +372,14 @@ private PreviewSessionIsHiddenEventArgs NotifyPreviewSessionIsHidden(AudioSessio
{
if (sessionInstanceIdentifier.Length == 0) return null;
- for (int i = 0; i < Sessions.Count; ++i)
+ for (int i = 0, max = Sessions.Count; i < max; ++i)
{
AudioSession session = Sessions[i];
if (session.SessionInstanceIdentifier.Equals(sessionInstanceIdentifier, stringComparison)) return session;
}
if (includeHiddenSessions)
{
- for (int i = 0; i < HiddenSessions.Count; ++i)
+ for (int i = 0, max = HiddenSessions.Count; i < max; ++i)
{
AudioSession session = HiddenSessions[i];
if (session.SessionInstanceIdentifier.Equals(sessionInstanceIdentifier, stringComparison)) return session;
diff --git a/VolumeControl.CoreAudio/AudioSessionMultiSelector.cs b/VolumeControl.CoreAudio/AudioSessionMultiSelector.cs
index 7c997eed3..363d19d68 100644
--- a/VolumeControl.CoreAudio/AudioSessionMultiSelector.cs
+++ b/VolumeControl.CoreAudio/AudioSessionMultiSelector.cs
@@ -21,11 +21,10 @@ public AudioSessionMultiSelector(AudioSessionManager audioSessionManager)
AudioSessionManager = audioSessionManager;
CurrentIndex = -1;
+ _selectedSessions = new();
_selectionStates = new();
- foreach (var session in Sessions) // populate the selection states list
- {
- _selectionStates.Add(NotifyPreviewSessionIsSelected(session, defaultIsSelected: false).IsSelected);
- }
+ // populate the lists:
+ Sessions.ForEach(AddSession);
AudioSessionManager.AddedSessionToList += this.AudioSessionManager_SessionAddedToList;
AudioSessionManager.RemovingSessionFromList += this.AudioSessionManager_RemovingSessionFromList; ;
@@ -46,12 +45,12 @@ public IReadOnlyList SelectionStates
if (LockSelection) return;
- var previouslySelectedItems = SelectedItems;
+ var previouslySelectedItems = SelectedSessions;
- _selectionStates = (List)value;
+ _selectionStates = value.ToList();
NotifyPropertyChanged();
- var selectedItems = SelectedItems;
+ var selectedItems = SelectedSessions;
// trigger selection changed notifications
for (int i = 0, max = SelectionStates.Count; i < max; ++i)
@@ -60,9 +59,13 @@ public IReadOnlyList SelectionStates
var wasSelectedBefore = previouslySelectedItems.Contains(session);
var isSelectedNow = selectedItems.Contains(session);
if (wasSelectedBefore && !isSelectedNow)
+ {
+ AddSelectedSession(session);
NotifySessionDeselected(session);
+ }
else if (!wasSelectedBefore && isSelectedNow)
{
+ RemoveSelectedSession(session);
NotifySessionSelected(session);
}
}
@@ -73,27 +76,38 @@ public IReadOnlyList SelectionStates
/// Gets or sets the list of selected AudioSession instances.
///
/// An array of all selected AudioSessions in the order that they appear in the Sessions list.
- public AudioSession[] SelectedItems
+ public IReadOnlyList SelectedSessions
{
- get
- {
- List l = new();
- for (int i = 0; i < SelectionStates.Count; ++i)
- {
- if (SelectionStates[i])
- l.Add(Sessions[i]);
- }
- return l.ToArray();
- }
+ get => _selectedSessions;
set
{
- for (int i = 0; i < SelectionStates.Count; ++i)
+ for (int i = 0, max = SelectionStates.Count; i < max; ++i)
{
- _selectionStates[i] = value.Contains(Sessions[i]);
+ var session = Sessions[i];
+ var newState = value.Contains(session);
+
+ if (_selectionStates[i] == newState) continue; //< no changes to make
+
+ if (_selectionStates[i] = newState)
+ {
+ AddSelectedSession(session);
+ NotifySessionSelected(session);
+ }
+ else
+ {
+ RemoveSelectedSession(session);
+ NotifySessionDeselected(session);
+ }
}
NotifyPropertyChanged();
}
}
+ private readonly List _selectedSessions;
+ ///
+ /// Gets whether there are any selected sessions or not.
+ ///
+ /// when there is at least one selected session; otherwise .
+ public bool HasSelectedSessions => SelectedSessions.Count > 0;
///
public int CurrentIndex
{
@@ -104,7 +118,7 @@ public int CurrentIndex
_currentIndex = value;
NotifyPropertyChanged();
- NotifyPropertyChanged(nameof(CurrentItem));
+ NotifyPropertyChanged(nameof(CurrentSession));
if (_currentIndex != -1)
NotifyCurrentItemChanged(Sessions[_currentIndex]);
}
@@ -122,9 +136,9 @@ public bool LockCurrentIndex
}
private bool _lockCurrentIndex;
///
- /// Gets or sets the item that the selector is currently at.
+ /// Gets or sets the session that the selector is currently pointing at.
///
- public AudioSession? CurrentItem
+ public AudioSession? CurrentSession
{
get => CurrentIndex == -1 ? null : Sessions[CurrentIndex];
set
@@ -153,9 +167,24 @@ public bool LockSelection
{
_lockSelection = value;
NotifyPropertyChanged();
+ if (LockCurrentIndexOnLockSelection)
+ LockCurrentIndex = value;
}
}
private bool _lockSelection;
+ ///
+ /// Gets or sets whether the LockCurrentIndex property is also set when LockSelection is changed.
+ ///
+ public bool LockCurrentIndexOnLockSelection
+ {
+ get => _lockCurrentIndexOnLockSelection;
+ set
+ {
+ _lockCurrentIndexOnLockSelection = value;
+ NotifyPropertyChanged();
+ }
+ }
+ private bool _lockCurrentIndexOnLockSelection;
#endregion Properties
#region Events
@@ -191,6 +220,45 @@ private PreviewSessionIsSelectedEventArgs NotifyPreviewSessionIsSelected(AudioSe
#region Methods
+ private void AddSelectedSession(AudioSession audioSession)
+ {
+ var hadSelectedSessions = HasSelectedSessions;
+ _selectedSessions.Add(audioSession);
+ if (!hadSelectedSessions)
+ NotifyPropertyChanged(nameof(HasSelectedSessions));
+ }
+ private void RemoveSelectedSession(AudioSession audioSession)
+ {
+ if (_selectedSessions.Remove(audioSession) && _selectedSessions.Count == 0)
+ {
+ NotifyPropertyChanged(nameof(HasSelectedSessions));
+ }
+ }
+
+ #region Add/Remove Session
+ private void AddSession(AudioSession session)
+ {
+ var isSelected = NotifyPreviewSessionIsSelected(session, defaultIsSelected: false).IsSelected;
+ _selectionStates.Insert(Sessions.IndexOf(session), isSelected);
+ if (isSelected)
+ {
+ AddSelectedSession(session);
+ NotifySessionSelected(session);
+ }
+ }
+ private void RemoveSession(AudioSession session)
+ {
+ var index = Sessions.IndexOf(session); //< we can get the index here because the session hasn't been removed yet
+ var wasSelected = _selectionStates[index];
+ _selectionStates.RemoveAt(index);
+ if (wasSelected)
+ {
+ RemoveSelectedSession(session);
+ NotifySessionDeselected(session);
+ }
+ }
+ #endregion Add/Remove Session
+
#region Get/Set SessionIsSelected
///
/// Gets whether the specified is selected or not.
@@ -221,9 +289,13 @@ public void SetSessionIsSelected(AudioSession audioSession, bool isSelected)
if (_selectionStates[index] == isSelected) return; //< don't do anything if nothing is changing
if (_selectionStates[index] = isSelected)
+ {
+ AddSelectedSession(audioSession);
NotifySessionSelected(audioSession);
+ }
else
{
+ RemoveSelectedSession(audioSession);
NotifySessionDeselected(audioSession);
}
}
@@ -240,11 +312,16 @@ public void SetSessionIsSelected(int index, bool isSelected)
if (_selectionStates[index] == isSelected) return; //< don't do anything if nothing is changing
+ var session = Sessions[index];
if (_selectionStates[index] = isSelected)
- NotifySessionSelected(Sessions[index]);
+ {
+ AddSelectedSession(session);
+ NotifySessionSelected(session);
+ }
else
{
- NotifySessionDeselected(Sessions[index]);
+ RemoveSelectedSession(session);
+ NotifySessionDeselected(session);
}
}
#endregion Get/Set SessionIsSelected
@@ -275,7 +352,8 @@ public void SelectCurrentItem()
if (LockSelection || CurrentIndex == -1) return;
_selectionStates[CurrentIndex] = true;
- NotifySessionSelected(CurrentItem!);
+ AddSelectedSession(CurrentSession!);
+ NotifySessionSelected(CurrentSession!);
}
///
/// Deselects the CurrentItem.
@@ -288,7 +366,8 @@ public void DeselectCurrentItem()
if (LockSelection || CurrentIndex == -1) return;
_selectionStates[CurrentIndex] = false;
- NotifySessionDeselected(CurrentItem!);
+ RemoveSelectedSession(CurrentSession!);
+ NotifySessionDeselected(CurrentSession!);
}
///
/// Toggles whether the CurrentItem is selected.
@@ -301,10 +380,14 @@ public void ToggleSelectCurrentItem()
if (LockSelection || CurrentIndex == -1) return;
if (_selectionStates[CurrentIndex] = !SelectionStates[CurrentIndex])
- NotifySessionSelected(CurrentItem!);
+ {
+ AddSelectedSession(CurrentSession!);
+ NotifySessionSelected(CurrentSession!);
+ }
else
{
- NotifySessionDeselected(CurrentItem!);
+ RemoveSelectedSession(CurrentSession!);
+ NotifySessionDeselected(CurrentSession!);
}
}
#endregion Select/Deselect/ToggleSelect CurrentItem
@@ -320,7 +403,7 @@ public void IncrementCurrentIndex()
{
if (LockCurrentIndex) return;
- if (CurrentIndex + 1 < SelectionStates.Count)
+ if (CurrentIndex < SelectionStates.Count - 1)
++CurrentIndex;
else
{ // loopback:
@@ -341,7 +424,7 @@ public void DecrementCurrentIndex()
--CurrentIndex;
else
{ // loopback:
- CurrentIndex = SelectionStates.Count;
+ CurrentIndex = SelectionStates.Count - 1;
}
}
///
@@ -364,20 +447,9 @@ public void UnsetCurrentIndex()
#region AudioSessionManager
private void AudioSessionManager_SessionAddedToList(object? sender, AudioSession e)
- {
- var isSelected = NotifyPreviewSessionIsSelected(e, defaultIsSelected: false).IsSelected;
- _selectionStates.Insert(Sessions.IndexOf(e), isSelected);
- if (isSelected)
- NotifySessionSelected(e);
- }
+ => AddSession(e);
private void AudioSessionManager_RemovingSessionFromList(object? sender, AudioSession e)
- {
- var index = Sessions.IndexOf(e); //< we can get the index here because the session hasn't been removed yet
- var wasSelected = _selectionStates[index];
- _selectionStates.RemoveAt(index);
- if (wasSelected)
- NotifySessionDeselected(e);
- }
+ => RemoveSession(e);
#endregion AudioSessionManager
#endregion EventHandlers
diff --git a/VolumeControl.CoreAudio/Events/PreviewSessionIsSelectedEventArgs.cs b/VolumeControl.CoreAudio/Events/PreviewSessionIsSelectedEventArgs.cs
index 86dd329ee..ea12f2912 100644
--- a/VolumeControl.CoreAudio/Events/PreviewSessionIsSelectedEventArgs.cs
+++ b/VolumeControl.CoreAudio/Events/PreviewSessionIsSelectedEventArgs.cs
@@ -1,6 +1,4 @@
-using VolumeControl.CoreAudio;
-
-namespace VolumeControl.CoreAudio.Events
+namespace VolumeControl.CoreAudio.Events
{
///
/// Event arguments object for the event type.
diff --git a/VolumeControl.HotkeyActions/AudioSessionActions.cs b/VolumeControl.HotkeyActions/AudioSessionActions.cs
index 0e6ae5915..a58c438d9 100644
--- a/VolumeControl.HotkeyActions/AudioSessionActions.cs
+++ b/VolumeControl.HotkeyActions/AudioSessionActions.cs
@@ -20,8 +20,9 @@ public sealed class AudioSessionActions
#region Properties
private static VCAPI VCAPI => VCAPI.Default;
- private static AudioSessionSelector AudioSessionSelector => VCAPI.AudioSessionSelector;
- private static AudioSession? SelectedSession => AudioSessionSelector.Selected;
+ private static AudioSessionMultiSelector MultiSelector => VCAPI.AudioSessionMultiSelector;
+ private static IReadOnlyList SelectedSessions => MultiSelector.SelectedSessions;
+ private static AudioSession? CurrentSession => MultiSelector.CurrentSession;
#endregion Properties
#region Action Methods
@@ -29,156 +30,228 @@ public sealed class AudioSessionActions
[HotkeyActionSetting(ActionTargetSpecifierName, typeof(ActionTargetSpecifier), ActionTargetSpecifierDescription)]
public void VolumeUp(object? sender, HotkeyActionPressedEventArgs e)
{
- bool forceShowNotification = false;
+ bool showNotification = false;
if (e.GetActionSettingValue(ActionTargetSpecifierName) is ActionTargetSpecifier specifier && specifier.Targets.Count > 0)
- {
- for (int i = 0; i < specifier.Targets.Count; ++i)
+ { // operate on target overrides:
+ for (int i = 0, max = specifier.Targets.Count; i < max; ++i)
{
if (VCAPI.AudioSessionManager.FindSessionWithName(specifier.Targets[i].Value) is AudioSession session)
{
session.IncreaseVolume(VCAPI.Settings.VolumeStepSize);
- forceShowNotification = true;
+ showNotification = true;
}
}
}
- else SelectedSession?.IncreaseVolume(VCAPI.Settings.VolumeStepSize);
+ else if (SelectedSessions.Count > 0)
+ { // operate on selected sessions:
+ for (int i = 0, max = SelectedSessions.Count; i < max; ++i)
+ {
+ SelectedSessions[i].IncreaseVolume(VCAPI.Settings.VolumeStepSize);
+ showNotification = true;
+ }
+ }
+ else if (CurrentSession != null)
+ { // operate on current item:
+ CurrentSession.IncreaseVolume(VCAPI.Settings.VolumeStepSize);
+ showNotification = true;
+ }
- if (!VCAPI.Settings.SessionListNotificationConfig.ShowOnVolumeChanged) return; //< don't show notifs if they're disabled on volume change
+ if (!VCAPI.Settings.SessionListNotificationConfig.ShowOnVolumeChanged)
+ return; //< don't show notifs if they're disabled on volume change
- if (forceShowNotification || VCAPI.AudioSessionSelector.Selected is not null)
+ if (showNotification)
VCAPI.ShowSessionListNotification();
}
[HotkeyAction(Description = "Decreases the volume of the selected session by the value of VolumeStep.")]
[HotkeyActionSetting(ActionTargetSpecifierName, typeof(ActionTargetSpecifier), ActionTargetSpecifierDescription)]
public void VolumeDown(object? sender, HotkeyActionPressedEventArgs e)
{
- bool forceShowNotification = false;
+ bool showNotification = false;
if (e.GetActionSettingValue(ActionTargetSpecifierName) is ActionTargetSpecifier specifier && specifier.Targets.Count > 0)
- {
- for (int i = 0; i < specifier.Targets.Count; ++i)
+ { // operate on target overrides:
+ for (int i = 0, max = specifier.Targets.Count; i < max; ++i)
{
if (VCAPI.AudioSessionManager.FindSessionWithName(specifier.Targets[i].Value) is AudioSession session)
{
session.DecreaseVolume(VCAPI.Settings.VolumeStepSize);
- forceShowNotification = true;
+ showNotification = true;
}
}
}
- else SelectedSession?.DecreaseVolume(VCAPI.Settings.VolumeStepSize);
+ else if (SelectedSessions.Count > 0)
+ { // operate on selected sessions:
+ for (int i = 0, max = SelectedSessions.Count; i < max; ++i)
+ {
+ SelectedSessions[i].DecreaseVolume(VCAPI.Settings.VolumeStepSize);
+ showNotification = true;
+ }
+ }
+ else if (CurrentSession != null)
+ { // operate on current item:
+ CurrentSession.DecreaseVolume(VCAPI.Settings.VolumeStepSize);
+ showNotification = true;
+ }
- if (!VCAPI.Settings.SessionListNotificationConfig.ShowOnVolumeChanged) return; //< don't show notifs if they're disabled on volume change
+ if (!VCAPI.Settings.SessionListNotificationConfig.ShowOnVolumeChanged)
+ return; //< don't show notifs if they're disabled on volume change
- if (forceShowNotification || VCAPI.AudioSessionSelector.Selected is not null)
+ if (showNotification)
VCAPI.ShowSessionListNotification();
}
[HotkeyAction(Description = "Mutes the selected session.")]
[HotkeyActionSetting(ActionTargetSpecifierName, typeof(ActionTargetSpecifier), ActionTargetSpecifierDescription)]
public void Mute(object? sender, HotkeyActionPressedEventArgs e)
{
- bool forceShowNotification = false;
+ bool showNotification = false;
if (e.GetActionSettingValue(ActionTargetSpecifierName) is ActionTargetSpecifier specifier && specifier.Targets.Count > 0)
- {
- for (int i = 0; i < specifier.Targets.Count; ++i)
+ { // operate on target overrides:
+ for (int i = 0, max = specifier.Targets.Count; i < max; ++i)
{
if (VCAPI.AudioSessionManager.FindSessionWithName(specifier.Targets[i].Value) is AudioSession session)
{
session.SetMute(true);
- forceShowNotification = true;
+ showNotification = true;
}
}
}
- else SelectedSession?.SetMute(true);
+ else if (SelectedSessions.Count > 0)
+ { // operate on selected sessions:
+ for (int i = 0, max = SelectedSessions.Count; i < max; ++i)
+ {
+ SelectedSessions[i].SetMute(true);
+ showNotification = true;
+ }
+ }
+ else if (CurrentSession != null)
+ { // operate on current item:
+ CurrentSession.SetMute(true);
+ showNotification = true;
+ }
- if (!VCAPI.Settings.SessionListNotificationConfig.ShowOnVolumeChanged) return; //< don't show notifs if they're disabled on volume change
+ if (!VCAPI.Settings.SessionListNotificationConfig.ShowOnVolumeChanged)
+ return; //< don't show notifs if they're disabled on volume change
- if (forceShowNotification || VCAPI.AudioSessionSelector.Selected is not null)
+ if (showNotification)
VCAPI.ShowSessionListNotification();
}
[HotkeyAction(Description = "Unmutes the selected session.")]
[HotkeyActionSetting(ActionTargetSpecifierName, typeof(ActionTargetSpecifier), ActionTargetSpecifierDescription)]
public void Unmute(object? sender, HotkeyActionPressedEventArgs e)
{
- bool forceShowNotification = false;
+ bool showNotification = false;
if (e.GetActionSettingValue(ActionTargetSpecifierName) is ActionTargetSpecifier specifier && specifier.Targets.Count > 0)
- {
- for (int i = 0; i < specifier.Targets.Count; ++i)
+ { // operate on target overrides:
+ for (int i = 0, max = specifier.Targets.Count; i < max; ++i)
{
if (VCAPI.AudioSessionManager.FindSessionWithName(specifier.Targets[i].Value) is AudioSession session)
{
session.SetMute(false);
- forceShowNotification = true;
+ showNotification = true;
}
}
}
- else SelectedSession?.SetMute(false);
+ else if (SelectedSessions.Count > 0)
+ { // operate on selected sessions:
+ for (int i = 0, max = SelectedSessions.Count; i < max; ++i)
+ {
+ SelectedSessions[i].SetMute(false);
+ showNotification = true;
+ }
+ }
+ else if (CurrentSession != null)
+ { // operate on current item:
+ CurrentSession.SetMute(false);
+ showNotification = true;
+ }
- if (!VCAPI.Settings.SessionListNotificationConfig.ShowOnVolumeChanged) return; //< don't show notifs if they're disabled on volume change
+ if (!VCAPI.Settings.SessionListNotificationConfig.ShowOnVolumeChanged)
+ return; //< don't show notifs if they're disabled on volume change
- if (forceShowNotification || VCAPI.AudioSessionSelector.Selected is not null)
+ if (showNotification)
VCAPI.ShowSessionListNotification();
}
[HotkeyAction(Description = "Toggles the selected session's mute state.")]
[HotkeyActionSetting(ActionTargetSpecifierName, typeof(ActionTargetSpecifier), ActionTargetSpecifierDescription)]
public void ToggleMute(object? sender, HotkeyActionPressedEventArgs e)
{
- bool forceShowNotification = false;
+ bool showNotification = false;
if (e.GetActionSettingValue(ActionTargetSpecifierName) is ActionTargetSpecifier specifier && specifier.Targets.Count > 0)
- {
- for (int i = 0; i < specifier.Targets.Count; ++i)
+ { // operate on target overrides:
+ for (int i = 0, max = specifier.Targets.Count; i < max; ++i)
{
if (VCAPI.AudioSessionManager.FindSessionWithName(specifier.Targets[i].Value) is AudioSession session)
{
session.ToggleMute();
- forceShowNotification = true;
+ showNotification = true;
}
}
}
- else SelectedSession?.ToggleMute();
+ else if (SelectedSessions.Count > 0)
+ { // operate on selected sessions:
+ for (int i = 0, max = SelectedSessions.Count; i < max; ++i)
+ {
+ SelectedSessions[i].ToggleMute();
+ showNotification = true;
+ }
+ }
+ else if (CurrentSession != null)
+ { // operate on current item:
+ CurrentSession.ToggleMute();
+ showNotification = true;
+ }
- if (!VCAPI.Settings.SessionListNotificationConfig.ShowOnVolumeChanged) return; //< don't show notifs if they're disabled on volume change
+ if (!VCAPI.Settings.SessionListNotificationConfig.ShowOnVolumeChanged)
+ return; //< don't show notifs if they're disabled on volume change
- if (forceShowNotification || VCAPI.AudioSessionSelector.Selected is not null)
+ if (showNotification)
VCAPI.ShowSessionListNotification();
}
- [HotkeyAction(Description = "Selects the next session in the list.")]
+ [HotkeyAction(Description = "Moves the selector to the next session in the list.")]
public void SelectNext(object? sender, HotkeyActionPressedEventArgs e)
{
- AudioSessionSelector.SelectNextSession();
+ MultiSelector.IncrementCurrentIndex();
VCAPI.ShowSessionListNotification();
}
- [HotkeyAction(Description = "Selects the previous session in the list.")]
+ [HotkeyAction(Description = "Moves the selector to the previous session in the list.")]
public void SelectPrevious(object? sender, HotkeyActionPressedEventArgs e)
{
- AudioSessionSelector.SelectPreviousSession();
+ MultiSelector.DecrementCurrentIndex();
VCAPI.ShowSessionListNotification();
}
[HotkeyAction(Description = "Locks the selected session, preventing it from being changed.")]
public void Lock(object? sender, HotkeyActionPressedEventArgs e)
{
- AudioSessionSelector.LockSelection = true;
+ MultiSelector.LockSelection = true;
VCAPI.ShowSessionListNotification();
}
[HotkeyAction(Description = "Unlocks the selected session, allowing it to be changed.")]
public void Unlock(object? sender, HotkeyActionPressedEventArgs e)
{
- AudioSessionSelector.LockSelection = false;
+ MultiSelector.LockSelection = false;
VCAPI.ShowSessionListNotification();
}
[HotkeyAction(Description = "Toggles whether the selected session can be changed or not.")]
public void ToggleLock(object? sender, HotkeyActionPressedEventArgs e)
{
- AudioSessionSelector.LockSelection = !AudioSessionSelector.LockSelection;
+ MultiSelector.LockSelection = !MultiSelector.LockSelection;
VCAPI.ShowSessionListNotification();
}
- [HotkeyAction(Description = "Changes the selected session to null.")]
+ [HotkeyAction(Description = "Unsets the selector.")]
public void Deselect(object? sender, HotkeyActionPressedEventArgs e)
{
- AudioSessionSelector.DeselectSession();
+ MultiSelector.DeselectCurrentItem();
+
+ VCAPI.ShowSessionListNotification();
+ }
+ [HotkeyAction(Description = "(De)selects the current session.")]
+ public void ToggleSelected(object? sender, HotkeyActionPressedEventArgs e)
+ {
+ MultiSelector.ToggleSelectCurrentItem();
VCAPI.ShowSessionListNotification();
}
diff --git a/VolumeControl.SDK/Internal/Initializer.cs b/VolumeControl.SDK/Internal/Initializer.cs
index 64d543097..2d3c4bb62 100644
--- a/VolumeControl.SDK/Internal/Initializer.cs
+++ b/VolumeControl.SDK/Internal/Initializer.cs
@@ -18,12 +18,19 @@ public static class Initializer
/// The audio device manager object.
/// The audio device selection manager object.
/// The audio session manager object.
- /// The audio session selection manager object.
+ /// The audio session selection manager object.
/// The hotkey manager object.
/// The mixer window's handle
/// The program settings container object.
/// Initialize was already called previously.
- public static VCAPI Initialize(AudioDeviceManager audioDeviceManager, AudioDeviceSelector audioDeviceSelector, AudioSessionManager audioSessionManager, AudioSessionSelector audioSessionSelector, HotkeyManager mgr, IntPtr mainWindowHWnd, Config settings)
+ public static VCAPI Initialize(
+ AudioDeviceManager audioDeviceManager,
+ AudioDeviceSelector audioDeviceSelector,
+ AudioSessionManager audioSessionManager,
+ AudioSessionMultiSelector audioSessionMultiSelector,
+ HotkeyManager mgr,
+ IntPtr mainWindowHWnd,
+ Config settings)
{
if (_initialized)
{
@@ -32,7 +39,14 @@ public static VCAPI Initialize(AudioDeviceManager audioDeviceManager, AudioDevic
}
_initialized = true;
- return VCAPI.Default = new(audioDeviceManager, audioDeviceSelector, audioSessionManager, audioSessionSelector, mgr, mainWindowHWnd, settings);
+ return VCAPI.Default = new(
+ audioDeviceManager,
+ audioDeviceSelector,
+ audioSessionManager,
+ audioSessionMultiSelector,
+ mgr,
+ mainWindowHWnd,
+ settings);
}
}
}
diff --git a/VolumeControl.SDK/VCAPI.cs b/VolumeControl.SDK/VCAPI.cs
index 54ae372f8..beee2e498 100644
--- a/VolumeControl.SDK/VCAPI.cs
+++ b/VolumeControl.SDK/VCAPI.cs
@@ -15,12 +15,12 @@ namespace VolumeControl.SDK
public class VCAPI
{
#region Initializer
- internal VCAPI(AudioDeviceManager audioDeviceManager, AudioDeviceSelector audioDeviceSelector, AudioSessionManager audioSessionManager, AudioSessionSelector audioSessionSelector, HotkeyManager hkManager, IntPtr MainHWnd, Config settings)
+ internal VCAPI(AudioDeviceManager audioDeviceManager, AudioDeviceSelector audioDeviceSelector, AudioSessionManager audioSessionManager, AudioSessionMultiSelector audioSessionMultiSelector, HotkeyManager hkManager, IntPtr MainHWnd, Config settings)
{
AudioDeviceManager = audioDeviceManager;
AudioDeviceSelector = audioDeviceSelector;
AudioSessionManager = audioSessionManager;
- AudioSessionSelector = audioSessionSelector;
+ AudioSessionMultiSelector = audioSessionMultiSelector;
HotkeyManager = hkManager;
MainWindowHWnd = MainHWnd;
Settings = settings;
@@ -54,7 +54,7 @@ internal VCAPI(AudioDeviceManager audioDeviceManager, AudioDeviceSelector audioD
///
/// Manages the selected instance for the .
///
- public AudioSessionSelector AudioSessionSelector { get; }
+ public AudioSessionMultiSelector AudioSessionMultiSelector { get; }
///
/// This is the global responsible for managing hotkeys.
///
diff --git a/VolumeControl/Mixer.xaml b/VolumeControl/Mixer.xaml
index 1e1e97391..5df998fae 100644
--- a/VolumeControl/Mixer.xaml
+++ b/VolumeControl/Mixer.xaml
@@ -227,14 +227,14 @@
-
+
-
+
@@ -183,50 +253,26 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/VolumeControl/SessionListNotification.xaml.cs b/VolumeControl/SessionListNotification.xaml.cs
index e84a1f1dc..017f3112a 100644
--- a/VolumeControl/SessionListNotification.xaml.cs
+++ b/VolumeControl/SessionListNotification.xaml.cs
@@ -1,13 +1,13 @@
using System;
using System.ComponentModel;
using System.Windows;
+using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media.Animation;
using VolumeControl.Core;
using VolumeControl.Helpers;
using VolumeControl.Log;
-using VolumeControl.SDK;
using VolumeControl.SDK.Internal;
using VolumeControl.ViewModels;
using VolumeControl.WPF;
@@ -334,13 +334,13 @@ private void ListView_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton.Equals(MouseButton.Middle))
{ // middle mouse toggles session lock
- VCSettings.AudioAPI.AudioSessionSelector.LockSelection = !VCSettings.AudioAPI.AudioSessionSelector.LockSelection;
+ VCSettings.AudioAPI.AudioSessionMultiSelector.LockSelection = !VCSettings.AudioAPI.AudioSessionMultiSelector.LockSelection;
e.Handled = true;
return;
}
else if (!Settings.LockTargetSession && e.ChangedButton.Equals(MouseButton.Right))
{ // right mouse deselects
- VCSettings.AudioAPI.AudioSessionSelector.DeselectSession();
+ VCSettings.AudioAPI.AudioSessionMultiSelector.UnsetCurrentIndex();
e.Handled = true;
return;
}
@@ -359,10 +359,7 @@ private void ListView_PreviewMouseDown(object sender, MouseButtonEventArgs e)
///
private void ListViewItem_Selected(object sender, RoutedEventArgs e)
{
- if (VCAPI.Default.AudioSessionSelector.Selected is null)
- { // only release mouse capture when there was no select
- ListView.ReleaseMouseCapture();
- }
+ ListView.ReleaseMouseCapture();
}
#endregion ListViewItem
diff --git a/VolumeControl/ViewModels/AudioDeviceManagerVM.cs b/VolumeControl/ViewModels/AudioDeviceManagerVM.cs
index 97c4ec6a0..66fce74a5 100644
--- a/VolumeControl/ViewModels/AudioDeviceManagerVM.cs
+++ b/VolumeControl/ViewModels/AudioDeviceManagerVM.cs
@@ -7,6 +7,7 @@
using System.Windows;
using System.Windows.Threading;
using VolumeControl.Core;
+using VolumeControl.Core.Helpers;
using VolumeControl.CoreAudio;
using VolumeControl.CoreAudio.Events;
using VolumeControl.Log;
@@ -23,45 +24,85 @@ public sealed class AudioDeviceManagerVM : DependencyObject, INotifyPropertyChan
{
public AudioDeviceManagerVM()
{
- AudioDeviceManager = new(DataFlow.Render);
+ var doDebugLogging = Log.IsEventVisible(VolumeControl.Log.Enum.EventType.DEBUG);
+ if (doDebugLogging) Log.Debug("Started initializing CoreAudio APIs.");
- Log.Debug("Initializing Audio Devices.");
+ // # INIT DEVICES #
+ // setup the device manager
+ AudioDeviceManager = new(DataFlow.Render);
+ // setup the devices list
Devices = new();
+ // attach handlers for devices being added/removed at runtime
AudioDeviceManager.DeviceAddedToList += AudioDeviceManager_DeviceAddedToList;
AudioDeviceManager.DeviceRemovedFromList += AudioDeviceManager_DeviceRemovedFromList;
- foreach (var device in AudioDeviceManager.Devices)
+ // populate the devices list
+ for (int i = 0, max = AudioDeviceManager.Devices.Count; i < max; ++i)
{
- Devices.Add(new(device));
+ Devices.Add(new AudioDeviceVM(AudioDeviceManager.Devices[i]));
}
- Log.Debug("Finished initializing Audio Devices, started initializing Audio Sessions.");
+ // setup the device selection manager
+ AudioDeviceSelector = new(AudioDeviceManager);
- AllSessions = new();
+ if (doDebugLogging) Log.Debug($"Successfully initialized {AudioDeviceManager.Devices.Count} audio devices.");
+ // # INIT SESSIONS #
+ // setup the session manager
AudioSessionManager = new();
- AudioSessionManager.PreviewSessionName += this.AudioSessionManager_PreviewSessionName;
+ // setup the sessions list
+ AllSessions = new();
+
+ // attach handlers for sessions being added/removed at runtime
AudioSessionManager.AddedSessionToList += this.AudioSessionManager_AddedSessionToList;
AudioSessionManager.RemovedSessionFromList += this.AudioSessionManager_RemovedSessionFromList;
- // hide sessions when started if their name is in the hidden sessions list
+ // attach handler to override session names
+ AudioSessionManager.PreviewSessionName += this.AudioSessionManager_PreviewSessionName;
+
+ // attach handler to set session hidden state when added
AudioSessionManager.PreviewSessionIsHidden += this.AudioSessionManager_PreviewSessionIsHidden;
- // hide/unhide sessions when added/removed from the hidden sessions list
+ // attach handler to hide/unhide sessions when the hidden sessions names list is changed
Settings.HiddenSessionProcessNames.CollectionChanged += this.HiddenSessionProcessNames_CollectionChanged;
- // populate the AudioSessionManager with AudioDeviceSessionManager instances, which also populates the lists of sessions
- Devices.Select(d => d.AudioDevice.SessionManager).ForEach(AudioSessionManager.AddSessionManager);
-
- AudioDeviceSelector = new(AudioDeviceManager);
- AudioSessionSelector = new(AudioSessionManager)
+ // setup the session selection manager
+ SelectedSessions = new();
+ SelectedSessionsComparer = Comparer.Create((a, b) => AllSessions.IndexOf(a) - AllSessions.IndexOf(b));
+ AudioSessionMultiSelector = new(AudioSessionManager)
{
LockSelection = Settings.LockTargetSession,
+ LockCurrentIndex = Settings.LockTargetSession,
+ LockCurrentIndexOnLockSelection = true
};
- Log.Debug("Finished initializing Audio Sessions.");
+ // populate the sessions lists
+ Devices.Select(d => d.AudioDevice.SessionManager).ForEach(AudioSessionManager.AddSessionManager);
+
+ // select all previously-selected sessions
+ foreach (var item in Settings.SelectedSessions)
+ {
+ if (AudioSessionManager.FindSessionWithSimilarProcessIdentifier(item.ProcessIdentifier, StringComparison.OrdinalIgnoreCase) is AudioSession session)
+ {
+ AudioSessionMultiSelector.SetSessionIsSelected(session, true);
+ this.SelectedSessions.Add(GetAudioSessionVM(session)!);
+ }
+ }
+ // set the current session
+ var currentSession = AudioSessionManager.FindSessionWithSimilarProcessIdentifier(Settings.TargetSession.ProcessIdentifier, StringComparison.OrdinalIgnoreCase);
+ AudioSessionMultiSelector.CurrentSession = currentSession;
+ this.CurrentSession = currentSession == null ? null : GetAudioSessionVM(currentSession);
+
+ // attach handlers to session selection events
+ AudioSessionMultiSelector.SessionSelected += this.AudioSessionMultiSelector_SessionSelected;
+ AudioSessionMultiSelector.SessionDeselected += this.AudioSessionMultiSelector_SessionDeselected;
+ AudioSessionMultiSelector.CurrentItemChanged += this.AudioSessionMultiSelector_CurrentItemChanged;
+
+ if (doDebugLogging) Log.Debug($"Successfully initialized {AudioSessionManager.Sessions.Count + AudioSessionManager.HiddenSessions.Count} {(AudioSessionManager.HiddenSessions.Count == 0 ? "" : $"({AudioSessionManager.HiddenSessions.Count} hidden)")} audio sessions.");
+
+ if (doDebugLogging) Log.Debug("Finished initializing CoreAudio APIs.");
}
#region Events
@@ -79,8 +120,24 @@ public AudioDeviceManagerVM()
public ObservableImmutableList Devices { get; }
public CoreAudio.AudioSessionManager AudioSessionManager { get; }
public ObservableImmutableList AllSessions { get; }
+ public ObservableImmutableList SelectedSessions { get; }
+ public Comparer SelectedSessionsComparer { get; }
+ public AudioSessionVM? CurrentSession { get; set; }
public AudioDeviceSelector AudioDeviceSelector { get; }
- public AudioSessionSelector AudioSessionSelector { get; }
+ public AudioSessionMultiSelector AudioSessionMultiSelector { get; }
+ public bool? AllSessionsSelected
+ {
+ get
+ {
+ var selected = SelectedSessions.Count;
+ var total = AllSessions.Count;
+
+ if (selected == total) return true;
+ else if (selected == 0) return false;
+ else return null;
+ }
+ set => AudioSessionMultiSelector.SetAllSessionSelectionStates(value == true);
+ }
#endregion Properties
#region Methods
@@ -122,7 +179,7 @@ private void AudioDeviceManager_DeviceRemovedFromList(object? sender, AudioDevic
#region AudioSessionManager
private void AudioSessionManager_AddedSessionToList(object? sender, AudioSession e)
- => Dispatcher.Invoke(() => AllSessions.Add(new AudioSessionVM(e)));
+ => Dispatcher.Invoke(() => AllSessions.Add(new AudioSessionVM(this, e)));
private void AudioSessionManager_RemovedSessionFromList(object? sender, AudioSession e)
{
// check if the vm actually exists to prevent possible exception in rare cases
@@ -183,6 +240,29 @@ private void HiddenSessionProcessNames_CollectionChanged(object? sender, System.
}
#endregion HiddenSessionProcessNames
+ #region AudioSessionMultiSelector
+ private void AudioSessionMultiSelector_SessionSelected(object? sender, AudioSession e)
+ {
+ Settings.SelectedSessions.AddIfUnique(e.GetTargetInfo());
+ this.SelectedSessions.Add(GetAudioSessionVM(e)!);
+ this.SelectedSessions.Sort(SelectedSessionsComparer);
+ // update the all selected checkbox
+ NotifyPropertyChanged(nameof(AllSessionsSelected));
+ }
+ private void AudioSessionMultiSelector_SessionDeselected(object? sender, AudioSession e)
+ {
+ Settings.SelectedSessions.Remove(e.GetTargetInfo());
+ this.SelectedSessions.Remove(GetAudioSessionVM(e)!);
+ // update the all selected checkbox
+ NotifyPropertyChanged(nameof(AllSessionsSelected));
+ }
+ private void AudioSessionMultiSelector_CurrentItemChanged(object? sender, AudioSession? e)
+ {
+ Settings.TargetSession = e?.GetTargetInfo() ?? TargetInfo.Empty;
+ CurrentSession = e == null ? null : GetAudioSessionVM(e);
+ }
+ #endregion AudioSessionMultiSelector
+
#endregion EventHandlers
}
}
diff --git a/VolumeControl/ViewModels/AudioDeviceVM.cs b/VolumeControl/ViewModels/AudioDeviceVM.cs
index f6cb514a6..70045b323 100644
--- a/VolumeControl/ViewModels/AudioDeviceVM.cs
+++ b/VolumeControl/ViewModels/AudioDeviceVM.cs
@@ -1,11 +1,9 @@
using System;
using System.ComponentModel;
-using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows.Media;
using VolumeControl.CoreAudio;
using VolumeControl.WPF;
-using VolumeControl.WPF.Collections;
namespace VolumeControl.ViewModels
{
@@ -21,17 +19,17 @@ public AudioDeviceVM(AudioDevice audioDevice)
Icon = IconExtractor.TryExtractFromPath(AudioDevice.IconPath, out ImageSource icon) ? icon : null;
Icon?.Freeze(); //< prevents WPF exceptions in some cases
- Sessions = new();
+ //Sessions = new();
// attach events to add and remove audio sessions from the Sessions list
- AudioDevice.SessionManager.SessionAddedToList += this.SessionManager_SessionAddedToList;
- AudioDevice.SessionManager.SessionRemovedFromList += this.SessionManager_SessionRemovedFromList;
+ //AudioDevice.SessionManager.SessionAddedToList += this.SessionManager_SessionAddedToList;
+ //AudioDevice.SessionManager.SessionRemovedFromList += this.SessionManager_SessionRemovedFromList;
// initialize Sessions list
- foreach (var session in AudioDevice.SessionManager.Sessions)
- {
- Sessions.Add(new AudioSessionVM(session));
- }
+ //foreach (var session in AudioDevice.SessionManager.Sessions)
+ //{
+ // Sessions.Add(new AudioSessionVM(session));
+ //}
}
#endregion Constructor
@@ -54,7 +52,7 @@ public ImageSource? Icon
private ImageSource? _icon = null;
public string Name => AudioDevice.Name;
public string DeviceFriendlyName => AudioDevice.FullName;
- public ObservableImmutableList Sessions { get; }
+ //public ObservableImmutableList Sessions { get; }
#endregion Properties
#region IDisposable Implementation
@@ -68,16 +66,16 @@ public void Dispose()
#region EventHandlers
#region SessionManager
- private void SessionManager_SessionAddedToList(object? sender, AudioSession e)
- {
- Sessions.Add(new AudioSessionVM(e));
- }
- private void SessionManager_SessionRemovedFromList(object? sender, AudioSession e)
- {
- var vm = Sessions.First(svm => svm.AudioSession.Equals(e));
- Sessions.Remove(vm);
- vm.Dispose();
- }
+ //private void SessionManager_SessionAddedToList(object? sender, AudioSession e)
+ //{
+ // Sessions.Add(new AudioSessionVM(e));
+ //}
+ //private void SessionManager_SessionRemovedFromList(object? sender, AudioSession e)
+ //{
+ // var vm = Sessions.First(svm => svm.AudioSession.Equals(e));
+ // Sessions.Remove(vm);
+ // vm.Dispose();
+ //}
#endregion SessionManager
#endregion EventHandlers
diff --git a/VolumeControl/ViewModels/AudioSessionVM.cs b/VolumeControl/ViewModels/AudioSessionVM.cs
index bce4f6f01..35a723d25 100644
--- a/VolumeControl/ViewModels/AudioSessionVM.cs
+++ b/VolumeControl/ViewModels/AudioSessionVM.cs
@@ -15,13 +15,18 @@ namespace VolumeControl.ViewModels
public sealed class AudioSessionVM : INotifyPropertyChanged, IDisposable
{
#region Constructor
- public AudioSessionVM(AudioSession audioSession)
+ public AudioSessionVM(AudioDeviceManagerVM manager, AudioSession audioSession)
{
+ AudioDeviceManagerVM = manager;
AudioSession = audioSession;
Icon = GetIcon();
AudioSession.IconPathChanged += (s, e) => Icon = GetIcon();
+
+ // update bindings on the IsSelected property when this session is selected or deselected
+ manager.AudioSessionMultiSelector.SessionSelected += this.AudioSessionMultiSelector_SessionSelected_SessionDeselected;
+ manager.AudioSessionMultiSelector.SessionDeselected += this.AudioSessionMultiSelector_SessionSelected_SessionDeselected;
}
#endregion Constructor
@@ -31,6 +36,7 @@ public AudioSessionVM(AudioSession audioSession)
#endregion Events
#region Properties
+ AudioDeviceManagerVM AudioDeviceManagerVM { get; }
public AudioSession AudioSession { get; }
public ImageSource? Icon
{
@@ -46,6 +52,17 @@ public ImageSource? Icon
public string ProcessName => AudioSession.ProcessName;
public string ProcessIdentifier => AudioSession.ProcessIdentifier;
public string Name => AudioSession.Name;
+ public bool IsSelected
+ {
+ get => SDK.VCAPI.Default.AudioSessionMultiSelector.GetSessionIsSelected(this.AudioSession);
+ set
+ {
+ _isSelectedChanging = true;
+ SDK.VCAPI.Default.AudioSessionMultiSelector.SetSessionIsSelected(this.AudioSession, value);
+ _isSelectedChanging = false;
+ NotifyPropertyChanged();
+ }
+ }
#endregion Properties
#region Methods
@@ -92,5 +109,16 @@ public void Dispose()
GC.SuppressFinalize(this);
}
#endregion IDisposable Implementation
+
+ private bool _isSelectedChanging;
+ private void AudioSessionMultiSelector_SessionSelected_SessionDeselected(object? sender, AudioSession e)
+ {
+ if (_isSelectedChanging) return; //< don't update if the source is this object
+
+ if (e.Equals(this.AudioSession))
+ {
+ NotifyPropertyChanged(nameof(IsSelected));
+ }
+ }
}
}
diff --git a/VolumeControl/ViewModels/VolumeControlVM.cs b/VolumeControl/ViewModels/VolumeControlVM.cs
index 8bb54d428..a06b280e1 100644
--- a/VolumeControl/ViewModels/VolumeControlVM.cs
+++ b/VolumeControl/ViewModels/VolumeControlVM.cs
@@ -41,7 +41,7 @@ public VolumeControlVM() : base()
this.HotkeyAPI = new(actionManager);
// Initialize the addon API
- var api = Initializer.Initialize(this.AudioAPI.AudioDeviceManager, this.AudioAPI.AudioDeviceSelector, this.AudioAPI.AudioSessionManager, this.AudioAPI.AudioSessionSelector, this.HotkeyAPI, this.MainWindowHandle, (AppConfig.Configuration.Default as Config)!);
+ var api = Initializer.Initialize(this.AudioAPI.AudioDeviceManager, this.AudioAPI.AudioDeviceSelector, this.AudioAPI.AudioSessionManager, this.AudioAPI.AudioSessionMultiSelector, this.HotkeyAPI, this.MainWindowHandle, (AppConfig.Configuration.Default as Config)!);
VCHotkeyAddon hotkeyAddonLoader = new();
@@ -82,7 +82,7 @@ public VolumeControlVM() : base()
this.HotkeyAPI.LoadHotkeys();
// attach event to update TargetSessionText & LockTargetSession properties
- VCAPI.Default.AudioSessionSelector.PropertyChanged += this.AudioSessionSelector_PropertyChanged;
+ VCAPI.Default.AudioSessionMultiSelector.PropertyChanged += this.AudioSessionSelector_PropertyChanged;
// setup autocomplete
RefreshSessionAutoCompleteSources();
@@ -139,7 +139,7 @@ public VolumeControlVM() : base()
///
public string TargetSessionText
{
- get => AudioAPI.AudioSessionSelector.Selected?.ProcessIdentifier ?? Settings.TargetSession.ProcessIdentifier;
+ get => AudioAPI.AudioSessionMultiSelector.CurrentSession?.ProcessIdentifier ?? Settings.TargetSession.ProcessIdentifier;
set
{
value = value.Trim();
@@ -150,7 +150,7 @@ public string TargetSessionText
{
if (AudioAPI.AudioSessionManager.FindSessionWithSimilarProcessIdentifier(value) is AudioSession session)
{ // text resolves to a valid AudioSession, select it:
- AudioAPI.AudioSessionSelector.Selected = session;
+ AudioAPI.AudioSessionMultiSelector.CurrentSession = session;
}
else
{ // text does not resolve to a valid AudioSession:
@@ -162,7 +162,7 @@ public string TargetSessionText
}
else
{
- AudioAPI.AudioSessionSelector.Selected = null;
+ AudioAPI.AudioSessionMultiSelector.CurrentSession = null;
}
_updatingAudioSessionSelectorFromTargetSessionText = false;
@@ -244,7 +244,7 @@ private void AudioSessionSelector_PropertyChanged(object? sender, System.Compone
{
if (e.PropertyName is null) return;
- if (e.PropertyName.Equals(nameof(AudioSessionSelector.Selected)))
+ if (e.PropertyName.Equals(nameof(AudioSessionMultiSelector.CurrentIndex)))
{
if (!_updatingAudioSessionSelectorFromTargetSessionText)
{
@@ -253,7 +253,7 @@ private void AudioSessionSelector_PropertyChanged(object? sender, System.Compone
}
else if (e.PropertyName.Equals(nameof(AudioSessionSelector.LockSelection)))
{
- LockTargetSession = VCAPI.Default.AudioSessionSelector.LockSelection;
+ LockTargetSession = VCAPI.Default.AudioSessionMultiSelector.LockSelection;
}
}
///