14
14
15
15
using System ;
16
16
using System . Collections . Generic ;
17
+ using System . Linq ;
17
18
using NAudio . CoreAudioApi ;
18
19
using Serilog ;
19
20
using SoundSwitch . Common . Framework . Audio . Device ;
@@ -26,16 +27,37 @@ namespace SoundSwitch.Framework.Audio.Lister
26
27
public class CachedAudioDeviceLister : IAudioDeviceLister
27
28
{
28
29
/// <inheritdoc />
29
- public IReadOnlyCollection < DeviceFullInfo > PlaybackDevices => _playbackDevices ;
30
+ public IReadOnlyCollection < DeviceFullInfo > PlaybackDevices
31
+ {
32
+ get
33
+ {
34
+ lock ( _lockPlayback )
35
+ {
36
+ return _playbackList ;
37
+ }
38
+ }
39
+ }
30
40
31
41
/// <inheritdoc />
32
- public IReadOnlyCollection < DeviceFullInfo > RecordingDevices => _recordingDevices ;
42
+ public IReadOnlyCollection < DeviceFullInfo > RecordingDevices
43
+ {
44
+ get
45
+ {
46
+ lock ( _lockRecording )
47
+ {
48
+ return _recordingList ;
49
+ }
50
+ }
51
+ }
33
52
34
53
private readonly DeviceState _state ;
35
54
private readonly DebounceDispatcher _dispatcher = new ( ) ;
36
- private readonly object _lock = new ( ) ;
37
- private readonly HashSet < DeviceFullInfo > _playbackDevices = new ( ) ;
38
- private readonly HashSet < DeviceFullInfo > _recordingDevices = new ( ) ;
55
+ private readonly object _lockRefresh = new ( ) ;
56
+ private readonly object _lockRecording = new ( ) ;
57
+ private readonly object _lockPlayback = new ( ) ;
58
+ private IReadOnlyCollection < DeviceFullInfo > _playbackList = new DeviceFullInfo [ 0 ] ;
59
+ private IReadOnlyCollection < DeviceFullInfo > _recordingList = new DeviceFullInfo [ 0 ] ;
60
+
39
61
40
62
public CachedAudioDeviceLister ( DeviceState state )
41
63
{
@@ -47,12 +69,13 @@ private void DeviceChanged(object sender, DeviceChangedEventBase e)
47
69
{
48
70
_dispatcher . Debounce ( 100 , o => Refresh ( ) ) ;
49
71
}
72
+
50
73
public void Refresh ( )
51
74
{
52
- lock ( _lock )
75
+ var playbackDevices = new Dictionary < string , DeviceFullInfo > ( ) ;
76
+ var recordingDevices = new Dictionary < string , DeviceFullInfo > ( ) ;
77
+ lock ( _lockRefresh )
53
78
{
54
- _recordingDevices . Clear ( ) ;
55
- _playbackDevices . Clear ( ) ;
56
79
Log . Information ( "[{@State}] Refreshing all devices" , _state ) ;
57
80
using var enumerator = new MMDeviceEnumerator ( ) ;
58
81
foreach ( var endPoint in enumerator . EnumerateAudioEndPoints ( DataFlow . All , _state ) )
@@ -68,10 +91,10 @@ public void Refresh()
68
91
switch ( deviceInfo . Type )
69
92
{
70
93
case DataFlow . Render :
71
- _playbackDevices . Add ( deviceInfo ) ;
94
+ playbackDevices . Add ( deviceInfo . Id , deviceInfo ) ;
72
95
break ;
73
96
case DataFlow . Capture :
74
- _recordingDevices . Add ( deviceInfo ) ;
97
+ recordingDevices . Add ( deviceInfo . Id , deviceInfo ) ;
75
98
break ;
76
99
case DataFlow . All :
77
100
break ;
@@ -85,7 +108,17 @@ public void Refresh()
85
108
}
86
109
}
87
110
88
- Log . Information ( "[{@State}] Refreshed all devices. {@Recording}/rec, {@Playback}/play" , _state , _recordingDevices . Count , _playbackDevices . Count ) ;
111
+ lock ( _lockPlayback )
112
+ {
113
+ _playbackList = playbackDevices . Values . ToArray ( ) ;
114
+ }
115
+
116
+ lock ( _lockRecording )
117
+ {
118
+ _recordingList = recordingDevices . Values . ToArray ( ) ;
119
+ }
120
+
121
+ Log . Information ( "[{@State}] Refreshed all devices. {@Recording}/rec, {@Playback}/play" , _state , recordingDevices . Count , playbackDevices . Count ) ;
89
122
}
90
123
}
91
124
0 commit comments