@@ -165,17 +165,45 @@ impl Drop for TriggerReceiver {
165165 }
166166}
167167
168+ #[ derive( Default ) ]
168169struct DeviceHandles {
169170 playback : Option < alsa:: PCM > ,
170171 capture : Option < alsa:: PCM > ,
171172}
172173
173174impl 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