@@ -5,9 +5,12 @@ use super::{Mixer, MixerConfig, VolumeCtrl};
55
66use alsa:: ctl:: { ElemId , ElemIface } ;
77use alsa:: mixer:: { MilliBel , SelemChannelId , SelemId } ;
8+ use alsa:: Error as AlsaError ;
89use alsa:: { Ctl , Round } ;
910
10- use std:: ffi:: CString ;
11+ use librespot_core:: Error ;
12+ use std:: ffi:: { CString , NulError } ;
13+ use thiserror:: Error ;
1114
1215#[ derive( Clone ) ]
1316#[ allow( dead_code) ]
@@ -29,8 +32,30 @@ pub struct AlsaMixer {
2932const SND_CTL_TLV_DB_GAIN_MUTE : MilliBel = MilliBel ( -9999999 ) ;
3033const ZERO_DB : MilliBel = MilliBel ( 0 ) ;
3134
35+ #[ derive( Debug , Error ) ]
36+ enum AlsaMixerError {
37+ #[ error( "Could not open Alsa mixer. {0}" ) ]
38+ CouldNotOpen ( AlsaError ) ,
39+ #[ error( "Could not find Alsa mixer control" ) ]
40+ CouldNotFindController ,
41+ #[ error( "Could not open Alsa softvol with that device. {0}" ) ]
42+ CouldNotOpenWithDevice ( AlsaError ) ,
43+ #[ error( "Could not open Alsa softvol with that name. {0}" ) ]
44+ CouldNotOpenWithName ( NulError ) ,
45+ #[ error( "Could not get Alsa softvol dB range. {0}" ) ]
46+ NoDbRange ( AlsaError ) ,
47+ #[ error( "Could not convert Alsa raw volume to dB volume. {0}" ) ]
48+ CouldNotConvertRaw ( AlsaError ) ,
49+ }
50+
51+ impl From < AlsaMixerError > for Error {
52+ fn from ( value : AlsaMixerError ) -> Self {
53+ Error :: failed_precondition ( value)
54+ }
55+ }
56+
3257impl Mixer for AlsaMixer {
33- fn open ( config : MixerConfig ) -> Self {
58+ fn open ( config : MixerConfig ) -> Result < Self , Error > {
3459 info ! (
3560 "Mixing with Alsa and volume control: {:?} for device: {} with mixer control: {},{}" ,
3661 config. volume_ctrl, config. device, config. control, config. index,
@@ -39,10 +64,10 @@ impl Mixer for AlsaMixer {
3964 let mut config = config; // clone
4065
4166 let mixer =
42- alsa:: mixer:: Mixer :: new ( & config. device , false ) . expect ( "Could not open Alsa mixer" ) ;
67+ alsa:: mixer:: Mixer :: new ( & config. device , false ) . map_err ( AlsaMixerError :: CouldNotOpen ) ? ;
4368 let simple_element = mixer
4469 . find_selem ( & SelemId :: new ( & config. control , config. index ) )
45- . expect ( "Could not find Alsa mixer control" ) ;
70+ . ok_or ( AlsaMixerError :: CouldNotFindController ) ? ;
4671
4772 // Query capabilities
4873 let has_switch = simple_element. has_playback_switch ( ) ;
@@ -57,17 +82,17 @@ impl Mixer for AlsaMixer {
5782 // Query dB volume range -- note that Alsa exposes a different
5883 // API for hardware and software mixers
5984 let ( min_millibel, max_millibel) = if is_softvol {
60- let control = Ctl :: new ( & config . device , false )
61- . expect ( "Could not open Alsa softvol with that device" ) ;
85+ let control =
86+ Ctl :: new ( & config . device , false ) . map_err ( AlsaMixerError :: CouldNotOpenWithDevice ) ? ;
6287 let mut element_id = ElemId :: new ( ElemIface :: Mixer ) ;
6388 element_id. set_name (
6489 & CString :: new ( config. control . as_str ( ) )
65- . expect ( "Could not open Alsa softvol with that name" ) ,
90+ . map_err ( AlsaMixerError :: CouldNotOpenWithName ) ? ,
6691 ) ;
6792 element_id. set_index ( config. index ) ;
6893 let ( min_millibel, mut max_millibel) = control
6994 . get_db_range ( & element_id)
70- . expect ( "Could not get Alsa softvol dB range" ) ;
95+ . map_err ( AlsaMixerError :: NoDbRange ) ? ;
7196
7297 // Alsa can report incorrect maximum volumes due to rounding
7398 // errors. e.g. Alsa rounds [-60.0..0.0] in range [0..255] to
@@ -97,7 +122,7 @@ impl Mixer for AlsaMixer {
97122 debug ! ( "Alsa mixer reported minimum dB as mute, trying workaround" ) ;
98123 min_millibel = simple_element
99124 . ask_playback_vol_db ( min + 1 )
100- . expect ( "Could not convert Alsa raw volume to dB volume" ) ;
125+ . map_err ( AlsaMixerError :: CouldNotConvertRaw ) ? ;
101126 }
102127 ( min_millibel, max_millibel)
103128 } ;
@@ -150,7 +175,7 @@ impl Mixer for AlsaMixer {
150175 ) ;
151176 debug ! ( "Alsa forcing linear dB mapping: {}" , use_linear_in_db) ;
152177
153- Self {
178+ Ok ( Self {
154179 config,
155180 min,
156181 max,
@@ -161,7 +186,7 @@ impl Mixer for AlsaMixer {
161186 has_switch,
162187 is_softvol,
163188 use_linear_in_db,
164- }
189+ } )
165190 }
166191
167192 fn volume ( & self ) -> u16 {
0 commit comments