pub const ext = @import("ext.zig");
const gstaudio = @This();

const std = @import("std");
const compat = @import("compat");
const gstbase = @import("gstbase1");
const gst = @import("gst1");
const gobject = @import("gobject2");
const glib = @import("glib2");
const gmodule = @import("gmodule2");
/// Subclasses must use (a subclass of) `gstaudio.AudioAggregatorPad` for both
/// their source and sink pads,
/// `gst.ElementClass.addStaticPadTemplateWithGtype` is a convenient
/// helper.
///
/// `gstaudio.AudioAggregator` can perform conversion on the data arriving
/// on its sink pads, based on the format expected downstream: in order
/// to enable that behaviour, the GType of the sink pads must either be
/// a (subclass of) `gstaudio.AudioAggregatorConvertPad` to use the default
/// `gstaudio.AudioConverter` implementation, or a subclass of `gstaudio.AudioAggregatorPad`
/// implementing `gstaudio.AudioAggregatorPadClass.convert_buffer`.
///
/// To allow for the output caps to change, the mechanism is the same as
/// above, with the GType of the source pad.
///
/// See `GstAudioMixer` for an example.
///
/// When conversion is enabled, `gstaudio.AudioAggregator` will accept
/// any type of raw audio caps and perform conversion
/// on the data arriving on its sink pads, with whatever downstream
/// expects as the target format.
///
/// In case downstream caps are not fully fixated, it will use
/// the first configured sink pad to finish fixating its source pad
/// caps.
///
/// A notable exception for now is the sample rate, sink pads must
/// have the same sample rate as either the downstream requirement,
/// or the first configured pad, or a combination of both (when
/// downstream specifies a range or a set of acceptable rates).
///
/// The `gstbase.Aggregator.signals.samples`-selected signal is provided with some
/// additional information about the output buffer:
/// - "offset"  G_TYPE_UINT64   Offset in samples since segment start
///   for the position that is next to be filled in the output buffer.
/// - "frames"  G_TYPE_UINT   Number of frames per output buffer.
///
/// In addition the `gstbase.Aggregator.peekNextSample` function returns
/// additional information in the info `gst.Structure` of the returned sample:
/// - "output-offset"  G_TYPE_UINT64   Sample offset in output segment relative to
///   the output segment's start where the current position of this input
///   buffer would be placed
/// - "position"  G_TYPE_UINT   current position in the input buffer in samples
/// - "size"  G_TYPE_UINT   size of the input buffer in samples
pub const AudioAggregator = extern struct {
    pub const Parent = gstbase.Aggregator;
    pub const Implements = [_]type{};
    pub const Class = gstaudio.AudioAggregatorClass;
    f_parent: gstbase.Aggregator,
    /// The caps set by the subclass
    f_current_caps: ?*gst.Caps,
    f_priv: ?*gstaudio.AudioAggregatorPrivate,
    f__gst_reserved: [4]*anyopaque,

    pub const virtual_methods = struct {
        /// Aggregates one input buffer to the output
        ///  buffer.  The in_offset and out_offset are in "frames", which is
        ///  the size of a sample times the number of channels. Returns TRUE if
        ///  any non-silence was added to the buffer
        pub const aggregate_one_buffer = struct {
            pub fn call(p_class: anytype, p_aagg: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_pad: *gstaudio.AudioAggregatorPad, p_inbuf: *gst.Buffer, p_in_offset: c_uint, p_outbuf: *gst.Buffer, p_out_offset: c_uint, p_num_frames: c_uint) c_int {
                return gobject.ext.as(AudioAggregator.Class, p_class).f_aggregate_one_buffer.?(gobject.ext.as(AudioAggregator, p_aagg), p_pad, p_inbuf, p_in_offset, p_outbuf, p_out_offset, p_num_frames);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_aagg: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_pad: *gstaudio.AudioAggregatorPad, p_inbuf: *gst.Buffer, p_in_offset: c_uint, p_outbuf: *gst.Buffer, p_out_offset: c_uint, p_num_frames: c_uint) callconv(.c) c_int) void {
                gobject.ext.as(AudioAggregator.Class, p_class).f_aggregate_one_buffer = @ptrCast(p_implementation);
            }
        };

        /// Create a new output buffer contains num_frames frames.
        pub const create_output_buffer = struct {
            pub fn call(p_class: anytype, p_aagg: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_num_frames: c_uint) *gst.Buffer {
                return gobject.ext.as(AudioAggregator.Class, p_class).f_create_output_buffer.?(gobject.ext.as(AudioAggregator, p_aagg), p_num_frames);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_aagg: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_num_frames: c_uint) callconv(.c) *gst.Buffer) void {
                gobject.ext.as(AudioAggregator.Class, p_class).f_create_output_buffer = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {
        pub const alignment_threshold = struct {
            pub const name = "alignment-threshold";

            pub const Type = u64;
        };

        pub const discont_wait = struct {
            pub const name = "discont-wait";

            pub const Type = u64;
        };

        /// Causes the element to aggregate on a timeout even when no live source is
        /// connected to its sinks. See `gstbase.Aggregator.properties.min`-upstream-latency for a
        /// companion property: in the vast majority of cases where you plan to plug in
        /// live sources with a non-zero latency, you should set it to a non-zero value.
        pub const force_live = struct {
            pub const name = "force-live";

            pub const Type = c_int;
        };

        /// Don't wait for inactive pads when live. An inactive pad
        /// is a pad that hasn't yet received a buffer, but that has
        /// been waited on at least once.
        ///
        /// The purpose of this property is to avoid aggregating on
        /// timeout when new pads are requested in advance of receiving
        /// data flow, for example the user may decide to connect it later,
        /// but wants to configure it already.
        pub const ignore_inactive_pads = struct {
            pub const name = "ignore-inactive-pads";

            pub const Type = c_int;
        };

        pub const output_buffer_duration = struct {
            pub const name = "output-buffer-duration";

            pub const Type = u64;
        };

        /// Output block size in nanoseconds, expressed as a fraction.
        pub const output_buffer_duration_fraction = struct {
            pub const name = "output-buffer-duration-fraction";

            pub const Type = ?*gst.Fraction;
        };
    };

    pub const signals = struct {};

    extern fn gst_audio_aggregator_set_sink_caps(p_aagg: *AudioAggregator, p_pad: *gstaudio.AudioAggregatorPad, p_caps: *gst.Caps) void;
    pub const setSinkCaps = gst_audio_aggregator_set_sink_caps;

    extern fn gst_audio_aggregator_get_type() usize;
    pub const getGObjectType = gst_audio_aggregator_get_type;

    extern fn g_object_ref(p_self: *gstaudio.AudioAggregator) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstaudio.AudioAggregator) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *AudioAggregator, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// An implementation of GstPad that can be used with `gstaudio.AudioAggregator`.
///
/// See `gstaudio.AudioAggregator` for more details.
pub const AudioAggregatorConvertPad = extern struct {
    pub const Parent = gstaudio.AudioAggregatorPad;
    pub const Implements = [_]type{};
    pub const Class = gstaudio.AudioAggregatorConvertPadClass;
    f_parent: gstaudio.AudioAggregatorPad,
    f_priv: ?*gstaudio.AudioAggregatorConvertPadPrivate,
    f__gst_reserved: [4]*anyopaque,

    pub const virtual_methods = struct {};

    pub const properties = struct {
        pub const converter_config = struct {
            pub const name = "converter-config";

            pub const Type = ?*gst.Structure;
        };
    };

    pub const signals = struct {};

    extern fn gst_audio_aggregator_convert_pad_get_type() usize;
    pub const getGObjectType = gst_audio_aggregator_convert_pad_get_type;

    extern fn g_object_ref(p_self: *gstaudio.AudioAggregatorConvertPad) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstaudio.AudioAggregatorConvertPad) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *AudioAggregatorConvertPad, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// The default implementation of GstPad used with `gstaudio.AudioAggregator`
pub const AudioAggregatorPad = extern struct {
    pub const Parent = gstbase.AggregatorPad;
    pub const Implements = [_]type{};
    pub const Class = gstaudio.AudioAggregatorPadClass;
    f_parent: gstbase.AggregatorPad,
    /// The audio info for this pad set from the incoming caps
    f_info: gstaudio.AudioInfo,
    f_priv: ?*gstaudio.AudioAggregatorPadPrivate,
    f__gst_reserved: [4]*anyopaque,

    pub const virtual_methods = struct {
        /// Convert a buffer from one format to another.
        pub const convert_buffer = struct {
            pub fn call(p_class: anytype, p_pad: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_in_info: *gstaudio.AudioInfo, p_out_info: *gstaudio.AudioInfo, p_buffer: *gst.Buffer) *gst.Buffer {
                return gobject.ext.as(AudioAggregatorPad.Class, p_class).f_convert_buffer.?(gobject.ext.as(AudioAggregatorPad, p_pad), p_in_info, p_out_info, p_buffer);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_pad: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_in_info: *gstaudio.AudioInfo, p_out_info: *gstaudio.AudioInfo, p_buffer: *gst.Buffer) callconv(.c) *gst.Buffer) void {
                gobject.ext.as(AudioAggregatorPad.Class, p_class).f_convert_buffer = @ptrCast(p_implementation);
            }
        };

        /// Called when either the input or output
        ///  formats have changed.
        pub const update_conversion_info = struct {
            pub fn call(p_class: anytype, p_pad: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) void {
                return gobject.ext.as(AudioAggregatorPad.Class, p_class).f_update_conversion_info.?(gobject.ext.as(AudioAggregatorPad, p_pad));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_pad: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) void) void {
                gobject.ext.as(AudioAggregatorPad.Class, p_class).f_update_conversion_info = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {
        /// Emit QoS messages when dropping buffers.
        pub const qos_messages = struct {
            pub const name = "qos-messages";

            pub const Type = c_int;
        };
    };

    pub const signals = struct {};

    extern fn gst_audio_aggregator_pad_get_type() usize;
    pub const getGObjectType = gst_audio_aggregator_pad_get_type;

    extern fn g_object_ref(p_self: *gstaudio.AudioAggregatorPad) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstaudio.AudioAggregatorPad) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *AudioAggregatorPad, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// This is the base class for audio sinks. Subclasses need to implement the
/// ::create_ringbuffer vmethod. This base class will then take care of
/// writing samples to the ringbuffer, synchronisation, clipping and flushing.
pub const AudioBaseSink = extern struct {
    pub const Parent = gstbase.BaseSink;
    pub const Implements = [_]type{};
    pub const Class = gstaudio.AudioBaseSinkClass;
    f_element: gstbase.BaseSink,
    f_ringbuffer: ?*gstaudio.AudioRingBuffer,
    f_buffer_time: u64,
    f_latency_time: u64,
    f_next_sample: u64,
    f_provided_clock: ?*gst.Clock,
    f_eos_rendering: c_int,
    f_priv: ?*gstaudio.AudioBaseSinkPrivate,
    f__gst_reserved: [4]*anyopaque,

    pub const virtual_methods = struct {
        /// Create and return the `gstaudio.AudioRingBuffer` for `sink`. This function will
        /// call the ::create_ringbuffer vmethod and will set `sink` as the parent of
        /// the returned buffer (see `gst.Object.setParent`).
        pub const create_ringbuffer = struct {
            pub fn call(p_class: anytype, p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) ?*gstaudio.AudioRingBuffer {
                return gobject.ext.as(AudioBaseSink.Class, p_class).f_create_ringbuffer.?(gobject.ext.as(AudioBaseSink, p_sink));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) ?*gstaudio.AudioRingBuffer) void {
                gobject.ext.as(AudioBaseSink.Class, p_class).f_create_ringbuffer = @ptrCast(p_implementation);
            }
        };

        /// payload data in a format suitable to write to the sink. If no
        ///           payloading is required, returns a reffed copy of the original
        ///           buffer, else returns the payloaded buffer with all other metadata
        ///           copied.
        pub const payload = struct {
            pub fn call(p_class: anytype, p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_buffer: *gst.Buffer) *gst.Buffer {
                return gobject.ext.as(AudioBaseSink.Class, p_class).f_payload.?(gobject.ext.as(AudioBaseSink, p_sink), p_buffer);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_buffer: *gst.Buffer) callconv(.c) *gst.Buffer) void {
                gobject.ext.as(AudioBaseSink.Class, p_class).f_payload = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {
        pub const alignment_threshold = struct {
            pub const name = "alignment-threshold";

            pub const Type = u64;
        };

        pub const buffer_time = struct {
            pub const name = "buffer-time";

            pub const Type = i64;
        };

        pub const can_activate_pull = struct {
            pub const name = "can-activate-pull";

            pub const Type = c_int;
        };

        /// A window of time in nanoseconds to wait before creating a discontinuity as
        /// a result of breaching the drift-tolerance.
        pub const discont_wait = struct {
            pub const name = "discont-wait";

            pub const Type = u64;
        };

        /// Controls the amount of time in microseconds that clocks are allowed
        /// to drift before resynchronisation happens.
        pub const drift_tolerance = struct {
            pub const name = "drift-tolerance";

            pub const Type = i64;
        };

        pub const latency_time = struct {
            pub const name = "latency-time";

            pub const Type = i64;
        };

        pub const provide_clock = struct {
            pub const name = "provide-clock";

            pub const Type = c_int;
        };

        pub const slave_method = struct {
            pub const name = "slave-method";

            pub const Type = gstaudio.AudioBaseSinkSlaveMethod;
        };
    };

    pub const signals = struct {};

    /// Create and return the `gstaudio.AudioRingBuffer` for `sink`. This function will
    /// call the ::create_ringbuffer vmethod and will set `sink` as the parent of
    /// the returned buffer (see `gst.Object.setParent`).
    extern fn gst_audio_base_sink_create_ringbuffer(p_sink: *AudioBaseSink) ?*gstaudio.AudioRingBuffer;
    pub const createRingbuffer = gst_audio_base_sink_create_ringbuffer;

    /// Get the current alignment threshold, in nanoseconds, used by `sink`.
    extern fn gst_audio_base_sink_get_alignment_threshold(p_sink: *AudioBaseSink) gst.ClockTime;
    pub const getAlignmentThreshold = gst_audio_base_sink_get_alignment_threshold;

    /// Get the current discont wait, in nanoseconds, used by `sink`.
    extern fn gst_audio_base_sink_get_discont_wait(p_sink: *AudioBaseSink) gst.ClockTime;
    pub const getDiscontWait = gst_audio_base_sink_get_discont_wait;

    /// Get the current drift tolerance, in microseconds, used by `sink`.
    extern fn gst_audio_base_sink_get_drift_tolerance(p_sink: *AudioBaseSink) i64;
    pub const getDriftTolerance = gst_audio_base_sink_get_drift_tolerance;

    /// Queries whether `sink` will provide a clock or not. See also
    /// gst_audio_base_sink_set_provide_clock.
    extern fn gst_audio_base_sink_get_provide_clock(p_sink: *AudioBaseSink) c_int;
    pub const getProvideClock = gst_audio_base_sink_get_provide_clock;

    /// Get the current slave method used by `sink`.
    extern fn gst_audio_base_sink_get_slave_method(p_sink: *AudioBaseSink) gstaudio.AudioBaseSinkSlaveMethod;
    pub const getSlaveMethod = gst_audio_base_sink_get_slave_method;

    /// Informs this base class that the audio output device has failed for
    /// some reason, causing a discontinuity (for example, because the device
    /// recovered from the error, but lost all contents of its ring buffer).
    /// This function is typically called by derived classes, and is useful
    /// for the custom slave method.
    extern fn gst_audio_base_sink_report_device_failure(p_sink: *AudioBaseSink) void;
    pub const reportDeviceFailure = gst_audio_base_sink_report_device_failure;

    /// Controls the sink's alignment threshold.
    extern fn gst_audio_base_sink_set_alignment_threshold(p_sink: *AudioBaseSink, p_alignment_threshold: gst.ClockTime) void;
    pub const setAlignmentThreshold = gst_audio_base_sink_set_alignment_threshold;

    /// Sets the custom slaving callback. This callback will
    /// be invoked if the slave-method property is set to
    /// GST_AUDIO_BASE_SINK_SLAVE_CUSTOM and the audio sink
    /// receives and plays samples.
    ///
    /// Setting the callback to NULL causes the sink to
    /// behave as if the GST_AUDIO_BASE_SINK_SLAVE_NONE
    /// method were used.
    extern fn gst_audio_base_sink_set_custom_slaving_callback(p_sink: *AudioBaseSink, p_callback: gstaudio.AudioBaseSinkCustomSlavingCallback, p_user_data: ?*anyopaque, p_notify: ?glib.DestroyNotify) void;
    pub const setCustomSlavingCallback = gst_audio_base_sink_set_custom_slaving_callback;

    /// Controls how long the sink will wait before creating a discontinuity.
    extern fn gst_audio_base_sink_set_discont_wait(p_sink: *AudioBaseSink, p_discont_wait: gst.ClockTime) void;
    pub const setDiscontWait = gst_audio_base_sink_set_discont_wait;

    /// Controls the sink's drift tolerance.
    extern fn gst_audio_base_sink_set_drift_tolerance(p_sink: *AudioBaseSink, p_drift_tolerance: i64) void;
    pub const setDriftTolerance = gst_audio_base_sink_set_drift_tolerance;

    /// Controls whether `sink` will provide a clock or not. If `provide` is `TRUE`,
    /// `gst.Element.provideClock` will return a clock that reflects the datarate
    /// of `sink`. If `provide` is `FALSE`, `gst.Element.provideClock` will return
    /// NULL.
    extern fn gst_audio_base_sink_set_provide_clock(p_sink: *AudioBaseSink, p_provide: c_int) void;
    pub const setProvideClock = gst_audio_base_sink_set_provide_clock;

    /// Controls how clock slaving will be performed in `sink`.
    extern fn gst_audio_base_sink_set_slave_method(p_sink: *AudioBaseSink, p_method: gstaudio.AudioBaseSinkSlaveMethod) void;
    pub const setSlaveMethod = gst_audio_base_sink_set_slave_method;

    extern fn gst_audio_base_sink_get_type() usize;
    pub const getGObjectType = gst_audio_base_sink_get_type;

    extern fn g_object_ref(p_self: *gstaudio.AudioBaseSink) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstaudio.AudioBaseSink) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *AudioBaseSink, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// This is the base class for audio sources. Subclasses need to implement the
/// ::create_ringbuffer vmethod. This base class will then take care of
/// reading samples from the ringbuffer, synchronisation and flushing.
pub const AudioBaseSrc = extern struct {
    pub const Parent = gstbase.PushSrc;
    pub const Implements = [_]type{};
    pub const Class = gstaudio.AudioBaseSrcClass;
    f_element: gstbase.PushSrc,
    f_ringbuffer: ?*gstaudio.AudioRingBuffer,
    f_buffer_time: gst.ClockTime,
    f_latency_time: gst.ClockTime,
    f_next_sample: u64,
    f_clock: ?*gst.Clock,
    f_priv: ?*gstaudio.AudioBaseSrcPrivate,
    f__gst_reserved: [4]*anyopaque,

    pub const virtual_methods = struct {
        /// Create and return the `gstaudio.AudioRingBuffer` for `src`. This function will call
        /// the ::create_ringbuffer vmethod and will set `src` as the parent of the
        /// returned buffer (see `gst.Object.setParent`).
        pub const create_ringbuffer = struct {
            pub fn call(p_class: anytype, p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) ?*gstaudio.AudioRingBuffer {
                return gobject.ext.as(AudioBaseSrc.Class, p_class).f_create_ringbuffer.?(gobject.ext.as(AudioBaseSrc, p_src));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) ?*gstaudio.AudioRingBuffer) void {
                gobject.ext.as(AudioBaseSrc.Class, p_class).f_create_ringbuffer = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {
        /// Actual configured size of audio buffer in microseconds.
        pub const actual_buffer_time = struct {
            pub const name = "actual-buffer-time";

            pub const Type = i64;
        };

        /// Actual configured audio latency in microseconds.
        pub const actual_latency_time = struct {
            pub const name = "actual-latency-time";

            pub const Type = i64;
        };

        pub const buffer_time = struct {
            pub const name = "buffer-time";

            pub const Type = i64;
        };

        pub const latency_time = struct {
            pub const name = "latency-time";

            pub const Type = i64;
        };

        pub const provide_clock = struct {
            pub const name = "provide-clock";

            pub const Type = c_int;
        };

        pub const slave_method = struct {
            pub const name = "slave-method";

            pub const Type = gstaudio.AudioBaseSrcSlaveMethod;
        };
    };

    pub const signals = struct {};

    /// Create and return the `gstaudio.AudioRingBuffer` for `src`. This function will call
    /// the ::create_ringbuffer vmethod and will set `src` as the parent of the
    /// returned buffer (see `gst.Object.setParent`).
    extern fn gst_audio_base_src_create_ringbuffer(p_src: *AudioBaseSrc) ?*gstaudio.AudioRingBuffer;
    pub const createRingbuffer = gst_audio_base_src_create_ringbuffer;

    /// Queries whether `src` will provide a clock or not. See also
    /// gst_audio_base_src_set_provide_clock.
    extern fn gst_audio_base_src_get_provide_clock(p_src: *AudioBaseSrc) c_int;
    pub const getProvideClock = gst_audio_base_src_get_provide_clock;

    /// Get the current slave method used by `src`.
    extern fn gst_audio_base_src_get_slave_method(p_src: *AudioBaseSrc) gstaudio.AudioBaseSrcSlaveMethod;
    pub const getSlaveMethod = gst_audio_base_src_get_slave_method;

    /// Controls whether `src` will provide a clock or not. If `provide` is `TRUE`,
    /// `gst.Element.provideClock` will return a clock that reflects the datarate
    /// of `src`. If `provide` is `FALSE`, `gst.Element.provideClock` will return NULL.
    extern fn gst_audio_base_src_set_provide_clock(p_src: *AudioBaseSrc, p_provide: c_int) void;
    pub const setProvideClock = gst_audio_base_src_set_provide_clock;

    /// Controls how clock slaving will be performed in `src`.
    extern fn gst_audio_base_src_set_slave_method(p_src: *AudioBaseSrc, p_method: gstaudio.AudioBaseSrcSlaveMethod) void;
    pub const setSlaveMethod = gst_audio_base_src_set_slave_method;

    extern fn gst_audio_base_src_get_type() usize;
    pub const getGObjectType = gst_audio_base_src_get_type;

    extern fn g_object_ref(p_self: *gstaudio.AudioBaseSrc) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstaudio.AudioBaseSrc) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *AudioBaseSrc, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Provides a base class for CD digital audio (CDDA) sources, which handles
/// things like seeking, querying, discid calculation, tags, and buffer
/// timestamping.
///
/// ## Using GstAudioCdSrc-based elements in applications
///
/// GstAudioCdSrc registers two `gst.Format`<!-- -->s of its own, namely
/// the "track" format and the "sector" format. Applications will usually
/// only find the "track" format interesting. You can retrieve that `gst.Format`
/// for use in seek events or queries with gst_format_get_by_nick("track").
///
/// In order to query the number of tracks, for example, an application would
/// set the CDDA source element to READY or PAUSED state and then query the
/// the number of tracks via `gst.Element.queryDuration` using the track
/// format acquired above. Applications can query the currently playing track
/// in the same way.
///
/// Alternatively, applications may retrieve the currently playing track and
/// the total number of tracks from the taglist that will posted on the bus
/// whenever the CD is opened or the currently playing track changes. The
/// taglist will contain GST_TAG_TRACK_NUMBER and GST_TAG_TRACK_COUNT tags.
///
/// Applications playing back CD audio using playbin and cdda://n URIs should
/// issue a seek command in track format to change between tracks, rather than
/// setting a new cdda://n+1 URI on playbin (as setting a new URI on playbin
/// involves closing and re-opening the CD device, which is much much slower).
///
/// ## Tags and meta-information
///
/// CDDA sources will automatically emit a number of tags, details about which
/// can be found in the libgsttag documentation. Those tags are:
/// `GST_TAG_CDDA_CDDB_DISCID`, `GST_TAG_CDDA_CDDB_DISCID_FULL`,
/// `GST_TAG_CDDA_MUSICBRAINZ_DISCID`, `GST_TAG_CDDA_MUSICBRAINZ_DISCID_FULL`,
/// among others.
///
/// ## Tracks and Table of Contents (TOC)
///
/// Applications will be informed of the available tracks via a TOC message
/// on the pipeline's `gst.Bus`. The `gst.Toc` will contain a `gst.TocEntry` for
/// each track, with information about each track. The duration for each
/// track can be retrieved via the `GST_TAG_DURATION` tag from each entry's
/// tag list, or calculated via `gst.TocEntry.getStartStopTimes`.
/// The track entries in the TOC will be sorted by track number.
pub const AudioCdSrc = extern struct {
    pub const Parent = gstbase.PushSrc;
    pub const Implements = [_]type{gst.URIHandler};
    pub const Class = gstaudio.AudioCdSrcClass;
    f_pushsrc: gstbase.PushSrc,
    f_tags: ?*gst.TagList,
    f_priv: ?*gstaudio.AudioCdSrcPrivate,
    f__gst_reserved1: [2]c_uint,
    f__gst_reserved2: [2]*anyopaque,

    pub const virtual_methods = struct {
        /// closing the device
        pub const close = struct {
            pub fn call(p_class: anytype, p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) void {
                return gobject.ext.as(AudioCdSrc.Class, p_class).f_close.?(gobject.ext.as(AudioCdSrc, p_src));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) void) void {
                gobject.ext.as(AudioCdSrc.Class, p_class).f_close = @ptrCast(p_implementation);
            }
        };

        /// opening the device
        pub const open = struct {
            pub fn call(p_class: anytype, p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_device: [*:0]const u8) c_int {
                return gobject.ext.as(AudioCdSrc.Class, p_class).f_open.?(gobject.ext.as(AudioCdSrc, p_src), p_device);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_device: [*:0]const u8) callconv(.c) c_int) void {
                gobject.ext.as(AudioCdSrc.Class, p_class).f_open = @ptrCast(p_implementation);
            }
        };

        /// reading a sector
        pub const read_sector = struct {
            pub fn call(p_class: anytype, p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_sector: c_int) *gst.Buffer {
                return gobject.ext.as(AudioCdSrc.Class, p_class).f_read_sector.?(gobject.ext.as(AudioCdSrc, p_src), p_sector);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_sector: c_int) callconv(.c) *gst.Buffer) void {
                gobject.ext.as(AudioCdSrc.Class, p_class).f_read_sector = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {
        pub const device = struct {
            pub const name = "device";

            pub const Type = ?[*:0]u8;
        };

        pub const mode = struct {
            pub const name = "mode";

            pub const Type = gstaudio.AudioCdSrcMode;
        };

        pub const track = struct {
            pub const name = "track";

            pub const Type = c_uint;
        };
    };

    pub const signals = struct {};

    /// CDDA sources use this function from their start vfunc to announce the
    /// available data and audio tracks to the base source class. The caller
    /// should allocate `track` on the stack, the base source will do a shallow
    /// copy of the structure (and take ownership of the taglist if there is one).
    extern fn gst_audio_cd_src_add_track(p_src: *AudioCdSrc, p_track: *gstaudio.AudioCdSrcTrack) c_int;
    pub const addTrack = gst_audio_cd_src_add_track;

    extern fn gst_audio_cd_src_get_type() usize;
    pub const getGObjectType = gst_audio_cd_src_get_type;

    extern fn g_object_ref(p_self: *gstaudio.AudioCdSrc) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstaudio.AudioCdSrc) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *AudioCdSrc, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// `gstaudio.AudioClock` makes it easy for elements to implement a `gst.Clock`, they
/// simply need to provide a function that returns the current clock time.
///
/// This object is internally used to implement the clock in `gstaudio.AudioBaseSink`.
pub const AudioClock = extern struct {
    pub const Parent = gst.SystemClock;
    pub const Implements = [_]type{};
    pub const Class = gstaudio.AudioClockClass;
    f_clock: gst.SystemClock,
    f_func: ?gstaudio.AudioClockGetTimeFunc,
    f_user_data: ?*anyopaque,
    f_destroy_notify: ?glib.DestroyNotify,
    f_last_time: gst.ClockTime,
    f_time_offset: gst.ClockTimeDiff,
    f__gst_reserved: [4]*anyopaque,

    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    /// Create a new `gstaudio.AudioClock` instance. Whenever the clock time should be
    /// calculated it will call `func` with `user_data`. When `func` returns
    /// `GST_CLOCK_TIME_NONE`, the clock will return the last reported time.
    extern fn gst_audio_clock_new(p_name: [*:0]const u8, p_func: gstaudio.AudioClockGetTimeFunc, p_user_data: ?*anyopaque, p_destroy_notify: ?glib.DestroyNotify) *gstaudio.AudioClock;
    pub const new = gst_audio_clock_new;

    /// Adjust `time` with the internal offset of the audio clock.
    extern fn gst_audio_clock_adjust(p_clock: *AudioClock, p_time: gst.ClockTime) gst.ClockTime;
    pub const adjust = gst_audio_clock_adjust;

    /// Report the time as returned by the `gstaudio.AudioClockGetTimeFunc` without applying
    /// any offsets.
    extern fn gst_audio_clock_get_time(p_clock: *AudioClock) gst.ClockTime;
    pub const getTime = gst_audio_clock_get_time;

    /// Invalidate the clock function. Call this function when the provided
    /// `gstaudio.AudioClockGetTimeFunc` cannot be called anymore, for example, when the
    /// user_data becomes invalid.
    ///
    /// After calling this function, `clock` will return the last returned time for
    /// the rest of its lifetime.
    extern fn gst_audio_clock_invalidate(p_clock: *AudioClock) void;
    pub const invalidate = gst_audio_clock_invalidate;

    /// Inform `clock` that future calls to `gstaudio.AudioClockGetTimeFunc` will return values
    /// starting from `time`. The clock will update an internal offset to make sure that
    /// future calls to internal_time will return an increasing result as required by
    /// the `gst.Clock` object.
    extern fn gst_audio_clock_reset(p_clock: *AudioClock, p_time: gst.ClockTime) void;
    pub const reset = gst_audio_clock_reset;

    extern fn gst_audio_clock_get_type() usize;
    pub const getGObjectType = gst_audio_clock_get_type;

    extern fn g_object_ref(p_self: *gstaudio.AudioClock) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstaudio.AudioClock) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *AudioClock, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// This base class is for audio decoders turning encoded data into
/// raw audio samples.
///
/// GstAudioDecoder and subclass should cooperate as follows.
///
/// ## Configuration
///
///   * Initially, GstAudioDecoder calls `start` when the decoder element
///     is activated, which allows subclass to perform any global setup.
///     Base class (context) parameters can already be set according to subclass
///     capabilities (or possibly upon receive more information in subsequent
///     `set_format`).
///   * GstAudioDecoder calls `set_format` to inform subclass of the format
///     of input audio data that it is about to receive.
///     While unlikely, it might be called more than once, if changing input
///     parameters require reconfiguration.
///   * GstAudioDecoder calls `stop` at end of all processing.
///
/// As of configuration stage, and throughout processing, GstAudioDecoder
/// provides various (context) parameters, e.g. describing the format of
/// output audio data (valid when output caps have been set) or current parsing state.
/// Conversely, subclass can and should configure context to inform
/// base class of its expectation w.r.t. buffer handling.
///
/// ## Data processing
///     * Base class gathers input data, and optionally allows subclass
///       to parse this into subsequently manageable (as defined by subclass)
///       chunks.  Such chunks are subsequently referred to as 'frames',
///       though they may or may not correspond to 1 (or more) audio format frame.
///     * Input frame is provided to subclass' `handle_frame`.
///     * If codec processing results in decoded data, subclass should call
///       `gst_audio_decoder_finish_frame` to have decoded data pushed
///       downstream.
///     * Just prior to actually pushing a buffer downstream,
///       it is passed to `pre_push`.  Subclass should either use this callback
///       to arrange for additional downstream pushing or otherwise ensure such
///       custom pushing occurs after at least a method call has finished since
///       setting src pad caps.
///     * During the parsing process GstAudioDecoderClass will handle both
///       srcpad and sinkpad events. Sink events will be passed to subclass
///       if `event` callback has been provided.
///
/// ## Shutdown phase
///
///   * GstAudioDecoder class calls `stop` to inform the subclass that data
///     parsing will be stopped.
///
/// Subclass is responsible for providing pad template caps for
/// source and sink pads. The pads need to be named "sink" and "src". It also
/// needs to set the fixed caps on srcpad, when the format is ensured.  This
/// is typically when base class calls subclass' `set_format` function, though
/// it might be delayed until calling `gst_audio_decoder_finish_frame`.
///
/// In summary, above process should have subclass concentrating on
/// codec data processing while leaving other matters to base class,
/// such as most notably timestamp handling.  While it may exert more control
/// in this area (see e.g. `pre_push`), it is very much not recommended.
///
/// In particular, base class will try to arrange for perfect output timestamps
/// as much as possible while tracking upstream timestamps.
/// To this end, if deviation between the next ideal expected perfect timestamp
/// and upstream exceeds `gstaudio.AudioDecoder.properties.tolerance`, then resync to upstream
/// occurs (which would happen always if the tolerance mechanism is disabled).
///
/// In non-live pipelines, baseclass can also (configurably) arrange for
/// output buffer aggregation which may help to redue large(r) numbers of
/// small(er) buffers being pushed and processed downstream. Note that this
/// feature is only available if the buffer layout is interleaved. For planar
/// buffers, the decoder implementation is fully responsible for the output
/// buffer size.
///
/// On the other hand, it should be noted that baseclass only provides limited
/// seeking support (upon explicit subclass request), as full-fledged support
/// should rather be left to upstream demuxer, parser or alike.  This simple
/// approach caters for seeking and duration reporting using estimated input
/// bitrates.
///
/// Things that subclass need to take care of:
///
///   * Provide pad templates
///   * Set source pad caps when appropriate
///   * Set user-configurable properties to sane defaults for format and
///      implementing codec at hand, and convey some subclass capabilities and
///      expectations in context.
///
///   * Accept data in `handle_frame` and provide encoded results to
///      `gst_audio_decoder_finish_frame`.  If it is prepared to perform
///      PLC, it should also accept NULL data in `handle_frame` and provide for
///      data for indicated duration.
pub const AudioDecoder = extern struct {
    pub const Parent = gst.Element;
    pub const Implements = [_]type{};
    pub const Class = gstaudio.AudioDecoderClass;
    f_element: gst.Element,
    f_sinkpad: ?*gst.Pad,
    f_srcpad: ?*gst.Pad,
    f_stream_lock: glib.RecMutex,
    f_input_segment: gst.Segment,
    f_output_segment: gst.Segment,
    f_priv: ?*gstaudio.AudioDecoderPrivate,
    f__gst_reserved: [20]*anyopaque,

    pub const virtual_methods = struct {
        /// Optional.
        ///                  Called when the element changes to GST_STATE_NULL.
        ///                  Allows closing external resources.
        pub const close = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_close.?(gobject.ext.as(AudioDecoder, p_dec));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_close = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                     Setup the allocation parameters for allocating output
        ///                     buffers. The passed in query contains the result of the
        ///                     downstream allocation query.
        ///                     Subclasses should chain up to the parent implementation to
        ///                     invoke the default handler.
        pub const decide_allocation = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) c_int {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_decide_allocation.?(gobject.ext.as(AudioDecoder, p_dec), p_query);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) callconv(.c) c_int) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_decide_allocation = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Instructs subclass to clear any codec caches and discard
        ///                  any pending samples and not yet returned decoded data.
        ///                  `hard` indicates whether a FLUSH is being processed,
        ///                  or otherwise a DISCONT (or conceptually similar).
        pub const flush = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_hard: c_int) void {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_flush.?(gobject.ext.as(AudioDecoder, p_dec), p_hard);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_hard: c_int) callconv(.c) void) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_flush = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Allows for a custom sink getcaps implementation.
        ///                  If not implemented,
        ///                  default returns gst_audio_decoder_proxy_getcaps
        ///                  applied to sink template caps.
        pub const getcaps = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_filter: *gst.Caps) *gst.Caps {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_getcaps.?(gobject.ext.as(AudioDecoder, p_dec), p_filter);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_filter: *gst.Caps) callconv(.c) *gst.Caps) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_getcaps = @ptrCast(p_implementation);
            }
        };

        /// Provides input data (or NULL to clear any remaining data)
        ///                  to subclass.  Input data ref management is performed by
        ///                  base class, subclass should not care or intervene,
        ///                  and input data is only valid until next call to base class,
        ///                  most notably a call to `gstaudio.AudioDecoder.finishFrame`.
        pub const handle_frame = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_buffer: *gst.Buffer) gst.FlowReturn {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_handle_frame.?(gobject.ext.as(AudioDecoder, p_dec), p_buffer);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_buffer: *gst.Buffer) callconv(.c) gst.FlowReturn) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_handle_frame = @ptrCast(p_implementation);
            }
        };

        /// Negotiate with downstream elements to currently configured `gstaudio.AudioInfo`.
        /// Unmark GST_PAD_FLAG_NEED_RECONFIGURE in any case. But mark it again if
        /// negotiate fails.
        pub const negotiate = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_negotiate.?(gobject.ext.as(AudioDecoder, p_dec));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_negotiate = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Called when the element changes to GST_STATE_READY.
        ///                  Allows opening external resources.
        pub const open = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_open.?(gobject.ext.as(AudioDecoder, p_dec));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_open = @ptrCast(p_implementation);
            }
        };

        pub const parse = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_adapter: *gstbase.Adapter, p_offset: *c_int, p_length: *c_int) gst.FlowReturn {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_parse.?(gobject.ext.as(AudioDecoder, p_dec), p_adapter, p_offset, p_length);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_adapter: *gstbase.Adapter, p_offset: *c_int, p_length: *c_int) callconv(.c) gst.FlowReturn) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_parse = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Called just prior to pushing (encoded data) buffer downstream.
        ///                  Subclass has full discretionary access to buffer,
        ///                  and a not OK flow return will abort downstream pushing.
        pub const pre_push = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_buffer: **gst.Buffer) gst.FlowReturn {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_pre_push.?(gobject.ext.as(AudioDecoder, p_dec), p_buffer);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_buffer: **gst.Buffer) callconv(.c) gst.FlowReturn) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_pre_push = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                      Propose buffer allocation parameters for upstream elements.
        ///                      Subclasses should chain up to the parent implementation to
        ///                      invoke the default handler.
        pub const propose_allocation = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) c_int {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_propose_allocation.?(gobject.ext.as(AudioDecoder, p_dec), p_query);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) callconv(.c) c_int) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_propose_allocation = @ptrCast(p_implementation);
            }
        };

        /// Notifies subclass of incoming data format (caps).
        pub const set_format = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_caps: *gst.Caps) c_int {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_set_format.?(gobject.ext.as(AudioDecoder, p_dec), p_caps);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_caps: *gst.Caps) callconv(.c) c_int) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_set_format = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Event handler on the sink pad. Subclasses should chain up to
        ///                  the parent implementation to invoke the default handler.
        pub const sink_event = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_event: *gst.Event) c_int {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_sink_event.?(gobject.ext.as(AudioDecoder, p_dec), p_event);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_event: *gst.Event) callconv(.c) c_int) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_sink_event = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Query handler on the sink pad. This function should
        ///                  return TRUE if the query could be performed. Subclasses
        ///                  should chain up to the parent implementation to invoke the
        ///                  default handler. Since: 1.6
        pub const sink_query = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) c_int {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_sink_query.?(gobject.ext.as(AudioDecoder, p_dec), p_query);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) callconv(.c) c_int) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_sink_query = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Event handler on the src pad. Subclasses should chain up to
        ///                  the parent implementation to invoke the default handler.
        pub const src_event = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_event: *gst.Event) c_int {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_src_event.?(gobject.ext.as(AudioDecoder, p_dec), p_event);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_event: *gst.Event) callconv(.c) c_int) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_src_event = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Query handler on the source pad. This function should
        ///                  return TRUE if the query could be performed. Subclasses
        ///                  should chain up to the parent implementation to invoke the
        ///                  default handler. Since: 1.6
        pub const src_query = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) c_int {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_src_query.?(gobject.ext.as(AudioDecoder, p_dec), p_query);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) callconv(.c) c_int) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_src_query = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Called when the element starts processing.
        ///                  Allows opening external resources.
        pub const start = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_start.?(gobject.ext.as(AudioDecoder, p_dec));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_start = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Called when the element stops processing.
        ///                  Allows closing external resources.
        pub const stop = struct {
            pub fn call(p_class: anytype, p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_stop.?(gobject.ext.as(AudioDecoder, p_dec));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_dec: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_stop = @ptrCast(p_implementation);
            }
        };

        /// Optional. Transform the metadata on the input buffer to the
        ///                  output buffer. By default this method copies all meta without
        ///                  tags and meta with only the "audio" tag. subclasses can
        ///                  implement this method and return `TRUE` if the metadata is to be
        ///                  copied. Since: 1.6
        pub const transform_meta = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_outbuf: *gst.Buffer, p_meta: *gst.Meta, p_inbuf: *gst.Buffer) c_int {
                return gobject.ext.as(AudioDecoder.Class, p_class).f_transform_meta.?(gobject.ext.as(AudioDecoder, p_enc), p_outbuf, p_meta, p_inbuf);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_outbuf: *gst.Buffer, p_meta: *gst.Meta, p_inbuf: *gst.Buffer) callconv(.c) c_int) void {
                gobject.ext.as(AudioDecoder.Class, p_class).f_transform_meta = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {
        /// Maximum number of tolerated consecutive decode errors. See
        /// `gstaudio.AudioDecoder.setMaxErrors` for more details.
        pub const max_errors = struct {
            pub const name = "max-errors";

            pub const Type = c_int;
        };

        pub const min_latency = struct {
            pub const name = "min-latency";

            pub const Type = i64;
        };

        pub const plc = struct {
            pub const name = "plc";

            pub const Type = c_int;
        };

        pub const tolerance = struct {
            pub const name = "tolerance";

            pub const Type = i64;
        };
    };

    pub const signals = struct {};

    /// Helper function that allocates a buffer to hold an audio frame
    /// for `dec`'s current output format.
    extern fn gst_audio_decoder_allocate_output_buffer(p_dec: *AudioDecoder, p_size: usize) *gst.Buffer;
    pub const allocateOutputBuffer = gst_audio_decoder_allocate_output_buffer;

    /// Collects decoded data and pushes it downstream.
    ///
    /// `buf` may be NULL in which case the indicated number of frames
    /// are discarded and considered to have produced no output
    /// (e.g. lead-in or setup frames).
    /// Otherwise, source pad caps must be set when it is called with valid
    /// data in `buf`.
    ///
    /// Note that a frame received in `gstaudio.AudioDecoderClass.virtual_methods.handle_frame` may be
    /// invalidated by a call to this function.
    extern fn gst_audio_decoder_finish_frame(p_dec: *AudioDecoder, p_buf: ?*gst.Buffer, p_frames: c_int) gst.FlowReturn;
    pub const finishFrame = gst_audio_decoder_finish_frame;

    /// Collects decoded data and pushes it downstream. This function may be called
    /// multiple times for a given input frame.
    ///
    /// `buf` may be NULL in which case it is assumed that the current input frame is
    /// finished. This is equivalent to calling `gstaudio.AudioDecoder.finishSubframe`
    /// with a NULL buffer and frames=1 after having pushed out all decoded audio
    /// subframes using this function.
    ///
    /// When called with valid data in `buf` the source pad caps must have been set
    /// already.
    ///
    /// Note that a frame received in `gstaudio.AudioDecoderClass.virtual_methods.handle_frame` may be
    /// invalidated by a call to this function.
    extern fn gst_audio_decoder_finish_subframe(p_dec: *AudioDecoder, p_buf: ?*gst.Buffer) gst.FlowReturn;
    pub const finishSubframe = gst_audio_decoder_finish_subframe;

    /// Lets `gstaudio.AudioDecoder` sub-classes to know the memory `allocator`
    /// used by the base class and its `params`.
    ///
    /// Unref the `allocator` after use it.
    extern fn gst_audio_decoder_get_allocator(p_dec: *AudioDecoder, p_allocator: ?**gst.Allocator, p_params: ?*gst.AllocationParams) void;
    pub const getAllocator = gst_audio_decoder_get_allocator;

    extern fn gst_audio_decoder_get_audio_info(p_dec: *AudioDecoder) *gstaudio.AudioInfo;
    pub const getAudioInfo = gst_audio_decoder_get_audio_info;

    extern fn gst_audio_decoder_get_delay(p_dec: *AudioDecoder) c_int;
    pub const getDelay = gst_audio_decoder_get_delay;

    /// Queries decoder drain handling.
    extern fn gst_audio_decoder_get_drainable(p_dec: *AudioDecoder) c_int;
    pub const getDrainable = gst_audio_decoder_get_drainable;

    extern fn gst_audio_decoder_get_estimate_rate(p_dec: *AudioDecoder) c_int;
    pub const getEstimateRate = gst_audio_decoder_get_estimate_rate;

    /// Sets the variables pointed to by `min` and `max` to the currently configured
    /// latency.
    extern fn gst_audio_decoder_get_latency(p_dec: *AudioDecoder, p_min: ?*gst.ClockTime, p_max: ?*gst.ClockTime) void;
    pub const getLatency = gst_audio_decoder_get_latency;

    extern fn gst_audio_decoder_get_max_errors(p_dec: *AudioDecoder) c_int;
    pub const getMaxErrors = gst_audio_decoder_get_max_errors;

    /// Queries decoder's latency aggregation.
    extern fn gst_audio_decoder_get_min_latency(p_dec: *AudioDecoder) gst.ClockTime;
    pub const getMinLatency = gst_audio_decoder_get_min_latency;

    /// Queries decoder required format handling.
    extern fn gst_audio_decoder_get_needs_format(p_dec: *AudioDecoder) c_int;
    pub const getNeedsFormat = gst_audio_decoder_get_needs_format;

    /// Return current parsing (sync and eos) state.
    extern fn gst_audio_decoder_get_parse_state(p_dec: *AudioDecoder, p_sync: ?*c_int, p_eos: ?*c_int) void;
    pub const getParseState = gst_audio_decoder_get_parse_state;

    /// Queries decoder packet loss concealment handling.
    extern fn gst_audio_decoder_get_plc(p_dec: *AudioDecoder) c_int;
    pub const getPlc = gst_audio_decoder_get_plc;

    extern fn gst_audio_decoder_get_plc_aware(p_dec: *AudioDecoder) c_int;
    pub const getPlcAware = gst_audio_decoder_get_plc_aware;

    /// Queries current audio jitter tolerance threshold.
    extern fn gst_audio_decoder_get_tolerance(p_dec: *AudioDecoder) gst.ClockTime;
    pub const getTolerance = gst_audio_decoder_get_tolerance;

    /// Sets the audio decoder tags and how they should be merged with any
    /// upstream stream tags. This will override any tags previously-set
    /// with `gstaudio.AudioDecoder.mergeTags`.
    ///
    /// Note that this is provided for convenience, and the subclass is
    /// not required to use this and can still do tag handling on its own.
    extern fn gst_audio_decoder_merge_tags(p_dec: *AudioDecoder, p_tags: ?*const gst.TagList, p_mode: gst.TagMergeMode) void;
    pub const mergeTags = gst_audio_decoder_merge_tags;

    /// Negotiate with downstream elements to currently configured `gstaudio.AudioInfo`.
    /// Unmark GST_PAD_FLAG_NEED_RECONFIGURE in any case. But mark it again if
    /// negotiate fails.
    extern fn gst_audio_decoder_negotiate(p_dec: *AudioDecoder) c_int;
    pub const negotiate = gst_audio_decoder_negotiate;

    /// Returns caps that express `caps` (or sink template caps if `caps` == NULL)
    /// restricted to rate/channels/... combinations supported by downstream
    /// elements.
    extern fn gst_audio_decoder_proxy_getcaps(p_decoder: *AudioDecoder, p_caps: ?*gst.Caps, p_filter: ?*gst.Caps) *gst.Caps;
    pub const proxyGetcaps = gst_audio_decoder_proxy_getcaps;

    /// Sets a caps in allocation query which are different from the set
    /// pad's caps. Use this function before calling
    /// `gstaudio.AudioDecoder.negotiate`. Setting to `NULL` the allocation
    /// query will use the caps from the pad.
    extern fn gst_audio_decoder_set_allocation_caps(p_dec: *AudioDecoder, p_allocation_caps: ?*gst.Caps) void;
    pub const setAllocationCaps = gst_audio_decoder_set_allocation_caps;

    /// Configures decoder drain handling.  If drainable, subclass might
    /// be handed a NULL buffer to have it return any leftover decoded data.
    /// Otherwise, it is not considered so capable and will only ever be passed
    /// real data.
    ///
    /// MT safe.
    extern fn gst_audio_decoder_set_drainable(p_dec: *AudioDecoder, p_enabled: c_int) void;
    pub const setDrainable = gst_audio_decoder_set_drainable;

    /// Allows baseclass to perform byte to time estimated conversion.
    extern fn gst_audio_decoder_set_estimate_rate(p_dec: *AudioDecoder, p_enabled: c_int) void;
    pub const setEstimateRate = gst_audio_decoder_set_estimate_rate;

    /// Sets decoder latency. If the provided values changed from
    /// previously provided ones, this will also post a LATENCY message on the bus
    /// so the pipeline can reconfigure its global latency.
    extern fn gst_audio_decoder_set_latency(p_dec: *AudioDecoder, p_min: gst.ClockTime, p_max: gst.ClockTime) void;
    pub const setLatency = gst_audio_decoder_set_latency;

    /// Sets numbers of tolerated decoder errors, where a tolerated one is then only
    /// warned about, but more than tolerated will lead to fatal error. You can set
    /// -1 for never returning fatal errors. Default is set to
    /// GST_AUDIO_DECODER_MAX_ERRORS.
    extern fn gst_audio_decoder_set_max_errors(p_dec: *AudioDecoder, p_num: c_int) void;
    pub const setMaxErrors = gst_audio_decoder_set_max_errors;

    /// Sets decoder minimum aggregation latency.
    ///
    /// MT safe.
    extern fn gst_audio_decoder_set_min_latency(p_dec: *AudioDecoder, p_num: gst.ClockTime) void;
    pub const setMinLatency = gst_audio_decoder_set_min_latency;

    /// Configures decoder format needs.  If enabled, subclass needs to be
    /// negotiated with format caps before it can process any data.  It will then
    /// never be handed any data before it has been configured.
    /// Otherwise, it might be handed data without having been configured and
    /// is then expected being able to do so either by default
    /// or based on the input data.
    ///
    /// MT safe.
    extern fn gst_audio_decoder_set_needs_format(p_dec: *AudioDecoder, p_enabled: c_int) void;
    pub const setNeedsFormat = gst_audio_decoder_set_needs_format;

    /// Configure output caps on the srcpad of `dec`. Similar to
    /// `gstaudio.AudioDecoder.setOutputFormat`, but allows subclasses to specify
    /// output caps that can't be expressed via `gstaudio.AudioInfo` e.g. caps that have
    /// caps features.
    extern fn gst_audio_decoder_set_output_caps(p_dec: *AudioDecoder, p_caps: *gst.Caps) c_int;
    pub const setOutputCaps = gst_audio_decoder_set_output_caps;

    /// Configure output info on the srcpad of `dec`.
    extern fn gst_audio_decoder_set_output_format(p_dec: *AudioDecoder, p_info: *const gstaudio.AudioInfo) c_int;
    pub const setOutputFormat = gst_audio_decoder_set_output_format;

    /// Enable or disable decoder packet loss concealment, provided subclass
    /// and codec are capable and allow handling plc.
    ///
    /// MT safe.
    extern fn gst_audio_decoder_set_plc(p_dec: *AudioDecoder, p_enabled: c_int) void;
    pub const setPlc = gst_audio_decoder_set_plc;

    /// Indicates whether or not subclass handles packet loss concealment (plc).
    extern fn gst_audio_decoder_set_plc_aware(p_dec: *AudioDecoder, p_plc: c_int) void;
    pub const setPlcAware = gst_audio_decoder_set_plc_aware;

    /// Configures decoder audio jitter tolerance threshold.
    ///
    /// MT safe.
    extern fn gst_audio_decoder_set_tolerance(p_dec: *AudioDecoder, p_tolerance: gst.ClockTime) void;
    pub const setTolerance = gst_audio_decoder_set_tolerance;

    /// Lets `gstaudio.AudioDecoder` sub-classes decide if they want the sink pad
    /// to use the default pad query handler to reply to accept-caps queries.
    ///
    /// By setting this to true it is possible to further customize the default
    /// handler with `GST_PAD_SET_ACCEPT_INTERSECT` and
    /// `GST_PAD_SET_ACCEPT_TEMPLATE`
    extern fn gst_audio_decoder_set_use_default_pad_acceptcaps(p_decoder: *AudioDecoder, p_use: c_int) void;
    pub const setUseDefaultPadAcceptcaps = gst_audio_decoder_set_use_default_pad_acceptcaps;

    extern fn gst_audio_decoder_get_type() usize;
    pub const getGObjectType = gst_audio_decoder_get_type;

    extern fn g_object_ref(p_self: *gstaudio.AudioDecoder) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstaudio.AudioDecoder) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *AudioDecoder, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// This base class is for audio encoders turning raw audio samples into
/// encoded audio data.
///
/// GstAudioEncoder and subclass should cooperate as follows.
///
/// ## Configuration
///
///   * Initially, GstAudioEncoder calls `start` when the encoder element
///     is activated, which allows subclass to perform any global setup.
///
///   * GstAudioEncoder calls `set_format` to inform subclass of the format
///     of input audio data that it is about to receive.  Subclass should
///     setup for encoding and configure various base class parameters
///     appropriately, notably those directing desired input data handling.
///     While unlikely, it might be called more than once, if changing input
///     parameters require reconfiguration.
///
///   * GstAudioEncoder calls `stop` at end of all processing.
///
/// As of configuration stage, and throughout processing, GstAudioEncoder
/// maintains various parameters that provide required context,
/// e.g. describing the format of input audio data.
/// Conversely, subclass can and should configure these context parameters
/// to inform base class of its expectation w.r.t. buffer handling.
///
/// ## Data processing
///
///     * Base class gathers input sample data (as directed by the context's
///       frame_samples and frame_max) and provides this to subclass' `handle_frame`.
///     * If codec processing results in encoded data, subclass should call
///       `gstaudio.AudioEncoder.finishFrame` to have encoded data pushed
///       downstream. Alternatively, it might also call
///       `gstaudio.AudioEncoder.finishFrame` (with a NULL buffer and some number of
///       dropped samples) to indicate dropped (non-encoded) samples.
///     * Just prior to actually pushing a buffer downstream,
///       it is passed to `pre_push`.
///     * During the parsing process GstAudioEncoderClass will handle both
///       srcpad and sinkpad events. Sink events will be passed to subclass
///       if `event` callback has been provided.
///
/// ## Shutdown phase
///
///   * GstAudioEncoder class calls `stop` to inform the subclass that data
///     parsing will be stopped.
///
/// Subclass is responsible for providing pad template caps for
/// source and sink pads. The pads need to be named "sink" and "src". It also
/// needs to set the fixed caps on srcpad, when the format is ensured.  This
/// is typically when base class calls subclass' `set_format` function, though
/// it might be delayed until calling `gst_audio_encoder_finish_frame`.
///
/// In summary, above process should have subclass concentrating on
/// codec data processing while leaving other matters to base class,
/// such as most notably timestamp handling.  While it may exert more control
/// in this area (see e.g. `pre_push`), it is very much not recommended.
///
/// In particular, base class will either favor tracking upstream timestamps
/// (at the possible expense of jitter) or aim to arrange for a perfect stream of
/// output timestamps, depending on `gstaudio.AudioEncoder.properties.perfect`-timestamp.
/// However, in the latter case, the input may not be so perfect or ideal, which
/// is handled as follows.  An input timestamp is compared with the expected
/// timestamp as dictated by input sample stream and if the deviation is less
/// than `gstaudio.AudioEncoder.properties.tolerance`, the deviation is discarded.
/// Otherwise, it is considered a discontuinity and subsequent output timestamp
/// is resynced to the new position after performing configured discontinuity
/// processing.  In the non-perfect-timestamp case, an upstream variation
/// exceeding tolerance only leads to marking DISCONT on subsequent outgoing
/// (while timestamps are adjusted to upstream regardless of variation).
/// While DISCONT is also marked in the perfect-timestamp case, this one
/// optionally (see `gstaudio.AudioEncoder.properties.hard`-resync)
/// performs some additional steps, such as clipping of (early) input samples
/// or draining all currently remaining input data, depending on the direction
/// of the discontuinity.
///
/// If perfect timestamps are arranged, it is also possible to request baseclass
/// (usually set by subclass) to provide additional buffer metadata (in OFFSET
/// and OFFSET_END) fields according to granule defined semantics currently
/// needed by oggmux.  Specifically, OFFSET is set to granulepos (= sample count
/// including buffer) and OFFSET_END to corresponding timestamp (as determined
/// by same sample count and sample rate).
///
/// Things that subclass need to take care of:
///
///   * Provide pad templates
///   * Set source pad caps when appropriate
///   * Inform base class of buffer processing needs using context's
///      frame_samples and frame_bytes.
///   * Set user-configurable properties to sane defaults for format and
///      implementing codec at hand, e.g. those controlling timestamp behaviour
///      and discontinuity processing.
///   * Accept data in `handle_frame` and provide encoded results to
///      `gstaudio.AudioEncoder.finishFrame`.
pub const AudioEncoder = extern struct {
    pub const Parent = gst.Element;
    pub const Implements = [_]type{gst.Preset};
    pub const Class = gstaudio.AudioEncoderClass;
    f_element: gst.Element,
    f_sinkpad: ?*gst.Pad,
    f_srcpad: ?*gst.Pad,
    f_stream_lock: glib.RecMutex,
    f_input_segment: gst.Segment,
    f_output_segment: gst.Segment,
    f_priv: ?*gstaudio.AudioEncoderPrivate,
    f__gst_reserved: [20]*anyopaque,

    pub const virtual_methods = struct {
        /// Optional.
        ///                  Called when the element changes to GST_STATE_NULL.
        ///                  Allows closing external resources.
        pub const close = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_close.?(gobject.ext.as(AudioEncoder, p_enc));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_close = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                     Setup the allocation parameters for allocating output
        ///                     buffers. The passed in query contains the result of the
        ///                     downstream allocation query.
        ///                     Subclasses should chain up to the parent implementation to
        ///                     invoke the default handler.
        pub const decide_allocation = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) c_int {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_decide_allocation.?(gobject.ext.as(AudioEncoder, p_enc), p_query);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) callconv(.c) c_int) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_decide_allocation = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Instructs subclass to clear any codec caches and discard
        ///                  any pending samples and not yet returned encoded data.
        pub const flush = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) void {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_flush.?(gobject.ext.as(AudioEncoder, p_enc));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) void) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_flush = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Allows for a custom sink getcaps implementation (e.g.
        ///                  for multichannel input specification).  If not implemented,
        ///                  default returns gst_audio_encoder_proxy_getcaps
        ///                  applied to sink template caps.
        pub const getcaps = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_filter: *gst.Caps) *gst.Caps {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_getcaps.?(gobject.ext.as(AudioEncoder, p_enc), p_filter);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_filter: *gst.Caps) callconv(.c) *gst.Caps) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_getcaps = @ptrCast(p_implementation);
            }
        };

        /// Provides input samples (or NULL to clear any remaining data)
        ///                  according to directions as configured by the subclass
        ///                  using the API.  Input data ref management is performed
        ///                  by base class, subclass should not care or intervene,
        ///                  and input data is only valid until next call to base class,
        ///                  most notably a call to `gstaudio.AudioEncoder.finishFrame`.
        pub const handle_frame = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_buffer: *gst.Buffer) gst.FlowReturn {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_handle_frame.?(gobject.ext.as(AudioEncoder, p_enc), p_buffer);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_buffer: *gst.Buffer) callconv(.c) gst.FlowReturn) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_handle_frame = @ptrCast(p_implementation);
            }
        };

        /// Negotiate with downstream elements to currently configured `gst.Caps`.
        /// Unmark GST_PAD_FLAG_NEED_RECONFIGURE in any case. But mark it again if
        /// negotiate fails.
        pub const negotiate = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_negotiate.?(gobject.ext.as(AudioEncoder, p_enc));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_negotiate = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Called when the element changes to GST_STATE_READY.
        ///                  Allows opening external resources.
        pub const open = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_open.?(gobject.ext.as(AudioEncoder, p_enc));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_open = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Called just prior to pushing (encoded data) buffer downstream.
        ///                  Subclass has full discretionary access to buffer,
        ///                  and a not OK flow return will abort downstream pushing.
        pub const pre_push = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_buffer: **gst.Buffer) gst.FlowReturn {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_pre_push.?(gobject.ext.as(AudioEncoder, p_enc), p_buffer);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_buffer: **gst.Buffer) callconv(.c) gst.FlowReturn) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_pre_push = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                      Propose buffer allocation parameters for upstream elements.
        ///                      Subclasses should chain up to the parent implementation to
        ///                      invoke the default handler.
        pub const propose_allocation = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) c_int {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_propose_allocation.?(gobject.ext.as(AudioEncoder, p_enc), p_query);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) callconv(.c) c_int) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_propose_allocation = @ptrCast(p_implementation);
            }
        };

        /// Notifies subclass of incoming data format.
        ///                  GstAudioInfo contains the format according to provided caps.
        pub const set_format = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_info: *gstaudio.AudioInfo) c_int {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_set_format.?(gobject.ext.as(AudioEncoder, p_enc), p_info);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_info: *gstaudio.AudioInfo) callconv(.c) c_int) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_set_format = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Event handler on the sink pad. Subclasses should chain up to
        ///                  the parent implementation to invoke the default handler.
        pub const sink_event = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_event: *gst.Event) c_int {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_sink_event.?(gobject.ext.as(AudioEncoder, p_enc), p_event);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_event: *gst.Event) callconv(.c) c_int) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_sink_event = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Query handler on the sink pad. This function should
        ///                  return TRUE if the query could be performed. Subclasses
        ///                  should chain up to the parent implementation to invoke the
        ///                  default handler. Since: 1.6
        pub const sink_query = struct {
            pub fn call(p_class: anytype, p_encoder: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) c_int {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_sink_query.?(gobject.ext.as(AudioEncoder, p_encoder), p_query);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_encoder: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) callconv(.c) c_int) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_sink_query = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Event handler on the src pad. Subclasses should chain up to
        ///                  the parent implementation to invoke the default handler.
        pub const src_event = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_event: *gst.Event) c_int {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_src_event.?(gobject.ext.as(AudioEncoder, p_enc), p_event);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_event: *gst.Event) callconv(.c) c_int) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_src_event = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Query handler on the source pad. This function should
        ///                  return TRUE if the query could be performed. Subclasses
        ///                  should chain up to the parent implementation to invoke the
        ///                  default handler. Since: 1.6
        pub const src_query = struct {
            pub fn call(p_class: anytype, p_encoder: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) c_int {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_src_query.?(gobject.ext.as(AudioEncoder, p_encoder), p_query);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_encoder: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_query: *gst.Query) callconv(.c) c_int) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_src_query = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Called when the element starts processing.
        ///                  Allows opening external resources.
        pub const start = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_start.?(gobject.ext.as(AudioEncoder, p_enc));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_start = @ptrCast(p_implementation);
            }
        };

        /// Optional.
        ///                  Called when the element stops processing.
        ///                  Allows closing external resources.
        pub const stop = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_stop.?(gobject.ext.as(AudioEncoder, p_enc));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_stop = @ptrCast(p_implementation);
            }
        };

        /// Optional. Transform the metadata on the input buffer to the
        ///                  output buffer. By default this method copies all meta without
        ///                  tags and meta with only the "audio" tag. subclasses can
        ///                  implement this method and return `TRUE` if the metadata is to be
        ///                  copied. Since: 1.6
        pub const transform_meta = struct {
            pub fn call(p_class: anytype, p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_outbuf: *gst.Buffer, p_meta: *gst.Meta, p_inbuf: *gst.Buffer) c_int {
                return gobject.ext.as(AudioEncoder.Class, p_class).f_transform_meta.?(gobject.ext.as(AudioEncoder, p_enc), p_outbuf, p_meta, p_inbuf);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_enc: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_outbuf: *gst.Buffer, p_meta: *gst.Meta, p_inbuf: *gst.Buffer) callconv(.c) c_int) void {
                gobject.ext.as(AudioEncoder.Class, p_class).f_transform_meta = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {
        pub const hard_resync = struct {
            pub const name = "hard-resync";

            pub const Type = c_int;
        };

        pub const mark_granule = struct {
            pub const name = "mark-granule";

            pub const Type = c_int;
        };

        pub const perfect_timestamp = struct {
            pub const name = "perfect-timestamp";

            pub const Type = c_int;
        };

        pub const tolerance = struct {
            pub const name = "tolerance";

            pub const Type = i64;
        };
    };

    pub const signals = struct {};

    /// Helper function that allocates a buffer to hold an encoded audio frame
    /// for `enc`'s current output format.
    extern fn gst_audio_encoder_allocate_output_buffer(p_enc: *AudioEncoder, p_size: usize) *gst.Buffer;
    pub const allocateOutputBuffer = gst_audio_encoder_allocate_output_buffer;

    /// Collects encoded data and pushes encoded data downstream.
    /// Source pad caps must be set when this is called.
    ///
    /// If `samples` < 0, then best estimate is all samples provided to encoder
    /// (subclass) so far.  `buf` may be NULL, in which case next number of `samples`
    /// are considered discarded, e.g. as a result of discontinuous transmission,
    /// and a discontinuity is marked.
    ///
    /// Note that samples received in `gstaudio.AudioEncoderClass.virtual_methods.handle_frame`
    /// may be invalidated by a call to this function.
    extern fn gst_audio_encoder_finish_frame(p_enc: *AudioEncoder, p_buffer: ?*gst.Buffer, p_samples: c_int) gst.FlowReturn;
    pub const finishFrame = gst_audio_encoder_finish_frame;

    /// Lets `gstaudio.AudioEncoder` sub-classes to know the memory `allocator`
    /// used by the base class and its `params`.
    ///
    /// Unref the `allocator` after use it.
    extern fn gst_audio_encoder_get_allocator(p_enc: *AudioEncoder, p_allocator: ?**gst.Allocator, p_params: ?*gst.AllocationParams) void;
    pub const getAllocator = gst_audio_encoder_get_allocator;

    extern fn gst_audio_encoder_get_audio_info(p_enc: *AudioEncoder) *gstaudio.AudioInfo;
    pub const getAudioInfo = gst_audio_encoder_get_audio_info;

    /// Queries encoder drain handling.
    extern fn gst_audio_encoder_get_drainable(p_enc: *AudioEncoder) c_int;
    pub const getDrainable = gst_audio_encoder_get_drainable;

    extern fn gst_audio_encoder_get_frame_max(p_enc: *AudioEncoder) c_int;
    pub const getFrameMax = gst_audio_encoder_get_frame_max;

    extern fn gst_audio_encoder_get_frame_samples_max(p_enc: *AudioEncoder) c_int;
    pub const getFrameSamplesMax = gst_audio_encoder_get_frame_samples_max;

    extern fn gst_audio_encoder_get_frame_samples_min(p_enc: *AudioEncoder) c_int;
    pub const getFrameSamplesMin = gst_audio_encoder_get_frame_samples_min;

    /// Queries encoder hard minimum handling.
    extern fn gst_audio_encoder_get_hard_min(p_enc: *AudioEncoder) c_int;
    pub const getHardMin = gst_audio_encoder_get_hard_min;

    extern fn gst_audio_encoder_get_hard_resync(p_enc: *AudioEncoder) c_int;
    pub const getHardResync = gst_audio_encoder_get_hard_resync;

    /// Sets the variables pointed to by `min` and `max` to the currently configured
    /// latency.
    extern fn gst_audio_encoder_get_latency(p_enc: *AudioEncoder, p_min: ?*gst.ClockTime, p_max: ?*gst.ClockTime) void;
    pub const getLatency = gst_audio_encoder_get_latency;

    extern fn gst_audio_encoder_get_lookahead(p_enc: *AudioEncoder) c_int;
    pub const getLookahead = gst_audio_encoder_get_lookahead;

    /// Queries if the encoder will handle granule marking.
    extern fn gst_audio_encoder_get_mark_granule(p_enc: *AudioEncoder) c_int;
    pub const getMarkGranule = gst_audio_encoder_get_mark_granule;

    /// Queries encoder perfect timestamp behaviour.
    extern fn gst_audio_encoder_get_perfect_timestamp(p_enc: *AudioEncoder) c_int;
    pub const getPerfectTimestamp = gst_audio_encoder_get_perfect_timestamp;

    /// Queries current audio jitter tolerance threshold.
    extern fn gst_audio_encoder_get_tolerance(p_enc: *AudioEncoder) gst.ClockTime;
    pub const getTolerance = gst_audio_encoder_get_tolerance;

    /// Sets the audio encoder tags and how they should be merged with any
    /// upstream stream tags. This will override any tags previously-set
    /// with `gstaudio.AudioEncoder.mergeTags`.
    ///
    /// Note that this is provided for convenience, and the subclass is
    /// not required to use this and can still do tag handling on its own.
    ///
    /// MT safe.
    extern fn gst_audio_encoder_merge_tags(p_enc: *AudioEncoder, p_tags: ?*const gst.TagList, p_mode: gst.TagMergeMode) void;
    pub const mergeTags = gst_audio_encoder_merge_tags;

    /// Negotiate with downstream elements to currently configured `gst.Caps`.
    /// Unmark GST_PAD_FLAG_NEED_RECONFIGURE in any case. But mark it again if
    /// negotiate fails.
    extern fn gst_audio_encoder_negotiate(p_enc: *AudioEncoder) c_int;
    pub const negotiate = gst_audio_encoder_negotiate;

    /// Returns caps that express `caps` (or sink template caps if `caps` == NULL)
    /// restricted to channel/rate combinations supported by downstream elements
    /// (e.g. muxers).
    extern fn gst_audio_encoder_proxy_getcaps(p_enc: *AudioEncoder, p_caps: ?*gst.Caps, p_filter: ?*gst.Caps) *gst.Caps;
    pub const proxyGetcaps = gst_audio_encoder_proxy_getcaps;

    /// Sets a caps in allocation query which are different from the set
    /// pad's caps. Use this function before calling
    /// `gstaudio.AudioEncoder.negotiate`. Setting to `NULL` the allocation
    /// query will use the caps from the pad.
    extern fn gst_audio_encoder_set_allocation_caps(p_enc: *AudioEncoder, p_allocation_caps: ?*gst.Caps) void;
    pub const setAllocationCaps = gst_audio_encoder_set_allocation_caps;

    /// Configures encoder drain handling.  If drainable, subclass might
    /// be handed a NULL buffer to have it return any leftover encoded data.
    /// Otherwise, it is not considered so capable and will only ever be passed
    /// real data.
    ///
    /// MT safe.
    extern fn gst_audio_encoder_set_drainable(p_enc: *AudioEncoder, p_enabled: c_int) void;
    pub const setDrainable = gst_audio_encoder_set_drainable;

    /// Sets max number of frames accepted at once (assumed minimally 1).
    /// Requires `frame_samples_min` and `frame_samples_max` to be the equal.
    ///
    /// Note: This value will be reset to 0 every time before
    /// `gstaudio.AudioEncoderClass.virtual_methods.set_format` is called.
    extern fn gst_audio_encoder_set_frame_max(p_enc: *AudioEncoder, p_num: c_int) void;
    pub const setFrameMax = gst_audio_encoder_set_frame_max;

    /// Sets number of samples (per channel) subclass needs to be handed,
    /// at most or will be handed all available if 0.
    ///
    /// If an exact number of samples is required, `gstaudio.AudioEncoder.setFrameSamplesMin`
    /// must be called with the same number.
    ///
    /// Note: This value will be reset to 0 every time before
    /// `gstaudio.AudioEncoderClass.virtual_methods.set_format` is called.
    extern fn gst_audio_encoder_set_frame_samples_max(p_enc: *AudioEncoder, p_num: c_int) void;
    pub const setFrameSamplesMax = gst_audio_encoder_set_frame_samples_max;

    /// Sets number of samples (per channel) subclass needs to be handed,
    /// at least or will be handed all available if 0.
    ///
    /// If an exact number of samples is required, `gstaudio.AudioEncoder.setFrameSamplesMax`
    /// must be called with the same number.
    ///
    /// Note: This value will be reset to 0 every time before
    /// `gstaudio.AudioEncoderClass.virtual_methods.set_format` is called.
    extern fn gst_audio_encoder_set_frame_samples_min(p_enc: *AudioEncoder, p_num: c_int) void;
    pub const setFrameSamplesMin = gst_audio_encoder_set_frame_samples_min;

    /// Configures encoder hard minimum handling.  If enabled, subclass
    /// will never be handed less samples than it configured, which otherwise
    /// might occur near end-of-data handling.  Instead, the leftover samples
    /// will simply be discarded.
    ///
    /// MT safe.
    extern fn gst_audio_encoder_set_hard_min(p_enc: *AudioEncoder, p_enabled: c_int) void;
    pub const setHardMin = gst_audio_encoder_set_hard_min;

    extern fn gst_audio_encoder_set_hard_resync(p_enc: *AudioEncoder, p_enabled: c_int) void;
    pub const setHardResync = gst_audio_encoder_set_hard_resync;

    /// Set the codec headers to be sent downstream whenever requested.
    extern fn gst_audio_encoder_set_headers(p_enc: *AudioEncoder, p_headers: *glib.List) void;
    pub const setHeaders = gst_audio_encoder_set_headers;

    /// Sets encoder latency. If the provided values changed from
    /// previously provided ones, this will also post a LATENCY message on the bus
    /// so the pipeline can reconfigure its global latency.
    extern fn gst_audio_encoder_set_latency(p_enc: *AudioEncoder, p_min: gst.ClockTime, p_max: gst.ClockTime) void;
    pub const setLatency = gst_audio_encoder_set_latency;

    /// Sets encoder lookahead (in units of input rate samples)
    ///
    /// Note: This value will be reset to 0 every time before
    /// `gstaudio.AudioEncoderClass.virtual_methods.set_format` is called.
    extern fn gst_audio_encoder_set_lookahead(p_enc: *AudioEncoder, p_num: c_int) void;
    pub const setLookahead = gst_audio_encoder_set_lookahead;

    /// Enable or disable encoder granule handling.
    ///
    /// MT safe.
    extern fn gst_audio_encoder_set_mark_granule(p_enc: *AudioEncoder, p_enabled: c_int) void;
    pub const setMarkGranule = gst_audio_encoder_set_mark_granule;

    /// Configure output caps on the srcpad of `enc`.
    extern fn gst_audio_encoder_set_output_format(p_enc: *AudioEncoder, p_caps: *gst.Caps) c_int;
    pub const setOutputFormat = gst_audio_encoder_set_output_format;

    /// Enable or disable encoder perfect output timestamp preference.
    ///
    /// MT safe.
    extern fn gst_audio_encoder_set_perfect_timestamp(p_enc: *AudioEncoder, p_enabled: c_int) void;
    pub const setPerfectTimestamp = gst_audio_encoder_set_perfect_timestamp;

    /// Configures encoder audio jitter tolerance threshold.
    ///
    /// MT safe.
    extern fn gst_audio_encoder_set_tolerance(p_enc: *AudioEncoder, p_tolerance: gst.ClockTime) void;
    pub const setTolerance = gst_audio_encoder_set_tolerance;

    extern fn gst_audio_encoder_get_type() usize;
    pub const getGObjectType = gst_audio_encoder_get_type;

    extern fn g_object_ref(p_self: *gstaudio.AudioEncoder) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstaudio.AudioEncoder) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *AudioEncoder, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// `gstaudio.AudioFilter` is a `gstbase.BaseTransform`<!-- -->-derived base class for simple audio
/// filters, ie. those that output the same format that they get as input.
///
/// `gstaudio.AudioFilter` will parse the input format for you (with error checking)
/// before calling your setup function. Also, elements deriving from
/// `gstaudio.AudioFilter` may use `gstaudio.AudioFilterClass.addPadTemplates` from
/// their class_init function to easily configure the set of caps/formats that
/// the element is able to handle.
///
/// Derived classes should override the `gstaudio.AudioFilterClass.virtual_methods.setup` and
/// `gstbase.BaseTransformClass.virtual_methods.transform_ip` and/or
/// `gstbase.BaseTransformClass.virtual_methods.transform`
/// virtual functions in their class_init function.
pub const AudioFilter = extern struct {
    pub const Parent = gstbase.BaseTransform;
    pub const Implements = [_]type{};
    pub const Class = gstaudio.AudioFilterClass;
    f_basetransform: gstbase.BaseTransform,
    f_info: gstaudio.AudioInfo,
    f__gst_reserved: [4]*anyopaque,

    pub const virtual_methods = struct {
        /// virtual function called whenever the format changes
        pub const setup = struct {
            pub fn call(p_class: anytype, p_filter: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_info: *const gstaudio.AudioInfo) c_int {
                return gobject.ext.as(AudioFilter.Class, p_class).f_setup.?(gobject.ext.as(AudioFilter, p_filter), p_info);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_filter: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_info: *const gstaudio.AudioInfo) callconv(.c) c_int) void {
                gobject.ext.as(AudioFilter.Class, p_class).f_setup = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {};

    pub const signals = struct {};

    extern fn gst_audio_filter_get_type() usize;
    pub const getGObjectType = gst_audio_filter_get_type;

    extern fn g_object_ref(p_self: *gstaudio.AudioFilter) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstaudio.AudioFilter) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *AudioFilter, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// This object is the base class for audio ringbuffers used by the base
/// audio source and sink classes.
///
/// The ringbuffer abstracts a circular buffer of data. One reader and
/// one writer can operate on the data from different threads in a lockfree
/// manner. The base class is sufficiently flexible to be used as an
/// abstraction for DMA based ringbuffers as well as a pure software
/// implementations.
pub const AudioRingBuffer = extern struct {
    pub const Parent = gst.Object;
    pub const Implements = [_]type{};
    pub const Class = gstaudio.AudioRingBufferClass;
    f_object: gst.Object,
    /// used to signal start/stop/pause/resume actions
    f_cond: glib.Cond,
    /// boolean indicating that the ringbuffer is open
    f_open: c_int,
    /// boolean indicating that the ringbuffer is acquired
    f_acquired: c_int,
    /// data in the ringbuffer
    f_memory: ?*u8,
    /// size of data in the ringbuffer
    f_size: usize,
    f_timestamps: ?*gst.ClockTime,
    /// format and layout of the ringbuffer data
    f_spec: gstaudio.AudioRingBufferSpec,
    /// number of samples in one segment
    f_samples_per_seg: c_int,
    /// pointer to memory holding one segment of silence samples
    f_empty_seg: ?*u8,
    /// state of the buffer
    f_state: c_int,
    /// readpointer in the ringbuffer
    f_segdone: c_int,
    /// segment corresponding to segment 0 (unused)
    f_segbase: c_int,
    /// is a reader or writer waiting for a free segment
    f_waiting: c_int,
    f_callback: ?gstaudio.AudioRingBufferCallback,
    f_cb_data: ?*anyopaque,
    f_need_reorder: c_int,
    f_channel_reorder_map: [64]c_int,
    f_flushing: c_int,
    f_may_start: c_int,
    f_active: c_int,
    f_cb_data_notify: ?glib.DestroyNotify,
    f_priv: ?*gstaudio.AudioRingBufferPrivate,
    f__gst_reserved: [2]*anyopaque,

    pub const virtual_methods = struct {
        /// Allocate the resources for the ringbuffer. This function fills
        /// in the data pointer of the ring buffer with a valid `gst.Buffer`
        /// to which samples can be written.
        pub const acquire = struct {
            pub fn call(p_class: anytype, p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_spec: *gstaudio.AudioRingBufferSpec) c_int {
                return gobject.ext.as(AudioRingBuffer.Class, p_class).f_acquire.?(gobject.ext.as(AudioRingBuffer, p_buf), p_spec);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_spec: *gstaudio.AudioRingBufferSpec) callconv(.c) c_int) void {
                gobject.ext.as(AudioRingBuffer.Class, p_class).f_acquire = @ptrCast(p_implementation);
            }
        };

        /// Activate `buf` to start or stop pulling data.
        ///
        /// MT safe.
        pub const activate = struct {
            pub fn call(p_class: anytype, p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_active: c_int) c_int {
                return gobject.ext.as(AudioRingBuffer.Class, p_class).f_activate.?(gobject.ext.as(AudioRingBuffer, p_buf), p_active);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_active: c_int) callconv(.c) c_int) void {
                gobject.ext.as(AudioRingBuffer.Class, p_class).f_activate = @ptrCast(p_implementation);
            }
        };

        /// Clear all samples from the ringbuffer.
        ///
        /// MT safe.
        pub const clear_all = struct {
            pub fn call(p_class: anytype, p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) void {
                return gobject.ext.as(AudioRingBuffer.Class, p_class).f_clear_all.?(gobject.ext.as(AudioRingBuffer, p_buf));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) void) void {
                gobject.ext.as(AudioRingBuffer.Class, p_class).f_clear_all = @ptrCast(p_implementation);
            }
        };

        /// Close the audio device associated with the ring buffer. The ring buffer
        /// should already have been released via `gstaudio.AudioRingBuffer.release`.
        pub const close_device = struct {
            pub fn call(p_class: anytype, p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioRingBuffer.Class, p_class).f_close_device.?(gobject.ext.as(AudioRingBuffer, p_buf));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioRingBuffer.Class, p_class).f_close_device = @ptrCast(p_implementation);
            }
        };

        /// Commit `in_samples` samples pointed to by `data` to the ringbuffer `buf`.
        ///
        /// `in_samples` and `out_samples` define the rate conversion to perform on the
        /// samples in `data`. For negative rates, `out_samples` must be negative and
        /// `in_samples` positive.
        ///
        /// When `out_samples` is positive, the first sample will be written at position `sample`
        /// in the ringbuffer. When `out_samples` is negative, the last sample will be written to
        /// `sample` in reverse order.
        ///
        /// `out_samples` does not need to be a multiple of the segment size of the ringbuffer
        /// although it is recommended for optimal performance.
        ///
        /// `accum` will hold a temporary accumulator used in rate conversion and should be
        /// set to 0 when this function is first called. In case the commit operation is
        /// interrupted, one can resume the processing by passing the previously returned
        /// `accum` value back to this function.
        ///
        /// MT safe.
        pub const commit = struct {
            pub fn call(p_class: anytype, p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_sample: *u64, p_data: [*]u8, p_in_samples: c_int, p_out_samples: c_int, p_accum: *c_int) c_uint {
                return gobject.ext.as(AudioRingBuffer.Class, p_class).f_commit.?(gobject.ext.as(AudioRingBuffer, p_buf), p_sample, p_data, p_in_samples, p_out_samples, p_accum);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_sample: *u64, p_data: [*]u8, p_in_samples: c_int, p_out_samples: c_int, p_accum: *c_int) callconv(.c) c_uint) void {
                gobject.ext.as(AudioRingBuffer.Class, p_class).f_commit = @ptrCast(p_implementation);
            }
        };

        /// Get the number of samples queued in the audio device. This is
        /// usually less than the segment size but can be bigger when the
        /// implementation uses another internal buffer between the audio
        /// device.
        ///
        /// For playback ringbuffers this is the amount of samples transferred from the
        /// ringbuffer to the device but still not played.
        ///
        /// For capture ringbuffers this is the amount of samples in the device that are
        /// not yet transferred to the ringbuffer.
        pub const delay = struct {
            pub fn call(p_class: anytype, p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_uint {
                return gobject.ext.as(AudioRingBuffer.Class, p_class).f_delay.?(gobject.ext.as(AudioRingBuffer, p_buf));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_uint) void {
                gobject.ext.as(AudioRingBuffer.Class, p_class).f_delay = @ptrCast(p_implementation);
            }
        };

        /// Open the audio device associated with the ring buffer. Does not perform any
        /// setup on the device. You must open the device before acquiring the ring
        /// buffer.
        pub const open_device = struct {
            pub fn call(p_class: anytype, p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioRingBuffer.Class, p_class).f_open_device.?(gobject.ext.as(AudioRingBuffer, p_buf));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioRingBuffer.Class, p_class).f_open_device = @ptrCast(p_implementation);
            }
        };

        /// Pause processing samples from the ringbuffer.
        pub const pause = struct {
            pub fn call(p_class: anytype, p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioRingBuffer.Class, p_class).f_pause.?(gobject.ext.as(AudioRingBuffer, p_buf));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioRingBuffer.Class, p_class).f_pause = @ptrCast(p_implementation);
            }
        };

        /// Free the resources of the ringbuffer.
        pub const release = struct {
            pub fn call(p_class: anytype, p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioRingBuffer.Class, p_class).f_release.?(gobject.ext.as(AudioRingBuffer, p_buf));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioRingBuffer.Class, p_class).f_release = @ptrCast(p_implementation);
            }
        };

        /// resume processing of samples after pause
        pub const @"resume" = struct {
            pub fn call(p_class: anytype, p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioRingBuffer.Class, p_class).f_resume.?(gobject.ext.as(AudioRingBuffer, p_buf));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioRingBuffer.Class, p_class).f_resume = @ptrCast(p_implementation);
            }
        };

        /// Start processing samples from the ringbuffer.
        pub const start = struct {
            pub fn call(p_class: anytype, p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioRingBuffer.Class, p_class).f_start.?(gobject.ext.as(AudioRingBuffer, p_buf));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioRingBuffer.Class, p_class).f_start = @ptrCast(p_implementation);
            }
        };

        /// Stop processing samples from the ringbuffer.
        pub const stop = struct {
            pub fn call(p_class: anytype, p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioRingBuffer.Class, p_class).f_stop.?(gobject.ext.as(AudioRingBuffer, p_buf));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_buf: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioRingBuffer.Class, p_class).f_stop = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {};

    pub const signals = struct {};

    /// Print debug info about the buffer sized in `spec` to the debug log.
    extern fn gst_audio_ring_buffer_debug_spec_buff(p_spec: *gstaudio.AudioRingBufferSpec) void;
    pub const debugSpecBuff = gst_audio_ring_buffer_debug_spec_buff;

    /// Print debug info about the parsed caps in `spec` to the debug log.
    extern fn gst_audio_ring_buffer_debug_spec_caps(p_spec: *gstaudio.AudioRingBufferSpec) void;
    pub const debugSpecCaps = gst_audio_ring_buffer_debug_spec_caps;

    /// Parse `caps` into `spec`.
    extern fn gst_audio_ring_buffer_parse_caps(p_spec: *gstaudio.AudioRingBufferSpec, p_caps: *gst.Caps) c_int;
    pub const parseCaps = gst_audio_ring_buffer_parse_caps;

    /// Allocate the resources for the ringbuffer. This function fills
    /// in the data pointer of the ring buffer with a valid `gst.Buffer`
    /// to which samples can be written.
    extern fn gst_audio_ring_buffer_acquire(p_buf: *AudioRingBuffer, p_spec: *gstaudio.AudioRingBufferSpec) c_int;
    pub const acquire = gst_audio_ring_buffer_acquire;

    /// Activate `buf` to start or stop pulling data.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_activate(p_buf: *AudioRingBuffer, p_active: c_int) c_int;
    pub const activate = gst_audio_ring_buffer_activate;

    /// Subclasses should call this function to notify the fact that
    /// `advance` segments are now processed by the device.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_advance(p_buf: *AudioRingBuffer, p_advance: c_uint) void;
    pub const advance = gst_audio_ring_buffer_advance;

    /// Clear the given segment of the buffer with silence samples.
    /// This function is used by subclasses.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_clear(p_buf: *AudioRingBuffer, p_segment: c_int) void;
    pub const clear = gst_audio_ring_buffer_clear;

    /// Clear all samples from the ringbuffer.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_clear_all(p_buf: *AudioRingBuffer) void;
    pub const clearAll = gst_audio_ring_buffer_clear_all;

    /// Close the audio device associated with the ring buffer. The ring buffer
    /// should already have been released via `gstaudio.AudioRingBuffer.release`.
    extern fn gst_audio_ring_buffer_close_device(p_buf: *AudioRingBuffer) c_int;
    pub const closeDevice = gst_audio_ring_buffer_close_device;

    /// Commit `in_samples` samples pointed to by `data` to the ringbuffer `buf`.
    ///
    /// `in_samples` and `out_samples` define the rate conversion to perform on the
    /// samples in `data`. For negative rates, `out_samples` must be negative and
    /// `in_samples` positive.
    ///
    /// When `out_samples` is positive, the first sample will be written at position `sample`
    /// in the ringbuffer. When `out_samples` is negative, the last sample will be written to
    /// `sample` in reverse order.
    ///
    /// `out_samples` does not need to be a multiple of the segment size of the ringbuffer
    /// although it is recommended for optimal performance.
    ///
    /// `accum` will hold a temporary accumulator used in rate conversion and should be
    /// set to 0 when this function is first called. In case the commit operation is
    /// interrupted, one can resume the processing by passing the previously returned
    /// `accum` value back to this function.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_commit(p_buf: *AudioRingBuffer, p_sample: *u64, p_data: [*]u8, p_in_samples: c_int, p_out_samples: c_int, p_accum: *c_int) c_uint;
    pub const commit = gst_audio_ring_buffer_commit;

    /// Convert `src_val` in `src_fmt` to the equivalent value in `dest_fmt`. The result
    /// will be put in `dest_val`.
    extern fn gst_audio_ring_buffer_convert(p_buf: *AudioRingBuffer, p_src_fmt: gst.Format, p_src_val: i64, p_dest_fmt: gst.Format, p_dest_val: *i64) c_int;
    pub const convert = gst_audio_ring_buffer_convert;

    /// Get the number of samples queued in the audio device. This is
    /// usually less than the segment size but can be bigger when the
    /// implementation uses another internal buffer between the audio
    /// device.
    ///
    /// For playback ringbuffers this is the amount of samples transferred from the
    /// ringbuffer to the device but still not played.
    ///
    /// For capture ringbuffers this is the amount of samples in the device that are
    /// not yet transferred to the ringbuffer.
    extern fn gst_audio_ring_buffer_delay(p_buf: *AudioRingBuffer) c_uint;
    pub const delay = gst_audio_ring_buffer_delay;

    /// Checks the status of the device associated with the ring buffer.
    extern fn gst_audio_ring_buffer_device_is_open(p_buf: *AudioRingBuffer) c_int;
    pub const deviceIsOpen = gst_audio_ring_buffer_device_is_open;

    /// Gets the current segment base number of the ringbuffer.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_get_segbase(p_buf: *AudioRingBuffer) u64;
    pub const getSegbase = gst_audio_ring_buffer_get_segbase;

    /// Gets the current segment number of the ringbuffer.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_get_segdone(p_buf: *AudioRingBuffer) u64;
    pub const getSegdone = gst_audio_ring_buffer_get_segdone;

    /// Check if the ringbuffer is acquired and ready to use.
    extern fn gst_audio_ring_buffer_is_acquired(p_buf: *AudioRingBuffer) c_int;
    pub const isAcquired = gst_audio_ring_buffer_is_acquired;

    /// Check if `buf` is activated.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_is_active(p_buf: *AudioRingBuffer) c_int;
    pub const isActive = gst_audio_ring_buffer_is_active;

    /// Check if `buf` is flushing.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_is_flushing(p_buf: *AudioRingBuffer) c_int;
    pub const isFlushing = gst_audio_ring_buffer_is_flushing;

    /// Tell the ringbuffer that it is allowed to start playback when
    /// the ringbuffer is filled with samples.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_may_start(p_buf: *AudioRingBuffer, p_allowed: c_int) void;
    pub const mayStart = gst_audio_ring_buffer_may_start;

    /// Open the audio device associated with the ring buffer. Does not perform any
    /// setup on the device. You must open the device before acquiring the ring
    /// buffer.
    extern fn gst_audio_ring_buffer_open_device(p_buf: *AudioRingBuffer) c_int;
    pub const openDevice = gst_audio_ring_buffer_open_device;

    /// Pause processing samples from the ringbuffer.
    extern fn gst_audio_ring_buffer_pause(p_buf: *AudioRingBuffer) c_int;
    pub const pause = gst_audio_ring_buffer_pause;

    /// Returns a pointer to memory where the data from segment `segment`
    /// can be found. This function is mostly used by subclasses.
    extern fn gst_audio_ring_buffer_prepare_read(p_buf: *AudioRingBuffer, p_segment: *c_int, p_readptr: *[*]u8, p_len: *c_int) c_int;
    pub const prepareRead = gst_audio_ring_buffer_prepare_read;

    /// Read `len` samples from the ringbuffer into the memory pointed
    /// to by `data`.
    /// The first sample should be read from position `sample` in
    /// the ringbuffer.
    ///
    /// `len` should not be a multiple of the segment size of the ringbuffer
    /// although it is recommended.
    ///
    /// `timestamp` will return the timestamp associated with the data returned.
    extern fn gst_audio_ring_buffer_read(p_buf: *AudioRingBuffer, p_sample: u64, p_data: [*]u8, p_len: c_uint, p_timestamp: *gst.ClockTime) c_uint;
    pub const read = gst_audio_ring_buffer_read;

    /// Free the resources of the ringbuffer.
    extern fn gst_audio_ring_buffer_release(p_buf: *AudioRingBuffer) c_int;
    pub const release = gst_audio_ring_buffer_release;

    /// Get the number of samples that were processed by the ringbuffer
    /// since it was last started. This does not include the number of samples not
    /// yet processed (see `gstaudio.AudioRingBuffer.delay`).
    extern fn gst_audio_ring_buffer_samples_done(p_buf: *AudioRingBuffer) u64;
    pub const samplesDone = gst_audio_ring_buffer_samples_done;

    /// Sets the given callback function on the buffer. This function
    /// will be called every time a segment has been written to a device.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_set_callback(p_buf: *AudioRingBuffer, p_cb: ?gstaudio.AudioRingBufferCallback, p_user_data: ?*anyopaque) void;
    pub const setCallback = gst_audio_ring_buffer_set_callback;

    /// Sets the given callback function on the buffer. This function
    /// will be called every time a segment has been written to a device.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_set_callback_full(p_buf: *AudioRingBuffer, p_cb: ?gstaudio.AudioRingBufferCallback, p_user_data: ?*anyopaque, p_notify: ?glib.DestroyNotify) void;
    pub const setCallbackFull = gst_audio_ring_buffer_set_callback_full;

    /// Tell the ringbuffer about the device's channel positions. This must
    /// be called in when the ringbuffer is acquired.
    extern fn gst_audio_ring_buffer_set_channel_positions(p_buf: *AudioRingBuffer, p_position: [*]const gstaudio.AudioChannelPosition) void;
    pub const setChannelPositions = gst_audio_ring_buffer_set_channel_positions;

    /// Mark the ringbuffer as errored after it has started.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_set_errored(p_buf: *AudioRingBuffer) void;
    pub const setErrored = gst_audio_ring_buffer_set_errored;

    /// Set the ringbuffer to flushing mode or normal mode.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_set_flushing(p_buf: *AudioRingBuffer, p_flushing: c_int) void;
    pub const setFlushing = gst_audio_ring_buffer_set_flushing;

    /// Make sure that the next sample written to the device is
    /// accounted for as being the `sample` sample written to the
    /// device. This value will be used in reporting the current
    /// sample position of the ringbuffer.
    ///
    /// This function will also clear the buffer with silence.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_set_sample(p_buf: *AudioRingBuffer, p_sample: u64) void;
    pub const setSample = gst_audio_ring_buffer_set_sample;

    /// Sets the current segment number of the ringbuffer.
    ///
    /// MT safe.
    extern fn gst_audio_ring_buffer_set_segdone(p_buf: *AudioRingBuffer, p_segdone: u64) void;
    pub const setSegdone = gst_audio_ring_buffer_set_segdone;

    extern fn gst_audio_ring_buffer_set_timestamp(p_buf: *AudioRingBuffer, p_readseg: c_int, p_timestamp: gst.ClockTime) void;
    pub const setTimestamp = gst_audio_ring_buffer_set_timestamp;

    /// Start processing samples from the ringbuffer.
    extern fn gst_audio_ring_buffer_start(p_buf: *AudioRingBuffer) c_int;
    pub const start = gst_audio_ring_buffer_start;

    /// Stop processing samples from the ringbuffer.
    extern fn gst_audio_ring_buffer_stop(p_buf: *AudioRingBuffer) c_int;
    pub const stop = gst_audio_ring_buffer_stop;

    extern fn gst_audio_ring_buffer_get_type() usize;
    pub const getGObjectType = gst_audio_ring_buffer_get_type;

    extern fn g_object_ref(p_self: *gstaudio.AudioRingBuffer) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstaudio.AudioRingBuffer) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *AudioRingBuffer, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// This is the most simple base class for audio sinks that only requires
/// subclasses to implement a set of simple functions:
///
/// * ``open`` :Open the device.
///
/// * ``prepare`` :Configure the device with the specified format.
///
/// * ``write`` :Write samples to the device.
///
/// * ``reset`` :Unblock writes and flush the device.
///
/// * ``delay`` :Get the number of samples written but not yet played
/// by the device.
///
/// * ``unprepare`` :Undo operations done by prepare.
///
/// * ``close`` :Close the device.
///
/// All scheduling of samples and timestamps is done in this base class
/// together with `gstaudio.AudioBaseSink` using a default implementation of a
/// `gstaudio.AudioRingBuffer` that uses threads.
pub const AudioSink = extern struct {
    pub const Parent = gstaudio.AudioBaseSink;
    pub const Implements = [_]type{};
    pub const Class = gstaudio.AudioSinkClass;
    f_element: gstaudio.AudioBaseSink,
    f_thread: ?*glib.Thread,
    f__gst_reserved: [4]*anyopaque,

    pub const virtual_methods = struct {
        /// Close the device.
        pub const close = struct {
            pub fn call(p_class: anytype, p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioSink.Class, p_class).f_close.?(gobject.ext.as(AudioSink, p_sink));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioSink.Class, p_class).f_close = @ptrCast(p_implementation);
            }
        };

        /// Return how many frames are still in the device. Participates in
        ///         computing the time for audio clocks and drives the synchronisation.
        pub const delay = struct {
            pub fn call(p_class: anytype, p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_uint {
                return gobject.ext.as(AudioSink.Class, p_class).f_delay.?(gobject.ext.as(AudioSink, p_sink));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_uint) void {
                gobject.ext.as(AudioSink.Class, p_class).f_delay = @ptrCast(p_implementation);
            }
        };

        /// Open the device. No configuration needs to be done at this point.
        ///        This function is also used to check if the device is available.
        pub const open = struct {
            pub fn call(p_class: anytype, p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioSink.Class, p_class).f_open.?(gobject.ext.as(AudioSink, p_sink));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioSink.Class, p_class).f_open = @ptrCast(p_implementation);
            }
        };

        /// Pause the device and unblock write as fast as possible.
        ///         For retro compatibility, the audio sink will fallback
        ///         to calling reset if this vmethod is not provided. Since: 1.18
        pub const pause = struct {
            pub fn call(p_class: anytype, p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) void {
                return gobject.ext.as(AudioSink.Class, p_class).f_pause.?(gobject.ext.as(AudioSink, p_sink));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) void) void {
                gobject.ext.as(AudioSink.Class, p_class).f_pause = @ptrCast(p_implementation);
            }
        };

        /// Prepare the device to operate with the specified parameters.
        pub const prepare = struct {
            pub fn call(p_class: anytype, p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_spec: *gstaudio.AudioRingBufferSpec) c_int {
                return gobject.ext.as(AudioSink.Class, p_class).f_prepare.?(gobject.ext.as(AudioSink, p_sink), p_spec);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_spec: *gstaudio.AudioRingBufferSpec) callconv(.c) c_int) void {
                gobject.ext.as(AudioSink.Class, p_class).f_prepare = @ptrCast(p_implementation);
            }
        };

        /// Returns as quickly as possible from a write and flush any pending
        ///         samples from the device.
        ///         This vmethod is deprecated. Please provide pause and stop instead.
        pub const reset = struct {
            pub fn call(p_class: anytype, p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) void {
                return gobject.ext.as(AudioSink.Class, p_class).f_reset.?(gobject.ext.as(AudioSink, p_sink));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) void) void {
                gobject.ext.as(AudioSink.Class, p_class).f_reset = @ptrCast(p_implementation);
            }
        };

        /// Resume the device. Since: 1.18
        pub const @"resume" = struct {
            pub fn call(p_class: anytype, p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) void {
                return gobject.ext.as(AudioSink.Class, p_class).f_resume.?(gobject.ext.as(AudioSink, p_sink));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) void) void {
                gobject.ext.as(AudioSink.Class, p_class).f_resume = @ptrCast(p_implementation);
            }
        };

        /// Stop the device and unblock write as fast as possible.
        ///        Pending samples are flushed from the device.
        ///        For retro compatibility, the audio sink will fallback
        ///        to calling reset if this vmethod is not provided. Since: 1.18
        pub const stop = struct {
            pub fn call(p_class: anytype, p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) void {
                return gobject.ext.as(AudioSink.Class, p_class).f_stop.?(gobject.ext.as(AudioSink, p_sink));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) void) void {
                gobject.ext.as(AudioSink.Class, p_class).f_stop = @ptrCast(p_implementation);
            }
        };

        /// Undo operations done in prepare.
        pub const unprepare = struct {
            pub fn call(p_class: anytype, p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioSink.Class, p_class).f_unprepare.?(gobject.ext.as(AudioSink, p_sink));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioSink.Class, p_class).f_unprepare = @ptrCast(p_implementation);
            }
        };

        /// Write samples to the device.
        pub const write = struct {
            pub fn call(p_class: anytype, p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_data: [*]u8, p_length: c_uint) c_int {
                return gobject.ext.as(AudioSink.Class, p_class).f_write.?(gobject.ext.as(AudioSink, p_sink), p_data, p_length);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_sink: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_data: [*]u8, p_length: c_uint) callconv(.c) c_int) void {
                gobject.ext.as(AudioSink.Class, p_class).f_write = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {};

    pub const signals = struct {};

    extern fn gst_audio_sink_get_type() usize;
    pub const getGObjectType = gst_audio_sink_get_type;

    extern fn g_object_ref(p_self: *gstaudio.AudioSink) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstaudio.AudioSink) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *AudioSink, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// This is the most simple base class for audio sources that only requires
/// subclasses to implement a set of simple functions:
///
/// * ``open`` :Open the device.
/// * ``prepare`` :Configure the device with the specified format.
/// * ``read`` :Read samples from the device.
/// * ``reset`` :Unblock reads and flush the device.
/// * ``delay`` :Get the number of samples in the device but not yet read.
/// * ``unprepare`` :Undo operations done by prepare.
/// * ``close`` :Close the device.
///
/// All scheduling of samples and timestamps is done in this base class
/// together with `gstaudio.AudioBaseSrc` using a default implementation of a
/// `gstaudio.AudioRingBuffer` that uses threads.
pub const AudioSrc = extern struct {
    pub const Parent = gstaudio.AudioBaseSrc;
    pub const Implements = [_]type{};
    pub const Class = gstaudio.AudioSrcClass;
    f_element: gstaudio.AudioBaseSrc,
    f_thread: ?*glib.Thread,
    f__gst_reserved: [4]*anyopaque,

    pub const virtual_methods = struct {
        /// close the device
        pub const close = struct {
            pub fn call(p_class: anytype, p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioSrc.Class, p_class).f_close.?(gobject.ext.as(AudioSrc, p_src));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioSrc.Class, p_class).f_close = @ptrCast(p_implementation);
            }
        };

        /// the number of frames queued in the device
        pub const delay = struct {
            pub fn call(p_class: anytype, p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_uint {
                return gobject.ext.as(AudioSrc.Class, p_class).f_delay.?(gobject.ext.as(AudioSrc, p_src));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_uint) void {
                gobject.ext.as(AudioSrc.Class, p_class).f_delay = @ptrCast(p_implementation);
            }
        };

        /// open the device with the specified caps
        pub const open = struct {
            pub fn call(p_class: anytype, p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioSrc.Class, p_class).f_open.?(gobject.ext.as(AudioSrc, p_src));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioSrc.Class, p_class).f_open = @ptrCast(p_implementation);
            }
        };

        /// configure device with format
        pub const prepare = struct {
            pub fn call(p_class: anytype, p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_spec: *gstaudio.AudioRingBufferSpec) c_int {
                return gobject.ext.as(AudioSrc.Class, p_class).f_prepare.?(gobject.ext.as(AudioSrc, p_src), p_spec);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_spec: *gstaudio.AudioRingBufferSpec) callconv(.c) c_int) void {
                gobject.ext.as(AudioSrc.Class, p_class).f_prepare = @ptrCast(p_implementation);
            }
        };

        /// Read samples from the device.
        pub const read = struct {
            pub fn call(p_class: anytype, p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_data: [*]u8, p_length: c_uint, p_timestamp: *gst.ClockTime) c_uint {
                return gobject.ext.as(AudioSrc.Class, p_class).f_read.?(gobject.ext.as(AudioSrc, p_src), p_data, p_length, p_timestamp);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_data: [*]u8, p_length: c_uint, p_timestamp: *gst.ClockTime) callconv(.c) c_uint) void {
                gobject.ext.as(AudioSrc.Class, p_class).f_read = @ptrCast(p_implementation);
            }
        };

        /// unblock a read to the device and reset.
        pub const reset = struct {
            pub fn call(p_class: anytype, p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) void {
                return gobject.ext.as(AudioSrc.Class, p_class).f_reset.?(gobject.ext.as(AudioSrc, p_src));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) void) void {
                gobject.ext.as(AudioSrc.Class, p_class).f_reset = @ptrCast(p_implementation);
            }
        };

        /// undo the configuration
        pub const unprepare = struct {
            pub fn call(p_class: anytype, p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) c_int {
                return gobject.ext.as(AudioSrc.Class, p_class).f_unprepare.?(gobject.ext.as(AudioSrc, p_src));
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_src: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance) callconv(.c) c_int) void {
                gobject.ext.as(AudioSrc.Class, p_class).f_unprepare = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {};

    pub const signals = struct {};

    extern fn gst_audio_src_get_type() usize;
    pub const getGObjectType = gst_audio_src_get_type;

    extern fn g_object_ref(p_self: *gstaudio.AudioSrc) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstaudio.AudioSrc) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *AudioSrc, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// This interface is implemented by elements that provide a stream volume. Examples for
/// such elements are `volume` and `playbin`.
///
/// Applications can use this interface to get or set the current stream volume. For this
/// the "volume" `gobject.Object` property can be used or the helper functions `gstaudio.StreamVolume.setVolume`
/// and `gstaudio.StreamVolume.getVolume`. This volume is always a linear factor, i.e. 0.0 is muted
/// 1.0 is 100%. For showing the volume in a GUI it might make sense to convert it to
/// a different format by using `gstaudio.streamVolumeConvertVolume`. Volume sliders should usually
/// use a cubic volume.
///
/// Separate from the volume the stream can also be muted by the "mute" `gobject.Object` property or
/// `gstaudio.StreamVolume.setMute` and `gstaudio.StreamVolume.getMute`.
///
/// Elements that provide some kind of stream volume should implement the "volume" and
/// "mute" `gobject.Object` properties and handle setting and getting of them properly.
/// The volume property is defined to be a linear volume factor.
pub const StreamVolume = opaque {
    pub const Prerequisites = [_]type{gobject.Object};
    pub const Iface = gstaudio.StreamVolumeInterface;
    pub const virtual_methods = struct {};

    pub const properties = struct {
        pub const mute = struct {
            pub const name = "mute";

            pub const Type = c_int;
        };

        pub const volume = struct {
            pub const name = "volume";

            pub const Type = f64;
        };
    };

    pub const signals = struct {};

    extern fn gst_stream_volume_convert_volume(p_from: gstaudio.StreamVolumeFormat, p_to: gstaudio.StreamVolumeFormat, p_val: f64) f64;
    pub const convertVolume = gst_stream_volume_convert_volume;

    extern fn gst_stream_volume_get_mute(p_volume: *StreamVolume) c_int;
    pub const getMute = gst_stream_volume_get_mute;

    extern fn gst_stream_volume_get_volume(p_volume: *StreamVolume, p_format: gstaudio.StreamVolumeFormat) f64;
    pub const getVolume = gst_stream_volume_get_volume;

    extern fn gst_stream_volume_set_mute(p_volume: *StreamVolume, p_mute: c_int) void;
    pub const setMute = gst_stream_volume_set_mute;

    extern fn gst_stream_volume_set_volume(p_volume: *StreamVolume, p_format: gstaudio.StreamVolumeFormat, p_val: f64) void;
    pub const setVolume = gst_stream_volume_set_volume;

    extern fn gst_stream_volume_get_type() usize;
    pub const getGObjectType = gst_stream_volume_get_type;

    extern fn g_object_ref(p_self: *gstaudio.StreamVolume) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstaudio.StreamVolume) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *StreamVolume, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioAggregatorClass = extern struct {
    pub const Instance = gstaudio.AudioAggregator;

    f_parent_class: gstbase.AggregatorClass,
    /// Create a new output buffer contains num_frames frames.
    f_create_output_buffer: ?*const fn (p_aagg: *gstaudio.AudioAggregator, p_num_frames: c_uint) callconv(.c) *gst.Buffer,
    /// Aggregates one input buffer to the output
    ///  buffer.  The in_offset and out_offset are in "frames", which is
    ///  the size of a sample times the number of channels. Returns TRUE if
    ///  any non-silence was added to the buffer
    f_aggregate_one_buffer: ?*const fn (p_aagg: *gstaudio.AudioAggregator, p_pad: *gstaudio.AudioAggregatorPad, p_inbuf: *gst.Buffer, p_in_offset: c_uint, p_outbuf: *gst.Buffer, p_out_offset: c_uint, p_num_frames: c_uint) callconv(.c) c_int,
    f__gst_reserved: [20]*anyopaque,

    pub fn as(p_instance: *AudioAggregatorClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioAggregatorConvertPadClass = extern struct {
    pub const Instance = gstaudio.AudioAggregatorConvertPad;

    f_parent_class: gstaudio.AudioAggregatorPadClass,
    f__gst_reserved: [4]*anyopaque,

    pub fn as(p_instance: *AudioAggregatorConvertPadClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioAggregatorConvertPadPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioAggregatorPadClass = extern struct {
    pub const Instance = gstaudio.AudioAggregatorPad;

    f_parent_class: gstbase.AggregatorPadClass,
    /// Convert a buffer from one format to another.
    f_convert_buffer: ?*const fn (p_pad: *gstaudio.AudioAggregatorPad, p_in_info: *gstaudio.AudioInfo, p_out_info: *gstaudio.AudioInfo, p_buffer: *gst.Buffer) callconv(.c) *gst.Buffer,
    /// Called when either the input or output
    ///  formats have changed.
    f_update_conversion_info: ?*const fn (p_pad: *gstaudio.AudioAggregatorPad) callconv(.c) void,
    f__gst_reserved: [20]*anyopaque,

    pub fn as(p_instance: *AudioAggregatorPadClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioAggregatorPadPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioAggregatorPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// `gstaudio.AudioBaseSink` class. Override the vmethod to implement
/// functionality.
pub const AudioBaseSinkClass = extern struct {
    pub const Instance = gstaudio.AudioBaseSink;

    /// the parent class.
    f_parent_class: gstbase.BaseSinkClass,
    /// create and return a `gstaudio.AudioRingBuffer` to write to.
    f_create_ringbuffer: ?*const fn (p_sink: *gstaudio.AudioBaseSink) callconv(.c) ?*gstaudio.AudioRingBuffer,
    /// payload data in a format suitable to write to the sink. If no
    ///           payloading is required, returns a reffed copy of the original
    ///           buffer, else returns the payloaded buffer with all other metadata
    ///           copied.
    f_payload: ?*const fn (p_sink: *gstaudio.AudioBaseSink, p_buffer: *gst.Buffer) callconv(.c) *gst.Buffer,
    f__gst_reserved: [4]*anyopaque,

    pub fn as(p_instance: *AudioBaseSinkClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioBaseSinkPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// `gstaudio.AudioBaseSrc` class. Override the vmethod to implement
/// functionality.
pub const AudioBaseSrcClass = extern struct {
    pub const Instance = gstaudio.AudioBaseSrc;

    /// the parent class.
    f_parent_class: gstbase.PushSrcClass,
    /// create and return a `gstaudio.AudioRingBuffer` to read from.
    f_create_ringbuffer: ?*const fn (p_src: *gstaudio.AudioBaseSrc) callconv(.c) ?*gstaudio.AudioRingBuffer,
    f__gst_reserved: [4]*anyopaque,

    pub fn as(p_instance: *AudioBaseSrcClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioBaseSrcPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// A structure containing the result of an audio buffer map operation,
/// which is executed with `gstaudio.audioBufferMap`. For non-interleaved (planar)
/// buffers, the beginning of each channel in the buffer has its own pointer in
/// the `planes` array. For interleaved buffers, the `planes` array only contains
/// one item, which is the pointer to the beginning of the buffer, and `n_planes`
/// equals 1.
///
/// The different channels in `planes` are always in the GStreamer channel order.
pub const AudioBuffer = extern struct {
    /// a `gstaudio.AudioInfo` describing the audio properties of this buffer
    f_info: gstaudio.AudioInfo,
    /// the size of the buffer in samples
    f_n_samples: usize,
    /// the number of planes available
    f_n_planes: c_int,
    /// an array of `n_planes` pointers pointing to the start of each
    ///   plane in the mapped buffer
    f_planes: ?*anyopaque,
    /// the mapped buffer
    f_buffer: ?*gst.Buffer,
    f_map_infos: ?*gst.MapInfo,
    f_priv_planes_arr: [8]*anyopaque,
    f_priv_map_infos_arr: [8]gst.MapInfo,
    f__gst_reserved: [4]*anyopaque,

    /// Clip the buffer to the given `gst.Segment`.
    ///
    /// After calling this function the caller does not own a reference to
    /// `buffer` anymore.
    extern fn gst_audio_buffer_clip(p_buffer: *gst.Buffer, p_segment: *const gst.Segment, p_rate: c_int, p_bpf: c_int) ?*gst.Buffer;
    pub const clip = gst_audio_buffer_clip;

    /// Maps an audio `gstbuffer` so that it can be read or written and stores the
    /// result of the map operation in `buffer`.
    ///
    /// This is especially useful when the `gstbuffer` is in non-interleaved (planar)
    /// layout, in which case this function will use the information in the
    /// `gstbuffer`'s attached `gstaudio.AudioMeta` in order to map each channel in a
    /// separate "plane" in `gstaudio.AudioBuffer`. If a `gstaudio.AudioMeta` is not attached
    /// on the `gstbuffer`, then it must be in interleaved layout.
    ///
    /// If a `gstaudio.AudioMeta` is attached, then the `gstaudio.AudioInfo` on the meta is checked
    /// against `info`. Normally, they should be equal, but in case they are not,
    /// a g_critical will be printed and the `gstaudio.AudioInfo` from the meta will be
    /// used.
    ///
    /// In non-interleaved buffers, it is possible to have each channel on a separate
    /// `gst.Memory`. In this case, each memory will be mapped separately to avoid
    /// copying their contents in a larger memory area. Do note though that it is
    /// not supported to have a single channel spanning over two or more different
    /// `gst.Memory` objects. Although the map operation will likely succeed in this
    /// case, it will be highly sub-optimal and it is recommended to merge all the
    /// memories in the buffer before calling this function.
    ///
    /// Note: The actual `gst.Buffer` is not ref'ed, but it is required to stay valid
    /// as long as it's mapped.
    extern fn gst_audio_buffer_map(p_buffer: *gstaudio.AudioBuffer, p_info: *const gstaudio.AudioInfo, p_gstbuffer: *gst.Buffer, p_flags: gst.MapFlags) c_int;
    pub const map = gst_audio_buffer_map;

    /// Reorders `buffer` from the channel positions `from` to the channel
    /// positions `to`. `from` and `to` must contain the same number of
    /// positions and the same positions, only in a different order.
    /// `buffer` must be writable.
    extern fn gst_audio_buffer_reorder_channels(p_buffer: *gst.Buffer, p_format: gstaudio.AudioFormat, p_channels: c_int, p_from: [*]const gstaudio.AudioChannelPosition, p_to: [*]const gstaudio.AudioChannelPosition) c_int;
    pub const reorderChannels = gst_audio_buffer_reorder_channels;

    /// Truncate the buffer to finally have `samples` number of samples, removing
    /// the necessary amount of samples from the end and `trim` number of samples
    /// from the beginning.
    ///
    /// This function does not know the audio rate, therefore the caller is
    /// responsible for re-setting the correct timestamp and duration to the
    /// buffer. However, timestamp will be preserved if trim == 0, and duration
    /// will also be preserved if there is no trimming to be done. Offset and
    /// offset end will be preserved / updated.
    ///
    /// After calling this function the caller does not own a reference to
    /// `buffer` anymore.
    extern fn gst_audio_buffer_truncate(p_buffer: *gst.Buffer, p_bpf: c_int, p_trim: usize, p_samples: usize) *gst.Buffer;
    pub const truncate = gst_audio_buffer_truncate;

    /// Unmaps an audio buffer that was previously mapped with
    /// `gstaudio.audioBufferMap`.
    extern fn gst_audio_buffer_unmap(p_buffer: *AudioBuffer) void;
    pub const unmap = gst_audio_buffer_unmap;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Audio CD source base class.
pub const AudioCdSrcClass = extern struct {
    pub const Instance = gstaudio.AudioCdSrc;

    /// the parent class
    f_pushsrc_class: gstbase.PushSrcClass,
    /// opening the device
    f_open: ?*const fn (p_src: *gstaudio.AudioCdSrc, p_device: [*:0]const u8) callconv(.c) c_int,
    /// closing the device
    f_close: ?*const fn (p_src: *gstaudio.AudioCdSrc) callconv(.c) void,
    /// reading a sector
    f_read_sector: ?*const fn (p_src: *gstaudio.AudioCdSrc, p_sector: c_int) callconv(.c) *gst.Buffer,
    f__gst_reserved: [20]*anyopaque,

    pub fn as(p_instance: *AudioCdSrcClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioCdSrcPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// CD track abstraction to communicate TOC entries to the base class.
///
/// This structure is only for use by sub-classed in connection with
/// `gstaudio.AudioCdSrc.addTrack`.
///
/// Applications will be informed of the available tracks via a TOC message
/// on the pipeline's `gst.Bus` instead.
pub const AudioCdSrcTrack = extern struct {
    /// Whether this is an audio track
    f_is_audio: c_int,
    /// Track number in TOC (usually starts from 1, but not always)
    f_num: c_uint,
    /// The first sector of this track (LBA)
    f_start: c_uint,
    /// The last sector of this track (LBA)
    f_end: c_uint,
    /// Track-specific tags (e.g. from cd-text information), or NULL
    f_tags: ?*gst.TagList,
    f__gst_reserved1: [2]c_uint,
    f__gst_reserved2: [2]*anyopaque,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioChannelMixer = opaque {
    /// Create a new channel mixer object for the given parameters.
    extern fn gst_audio_channel_mixer_new(p_flags: gstaudio.AudioChannelMixerFlags, p_format: gstaudio.AudioFormat, p_in_channels: c_int, p_in_position: *gstaudio.AudioChannelPosition, p_out_channels: c_int, p_out_position: *gstaudio.AudioChannelPosition) *gstaudio.AudioChannelMixer;
    pub const new = gst_audio_channel_mixer_new;

    /// Create a new channel mixer object for the given parameters.
    extern fn gst_audio_channel_mixer_new_with_matrix(p_flags: gstaudio.AudioChannelMixerFlags, p_format: gstaudio.AudioFormat, p_in_channels: c_int, p_out_channels: c_int, p_matrix: ?**f32) *gstaudio.AudioChannelMixer;
    pub const newWithMatrix = gst_audio_channel_mixer_new_with_matrix;

    /// Free memory allocated by `mix`.
    extern fn gst_audio_channel_mixer_free(p_mix: *AudioChannelMixer) void;
    pub const free = gst_audio_channel_mixer_free;

    /// Check if `mix` is in passthrough.
    ///
    /// Only N x N mix identity matrices are considered passthrough,
    /// this is determined by comparing the contents of the matrix
    /// with 0.0 and 1.0.
    ///
    /// As this is floating point comparisons, if the values have been
    /// generated, they should be rounded up or down by explicit
    /// assignment of 0.0 or 1.0 to values within a user-defined
    /// epsilon, this code doesn't make assumptions as to what may
    /// constitute an appropriate epsilon.
    extern fn gst_audio_channel_mixer_is_passthrough(p_mix: *AudioChannelMixer) c_int;
    pub const isPassthrough = gst_audio_channel_mixer_is_passthrough;

    /// In case the samples are interleaved, `in` and `out` must point to an
    /// array with a single element pointing to a block of interleaved samples.
    ///
    /// If non-interleaved samples are used, `in` and `out` must point to an
    /// array with pointers to memory blocks, one for each channel.
    ///
    /// Perform channel mixing on `in_data` and write the result to `out_data`.
    /// `in_data` and `out_data` need to be in `format` and `layout`.
    extern fn gst_audio_channel_mixer_samples(p_mix: *AudioChannelMixer, p_in: ?*anyopaque, p_out: ?*anyopaque, p_samples: c_int) void;
    pub const samples = gst_audio_channel_mixer_samples;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Extra buffer metadata describing how much audio has to be clipped from
/// the start or end of a buffer. This is used for compressed formats, where
/// the first frame usually has some additional samples due to encoder and
/// decoder delays, and the last frame usually has some additional samples to
/// be able to fill the complete last frame.
///
/// This is used to ensure that decoded data in the end has the same amount of
/// samples, and multiply decoded streams can be gaplessly concatenated.
///
/// Note: If clipping of the start is done by adjusting the segment, this meta
/// has to be dropped from buffers as otherwise clipping could happen twice.
pub const AudioClippingMeta = extern struct {
    /// parent `gst.Meta`
    f_meta: gst.Meta,
    /// GstFormat of `start` and `stop`, GST_FORMAT_DEFAULT is samples
    f_format: gst.Format,
    /// Amount of audio to clip from start of buffer
    f_start: u64,
    /// Amount of  to clip from end of buffer
    f_end: u64,

    extern fn gst_audio_clipping_meta_get_info() *const gst.MetaInfo;
    pub const getInfo = gst_audio_clipping_meta_get_info;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioClockClass = extern struct {
    pub const Instance = gstaudio.AudioClock;

    f_parent_class: gst.SystemClockClass,
    f__gst_reserved: [4]*anyopaque,

    pub fn as(p_instance: *AudioClockClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// This object is used to convert audio samples from one format to another.
/// The object can perform conversion of:
///
///  * audio format with optional dithering and noise shaping
///
///  * audio samplerate
///
///  * audio channels and channel layout
pub const AudioConverter = opaque {
    /// Create a new `gstaudio.AudioConverter` that is able to convert between `in` and `out`
    /// audio formats.
    ///
    /// `config` contains extra configuration options, see `GST_AUDIO_CONVERTER_OPT_*`
    /// parameters for details about the options and values.
    extern fn gst_audio_converter_new(p_flags: gstaudio.AudioConverterFlags, p_in_info: *gstaudio.AudioInfo, p_out_info: *gstaudio.AudioInfo, p_config: ?*gst.Structure) ?*gstaudio.AudioConverter;
    pub const new = gst_audio_converter_new;

    /// Convenience wrapper around `gstaudio.AudioConverter.samples`, which will
    /// perform allocation of the output buffer based on the result from
    /// `gstaudio.AudioConverter.getOutFrames`.
    extern fn gst_audio_converter_convert(p_convert: *AudioConverter, p_flags: gstaudio.AudioConverterFlags, p_in: [*]u8, p_in_size: usize, p_out: *[*]u8, p_out_size: *usize) c_int;
    pub const convert = gst_audio_converter_convert;

    /// Free a previously allocated `convert` instance.
    extern fn gst_audio_converter_free(p_convert: *AudioConverter) void;
    pub const free = gst_audio_converter_free;

    /// Get the current configuration of `convert`.
    extern fn gst_audio_converter_get_config(p_convert: *AudioConverter, p_in_rate: ?*c_int, p_out_rate: ?*c_int) *const gst.Structure;
    pub const getConfig = gst_audio_converter_get_config;

    /// Calculate how many input frames are currently needed by `convert` to produce
    /// `out_frames` of output frames.
    extern fn gst_audio_converter_get_in_frames(p_convert: *AudioConverter, p_out_frames: usize) usize;
    pub const getInFrames = gst_audio_converter_get_in_frames;

    /// Get the maximum number of input frames that the converter would
    /// need before producing output.
    extern fn gst_audio_converter_get_max_latency(p_convert: *AudioConverter) usize;
    pub const getMaxLatency = gst_audio_converter_get_max_latency;

    /// Calculate how many output frames can be produced when `in_frames` input
    /// frames are given to `convert`.
    extern fn gst_audio_converter_get_out_frames(p_convert: *AudioConverter, p_in_frames: usize) usize;
    pub const getOutFrames = gst_audio_converter_get_out_frames;

    /// Returns whether the audio converter will operate in passthrough mode.
    /// The return value would be typically input to `gstbase.BaseTransform.setPassthrough`
    extern fn gst_audio_converter_is_passthrough(p_convert: *AudioConverter) c_int;
    pub const isPassthrough = gst_audio_converter_is_passthrough;

    /// Reset `convert` to the state it was when it was first created, clearing
    /// any history it might currently have.
    extern fn gst_audio_converter_reset(p_convert: *AudioConverter) void;
    pub const reset = gst_audio_converter_reset;

    /// Perform the conversion with `in_frames` in `in` to `out_frames` in `out`
    /// using `convert`.
    ///
    /// In case the samples are interleaved, `in` and `out` must point to an
    /// array with a single element pointing to a block of interleaved samples.
    ///
    /// If non-interleaved samples are used, `in` and `out` must point to an
    /// array with pointers to memory blocks, one for each channel.
    ///
    /// `in` may be `NULL`, in which case `in_frames` of silence samples are processed
    /// by the converter.
    ///
    /// This function always produces `out_frames` of output and consumes `in_frames` of
    /// input. Use `gstaudio.AudioConverter.getOutFrames` and
    /// `gstaudio.AudioConverter.getInFrames` to make sure `in_frames` and `out_frames`
    /// are matching and `in` and `out` point to enough memory.
    extern fn gst_audio_converter_samples(p_convert: *AudioConverter, p_flags: gstaudio.AudioConverterFlags, p_in: ?*anyopaque, p_in_frames: usize, p_out: ?*anyopaque, p_out_frames: usize) c_int;
    pub const samples = gst_audio_converter_samples;

    /// Returns whether the audio converter can perform the conversion in-place.
    /// The return value would be typically input to `gstbase.BaseTransform.setInPlace`
    extern fn gst_audio_converter_supports_inplace(p_convert: *AudioConverter) c_int;
    pub const supportsInplace = gst_audio_converter_supports_inplace;

    /// Set `in_rate`, `out_rate` and `config` as extra configuration for `convert`.
    ///
    /// `in_rate` and `out_rate` specify the new sample rates of input and output
    /// formats. A value of 0 leaves the sample rate unchanged.
    ///
    /// `config` can be `NULL`, in which case, the current configuration is not
    /// changed.
    ///
    /// If the parameters in `config` can not be set exactly, this function returns
    /// `FALSE` and will try to update as much state as possible. The new state can
    /// then be retrieved and refined with `gstaudio.AudioConverter.getConfig`.
    ///
    /// Look at the `GST_AUDIO_CONVERTER_OPT_*` fields to check valid configuration
    /// option and values.
    extern fn gst_audio_converter_update_config(p_convert: *AudioConverter, p_in_rate: c_int, p_out_rate: c_int, p_config: ?*gst.Structure) c_int;
    pub const updateConfig = gst_audio_converter_update_config;

    extern fn gst_audio_converter_get_type() usize;
    pub const getGObjectType = gst_audio_converter_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Subclasses can override any of the available virtual methods or not, as
/// needed. At minimum `handle_frame` (and likely `set_format`) needs to be
/// overridden.
pub const AudioDecoderClass = extern struct {
    pub const Instance = gstaudio.AudioDecoder;

    /// The parent class structure
    f_element_class: gst.ElementClass,
    /// Optional.
    ///                  Called when the element starts processing.
    ///                  Allows opening external resources.
    f_start: ?*const fn (p_dec: *gstaudio.AudioDecoder) callconv(.c) c_int,
    /// Optional.
    ///                  Called when the element stops processing.
    ///                  Allows closing external resources.
    f_stop: ?*const fn (p_dec: *gstaudio.AudioDecoder) callconv(.c) c_int,
    /// Notifies subclass of incoming data format (caps).
    f_set_format: ?*const fn (p_dec: *gstaudio.AudioDecoder, p_caps: *gst.Caps) callconv(.c) c_int,
    /// Optional.
    ///                  Allows chopping incoming data into manageable units (frames)
    ///                  for subsequent decoding.  This division is at subclass
    ///                  discretion and may or may not correspond to 1 (or more)
    ///                  frames as defined by audio format.
    f_parse: ?*const fn (p_dec: *gstaudio.AudioDecoder, p_adapter: *gstbase.Adapter, p_offset: *c_int, p_length: *c_int) callconv(.c) gst.FlowReturn,
    /// Provides input data (or NULL to clear any remaining data)
    ///                  to subclass.  Input data ref management is performed by
    ///                  base class, subclass should not care or intervene,
    ///                  and input data is only valid until next call to base class,
    ///                  most notably a call to `gstaudio.AudioDecoder.finishFrame`.
    f_handle_frame: ?*const fn (p_dec: *gstaudio.AudioDecoder, p_buffer: *gst.Buffer) callconv(.c) gst.FlowReturn,
    /// Optional.
    ///                  Instructs subclass to clear any codec caches and discard
    ///                  any pending samples and not yet returned decoded data.
    ///                  `hard` indicates whether a FLUSH is being processed,
    ///                  or otherwise a DISCONT (or conceptually similar).
    f_flush: ?*const fn (p_dec: *gstaudio.AudioDecoder, p_hard: c_int) callconv(.c) void,
    /// Optional.
    ///                  Called just prior to pushing (encoded data) buffer downstream.
    ///                  Subclass has full discretionary access to buffer,
    ///                  and a not OK flow return will abort downstream pushing.
    f_pre_push: ?*const fn (p_dec: *gstaudio.AudioDecoder, p_buffer: **gst.Buffer) callconv(.c) gst.FlowReturn,
    /// Optional.
    ///                  Event handler on the sink pad. Subclasses should chain up to
    ///                  the parent implementation to invoke the default handler.
    f_sink_event: ?*const fn (p_dec: *gstaudio.AudioDecoder, p_event: *gst.Event) callconv(.c) c_int,
    /// Optional.
    ///                  Event handler on the src pad. Subclasses should chain up to
    ///                  the parent implementation to invoke the default handler.
    f_src_event: ?*const fn (p_dec: *gstaudio.AudioDecoder, p_event: *gst.Event) callconv(.c) c_int,
    /// Optional.
    ///                  Called when the element changes to GST_STATE_READY.
    ///                  Allows opening external resources.
    f_open: ?*const fn (p_dec: *gstaudio.AudioDecoder) callconv(.c) c_int,
    /// Optional.
    ///                  Called when the element changes to GST_STATE_NULL.
    ///                  Allows closing external resources.
    f_close: ?*const fn (p_dec: *gstaudio.AudioDecoder) callconv(.c) c_int,
    /// Optional.
    ///                  Negotiate with downstream and configure buffer pools, etc.
    ///                  Subclasses should chain up to the parent implementation to
    ///                  invoke the default handler.
    f_negotiate: ?*const fn (p_dec: *gstaudio.AudioDecoder) callconv(.c) c_int,
    /// Optional.
    ///                     Setup the allocation parameters for allocating output
    ///                     buffers. The passed in query contains the result of the
    ///                     downstream allocation query.
    ///                     Subclasses should chain up to the parent implementation to
    ///                     invoke the default handler.
    f_decide_allocation: ?*const fn (p_dec: *gstaudio.AudioDecoder, p_query: *gst.Query) callconv(.c) c_int,
    /// Optional.
    ///                      Propose buffer allocation parameters for upstream elements.
    ///                      Subclasses should chain up to the parent implementation to
    ///                      invoke the default handler.
    f_propose_allocation: ?*const fn (p_dec: *gstaudio.AudioDecoder, p_query: *gst.Query) callconv(.c) c_int,
    /// Optional.
    ///                  Query handler on the sink pad. This function should
    ///                  return TRUE if the query could be performed. Subclasses
    ///                  should chain up to the parent implementation to invoke the
    ///                  default handler. Since: 1.6
    f_sink_query: ?*const fn (p_dec: *gstaudio.AudioDecoder, p_query: *gst.Query) callconv(.c) c_int,
    /// Optional.
    ///                  Query handler on the source pad. This function should
    ///                  return TRUE if the query could be performed. Subclasses
    ///                  should chain up to the parent implementation to invoke the
    ///                  default handler. Since: 1.6
    f_src_query: ?*const fn (p_dec: *gstaudio.AudioDecoder, p_query: *gst.Query) callconv(.c) c_int,
    /// Optional.
    ///                  Allows for a custom sink getcaps implementation.
    ///                  If not implemented,
    ///                  default returns gst_audio_decoder_proxy_getcaps
    ///                  applied to sink template caps.
    f_getcaps: ?*const fn (p_dec: *gstaudio.AudioDecoder, p_filter: *gst.Caps) callconv(.c) *gst.Caps,
    /// Optional. Transform the metadata on the input buffer to the
    ///                  output buffer. By default this method copies all meta without
    ///                  tags and meta with only the "audio" tag. subclasses can
    ///                  implement this method and return `TRUE` if the metadata is to be
    ///                  copied. Since: 1.6
    f_transform_meta: ?*const fn (p_enc: *gstaudio.AudioDecoder, p_outbuf: *gst.Buffer, p_meta: *gst.Meta, p_inbuf: *gst.Buffer) callconv(.c) c_int,
    f__gst_reserved: [16]*anyopaque,

    pub fn as(p_instance: *AudioDecoderClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioDecoderPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Extra buffer metadata describing audio downmixing matrix. This metadata is
/// attached to audio buffers and contains a matrix to downmix the buffer number
/// of channels to `channels`.
///
/// `matrix` is an two-dimensional array of `to_channels` times `from_channels`
/// coefficients, i.e. the i-th output channels is constructed by multiplicating
/// the input channels with the coefficients in `matrix`[i] and taking the sum
/// of the results.
pub const AudioDownmixMeta = extern struct {
    /// parent `gst.Meta`
    f_meta: gst.Meta,
    /// the channel positions of the source
    f_from_position: ?*gstaudio.AudioChannelPosition,
    /// the channel positions of the destination
    f_to_position: ?*gstaudio.AudioChannelPosition,
    /// the number of channels of the source
    f_from_channels: c_int,
    /// the number of channels of the destination
    f_to_channels: c_int,
    /// the matrix coefficients.
    f_matrix: ?**f32,

    extern fn gst_audio_downmix_meta_get_info() *const gst.MetaInfo;
    pub const getInfo = gst_audio_downmix_meta_get_info;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Subclasses can override any of the available virtual methods or not, as
/// needed. At minimum `set_format` and `handle_frame` needs to be overridden.
pub const AudioEncoderClass = extern struct {
    pub const Instance = gstaudio.AudioEncoder;

    /// The parent class structure
    f_element_class: gst.ElementClass,
    /// Optional.
    ///                  Called when the element starts processing.
    ///                  Allows opening external resources.
    f_start: ?*const fn (p_enc: *gstaudio.AudioEncoder) callconv(.c) c_int,
    /// Optional.
    ///                  Called when the element stops processing.
    ///                  Allows closing external resources.
    f_stop: ?*const fn (p_enc: *gstaudio.AudioEncoder) callconv(.c) c_int,
    /// Notifies subclass of incoming data format.
    ///                  GstAudioInfo contains the format according to provided caps.
    f_set_format: ?*const fn (p_enc: *gstaudio.AudioEncoder, p_info: *gstaudio.AudioInfo) callconv(.c) c_int,
    /// Provides input samples (or NULL to clear any remaining data)
    ///                  according to directions as configured by the subclass
    ///                  using the API.  Input data ref management is performed
    ///                  by base class, subclass should not care or intervene,
    ///                  and input data is only valid until next call to base class,
    ///                  most notably a call to `gstaudio.AudioEncoder.finishFrame`.
    f_handle_frame: ?*const fn (p_enc: *gstaudio.AudioEncoder, p_buffer: *gst.Buffer) callconv(.c) gst.FlowReturn,
    /// Optional.
    ///                  Instructs subclass to clear any codec caches and discard
    ///                  any pending samples and not yet returned encoded data.
    f_flush: ?*const fn (p_enc: *gstaudio.AudioEncoder) callconv(.c) void,
    /// Optional.
    ///                  Called just prior to pushing (encoded data) buffer downstream.
    ///                  Subclass has full discretionary access to buffer,
    ///                  and a not OK flow return will abort downstream pushing.
    f_pre_push: ?*const fn (p_enc: *gstaudio.AudioEncoder, p_buffer: **gst.Buffer) callconv(.c) gst.FlowReturn,
    /// Optional.
    ///                  Event handler on the sink pad. Subclasses should chain up to
    ///                  the parent implementation to invoke the default handler.
    f_sink_event: ?*const fn (p_enc: *gstaudio.AudioEncoder, p_event: *gst.Event) callconv(.c) c_int,
    /// Optional.
    ///                  Event handler on the src pad. Subclasses should chain up to
    ///                  the parent implementation to invoke the default handler.
    f_src_event: ?*const fn (p_enc: *gstaudio.AudioEncoder, p_event: *gst.Event) callconv(.c) c_int,
    /// Optional.
    ///                  Allows for a custom sink getcaps implementation (e.g.
    ///                  for multichannel input specification).  If not implemented,
    ///                  default returns gst_audio_encoder_proxy_getcaps
    ///                  applied to sink template caps.
    f_getcaps: ?*const fn (p_enc: *gstaudio.AudioEncoder, p_filter: *gst.Caps) callconv(.c) *gst.Caps,
    /// Optional.
    ///                  Called when the element changes to GST_STATE_READY.
    ///                  Allows opening external resources.
    f_open: ?*const fn (p_enc: *gstaudio.AudioEncoder) callconv(.c) c_int,
    /// Optional.
    ///                  Called when the element changes to GST_STATE_NULL.
    ///                  Allows closing external resources.
    f_close: ?*const fn (p_enc: *gstaudio.AudioEncoder) callconv(.c) c_int,
    /// Optional.
    ///                  Negotiate with downstream and configure buffer pools, etc.
    ///                  Subclasses should chain up to the parent implementation to
    ///                  invoke the default handler.
    f_negotiate: ?*const fn (p_enc: *gstaudio.AudioEncoder) callconv(.c) c_int,
    /// Optional.
    ///                     Setup the allocation parameters for allocating output
    ///                     buffers. The passed in query contains the result of the
    ///                     downstream allocation query.
    ///                     Subclasses should chain up to the parent implementation to
    ///                     invoke the default handler.
    f_decide_allocation: ?*const fn (p_enc: *gstaudio.AudioEncoder, p_query: *gst.Query) callconv(.c) c_int,
    /// Optional.
    ///                      Propose buffer allocation parameters for upstream elements.
    ///                      Subclasses should chain up to the parent implementation to
    ///                      invoke the default handler.
    f_propose_allocation: ?*const fn (p_enc: *gstaudio.AudioEncoder, p_query: *gst.Query) callconv(.c) c_int,
    /// Optional. Transform the metadata on the input buffer to the
    ///                  output buffer. By default this method copies all meta without
    ///                  tags and meta with only the "audio" tag. subclasses can
    ///                  implement this method and return `TRUE` if the metadata is to be
    ///                  copied. Since: 1.6
    f_transform_meta: ?*const fn (p_enc: *gstaudio.AudioEncoder, p_outbuf: *gst.Buffer, p_meta: *gst.Meta, p_inbuf: *gst.Buffer) callconv(.c) c_int,
    /// Optional.
    ///                  Query handler on the sink pad. This function should
    ///                  return TRUE if the query could be performed. Subclasses
    ///                  should chain up to the parent implementation to invoke the
    ///                  default handler. Since: 1.6
    f_sink_query: ?*const fn (p_encoder: *gstaudio.AudioEncoder, p_query: *gst.Query) callconv(.c) c_int,
    /// Optional.
    ///                  Query handler on the source pad. This function should
    ///                  return TRUE if the query could be performed. Subclasses
    ///                  should chain up to the parent implementation to invoke the
    ///                  default handler. Since: 1.6
    f_src_query: ?*const fn (p_encoder: *gstaudio.AudioEncoder, p_query: *gst.Query) callconv(.c) c_int,
    f__gst_reserved: [17]*anyopaque,

    pub fn as(p_instance: *AudioEncoderClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioEncoderPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// In addition to the `setup` virtual function, you should also override the
/// GstBaseTransform::transform and/or GstBaseTransform::transform_ip virtual
/// function.
pub const AudioFilterClass = extern struct {
    pub const Instance = gstaudio.AudioFilter;

    /// parent class
    f_basetransformclass: gstbase.BaseTransformClass,
    /// virtual function called whenever the format changes
    f_setup: ?*const fn (p_filter: *gstaudio.AudioFilter, p_info: *const gstaudio.AudioInfo) callconv(.c) c_int,
    f__gst_reserved: [4]*anyopaque,

    /// Convenience function to add pad templates to this element class, with
    /// `allowed_caps` as the caps that can be handled.
    ///
    /// This function is usually used from within a GObject class_init function.
    extern fn gst_audio_filter_class_add_pad_templates(p_klass: *AudioFilterClass, p_allowed_caps: *gst.Caps) void;
    pub const addPadTemplates = gst_audio_filter_class_add_pad_templates;

    pub fn as(p_instance: *AudioFilterClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Information for an audio format.
pub const AudioFormatInfo = extern struct {
    /// `gstaudio.AudioFormat`
    f_format: gstaudio.AudioFormat,
    /// string representation of the format
    f_name: ?[*:0]const u8,
    /// user readable description of the format
    f_description: ?[*:0]const u8,
    /// `gstaudio.AudioFormatFlags`
    f_flags: gstaudio.AudioFormatFlags,
    /// the endianness
    f_endianness: c_int,
    /// amount of bits used for one sample
    f_width: c_int,
    /// amount of valid bits in `width`
    f_depth: c_int,
    /// `width`/8 bytes with 1 silent sample
    f_silence: [8]u8,
    /// the format of the unpacked samples
    f_unpack_format: gstaudio.AudioFormat,
    /// function to unpack samples
    f_unpack_func: ?gstaudio.AudioFormatUnpack,
    /// function to pack samples
    f_pack_func: ?gstaudio.AudioFormatPack,
    f__gst_reserved: [4]*anyopaque,

    /// Fill `length` bytes in `dest` with silence samples for `info`.
    extern fn gst_audio_format_info_fill_silence(p_info: *const AudioFormatInfo, p_dest: [*]u8, p_length: usize) void;
    pub const fillSilence = gst_audio_format_info_fill_silence;

    extern fn gst_audio_format_info_get_type() usize;
    pub const getGObjectType = gst_audio_format_info_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Information describing audio properties. This information can be filled
/// in from GstCaps with `gstaudio.audioInfoFromCaps`.
///
/// Use the provided macros to access the info in this structure.
pub const AudioInfo = extern struct {
    /// the format info of the audio
    f_finfo: ?*const gstaudio.AudioFormatInfo,
    /// additional audio flags
    f_flags: gstaudio.AudioFlags,
    /// audio layout
    f_layout: gstaudio.AudioLayout,
    /// the audio sample rate
    f_rate: c_int,
    /// the number of channels
    f_channels: c_int,
    /// the number of bytes for one frame, this is the size of one
    ///         sample * `channels`
    f_bpf: c_int,
    /// the positions for each channel
    f_position: [64]gstaudio.AudioChannelPosition,
    f__gst_reserved: [4]*anyopaque,

    /// Parse `caps` and update `info`.
    extern fn gst_audio_info_from_caps(p_info: *gstaudio.AudioInfo, p_caps: *const gst.Caps) c_int;
    pub const fromCaps = gst_audio_info_from_caps;

    /// Initialize `info` with default values.
    extern fn gst_audio_info_init(p_info: *gstaudio.AudioInfo) void;
    pub const init = gst_audio_info_init;

    /// Allocate a new `gstaudio.AudioInfo` that is also initialized with
    /// `gstaudio.audioInfoInit`.
    extern fn gst_audio_info_new() *gstaudio.AudioInfo;
    pub const new = gst_audio_info_new;

    /// Parse `caps` to generate a `gstaudio.AudioInfo`.
    extern fn gst_audio_info_new_from_caps(p_caps: *const gst.Caps) ?*gstaudio.AudioInfo;
    pub const newFromCaps = gst_audio_info_new_from_caps;

    /// Converts among various `gst.Format` types.  This function handles
    /// GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT.  For
    /// raw audio, GST_FORMAT_DEFAULT corresponds to audio frames.  This
    /// function can be used to handle pad queries of the type GST_QUERY_CONVERT.
    extern fn gst_audio_info_convert(p_info: *const AudioInfo, p_src_fmt: gst.Format, p_src_val: i64, p_dest_fmt: gst.Format, p_dest_val: *i64) c_int;
    pub const convert = gst_audio_info_convert;

    /// Copy a GstAudioInfo structure.
    extern fn gst_audio_info_copy(p_info: *const AudioInfo) *gstaudio.AudioInfo;
    pub const copy = gst_audio_info_copy;

    /// Free a GstAudioInfo structure previously allocated with `gstaudio.AudioInfo.new`
    /// or `gstaudio.AudioInfo.copy`.
    extern fn gst_audio_info_free(p_info: *AudioInfo) void;
    pub const free = gst_audio_info_free;

    /// Compares two `gstaudio.AudioInfo` and returns whether they are equal or not
    extern fn gst_audio_info_is_equal(p_info: *const AudioInfo, p_other: *const gstaudio.AudioInfo) c_int;
    pub const isEqual = gst_audio_info_is_equal;

    /// Set the default info for the audio info of `format` and `rate` and `channels`.
    ///
    /// Note: This initializes `info` first, no values are preserved.
    extern fn gst_audio_info_set_format(p_info: *AudioInfo, p_format: gstaudio.AudioFormat, p_rate: c_int, p_channels: c_int, p_position: ?*const [64]gstaudio.AudioChannelPosition) void;
    pub const setFormat = gst_audio_info_set_format;

    /// Convert the values of `info` into a `gst.Caps`.
    extern fn gst_audio_info_to_caps(p_info: *const AudioInfo) *gst.Caps;
    pub const toCaps = gst_audio_info_to_caps;

    extern fn gst_audio_info_get_type() usize;
    pub const getGObjectType = gst_audio_info_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Meta containing Audio Level Indication: https://tools.ietf.org/html/rfc6464
pub const AudioLevelMeta = extern struct {
    /// parent `gst.Meta`
    f_meta: gst.Meta,
    /// the -dBov from 0-127 (127 is silence).
    f_level: u8,
    /// whether the buffer contains voice activity
    f_voice_activity: c_int,

    /// Return the `gst.MetaInfo` associated with `gstaudio.AudioLevelMeta`.
    extern fn gst_audio_level_meta_get_info() *const gst.MetaInfo;
    pub const getInfo = gst_audio_level_meta_get_info;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// `gstaudio.AudioDownmixMeta` defines an audio downmix matrix to be send along with
/// audio buffers. These functions in this module help to create and attach the
/// meta as well as extracting it.
pub const AudioMeta = extern struct {
    /// parent `gst.Meta`
    f_meta: gst.Meta,
    /// the audio properties of the buffer
    f_info: gstaudio.AudioInfo,
    /// the number of valid samples in the buffer
    f_samples: usize,
    /// the offsets (in bytes) where each channel plane starts in the
    ///   buffer or `NULL` if the buffer has interleaved layout; if not `NULL`, this
    ///   is guaranteed to be an array of `info`.channels elements
    f_offsets: ?*usize,
    f_priv_offsets_arr: [8]usize,
    f__gst_reserved: [4]*anyopaque,

    extern fn gst_audio_meta_get_info() *const gst.MetaInfo;
    pub const getInfo = gst_audio_meta_get_info;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioQuantize = opaque {
    /// Create a new quantizer object with the given parameters.
    ///
    /// Output samples will be quantized to a multiple of `quantizer`. Better
    /// performance is achieved when `quantizer` is a power of 2.
    ///
    /// Dithering and noise-shaping can be performed during quantization with
    /// the `dither` and `ns` parameters.
    extern fn gst_audio_quantize_new(p_dither: gstaudio.AudioDitherMethod, p_ns: gstaudio.AudioNoiseShapingMethod, p_flags: gstaudio.AudioQuantizeFlags, p_format: gstaudio.AudioFormat, p_channels: c_uint, p_quantizer: c_uint) *gstaudio.AudioQuantize;
    pub const new = gst_audio_quantize_new;

    /// Free a `gstaudio.AudioQuantize`.
    extern fn gst_audio_quantize_free(p_quant: *AudioQuantize) void;
    pub const free = gst_audio_quantize_free;

    /// Reset `quant` to the state is was when created, clearing any
    /// history it might have.
    extern fn gst_audio_quantize_reset(p_quant: *AudioQuantize) void;
    pub const reset = gst_audio_quantize_reset;

    /// Perform quantization on `samples` in `in` and write the result to `out`.
    ///
    /// In case the samples are interleaved, `in` and `out` must point to an
    /// array with a single element pointing to a block of interleaved samples.
    ///
    /// If non-interleaved samples are used, `in` and `out` must point to an
    /// array with pointers to memory blocks, one for each channel.
    ///
    /// `in` and `out` may point to the same memory location, in which case samples will be
    /// modified in-place.
    extern fn gst_audio_quantize_samples(p_quant: *AudioQuantize, p_in: ?*anyopaque, p_out: ?*anyopaque, p_samples: c_uint) void;
    pub const samples = gst_audio_quantize_samples;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// `gstaudio.AudioResampler` is a structure which holds the information
/// required to perform various kinds of resampling filtering.
pub const AudioResampler = opaque {
    /// Make a new resampler.
    extern fn gst_audio_resampler_new(p_method: gstaudio.AudioResamplerMethod, p_flags: gstaudio.AudioResamplerFlags, p_format: gstaudio.AudioFormat, p_channels: c_int, p_in_rate: c_int, p_out_rate: c_int, p_options: *gst.Structure) *gstaudio.AudioResampler;
    pub const new = gst_audio_resampler_new;

    /// Set the parameters for resampling from `in_rate` to `out_rate` using `method`
    /// for `quality` in `options`.
    extern fn gst_audio_resampler_options_set_quality(p_method: gstaudio.AudioResamplerMethod, p_quality: c_uint, p_in_rate: c_int, p_out_rate: c_int, p_options: *gst.Structure) void;
    pub const optionsSetQuality = gst_audio_resampler_options_set_quality;

    /// Free a previously allocated `gstaudio.AudioResampler` `resampler`.
    extern fn gst_audio_resampler_free(p_resampler: *AudioResampler) void;
    pub const free = gst_audio_resampler_free;

    /// Get the number of input frames that would currently be needed
    /// to produce `out_frames` from `resampler`.
    extern fn gst_audio_resampler_get_in_frames(p_resampler: *AudioResampler, p_out_frames: usize) usize;
    pub const getInFrames = gst_audio_resampler_get_in_frames;

    /// Get the maximum number of input samples that the resampler would
    /// need before producing output.
    extern fn gst_audio_resampler_get_max_latency(p_resampler: *AudioResampler) usize;
    pub const getMaxLatency = gst_audio_resampler_get_max_latency;

    /// Get the number of output frames that would be currently available when
    /// `in_frames` are given to `resampler`.
    extern fn gst_audio_resampler_get_out_frames(p_resampler: *AudioResampler, p_in_frames: usize) usize;
    pub const getOutFrames = gst_audio_resampler_get_out_frames;

    /// Perform resampling on `in_frames` frames in `in` and write `out_frames` to `out`.
    ///
    /// In case the samples are interleaved, `in` and `out` must point to an
    /// array with a single element pointing to a block of interleaved samples.
    ///
    /// If non-interleaved samples are used, `in` and `out` must point to an
    /// array with pointers to memory blocks, one for each channel.
    ///
    /// `in` may be `NULL`, in which case `in_frames` of silence samples are pushed
    /// into the resampler.
    ///
    /// This function always produces `out_frames` of output and consumes `in_frames` of
    /// input. Use `gstaudio.AudioResampler.getOutFrames` and
    /// `gstaudio.AudioResampler.getInFrames` to make sure `in_frames` and `out_frames`
    /// are matching and `in` and `out` point to enough memory.
    extern fn gst_audio_resampler_resample(p_resampler: *AudioResampler, p_in: ?*anyopaque, p_in_frames: usize, p_out: ?*anyopaque, p_out_frames: usize) void;
    pub const resample = gst_audio_resampler_resample;

    /// Reset `resampler` to the state it was when it was first created, discarding
    /// all sample history.
    extern fn gst_audio_resampler_reset(p_resampler: *AudioResampler) void;
    pub const reset = gst_audio_resampler_reset;

    /// Update the resampler parameters for `resampler`. This function should
    /// not be called concurrently with any other function on `resampler`.
    ///
    /// When `in_rate` or `out_rate` is 0, its value is unchanged.
    ///
    /// When `options` is `NULL`, the previously configured options are reused.
    extern fn gst_audio_resampler_update(p_resampler: *AudioResampler, p_in_rate: c_int, p_out_rate: c_int, p_options: *gst.Structure) c_int;
    pub const update = gst_audio_resampler_update;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// The vmethods that subclasses can override to implement the ringbuffer.
pub const AudioRingBufferClass = extern struct {
    pub const Instance = gstaudio.AudioRingBuffer;

    /// parent class
    f_parent_class: gst.ObjectClass,
    /// open the device, don't set any params or allocate anything
    f_open_device: ?*const fn (p_buf: *gstaudio.AudioRingBuffer) callconv(.c) c_int,
    /// allocate the resources for the ringbuffer using the given spec
    f_acquire: ?*const fn (p_buf: *gstaudio.AudioRingBuffer, p_spec: *gstaudio.AudioRingBufferSpec) callconv(.c) c_int,
    /// free resources of the ringbuffer
    f_release: ?*const fn (p_buf: *gstaudio.AudioRingBuffer) callconv(.c) c_int,
    /// close the device
    f_close_device: ?*const fn (p_buf: *gstaudio.AudioRingBuffer) callconv(.c) c_int,
    /// start processing of samples
    f_start: ?*const fn (p_buf: *gstaudio.AudioRingBuffer) callconv(.c) c_int,
    /// pause processing of samples
    f_pause: ?*const fn (p_buf: *gstaudio.AudioRingBuffer) callconv(.c) c_int,
    /// resume processing of samples after pause
    f_resume: ?*const fn (p_buf: *gstaudio.AudioRingBuffer) callconv(.c) c_int,
    /// stop processing of samples
    f_stop: ?*const fn (p_buf: *gstaudio.AudioRingBuffer) callconv(.c) c_int,
    /// get number of frames queued in device
    f_delay: ?*const fn (p_buf: *gstaudio.AudioRingBuffer) callconv(.c) c_uint,
    /// activate the thread that starts pulling and monitoring the
    /// consumed segments in the device.
    f_activate: ?*const fn (p_buf: *gstaudio.AudioRingBuffer, p_active: c_int) callconv(.c) c_int,
    /// write samples into the ringbuffer
    f_commit: ?*const fn (p_buf: *gstaudio.AudioRingBuffer, p_sample: *u64, p_data: [*]u8, p_in_samples: c_int, p_out_samples: c_int, p_accum: *c_int) callconv(.c) c_uint,
    /// Optional.
    ///             Clear the entire ringbuffer.
    ///             Subclasses should chain up to the parent implementation to
    ///             invoke the default handler.
    f_clear_all: ?*const fn (p_buf: *gstaudio.AudioRingBuffer) callconv(.c) void,
    f__gst_reserved: [4]*anyopaque,

    pub fn as(p_instance: *AudioRingBufferClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioRingBufferPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// The structure containing the format specification of the ringbuffer.
///
/// When `type` is GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DSD, the `dsd_format`
/// is valid (otherwise it is unused). Also, when DSD is the sample type,
/// only the rate, channels, position, and bpf fields in `info` are populated.
pub const AudioRingBufferSpec = extern struct {
    /// The caps that generated the Spec.
    f_caps: ?*gst.Caps,
    /// the sample type
    f_type: gstaudio.AudioRingBufferFormatType,
    /// the `gstaudio.AudioInfo`
    f_info: gstaudio.AudioInfo,
    /// the latency in microseconds
    f_latency_time: u64,
    /// the total buffer size in microseconds
    f_buffer_time: u64,
    /// the size of one segment in bytes
    f_segsize: c_int,
    /// the total number of segments
    f_segtotal: c_int,
    /// number of segments queued in the lower level device,
    ///  defaults to segtotal
    f_seglatency: c_int,
    anon0: extern union {
        anon0: extern struct {
            f_dsd_format: gstaudio.DsdFormat,
        },
        f__gst_reserved: [4]*anyopaque,
    },

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioSinkClass = extern struct {
    pub const Instance = gstaudio.AudioSink;

    /// the parent class structure.
    f_parent_class: gstaudio.AudioBaseSinkClass,
    /// Open the device. No configuration needs to be done at this point.
    ///        This function is also used to check if the device is available.
    f_open: ?*const fn (p_sink: *gstaudio.AudioSink) callconv(.c) c_int,
    /// Prepare the device to operate with the specified parameters.
    f_prepare: ?*const fn (p_sink: *gstaudio.AudioSink, p_spec: *gstaudio.AudioRingBufferSpec) callconv(.c) c_int,
    /// Undo operations done in prepare.
    f_unprepare: ?*const fn (p_sink: *gstaudio.AudioSink) callconv(.c) c_int,
    /// Close the device.
    f_close: ?*const fn (p_sink: *gstaudio.AudioSink) callconv(.c) c_int,
    /// Write data to the device.
    ///         This vmethod is allowed to block until all the data is written.
    ///         If such is the case then it is expected that pause, stop and
    ///         reset will unblock the write when called.
    f_write: ?*const fn (p_sink: *gstaudio.AudioSink, p_data: [*]u8, p_length: c_uint) callconv(.c) c_int,
    /// Return how many frames are still in the device. Participates in
    ///         computing the time for audio clocks and drives the synchronisation.
    f_delay: ?*const fn (p_sink: *gstaudio.AudioSink) callconv(.c) c_uint,
    /// Returns as quickly as possible from a write and flush any pending
    ///         samples from the device.
    ///         This vmethod is deprecated. Please provide pause and stop instead.
    f_reset: ?*const fn (p_sink: *gstaudio.AudioSink) callconv(.c) void,
    /// Pause the device and unblock write as fast as possible.
    ///         For retro compatibility, the audio sink will fallback
    ///         to calling reset if this vmethod is not provided. Since: 1.18
    f_pause: ?*const fn (p_sink: *gstaudio.AudioSink) callconv(.c) void,
    /// Resume the device. Since: 1.18
    f_resume: ?*const fn (p_sink: *gstaudio.AudioSink) callconv(.c) void,
    /// Stop the device and unblock write as fast as possible.
    ///        Pending samples are flushed from the device.
    ///        For retro compatibility, the audio sink will fallback
    ///        to calling reset if this vmethod is not provided. Since: 1.18
    f_stop: ?*const fn (p_sink: *gstaudio.AudioSink) callconv(.c) void,
    /// class extension structure. Since: 1.18
    f_extension: ?*gstaudio.AudioSinkClassExtension,

    pub fn as(p_instance: *AudioSinkClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AudioSinkClassExtension = extern struct {
    f_clear_all: ?*const fn (p_sink: *gstaudio.AudioSink) callconv(.c) void,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// `gstaudio.AudioSrc` class. Override the vmethod to implement
/// functionality.
pub const AudioSrcClass = extern struct {
    pub const Instance = gstaudio.AudioSrc;

    /// the parent class.
    f_parent_class: gstaudio.AudioBaseSrcClass,
    /// open the device with the specified caps
    f_open: ?*const fn (p_src: *gstaudio.AudioSrc) callconv(.c) c_int,
    /// configure device with format
    f_prepare: ?*const fn (p_src: *gstaudio.AudioSrc, p_spec: *gstaudio.AudioRingBufferSpec) callconv(.c) c_int,
    /// undo the configuration
    f_unprepare: ?*const fn (p_src: *gstaudio.AudioSrc) callconv(.c) c_int,
    /// close the device
    f_close: ?*const fn (p_src: *gstaudio.AudioSrc) callconv(.c) c_int,
    /// read samples from the audio device
    f_read: ?*const fn (p_src: *gstaudio.AudioSrc, p_data: [*]u8, p_length: c_uint, p_timestamp: *gst.ClockTime) callconv(.c) c_uint,
    /// the number of frames queued in the device
    f_delay: ?*const fn (p_src: *gstaudio.AudioSrc) callconv(.c) c_uint,
    /// unblock a read to the device and reset.
    f_reset: ?*const fn (p_src: *gstaudio.AudioSrc) callconv(.c) void,
    f__gst_reserved: [4]*anyopaque,

    pub fn as(p_instance: *AudioSrcClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// `gstaudio.AudioStreamAlign` provides a helper object that helps tracking audio
/// stream alignment and discontinuities, and detects discontinuities if
/// possible.
///
/// See `gstaudio.AudioStreamAlign.new` for a description of its parameters and
/// `gstaudio.AudioStreamAlign.process` for the details of the processing.
pub const AudioStreamAlign = opaque {
    /// Allocate a new `gstaudio.AudioStreamAlign` with the given configuration. All
    /// processing happens according to sample rate `rate`, until
    /// `gstaudio.AudioStreamAlign.setRate` is called with a new `rate`.
    /// A negative rate can be used for reverse playback.
    ///
    /// `alignment_threshold` gives the tolerance in nanoseconds after which a
    /// timestamp difference is considered a discontinuity. Once detected,
    /// `discont_wait` nanoseconds have to pass without going below the threshold
    /// again until the output buffer is marked as a discontinuity. These can later
    /// be re-configured with `gstaudio.AudioStreamAlign.setAlignmentThreshold` and
    /// `gstaudio.AudioStreamAlign.setDiscontWait`.
    extern fn gst_audio_stream_align_new(p_rate: c_int, p_alignment_threshold: gst.ClockTime, p_discont_wait: gst.ClockTime) *gstaudio.AudioStreamAlign;
    pub const new = gst_audio_stream_align_new;

    /// Copy a GstAudioStreamAlign structure.
    extern fn gst_audio_stream_align_copy(p_align: *const AudioStreamAlign) *gstaudio.AudioStreamAlign;
    pub const copy = gst_audio_stream_align_copy;

    /// Free a GstAudioStreamAlign structure previously allocated with `gstaudio.AudioStreamAlign.new`
    /// or `gstaudio.AudioStreamAlign.copy`.
    extern fn gst_audio_stream_align_free(p_align: *AudioStreamAlign) void;
    pub const free = gst_audio_stream_align_free;

    /// Gets the currently configured alignment threshold.
    extern fn gst_audio_stream_align_get_alignment_threshold(p_align: *const AudioStreamAlign) gst.ClockTime;
    pub const getAlignmentThreshold = gst_audio_stream_align_get_alignment_threshold;

    /// Gets the currently configured discont wait.
    extern fn gst_audio_stream_align_get_discont_wait(p_align: *const AudioStreamAlign) gst.ClockTime;
    pub const getDiscontWait = gst_audio_stream_align_get_discont_wait;

    /// Gets the currently configured sample rate.
    extern fn gst_audio_stream_align_get_rate(p_align: *const AudioStreamAlign) c_int;
    pub const getRate = gst_audio_stream_align_get_rate;

    /// Returns the number of samples that were processed since the last
    /// discontinuity was detected.
    extern fn gst_audio_stream_align_get_samples_since_discont(p_align: *const AudioStreamAlign) u64;
    pub const getSamplesSinceDiscont = gst_audio_stream_align_get_samples_since_discont;

    /// Timestamp that was passed when a discontinuity was detected, i.e. the first
    /// timestamp after the discontinuity.
    extern fn gst_audio_stream_align_get_timestamp_at_discont(p_align: *const AudioStreamAlign) gst.ClockTime;
    pub const getTimestampAtDiscont = gst_audio_stream_align_get_timestamp_at_discont;

    /// Marks the next buffer as discontinuous and resets timestamp tracking.
    extern fn gst_audio_stream_align_mark_discont(p_align: *AudioStreamAlign) void;
    pub const markDiscont = gst_audio_stream_align_mark_discont;

    /// Processes data with `timestamp` and `n_samples`, and returns the output
    /// timestamp, duration and sample position together with a boolean to signal
    /// whether a discontinuity was detected or not. All non-discontinuous data
    /// will have perfect timestamps and durations.
    ///
    /// A discontinuity is detected once the difference between the actual
    /// timestamp and the timestamp calculated from the sample count since the last
    /// discontinuity differs by more than the alignment threshold for a duration
    /// longer than discont wait.
    ///
    /// Note: In reverse playback, every buffer is considered discontinuous in the
    /// context of buffer flags because the last sample of the previous buffer is
    /// discontinuous with the first sample of the current one. However for this
    /// function they are only considered discontinuous in reverse playback if the
    /// first sample of the previous buffer is discontinuous with the last sample
    /// of the current one.
    extern fn gst_audio_stream_align_process(p_align: *AudioStreamAlign, p_discont: c_int, p_timestamp: gst.ClockTime, p_n_samples: c_uint, p_out_timestamp: *gst.ClockTime, p_out_duration: *gst.ClockTime, p_out_sample_position: *u64) c_int;
    pub const process = gst_audio_stream_align_process;

    /// Sets `alignment_treshold` as new alignment threshold for the following processing.
    extern fn gst_audio_stream_align_set_alignment_threshold(p_align: *AudioStreamAlign, p_alignment_threshold: gst.ClockTime) void;
    pub const setAlignmentThreshold = gst_audio_stream_align_set_alignment_threshold;

    /// Sets `alignment_treshold` as new discont wait for the following processing.
    extern fn gst_audio_stream_align_set_discont_wait(p_align: *AudioStreamAlign, p_discont_wait: gst.ClockTime) void;
    pub const setDiscontWait = gst_audio_stream_align_set_discont_wait;

    /// Sets `rate` as new sample rate for the following processing. If the sample
    /// rate differs this implicitly marks the next data as discontinuous.
    extern fn gst_audio_stream_align_set_rate(p_align: *AudioStreamAlign, p_rate: c_int) void;
    pub const setRate = gst_audio_stream_align_set_rate;

    extern fn gst_audio_stream_align_get_type() usize;
    pub const getGObjectType = gst_audio_stream_align_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Information describing DSD audio properties.
///
/// In DSD, the "sample format" is the bit. Unlike PCM, there are no further
/// "sample formats" in DSD. However, in software, DSD bits are grouped into
/// bytes (since dealing with individual bits is impractical), and these bytes
/// in turn are grouped into words. This becomes relevant when interleaving
/// channels and transmitting DSD data through audio APIs. The different
/// types of grouping DSD bytes are referred to as the "DSD grouping forma"
/// or just "DSD format". `gstaudio.DsdFormat` has a list of valid ways of grouping
/// DSD bytes into words.
///
/// DSD rates are equivalent to PCM sample rates, except that they specify
/// how many DSD bytes are consumed per second. This refers to the bytes per
/// second _per channel_; the rate does not change when the number of channel
/// changes. (Strictly speaking, it would be more correct to measure the
/// *bits* per second, since the bit is the DSD "sample format", but it is
/// more practical to use bytes.) In DSD, bit rates are always an integer
/// multiple of the CD audio rate (44100) or the DAT rate (48000). DSD64-44x
/// is 44100 * 64 = 2822400 bits per second, or 352800 bytes per second
/// (the latter would be used in this info structure). DSD64-48x is
/// 48000 * 64 = 3072000 bits per second, or 384000 bytes per second.
/// `GST_DSD_MAKE_DSD_RATE_44x` can be used for specifying DSD-44x rates,
/// *and `GST_DSD_MAKE_DSD_RATE_48x` can be used for specifying DSD-48x ones.
/// Also, since DSD-48x is less well known, when the multiplier is given
/// without the 44x/48x specifier, 44x is typically implied.
///
/// It is important to know that in DSD, different format widths correspond
/// to different playtimes. That is, a word with 32 DSD bits covers two times
/// as much playtime as a word with 16 DSD bits. This is in contrast to PCM,
/// where one word (= one PCM sample) always covers a time period of 1/samplerate,
/// no matter how many bits a PCM sample is made of. For this reason, DSD
/// and PCM widths and strides cannot be used the same way.
///
/// Multiple channels are arranged in DSD data either interleaved or non-
/// interleaved. This is similar to PCM. Interleaved layouts rotate between
/// channels and words. First, word 0 of channel 0 is present. Then word
/// 0 of channel 1 follows. Then word 0 of channel 2 etc. until all
/// channels are through, then comes word 1 of channel 0 etc.
///
/// Non-interleaved data is planar. First, all words of channel 0 are
/// present, then all words of channel 1 etc. Unlike interleaved data,
/// non-interleaved data can be sparse, that is, there can be space in
/// between the planes. the `positions` array specifies the plane offsets.
///
/// In uncommon cases, the DSD bits in the data bytes can be stored in reverse
/// order. For example, normally, in DSDU8, the first byte contains DSD bits
/// 0 to 7, and the most significant bit of that byte is DSD bit 0. If this
/// order is reversed, then bit 7 is the first one instead. In that ase,
/// `reversed_bytes` is set to TRUE.
///
/// Use the provided macros to access the info in this structure.
pub const DsdInfo = extern struct {
    /// DSD grouping format
    f_format: gstaudio.DsdFormat,
    /// DSD rate
    f_rate: c_int,
    /// number of channels (must be at least 1)
    f_channels: c_int,
    /// audio layout
    f_layout: gstaudio.AudioLayout,
    /// true if the DSD bits in the data bytes are reversed,
    ///   that is, the least significant bit comes first
    f_reversed_bytes: c_int,
    /// positions for each channel
    f_positions: [64]gstaudio.AudioChannelPosition,
    f_flags: gstaudio.AudioFlags,
    f__gst_reserved: [4]*anyopaque,

    /// Parse `caps` and update `info`.
    extern fn gst_dsd_info_from_caps(p_info: *gstaudio.DsdInfo, p_caps: *const gst.Caps) c_int;
    pub const fromCaps = gst_dsd_info_from_caps;

    /// Initialize `info` with default values.
    extern fn gst_dsd_info_init(p_info: *gstaudio.DsdInfo) void;
    pub const init = gst_dsd_info_init;

    /// Allocate a new `gstaudio.DsdInfo` that is also initialized with
    /// `gstaudio.dsdInfoInit`.
    extern fn gst_dsd_info_new() *gstaudio.DsdInfo;
    pub const new = gst_dsd_info_new;

    /// Parse `caps` to generate a `gstaudio.DsdInfo`.
    extern fn gst_dsd_info_new_from_caps(p_caps: *const gst.Caps) *gstaudio.DsdInfo;
    pub const newFromCaps = gst_dsd_info_new_from_caps;

    /// Copy a GstDsdInfo structure.
    extern fn gst_dsd_info_copy(p_info: *const DsdInfo) *gstaudio.DsdInfo;
    pub const copy = gst_dsd_info_copy;

    /// Free a GstDsdInfo structure previously allocated with `gstaudio.DsdInfo.new`
    /// or `gstaudio.DsdInfo.copy`.
    extern fn gst_dsd_info_free(p_info: *DsdInfo) void;
    pub const free = gst_dsd_info_free;

    /// Compares two `gstaudio.DsdInfo` and returns whether they are equal or not
    extern fn gst_dsd_info_is_equal(p_info: *const DsdInfo, p_other: *const gstaudio.DsdInfo) c_int;
    pub const isEqual = gst_dsd_info_is_equal;

    /// Set the default info for the DSD info of `format` and `rate` and `channels`.
    ///
    /// Note: This initializes `info` first, no values are preserved.
    extern fn gst_dsd_info_set_format(p_info: *DsdInfo, p_format: gstaudio.DsdFormat, p_rate: c_int, p_channels: c_int, p_positions: ?*const [64]gstaudio.AudioChannelPosition) void;
    pub const setFormat = gst_dsd_info_set_format;

    /// Convert the values of `info` into a `gst.Caps`.
    extern fn gst_dsd_info_to_caps(p_info: *const DsdInfo) *gst.Caps;
    pub const toCaps = gst_dsd_info_to_caps;

    extern fn gst_dsd_info_get_type() usize;
    pub const getGObjectType = gst_dsd_info_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Buffer metadata describing planar DSD contents in the buffer. This is not needed
/// for interleaved DSD data, and is required for non-interleaved (= planar) data.
///
/// The different channels in `offsets` are always in the GStreamer channel order.
/// Zero-copy channel reordering can be implemented by swapping the values in
/// `offsets`.
///
/// It is not allowed for channels to overlap in memory,
/// i.e. for each i in [0, channels), the range
/// [`offsets`[i], `offsets`[i] + `num_bytes_per_channel`) must not overlap
/// with any other such range.
///
/// It is, however, allowed to have parts of the buffer memory unused, by using
/// `offsets` and `num_bytes_per_channel` in such a way that leave gaps on it.
/// This is used to implement zero-copy clipping in non-interleaved buffers.
///
/// Obviously, due to the above, it is not safe to infer the
/// number of valid bytes from the size of the buffer. You should always
/// use the `num_bytes_per_channel` variable of this metadata.
pub const DsdPlaneOffsetMeta = extern struct {
    /// parent `gst.Meta`
    f_meta: gst.Meta,
    /// number of channels in the DSD data
    f_num_channels: c_int,
    /// the number of valid bytes per channel in the buffer
    f_num_bytes_per_channel: usize,
    /// the offsets (in bytes) where each channel plane starts in the buffer
    f_offsets: ?*usize,
    f_priv_offsets_arr: [8]usize,
    f__gst_reserved: [4]*anyopaque,

    extern fn gst_dsd_plane_offset_meta_get_info() *const gst.MetaInfo;
    pub const getInfo = gst_dsd_plane_offset_meta_get_info;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const StreamVolumeInterface = extern struct {
    pub const Instance = gstaudio.StreamVolume;

    f_iface: gobject.TypeInterface,

    pub fn as(p_instance: *StreamVolumeInterface, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Different possible reasons for discontinuities. This enum is useful for the custom
/// slave method.
pub const AudioBaseSinkDiscontReason = enum(c_int) {
    no_discont = 0,
    new_caps = 1,
    flush = 2,
    sync_latency = 3,
    alignment = 4,
    device_failure = 5,
    _,

    extern fn gst_audio_base_sink_discont_reason_get_type() usize;
    pub const getGObjectType = gst_audio_base_sink_discont_reason_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Different possible clock slaving algorithms used when the internal audio
/// clock is not selected as the pipeline master clock.
pub const AudioBaseSinkSlaveMethod = enum(c_int) {
    resample = 0,
    skew = 1,
    none = 2,
    custom = 3,
    _,

    extern fn gst_audio_base_sink_slave_method_get_type() usize;
    pub const getGObjectType = gst_audio_base_sink_slave_method_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Different possible clock slaving algorithms when the internal audio clock was
/// not selected as the pipeline clock.
pub const AudioBaseSrcSlaveMethod = enum(c_int) {
    resample = 0,
    re_timestamp = 1,
    skew = 2,
    none = 3,
    _,

    extern fn gst_audio_base_src_slave_method_get_type() usize;
    pub const getGObjectType = gst_audio_base_src_slave_method_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Mode in which the CD audio source operates. Influences timestamping,
/// EOS handling and seeking.
pub const AudioCdSrcMode = enum(c_int) {
    normal = 0,
    continuous = 1,
    _,

    extern fn gst_audio_cd_src_mode_get_type() usize;
    pub const getGObjectType = gst_audio_cd_src_mode_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Audio channel positions.
///
/// These are the channels defined in SMPTE 2036-2-2008
/// Table 1 for 22.2 audio systems with the Surround and Wide channels from
/// DTS Coherent Acoustics (v.1.3.1) and 10.2 and 7.1 layouts. In the caps the
/// actual channel layout is expressed with a channel count and a channel mask,
/// which describes the existing channels. The positions in the bit mask correspond
/// to the enum values.
/// For negotiation it is allowed to have more bits set in the channel mask than
/// the number of channels to specify the allowed channel positions but this is
/// not allowed in negotiated caps. It is not allowed in any situation other
/// than the one mentioned below to have less bits set in the channel mask than
/// the number of channels.
///
/// `GST_AUDIO_CHANNEL_POSITION_MONO` can only be used with a single mono channel that
/// has no direction information and would be mixed into all directional channels.
/// This is expressed in caps by having a single channel and no channel mask.
///
/// `GST_AUDIO_CHANNEL_POSITION_NONE` can only be used if all channels have this position.
/// This is expressed in caps by having a channel mask with no bits set.
///
/// As another special case it is allowed to have two channels without a channel mask.
/// This implicitly means that this is a stereo stream with a front left and front right
/// channel.
pub const AudioChannelPosition = enum(c_int) {
    none = -3,
    mono = -2,
    invalid = -1,
    front_left = 0,
    front_right = 1,
    front_center = 2,
    lfe1 = 3,
    rear_left = 4,
    rear_right = 5,
    front_left_of_center = 6,
    front_right_of_center = 7,
    rear_center = 8,
    lfe2 = 9,
    side_left = 10,
    side_right = 11,
    top_front_left = 12,
    top_front_right = 13,
    top_front_center = 14,
    top_center = 15,
    top_rear_left = 16,
    top_rear_right = 17,
    top_side_left = 18,
    top_side_right = 19,
    top_rear_center = 20,
    bottom_front_center = 21,
    bottom_front_left = 22,
    bottom_front_right = 23,
    wide_left = 24,
    wide_right = 25,
    surround_left = 26,
    surround_right = 27,
    top_surround_left = 28,
    top_surround_right = 29,
    _,

    extern fn gst_audio_channel_position_get_type() usize;
    pub const getGObjectType = gst_audio_channel_position_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Set of available dithering methods.
pub const AudioDitherMethod = enum(c_int) {
    none = 0,
    rpdf = 1,
    tpdf = 2,
    tpdf_hf = 3,
    _,

    extern fn gst_audio_dither_method_get_type() usize;
    pub const getGObjectType = gst_audio_dither_method_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Enum value describing the most common audio formats.
pub const AudioFormat = enum(c_int) {
    unknown = 0,
    encoded = 1,
    s8 = 2,
    u8 = 3,
    s16le = 4,
    s16be = 5,
    u16le = 6,
    u16be = 7,
    s24_32le = 8,
    s24_32be = 9,
    u24_32le = 10,
    u24_32be = 11,
    s32le = 12,
    s32be = 13,
    u32le = 14,
    u32be = 15,
    s24le = 16,
    s24be = 17,
    u24le = 18,
    u24be = 19,
    s20le = 20,
    s20be = 21,
    u20le = 22,
    u20be = 23,
    s18le = 24,
    s18be = 25,
    u18le = 26,
    u18be = 27,
    f32le = 28,
    f32be = 29,
    f64le = 30,
    f64be = 31,
    _,

    pub const s16 = AudioFormat.s16le;
    pub const @"u16" = AudioFormat.u16le;
    pub const s24_32 = AudioFormat.s24_32le;
    pub const u24_32 = AudioFormat.u24_32le;
    pub const s32 = AudioFormat.s32le;
    pub const @"u32" = AudioFormat.u32le;
    pub const s24 = AudioFormat.s24le;
    pub const @"u24" = AudioFormat.u24le;
    pub const s20 = AudioFormat.s20le;
    pub const @"u20" = AudioFormat.u20le;
    pub const s18 = AudioFormat.s18le;
    pub const @"u18" = AudioFormat.u18le;
    pub const @"f32" = AudioFormat.f32le;
    pub const @"f64" = AudioFormat.f64le;
    /// Construct a `gstaudio.AudioFormat` with given parameters.
    extern fn gst_audio_format_build_integer(p_sign: c_int, p_endianness: c_int, p_width: c_int, p_depth: c_int) gstaudio.AudioFormat;
    pub const buildInteger = gst_audio_format_build_integer;

    /// Fill `length` bytes in `dest` with silence samples for `info`.
    extern fn gst_audio_format_fill_silence(p_info: *const gstaudio.AudioFormatInfo, p_dest: [*]u8, p_length: usize) void;
    pub const fillSilence = gst_audio_format_fill_silence;

    /// Convert the `format` string to its `gstaudio.AudioFormat`.
    extern fn gst_audio_format_from_string(p_format: [*:0]const u8) gstaudio.AudioFormat;
    pub const fromString = gst_audio_format_from_string;

    /// Get the `gstaudio.AudioFormatInfo` for `format`
    extern fn gst_audio_format_get_info(p_format: gstaudio.AudioFormat) *const gstaudio.AudioFormatInfo;
    pub const getInfo = gst_audio_format_get_info;

    /// Returns a string containing a descriptive name for the `gstaudio.AudioFormat`.
    ///
    /// Since 1.26 this can also be used with `GST_AUDIO_FORMAT_UNKNOWN`, previous
    /// versions were printing a critical warning and returned `NULL`.
    extern fn gst_audio_format_to_string(p_format: gstaudio.AudioFormat) [*:0]const u8;
    pub const toString = gst_audio_format_to_string;

    extern fn gst_audio_format_get_type() usize;
    pub const getGObjectType = gst_audio_format_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Layout of the audio samples for the different channels.
pub const AudioLayout = enum(c_int) {
    interleaved = 0,
    non_interleaved = 1,
    _,

    extern fn gst_audio_layout_get_type() usize;
    pub const getGObjectType = gst_audio_layout_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Set of available noise shaping methods
pub const AudioNoiseShapingMethod = enum(c_int) {
    none = 0,
    error_feedback = 1,
    simple = 2,
    medium = 3,
    high = 4,
    _,

    extern fn gst_audio_noise_shaping_method_get_type() usize;
    pub const getGObjectType = gst_audio_noise_shaping_method_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// The different filter interpolation methods.
pub const AudioResamplerFilterInterpolation = enum(c_int) {
    none = 0,
    linear = 1,
    cubic = 2,
    _,

    extern fn gst_audio_resampler_filter_interpolation_get_type() usize;
    pub const getGObjectType = gst_audio_resampler_filter_interpolation_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Select for the filter tables should be set up.
pub const AudioResamplerFilterMode = enum(c_int) {
    interpolated = 0,
    full = 1,
    auto = 2,
    _,

    extern fn gst_audio_resampler_filter_mode_get_type() usize;
    pub const getGObjectType = gst_audio_resampler_filter_mode_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Different subsampling and upsampling methods
pub const AudioResamplerMethod = enum(c_int) {
    nearest = 0,
    linear = 1,
    cubic = 2,
    blackman_nuttall = 3,
    kaiser = 4,
    _,

    extern fn gst_audio_resampler_method_get_type() usize;
    pub const getGObjectType = gst_audio_resampler_method_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// The format of the samples in the ringbuffer.
pub const AudioRingBufferFormatType = enum(c_int) {
    raw = 0,
    mu_law = 1,
    a_law = 2,
    ima_adpcm = 3,
    mpeg = 4,
    gsm = 5,
    iec958 = 6,
    ac3 = 7,
    eac3 = 8,
    dts = 9,
    mpeg2_aac = 10,
    mpeg4_aac = 11,
    mpeg2_aac_raw = 12,
    mpeg4_aac_raw = 13,
    flac = 14,
    dsd = 15,
    _,

    extern fn gst_audio_ring_buffer_format_type_get_type() usize;
    pub const getGObjectType = gst_audio_ring_buffer_format_type_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// The state of the ringbuffer.
pub const AudioRingBufferState = enum(c_int) {
    stopped = 0,
    paused = 1,
    started = 2,
    @"error" = 3,
    _,

    extern fn gst_audio_ring_buffer_state_get_type() usize;
    pub const getGObjectType = gst_audio_ring_buffer_state_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Enum value describing how DSD bits are grouped.
pub const DsdFormat = enum(c_int) {
    dsd_format_unknown = 0,
    dsd_format_u8 = 1,
    dsd_format_u16le = 2,
    dsd_format_u16be = 3,
    dsd_format_u32le = 4,
    dsd_format_u32be = 5,
    num_dsd_formats = 6,
    _,

    pub const dsd_format_u16 = DsdFormat.dsd_format_u16le;
    pub const dsd_format_u32 = DsdFormat.dsd_format_u32le;
    /// Convert the DSD format string `str` to its `gstaudio.DsdFormat`.
    extern fn gst_dsd_format_from_string(p_str: [*:0]const u8) gstaudio.DsdFormat;
    pub const fromString = gst_dsd_format_from_string;

    extern fn gst_dsd_format_get_width(p_format: gstaudio.DsdFormat) c_uint;
    pub const getWidth = gst_dsd_format_get_width;

    /// Returns a string containing a descriptive name for
    /// the `gstaudio.DsdFormat` if there is one, or NULL otherwise.
    extern fn gst_dsd_format_to_string(p_format: gstaudio.DsdFormat) [*:0]const u8;
    pub const toString = gst_dsd_format_to_string;

    extern fn gst_dsd_format_get_type() usize;
    pub const getGObjectType = gst_dsd_format_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Different representations of a stream volume. `gstaudio.streamVolumeConvertVolume`
/// allows to convert between the different representations.
///
/// Formulas to convert from a linear to a cubic or dB volume are
/// cbrt(val) and 20 * log10 (val).
pub const StreamVolumeFormat = enum(c_int) {
    linear = 0,
    cubic = 1,
    db = 2,
    _,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Flags passed to `gstaudio.audioChannelMixerNew`
pub const AudioChannelMixerFlags = packed struct(c_uint) {
    non_interleaved_in: bool = false,
    non_interleaved_out: bool = false,
    unpositioned_in: bool = false,
    unpositioned_out: bool = false,
    _padding4: bool = false,
    _padding5: bool = false,
    _padding6: bool = false,
    _padding7: bool = false,
    _padding8: bool = false,
    _padding9: bool = false,
    _padding10: bool = false,
    _padding11: bool = false,
    _padding12: bool = false,
    _padding13: bool = false,
    _padding14: bool = false,
    _padding15: bool = false,
    _padding16: bool = false,
    _padding17: bool = false,
    _padding18: bool = false,
    _padding19: bool = false,
    _padding20: bool = false,
    _padding21: bool = false,
    _padding22: bool = false,
    _padding23: bool = false,
    _padding24: bool = false,
    _padding25: bool = false,
    _padding26: bool = false,
    _padding27: bool = false,
    _padding28: bool = false,
    _padding29: bool = false,
    _padding30: bool = false,
    _padding31: bool = false,

    pub const flags_none: AudioChannelMixerFlags = @bitCast(@as(c_uint, 0));
    pub const flags_non_interleaved_in: AudioChannelMixerFlags = @bitCast(@as(c_uint, 1));
    pub const flags_non_interleaved_out: AudioChannelMixerFlags = @bitCast(@as(c_uint, 2));
    pub const flags_unpositioned_in: AudioChannelMixerFlags = @bitCast(@as(c_uint, 4));
    pub const flags_unpositioned_out: AudioChannelMixerFlags = @bitCast(@as(c_uint, 8));
    extern fn gst_audio_channel_mixer_flags_get_type() usize;
    pub const getGObjectType = gst_audio_channel_mixer_flags_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Extra flags passed to `gstaudio.AudioConverter.new` and `gstaudio.AudioConverter.samples`.
pub const AudioConverterFlags = packed struct(c_uint) {
    in_writable: bool = false,
    variable_rate: bool = false,
    _padding2: bool = false,
    _padding3: bool = false,
    _padding4: bool = false,
    _padding5: bool = false,
    _padding6: bool = false,
    _padding7: bool = false,
    _padding8: bool = false,
    _padding9: bool = false,
    _padding10: bool = false,
    _padding11: bool = false,
    _padding12: bool = false,
    _padding13: bool = false,
    _padding14: bool = false,
    _padding15: bool = false,
    _padding16: bool = false,
    _padding17: bool = false,
    _padding18: bool = false,
    _padding19: bool = false,
    _padding20: bool = false,
    _padding21: bool = false,
    _padding22: bool = false,
    _padding23: bool = false,
    _padding24: bool = false,
    _padding25: bool = false,
    _padding26: bool = false,
    _padding27: bool = false,
    _padding28: bool = false,
    _padding29: bool = false,
    _padding30: bool = false,
    _padding31: bool = false,

    pub const flags_none: AudioConverterFlags = @bitCast(@as(c_uint, 0));
    pub const flags_in_writable: AudioConverterFlags = @bitCast(@as(c_uint, 1));
    pub const flags_variable_rate: AudioConverterFlags = @bitCast(@as(c_uint, 2));
    extern fn gst_audio_converter_flags_get_type() usize;
    pub const getGObjectType = gst_audio_converter_flags_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Extra audio flags
pub const AudioFlags = packed struct(c_uint) {
    unpositioned: bool = false,
    _padding1: bool = false,
    _padding2: bool = false,
    _padding3: bool = false,
    _padding4: bool = false,
    _padding5: bool = false,
    _padding6: bool = false,
    _padding7: bool = false,
    _padding8: bool = false,
    _padding9: bool = false,
    _padding10: bool = false,
    _padding11: bool = false,
    _padding12: bool = false,
    _padding13: bool = false,
    _padding14: bool = false,
    _padding15: bool = false,
    _padding16: bool = false,
    _padding17: bool = false,
    _padding18: bool = false,
    _padding19: bool = false,
    _padding20: bool = false,
    _padding21: bool = false,
    _padding22: bool = false,
    _padding23: bool = false,
    _padding24: bool = false,
    _padding25: bool = false,
    _padding26: bool = false,
    _padding27: bool = false,
    _padding28: bool = false,
    _padding29: bool = false,
    _padding30: bool = false,
    _padding31: bool = false,

    pub const flags_none: AudioFlags = @bitCast(@as(c_uint, 0));
    pub const flags_unpositioned: AudioFlags = @bitCast(@as(c_uint, 1));
    extern fn gst_audio_flags_get_type() usize;
    pub const getGObjectType = gst_audio_flags_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// The different audio flags that a format info can have.
pub const AudioFormatFlags = packed struct(c_uint) {
    integer: bool = false,
    float: bool = false,
    signed: bool = false,
    _padding3: bool = false,
    complex: bool = false,
    unpack: bool = false,
    _padding6: bool = false,
    _padding7: bool = false,
    _padding8: bool = false,
    _padding9: bool = false,
    _padding10: bool = false,
    _padding11: bool = false,
    _padding12: bool = false,
    _padding13: bool = false,
    _padding14: bool = false,
    _padding15: bool = false,
    _padding16: bool = false,
    _padding17: bool = false,
    _padding18: bool = false,
    _padding19: bool = false,
    _padding20: bool = false,
    _padding21: bool = false,
    _padding22: bool = false,
    _padding23: bool = false,
    _padding24: bool = false,
    _padding25: bool = false,
    _padding26: bool = false,
    _padding27: bool = false,
    _padding28: bool = false,
    _padding29: bool = false,
    _padding30: bool = false,
    _padding31: bool = false,

    pub const flags_integer: AudioFormatFlags = @bitCast(@as(c_uint, 1));
    pub const flags_float: AudioFormatFlags = @bitCast(@as(c_uint, 2));
    pub const flags_signed: AudioFormatFlags = @bitCast(@as(c_uint, 4));
    pub const flags_complex: AudioFormatFlags = @bitCast(@as(c_uint, 16));
    pub const flags_unpack: AudioFormatFlags = @bitCast(@as(c_uint, 32));
    extern fn gst_audio_format_flags_get_type() usize;
    pub const getGObjectType = gst_audio_format_flags_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// The different flags that can be used when packing and unpacking.
pub const AudioPackFlags = packed struct(c_uint) {
    truncate_range: bool = false,
    _padding1: bool = false,
    _padding2: bool = false,
    _padding3: bool = false,
    _padding4: bool = false,
    _padding5: bool = false,
    _padding6: bool = false,
    _padding7: bool = false,
    _padding8: bool = false,
    _padding9: bool = false,
    _padding10: bool = false,
    _padding11: bool = false,
    _padding12: bool = false,
    _padding13: bool = false,
    _padding14: bool = false,
    _padding15: bool = false,
    _padding16: bool = false,
    _padding17: bool = false,
    _padding18: bool = false,
    _padding19: bool = false,
    _padding20: bool = false,
    _padding21: bool = false,
    _padding22: bool = false,
    _padding23: bool = false,
    _padding24: bool = false,
    _padding25: bool = false,
    _padding26: bool = false,
    _padding27: bool = false,
    _padding28: bool = false,
    _padding29: bool = false,
    _padding30: bool = false,
    _padding31: bool = false,

    pub const flags_none: AudioPackFlags = @bitCast(@as(c_uint, 0));
    pub const flags_truncate_range: AudioPackFlags = @bitCast(@as(c_uint, 1));
    extern fn gst_audio_pack_flags_get_type() usize;
    pub const getGObjectType = gst_audio_pack_flags_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Extra flags that can be passed to `gstaudio.audioQuantizeNew`
pub const AudioQuantizeFlags = packed struct(c_uint) {
    non_interleaved: bool = false,
    _padding1: bool = false,
    _padding2: bool = false,
    _padding3: bool = false,
    _padding4: bool = false,
    _padding5: bool = false,
    _padding6: bool = false,
    _padding7: bool = false,
    _padding8: bool = false,
    _padding9: bool = false,
    _padding10: bool = false,
    _padding11: bool = false,
    _padding12: bool = false,
    _padding13: bool = false,
    _padding14: bool = false,
    _padding15: bool = false,
    _padding16: bool = false,
    _padding17: bool = false,
    _padding18: bool = false,
    _padding19: bool = false,
    _padding20: bool = false,
    _padding21: bool = false,
    _padding22: bool = false,
    _padding23: bool = false,
    _padding24: bool = false,
    _padding25: bool = false,
    _padding26: bool = false,
    _padding27: bool = false,
    _padding28: bool = false,
    _padding29: bool = false,
    _padding30: bool = false,
    _padding31: bool = false,

    pub const flags_none: AudioQuantizeFlags = @bitCast(@as(c_uint, 0));
    pub const flags_non_interleaved: AudioQuantizeFlags = @bitCast(@as(c_uint, 1));
    extern fn gst_audio_quantize_flags_get_type() usize;
    pub const getGObjectType = gst_audio_quantize_flags_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Different resampler flags.
pub const AudioResamplerFlags = packed struct(c_uint) {
    non_interleaved_in: bool = false,
    non_interleaved_out: bool = false,
    variable_rate: bool = false,
    _padding3: bool = false,
    _padding4: bool = false,
    _padding5: bool = false,
    _padding6: bool = false,
    _padding7: bool = false,
    _padding8: bool = false,
    _padding9: bool = false,
    _padding10: bool = false,
    _padding11: bool = false,
    _padding12: bool = false,
    _padding13: bool = false,
    _padding14: bool = false,
    _padding15: bool = false,
    _padding16: bool = false,
    _padding17: bool = false,
    _padding18: bool = false,
    _padding19: bool = false,
    _padding20: bool = false,
    _padding21: bool = false,
    _padding22: bool = false,
    _padding23: bool = false,
    _padding24: bool = false,
    _padding25: bool = false,
    _padding26: bool = false,
    _padding27: bool = false,
    _padding28: bool = false,
    _padding29: bool = false,
    _padding30: bool = false,
    _padding31: bool = false,

    pub const flags_none: AudioResamplerFlags = @bitCast(@as(c_uint, 0));
    pub const flags_non_interleaved_in: AudioResamplerFlags = @bitCast(@as(c_uint, 1));
    pub const flags_non_interleaved_out: AudioResamplerFlags = @bitCast(@as(c_uint, 2));
    pub const flags_variable_rate: AudioResamplerFlags = @bitCast(@as(c_uint, 4));
    extern fn gst_audio_resampler_flags_get_type() usize;
    pub const getGObjectType = gst_audio_resampler_flags_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Get the fallback channel-mask for the given number of channels.
///
/// This function returns a reasonable fallback channel-mask and should be
/// called as a last resort when the specific channel map is unknown.
extern fn gst_audio_channel_get_fallback_mask(p_channels: c_int) u64;
pub const audioChannelGetFallbackMask = gst_audio_channel_get_fallback_mask;

/// Convert the `channels` present in `channel_mask` to a `position` array
/// (which should have at least `channels` entries ensured by caller).
/// If `channel_mask` is set to 0, it is considered as 'not present' for purpose
/// of conversion.
/// A partially valid `channel_mask` with less bits set than the number
/// of channels is considered valid.
extern fn gst_audio_channel_positions_from_mask(p_channels: c_int, p_channel_mask: u64, p_position: [*]gstaudio.AudioChannelPosition) c_int;
pub const audioChannelPositionsFromMask = gst_audio_channel_positions_from_mask;

/// Convert the `position` array of `channels` channels to a bitmask.
///
/// If `force_order` is `TRUE` it additionally checks if the channels are
/// in the order required by GStreamer.
extern fn gst_audio_channel_positions_to_mask(p_position: [*]const gstaudio.AudioChannelPosition, p_channels: c_int, p_force_order: c_int, p_channel_mask: *u64) c_int;
pub const audioChannelPositionsToMask = gst_audio_channel_positions_to_mask;

/// Converts `position` to a human-readable string representation for
/// debugging purposes.
extern fn gst_audio_channel_positions_to_string(p_position: [*]const gstaudio.AudioChannelPosition, p_channels: c_int) [*:0]u8;
pub const audioChannelPositionsToString = gst_audio_channel_positions_to_string;

/// Reorders the channel positions in `position` from any order to
/// the GStreamer channel order.
extern fn gst_audio_channel_positions_to_valid_order(p_position: [*]gstaudio.AudioChannelPosition, p_channels: c_int) c_int;
pub const audioChannelPositionsToValidOrder = gst_audio_channel_positions_to_valid_order;

/// Checks if `position` contains valid channel positions for
/// `channels` channels. If `force_order` is `TRUE` it additionally
/// checks if the channels are in the order required by GStreamer.
extern fn gst_audio_check_valid_channel_positions(p_position: [*]const gstaudio.AudioChannelPosition, p_channels: c_int, p_force_order: c_int) c_int;
pub const audioCheckValidChannelPositions = gst_audio_check_valid_channel_positions;

extern fn gst_audio_clipping_meta_api_get_type() usize;
pub const audioClippingMetaApiGetType = gst_audio_clipping_meta_api_get_type;

extern fn gst_audio_downmix_meta_api_get_type() usize;
pub const audioDownmixMetaApiGetType = gst_audio_downmix_meta_api_get_type;

/// Return all the raw audio formats supported by GStreamer.
extern fn gst_audio_formats_raw(p_len: *c_uint) [*]const gstaudio.AudioFormat;
pub const audioFormatsRaw = gst_audio_formats_raw;

/// Returns a reorder map for `from` to `to` that can be used in
/// custom channel reordering code, e.g. to convert from or to the
/// GStreamer channel order. `from` and `to` must contain the same
/// number of positions and the same positions, only in a
/// different order.
///
/// The resulting `reorder_map` can be used for reordering by assigning
/// channel i of the input to channel reorder_map[i] of the output.
extern fn gst_audio_get_channel_reorder_map(p_channels: c_int, p_from: [*]const gstaudio.AudioChannelPosition, p_to: [*]const gstaudio.AudioChannelPosition, p_reorder_map: [*]c_int) c_int;
pub const audioGetChannelReorderMap = gst_audio_get_channel_reorder_map;

/// Calculated the size of the buffer expected by `gstaudio.audioIec61937Payload` for
/// payloading type from `spec`.
extern fn gst_audio_iec61937_frame_size(p_spec: *const gstaudio.AudioRingBufferSpec) c_uint;
pub const audioIec61937FrameSize = gst_audio_iec61937_frame_size;

/// Payloads `src` in the form specified by IEC 61937 for the type from `spec` and
/// stores the result in `dst`. `src` must contain exactly one frame of data and
/// the frame is not checked for errors.
extern fn gst_audio_iec61937_payload(p_src: [*]const u8, p_src_n: c_uint, p_dst: [*]u8, p_dst_n: c_uint, p_spec: *const gstaudio.AudioRingBufferSpec, p_endianness: c_int) c_int;
pub const audioIec61937Payload = gst_audio_iec61937_payload;

/// Return the `gobject.Type` associated with `gstaudio.AudioLevelMeta`.
extern fn gst_audio_level_meta_api_get_type() usize;
pub const audioLevelMetaApiGetType = gst_audio_level_meta_api_get_type;

/// Return a generic raw audio caps for formats defined in `formats`.
/// If `formats` is `NULL` returns a caps for all the supported raw audio formats,
/// see `gstaudio.audioFormatsRaw`.
extern fn gst_audio_make_raw_caps(p_formats: ?[*]const gstaudio.AudioFormat, p_len: c_uint, p_layout: gstaudio.AudioLayout) *gst.Caps;
pub const audioMakeRawCaps = gst_audio_make_raw_caps;

extern fn gst_audio_meta_api_get_type() usize;
pub const audioMetaApiGetType = gst_audio_meta_api_get_type;

/// Reorders `data` from the channel positions `from` to the channel
/// positions `to`. `from` and `to` must contain the same number of
/// positions and the same positions, only in a different order.
///
/// This function internally calls `gstaudio.audioGetChannelReorderMap` and
/// `gstaudio.audioReorderChannelsWithReorderMap`. It is more efficient to call
/// `gstaudio.audioGetChannelReorderMap` once to retrieve the reorder map and
/// then call `gstaudio.audioReorderChannelsWithReorderMap` with the same
/// reorder map until the channel positions change.
///
/// Note: this function assumes the audio data is in interleaved layout
extern fn gst_audio_reorder_channels(p_data: [*]u8, p_size: usize, p_format: gstaudio.AudioFormat, p_channels: c_int, p_from: [*]const gstaudio.AudioChannelPosition, p_to: [*]const gstaudio.AudioChannelPosition) c_int;
pub const audioReorderChannels = gst_audio_reorder_channels;

/// Reorders `data` with the given `reorder_map`.
///
/// The reorder map can be retrieved for example with
/// `gstaudio.audioGetChannelReorderMap`.
///
/// Note: this function assumes the audio data is in interleaved layout
extern fn gst_audio_reorder_channels_with_reorder_map(p_data: [*]u8, p_size: usize, p_bps: c_int, p_channels: c_int, p_reorder_map: [*]const c_int) void;
pub const audioReorderChannelsWithReorderMap = gst_audio_reorder_channels_with_reorder_map;

/// Attaches `gstaudio.AudioClippingMeta` metadata to `buffer` with the given parameters.
extern fn gst_buffer_add_audio_clipping_meta(p_buffer: *gst.Buffer, p_format: gst.Format, p_start: u64, p_end: u64) *gstaudio.AudioClippingMeta;
pub const bufferAddAudioClippingMeta = gst_buffer_add_audio_clipping_meta;

/// Attaches `gstaudio.AudioDownmixMeta` metadata to `buffer` with the given parameters.
///
/// `matrix` is an two-dimensional array of `to_channels` times `from_channels`
/// coefficients, i.e. the i-th output channels is constructed by multiplicating
/// the input channels with the coefficients in `matrix`[i] and taking the sum
/// of the results.
extern fn gst_buffer_add_audio_downmix_meta(p_buffer: *gst.Buffer, p_from_position: [*]const gstaudio.AudioChannelPosition, p_from_channels: c_int, p_to_position: [*]const gstaudio.AudioChannelPosition, p_to_channels: c_int, p_matrix: **const f32) *gstaudio.AudioDownmixMeta;
pub const bufferAddAudioDownmixMeta = gst_buffer_add_audio_downmix_meta;

/// Attaches audio level information to `buffer`. (RFC 6464)
extern fn gst_buffer_add_audio_level_meta(p_buffer: *gst.Buffer, p_level: u8, p_voice_activity: c_int) ?*gstaudio.AudioLevelMeta;
pub const bufferAddAudioLevelMeta = gst_buffer_add_audio_level_meta;

/// Allocates and attaches a `gstaudio.AudioMeta` on `buffer`, which must be writable
/// for that purpose. The fields of the `gstaudio.AudioMeta` are directly populated
/// from the arguments of this function.
///
/// When `info`->layout is `GST_AUDIO_LAYOUT_NON_INTERLEAVED` and `offsets` is
/// `NULL`, the offsets are calculated with a formula that assumes the planes are
/// tightly packed and in sequence:
/// offsets[channel] = channel * `samples` * sample_stride
///
/// It is not allowed for channels to overlap in memory,
/// i.e. for each i in [0, channels), the range
/// [`offsets`[i], `offsets`[i] + `samples` * sample_stride) must not overlap
/// with any other such range. This function will assert if the parameters
/// specified cause this restriction to be violated.
///
/// It is, obviously, also not allowed to specify parameters that would cause
/// out-of-bounds memory access on `buffer`. This is also checked, which means
/// that you must add enough memory on the `buffer` before adding this meta.
extern fn gst_buffer_add_audio_meta(p_buffer: *gst.Buffer, p_info: *const gstaudio.AudioInfo, p_samples: usize, p_offsets: ?*usize) *gstaudio.AudioMeta;
pub const bufferAddAudioMeta = gst_buffer_add_audio_meta;

/// Allocates and attaches a `gstaudio.DsdPlaneOffsetMeta` on `buffer`, which must be
/// writable for that purpose. The fields of the `gstaudio.DsdPlaneOffsetMeta` are
/// directly populated from the arguments of this function.
///
/// If `offsets` is NULL, then the meta's offsets field is left uninitialized.
/// This is useful if for example offset values are to be calculated in the
/// meta's offsets field in-place. Similarly, `num_bytes_per_channel` can be
/// set to 0, but only if `offsets` is NULL. This is useful if the number of
/// bytes per channel is known only later.
///
/// It is not allowed for channels to overlap in memory,
/// i.e. for each i in [0, channels), the range
/// [`offsets`[i], `offsets`[i] + `num_bytes_per_channel`) must not overlap
/// with any other such range. This function will assert if the parameters
/// specified cause this restriction to be violated.
///
/// It is, obviously, also not allowed to specify parameters that would cause
/// out-of-bounds memory access on `buffer`. This is also checked, which means
/// that you must add enough memory on the `buffer` before adding this meta.
///
/// This meta is only needed for non-interleaved (= planar) DSD data.
extern fn gst_buffer_add_dsd_plane_offset_meta(p_buffer: *gst.Buffer, p_num_channels: c_int, p_num_bytes_per_channel: usize, p_offsets: ?*usize) *gstaudio.DsdPlaneOffsetMeta;
pub const bufferAddDsdPlaneOffsetMeta = gst_buffer_add_dsd_plane_offset_meta;

/// Find the `gstaudio.AudioDownmixMeta` on `buffer` for the given destination
/// channel positions.
extern fn gst_buffer_get_audio_downmix_meta_for_channels(p_buffer: *gst.Buffer, p_to_position: [*]const gstaudio.AudioChannelPosition, p_to_channels: c_int) *gstaudio.AudioDownmixMeta;
pub const bufferGetAudioDownmixMetaForChannels = gst_buffer_get_audio_downmix_meta_for_channels;

/// Find the `gstaudio.AudioLevelMeta` on `buffer`.
extern fn gst_buffer_get_audio_level_meta(p_buffer: *gst.Buffer) ?*gstaudio.AudioLevelMeta;
pub const bufferGetAudioLevelMeta = gst_buffer_get_audio_level_meta;

/// Converts DSD data from one layout and grouping format to another.
/// `num_bytes` must be an integer multiple of the width of both input
/// and output format. For example, if the input format is GST_DSD_FORMAT_U32LE,
/// and the output format is GST_DSD_FORMAT_U16BE, then `num_bytes` must
/// be an integer multiple of both 4 (U32LE width) and 2 (U16BE width).
///
/// `reverse_byte_bits` is necessary if the bit order within the DSD bytes
/// needs to be reversed. This is rarely necessary, and is not to be
/// confused with the endianness of formats (which determines the ordering
/// of *bytes*).
///
/// `input_plane_offsets` must not be NULL if `input_layout` is set to
/// `GST_AUDIO_LAYOUT_NON_INTERLEAVED`. The same applies to `output_plane_offsets`.
/// These plane offsets define the starting offset of the planes (there is
/// exactly one plane per channel) within `input_data` and `output_data`
/// respectively. If GST_AUDIO_LAYOUT_INTERLEAVED is used, the plane offsets
/// are ignored.
extern fn gst_dsd_convert(p_input_data: *const u8, p_output_data: *u8, p_input_format: gstaudio.DsdFormat, p_output_format: gstaudio.DsdFormat, p_input_layout: gstaudio.AudioLayout, p_output_layout: gstaudio.AudioLayout, p_input_plane_offsets: *const usize, p_output_plane_offsets: *const usize, p_num_dsd_bytes: usize, p_num_channels: c_int, p_reverse_byte_bits: c_int) void;
pub const dsdConvert = gst_dsd_convert;

extern fn gst_dsd_plane_offset_meta_api_get_type() usize;
pub const dsdPlaneOffsetMetaApiGetType = gst_dsd_plane_offset_meta_api_get_type;

/// This function is set with `gstaudio.AudioBaseSink.setCustomSlavingCallback`
/// and is called during playback. It receives the current time of external and
/// internal clocks, which the callback can then use to apply any custom
/// slaving/synchronization schemes.
///
/// The external clock is the sink's element clock, the internal one is the
/// internal audio clock. The internal audio clock's calibration is applied to
/// the timestamps before they are passed to the callback. The difference between
/// etime and itime is the skew; how much internal and external clock lie apart
/// from each other. A skew of 0 means both clocks are perfectly in sync.
/// itime > etime means the external clock is going slower, while itime < etime
/// means it is going faster than the internal clock. etime and itime are always
/// valid timestamps, except for when a discontinuity happens.
///
/// requested_skew is an output value the callback can write to. It informs the
/// sink of whether or not it should move the playout pointer, and if so, by how
/// much. This pointer is only NULL if a discontinuity occurs; otherwise, it is
/// safe to write to *requested_skew. The default skew is 0.
///
/// The sink may experience discontinuities. If one happens, discont is TRUE,
/// itime, etime are set to GST_CLOCK_TIME_NONE, and requested_skew is NULL.
/// This makes it possible to reset custom clock slaving algorithms when a
/// discontinuity happens.
pub const AudioBaseSinkCustomSlavingCallback = *const fn (p_sink: *gstaudio.AudioBaseSink, p_etime: gst.ClockTime, p_itime: gst.ClockTime, p_requested_skew: *gst.ClockTimeDiff, p_discont_reason: gstaudio.AudioBaseSinkDiscontReason, p_user_data: ?*anyopaque) callconv(.c) void;

/// This function will be called whenever the current clock time needs to be
/// calculated. If this function returns `GST_CLOCK_TIME_NONE`, the last reported
/// time will be returned by the clock.
pub const AudioClockGetTimeFunc = *const fn (p_clock: *gst.Clock, p_user_data: ?*anyopaque) callconv(.c) gst.ClockTime;

/// Packs `length` samples from `src` to the data array in format `info`.
/// The samples from source have each channel interleaved
/// and will be packed into `data`.
pub const AudioFormatPack = *const fn (p_info: *const gstaudio.AudioFormatInfo, p_flags: gstaudio.AudioPackFlags, p_src: [*]const u8, p_data: [*]u8, p_length: c_int) callconv(.c) void;

/// Unpacks `length` samples from the given data of format `info`.
/// The samples will be unpacked into `dest` which each channel
/// interleaved. `dest` should at least be big enough to hold `length` *
/// channels * size(unpack_format) bytes.
pub const AudioFormatUnpack = *const fn (p_info: *const gstaudio.AudioFormatInfo, p_flags: gstaudio.AudioPackFlags, p_dest: [*]u8, p_data: [*]const u8, p_length: c_int) callconv(.c) void;

/// This function is set with `gstaudio.AudioRingBuffer.setCallback` and is
/// called to fill the memory at `data` with `len` bytes of samples.
pub const AudioRingBufferCallback = *const fn (p_rbuf: *gstaudio.AudioRingBuffer, p_data: [*]u8, p_len: c_uint, p_user_data: ?*anyopaque) callconv(.c) void;

/// Maximum range of allowed channels, for use in template caps strings.
pub const AUDIO_CHANNELS_RANGE = "(int) [ 1, max ]";
/// `gstaudio.AudioDitherMethod`, The dither method to use when
/// changing bit depth.
/// Default is `GST_AUDIO_DITHER_NONE`.
pub const AUDIO_CONVERTER_OPT_DITHER_METHOD = "GstAudioConverter.dither-method";
/// Threshold for the output bit depth at/below which to apply dithering.
///
/// Default is 20 bit.
pub const AUDIO_CONVERTER_OPT_DITHER_THRESHOLD = "GstAudioConverter.dither-threshold";
/// `GST_TYPE_LIST`, The channel mapping matrix.
///
/// The matrix coefficients must be between -1 and 1: the number of rows is equal
/// to the number of output channels and the number of columns is equal to the
/// number of input channels.
///
/// ## Example matrix generation code
/// To generate the matrix using code:
///
/// ```
/// GValue v = G_VALUE_INIT;
/// GValue v2 = G_VALUE_INIT;
/// GValue v3 = G_VALUE_INIT;
///
/// g_value_init (&v2, GST_TYPE_ARRAY);
/// g_value_init (&v3, G_TYPE_DOUBLE);
/// g_value_set_double (&v3, 1);
/// gst_value_array_append_value (&v2, &v3);
/// g_value_unset (&v3);
/// [ Repeat for as many double as your input channels - unset and reinit v3 ]
/// g_value_init (&v, GST_TYPE_ARRAY);
/// gst_value_array_append_value (&v, &v2);
/// g_value_unset (&v2);
/// [ Repeat for as many v2's as your output channels - unset and reinit v2]
/// g_object_set_property (G_OBJECT (audiomixmatrix), "matrix", &v);
/// g_value_unset (&v);
/// ```
pub const AUDIO_CONVERTER_OPT_MIX_MATRIX = "GstAudioConverter.mix-matrix";
/// `gstaudio.AudioNoiseShapingMethod`, The noise shaping method to use
/// to mask noise from quantization errors.
/// Default is `GST_AUDIO_NOISE_SHAPING_NONE`.
pub const AUDIO_CONVERTER_OPT_NOISE_SHAPING_METHOD = "GstAudioConverter.noise-shaping-method";
/// `G_TYPE_UINT`, The quantization amount. Components will be
/// quantized to multiples of this value.
/// Default is 1
pub const AUDIO_CONVERTER_OPT_QUANTIZATION = "GstAudioConverter.quantization";
/// `gstaudio.AudioResamplerMethod`, The resampler method to use when
/// changing sample rates.
/// Default is `GST_AUDIO_RESAMPLER_METHOD_BLACKMAN_NUTTALL`.
pub const AUDIO_CONVERTER_OPT_RESAMPLER_METHOD = "GstAudioConverter.resampler-method";
/// Default maximum number of errors tolerated before signaling error.
pub const AUDIO_DECODER_MAX_ERRORS = -1;
/// The name of the templates for the sink pad.
pub const AUDIO_DECODER_SINK_NAME = "sink";
/// The name of the templates for the source pad.
pub const AUDIO_DECODER_SRC_NAME = "src";
/// Standard number of channels used in consumer audio.
pub const AUDIO_DEF_CHANNELS = 2;
/// Standard format used in consumer audio.
pub const AUDIO_DEF_FORMAT = "S16LE";
/// Standard sampling rate used in consumer audio.
pub const AUDIO_DEF_RATE = 44100;
/// the name of the templates for the sink pad
pub const AUDIO_ENCODER_SINK_NAME = "sink";
/// the name of the templates for the source pad
pub const AUDIO_ENCODER_SRC_NAME = "src";
/// List of all audio formats, for use in template caps strings.
///
/// Formats are sorted by decreasing "quality", using these criteria by priority:
///   - depth
///   - width
///   - Float > Signed > Unsigned
///   - native endianness preferred
pub const AUDIO_FORMATS_ALL = "{ F64BE, F64LE, F32BE, F32LE, S32BE, S32LE, U32BE, U32LE, S24_32BE, S24_32LE, U24_32BE, U24_32LE, S24BE, S24LE, U24BE, U24LE, S20BE, S20LE, U20BE, U20LE, S18BE, S18LE, U18BE, U18LE, S16BE, S16LE, U16BE, U16LE, S8, U8 }";
/// Number of audio formats in `gstaudio.AudioFormat`.
pub const AUDIO_FORMAT_LAST = 32;
/// Maximum range of allowed sample rates, for use in template caps strings.
pub const AUDIO_RATE_RANGE = "(int) [ 1, max ]";
/// G_TYPE_DOUBLE, B parameter of the cubic filter.
/// Values between 0.0 and 2.0 are accepted. 1.0 is the default.
///
/// Below are some values of popular filters:
///                    B       C
/// Hermite           0.0     0.0
/// Spline            1.0     0.0
/// Catmull-Rom       0.0     1/2
pub const AUDIO_RESAMPLER_OPT_CUBIC_B = "GstAudioResampler.cubic-b";
/// G_TYPE_DOUBLE, C parameter of the cubic filter.
/// Values between 0.0 and 2.0 are accepted. 0.0 is the default.
///
/// See `GST_AUDIO_RESAMPLER_OPT_CUBIC_B` for some more common values
pub const AUDIO_RESAMPLER_OPT_CUBIC_C = "GstAudioResampler.cubic-c";
/// G_TYPE_DOUBLE, Cutoff parameter for the filter. 0.940 is the default.
pub const AUDIO_RESAMPLER_OPT_CUTOFF = "GstAudioResampler.cutoff";
/// GST_TYPE_AUDIO_RESAMPLER_INTERPOLATION: how the filter coefficients should be
///    interpolated.
/// GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_CUBIC is default.
pub const AUDIO_RESAMPLER_OPT_FILTER_INTERPOLATION = "GstAudioResampler.filter-interpolation";
/// GST_TYPE_AUDIO_RESAMPLER_FILTER_MODE: how the filter tables should be
/// constructed.
/// GST_AUDIO_RESAMPLER_FILTER_MODE_AUTO is the default.
pub const AUDIO_RESAMPLER_OPT_FILTER_MODE = "GstAudioResampler.filter-mode";
/// G_TYPE_UINT: the amount of memory to use for full filter tables before
/// switching to interpolated filter tables.
/// 1048576 is the default.
pub const AUDIO_RESAMPLER_OPT_FILTER_MODE_THRESHOLD = "GstAudioResampler.filter-mode-threshold";
/// G_TYPE_UINT, oversampling to use when interpolating filters
/// 8 is the default.
pub const AUDIO_RESAMPLER_OPT_FILTER_OVERSAMPLE = "GstAudioResampler.filter-oversample";
/// G_TYPE_DOUBLE: The maximum allowed phase error when switching sample
/// rates.
/// 0.1 is the default.
pub const AUDIO_RESAMPLER_OPT_MAX_PHASE_ERROR = "GstAudioResampler.max-phase-error";
/// G_TYPE_INT: the number of taps to use for the filter.
/// 0 is the default and selects the taps automatically.
pub const AUDIO_RESAMPLER_OPT_N_TAPS = "GstAudioResampler.n-taps";
/// G_TYPE_DOUBLE, stopband attenuation in decibels. The attenuation
/// after the stopband for the kaiser window. 85 dB is the default.
pub const AUDIO_RESAMPLER_OPT_STOP_ATTENUATION = "GstAudioResampler.stop-attenutation";
/// G_TYPE_DOUBLE, transition bandwidth. The width of the
/// transition band for the kaiser window. 0.087 is the default.
pub const AUDIO_RESAMPLER_OPT_TRANSITION_BANDWIDTH = "GstAudioResampler.transition-bandwidth";
pub const AUDIO_RESAMPLER_QUALITY_DEFAULT = 4;
pub const AUDIO_RESAMPLER_QUALITY_MAX = 10;
pub const AUDIO_RESAMPLER_QUALITY_MIN = 0;
/// List of all DSD formats, for use in template caps strings.
///
/// Big endian formats are preferred, since little-endian ones flip around
/// the DSD bytes, and most DSD hardware uses big endian formats.
pub const DSD_FORMATS_ALL = "{ DSDU32BE, DSDU16BE, DSDU8, DSDU32LE, DSDU16LE }";
/// The GStreamer media type for DSD.
pub const DSD_MEDIA_TYPE = "audio/x-dsd";
/// Silence pattern for DSD data.
///
/// In DSD, a nullbyte does not correspond to silence. To fill memory regions
/// with "DSD silence", these regions must be filled with byte 0x69 instead
/// (this is the DSD silence pattern). This constant provides that pattern
/// in a more readable fashion.
pub const DSD_SILENCE_PATTERN_BYTE = 105;
/// This metadata stays relevant as long as channels are unchanged.
pub const META_TAG_AUDIO_CHANNELS_STR = "channels";
/// This metadata stays relevant as long as sample rate is unchanged.
pub const META_TAG_AUDIO_RATE_STR = "rate";
/// This metadata is relevant for audio streams.
pub const META_TAG_AUDIO_STR = "audio";
/// This metadata stays relevant as long as the DSD plane offsets are unchanged.
pub const META_TAG_DSD_PLANE_OFFSETS_STR = "dsdplaneoffsets";

test {
    @setEvalBranchQuota(100_000);
    std.testing.refAllDecls(@This());
    std.testing.refAllDecls(ext);
}
