//! 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 crate::*;

/// Options controlling buffer scheduling.
///
///
/// The buffer loops indefinitely.
///
/// The buffer interrupts any buffer already playing.
///
/// The buffer interrupts any buffer already playing, at its loop point.
///
/// API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0))
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avaudioplayernodebufferoptions?language=objc)
// NS_OPTIONS
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct AVAudioPlayerNodeBufferOptions(pub NSUInteger);
bitflags::bitflags! {
    impl AVAudioPlayerNodeBufferOptions: NSUInteger {
        #[doc(alias = "AVAudioPlayerNodeBufferLoops")]
        const Loops = 1<<0;
        #[doc(alias = "AVAudioPlayerNodeBufferInterrupts")]
        const Interrupts = 1<<1;
        #[doc(alias = "AVAudioPlayerNodeBufferInterruptsAtLoop")]
        const InterruptsAtLoop = 1<<2;
    }
}

unsafe impl Encode for AVAudioPlayerNodeBufferOptions {
    const ENCODING: Encoding = NSUInteger::ENCODING;
}

unsafe impl RefEncode for AVAudioPlayerNodeBufferOptions {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// Specifies when the completion handler must be invoked.
///
///
/// The buffer or file data has been consumed by the player.
///
/// The buffer or file data has been rendered (i.e. output) by the player. This
/// does not account for any signal processing latencies downstream of the player
/// in the engine (see `AVAudioNode(outputPresentationLatency)`).
///
/// Applicable only when the engine is rendering to/from an audio device.
/// The buffer or file has finished playing. This accounts for both (small) signal
/// processing latencies downstream of the player in the engine, as well as
/// (possibly significant) latency in the audio playback device.
///
/// API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avaudioplayernodecompletioncallbacktype?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct AVAudioPlayerNodeCompletionCallbackType(pub NSInteger);
impl AVAudioPlayerNodeCompletionCallbackType {
    #[doc(alias = "AVAudioPlayerNodeCompletionDataConsumed")]
    pub const DataConsumed: Self = Self(0);
    #[doc(alias = "AVAudioPlayerNodeCompletionDataRendered")]
    pub const DataRendered: Self = Self(1);
    #[doc(alias = "AVAudioPlayerNodeCompletionDataPlayedBack")]
    pub const DataPlayedBack: Self = Self(2);
}

unsafe impl Encode for AVAudioPlayerNodeCompletionCallbackType {
    const ENCODING: Encoding = NSInteger::ENCODING;
}

unsafe impl RefEncode for AVAudioPlayerNodeCompletionCallbackType {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// Buffer or file completion callback handler.
///
/// Parameter `callbackType`: Indicates the type of buffer or file completion when the callback is invoked.
///
/// AVAudioPlayerNode issues this callback to inform the client about the specific type of
/// buffer or file completion. See `AVAudioPlayerNodeCompletionCallbackType` for more details.
///
/// Note that the `AVAudioNodeCompletionHandler` callback from some of the player's scheduling
/// methods (e.g. `scheduleBuffer:completionHandler:`) is equivalent to the
/// AVAudioPlayerNodeCompletionHandler callback for `AVAudioPlayerNodeCompletionDataConsumed`.
///
/// In general the callbacks arrive on a non-main thread and it is the client's responsibility
/// to handle them in a thread-safe manner.
///
/// Setting or getting properties on an AVAudioPlayerNode while the AVAudioEngine is running requires
/// some synchronisation between the calling threads internally. If you want to call player node API within this
/// completion handler block, calls should be synchronised to the same thread/queue.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avaudioplayernodecompletionhandler?language=objc)
#[cfg(feature = "block2")]
pub type AVAudioPlayerNodeCompletionHandler =
    *mut block2::DynBlock<dyn Fn(AVAudioPlayerNodeCompletionCallbackType)>;

extern_class!(
    /// Play buffers or segments of audio files.
    ///
    /// AVAudioPlayerNode supports scheduling the playback of `AVAudioBuffer` instances,
    /// or segments of audio files opened via `AVAudioFile`. Buffers and segments may be
    /// scheduled at specific points in time, or to play immediately following preceding segments.
    ///
    /// FORMATS
    ///
    /// Normally, you will want to configure the node's output format with the same number of
    /// channels as are in the files and buffers to be played. Otherwise, channels will be dropped
    /// or added as required. It is usually better to use an `AVAudioMixerNode` to
    /// do this.
    ///
    /// Similarly, when playing file segments, the node will sample rate convert if necessary, but
    /// it is often preferable to configure the node's output sample rate to match that of the file(s)
    /// and use a mixer to perform the rate conversion.
    ///
    /// When playing buffers, there is an implicit assumption that the buffers are at the same
    /// sample rate as the node's output format.
    ///
    /// TIMELINES
    ///
    /// The usual `AVAudioNode` sample times (as observed by `lastRenderTime`)
    /// have an arbitrary zero point. AVAudioPlayerNode superimposes a second "player timeline" on
    /// top of this, to reflect when the player was started, and intervals during which it was
    /// paused. The methods `nodeTimeForPlayerTime:` and `playerTimeForNodeTime:`
    /// convert between the two.
    ///
    /// This class' `stop` method unschedules all previously scheduled buffers and
    /// file segments, and returns the player timeline to sample time 0.
    ///
    /// TIMESTAMPS
    ///
    /// The "schedule" methods all take an `AVAudioTime` "when" parameter. This is
    /// interpreted as follows:
    ///
    /// 1. nil:
    /// - if there have been previous commands, the new one is played immediately following the
    /// last one.
    /// - otherwise, if the node is playing, the event is played in the very near future.
    /// - otherwise, the command is played at sample time 0.
    /// 2. sample time:
    /// - relative to the node's start time (which begins at 0 when the node is started).
    /// 3. host time:
    /// - ignored unless the sample time is invalid when the engine is rendering to an audio
    /// device.
    /// - ignored in manual rendering mode.
    ///
    /// ERRORS
    ///
    /// The "schedule" methods can fail if:
    ///
    /// 1. a buffer's channel count does not match that of the node's output format.
    /// 2. a file can't be accessed.
    /// 3. an AVAudioTime specifies neither a valid sample time or host time.
    /// 4. a segment's start frame or frame count is negative.
    ///
    /// BUFFER/FILE COMPLETION HANDLERS
    ///
    /// The buffer or file completion handlers (see scheduling methods) are a means to schedule
    /// more data if available on the player node. See `AVAudioPlayerNodeCompletionCallbackType`
    /// for details on the different buffer/file completion callback types.
    ///
    /// Note that a player should not be stopped from within a completion handler callback because
    /// it can deadlock while trying to unschedule previously scheduled buffers.
    ///
    /// OFFLINE RENDERING
    ///
    /// When a player node is used with the engine operating in the manual rendering mode, the
    /// buffer/file completion handlers, `lastRenderTime` and the latencies (`latency` and
    /// `outputPresentationLatency`) can be used to track how much data the player has rendered and
    /// how much more data is left to render.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avaudioplayernode?language=objc)
    #[unsafe(super(AVAudioNode, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    #[cfg(feature = "AVAudioNode")]
    pub struct AVAudioPlayerNode;
);

#[cfg(all(feature = "AVAudioMixing", feature = "AVAudioNode"))]
extern_conformance!(
    unsafe impl AVAudio3DMixing for AVAudioPlayerNode {}
);

#[cfg(all(feature = "AVAudioMixing", feature = "AVAudioNode"))]
extern_conformance!(
    unsafe impl AVAudioMixing for AVAudioPlayerNode {}
);

#[cfg(all(feature = "AVAudioMixing", feature = "AVAudioNode"))]
extern_conformance!(
    unsafe impl AVAudioStereoMixing for AVAudioPlayerNode {}
);

#[cfg(feature = "AVAudioNode")]
extern_conformance!(
    unsafe impl NSObjectProtocol for AVAudioPlayerNode {}
);

#[cfg(feature = "AVAudioNode")]
impl AVAudioPlayerNode {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[cfg(all(
            feature = "AVAudioBuffer",
            feature = "AVAudioTypes",
            feature = "block2"
        ))]
        /// Schedule playing samples from an AVAudioBuffer.
        ///
        /// Parameter `buffer`: the buffer to play
        ///
        /// Parameter `completionHandler`: called after the buffer has been consumed by the player or the player is stopped. may be nil.
        ///
        /// Schedules the buffer to be played following any previously scheduled commands.
        ///
        /// It is possible for the completionHandler to be called before rendering begins
        /// or before the buffer is played completely.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleBuffer:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleBuffer_completionHandler(
            &self,
            buffer: &AVAudioPCMBuffer,
            completion_handler: AVAudioNodeCompletionHandler,
        );

        #[cfg(all(feature = "AVAudioBuffer", feature = "block2"))]
        /// Schedule playing samples from an AVAudioBuffer.
        ///
        /// Parameter `buffer`: the buffer to play
        ///
        /// Parameter `callbackType`: option to specify when the completion handler must be called
        ///
        /// Parameter `completionHandler`: called after the buffer has been consumed by the player or has finished playing back or
        /// the player is stopped. may be nil.
        ///
        /// Schedules the buffer to be played following any previously scheduled commands.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleBuffer:completionCallbackType:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleBuffer_completionCallbackType_completionHandler(
            &self,
            buffer: &AVAudioPCMBuffer,
            callback_type: AVAudioPlayerNodeCompletionCallbackType,
            completion_handler: AVAudioPlayerNodeCompletionHandler,
        );

        #[cfg(all(
            feature = "AVAudioBuffer",
            feature = "AVAudioTime",
            feature = "AVAudioTypes",
            feature = "block2"
        ))]
        /// Schedule playing samples from an AVAudioBuffer.
        ///
        /// Parameter `buffer`: the buffer to play
        ///
        /// Parameter `when`: the time at which to play the buffer. see the discussion of timestamps, above.
        ///
        /// Parameter `options`: options for looping, interrupting other buffers, etc.
        ///
        /// Parameter `completionHandler`: called after the buffer has been consumed by the player or the player is stopped. may be nil.
        ///
        /// It is possible for the completionHandler to be called before rendering begins
        /// or before the buffer is played completely.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleBuffer:atTime:options:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleBuffer_atTime_options_completionHandler(
            &self,
            buffer: &AVAudioPCMBuffer,
            when: Option<&AVAudioTime>,
            options: AVAudioPlayerNodeBufferOptions,
            completion_handler: AVAudioNodeCompletionHandler,
        );

        #[cfg(all(feature = "AVAudioBuffer", feature = "AVAudioTime", feature = "block2"))]
        /// Schedule playing samples from an AVAudioBuffer.
        ///
        /// Parameter `buffer`: the buffer to play
        ///
        /// Parameter `when`: the time at which to play the buffer. see the discussion of timestamps, above.
        ///
        /// Parameter `options`: options for looping, interrupting other buffers, etc.
        ///
        /// Parameter `callbackType`: option to specify when the completion handler must be called
        ///
        /// Parameter `completionHandler`: called after the buffer has been consumed by the player or has finished playing back or
        /// the player is stopped. may be nil.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleBuffer:atTime:options:completionCallbackType:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleBuffer_atTime_options_completionCallbackType_completionHandler(
            &self,
            buffer: &AVAudioPCMBuffer,
            when: Option<&AVAudioTime>,
            options: AVAudioPlayerNodeBufferOptions,
            callback_type: AVAudioPlayerNodeCompletionCallbackType,
            completion_handler: AVAudioPlayerNodeCompletionHandler,
        );

        #[cfg(all(
            feature = "AVAudioFile",
            feature = "AVAudioTime",
            feature = "AVAudioTypes",
            feature = "block2"
        ))]
        /// Schedule playing of an entire audio file.
        ///
        /// Parameter `file`: the file to play
        ///
        /// Parameter `when`: the time at which to play the file. see the discussion of timestamps, above.
        ///
        /// Parameter `completionHandler`: called after the file has been consumed by the player or the player is stopped. may be nil.
        ///
        /// It is possible for the completionHandler to be called before rendering begins
        /// or before the file is played completely.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleFile:atTime:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleFile_atTime_completionHandler(
            &self,
            file: &AVAudioFile,
            when: Option<&AVAudioTime>,
            completion_handler: AVAudioNodeCompletionHandler,
        );

        #[cfg(all(feature = "AVAudioFile", feature = "AVAudioTime", feature = "block2"))]
        /// Schedule playing of an entire audio file.
        ///
        /// Parameter `file`: the file to play
        ///
        /// Parameter `when`: the time at which to play the file. see the discussion of timestamps, above.
        ///
        /// Parameter `callbackType`: option to specify when the completion handler must be called
        ///
        /// Parameter `completionHandler`: called after the file has been consumed by the player or has finished playing back or
        /// the player is stopped. may be nil.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleFile:atTime:completionCallbackType:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleFile_atTime_completionCallbackType_completionHandler(
            &self,
            file: &AVAudioFile,
            when: Option<&AVAudioTime>,
            callback_type: AVAudioPlayerNodeCompletionCallbackType,
            completion_handler: AVAudioPlayerNodeCompletionHandler,
        );

        #[cfg(all(
            feature = "AVAudioFile",
            feature = "AVAudioTime",
            feature = "AVAudioTypes",
            feature = "block2"
        ))]
        /// Schedule playing a segment of an audio file.
        ///
        /// Parameter `file`: the file to play
        ///
        /// Parameter `startFrame`: the starting frame position in the stream
        ///
        /// Parameter `numberFrames`: the number of frames to play
        ///
        /// Parameter `when`: the time at which to play the region. see the discussion of timestamps, above.
        ///
        /// Parameter `completionHandler`: called after the segment has been consumed by the player or the player is stopped. may be nil.
        ///
        /// It is possible for the completionHandler to be called before rendering begins
        /// or before the segment is played completely.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleSegment:startingFrame:frameCount:atTime:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleSegment_startingFrame_frameCount_atTime_completionHandler(
            &self,
            file: &AVAudioFile,
            start_frame: AVAudioFramePosition,
            number_frames: AVAudioFrameCount,
            when: Option<&AVAudioTime>,
            completion_handler: AVAudioNodeCompletionHandler,
        );

        #[cfg(all(
            feature = "AVAudioFile",
            feature = "AVAudioTime",
            feature = "AVAudioTypes",
            feature = "block2"
        ))]
        /// Schedule playing a segment of an audio file.
        ///
        /// Parameter `file`: the file to play
        ///
        /// Parameter `startFrame`: the starting frame position in the stream
        ///
        /// Parameter `numberFrames`: the number of frames to play
        ///
        /// Parameter `when`: the time at which to play the region. see the discussion of timestamps, above.
        ///
        /// Parameter `callbackType`: option to specify when the completion handler must be called
        ///
        /// Parameter `completionHandler`: called after the segment has been consumed by the player or has finished playing back or
        /// the player is stopped. may be nil.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleSegment:startingFrame:frameCount:atTime:completionCallbackType:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleSegment_startingFrame_frameCount_atTime_completionCallbackType_completionHandler(
            &self,
            file: &AVAudioFile,
            start_frame: AVAudioFramePosition,
            number_frames: AVAudioFrameCount,
            when: Option<&AVAudioTime>,
            callback_type: AVAudioPlayerNodeCompletionCallbackType,
            completion_handler: AVAudioPlayerNodeCompletionHandler,
        );

        /// Clear all of the node's previously scheduled events and stop playback.
        ///
        /// All of the node's previously scheduled events are cleared, including any that are in the
        /// middle of playing. The node's sample time (and therefore the times to which new events are
        /// to be scheduled) is reset to 0, and will not proceed until the node is started again (via
        /// play or playAtTime).
        ///
        /// Note that pausing or stopping all the players connected to an engine does not pause or stop
        /// the engine or the underlying hardware. The engine must be explicitly paused or stopped for
        /// the hardware to stop.
        #[unsafe(method(stop))]
        #[unsafe(method_family = none)]
        pub unsafe fn stop(&self);

        #[cfg(feature = "AVAudioTypes")]
        /// Prepares previously scheduled file regions or buffers for playback.
        ///
        /// Parameter `frameCount`: The number of sample frames of data to be prepared before returning.
        #[unsafe(method(prepareWithFrameCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn prepareWithFrameCount(&self, frame_count: AVAudioFrameCount);

        /// Start or resume playback immediately.
        ///
        /// equivalent to playAtTime:nil
        #[unsafe(method(play))]
        #[unsafe(method_family = none)]
        pub unsafe fn play(&self);

        #[cfg(feature = "AVAudioTime")]
        /// Start or resume playback at a specific time.
        ///
        /// Parameter `when`: the node time at which to start or resume playback. nil signifies "now".
        ///
        /// This node is initially paused. Requests to play buffers or file segments are enqueued, and
        /// any necessary decoding begins immediately. Playback does not begin, however, until the player
        /// has started playing, via this method.
        ///
        /// Note that providing an AVAudioTime which is past (before lastRenderTime) will cause the
        /// player to begin playback immediately.
        ///
        /// E.g. To start a player X seconds in future:
        /// <pre>
        /// // start engine and player
        /// NSError *nsErr = nil;
        /// [_engine startAndReturnError:
        /// &nsErr
        /// ];
        /// if (!nsErr) {
        /// const float kStartDelayTime = 0.5; // sec
        /// AVAudioFormat *outputFormat = [_player outputFormatForBus:0];
        /// AVAudioFramePosition startSampleTime = _player.lastRenderTime.sampleTime + kStartDelayTime * outputFormat.sampleRate;
        /// AVAudioTime *startTime = [AVAudioTime timeWithSampleTime:startSampleTime atRate:outputFormat.sampleRate];
        /// [_player playAtTime:startTime];
        /// }
        /// </pre>
        #[unsafe(method(playAtTime:))]
        #[unsafe(method_family = none)]
        pub unsafe fn playAtTime(&self, when: Option<&AVAudioTime>);

        /// Pause playback.
        ///
        /// The player's sample time does not advance while the node is paused.
        ///
        /// Note that pausing or stopping all the players connected to an engine does not pause or stop
        /// the engine or the underlying hardware. The engine must be explicitly paused or stopped for
        /// the hardware to stop.
        #[unsafe(method(pause))]
        #[unsafe(method_family = none)]
        pub unsafe fn pause(&self);

        #[cfg(feature = "AVAudioTime")]
        /// Convert from player time to node time.
        ///
        /// Parameter `playerTime`: a time relative to the player's start time
        ///
        /// Returns: a node time
        ///
        /// This method and its inverse `playerTimeForNodeTime:` are discussed in the
        /// introduction to this class.
        ///
        /// If the player is not playing when this method is called, nil is returned.
        #[unsafe(method(nodeTimeForPlayerTime:))]
        #[unsafe(method_family = none)]
        pub unsafe fn nodeTimeForPlayerTime(
            &self,
            player_time: &AVAudioTime,
        ) -> Option<Retained<AVAudioTime>>;

        #[cfg(feature = "AVAudioTime")]
        /// Convert from node time to player time.
        ///
        /// Parameter `nodeTime`: a node time
        ///
        /// Returns: a time relative to the player's start time
        ///
        /// This method and its inverse `nodeTimeForPlayerTime:` are discussed in the
        /// introduction to this class.
        ///
        /// If the player is not playing when this method is called, nil is returned.
        #[unsafe(method(playerTimeForNodeTime:))]
        #[unsafe(method_family = none)]
        pub unsafe fn playerTimeForNodeTime(
            &self,
            node_time: &AVAudioTime,
        ) -> Option<Retained<AVAudioTime>>;

        /// Indicates whether or not the player is playing.
        #[unsafe(method(isPlaying))]
        #[unsafe(method_family = none)]
        pub unsafe fn isPlaying(&self) -> bool;
    );
}

/// Methods declared on superclass `NSObject`.
#[cfg(feature = "AVAudioNode")]
impl AVAudioPlayerNode {
    extern_methods!(
        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}
