15
15
using System ;
16
16
using System . Collections . Generic ;
17
17
using System . Linq ;
18
- using System . Threading ;
19
18
using NAudio . CoreAudioApi ;
20
19
using Serilog ;
21
20
using SoundSwitch . Common . Framework . Audio . Device ;
@@ -28,85 +27,66 @@ namespace SoundSwitch.Framework.Audio.Lister
28
27
public class CachedAudioDeviceLister : IAudioDeviceLister
29
28
{
30
29
/// <inheritdoc />
31
- public IReadOnlyCollection < DeviceFullInfo > PlaybackDevices
32
- {
33
- get
34
- {
35
- lock ( _lock )
36
- {
37
- return _playbackDevices ;
38
- }
39
- }
40
- }
30
+ public IReadOnlyCollection < DeviceFullInfo > PlaybackDevices => _playbackDevices ;
41
31
42
32
/// <inheritdoc />
43
- public IReadOnlyCollection < DeviceFullInfo > RecordingDevices
44
- {
45
- get
46
- {
47
- lock ( _lock )
48
- {
49
- return _recordingDevices ;
50
- }
51
- }
52
- }
33
+ public IReadOnlyCollection < DeviceFullInfo > RecordingDevices => _recordingDevices ;
53
34
54
- private readonly DeviceState _state ;
55
- private readonly DebounceDispatcher _dispatcher = new ( ) ;
56
- private readonly object _lock = new ( ) ;
57
- private IReadOnlyCollection < DeviceFullInfo > _playbackDevices = new List < DeviceFullInfo > ( ) ;
58
- private IReadOnlyCollection < DeviceFullInfo > _recordingDevices = new List < DeviceFullInfo > ( ) ;
35
+ private readonly DeviceState _state ;
36
+ private readonly DebounceDispatcher _dispatcher = new ( ) ;
37
+ private readonly object _lock = new ( ) ;
38
+ private readonly HashSet < DeviceFullInfo > _playbackDevices = new ( ) ;
39
+ private readonly HashSet < DeviceFullInfo > _recordingDevices = new ( ) ;
59
40
60
41
public CachedAudioDeviceLister ( DeviceState state )
61
42
{
62
- _state = state ;
43
+ _state = state ;
63
44
MMNotificationClient . Instance . DevicesChanged += DeviceChanged ;
64
45
}
65
46
66
47
private void DeviceChanged ( object sender , DeviceChangedEventBase e )
67
48
{
68
49
_dispatcher . Debounce ( 100 , o => Refresh ( ) ) ;
69
50
}
70
-
71
- private void UpdatePlayback ( )
72
- {
73
- Log . Information ( "[{@State}] Refreshing playback" , _state ) ;
74
- using var enumerator = new MMDeviceEnumerator ( ) ;
75
- _playbackDevices = CreateDeviceList ( enumerator . EnumerateAudioEndPoints ( DataFlow . Render , _state ) ) ;
76
- Log . Information ( "[{@State}] Refreshed playbacks: {@Playbacks}" , _state , _playbackDevices . Select ( info => new { info . Name , info . Id } ) ) ;
77
- }
78
-
79
- private void UpdateRecording ( )
80
- {
81
- Log . Information ( "[{@State}] Refreshing recording" , _state ) ;
82
- using var enumerator = new MMDeviceEnumerator ( ) ;
83
- _recordingDevices = CreateDeviceList ( enumerator . EnumerateAudioEndPoints ( DataFlow . Capture , _state ) ) ;
84
- Log . Information ( "[{@State}] Refreshed recordings: {@Recordings}" , _state , _recordingDevices . Select ( info => new { info . Name , info . Id } ) ) ;
85
- }
86
-
87
51
public void Refresh ( )
88
52
{
89
53
lock ( _lock )
90
54
{
55
+ _recordingDevices . Clear ( ) ;
56
+ _playbackDevices . Clear ( ) ;
91
57
Log . Information ( "[{@State}] Refreshing all devices" , _state ) ;
92
- var threadPlayback = new Thread ( UpdatePlayback )
93
- {
94
- Name = $ "Playback Refresh { _state } ",
95
- IsBackground = true
96
- } ;
97
- var threadRecording = new Thread ( UpdateRecording )
58
+ using var enumerator = new MMDeviceEnumerator ( ) ;
59
+ foreach ( var endPoint in enumerator . EnumerateAudioEndPoints ( DataFlow . All , _state ) )
98
60
{
99
- Name = $ "Recording Refresh { _state } ",
100
- IsBackground = true
101
- } ;
102
-
103
- threadPlayback . Start ( ) ;
104
- threadRecording . Start ( ) ;
105
-
106
- threadPlayback . Join ( ) ;
107
- threadRecording . Join ( ) ;
61
+ try
62
+ {
63
+ var deviceInfo = new DeviceFullInfo ( endPoint ) ;
64
+ if ( string . IsNullOrEmpty ( deviceInfo . Name ) )
65
+ {
66
+ continue ;
67
+ }
68
+
69
+ switch ( deviceInfo . Type )
70
+ {
71
+ case DataFlow . Render :
72
+ _playbackDevices . Add ( deviceInfo ) ;
73
+ break ;
74
+ case DataFlow . Capture :
75
+ _recordingDevices . Add ( deviceInfo ) ;
76
+ break ;
77
+ case DataFlow . All :
78
+ break ;
79
+ default :
80
+ throw new ArgumentOutOfRangeException ( ) ;
81
+ }
82
+ }
83
+ catch ( Exception e )
84
+ {
85
+ Log . Warning ( e , "Can't get name of device {device}" , endPoint . ID ) ;
86
+ }
87
+ }
108
88
109
- Log . Information ( "[{@State}] Refreshed all devices" , _state ) ;
89
+ Log . Information ( "[{@State}] Refreshed all devices. {@Recording}/rec, {@Playback}/play " , _state , _recordingDevices . Count , _playbackDevices . Count ) ;
110
90
}
111
91
}
112
92
0 commit comments