Skip to content

Commit 8dba79c

Browse files
committed
More rewrites and improvements. Add mute toggle in volume slider control
1 parent f513de1 commit 8dba79c

9 files changed

+162
-94
lines changed

Classes/Globals.cs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public static class Globals
2121

2222
private static float dpiScale = Utils.GetDpiScale();
2323
private static readonly Color defaultColor = Color.SkyBlue;
24+
2425
public static MainForm MainForm { get => mainForm; set => mainForm = value; }
2526
public static InputHandler InputHandler { get => inputHandler; set => inputHandler = value; }
2627
public static AudioHandler AudioHandler { get => audioHandler; set => audioHandler = value; }

Classes/Handlers/AudioHandler.cs

+5-4
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,12 @@ public async void DeviceStateChanged(DeviceChangedArgs value)
127127
case DeviceChangedType.VolumeChanged:
128128
Globals.MainForm.SetAppAppearances(ActionTriggerType.InternalEvent);
129129
if (Globals.VolumeSliderControlForm != null)
130-
await Globals.VolumeSliderControlForm.UpdateVolumeState();
130+
Globals.VolumeSliderControlForm.UpdateVolumeState();
131131
break;
132132
case DeviceChangedType.MuteChanged:
133133
Globals.MainForm.SetAppAppearances(ActionTriggerType.InternalEvent);
134134
if (Globals.VolumeSliderControlForm != null)
135-
await Globals.VolumeSliderControlForm.UpdateVolumeState();
135+
Globals.VolumeSliderControlForm.UpdateVolumeState();
136136
break;
137137
case DeviceChangedType.DefaultChanged:
138138
if (Globals.AudioAvailable && Globals.InputAvailable)
@@ -154,14 +154,15 @@ public async void DeviceStateChanged(DeviceChangedArgs value)
154154
if (currentPeakValue > 1)
155155
currentPeakValue = 1;
156156

157-
Globals.VolumeSliderControlForm.UpdatePeakValue(peakVal.PeakValue);
157+
if (Globals.VolumeSliderControlForm != null)
158+
Globals.VolumeSliderControlForm.UpdatePeakValue(peakVal.PeakValue);
158159
}
159160
break;
160161
default:
161162
break;
162163
}
163164
if (value.ChangedType != DeviceChangedType.PeakValueChanged && Globals.AudioPlaybackDevicesForm != null)
164-
await Globals.AudioPlaybackDevicesForm.RefreshOnDeviceActivity();
165+
await Globals.AudioPlaybackDevicesForm.OnDeviceChanged();
165166
}
166167
}
167168

Forms/AudioPlaybackDevicesForm.Designer.cs

+13-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Forms/AudioPlaybackDevicesForm.cs

+82-56
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections;
23
using System.Collections.Generic;
34
using System.Drawing;
45
using System.Linq;
@@ -14,10 +15,15 @@ namespace tb_vol_scroll.Forms
1415
public partial class AudioPlaybackDevicesForm : Form
1516
{
1617
private bool isRefreshing = false;
18+
19+
private Queue updateDeviceTaskQueue = new Queue();
20+
private Task updateDeviceTask = null;
21+
22+
1723
public AudioPlaybackDevicesForm()
1824
{
1925
InitializeComponent();
20-
Utils.SetWindowTheme(DevicesListView.Handle, "Explorer", null);
26+
//Utils.SetWindowTheme(DevicesListView.Handle, "Explorer", null);
2127

2228
}
2329

@@ -46,24 +52,31 @@ private async void AudioPlaybackDevicesForm_Shown(object sender, EventArgs e)
4652
await LoadAudioPlaybackDevicesList();
4753
}
4854

49-
public async Task LoadAudioPlaybackDevicesList()
55+
private async Task ProcessUpdateDeviceQueue()
5056
{
51-
Utils.InvokeIfRequired(this, () =>
57+
if ((updateDeviceTask == null) || updateDeviceTask.IsCompleted)
5258
{
53-
SuspendLayout();
54-
DevicesListView.Items.Clear();
55-
SetDefaultButton.Enabled = false;
56-
RefreshButton.Enabled = false;
57-
});
59+
if (updateDeviceTaskQueue.Count != 0)
60+
{
61+
updateDeviceTaskQueue.Dequeue();
62+
updateDeviceTask = RefreshOnDeviceActivity();
63+
await updateDeviceTask;
64+
if (updateDeviceTaskQueue.Count != 0)
65+
await ProcessUpdateDeviceQueue();
66+
}
67+
}
68+
}
5869

70+
public async Task LoadAudioPlaybackDevicesList()
71+
{
5972
List<ListViewItem> deviceListViewItem = new List<ListViewItem>();
6073
List<CoreAudioDevice> audioDevices = (await Task.Run(() => Globals.AudioHandler.AudioController.GetPlaybackDevicesAsync(DeviceState.Active))).ToList();
6174
if (audioDevices.Count != 0)
6275
{
6376
foreach (CoreAudioDevice d in audioDevices)
6477
{
65-
Utils.ExtractIconEx(d.IconPath.Split(',')[0], int.Parse(d.IconPath.Split(',')[1]), out IntPtr hIcon, IntPtr.Zero, 1);
66-
DevicesListViewImageList.Images.Add(Icon.FromHandle(hIcon));
78+
Icon iconImg = Utils.GetIconFromResource(d.IconPath);
79+
DevicesListViewImageList.Images.Add(iconImg);
6780
ListViewItem deviceItem = new ListViewItem
6881
{
6982
ImageIndex = audioDevices.IndexOf(d),
@@ -80,92 +93,99 @@ public async Task LoadAudioPlaybackDevicesList()
8093
Utils.InvokeIfRequired(this, () =>
8194
{
8295
DevicesListView.Items.AddRange(deviceListViewItem.ToArray());
83-
RefreshButton.Enabled = true;
8496
bool hasScrollBars = DevicesListView.ClientSize.Height < (DevicesListView.Items.Count + 1) * DevicesListView.Items[0].Bounds.Height;
8597
DevicesListView.Columns[0].Width = DevicesListView.Width - (60 * 3) - (hasScrollBars ? 25 : 0);
86-
ResumeLayout();
98+
RefreshButton.Enabled = true;
8799
});
88100
}
89101

90102
private async void SetDefaultButton_Click(object sender, EventArgs e)
91103
{
92-
if (DevicesListView.SelectedItems.Count == 0)
104+
if (DevicesListView.SelectedItems.Count == 1)
93105
{
94106
CoreAudioDevice newPlaybackDevice = (CoreAudioDevice)DevicesListView.SelectedItems[0].Tag;
107+
DevicesListView.SelectedItems.Clear();
95108
await newPlaybackDevice.SetAsDefaultAsync();
96109
}
97-
SetDefaultButton.Enabled = false;
110+
MakeDefaultButton.Enabled = false;
98111
}
99112

100113
public async Task RefreshOnDeviceActivity()
101114
{
102-
if (!isRefreshing)
115+
List<CoreAudioDevice> audioDevices = (await Task.Run(() => Globals.AudioHandler.AudioController.GetPlaybackDevicesAsync(DeviceState.Active))).ToList();
116+
Utils.InvokeIfRequired(this, () =>
103117
{
104-
isRefreshing = true;
105-
List<CoreAudioDevice> audioDevices = (await Task.Run(() => Globals.AudioHandler.AudioController.GetPlaybackDevicesAsync(DeviceState.Active))).ToList();
106-
Utils.InvokeIfRequired(this, () =>
118+
RefreshButton.Enabled = false;
119+
foreach (ListViewItem deviceItem in DevicesListView.Items)
107120
{
108-
foreach (ListViewItem deviceItem in DevicesListView.Items)
121+
if (audioDevices.Contains(deviceItem.Tag))
109122
{
110-
if (audioDevices.Contains(deviceItem.Tag))
111-
{
112-
deviceItem.SubItems[1].Text = $"{(int)Math.Round(((CoreAudioDevice)deviceItem.Tag).Volume)}%";
113-
deviceItem.SubItems[2].Text = ((CoreAudioDevice)deviceItem.Tag).IsDefaultDevice ? "Yes" : "No";
114-
deviceItem.SubItems[3].Text = ((CoreAudioDevice)deviceItem.Tag).IsMuted ? "Yes" : "No";
115-
deviceItem.BackColor = ((CoreAudioDevice)deviceItem.Tag).IsDefaultDevice ? Color.FromArgb(225, 255, 225) : Color.White;
116-
}
117-
else
118-
deviceItem.Remove();
119-
audioDevices.Remove((CoreAudioDevice)deviceItem.Tag);
123+
deviceItem.SubItems[1].Text = $"{(int)Math.Round(((CoreAudioDevice)deviceItem.Tag).Volume)}%";
124+
deviceItem.SubItems[2].Text = ((CoreAudioDevice)deviceItem.Tag).IsDefaultDevice ? "Yes" : "No";
125+
deviceItem.SubItems[3].Text = ((CoreAudioDevice)deviceItem.Tag).IsMuted ? "Yes" : "No";
126+
deviceItem.BackColor = ((CoreAudioDevice)deviceItem.Tag).IsDefaultDevice ? Color.FromArgb(225, 255, 225) : Color.White;
120127
}
121-
if (audioDevices.Count != 0)
128+
else
129+
deviceItem.Remove();
130+
audioDevices.Remove((CoreAudioDevice)deviceItem.Tag);
131+
}
132+
if (audioDevices.Count != 0)
133+
{
134+
foreach (CoreAudioDevice device in audioDevices)
122135
{
123-
foreach (CoreAudioDevice device in audioDevices)
136+
ListViewItem deviceItem = new ListViewItem
124137
{
125-
ListViewItem deviceItem = new ListViewItem
126-
{
127-
Text = device.FullName
128-
};
129-
deviceItem.SubItems.Add($"{(int)Math.Round(device.Volume)}%");
130-
deviceItem.SubItems.Add(device.IsDefaultDevice ? "Yes" : "No");
131-
deviceItem.SubItems.Add(device.IsMuted ? "Yes" : "No");
132-
deviceItem.BackColor = device.IsDefaultDevice ? Color.FromArgb(230, 255, 230) : Color.White;
133-
deviceItem.Tag = device;
134-
DevicesListView.Items.Add(deviceItem);
135-
}
138+
Text = device.FullName
139+
};
140+
deviceItem.SubItems.Add($"{(int)Math.Round(device.Volume)}%");
141+
deviceItem.SubItems.Add(device.IsDefaultDevice ? "Yes" : "No");
142+
deviceItem.SubItems.Add(device.IsMuted ? "Yes" : "No");
143+
deviceItem.BackColor = device.IsDefaultDevice ? Color.FromArgb(230, 255, 230) : Color.White;
144+
deviceItem.Tag = device;
145+
DevicesListView.Items.Add(deviceItem);
136146
}
137-
DevicesListViewImageList.Images.Clear();
138-
foreach (ListViewItem deviceItem in DevicesListView.Items)
139-
{
140-
CoreAudioDevice audioDevice = ((CoreAudioDevice)deviceItem.Tag);
141-
Utils.ExtractIconEx(audioDevice.IconPath.Split(',')[0], int.Parse(audioDevice.IconPath.Split(',')[1]), out IntPtr hIcon, IntPtr.Zero, 1);
142-
DevicesListViewImageList.Images.Add(Icon.FromHandle(hIcon));
143-
deviceItem.ImageIndex = DevicesListView.Items.IndexOf(deviceItem);
147+
}
148+
DevicesListViewImageList.Images.Clear();
149+
foreach (ListViewItem deviceItem in DevicesListView.Items)
150+
{
151+
CoreAudioDevice audioDevice = (CoreAudioDevice)deviceItem.Tag;
152+
Icon iconImg = Utils.GetIconFromResource(audioDevice.IconPath);
153+
DevicesListViewImageList.Images.Add(iconImg);
154+
deviceItem.ImageIndex = DevicesListView.Items.IndexOf(deviceItem);
144155

145-
}
146156
bool hasScrollBars = DevicesListView.ClientSize.Height < (DevicesListView.Items.Count + 1) * DevicesListView.Items[0].Bounds.Height;
147157
DevicesListView.Columns[0].Width = DevicesListView.Width - (60 * 3) - (hasScrollBars ? 25 : 0);
158+
RefreshButton.Enabled = true;
159+
160+
}
161+
});
162+
}
163+
164+
public async Task OnDeviceChanged()
165+
{
166+
if (updateDeviceTaskQueue.Count == 0)
167+
updateDeviceTaskQueue.Enqueue(null);
168+
if (updateDeviceTaskQueue.Count != 0)
169+
await ProcessUpdateDeviceQueue();
170+
148171

149-
});
150-
isRefreshing = false;
151-
}
152172
}
153173

154174

155175
private async void RefreshButton_Click(object sender, EventArgs e)
156176
{
157-
await RefreshOnDeviceActivity();
177+
await OnDeviceChanged();
158178
}
159179

160180
private void AudioPlaybackDevicesForm_Deactivate(object sender, EventArgs e)
161181
{
162-
if (!isRefreshing)
163182
Close();
164183
}
165184

166185
private void DevicesListView_SelectedIndexChanged(object sender, EventArgs e)
167186
{
168-
SetDefaultButton.Enabled = DevicesListView.SelectedItems.Count == 1;
187+
MakeDefaultButton.Enabled = DevicesListView.SelectedItems.Count == 1;
188+
Utils.AvoidControlFocus(DevicesListView.Handle);
169189
}
170190

171191
private async void DevicesListView_DoubleClick(object sender, EventArgs e)
@@ -178,5 +198,11 @@ private async void DevicesListView_DoubleClick(object sender, EventArgs e)
178198
Close();
179199
}
180200
}
201+
202+
private void AudioPlaybackDevicesForm_FormClosing(object sender, FormClosingEventArgs e)
203+
{
204+
updateDeviceTaskQueue.Clear();
205+
updateDeviceTask = null;
206+
}
181207
}
182208
}

Forms/ConfigurationForm.Designer.cs

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Forms/FontDialogForm.Designer.cs

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Forms/MainForm.Designer.cs

-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)