Skip to content

Commit

Permalink
Continue on av::AudioSession
Browse files Browse the repository at this point in the history
  • Loading branch information
yury committed Dec 28, 2023
1 parent ee216f4 commit 72628a0
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 13 deletions.
2 changes: 1 addition & 1 deletion cidre/src/av/audio/player_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl PlayerNode {
#[objc::msg_send(scheduleBuffer:completionHandler:)]
pub unsafe fn _schedule_buf_ch(&self, buffer: &av::AudioPcmBuf, handler: *mut c_void);

/// Schedule playing samples from an av::AudioPCMBuffer.
/// Schedule playing samples from an [`av::AudioPCMBuf`].
///
/// Schedules the buffer to be played following any previously scheduled commands.
#[inline]
Expand Down
81 changes: 78 additions & 3 deletions cidre/src/av/audio/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub use types::Port;
pub use types::PortOverride;
pub use types::PromptStyle;
pub use types::RecordPermission;
pub use types::RenderingMode;
pub use types::RouteChangeReason;
pub use types::RouteSharingPolicy;
pub use types::SetActiveOpts;
Expand Down Expand Up @@ -112,7 +113,7 @@ impl Session {
}

#[objc::msg_send(setCategory:mode:routeSharingPolicy:options:error:)]
pub unsafe fn set_category_mode_policy_opts_err<'ear>(
pub unsafe fn set_category_mode_policy_opts_err_throws<'ear>(
&mut self,
val: &Category,
mode: &Mode,
Expand All @@ -121,7 +122,7 @@ impl Session {
error: *mut Option<&'ear ns::Error>,
) -> bool;

pub fn set_category_mode_policy_opts<'ear>(
pub unsafe fn set_category_mode_policy_opts_throws<'ear>(
&mut self,
val: &Category,
mode: &Mode,
Expand All @@ -130,7 +131,7 @@ impl Session {
) -> Result<(), &'ear ns::Error> {
let mut err = None;
unsafe {
if self.set_category_mode_policy_opts_err(
if self.set_category_mode_policy_opts_err_throws(
val,
mode,
route_sharing_policy,
Expand All @@ -144,6 +145,18 @@ impl Session {
}
}

pub fn set_category_mode_policy_opts<'ear>(
&mut self,
val: &Category,
mode: &Mode,
route_sharing_policy: RouteSharingPolicy,
options: CategoryOpts,
) -> Result<(), ns::ExErr<'ear>> {
ns::try_catch_err(|| unsafe {
self.set_category_mode_policy_opts_throws(val, mode, route_sharing_policy, options)
})
}

#[objc::msg_send(policy)]
pub fn category(&self) -> &Category;

Expand Down Expand Up @@ -332,3 +345,65 @@ impl Session {
extern "C" {
static AV_AUDIO_SESSION: &'static objc::Class<Session>;
}

/// Notifications
impl Session {
#[doc(alias = "AVAudioSessionInterruptionNotification")]
#[inline]
pub fn interruption_notification() -> &'static ns::NotificationName {
unsafe { AVAudioSessionInterruptionNotification }
}

#[doc(alias = "AVAudioSessionRouteChangeNotification")]
#[inline]
pub fn route_change_notification() -> &'static ns::NotificationName {
unsafe { AVAudioSessionRouteChangeNotification }
}

#[doc(alias = "AVAudioSessionMediaServicesWereLostNotification")]
#[inline]
pub fn media_services_where_lost_notification() -> &'static ns::NotificationName {
unsafe { AVAudioSessionMediaServicesWereLostNotification }
}

#[doc(alias = "AVAudioSessionMediaServicesWereResetNotification")]
#[inline]
pub fn media_services_where_reset_notification() -> &'static ns::NotificationName {
unsafe { AVAudioSessionMediaServicesWereResetNotification }
}

#[doc(alias = "AVAudioSessionSilenceSecondaryAudioHintNotification")]
#[inline]
pub fn silence_secondary_audio_hint_notification() -> &'static ns::NotificationName {
unsafe { AVAudioSessionSilenceSecondaryAudioHintNotification }
}

#[doc(alias = "AVAudioSessionSpatialPlaybackCapabilitiesChangedNotification")]
#[inline]
pub fn spatial_playback_capabilities_changed_notification() -> &'static ns::NotificationName {
unsafe { AVAudioSessionSpatialPlaybackCapabilitiesChangedNotification }
}

#[doc(alias = "AVAudioSessionRenderingModeChangeNotification")]
#[inline]
pub fn rendering_mode_change_notification() -> &'static ns::NotificationName {
unsafe { AVAudioSessionRenderingModeChangeNotification }
}
#[doc(alias = "AVAudioSessionRenderingCapabilitiesChangeNotification")]
#[inline]
pub fn rendering_capabilities_change_notification() -> &'static ns::NotificationName {
unsafe { AVAudioSessionRenderingCapabilitiesChangeNotification }
}
}

extern "C" {
static AVAudioSessionInterruptionNotification: &'static ns::NotificationName;
static AVAudioSessionRouteChangeNotification: &'static ns::NotificationName;
static AVAudioSessionMediaServicesWereLostNotification: &'static ns::NotificationName;
static AVAudioSessionMediaServicesWereResetNotification: &'static ns::NotificationName;
static AVAudioSessionSilenceSecondaryAudioHintNotification: &'static ns::NotificationName;
static AVAudioSessionSpatialPlaybackCapabilitiesChangedNotification:
&'static ns::NotificationName;
static AVAudioSessionRenderingModeChangeNotification: &'static ns::NotificationName;
static AVAudioSessionRenderingCapabilitiesChangeNotification: &'static ns::NotificationName;
}
37 changes: 30 additions & 7 deletions cidre/src/av/audio/session/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -647,24 +647,24 @@ pub enum SilenceSecondaryAudioHintType {
/// durations. If your app requires input and output audio to be presented in the same realtime
/// I/O callback, or requires that input and output audio have the same sample rate or IO buffer
/// duration, or if your app requires the ability to set a preferred sample rate or IO buffer duration
/// for audio input, set the AVAudioSessionIOType to Aggregated.
/// for audio input, set the [`av::AudioSessionIoType`] to Aggregated.
///
/// Apps that don't use AVCaptureSession and use [`av::AudioSessionCategory::play_and_record()`] will continue
/// to have aggregated audio I/O, as in previous versions of iOS.
#[doc(alias = "AVAudioSessionIOType")]
#[derive(Debug, Eq, PartialEq)]
#[repr(usize)]
pub enum IoType {
/// The default value. If your app does not use AVCaptureSession or does not have any specific
/// The default value. If your app does not use [`av::CaptureSession`] or does not have any specific
/// requirement for aggregating input and output audio in the same realtime I/O callback, use this
/// value. Note that if your app does not use AVCaptureSession, it will get aggregated I/O when using
/// AVAudioSessionCategoryPlayAndRecord.
/// value. Note that if your app does not use [`av::CaptureSession`], it will get aggregated I/O when using
/// [`av::AudioSessionCategory::play_and_record()`].
///
/// If your app does utilize AVCaptureSession, use of this value will allow AVCaptureSession to
/// If your app does utilize [`av::CaptureSession`], use of this value will allow [`av::CaptureSession`] to
/// start recording without glitching already running output audio and will allow the system to
/// utilize power-saving optimizations.
NotSpecified = 0,
/// Use this value if your session uses AVAudioSessionCategoryPlayAndRecord and requires input and
/// Use this value if your session uses [`av::AudioSessionCategory::play_and_record()`] and requires input and
/// output audio to be presented in the same realtime I/O callback. For example, if your app will be using
/// a RemoteIO with both input and output enabled.
///
Expand Down Expand Up @@ -751,7 +751,7 @@ pub enum StereoOrientation {
}

#[doc(alias = "AVAudioSessionRecordPermission")]
#[derive(Debug, Eq, PartialEq)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[repr(usize)]
pub enum RecordPermission {
/// The user has not yet been asked for permission.
Expand All @@ -761,3 +761,26 @@ pub enum RecordPermission {
/// The user has been asked and has granted permission.
Granted = u32::from_be_bytes(*b"grnt") as _,
}

#[doc(alias = "AVAudioSessionRenderingMode")]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[repr(isize)]
pub enum RenderingMode {
/// Default Mode when no asset is loaded or playing
NotApplicable = 0,

/// Default mode for non multi-channel cases
MonoStereo = 1,

/// Default mode for multi-channel cases that do not fall into the modes below
Surround = 2,

/// Fallback mode if provided content is Dolby variant but hardware capabilities don't support it
SpatialAudio = 3,

/// Dolby Audio mode
DolbyAudio = 4,

/// Dolby Atmos mode
DolbyAtmos = 5,
}
6 changes: 6 additions & 0 deletions cidre/src/av/capture/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::blocks;
extern "C" {
static AVCaptureDeviceTypeExternal: &'static Type;
static AVCaptureDeviceTypeBuiltInMicrophone: &'static Type;
static AVCaptureDeviceTypeMicrophone: &'static Type;
static AVCaptureDeviceTypeBuiltInWideAngleCamera: &'static Type;
static AVCaptureDeviceTypeBuiltInTelephotoCamera: &'static Type;
static AVCaptureDeviceTypeBuiltInUltraWideCamera: &'static Type;
Expand Down Expand Up @@ -1573,6 +1574,11 @@ impl Type {
unsafe { AVCaptureDeviceTypeBuiltInMicrophone }
}

#[doc(alias = "AVCaptureDeviceTypeMicrophone")]
pub fn microphone() -> &'static Self {
unsafe { AVCaptureDeviceTypeMicrophone }
}

#[doc(alias = "AVCaptureDeviceTypeBuiltInWideAngleCamera")]
pub fn built_in_wide_angle_camera() -> &'static Self {
unsafe { AVCaptureDeviceTypeBuiltInWideAngleCamera }
Expand Down
14 changes: 13 additions & 1 deletion cidre/src/ns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub use objc_runtime::ExceptionName;
pub mod exception;
pub use exception::set_uncaught_exception_handler;
pub use exception::try_catch;
pub use exception::try_catch_err;
pub use exception::uncaught_exception_handler;
pub use exception::Exception;
pub use exception::UncaughtExceptionHandler;
Expand Down Expand Up @@ -142,7 +143,7 @@ pub use file_manager::FileAttrKey;
pub use file_manager::FileAttrType;
pub use file_manager::FileManager;
pub use file_manager::FileProtectionType;
pub use file_manager::ItemReplacementOpts as FileManagerItemReplacementOptions;
pub use file_manager::ItemReplacementOpts as FileManagerItemReplacementOpts;
pub use file_manager::UrlRelationship;
pub use file_manager::VolumeEnumOpts;

Expand Down Expand Up @@ -211,3 +212,14 @@ mod app;

#[cfg(all(feature = "app", target_os = "macos"))]
pub use app::*;

/// Special Exception or Error type
/// some API can still throw exception even if they
/// return Error
///
/// See av::AudioSession API
#[derive(Debug)]
pub enum ExErr<'ar> {
Ex(&'ar Exception),
Err(&'ar Error),
}
11 changes: 10 additions & 1 deletion cidre/src/ns/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
use crate::{arc, cf, define_cls, define_obj_type, ns, objc};

define_obj_type!(pub Error(ns::Id));
impl<'ear> From<&'ear ns::Error> for ns::ExErr<'ear> {
fn from(value: &'ear ns::Error) -> Self {
Self::Err(value)
}
}

define_obj_type!(
#[doc(alias = "NSError")]
pub Error(ns::Id)
);

impl arc::A<Error> {
#[objc::msg_send(initWithDomain:code:userInfo:)]
Expand Down
13 changes: 13 additions & 0 deletions cidre/src/ns/exception.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,19 @@ where
}
}

impl<'ear> From<&'ear ns::Exception> for ns::ExErr<'ear> {
fn from(value: &'ear ns::Exception) -> Self {
Self::Ex(value)
}
}

pub fn try_catch_err<'ar, F, R>(f: F) -> Result<R, ns::ExErr<'ar>>
where
F: FnOnce() -> Result<R, &'ar ns::Error>,
{
Ok(try_catch(f)??)
}

#[cfg(test)]
mod tests {

Expand Down

0 comments on commit 72628a0

Please sign in to comment.