Skip to content

Commit 9c4e240

Browse files
committed
Further refactoring of DeviceHandles.
Also fixes #515.
1 parent b89df31 commit 9c4e240

File tree

2 files changed

+42
-50
lines changed

2 files changed

+42
-50
lines changed

src/host/alsa/enumerate.rs

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::alsa;
22
use super::parking_lot::Mutex;
3-
use super::Device;
3+
use super::{Device, DeviceHandles};
44
use {BackendSpecificError, DevicesError};
55

66
/// ALSA implementation for `Devices`.
@@ -27,37 +27,17 @@ impl Iterator for Devices {
2727
match self.hint_iter.next() {
2828
None => return None,
2929
Some(hint) => {
30-
let name = hint.name;
31-
32-
let io = hint.direction;
33-
34-
if let Some(io) = io {
35-
if io != alsa::Direction::Playback {
36-
continue;
37-
}
38-
}
39-
40-
let name = match name {
41-
Some(name) => {
42-
// Ignoring the `null` device.
43-
if name == "null" {
44-
continue;
45-
}
46-
name
47-
}
48-
_ => continue,
30+
let name = match hint.name {
31+
None => continue,
32+
// Ignoring the `null` device.
33+
Some(name) if name == "null" => continue,
34+
Some(name) => name,
4935
};
5036

51-
// See if the device has an available output stream.
52-
let playback = alsa::pcm::PCM::new(&name, alsa::Direction::Playback, true).ok();
53-
54-
// See if the device has an available input stream.
55-
let capture = alsa::pcm::PCM::new(&name, alsa::Direction::Capture, true).ok();
56-
57-
if playback.is_some() || capture.is_some() {
37+
if let Ok(handles) = DeviceHandles::open(&name) {
5838
return Some(Device {
5939
name,
60-
handles: Mutex::new(super::DeviceHandles { playback, capture }),
40+
handles: Mutex::new(handles),
6141
});
6242
}
6343
}
@@ -70,21 +50,15 @@ impl Iterator for Devices {
7050
pub fn default_input_device() -> Option<Device> {
7151
Some(Device {
7252
name: "default".to_owned(),
73-
handles: Mutex::new(super::DeviceHandles {
74-
playback: None,
75-
capture: None,
76-
}),
53+
handles: Mutex::new(Default::default()),
7754
})
7855
}
7956

8057
#[inline]
8158
pub fn default_output_device() -> Option<Device> {
8259
Some(Device {
8360
name: "default".to_owned(),
84-
handles: Mutex::new(super::DeviceHandles {
85-
playback: None,
86-
capture: None,
87-
}),
61+
handles: Mutex::new(Default::default()),
8862
})
8963
}
9064

src/host/alsa/mod.rs

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -165,17 +165,45 @@ impl Drop for TriggerReceiver {
165165
}
166166
}
167167

168+
#[derive(Default)]
168169
struct DeviceHandles {
169170
playback: Option<alsa::PCM>,
170171
capture: Option<alsa::PCM>,
171172
}
172173

173174
impl DeviceHandles {
174-
fn handle_mut(&mut self, stream_type: alsa::Direction) -> &mut Option<alsa::PCM> {
175-
match stream_type {
175+
/// Create `DeviceHandles` for `name` and try to open a handle for both
176+
/// directions. Returns `Ok` if either direction is opened successfully.
177+
fn open(name: &str) -> Result<Self, alsa::Error> {
178+
let mut handles = Self::default();
179+
let playback_err = handles.try_open(name, alsa::Direction::Playback).err();
180+
let capture_err = handles.try_open(name, alsa::Direction::Capture).err();
181+
if let Some(err) = capture_err.and(playback_err) {
182+
Err(err)
183+
} else {
184+
Ok(handles)
185+
}
186+
}
187+
188+
/// Get a mutable reference to the `Option` for a specific `stream_type`.
189+
/// If the `Option` is `None`, the `alsa::PCM` will be opened and placed in
190+
/// the `Option` before returning. If `handle_mut()` returns `Ok` the contained
191+
/// `Option` is guaranteed to be `Some(..)`.
192+
fn try_open(
193+
&mut self,
194+
name: &str,
195+
stream_type: alsa::Direction,
196+
) -> Result<&mut Option<alsa::PCM>, alsa::Error> {
197+
let handle = match stream_type {
176198
alsa::Direction::Playback => &mut self.playback,
177199
alsa::Direction::Capture => &mut self.capture,
200+
};
201+
202+
if handle.is_none() {
203+
*handle = Some(alsa::pcm::PCM::new(name, stream_type, true)?);
178204
}
205+
206+
Ok(handle)
179207
}
180208

181209
/// Get a mutable reference to the `alsa::PCM` handle for a specific `stream_type`.
@@ -185,23 +213,13 @@ impl DeviceHandles {
185213
name: &str,
186214
stream_type: alsa::Direction,
187215
) -> Result<&mut alsa::PCM, alsa::Error> {
188-
let pcm = self.handle_mut(stream_type);
189-
match pcm {
190-
Some(pcm) => Ok(pcm),
191-
None => {
192-
*pcm = Some(alsa::pcm::PCM::new(name, stream_type, true)?);
193-
Ok(pcm.as_mut().unwrap())
194-
}
195-
}
216+
Ok(self.try_open(name, stream_type)?.as_mut().unwrap())
196217
}
197218

198219
/// Take ownership of the `alsa::PCM` handle for a specific `stream_type`.
199220
/// If the handle is not yet opened, it will be opened and returned.
200221
fn take(&mut self, name: &str, stream_type: alsa::Direction) -> Result<alsa::PCM, alsa::Error> {
201-
match self.handle_mut(stream_type).take() {
202-
Some(pcm) => Ok(pcm),
203-
None => Ok(alsa::pcm::PCM::new(name, stream_type, true)?),
204-
}
222+
Ok(self.try_open(name, stream_type)?.take().unwrap())
205223
}
206224
}
207225

0 commit comments

Comments
 (0)