//! 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!(
    /// The base class for all events associated with an AVMusicTrack.
    ///
    /// This class is provided to allow enumeration of the heterogenous events contained within an AVMusicTrack.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avmusicevent?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVMusicEvent;
);

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

impl AVMusicEvent {
    extern_methods!();
}

/// Methods declared on superclass `NSObject`.
impl AVMusicEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}

extern_class!(
    /// The event class representing MIDI note-on/off messages.
    ///
    /// Parameter `channel`: The MIDI channel for the note.  Range: 0-15.
    ///
    /// Parameter `key`: The MIDI key number for the note.  Range: 0-127.
    ///
    /// Parameter `velocity`: The MIDI velocity for the note.  Range: 0-127 (see discussion).
    ///
    /// Parameter `duration`: The duration of this note event in AVMusicTimeStamp beats.  Range: Any non-negative number.
    ///
    /// The AVAudioSequencer will automatically send a MIDI note-off after the note duration has passed.
    /// To send an explicit note-off event, create an AVMIDINoteEvent with its velocity set to zero.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avmidinoteevent?language=objc)
    #[unsafe(super(AVMusicEvent, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVMIDINoteEvent;
);

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

impl AVMIDINoteEvent {
    extern_methods!(
        #[cfg(feature = "AVAudioTypes")]
        /// Initialize the event with a MIDI channel, key number, velocity and duration.
        ///
        /// Parameter `channel`: The MIDI channel.  Range: 0-15.
        ///
        /// Parameter `key`: The MIDI key number.  Range: 0-127.
        ///
        /// Parameter `velocity`: The MIDI velocity.  Range: 0-127 with zero indicating a note-off event.
        ///
        /// Parameter `duration`: The duration in beats for this note.  Range: Any non-negative number.
        #[unsafe(method(initWithChannel:key:velocity:duration:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithChannel_key_velocity_duration(
            this: Allocated<Self>,
            channel: u32,
            key_num: u32,
            velocity: u32,
            duration: AVMusicTimeStamp,
        ) -> Retained<Self>;

        /// The MIDI channel for the event.  Range: 0-15.
        #[unsafe(method(channel))]
        #[unsafe(method_family = none)]
        pub unsafe fn channel(&self) -> u32;

        /// Setter for [`channel`][Self::channel].
        #[unsafe(method(setChannel:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setChannel(&self, channel: u32);

        /// The MIDI key number for the event.  Range: 0-127.
        #[unsafe(method(key))]
        #[unsafe(method_family = none)]
        pub unsafe fn key(&self) -> u32;

        /// Setter for [`key`][Self::key].
        #[unsafe(method(setKey:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setKey(&self, key: u32);

        /// The MIDI velocity for the event.  Range: 0-127.
        #[unsafe(method(velocity))]
        #[unsafe(method_family = none)]
        pub unsafe fn velocity(&self) -> u32;

        /// Setter for [`velocity`][Self::velocity].
        #[unsafe(method(setVelocity:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setVelocity(&self, velocity: u32);

        #[cfg(feature = "AVAudioTypes")]
        /// The duration of the event in AVMusicTimeStamp beats.  Range: Any non-negative number.
        #[unsafe(method(duration))]
        #[unsafe(method_family = none)]
        pub unsafe fn duration(&self) -> AVMusicTimeStamp;

        #[cfg(feature = "AVAudioTypes")]
        /// Setter for [`duration`][Self::duration].
        #[unsafe(method(setDuration:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setDuration(&self, duration: AVMusicTimeStamp);
    );
}

/// Methods declared on superclass `NSObject`.
impl AVMIDINoteEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}

extern_class!(
    /// The event base class for all MIDI messages which operate on a single MIDI channel.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avmidichannelevent?language=objc)
    #[unsafe(super(AVMusicEvent, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVMIDIChannelEvent;
);

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

impl AVMIDIChannelEvent {
    extern_methods!(
        /// The MIDI channel for the event.  Range: 0-15.
        #[unsafe(method(channel))]
        #[unsafe(method_family = none)]
        pub unsafe fn channel(&self) -> u32;

        /// Setter for [`channel`][Self::channel].
        #[unsafe(method(setChannel:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setChannel(&self, channel: u32);
    );
}

/// Methods declared on superclass `NSObject`.
impl AVMIDIChannelEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}

/// Types of MIDI control change events.  See the General MIDI Specification for details.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avmidicontrolchangemessagetype?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct AVMIDIControlChangeMessageType(pub NSInteger);
impl AVMIDIControlChangeMessageType {
    #[doc(alias = "AVMIDIControlChangeMessageTypeBankSelect")]
    pub const BankSelect: Self = Self(0);
    #[doc(alias = "AVMIDIControlChangeMessageTypeModWheel")]
    pub const ModWheel: Self = Self(1);
    #[doc(alias = "AVMIDIControlChangeMessageTypeBreath")]
    pub const Breath: Self = Self(2);
    #[doc(alias = "AVMIDIControlChangeMessageTypeFoot")]
    pub const Foot: Self = Self(4);
    #[doc(alias = "AVMIDIControlChangeMessageTypePortamentoTime")]
    pub const PortamentoTime: Self = Self(5);
    #[doc(alias = "AVMIDIControlChangeMessageTypeDataEntry")]
    pub const DataEntry: Self = Self(6);
    #[doc(alias = "AVMIDIControlChangeMessageTypeVolume")]
    pub const Volume: Self = Self(7);
    #[doc(alias = "AVMIDIControlChangeMessageTypeBalance")]
    pub const Balance: Self = Self(8);
    #[doc(alias = "AVMIDIControlChangeMessageTypePan")]
    pub const Pan: Self = Self(10);
    #[doc(alias = "AVMIDIControlChangeMessageTypeExpression")]
    pub const Expression: Self = Self(11);
    #[doc(alias = "AVMIDIControlChangeMessageTypeSustain")]
    pub const Sustain: Self = Self(64);
    #[doc(alias = "AVMIDIControlChangeMessageTypePortamento")]
    pub const Portamento: Self = Self(65);
    #[doc(alias = "AVMIDIControlChangeMessageTypeSostenuto")]
    pub const Sostenuto: Self = Self(66);
    #[doc(alias = "AVMIDIControlChangeMessageTypeSoft")]
    pub const Soft: Self = Self(67);
    #[doc(alias = "AVMIDIControlChangeMessageTypeLegatoPedal")]
    pub const LegatoPedal: Self = Self(68);
    #[doc(alias = "AVMIDIControlChangeMessageTypeHold2Pedal")]
    pub const Hold2Pedal: Self = Self(69);
    #[doc(alias = "AVMIDIControlChangeMessageTypeFilterResonance")]
    pub const FilterResonance: Self = Self(71);
    #[doc(alias = "AVMIDIControlChangeMessageTypeReleaseTime")]
    pub const ReleaseTime: Self = Self(72);
    #[doc(alias = "AVMIDIControlChangeMessageTypeAttackTime")]
    pub const AttackTime: Self = Self(73);
    #[doc(alias = "AVMIDIControlChangeMessageTypeBrightness")]
    pub const Brightness: Self = Self(74);
    #[doc(alias = "AVMIDIControlChangeMessageTypeDecayTime")]
    pub const DecayTime: Self = Self(75);
    #[doc(alias = "AVMIDIControlChangeMessageTypeVibratoRate")]
    pub const VibratoRate: Self = Self(76);
    #[doc(alias = "AVMIDIControlChangeMessageTypeVibratoDepth")]
    pub const VibratoDepth: Self = Self(77);
    #[doc(alias = "AVMIDIControlChangeMessageTypeVibratoDelay")]
    pub const VibratoDelay: Self = Self(78);
    #[doc(alias = "AVMIDIControlChangeMessageTypeReverbLevel")]
    pub const ReverbLevel: Self = Self(91);
    #[doc(alias = "AVMIDIControlChangeMessageTypeChorusLevel")]
    pub const ChorusLevel: Self = Self(93);
    #[doc(alias = "AVMIDIControlChangeMessageTypeRPN_LSB")]
    pub const RPN_LSB: Self = Self(100);
    #[doc(alias = "AVMIDIControlChangeMessageTypeRPN_MSB")]
    pub const RPN_MSB: Self = Self(101);
    #[doc(alias = "AVMIDIControlChangeMessageTypeAllSoundOff")]
    pub const AllSoundOff: Self = Self(120);
    #[doc(alias = "AVMIDIControlChangeMessageTypeResetAllControllers")]
    pub const ResetAllControllers: Self = Self(121);
    #[doc(alias = "AVMIDIControlChangeMessageTypeAllNotesOff")]
    pub const AllNotesOff: Self = Self(123);
    #[doc(alias = "AVMIDIControlChangeMessageTypeOmniModeOff")]
    pub const OmniModeOff: Self = Self(124);
    #[doc(alias = "AVMIDIControlChangeMessageTypeOmniModeOn")]
    pub const OmniModeOn: Self = Self(125);
    #[doc(alias = "AVMIDIControlChangeMessageTypeMonoModeOn")]
    pub const MonoModeOn: Self = Self(126);
    #[doc(alias = "AVMIDIControlChangeMessageTypeMonoModeOff")]
    pub const MonoModeOff: Self = Self(127);
}

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

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

extern_class!(
    /// The event class representing MIDI control change messages.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avmidicontrolchangeevent?language=objc)
    #[unsafe(super(AVMIDIChannelEvent, AVMusicEvent, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVMIDIControlChangeEvent;
);

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

impl AVMIDIControlChangeEvent {
    extern_methods!(
        /// Initialize the event with a channel, a control change type, and a control value.
        ///
        /// Parameter `channel`: The MIDI channel for the control change.  Range: 0-15.
        ///
        /// Parameter `messageType`: The AVMIDIControlChangeMessageType indicating which MIDI control change message to send.
        ///
        /// Parameter `value`: The value for this control change.  Range: Depends on the type (see the General MIDI specification).
        #[unsafe(method(initWithChannel:messageType:value:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithChannel_messageType_value(
            this: Allocated<Self>,
            channel: u32,
            message_type: AVMIDIControlChangeMessageType,
            value: u32,
        ) -> Retained<Self>;

        /// The type of control change message, specified as an AVMIDIControlChangeMessageType.
        #[unsafe(method(messageType))]
        #[unsafe(method_family = none)]
        pub unsafe fn messageType(&self) -> AVMIDIControlChangeMessageType;

        /// The value of the control change event.  The range of this value depends on the type (see the General MIDI specification).
        #[unsafe(method(value))]
        #[unsafe(method_family = none)]
        pub unsafe fn value(&self) -> u32;
    );
}

/// Methods declared on superclass `NSObject`.
impl AVMIDIControlChangeEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}

extern_class!(
    /// The event class representing MIDI "poly" or "key" pressure messages.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avmidipolypressureevent?language=objc)
    #[unsafe(super(AVMIDIChannelEvent, AVMusicEvent, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVMIDIPolyPressureEvent;
);

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

impl AVMIDIPolyPressureEvent {
    extern_methods!(
        /// Initialize the event with a channel, a MIDI key number, and a key pressure value.
        ///
        /// Parameter `channel`: The MIDI channel for the message.  Range: 0-15.
        ///
        /// Parameter `key`: The MIDI key number to which the pressure should be applied.
        ///
        /// Parameter `pressure`: The poly pressure value.
        #[unsafe(method(initWithChannel:key:pressure:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithChannel_key_pressure(
            this: Allocated<Self>,
            channel: u32,
            key: u32,
            pressure: u32,
        ) -> Retained<Self>;

        /// The MIDI key number.
        #[unsafe(method(key))]
        #[unsafe(method_family = none)]
        pub unsafe fn key(&self) -> u32;

        /// Setter for [`key`][Self::key].
        #[unsafe(method(setKey:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setKey(&self, key: u32);

        /// The poly pressure value for the requested key.
        #[unsafe(method(pressure))]
        #[unsafe(method_family = none)]
        pub unsafe fn pressure(&self) -> u32;

        /// Setter for [`pressure`][Self::pressure].
        #[unsafe(method(setPressure:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPressure(&self, pressure: u32);
    );
}

/// Methods declared on superclass `NSObject`.
impl AVMIDIPolyPressureEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}

extern_class!(
    /// The event class representing MIDI program or patch change messages.
    ///
    /// The effect of these messages will depend on the containing AVMusicTrack's destinationAudioUnit.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avmidiprogramchangeevent?language=objc)
    #[unsafe(super(AVMIDIChannelEvent, AVMusicEvent, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVMIDIProgramChangeEvent;
);

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

impl AVMIDIProgramChangeEvent {
    extern_methods!(
        /// Initialize the event with a channel and a program number.
        ///
        /// Parameter `channel`: The MIDI channel for the message.  Range: 0-15.
        ///
        /// Parameter `programNumber`: The program number to be sent.  Range: 0-127.
        ///
        /// Per the General MIDI specification, the actual instrument that is chosen will depend on optional
        /// AVMIDIControlChangeMessageTypeBankSelect events sent prior to this program change.
        #[unsafe(method(initWithChannel:programNumber:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithChannel_programNumber(
            this: Allocated<Self>,
            channel: u32,
            program_number: u32,
        ) -> Retained<Self>;

        /// The MIDI program number.  Range: 0-127.
        #[unsafe(method(programNumber))]
        #[unsafe(method_family = none)]
        pub unsafe fn programNumber(&self) -> u32;

        /// Setter for [`programNumber`][Self::programNumber].
        #[unsafe(method(setProgramNumber:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setProgramNumber(&self, program_number: u32);
    );
}

/// Methods declared on superclass `NSObject`.
impl AVMIDIProgramChangeEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}

extern_class!(
    /// The event class representing MIDI channel pressure messages.
    ///
    /// The effect of these messages will depend on the containing AVMusicTrack's destinationAudioUnit
    /// and the capabilities of the destination's currently-loaded instrument.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avmidichannelpressureevent?language=objc)
    #[unsafe(super(AVMIDIChannelEvent, AVMusicEvent, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVMIDIChannelPressureEvent;
);

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

impl AVMIDIChannelPressureEvent {
    extern_methods!(
        /// Initialize the event with a channel and a pressure value.
        ///
        /// Parameter `channel`: The MIDI channel for the message.  Range: 0-15.
        ///
        /// Parameter `pressure`: The MIDI channel pressure.  Range: 0-127.
        #[unsafe(method(initWithChannel:pressure:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithChannel_pressure(
            this: Allocated<Self>,
            channel: u32,
            pressure: u32,
        ) -> Retained<Self>;

        /// The MIDI channel pressure.
        #[unsafe(method(pressure))]
        #[unsafe(method_family = none)]
        pub unsafe fn pressure(&self) -> u32;

        /// Setter for [`pressure`][Self::pressure].
        #[unsafe(method(setPressure:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPressure(&self, pressure: u32);
    );
}

/// Methods declared on superclass `NSObject`.
impl AVMIDIChannelPressureEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}

extern_class!(
    /// The event class representing MIDI pitch bend messages.
    ///
    /// The effect of these messages will depend on the AVMusicTrack's destinationAudioUnit
    /// and the capabilities of the destination's currently-loaded instrument.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avmidipitchbendevent?language=objc)
    #[unsafe(super(AVMIDIChannelEvent, AVMusicEvent, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVMIDIPitchBendEvent;
);

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

impl AVMIDIPitchBendEvent {
    extern_methods!(
        /// Initialize the event with a channel and a pitch bend value.
        ///
        /// Parameter `channel`: The MIDI channel for the message.  Range: 0-15.
        ///
        /// Parameter `value`: The pitch bend value.  Range: 0-16383 (midpoint 8192).
        #[unsafe(method(initWithChannel:value:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithChannel_value(
            this: Allocated<Self>,
            channel: u32,
            value: u32,
        ) -> Retained<Self>;

        /// The value of the pitch bend event.  Range: 0-16383 (midpoint 8192).
        #[unsafe(method(value))]
        #[unsafe(method_family = none)]
        pub unsafe fn value(&self) -> u32;

        /// Setter for [`value`][Self::value].
        #[unsafe(method(setValue:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setValue(&self, value: u32);
    );
}

/// Methods declared on superclass `NSObject`.
impl AVMIDIPitchBendEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}

extern_class!(
    /// The event class representing MIDI system exclusive messages.
    ///
    /// The size and contents of an AVMIDISysexEvent cannot be modified once created.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avmidisysexevent?language=objc)
    #[unsafe(super(AVMusicEvent, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVMIDISysexEvent;
);

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

impl AVMIDISysexEvent {
    extern_methods!(
        /// Initialize the event with an NSData.
        ///
        /// Parameter `data`: An NSData object containing the raw contents of the system exclusive event.
        #[unsafe(method(initWithData:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithData(this: Allocated<Self>, data: &NSData) -> Retained<Self>;

        /// The size of the raw data associated with this system exclusive event.
        #[unsafe(method(sizeInBytes))]
        #[unsafe(method_family = none)]
        pub unsafe fn sizeInBytes(&self) -> u32;
    );
}

/// Methods declared on superclass `NSObject`.
impl AVMIDISysexEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}

/// Constants which indicate which type of MIDI Meta-Event to create.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avmidimetaeventtype?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct AVMIDIMetaEventType(pub NSInteger);
impl AVMIDIMetaEventType {
    #[doc(alias = "AVMIDIMetaEventTypeSequenceNumber")]
    pub const SequenceNumber: Self = Self(0x00);
    #[doc(alias = "AVMIDIMetaEventTypeText")]
    pub const Text: Self = Self(0x01);
    #[doc(alias = "AVMIDIMetaEventTypeCopyright")]
    pub const Copyright: Self = Self(0x02);
    #[doc(alias = "AVMIDIMetaEventTypeTrackName")]
    pub const TrackName: Self = Self(0x03);
    #[doc(alias = "AVMIDIMetaEventTypeInstrument")]
    pub const Instrument: Self = Self(0x04);
    #[doc(alias = "AVMIDIMetaEventTypeLyric")]
    pub const Lyric: Self = Self(0x05);
    #[doc(alias = "AVMIDIMetaEventTypeMarker")]
    pub const Marker: Self = Self(0x06);
    #[doc(alias = "AVMIDIMetaEventTypeCuePoint")]
    pub const CuePoint: Self = Self(0x07);
    #[doc(alias = "AVMIDIMetaEventTypeMidiChannel")]
    pub const MidiChannel: Self = Self(0x20);
    #[doc(alias = "AVMIDIMetaEventTypeMidiPort")]
    pub const MidiPort: Self = Self(0x21);
    #[doc(alias = "AVMIDIMetaEventTypeEndOfTrack")]
    pub const EndOfTrack: Self = Self(0x2f);
    #[doc(alias = "AVMIDIMetaEventTypeTempo")]
    pub const Tempo: Self = Self(0x51);
    #[doc(alias = "AVMIDIMetaEventTypeSmpteOffset")]
    pub const SmpteOffset: Self = Self(0x54);
    #[doc(alias = "AVMIDIMetaEventTypeTimeSignature")]
    pub const TimeSignature: Self = Self(0x58);
    #[doc(alias = "AVMIDIMetaEventTypeKeySignature")]
    pub const KeySignature: Self = Self(0x59);
    #[doc(alias = "AVMIDIMetaEventTypeProprietaryEvent")]
    pub const ProprietaryEvent: Self = Self(0x7f);
}

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

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

extern_class!(
    /// The event class representing MIDI Meta-Event messages.
    ///
    /// The size and contents of an AVMIDIMetaEvent cannot be modified once created.
    ///
    /// Events with AVMIDIMetaEventType AVMIDIMetaEventTypeTempo, AVMIDIMetaEventTypeSmpteOffset,
    /// or AVMIDIMetaEventTypeTimeSignature can only be added to a sequence's tempo track.
    ///
    /// The class does not verify that the content matches the MIDI specification.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avmidimetaevent?language=objc)
    #[unsafe(super(AVMusicEvent, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVMIDIMetaEvent;
);

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

impl AVMIDIMetaEvent {
    extern_methods!(
        /// Initialize the event with a MIDI Meta-Event type and an NSData.
        ///
        /// Parameter `type`: A AVMIDIMetaEventType indicating which type of Meta-Event.
        ///
        /// Parameter `data`: An NSData object containing the raw contents of the Meta-Event.
        #[unsafe(method(initWithType:data:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithType_data(
            this: Allocated<Self>,
            r#type: AVMIDIMetaEventType,
            data: &NSData,
        ) -> Retained<Self>;

        /// The type of Meta-Event, specified as an AVMIDIMetaEventType.
        #[unsafe(method(type))]
        #[unsafe(method_family = none)]
        pub unsafe fn r#type(&self) -> AVMIDIMetaEventType;
    );
}

/// Methods declared on superclass `NSObject`.
impl AVMIDIMetaEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}

extern_class!(
    /// The event class representing custom user messages.
    ///
    /// When a scheduled AVMusicUserEvent is reached during playback of a AVMusicTrack, the track's
    /// user callback block will be called if it has been set.  The event's NSData will be provided as
    /// an argument to that block.
    /// The size and contents of an AVMusicUserEvent cannot be modified once created.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avmusicuserevent?language=objc)
    #[unsafe(super(AVMusicEvent, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVMusicUserEvent;
);

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

impl AVMusicUserEvent {
    extern_methods!(
        /// Initialize the event with an NSData.
        ///
        /// Parameter `data`: An NSData object containing the contents to be returned via the AVMusicTrack's user callback.
        #[unsafe(method(initWithData:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithData(this: Allocated<Self>, data: &NSData) -> Retained<Self>;

        /// The size of the data associated with this user event.
        #[unsafe(method(sizeInBytes))]
        #[unsafe(method_family = none)]
        pub unsafe fn sizeInBytes(&self) -> u32;
    );
}

/// Methods declared on superclass `NSObject`.
impl AVMusicUserEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}

extern "C" {
    /// A constant representing the default instrument ID to use for an AVExtendedNoteOnEvent.  This indicates to the
    /// system to use the instrument currently loaded on the channel referenced by the groupID.  This is the only
    /// supported value at this time.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avextendednoteoneventdefaultinstrument?language=objc)
    pub static AVExtendedNoteOnEventDefaultInstrument: u32;
}

extern_class!(
    /// The event class representing a custom extension of a MIDI note-on.
    ///
    /// Using an AVExtendedNoteOnEvent allows an application to trigger a specialized note-on event on one of several
    /// Apple audio units which support it.  The floating point note and velocity numbers allow optional fractional control
    /// of the note's run-time properties which are modulated by those inputs.  In addition, it supports the possibility
    /// of an audio unit with more than the standard 16 MIDI channels.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avextendednoteonevent?language=objc)
    #[unsafe(super(AVMusicEvent, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVExtendedNoteOnEvent;
);

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

impl AVExtendedNoteOnEvent {
    extern_methods!(
        #[cfg(feature = "AVAudioTypes")]
        /// Initialize the event with a midi note, velocity, instrument and group ID, and a duration.
        ///
        /// Parameter `midiNote`: The MIDI velocity represented as a floating point.  Range: Destination-dependent, usually 0.0 - 127.0.
        ///
        /// Parameter `velocity`: The MIDI velocity represented as a floating point.  Range: Destination-dependent, usually 0.0 - 127.0.
        ///
        /// Parameter `groupID`: An index indicating the AudioUnitElement within the Group Scope which should handle this event (see AudioUnitElement).
        /// This normally maps to a channel within the audio unit.
        /// Range: normally between 0 and 15, but may be higher if the AVMusicTrack's destinationAudioUnit supports more channels.
        ///
        /// Parameter `duration`: The duration of this event in AVMusicTimeStamp beats.  Range:  Any nonnegative number.
        #[unsafe(method(initWithMIDINote:velocity:groupID:duration:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithMIDINote_velocity_groupID_duration(
            this: Allocated<Self>,
            midi_note: c_float,
            velocity: c_float,
            group_id: u32,
            duration: AVMusicTimeStamp,
        ) -> Retained<Self>;

        #[cfg(feature = "AVAudioTypes")]
        /// Initialize the event with a midi note, velocity, instrument and group ID, and a duration.
        ///
        /// This initializer is identical to initWithMIDINote:velocity:groupID:duration with the addition of
        /// an instrumentID parameter which will allow for the possibility of an externally-created custom instrument.
        /// If this initializer is used, instrumentID should be set to AVExtendedNoteOnEventDefaultInstrument for now.
        #[unsafe(method(initWithMIDINote:velocity:instrumentID:groupID:duration:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithMIDINote_velocity_instrumentID_groupID_duration(
            this: Allocated<Self>,
            midi_note: c_float,
            velocity: c_float,
            instrument_id: u32,
            group_id: u32,
            duration: AVMusicTimeStamp,
        ) -> Retained<Self>;

        /// The MIDI note number represented as a floating point.  If the instrument within the AVMusicTrack's
        /// destinationAudioUnit supports fractional values, this may be used to generate arbitrary
        /// macro- and micro-tunings.  Range: Destination-dependent, usually 0.0 - 127.0.
        #[unsafe(method(midiNote))]
        #[unsafe(method_family = none)]
        pub unsafe fn midiNote(&self) -> c_float;

        /// Setter for [`midiNote`][Self::midiNote].
        #[unsafe(method(setMidiNote:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setMidiNote(&self, midi_note: c_float);

        /// The MIDI velocity represented as a floating point.  If the instrument within the AVMusicTrack's
        /// destinationAudioUnit supports fractional values, this may be used to generate very precise changes
        /// in gain, etc.  Range: Destination-dependent, usually 0.0 - 127.0.
        #[unsafe(method(velocity))]
        #[unsafe(method_family = none)]
        pub unsafe fn velocity(&self) -> c_float;

        /// Setter for [`velocity`][Self::velocity].
        #[unsafe(method(setVelocity:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setVelocity(&self, velocity: c_float);

        /// This should be set to AVExtendedNoteOnEventDefaultInstrument.
        #[unsafe(method(instrumentID))]
        #[unsafe(method_family = none)]
        pub unsafe fn instrumentID(&self) -> u32;

        /// Setter for [`instrumentID`][Self::instrumentID].
        #[unsafe(method(setInstrumentID:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setInstrumentID(&self, instrument_id: u32);

        /// This represents the audio unit channel (i.e., Group Scope) which should handle this event.
        /// Range: normally between 0 and 15, but may be higher if the AVMusicTrack's destinationAudioUnit
        /// supports more channels.
        #[unsafe(method(groupID))]
        #[unsafe(method_family = none)]
        pub unsafe fn groupID(&self) -> u32;

        /// Setter for [`groupID`][Self::groupID].
        #[unsafe(method(setGroupID:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setGroupID(&self, group_id: u32);

        #[cfg(feature = "AVAudioTypes")]
        /// The duration of this event in AVMusicTimeStamp beats.  Range:  Any nonnegative number.
        #[unsafe(method(duration))]
        #[unsafe(method_family = none)]
        pub unsafe fn duration(&self) -> AVMusicTimeStamp;

        #[cfg(feature = "AVAudioTypes")]
        /// Setter for [`duration`][Self::duration].
        #[unsafe(method(setDuration:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setDuration(&self, duration: AVMusicTimeStamp);
    );
}

/// Methods declared on superclass `NSObject`.
impl AVExtendedNoteOnEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}

extern_class!(
    /// The event class representing a parameter set/change event on the AVMusicTrack's destinationAudioUnit.
    ///
    /// AVParameterEvents make it possible to schedule and/or automate parameter changes on the audio unit
    /// that has been configured as the destination for the AVMusicTrack containing this event.
    ///
    /// When the track is played as part of a sequence, the destination audio unit will receive set-parameter
    /// messages whose values change smoothly along a linear ramp between each event's beat location.
    ///
    /// If an AVParameterEvent is added to an empty, non-automation track, the track becomes an automation track.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avparameterevent?language=objc)
    #[unsafe(super(AVMusicEvent, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVParameterEvent;
);

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

impl AVParameterEvent {
    extern_methods!(
        /// Initialize the event with the parameter ID, scope, element, and value for the parameter to be set.
        ///
        /// Parameter `parameterID`: The ID of the parameter (see AudioUnitParameterID).
        ///
        /// Parameter `scope`: The audio unit scope for the parameter (see AudioUnitScope).
        ///
        /// Parameter `element`: The element index within the scope (see AudioUnitElement).
        ///
        /// Parameter `value`: The value of the parameter to be set.  Range:  Dependent on parameter.
        #[unsafe(method(initWithParameterID:scope:element:value:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithParameterID_scope_element_value(
            this: Allocated<Self>,
            parameter_id: u32,
            scope: u32,
            element: u32,
            value: c_float,
        ) -> Retained<Self>;

        /// The ID of the parameter (see AudioUnitParameterID).
        #[unsafe(method(parameterID))]
        #[unsafe(method_family = none)]
        pub unsafe fn parameterID(&self) -> u32;

        /// Setter for [`parameterID`][Self::parameterID].
        #[unsafe(method(setParameterID:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setParameterID(&self, parameter_id: u32);

        /// The audio unit scope for the parameter (see AudioUnitScope).
        #[unsafe(method(scope))]
        #[unsafe(method_family = none)]
        pub unsafe fn scope(&self) -> u32;

        /// Setter for [`scope`][Self::scope].
        #[unsafe(method(setScope:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setScope(&self, scope: u32);

        /// The element index within the scope (see AudioUnitElement).
        #[unsafe(method(element))]
        #[unsafe(method_family = none)]
        pub unsafe fn element(&self) -> u32;

        /// Setter for [`element`][Self::element].
        #[unsafe(method(setElement:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setElement(&self, element: u32);

        /// The value of the parameter to be set.  Range:  Dependent on parameter.
        #[unsafe(method(value))]
        #[unsafe(method_family = none)]
        pub unsafe fn value(&self) -> c_float;

        /// Setter for [`value`][Self::value].
        #[unsafe(method(setValue:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setValue(&self, value: c_float);
    );
}

/// Methods declared on superclass `NSObject`.
impl AVParameterEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}

extern_class!(
    /// The event class representing a preset load and change on the AVMusicTrack's destinationAudioUnit.
    ///
    /// AVAUPresetEvents make it possible to schedule and/or automate preset changes on the audio unit
    /// that has been configured as the destination for the AVMusicTrack containing this event.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avaupresetevent?language=objc)
    #[unsafe(super(AVMusicEvent, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVAUPresetEvent;
);

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

impl AVAUPresetEvent {
    extern_methods!(
        /// Initialize the event with the scope, element, and dictionary for the preset.
        ///
        /// Parameter `scope`: The audio unit scope for the parameter (see AudioUnitScope).  This should always be set to Global.
        ///
        /// Parameter `element`: The element index within the scope (see AudioUnitElement).  This should usually be set to 0.
        ///
        /// Parameter `presetDictionary`: An NSDictionary containing the preset.  The audio unit will expect this to be a dictionary
        /// structured as an appropriate audio unit preset.
        ///
        /// The dictionary passed to this initializer will be copied and is not editable once the event is
        /// created.
        ///
        /// # Safety
        ///
        /// `preset_dictionary` generic should be of the correct type.
        #[unsafe(method(initWithScope:element:dictionary:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithScope_element_dictionary(
            this: Allocated<Self>,
            scope: u32,
            element: u32,
            preset_dictionary: &NSDictionary,
        ) -> Retained<Self>;

        /// The audio unit scope for the parameter (see AudioUnitScope).  This should always be set to Global.
        #[unsafe(method(scope))]
        #[unsafe(method_family = none)]
        pub unsafe fn scope(&self) -> u32;

        /// Setter for [`scope`][Self::scope].
        #[unsafe(method(setScope:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setScope(&self, scope: u32);

        /// The element index within the scope (see AudioUnitElement).  This should usually be set to 0.
        #[unsafe(method(element))]
        #[unsafe(method_family = none)]
        pub unsafe fn element(&self) -> u32;

        /// Setter for [`element`][Self::element].
        #[unsafe(method(setElement:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setElement(&self, element: u32);

        /// An NSDictionary containing the preset.
        #[unsafe(method(presetDictionary))]
        #[unsafe(method_family = none)]
        pub unsafe fn presetDictionary(&self) -> Retained<NSDictionary>;
    );
}

/// Methods declared on superclass `NSObject`.
impl AVAUPresetEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}

extern_class!(
    /// The event class representing a tempo change to a specific beats-per-minute value.
    ///
    /// This event provides a way to specify a tempo change that is less cumbersome than using
    /// tempo meta-events.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avextendedtempoevent?language=objc)
    #[unsafe(super(AVMusicEvent, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVExtendedTempoEvent;
);

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

impl AVExtendedTempoEvent {
    extern_methods!(
        /// Initialize the event tempo.
        ///
        /// Parameter `tempo`: The new tempo in beats-per-minute.  Range:  Any positive value.
        /// The new tempo will begin at the timestamp for this event.
        #[unsafe(method(initWithTempo:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithTempo(this: Allocated<Self>, tempo: c_double) -> Retained<Self>;

        /// The new tempo in beats-per-minute.  Range:  Any positive value.
        #[unsafe(method(tempo))]
        #[unsafe(method_family = none)]
        pub unsafe fn tempo(&self) -> c_double;

        /// Setter for [`tempo`][Self::tempo].
        #[unsafe(method(setTempo:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setTempo(&self, tempo: c_double);
    );
}

/// Methods declared on superclass `NSObject`.
impl AVExtendedTempoEvent {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}
