@@ -17,7 +17,7 @@ use std::{
1717 ptr:: NonNull ,
1818} ;
1919
20- use num_enum:: { IntoPrimitive , TryFromPrimitive } ;
20+ use num_enum:: { FromPrimitive , IntoPrimitive , TryFromPrimitive } ;
2121use thiserror:: Error ;
2222
2323use crate :: utils:: abort_on_panic;
@@ -353,9 +353,10 @@ pub enum AudioCallbackResult {
353353}
354354
355355#[ repr( i32 ) ]
356- #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
356+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , FromPrimitive , IntoPrimitive ) ]
357+ #[ non_exhaustive]
357358#[ doc( alias = "aaudio_result_t" ) ]
358- pub enum AudioErrorResult {
359+ pub enum AudioResult {
359360 #[ doc( alias = "AAUDIO_ERROR_BASE" ) ]
360361 Base = ffi:: AAUDIO_ERROR_BASE ,
361362 /// The audio device was disconnected. This could occur, for example, when headphones
@@ -409,58 +410,44 @@ pub enum AudioErrorResult {
409410 /// The requested sample rate was not supported.
410411 #[ doc( alias = "AAUDIO_ERROR_INVALID_RATE" ) ]
411412 InvalidRate = ffi:: AAUDIO_ERROR_INVALID_RATE ,
413+ // Use the OK discriminant, as no-one will be able to call `as i32` and only has access to the
414+ // constants via `From` provided by `IntoPrimitive` which reads the contained value.
415+ #[ num_enum( catch_all) ]
416+ Unknown ( i32 ) = ffi:: AAUDIO_OK ,
412417}
413418
414- impl AudioErrorResult {
419+ impl AudioResult {
415420 #[ doc( alias = "AAudio_convertStreamStateToText" ) ]
416421 pub fn to_text ( self ) -> Cow < ' static , str > {
417- let ptr = unsafe {
418- CStr :: from_ptr ( ffi:: AAudio_convertStreamStateToText (
419- self as ffi:: aaudio_result_t ,
420- ) )
421- } ;
422+ let ptr = unsafe { CStr :: from_ptr ( ffi:: AAudio_convertStreamStateToText ( self . into ( ) ) ) } ;
422423 ptr. to_string_lossy ( )
423424 }
425+
426+ /// Returns [`Ok`] on [`ffi::AAUDIO_OK`], [`Err`] otherwise (including positive values).
427+ ///
428+ /// Note that some known error codes (currently only for `AMediaCodec`) are positive.
429+ pub ( crate ) fn from_result ( status : ffi:: aaudio_result_t ) -> Result < ( ) , Self > {
430+ match status {
431+ ffi:: AAUDIO_OK => Ok ( ( ) ) ,
432+ x => Err ( Self :: from ( x) ) ,
433+ }
434+ }
424435}
425436
426437#[ derive( Debug , Error ) ]
427438pub enum AudioError {
428439 #[ error( "error Audio result ({0:?})" ) ]
429- ErrorResult ( AudioErrorResult ) ,
430- #[ error( "unknown AAudio error result ({0})" ) ]
431- UnknownResult ( i32 ) ,
440+ ErrorResult ( AudioResult ) ,
432441 #[ error( "unsupported AAudio result value received ({0})" ) ]
433442 UnsupportedValue ( i32 ) ,
434443}
435444
436445impl AudioError {
437- pub ( crate ) fn from_result < T > (
438- result : ffi:: aaudio_result_t ,
439- on_success : impl FnOnce ( ) -> T ,
440- ) -> Result < T > {
441- use AudioErrorResult :: * ;
442- let result = match result {
443- value if value >= 0 => return Ok ( on_success ( ) ) ,
444- ffi:: AAUDIO_ERROR_BASE => Base ,
445- ffi:: AAUDIO_ERROR_DISCONNECTED => Disconnected ,
446- ffi:: AAUDIO_ERROR_ILLEGAL_ARGUMENT => IllegalArgument ,
447- ffi:: AAUDIO_ERROR_INTERNAL => Internal ,
448- ffi:: AAUDIO_ERROR_INVALID_STATE => InvalidState ,
449- ffi:: AAUDIO_ERROR_INVALID_HANDLE => InvalidHandle ,
450- ffi:: AAUDIO_ERROR_UNIMPLEMENTED => Unimplemented ,
451- ffi:: AAUDIO_ERROR_UNAVAILABLE => Unavailable ,
452- ffi:: AAUDIO_ERROR_NO_FREE_HANDLES => NoFreeHandles ,
453- ffi:: AAUDIO_ERROR_NO_MEMORY => NoMemory ,
454- ffi:: AAUDIO_ERROR_NULL => Null ,
455- ffi:: AAUDIO_ERROR_TIMEOUT => Timeout ,
456- ffi:: AAUDIO_ERROR_WOULD_BLOCK => WouldBlock ,
457- ffi:: AAUDIO_ERROR_INVALID_FORMAT => InvalidFormat ,
458- ffi:: AAUDIO_ERROR_OUT_OF_RANGE => OutOfRange ,
459- ffi:: AAUDIO_ERROR_NO_SERVICE => NoService ,
460- ffi:: AAUDIO_ERROR_INVALID_RATE => InvalidRate ,
461- _ => return Err ( AudioError :: UnknownResult ( result) ) ,
462- } ;
463- Err ( AudioError :: ErrorResult ( result) )
446+ /// Returns [`Ok`] on [`ffi::AAUDIO_OK`], [`Err`] otherwise (including positive values).
447+ ///
448+ /// Note that some known error codes (currently only for `AMediaCodec`) are positive.
449+ pub ( crate ) fn from_result ( status : ffi:: aaudio_result_t ) -> Result < ( ) > {
450+ AudioResult :: from_result ( status) . map_err ( Self :: ErrorResult )
464451 }
465452}
466453
@@ -469,7 +456,7 @@ pub type Result<T, E = AudioError> = std::result::Result<T, E>;
469456fn construct < T > ( with_ptr : impl FnOnce ( * mut T ) -> ffi:: aaudio_result_t ) -> Result < T > {
470457 let mut result = MaybeUninit :: uninit ( ) ;
471458 let status = with_ptr ( result. as_mut_ptr ( ) ) ;
472- AudioError :: from_result ( status, | | unsafe { result. assume_init ( ) } )
459+ AudioError :: from_result ( status) . map ( | ( ) | unsafe { result. assume_init ( ) } )
473460}
474461
475462fn enum_return_value < T : TryFrom < u32 > > ( return_value : i32 ) -> Result < T > {
@@ -754,7 +741,7 @@ impl AudioStreamBuilder {
754741 data_callback : None ,
755742 error_callback : None ,
756743 } ;
757- let err = AudioError :: from_result ( error, || ( ) ) . unwrap_err ( ) ;
744+ let err = AudioError :: from_result ( error) . unwrap_err ( ) ;
758745 ( * callback) ( & stream, err) ;
759746 std:: mem:: forget ( stream) ;
760747 } )
@@ -984,7 +971,7 @@ impl Drop for AudioStreamBuilder {
984971 #[ doc( alias = "AAudioStreamBuilder_delete" ) ]
985972 fn drop ( & mut self ) {
986973 let status = unsafe { ffi:: AAudioStreamBuilder_delete ( self . as_ptr ( ) ) } ;
987- AudioError :: from_result ( status, || ( ) ) . unwrap ( ) ;
974+ AudioError :: from_result ( status) . unwrap ( ) ;
988975 }
989976}
990977
@@ -1209,12 +1196,12 @@ impl AudioStream {
12091196 /// It can also be used to align a recorded stream with a playback stream.
12101197 ///
12111198 /// Timestamps are only valid when the stream is in `Started` state.
1212- /// [`InvalidState`][AudioErrorResult ::InvalidState] will be returned
1199+ /// [`InvalidState`][AudioResult ::InvalidState] will be returned
12131200 /// if the stream is not started.
12141201 /// Note that because [`AudioStream::request_start()`] is asynchronous,
12151202 /// timestamps will not be valid until a short time after calling
12161203 /// [`AudioStream::request_start()`].
1217- /// So [`InvalidState`][AudioErrorResult ::InvalidState] should not be
1204+ /// So [`InvalidState`][AudioResult ::InvalidState] should not be
12181205 /// considered a fatal error.
12191206 /// Just try calling again later.
12201207 ///
@@ -1296,7 +1283,7 @@ impl AudioStream {
12961283 ) -> Result < u32 > {
12971284 let result = ffi:: AAudioStream_read ( self . as_ptr ( ) , buffer, num_frames, timeout_nanoseconds) ;
12981285
1299- AudioError :: from_result ( result, | | result as u32 )
1286+ AudioError :: from_result ( result) . map ( | ( ) | result as u32 )
13001287 }
13011288
13021289 /// Asynchronous request for the stream to flush.
@@ -1306,11 +1293,11 @@ impl AudioStream {
13061293 /// After this call the state will be in [`Flushing`][AudioStreamState::Flushing] or
13071294 /// [`Flushed`][AudioStreamState::Flushed].
13081295 ///
1309- /// This will return [`Unimplemented`][AudioErrorResult ::Unimplemented] for input streams.
1296+ /// This will return [`Unimplemented`][AudioResult ::Unimplemented] for input streams.
13101297 #[ doc( alias = "AAudioStream_requestFlush" ) ]
13111298 pub fn request_flush ( & self ) -> Result < ( ) > {
13121299 let result = unsafe { ffi:: AAudioStream_requestFlush ( self . as_ptr ( ) ) } ;
1313- AudioError :: from_result ( result, || ( ) )
1300+ AudioError :: from_result ( result)
13141301 }
13151302
13161303 /// Asynchronous request for the stream to pause.
@@ -1319,12 +1306,12 @@ impl AudioStream {
13191306 /// After this call the state will be in [`Pausing`][AudioStreamState::Pausing] or
13201307 /// [`Paused`][AudioStreamState::Paused].
13211308 ///
1322- /// This will return [`Unimplemented`][AudioErrorResult ::Unimplemented] for input streams.
1309+ /// This will return [`Unimplemented`][AudioResult ::Unimplemented] for input streams.
13231310 /// For input streams use [`AudioStream::request_stop()`].
13241311 #[ doc( alias = "AAudioStream_requestPause" ) ]
13251312 pub fn request_pause ( & self ) -> Result < ( ) > {
13261313 let result = unsafe { ffi:: AAudioStream_requestPause ( self . as_ptr ( ) ) } ;
1327- AudioError :: from_result ( result, || ( ) )
1314+ AudioError :: from_result ( result)
13281315 }
13291316
13301317 /// Asynchronously request to start playing the stream. For output streams, one should
@@ -1335,7 +1322,7 @@ impl AudioStream {
13351322 #[ doc( alias = "AAudioStream_requestStart" ) ]
13361323 pub fn request_start ( & self ) -> Result < ( ) > {
13371324 let result = unsafe { ffi:: AAudioStream_requestStart ( self . as_ptr ( ) ) } ;
1338- AudioError :: from_result ( result, || ( ) )
1325+ AudioError :: from_result ( result)
13391326 }
13401327
13411328 /// Asynchronous request for the stream to stop.
@@ -1345,7 +1332,7 @@ impl AudioStream {
13451332 #[ doc( alias = "AAudioStream_requestStop" ) ]
13461333 pub fn request_stop ( & self ) -> Result < ( ) > {
13471334 let result = unsafe { ffi:: AAudioStream_requestStop ( self . as_ptr ( ) ) } ;
1348- AudioError :: from_result ( result, || ( ) )
1335+ AudioError :: from_result ( result)
13491336 }
13501337
13511338 /// This can be used to adjust the latency of the buffer by changing
@@ -1366,7 +1353,7 @@ impl AudioStream {
13661353 #[ doc( alias = "AAudioStream_setBufferSizeInFrames" ) ]
13671354 pub fn set_buffer_size_in_frames ( & self , num_frames : i32 ) -> Result < i32 > {
13681355 let result = unsafe { ffi:: AAudioStream_setBufferSizeInFrames ( self . as_ptr ( ) , num_frames) } ;
1369- AudioError :: from_result ( result, | | result)
1356+ AudioError :: from_result ( result) . map ( | ( ) | result)
13701357 }
13711358
13721359 /// Wait until the current state no longer matches the input state.
@@ -1423,14 +1410,14 @@ impl AudioStream {
14231410 let result =
14241411 ffi:: AAudioStream_write ( self . as_ptr ( ) , buffer, num_frames, timeout_nanoseconds) ;
14251412
1426- AudioError :: from_result ( result, | | result as u32 )
1413+ AudioError :: from_result ( result) . map ( | ( ) | result as u32 )
14271414 }
14281415}
14291416
14301417impl Drop for AudioStream {
14311418 #[ doc( alias = "AAudioStream_close" ) ]
14321419 fn drop ( & mut self ) {
14331420 let status = unsafe { ffi:: AAudioStream_close ( self . as_ptr ( ) ) } ;
1434- AudioError :: from_result ( status, || ( ) ) . unwrap ( ) ;
1421+ AudioError :: from_result ( status) . unwrap ( ) ;
14351422 }
14361423}
0 commit comments