//! This file has been automatically generated by `objc2`'s `header-translator`.
//! DO NOT EDIT
use core::ffi::*;
use core::ptr::NonNull;
use objc2::__framework_prelude::*;
use objc2_foundation::*;

use crate::*;

extern_class!(
    /// [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avaudiosession?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVAudioSession;
);

unsafe impl Send for AVAudioSession {}

unsafe impl Sync for AVAudioSession {}

extern_conformance!(
    unsafe impl NSObjectProtocol for AVAudioSession {}
);

impl AVAudioSession {
    extern_methods!(
        /// Return singleton instance.
        #[unsafe(method(sharedInstance))]
        #[unsafe(method_family = none)]
        pub unsafe fn sharedInstance() -> Retained<AVAudioSession>;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Get the list of categories available on the device.  Certain categories may be unavailable on
        /// particular devices.  For example, AVAudioSessionCategoryRecord will not be available on devices
        /// that have no support for audio input.
        ///
        /// This property is not atomic.
        ///
        /// # Safety
        ///
        /// This might not be thread-safe.
        #[unsafe(method(availableCategories))]
        #[unsafe(method_family = none)]
        pub unsafe fn availableCategories(&self) -> Retained<NSArray<AVAudioSessionCategory>>;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Set session category.
        #[unsafe(method(setCategory:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setCategory_error(
            &self,
            category: &AVAudioSessionCategory,
        ) -> Result<(), Retained<NSError>>;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Set session category with options.
        #[unsafe(method(setCategory:withOptions:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setCategory_withOptions_error(
            &self,
            category: &AVAudioSessionCategory,
            options: AVAudioSessionCategoryOptions,
        ) -> Result<(), Retained<NSError>>;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Set session category and mode with options.
        #[unsafe(method(setCategory:mode:options:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setCategory_mode_options_error(
            &self,
            category: &AVAudioSessionCategory,
            mode: &AVAudioSessionMode,
            options: AVAudioSessionCategoryOptions,
        ) -> Result<(), Retained<NSError>>;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Set session category, mode, routing sharing policy, and options.
        ///
        /// Use of the long-form route sharing policy is only valid in conjunction with a limited set of
        /// category, mode, and option values.
        ///
        /// Allowed categories: AVAudioSessionCategoryPlayback.
        ///
        /// Allowed modes: AVAudioSessionModeDefault, AVAudioSessionModeMoviePlayback,
        /// AVAudioSessionModeSpokenAudio.
        ///
        /// Allowed options: None. Options are allowed when changing the routing policy back to Default,
        /// however.
        #[unsafe(method(setCategory:mode:routeSharingPolicy:options:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setCategory_mode_routeSharingPolicy_options_error(
            &self,
            category: &AVAudioSessionCategory,
            mode: &AVAudioSessionMode,
            policy: AVAudioSessionRouteSharingPolicy,
            options: AVAudioSessionCategoryOptions,
        ) -> Result<(), Retained<NSError>>;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Get session category.
        /// Examples: AVAudioSessionCategoryRecord, AVAudioSessionCategoryPlayAndRecord, etc.
        #[unsafe(method(category))]
        #[unsafe(method_family = none)]
        pub unsafe fn category(&self) -> Retained<AVAudioSessionCategory>;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Get the current set of AVAudioSessionCategoryOptions.
        #[unsafe(method(categoryOptions))]
        #[unsafe(method_family = none)]
        pub unsafe fn categoryOptions(&self) -> AVAudioSessionCategoryOptions;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Get the route sharing policy.
        ///
        /// See AVAudioSessionRouteSharingPolicy for a description of the available policies.
        /// See setCategory:mode:routeSharingPolicy:options:error: for additional discussion.
        #[unsafe(method(routeSharingPolicy))]
        #[unsafe(method_family = none)]
        pub unsafe fn routeSharingPolicy(&self) -> AVAudioSessionRouteSharingPolicy;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Get the list of modes available on the device.  Certain modes may be unavailable on particular
        /// devices.  For example, AVAudioSessionModeVideoRecording will not be available on devices that
        /// have no support for recording video.
        #[unsafe(method(availableModes))]
        #[unsafe(method_family = none)]
        pub unsafe fn availableModes(&self) -> Retained<NSArray<AVAudioSessionMode>>;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Set the session's mode.
        ///
        /// Modes modify the audio category in order to introduce behavior that is tailored to the specific
        /// use of audio within an application. Examples:  AVAudioSessionModeVideoRecording,
        /// AVAudioSessionModeVoiceChat, AVAudioSessionModeMeasurement, etc.
        #[unsafe(method(setMode:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setMode_error(
            &self,
            mode: &AVAudioSessionMode,
        ) -> Result<(), Retained<NSError>>;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Get the session's mode.
        #[unsafe(method(mode))]
        #[unsafe(method_family = none)]
        pub unsafe fn mode(&self) -> Retained<AVAudioSessionMode>;

        /// Set allowHapticsAndSystemSoundsDuringRecording to YES in order to allow system sounds and haptics to play while the session is actively using audio input.
        /// Default value is NO.
        #[unsafe(method(setAllowHapticsAndSystemSoundsDuringRecording:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setAllowHapticsAndSystemSoundsDuringRecording_error(
            &self,
            in_value: bool,
        ) -> Result<(), Retained<NSError>>;

        /// Whether system sounds and haptics can play while the session is actively using audio input.
        #[unsafe(method(allowHapticsAndSystemSoundsDuringRecording))]
        #[unsafe(method_family = none)]
        pub unsafe fn allowHapticsAndSystemSoundsDuringRecording(&self) -> bool;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Returns an enum indicating whether the user has granted or denied permission to record, or has
        /// not been asked
        #[deprecated = "Please use AVAudioApplication recordPermission"]
        #[unsafe(method(recordPermission))]
        #[unsafe(method_family = none)]
        pub unsafe fn recordPermission(&self) -> AVAudioSessionRecordPermission;

        #[cfg(feature = "block2")]
        /// Checks to see if calling process has permission to record audio.
        ///
        /// The 'response' block will be called immediately if permission has already been granted or
        /// denied.  Otherwise, it presents a dialog to notify the user and allow them to choose, and calls
        /// the block once the UI has been dismissed.  'granted' indicates whether permission has been
        /// granted. Note that the block may be called in a different thread context.
        #[deprecated = "Please use AVAudioApplication requestRecordPermissionWithCompletionHandler"]
        #[unsafe(method(requestRecordPermission:))]
        #[unsafe(method_family = none)]
        pub unsafe fn requestRecordPermission(&self, response: &block2::DynBlock<dyn Fn(Bool)>);

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Use this method to temporarily override the output to built-in speaker.
        ///
        /// This method is only valid for a session using PlayAndRecord category. This change remains in
        /// effect only until the current route changes or you call this method again with the
        /// AVAudioSessionPortOverrideNone option. Sessions using PlayAndRecord category that always want to
        /// prefer the built-in speaker output over the receiver, should use
        /// AVAudioSessionCategoryOptionDefaultToSpeaker instead.
        #[unsafe(method(overrideOutputAudioPort:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn overrideOutputAudioPort_error(
            &self,
            port_override: AVAudioSessionPortOverride,
        ) -> Result<(), Retained<NSError>>;

        #[cfg(feature = "AVAudioSessionRoute")]
        /// Select a preferred input port for audio routing.
        ///
        /// If the input port is already part of the current audio route, this will have no effect.
        /// Otherwise, selecting an input port for routing will initiate a route change to use the preferred
        /// input port. Setting a nil value will clear the preference.
        #[unsafe(method(setPreferredInput:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPreferredInput_error(
            &self,
            in_port: Option<&AVAudioSessionPortDescription>,
        ) -> Result<(), Retained<NSError>>;

        #[cfg(feature = "AVAudioSessionRoute")]
        /// Get the preferred input port.  Will be nil if no preference has been set.
        #[unsafe(method(preferredInput))]
        #[unsafe(method_family = none)]
        pub unsafe fn preferredInput(&self) -> Option<Retained<AVAudioSessionPortDescription>>;

        /// Set ringtone and alert interruption preference.
        ///
        /// Inform the system when the session prefers to not be interrupted by
        /// ringtones and alerts. By setting this property to YES, clients will not be interrupted
        /// by incoming call notifications and other alerts. Starting in iOS 14.0, users can set a global
        /// preference for incoming call display style to "Banner" or "Full Screen". With "Banner" display style,
        /// if below property is set to YES then system audio will be silenced. Thus, clients will not be interrupted
        /// on incoming call notification and user will have opportunity to accept or decline the call. If call is declined,
        /// the session will not be interrupted, but if user accepts the incoming call, the session will be interrupted.
        /// With  display style set as "Full Screen", below property will have no effect and clients will be
        /// interrupted by incoming calls. Apps that record audio and/or video and apps that are used for
        /// music performance are candidates for using this feature.
        #[unsafe(method(setPrefersNoInterruptionsFromSystemAlerts:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPrefersNoInterruptionsFromSystemAlerts_error(
            &self,
            in_value: bool,
        ) -> Result<(), Retained<NSError>>;

        /// This property is not atomic.
        ///
        /// # Safety
        ///
        /// This might not be thread-safe.
        #[unsafe(method(prefersNoInterruptionsFromSystemAlerts))]
        #[unsafe(method_family = none)]
        pub unsafe fn prefersNoInterruptionsFromSystemAlerts(&self) -> bool;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Get the currently resolved rendering mode to badge content appropriately.
        /// Clients should use this property to determine what to badge content as.
        #[unsafe(method(renderingMode))]
        #[unsafe(method_family = none)]
        pub unsafe fn renderingMode(&self) -> AVAudioSessionRenderingMode;

        /// Set a preference to enable echo cancelled input on supported hardware
        ///
        /// Applications might want to record the built-in microphone's input while also playing audio out via the built-in speaker.
        /// Enabling echo cancelled input is useful when the application needs the input signal to be clear of any echoes
        /// from the audio playing out of the built-in speaker.
        ///
        /// Audio sessions using Voice Processor don't need this option as echo cancellation is implicitly applied for those routes.
        /// The Voice Processor solution is tuned for voice signals, unlike this option, which is tuned for better capture
        /// of wider range of audio signals in the presence of built-in speaker echo.
        ///
        /// This option is valid only when used with AVAudioSessionCategoryPlayAndRecord and AVAudioSessionModeDefault and is only available
        /// on certain 2024 or later iPhone models. Support can be queried using property `isEchoCancelledInputAvailable`.
        /// Other recording sessions might be interrupted if this option is not compatible with sessions that are already recording.
        ///
        /// After an audio session goes active, `isEchoCancelledInputEnabled` property can be queried to check if the option was honored.
        /// Note that the enabled state may change after route changes, e.g. if user plugs in a headset, that route might not support echo cancellation.
        #[unsafe(method(setPrefersEchoCancelledInput:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPrefersEchoCancelledInput_error(
            &self,
            value: bool,
        ) -> Result<(), Retained<NSError>>;

        /// This property is not atomic.
        ///
        /// # Safety
        ///
        /// This might not be thread-safe.
        #[unsafe(method(prefersEchoCancelledInput))]
        #[unsafe(method_family = none)]
        pub unsafe fn prefersEchoCancelledInput(&self) -> bool;

        /// Returns YES if echo cancelled input is successfully enabled on an active session.
        /// Please see `prefersEchoCancelledInput` above for more details.
        ///
        /// This property is not atomic.
        ///
        /// # Safety
        ///
        /// This might not be thread-safe.
        #[unsafe(method(isEchoCancelledInputEnabled))]
        #[unsafe(method_family = none)]
        pub unsafe fn isEchoCancelledInputEnabled(&self) -> bool;

        /// Query whether built-in mic / built-in speaker route supports echo cancellation for the session's given category and mode.
        /// Returns YES if device model supports echo cancellation and the audio category is PlayAndRecord and the mode is Default.
        ///
        /// This property is not atomic.
        ///
        /// # Safety
        ///
        /// This might not be thread-safe.
        #[unsafe(method(isEchoCancelledInputAvailable))]
        #[unsafe(method_family = none)]
        pub unsafe fn isEchoCancelledInputAvailable(&self) -> bool;

        /// Sets a Boolean value to inform the system to mute the session's output audio. The default value is false (unmuted).
        ///
        /// This property is supported with all categories and modes, except for
        /// ``AVAudioSessionCategoryPlayAndRecord`` where it is only supported with ``AVAudioSessionModeDefault``.
        /// Changing the mode to non-default mode with ``AVAudioSessionCategoryPlayAndRecord``
        /// category will cause the session to unmute.
        ///
        /// Changes in output mute state can be observed via ``AVAudioSessionOutputMuteStateChangeNotification``.
        /// If this value is set to true, ``AVAudioSessionUserIntentToUnmuteOutputNotification``
        /// may be sent when a user hints to unmute by changing the volume.
        ///
        /// - Note: This will not mute system sounds and haptics.
        ///
        /// - Parameters:
        /// - `muted`: A Boolean value to set the audio output to the desired muted state.
        /// - `error`: A pointer to an error object. If an error occurs, the framework sets the pointer to an error object that describes the failure.
        #[unsafe(method(setOutputMuted:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setOutputMuted_error(&self, muted: bool) -> Result<(), Retained<NSError>>;

        /// A Boolean value that indicates whether audio output is in a muted state.
        #[unsafe(method(isOutputMuted))]
        #[unsafe(method_family = none)]
        pub unsafe fn isOutputMuted(&self) -> bool;
    );
}

/// Activation.
impl AVAudioSession {
    extern_methods!(
        /// Set the session active or inactive.
        ///
        /// Note that activating an audio session is a synchronous (blocking) operation.
        /// Therefore, we recommend that applications not activate their session from a thread where a long
        /// blocking operation will be problematic.
        /// Apps may activate a AVAudioSessionCategoryPlayback session when another app is hosting a
        /// call (to start a SharePlay activity for example). However, they are not permitted to capture the
        /// microphone of the active call, so attempts to activate a session with category
        /// AVAudioSessionCategoryRecord or AVAudioSessionCategoryPlayAndRecord will fail with error
        /// AVAudioSessionErrorCodeInsufficientPriority.
        /// When deactivating a session, the caller is required to
        /// first stop or pause all running I/Os (e.g. audio queues, players, recorders, converters,
        /// remote I/Os, etc.). Starting in iOS 8, if the session has running I/Os at the time that
        /// deactivation is requested, the session will be deactivated, but the method will return NO and
        /// populate the NSError with the code property set to AVAudioSessionErrorCodeIsBusy to indicate the
        /// misuse of the API. Prior to iOS 8, the session would have remained active if it had running I/Os
        /// at the time of the deactivation request. Starting in iOS 19.0, deactivating while IO is running will
        /// no longer return AVAudioSessionErrorCodeIsBusy.
        #[unsafe(method(setActive:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setActive_error(&self, active: bool) -> Result<(), Retained<NSError>>;

        #[cfg(feature = "AVAudioSessionTypes")]
        #[unsafe(method(setActive:withOptions:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setActive_withOptions_error(
            &self,
            active: bool,
            options: AVAudioSessionSetActiveOptions,
        ) -> Result<(), Retained<NSError>>;

        #[cfg(all(feature = "AVAudioSessionTypes", feature = "block2"))]
        /// Asynchronously activate the session.
        ///
        /// This is a relatively time consuming operation. The completion handler will be called when the
        /// activation completes or if an error occurs while attempting to activate the session. If the
        /// session is configured to use AVAudioSessionRouteSharingPolicyLongFormAudio on watchOS, this
        /// method will also cause a route picker to be presented to the user in cases where an appropriate
        /// output route has not already been selected automatically. watchOS apps using
        /// AVAudioSessionRouteSharingPolicyLongFormAudio should be prepared for this method to fail if no
        /// eligible audio route can be activated or if the user cancels the route picker view.
        #[unsafe(method(activateWithOptions:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn activateWithOptions_completionHandler(
            &self,
            options: AVAudioSessionActivationOptions,
            handler: &block2::DynBlock<dyn Fn(Bool, *mut NSError)>,
        );
    );
}

/// AVAudioSessionHardwareConfiguration.
///
/// this category deals with the set of properties that reflect the current state of
/// audio hardware in the current route.  Applications whose functionality depends on these
/// properties should reevaluate them any time the route changes.
impl AVAudioSession {
    extern_methods!(
        /// The preferred hardware sample rate for the session. The actual sample rate may be different.
        #[unsafe(method(setPreferredSampleRate:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPreferredSampleRate_error(
            &self,
            sample_rate: c_double,
        ) -> Result<(), Retained<NSError>>;

        #[unsafe(method(preferredSampleRate))]
        #[unsafe(method_family = none)]
        pub unsafe fn preferredSampleRate(&self) -> c_double;

        /// The preferred hardware IO buffer duration in seconds. The actual IO buffer duration may be
        /// different.
        #[unsafe(method(setPreferredIOBufferDuration:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPreferredIOBufferDuration_error(
            &self,
            duration: NSTimeInterval,
        ) -> Result<(), Retained<NSError>>;

        #[unsafe(method(preferredIOBufferDuration))]
        #[unsafe(method_family = none)]
        pub unsafe fn preferredIOBufferDuration(&self) -> NSTimeInterval;

        /// Sets the number of input channels that the app would prefer for the current route
        #[unsafe(method(setPreferredInputNumberOfChannels:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPreferredInputNumberOfChannels_error(
            &self,
            count: NSInteger,
        ) -> Result<(), Retained<NSError>>;

        #[unsafe(method(preferredInputNumberOfChannels))]
        #[unsafe(method_family = none)]
        pub unsafe fn preferredInputNumberOfChannels(&self) -> NSInteger;

        /// Sets the number of output channels that the app would prefer for the current route
        #[unsafe(method(setPreferredOutputNumberOfChannels:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPreferredOutputNumberOfChannels_error(
            &self,
            count: NSInteger,
        ) -> Result<(), Retained<NSError>>;

        #[unsafe(method(preferredOutputNumberOfChannels))]
        #[unsafe(method_family = none)]
        pub unsafe fn preferredOutputNumberOfChannels(&self) -> NSInteger;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Sets the preferred input orientation.
        /// The input orientation determines which directions will be left and right
        /// when a built-in mic data source with the AVAudioSessionPolarPatternStereo polar pattern is selected.
        /// Typically, this orientation should match how the user is holding the device while recording, which will match
        /// the application's interface orientation when a single app is on the screen.
        /// The actual input orientation may be different, for example, if another app's session is in control of routing.
        /// The input orientation is independent of the orientation property of an AVAudioSessionDataSourceDescription.
        #[unsafe(method(setPreferredInputOrientation:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPreferredInputOrientation_error(
            &self,
            orientation: AVAudioStereoOrientation,
        ) -> Result<(), Retained<NSError>>;

        #[cfg(feature = "AVAudioSessionTypes")]
        #[unsafe(method(preferredInputOrientation))]
        #[unsafe(method_family = none)]
        pub unsafe fn preferredInputOrientation(&self) -> AVAudioStereoOrientation;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Describes the orientation of the input data source (valid for the built-in mic input data source when a stereo polar pattern is selected).
        #[unsafe(method(inputOrientation))]
        #[unsafe(method_family = none)]
        pub unsafe fn inputOrientation(&self) -> AVAudioStereoOrientation;

        /// Returns the largest number of audio input channels available for the current route
        #[unsafe(method(maximumInputNumberOfChannels))]
        #[unsafe(method_family = none)]
        pub unsafe fn maximumInputNumberOfChannels(&self) -> NSInteger;

        /// Returns the largest number of audio output channels available for the current route
        #[unsafe(method(maximumOutputNumberOfChannels))]
        #[unsafe(method_family = none)]
        pub unsafe fn maximumOutputNumberOfChannels(&self) -> NSInteger;

        /// A value defined over the range [0.0, 1.0], with 0.0 corresponding to the lowest analog
        /// gain setting and 1.0 corresponding to the highest analog gain setting.
        ///
        /// Attempting to set values outside of the defined range will result in the value being "clamped"
        /// to a valid input.  This is a global input gain setting that applies to the current input source
        /// for the entire system. When no applications are using the input gain control, the system will
        /// restore the default input gain setting for the input source.  Note that some audio accessories,
        /// such as USB devices, may not have a default value.  This property is only valid if
        /// inputGainSettable is true.  Note: inputGain is key-value observable.
        #[unsafe(method(setInputGain:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setInputGain_error(&self, gain: c_float) -> Result<(), Retained<NSError>>;

        /// value in range [0.0, 1.0]
        #[unsafe(method(inputGain))]
        #[unsafe(method_family = none)]
        pub unsafe fn inputGain(&self) -> c_float;

        /// True when audio input gain is available.  Some input ports may not provide the ability to set the
        /// input gain, so check this value before attempting to set input gain.
        #[unsafe(method(isInputGainSettable))]
        #[unsafe(method_family = none)]
        pub unsafe fn isInputGainSettable(&self) -> bool;

        /// True if input hardware is available. Key-value observable.
        #[unsafe(method(isInputAvailable))]
        #[unsafe(method_family = none)]
        pub unsafe fn isInputAvailable(&self) -> bool;

        #[cfg(feature = "AVAudioSessionRoute")]
        /// DataSource methods are for use with routes that support input or output data source
        /// selection.
        ///
        /// If the attached accessory supports data source selection, the data source properties/methods
        /// provide for discovery and selection of input and/or output data sources. Note that the
        /// properties and methods for data source selection below are equivalent to the properties and
        /// methods on AVAudioSessionPortDescription. The methods below only apply to the currently routed
        /// ports.
        ///
        /// Key-value observable.
        #[unsafe(method(inputDataSources))]
        #[unsafe(method_family = none)]
        pub unsafe fn inputDataSources(
            &self,
        ) -> Option<Retained<NSArray<AVAudioSessionDataSourceDescription>>>;

        #[cfg(feature = "AVAudioSessionRoute")]
        /// Obtain the currently selected input data source.  Will be nil if no data sources are available.
        #[unsafe(method(inputDataSource))]
        #[unsafe(method_family = none)]
        pub unsafe fn inputDataSource(
            &self,
        ) -> Option<Retained<AVAudioSessionDataSourceDescription>>;

        #[cfg(feature = "AVAudioSessionRoute")]
        /// Select a new input data source. Setting a nil value will clear the data source preference.
        #[unsafe(method(setInputDataSource:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setInputDataSource_error(
            &self,
            data_source: Option<&AVAudioSessionDataSourceDescription>,
        ) -> Result<(), Retained<NSError>>;

        #[cfg(feature = "AVAudioSessionRoute")]
        /// See inputDataSources for background. Key-value observable.
        #[unsafe(method(outputDataSources))]
        #[unsafe(method_family = none)]
        pub unsafe fn outputDataSources(
            &self,
        ) -> Option<Retained<NSArray<AVAudioSessionDataSourceDescription>>>;

        #[cfg(feature = "AVAudioSessionRoute")]
        /// Obtain the currently selected output data source.  Will be nil if no data sources are available.
        #[unsafe(method(outputDataSource))]
        #[unsafe(method_family = none)]
        pub unsafe fn outputDataSource(
            &self,
        ) -> Option<Retained<AVAudioSessionDataSourceDescription>>;

        #[cfg(feature = "AVAudioSessionRoute")]
        /// Select a new output data source. Setting a nil value will clear the data source preference.
        #[unsafe(method(setOutputDataSource:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setOutputDataSource_error(
            &self,
            data_source: Option<&AVAudioSessionDataSourceDescription>,
        ) -> Result<(), Retained<NSError>>;

        /// The current hardware sample rate. Is key-value observable (starting iOS 18.0).
        #[unsafe(method(sampleRate))]
        #[unsafe(method_family = none)]
        pub unsafe fn sampleRate(&self) -> c_double;

        /// The current number of hardware input channels. Is key-value observable.
        #[unsafe(method(inputNumberOfChannels))]
        #[unsafe(method_family = none)]
        pub unsafe fn inputNumberOfChannels(&self) -> NSInteger;

        /// The current number of hardware output channels. Is key-value observable.
        #[unsafe(method(outputNumberOfChannels))]
        #[unsafe(method_family = none)]
        pub unsafe fn outputNumberOfChannels(&self) -> NSInteger;

        /// The current hardware input latency in seconds.
        #[unsafe(method(inputLatency))]
        #[unsafe(method_family = none)]
        pub unsafe fn inputLatency(&self) -> NSTimeInterval;

        /// The current hardware output latency in seconds.
        #[unsafe(method(outputLatency))]
        #[unsafe(method_family = none)]
        pub unsafe fn outputLatency(&self) -> NSTimeInterval;

        /// The current hardware IO buffer duration in seconds. Is key-value observable.
        #[unsafe(method(IOBufferDuration))]
        #[unsafe(method_family = none)]
        pub unsafe fn IOBufferDuration(&self) -> NSTimeInterval;

        #[cfg(feature = "AVAudioChannelLayout")]
        /// Get an array of channel layouts that the current route supports.
        /// This property is only supported when the output is routed to ports of type AVAudioSessionPortCarAudio or AVAudioSessionPortAirPlay
        /// Otherwise, an empty array will be returned. Note that this will return an empty array if session is inactive.
        /// Clients should listen to AVAudioSessionRenderingCapabilitiesChangeNotification to be notified when this changes.
        #[unsafe(method(supportedOutputChannelLayouts))]
        #[unsafe(method_family = none)]
        pub unsafe fn supportedOutputChannelLayouts(
            &self,
        ) -> Retained<NSArray<AVAudioChannelLayout>>;
    );
}

/// Observation.
impl AVAudioSession {
    extern_methods!(
        /// True when another application is playing audio.
        ///
        /// Note: As of iOS 8.0, Apple recommends that most applications use
        /// secondaryAudioShouldBeSilencedHint instead of this property. The otherAudioPlaying property
        /// will be true if any other audio (including audio from an app using
        /// AVAudioSessionCategoryAmbient) is playing, whereas the secondaryAudioShouldBeSilencedHint
        /// property is more restrictive in its consideration of whether primary audio from another
        /// application is playing.
        #[unsafe(method(isOtherAudioPlaying))]
        #[unsafe(method_family = none)]
        pub unsafe fn isOtherAudioPlaying(&self) -> bool;

        /// True when another application with a non-mixable audio session is playing audio.
        ///
        /// Applications may use this property as a hint to silence audio that is secondary to the
        /// functionality of the application. For example, a game app using AVAudioSessionCategoryAmbient
        /// may use this property to decide to mute its soundtrack while leaving its sound effects unmuted.
        /// Note: This property is closely related to AVAudioSessionSilenceSecondaryAudioHintNotification.
        #[unsafe(method(secondaryAudioShouldBeSilencedHint))]
        #[unsafe(method_family = none)]
        pub unsafe fn secondaryAudioShouldBeSilencedHint(&self) -> bool;

        /// The current output volume. Value in range [0.0, 1.0]. Is key-value observable.
        #[unsafe(method(outputVolume))]
        #[unsafe(method_family = none)]
        pub unsafe fn outputVolume(&self) -> c_float;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// The prompt style is a hint to sessions using AVAudioSessionModeVoicePrompt to alter the type of
        /// prompts they issue in response to other audio activity on the system, such as Siri and phone
        /// calls. This property is key-value observable.
        #[unsafe(method(promptStyle))]
        #[unsafe(method_family = none)]
        pub unsafe fn promptStyle(&self) -> AVAudioSessionPromptStyle;
    );
}

/// RoutingConfiguration.
impl AVAudioSession {
    extern_methods!(
        #[cfg(feature = "AVAudioSessionRoute")]
        /// Get the set of input ports that are available for routing.
        ///
        /// Note that this property only applies to the session's current category and mode. For
        /// example, if the session's current category is AVAudioSessionCategoryPlayback, there will be
        /// no available inputs.
        ///
        /// On iOS, clients can listen to AVAudioSessionAvailableInputsChangeNotification to
        /// be notified when this changes.
        #[unsafe(method(availableInputs))]
        #[unsafe(method_family = none)]
        pub unsafe fn availableInputs(
            &self,
        ) -> Option<Retained<NSArray<AVAudioSessionPortDescription>>>;

        #[cfg(feature = "AVAudioSessionRoute")]
        /// A description of the current route, consisting of zero or more input ports and zero or more
        /// output ports
        #[unsafe(method(currentRoute))]
        #[unsafe(method_family = none)]
        pub unsafe fn currentRoute(&self) -> Retained<AVAudioSessionRouteDescription>;

        #[cfg(feature = "AVAudioSessionTypes")]
        /// Controls whether audio input and output are aggregated. Only valid in combination with
        /// AVAudioSessionCategoryPlayAndRecord or AVAudioSessionCategoryMultiRoute.
        ///
        /// See the AVAudioSessionIOType documentation for a more detailed explanation of why a client may
        /// want to change the IO type.
        #[unsafe(method(setAggregatedIOPreference:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setAggregatedIOPreference_error(
            &self,
            in_io_type: AVAudioSessionIOType,
        ) -> Result<(), Retained<NSError>>;

        /// Set YES to inform the system if the app can supply multichannel audio content.
        /// Default value is NO. This property is intended to be used by 'Now Playing' applications.
        /// See https://developer.apple.com/documentation/mediaplayer/becoming_a_now_playable_app for more information
        /// about what it means to be a 'Now Playing' application. Typically 'Now Playing' applications will also use
        /// AVAudioSessionRouteSharingPolicyLongFormAudio or AVAudioSessionRouteSharingPolicyLongFormVideo.
        #[unsafe(method(setSupportsMultichannelContent:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setSupportsMultichannelContent_error(
            &self,
            in_value: bool,
        ) -> Result<(), Retained<NSError>>;

        #[unsafe(method(supportsMultichannelContent))]
        #[unsafe(method_family = none)]
        pub unsafe fn supportsMultichannelContent(&self) -> bool;

        /// Use this method to opt in or opt out of interruption on route disconnect policy.
        ///
        /// As described in the Audio Session Programming Guide, most media playback apps are expected
        /// to pause playback if the route change reason is AVAudioSessionRouteChangeReasonOldDeviceUnavailable.
        ///
        /// Starting in iOS 17, by default Now Playing sessions will be interrupted if they are active
        /// when a route change occurs because of a disconnect event. All other sessions will not be
        /// interrupted due to a disconnect event.
        #[unsafe(method(setPrefersInterruptionOnRouteDisconnect:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPrefersInterruptionOnRouteDisconnect_error(
            &self,
            in_value: bool,
        ) -> Result<(), Retained<NSError>>;

        /// Indicates if session will be interrupted on route disconnect.
        #[unsafe(method(prefersInterruptionOnRouteDisconnect))]
        #[unsafe(method_family = none)]
        pub unsafe fn prefersInterruptionOnRouteDisconnect(&self) -> bool;
    );
}

/// MicrophoneInjection.
impl AVAudioSession {
    extern_methods!(
        #[cfg(feature = "AVAudioSessionTypes")]
        /// Set the preferred form of audio injection into another app's input stream
        /// See AVAudioSessionMicrophoneInjectionMode for available modes
        #[unsafe(method(setPreferredMicrophoneInjectionMode:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPreferredMicrophoneInjectionMode_error(
            &self,
            in_value: AVAudioSessionMicrophoneInjectionMode,
        ) -> Result<(), Retained<NSError>>;

        #[cfg(feature = "AVAudioSessionTypes")]
        #[unsafe(method(preferredMicrophoneInjectionMode))]
        #[unsafe(method_family = none)]
        pub unsafe fn preferredMicrophoneInjectionMode(
            &self,
        ) -> AVAudioSessionMicrophoneInjectionMode;

        /// Indicates if microphone injection is available.
        /// Observe AVAudioSessionMicrophoneInjectionCapabilitiesChangeNotification for changes to this property
        #[unsafe(method(isMicrophoneInjectionAvailable))]
        #[unsafe(method_family = none)]
        pub unsafe fn isMicrophoneInjectionAvailable(&self) -> bool;
    );
}
