@@ -94,6 +94,25 @@ const DEFAULT_PERIODS: alsa::pcm::Frames = 2;
9494// Some ALSA plugins (e.g. alsaequal, certain USB drivers) are not reentrant.
9595static ALSA_OPEN_MUTEX : std:: sync:: Mutex < ( ) > = std:: sync:: Mutex :: new ( ( ) ) ;
9696
97+ fn open_pcm ( pcm_id : & str , direction : alsa:: Direction ) -> Result < alsa:: pcm:: PCM , Error > {
98+ let _guard = ALSA_OPEN_MUTEX . lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) ;
99+ alsa:: pcm:: PCM :: new ( pcm_id, direction, true ) . map_err ( |e| {
100+ let e = Error :: from ( e) ;
101+ if e. kind ( ) == ErrorKind :: UnsupportedConfig {
102+ let dir = match direction {
103+ alsa:: Direction :: Capture => "input" ,
104+ alsa:: Direction :: Playback => "output" ,
105+ } ;
106+ Error :: with_message (
107+ ErrorKind :: UnsupportedOperation ,
108+ format ! ( "Device does not support {dir}" ) ,
109+ )
110+ } else {
111+ e
112+ }
113+ } )
114+ }
115+
97116// TODO: Not yet defined in rust-lang/libc crate
98117const LIBC_ENOTSUPP : libc:: c_int = 524 ;
99118
@@ -361,10 +380,9 @@ impl Device {
361380 sample_format : SampleFormat ,
362381 stream_type : alsa:: Direction ,
363382 ) -> Result < StreamInner , Error > {
364- let handle = {
365- let _guard = ALSA_OPEN_MUTEX . lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) ;
366- alsa:: pcm:: PCM :: new ( & self . pcm_id , stream_type, true ) ?
367- } ;
383+ crate :: validate_stream_config ( & conf) ?;
384+
385+ let handle = open_pcm ( & self . pcm_id , stream_type) ?;
368386
369387 let hw_params = set_hw_params_from_format ( & handle, conf, sample_format) ?;
370388 let ( buffer_size, period_size) = set_sw_params_from_format ( & handle, stream_type) ?;
@@ -438,10 +456,7 @@ impl Device {
438456 & self ,
439457 stream_t : alsa:: Direction ,
440458 ) -> Result < VecIntoIter < SupportedStreamConfigRange > , Error > {
441- let pcm = {
442- let _guard = ALSA_OPEN_MUTEX . lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) ;
443- alsa:: pcm:: PCM :: new ( & self . pcm_id , stream_t, true ) ?
444- } ;
459+ let pcm = open_pcm ( & self . pcm_id , stream_t) ?;
445460
446461 let hw_params = alsa:: pcm:: HwParams :: any ( & pcm) ?;
447462
@@ -520,7 +535,8 @@ impl Device {
520535 const CHANNEL_ENUM_CAP : u32 = 64 ;
521536 let max_channels = hw_params
522537 . get_channels_max ( ) ?
523- . min ( min_channels. max ( CHANNEL_ENUM_CAP ) ) ;
538+ . min ( CHANNEL_ENUM_CAP )
539+ . min ( ChannelCount :: MAX as u32 ) ;
524540
525541 let mut output = Vec :: new ( ) ;
526542 let mut seen_formats: Vec < SampleFormat > = Vec :: new ( ) ;
@@ -564,22 +580,9 @@ impl Device {
564580 // ALSA does not offer default stream formats, so instead we compare all supported formats by
565581 // the `SupportedStreamConfigRange::cmp_default_heuristics` order and select the greatest.
566582 fn default_config ( & self , stream_t : alsa:: Direction ) -> Result < SupportedStreamConfig , Error > {
567- let mut formats: Vec < _ > = {
568- match self . supported_configs ( stream_t) {
569- // EINVAL when querying direction the device does not support (input-only or output-only)
570- Err ( err) if err. kind ( ) == ErrorKind :: UnsupportedConfig => {
571- let dir = match stream_t {
572- alsa:: Direction :: Capture => "input" ,
573- alsa:: Direction :: Playback => "output" ,
574- } ;
575- return Err ( Error :: with_message (
576- ErrorKind :: UnsupportedOperation ,
577- format ! ( "Device does not support {dir}" ) ,
578- ) ) ;
579- }
580- Err ( err) => return Err ( err) ,
581- Ok ( fmts) => fmts. collect ( ) ,
582- }
583+ let mut formats: Vec < _ > = match self . supported_configs ( stream_t) {
584+ Err ( err) => return Err ( err) ,
585+ Ok ( fmts) => fmts. collect ( ) ,
583586 } ;
584587
585588 formats. sort_by ( |a, b| a. cmp_default_heuristics ( b) ) ;
@@ -1574,13 +1577,6 @@ fn set_hw_params_from_format(
15741577 // buffer_size = 2x and period_size = x. This provides consistent low-latency
15751578 // behavior across different ALSA implementations and hardware.
15761579 if let BufferSize :: Fixed ( period_size) = config. buffer_size {
1577- if period_size == 0 {
1578- return Err ( Error :: with_message (
1579- ErrorKind :: InvalidInput ,
1580- "Buffer size must be greater than 0" ,
1581- ) ) ;
1582- }
1583-
15841580 let period_size = period_size as alsa:: pcm:: Frames ;
15851581
15861582 // Validate the requested size against the device's supported ranges using the same PCM
0 commit comments