pub const ext = @import("ext.zig");
const gsttag = @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");
/// Provides a base class for demuxing tags at the beginning or end of a
/// stream and handles things like typefinding, querying, seeking, and
/// different modes of operation (chain-based, pull_range-based, and providing
/// downstream elements with random access if upstream supports that). The tag
/// is stripped from the output, and all offsets are adjusted for the tag
/// sizes, so that to the downstream element the stream will appear as if
/// there was no tag at all. Also, once the tag has been parsed, GstTagDemux
/// will try to determine the media type of the resulting stream and add a
/// source pad with the appropriate caps in order to facilitate auto-plugging.
///
/// ## Deriving from GstTagDemux
///
/// Subclasses have to do four things:
///
///  * In their base init function, they must add a pad template for the sink
///    pad to the element class, describing the media type they can parse in
///    the caps of the pad template.
///  * In their class init function, they must override
///    GST_TAG_DEMUX_CLASS(demux_klass)->identify_tag with their own identify
///    function.
///  * In their class init function, they must override
///  GST_TAG_DEMUX_CLASS(demux_klass)->parse_tag with their own parse
///  function.
///  * In their class init function, they must also set
///    GST_TAG_DEMUX_CLASS(demux_klass)->min_start_size and/or
///  GST_TAG_DEMUX_CLASS(demux_klass)->min_end_size to the minimum size required
///  for the identify function to decide whether the stream has a supported tag
///  or not. A class parsing ID3v1 tags, for example, would set min_end_size to
///  128 bytes.
pub const TagDemux = extern struct {
    pub const Parent = gst.Element;
    pub const Implements = [_]type{};
    pub const Class = gsttag.TagDemuxClass;
    /// parent element
    f_element: gst.Element,
    f_priv: ?*gsttag.TagDemuxPrivate,
    f_reserved: [4]*anyopaque,

    pub const virtual_methods = struct {
        /// identify tag and determine the size required to parse the
        /// tag. Buffer may be larger than the specified minimum size.
        /// Subclassed MUST override this vfunc in their class_init function.
        pub const identify_tag = struct {
            pub fn call(p_class: anytype, p_demux: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_buffer: *gst.Buffer, p_start_tag: c_int, p_tag_size: *c_uint) c_int {
                return gobject.ext.as(TagDemux.Class, p_class).f_identify_tag.?(gobject.ext.as(TagDemux, p_demux), p_buffer, p_start_tag, p_tag_size);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_demux: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_buffer: *gst.Buffer, p_start_tag: c_int, p_tag_size: *c_uint) callconv(.c) c_int) void {
                gobject.ext.as(TagDemux.Class, p_class).f_identify_tag = @ptrCast(p_implementation);
            }
        };

        /// merge start and end tags. Subclasses may want to override this
        /// vfunc to allow prioritising of start or end tag according to user
        /// preference.  Note that both start_tags and end_tags may be NULL. By default
        /// start tags are preferred over end tags.
        pub const merge_tags = struct {
            pub fn call(p_class: anytype, p_demux: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_start_tags: *const gst.TagList, p_end_tags: *const gst.TagList) *gst.TagList {
                return gobject.ext.as(TagDemux.Class, p_class).f_merge_tags.?(gobject.ext.as(TagDemux, p_demux), p_start_tags, p_end_tags);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_demux: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_start_tags: *const gst.TagList, p_end_tags: *const gst.TagList) callconv(.c) *gst.TagList) void {
                gobject.ext.as(TagDemux.Class, p_class).f_merge_tags = @ptrCast(p_implementation);
            }
        };

        /// parse the tag. Buffer will be exactly of the size determined by
        /// the identify_tag vfunc before. The parse_tag vfunc may change the size
        /// stored in *tag_size and return GST_TAG_DEMUX_RESULT_AGAIN to request a
        /// larger or smaller buffer. It is also permitted to adjust the tag_size to a
        /// smaller value and then return GST_TAG_DEMUX_RESULT_OK in one go.
        /// Subclassed MUST override the parse_tag vfunc in their class_init function.
        pub const parse_tag = struct {
            pub fn call(p_class: anytype, p_demux: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_buffer: *gst.Buffer, p_start_tag: c_int, p_tag_size: *c_uint, p_tags: **gst.TagList) gsttag.TagDemuxResult {
                return gobject.ext.as(TagDemux.Class, p_class).f_parse_tag.?(gobject.ext.as(TagDemux, p_demux), p_buffer, p_start_tag, p_tag_size, p_tags);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_demux: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_buffer: *gst.Buffer, p_start_tag: c_int, p_tag_size: *c_uint, p_tags: **gst.TagList) callconv(.c) gsttag.TagDemuxResult) void {
                gobject.ext.as(TagDemux.Class, p_class).f_parse_tag = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {};

    pub const signals = struct {};

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

    extern fn g_object_ref(p_self: *gsttag.TagDemux) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gsttag.TagDemux) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *TagDemux, 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 adding tags at the beginning or end of a
/// stream.
///
/// ## Deriving from GstTagMux
///
/// Subclasses have to do the following things:
///
///  * In their base init function, they must add pad templates for the sink
///    pad and the source pad to the element class, describing the media type
///    they accept and output in the caps of the pad template.
///  * In their class init function, they must override the
///    GST_TAG_MUX_CLASS(mux_klass)->render_start_tag and/or
///    GST_TAG_MUX_CLASS(mux_klass)->render_end_tag vfuncs and set up a render
///    function.
pub const TagMux = extern struct {
    pub const Parent = gst.Element;
    pub const Implements = [_]type{gst.TagSetter};
    pub const Class = gsttag.TagMuxClass;
    /// parent element
    f_element: gst.Element,
    f_priv: ?*gsttag.TagMuxPrivate,
    f__gst_reserved: [4]*anyopaque,

    pub const virtual_methods = struct {
        /// create a tag buffer to add to the end of the
        ///     input stream given a tag list, or NULL
        pub const render_end_tag = struct {
            pub fn call(p_class: anytype, p_mux: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_tag_list: *const gst.TagList) *gst.Buffer {
                return gobject.ext.as(TagMux.Class, p_class).f_render_end_tag.?(gobject.ext.as(TagMux, p_mux), p_tag_list);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_mux: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_tag_list: *const gst.TagList) callconv(.c) *gst.Buffer) void {
                gobject.ext.as(TagMux.Class, p_class).f_render_end_tag = @ptrCast(p_implementation);
            }
        };

        /// create a tag buffer to add to the beginning of the
        ///     input stream given a tag list, or NULL
        pub const render_start_tag = struct {
            pub fn call(p_class: anytype, p_mux: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_tag_list: *const gst.TagList) *gst.Buffer {
                return gobject.ext.as(TagMux.Class, p_class).f_render_start_tag.?(gobject.ext.as(TagMux, p_mux), p_tag_list);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_mux: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_tag_list: *const gst.TagList) callconv(.c) *gst.Buffer) void {
                gobject.ext.as(TagMux.Class, p_class).f_render_start_tag = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {};

    pub const signals = struct {};

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

    extern fn g_object_ref(p_self: *gsttag.TagMux) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gsttag.TagMux) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *TagMux, 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 are able to do XMP serialization. Examples for
/// such elements are `jifmux` and `qtmux`.
///
/// Applications can use this interface to configure which XMP schemas should be used when serializing
/// tags into XMP. Schemas are represented by their names, a full list of the supported schemas can be
/// obtained from `gsttag.tagXmpListSchemas`. By default, all schemas are used.
pub const TagXmpWriter = opaque {
    pub const Prerequisites = [_]type{gst.Element};
    pub const Iface = gsttag.TagXmpWriterInterface;
    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    /// Adds all available XMP schemas to the configuration. Meaning that
    /// all will be used.
    extern fn gst_tag_xmp_writer_add_all_schemas(p_config: *TagXmpWriter) void;
    pub const addAllSchemas = gst_tag_xmp_writer_add_all_schemas;

    /// Adds `schema` to the list schemas
    extern fn gst_tag_xmp_writer_add_schema(p_config: *TagXmpWriter, p_schema: [*:0]const u8) void;
    pub const addSchema = gst_tag_xmp_writer_add_schema;

    /// Checks if `schema` is going to be used
    extern fn gst_tag_xmp_writer_has_schema(p_config: *TagXmpWriter, p_schema: [*:0]const u8) c_int;
    pub const hasSchema = gst_tag_xmp_writer_has_schema;

    /// Removes all schemas from the list of schemas to use. Meaning that no
    /// XMP will be generated.
    extern fn gst_tag_xmp_writer_remove_all_schemas(p_config: *TagXmpWriter) void;
    pub const removeAllSchemas = gst_tag_xmp_writer_remove_all_schemas;

    /// Removes a schema from the list of schemas to use. Nothing is done if
    /// the schema wasn't in the list
    extern fn gst_tag_xmp_writer_remove_schema(p_config: *TagXmpWriter, p_schema: [*:0]const u8) void;
    pub const removeSchema = gst_tag_xmp_writer_remove_schema;

    extern fn gst_tag_xmp_writer_tag_list_to_xmp_buffer(p_config: *TagXmpWriter, p_taglist: *const gst.TagList, p_read_only: c_int) *gst.Buffer;
    pub const tagListToXmpBuffer = gst_tag_xmp_writer_tag_list_to_xmp_buffer;

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

    extern fn g_object_ref(p_self: *gsttag.TagXmpWriter) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gsttag.TagXmpWriter) void;
    pub const unref = g_object_unref;

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

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

/// The `gsttag.TagDemuxClass` structure.  See documentation at beginning of section
/// for details about what subclasses need to override and do.
pub const TagDemuxClass = extern struct {
    pub const Instance = gsttag.TagDemux;

    /// the parent class.
    f_parent_class: gst.ElementClass,
    /// minimum size required to identify a tag at the start and
    /// determine its total size. Set to 0 if not interested in start tags.
    /// Subclasses should set this in their class_init function.
    f_min_start_size: c_uint,
    /// minimum size required to identify a tag at the end and
    /// determine its total size. Set to 0 if not interested in end tags.
    /// Subclasses should set this in their class_init function.
    f_min_end_size: c_uint,
    /// identify tag and determine the size required to parse the
    /// tag. Buffer may be larger than the specified minimum size.
    /// Subclassed MUST override this vfunc in their class_init function.
    f_identify_tag: ?*const fn (p_demux: *gsttag.TagDemux, p_buffer: *gst.Buffer, p_start_tag: c_int, p_tag_size: *c_uint) callconv(.c) c_int,
    /// parse the tag. Buffer will be exactly of the size determined by
    /// the identify_tag vfunc before. The parse_tag vfunc may change the size
    /// stored in *tag_size and return GST_TAG_DEMUX_RESULT_AGAIN to request a
    /// larger or smaller buffer. It is also permitted to adjust the tag_size to a
    /// smaller value and then return GST_TAG_DEMUX_RESULT_OK in one go.
    /// Subclassed MUST override the parse_tag vfunc in their class_init function.
    f_parse_tag: ?*const fn (p_demux: *gsttag.TagDemux, p_buffer: *gst.Buffer, p_start_tag: c_int, p_tag_size: *c_uint, p_tags: **gst.TagList) callconv(.c) gsttag.TagDemuxResult,
    /// merge start and end tags. Subclasses may want to override this
    /// vfunc to allow prioritising of start or end tag according to user
    /// preference.  Note that both start_tags and end_tags may be NULL. By default
    /// start tags are preferred over end tags.
    f_merge_tags: ?*const fn (p_demux: *gsttag.TagDemux, p_start_tags: *const gst.TagList, p_end_tags: *const gst.TagList) callconv(.c) *gst.TagList,
    f_reserved: [4]*anyopaque,

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

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

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

/// The `gsttag.TagMuxClass` structure. Subclasses need to override at least one
/// of the two render vfuncs.
pub const TagMuxClass = extern struct {
    pub const Instance = gsttag.TagMux;

    /// the parent class.
    f_parent_class: gst.ElementClass,
    /// create a tag buffer to add to the beginning of the
    ///     input stream given a tag list, or NULL
    f_render_start_tag: ?*const fn (p_mux: *gsttag.TagMux, p_tag_list: *const gst.TagList) callconv(.c) *gst.Buffer,
    /// create a tag buffer to add to the end of the
    ///     input stream given a tag list, or NULL
    f_render_end_tag: ?*const fn (p_mux: *gsttag.TagMux, p_tag_list: *const gst.TagList) callconv(.c) *gst.Buffer,
    f__gst_reserved: [4]*anyopaque,

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

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

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

pub const TagXmpWriterInterface = extern struct {
    pub const Instance = gsttag.TagXmpWriter;

    f_parent: gobject.TypeInterface,

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

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

/// Result values from the parse_tag virtual function.
pub const TagDemuxResult = enum(c_int) {
    broken_tag = 0,
    again = 1,
    ok = 2,
    _,

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

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

/// Type of image contained in an image tag (specified as "image-type" field in
/// the info structure in the image's `gst.Sample`)
pub const TagImageType = enum(c_int) {
    none = -1,
    undefined = 0,
    front_cover = 1,
    back_cover = 2,
    leaflet_page = 3,
    medium = 4,
    lead_artist = 5,
    artist = 6,
    conductor = 7,
    band_orchestra = 8,
    composer = 9,
    lyricist = 10,
    recording_location = 11,
    during_recording = 12,
    during_performance = 13,
    video_capture = 14,
    fish = 15,
    illustration = 16,
    band_artist_logo = 17,
    publisher_studio_logo = 18,
    _,

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

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

/// See http://creativecommons.org/ns for more information.
pub const TagLicenseFlags = packed struct(c_uint) {
    permits_reproduction: bool = false,
    permits_distribution: bool = false,
    permits_derivative_works: bool = false,
    permits_sharing: bool = false,
    _padding4: bool = false,
    _padding5: bool = false,
    _padding6: bool = false,
    _padding7: bool = false,
    requires_notice: bool = false,
    requires_attribution: bool = false,
    requires_share_alike: bool = false,
    requires_source_code: bool = false,
    requires_copyleft: bool = false,
    requires_lesser_copyleft: bool = false,
    _padding14: bool = false,
    _padding15: bool = false,
    prohibits_commercial_use: bool = false,
    prohibits_high_income_nation_use: bool = false,
    _padding18: bool = false,
    _padding19: bool = false,
    _padding20: bool = false,
    _padding21: bool = false,
    _padding22: bool = false,
    _padding23: bool = false,
    creative_commons_license: bool = false,
    free_software_foundation_license: bool = false,
    _padding26: bool = false,
    _padding27: bool = false,
    _padding28: bool = false,
    _padding29: bool = false,
    _padding30: bool = false,
    _padding31: bool = false,

    pub const flags_permits_reproduction: TagLicenseFlags = @bitCast(@as(c_uint, 1));
    pub const flags_permits_distribution: TagLicenseFlags = @bitCast(@as(c_uint, 2));
    pub const flags_permits_derivative_works: TagLicenseFlags = @bitCast(@as(c_uint, 4));
    pub const flags_permits_sharing: TagLicenseFlags = @bitCast(@as(c_uint, 8));
    pub const flags_requires_notice: TagLicenseFlags = @bitCast(@as(c_uint, 256));
    pub const flags_requires_attribution: TagLicenseFlags = @bitCast(@as(c_uint, 512));
    pub const flags_requires_share_alike: TagLicenseFlags = @bitCast(@as(c_uint, 1024));
    pub const flags_requires_source_code: TagLicenseFlags = @bitCast(@as(c_uint, 2048));
    pub const flags_requires_copyleft: TagLicenseFlags = @bitCast(@as(c_uint, 4096));
    pub const flags_requires_lesser_copyleft: TagLicenseFlags = @bitCast(@as(c_uint, 8192));
    pub const flags_prohibits_commercial_use: TagLicenseFlags = @bitCast(@as(c_uint, 65536));
    pub const flags_prohibits_high_income_nation_use: TagLicenseFlags = @bitCast(@as(c_uint, 131072));
    pub const flags_creative_commons_license: TagLicenseFlags = @bitCast(@as(c_uint, 16777216));
    pub const flags_free_software_foundation_license: TagLicenseFlags = @bitCast(@as(c_uint, 33554432));
    extern fn gst_tag_license_flags_get_type() usize;
    pub const getGObjectType = gst_tag_license_flags_get_type;

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

/// Check if a given string contains a known ISO 639 language code.
///
/// This is useful in situations where it's not clear whether a given
/// string is a language code (which should be put into a `GST_TAG_LANGUAGE_CODE`
/// tag) or a free-form language name descriptor (which should be put into a
/// `GST_TAG_LANGUAGE_NAME` tag instead).
extern fn gst_tag_check_language_code(p_lang_code: [*:0]const u8) c_int;
pub const tagCheckLanguageCode = gst_tag_check_language_code;

/// Convenience function to read a string with unknown character encoding. If
/// the string is already in UTF-8 encoding, it will be returned right away.
/// If not it tries to detect byte-order-mark for UTF-16/32 cases and use that.
/// Otherwise, the environment will be searched for a number of environment
/// variables (whose names are specified in the NULL-terminated string array
/// `env_vars`) containing a list of character encodings to try/use. If none
/// are specified, the current locale will be tried. If that also doesn't work,
/// WINDOWS-1252/ISO-8859-1 is assumed (which will almost always succeed).
extern fn gst_tag_freeform_string_to_utf8(p_data: [*]const u8, p_size: c_int, p_env_vars: [*][*:0]const u8) ?[*:0]u8;
pub const tagFreeformStringToUtf8 = gst_tag_freeform_string_to_utf8;

/// Looks up the GStreamer tag for a ID3v2 tag.
extern fn gst_tag_from_id3_tag(p_id3_tag: [*:0]const u8) ?[*:0]const u8;
pub const tagFromId3Tag = gst_tag_from_id3_tag;

/// Looks up the GStreamer tag for an ID3v2 user tag (e.g. description in
/// TXXX frame or owner in UFID frame).
extern fn gst_tag_from_id3_user_tag(p_type: [*:0]const u8, p_id3_user_tag: [*:0]const u8) ?[*:0]const u8;
pub const tagFromId3UserTag = gst_tag_from_id3_user_tag;

/// Looks up the GStreamer tag for a vorbiscomment tag.
extern fn gst_tag_from_vorbis_tag(p_vorbis_tag: [*:0]const u8) ?[*:0]const u8;
pub const tagFromVorbisTag = gst_tag_from_vorbis_tag;

/// Determines size of an ID3v2 tag on buffer containing at least ID3v2 header,
/// i.e. at least `GST_TAG_ID3V2_HEADER_SIZE` (10) bytes;
extern fn gst_tag_get_id3v2_tag_size(p_buffer: *gst.Buffer) c_uint;
pub const tagGetId3v2TagSize = gst_tag_get_id3v2_tag_size;

/// Returns two-letter ISO-639-1 language code given a three-letter ISO-639-2
/// language code or two-letter ISO-639-1 language code (both are accepted for
/// convenience).
///
/// Language codes are case-sensitive and expected to be lower case.
extern fn gst_tag_get_language_code_iso_639_1(p_lang_code: [*:0]const u8) ?[*:0]const u8;
pub const tagGetLanguageCodeIso6391 = gst_tag_get_language_code_iso_639_1;

/// Returns three-letter ISO-639-2 "bibliographic" language code given a
/// two-letter ISO-639-1 language code or a three-letter ISO-639-2 language
/// code (both are accepted for convenience).
///
/// The "bibliographic" code is derived from the English name of the language
/// (e.g. "ger" for German instead of "de" or "deu"). In most scenarios, the
/// "terminological" codes are preferred.
///
/// Language codes are case-sensitive and expected to be lower case.
extern fn gst_tag_get_language_code_iso_639_2B(p_lang_code: [*:0]const u8) ?[*:0]const u8;
pub const tagGetLanguageCodeIso6392B = gst_tag_get_language_code_iso_639_2B;

/// Returns three-letter ISO-639-2 "terminological" language code given a
/// two-letter ISO-639-1 language code or a three-letter ISO-639-2 language
/// code (both are accepted for convenience).
///
/// The "terminological" code is derived from the local name of the language
/// (e.g. "deu" for German instead of "ger"). In most scenarios, the
/// "terminological" codes are preferred over the "bibliographic" ones.
///
/// Language codes are case-sensitive and expected to be lower case.
extern fn gst_tag_get_language_code_iso_639_2T(p_lang_code: [*:0]const u8) ?[*:0]const u8;
pub const tagGetLanguageCodeIso6392T = gst_tag_get_language_code_iso_639_2T;

/// Returns a list of known language codes (in form of two-letter ISO-639-1
/// codes). This is useful for UIs to build a list of available languages for
/// tagging purposes (e.g. to tag an audio track appropriately in a video or
/// audio editor).
extern fn gst_tag_get_language_codes() [*][*:0]u8;
pub const tagGetLanguageCodes = gst_tag_get_language_codes;

/// Returns the name of the language given an ISO-639 language code as
/// found in a GST_TAG_LANGUAGE_CODE tag. The name will be translated
/// according to the current locale (if the library was built against the
/// iso-codes package, otherwise the English name will be returned).
///
/// Language codes are case-sensitive and expected to be lower case.
extern fn gst_tag_get_language_name(p_language_code: [*:0]const u8) ?[*:0]const u8;
pub const tagGetLanguageName = gst_tag_get_language_name;

/// Get the description of a license, which is a translated description
/// of the license's main features.
extern fn gst_tag_get_license_description(p_license_ref: [*:0]const u8) ?[*:0]const u8;
pub const tagGetLicenseDescription = gst_tag_get_license_description;

/// Get the flags of a license, which describe most of the features of
/// a license in their most general form.
extern fn gst_tag_get_license_flags(p_license_ref: [*:0]const u8) gsttag.TagLicenseFlags;
pub const tagGetLicenseFlags = gst_tag_get_license_flags;

/// Get the jurisdiction code of a license. This is usually a two-letter
/// ISO 3166-1 alpha-2 code, but there is also the special case of Scotland,
/// for which no code exists and which is thus represented as "scotland".
///
/// Known jurisdictions: ar, at, au, be, bg, br, ca, ch, cl, cn, co, de,
/// dk, es, fi, fr, hr, hu, il, in, it, jp, kr, mk, mt, mx, my, nl, pe, pl,
/// pt, scotland, se, si, tw, uk, us, za.
extern fn gst_tag_get_license_jurisdiction(p_license_ref: [*:0]const u8) ?[*:0]const u8;
pub const tagGetLicenseJurisdiction = gst_tag_get_license_jurisdiction;

/// Get the nick name of a license, which is a short (untranslated) string
/// such as e.g. "CC BY-NC-ND 2.0 UK".
extern fn gst_tag_get_license_nick(p_license_ref: [*:0]const u8) ?[*:0]const u8;
pub const tagGetLicenseNick = gst_tag_get_license_nick;

/// Get the title of a license, which is a short translated description
/// of the license's features (generally not very pretty though).
extern fn gst_tag_get_license_title(p_license_ref: [*:0]const u8) ?[*:0]const u8;
pub const tagGetLicenseTitle = gst_tag_get_license_title;

/// Get the version of a license.
extern fn gst_tag_get_license_version(p_license_ref: [*:0]const u8) ?[*:0]const u8;
pub const tagGetLicenseVersion = gst_tag_get_license_version;

/// Returns a list of known license references (in form of URIs). This is
/// useful for UIs to build a list of available licenses for tagging purposes
/// (e.g. to tag an audio track appropriately in a video or audio editor, or
/// an image in a camera application).
extern fn gst_tag_get_licenses() [*][*:0]u8;
pub const tagGetLicenses = gst_tag_get_licenses;

/// Gets the number of ID3v1 genres that can be identified. Winamp genres are
/// included.
extern fn gst_tag_id3_genre_count() c_uint;
pub const tagId3GenreCount = gst_tag_id3_genre_count;

/// Gets the ID3v1 genre name for a given ID.
extern fn gst_tag_id3_genre_get(p_id: c_uint) ?[*:0]const u8;
pub const tagId3GenreGet = gst_tag_id3_genre_get;

/// Helper function for tag-reading plugins to create a `gst.Sample` suitable to
/// add to a `gst.TagList` as an image tag (such as `GST_TAG_IMAGE` or
/// `GST_TAG_PREVIEW_IMAGE`) from the encoded image data and an (optional) image
/// type.
///
/// Background: cover art and other images in tags are usually stored as a
/// blob of binary image data, often accompanied by a MIME type or some other
/// content type string (e.g. 'png', 'jpeg', 'jpg'). Sometimes there is also an
/// 'image type' to indicate what kind of image this is (e.g. front cover,
/// back cover, artist, etc.). The image data may also be an URI to the image
/// rather than the image itself.
///
/// In GStreamer, image tags are `gst.Sample`<!-- -->s containing the raw image
/// data, with the sample caps describing the content type of the image
/// (e.g. image/jpeg, image/png, text/uri-list). The sample info may contain
/// an additional 'image-type' field of `gsttag.TagImageType` to describe
/// the type of image (front cover, back cover etc.). `GST_TAG_PREVIEW_IMAGE`
/// tags should not carry an image type, their type is already indicated via
/// the special tag name.
///
/// This function will do various checks and typefind the encoded image
/// data (we can't trust the declared mime type).
extern fn gst_tag_image_data_to_image_sample(p_image_data: [*]const u8, p_image_data_len: c_uint, p_image_type: gsttag.TagImageType) ?*gst.Sample;
pub const tagImageDataToImageSample = gst_tag_image_data_to_image_sample;

/// Adds an image from an ID3 APIC frame (or similar, such as used in FLAC)
/// to the given tag list. Also see `gsttag.tagImageDataToImageSample` for
/// more information on image tags in GStreamer.
extern fn gst_tag_list_add_id3_image(p_tag_list: *gst.TagList, p_image_data: [*]const u8, p_image_data_len: c_uint, p_id3_picture_type: c_uint) c_int;
pub const tagListAddId3Image = gst_tag_list_add_id3_image;

/// Parses the IFD and IFD tags data contained in the buffer and puts it
/// on a taglist. The base_offset is used to subtract from the offset in
/// the tag entries and be able to get the offset relative to the buffer
/// start
extern fn gst_tag_list_from_exif_buffer(p_buffer: *gst.Buffer, p_byte_order: c_int, p_base_offset: u32) *gst.TagList;
pub const tagListFromExifBuffer = gst_tag_list_from_exif_buffer;

/// Parses the exif tags starting with a tiff header structure.
extern fn gst_tag_list_from_exif_buffer_with_tiff_header(p_buffer: *gst.Buffer) *gst.TagList;
pub const tagListFromExifBufferWithTiffHeader = gst_tag_list_from_exif_buffer_with_tiff_header;

/// Creates a new tag list that contains the information parsed out of a
/// ID3 tag.
extern fn gst_tag_list_from_id3v2_tag(p_buffer: *gst.Buffer) ?*gst.TagList;
pub const tagListFromId3v2Tag = gst_tag_list_from_id3v2_tag;

/// Creates a new tag list that contains the information parsed out of a
/// vorbiscomment packet.
extern fn gst_tag_list_from_vorbiscomment(p_data: [*]const u8, p_size: usize, p_id_data: [*]const u8, p_id_data_length: c_uint, p_vendor_string: ?*[*:0]u8) ?*gst.TagList;
pub const tagListFromVorbiscomment = gst_tag_list_from_vorbiscomment;

/// Creates a new tag list that contains the information parsed out of a
/// vorbiscomment packet.
extern fn gst_tag_list_from_vorbiscomment_buffer(p_buffer: *gst.Buffer, p_id_data: [*]const u8, p_id_data_length: c_uint, p_vendor_string: ?*[*:0]u8) ?*gst.TagList;
pub const tagListFromVorbiscommentBuffer = gst_tag_list_from_vorbiscomment_buffer;

/// Parse a xmp packet into a taglist.
extern fn gst_tag_list_from_xmp_buffer(p_buffer: *gst.Buffer) ?*gst.TagList;
pub const tagListFromXmpBuffer = gst_tag_list_from_xmp_buffer;

/// Parses the data containing an ID3v1 tag and returns a `gst.TagList` from the
/// parsed data.
extern fn gst_tag_list_new_from_id3v1(p_data: *const [128]u8) ?*gst.TagList;
pub const tagListNewFromId3v1 = gst_tag_list_new_from_id3v1;

/// Formats the tags in taglist on exif format. The resulting buffer contains
/// the tags IFD and is followed by the data pointed by the tag entries.
extern fn gst_tag_list_to_exif_buffer(p_taglist: *const gst.TagList, p_byte_order: c_int, p_base_offset: u32) *gst.Buffer;
pub const tagListToExifBuffer = gst_tag_list_to_exif_buffer;

/// Formats the tags in taglist into exif structure, a tiff header
/// is put in the beginning of the buffer.
extern fn gst_tag_list_to_exif_buffer_with_tiff_header(p_taglist: *const gst.TagList) *gst.Buffer;
pub const tagListToExifBufferWithTiffHeader = gst_tag_list_to_exif_buffer_with_tiff_header;

/// Creates a new vorbiscomment buffer from a tag list.
extern fn gst_tag_list_to_vorbiscomment_buffer(p_list: *const gst.TagList, p_id_data: [*]const u8, p_id_data_length: c_uint, p_vendor_string: ?[*:0]const u8) *gst.Buffer;
pub const tagListToVorbiscommentBuffer = gst_tag_list_to_vorbiscomment_buffer;

/// Formats a taglist as a xmp packet using only the selected
/// schemas. An empty list (`NULL`) means that all schemas should
/// be used
extern fn gst_tag_list_to_xmp_buffer(p_list: *const gst.TagList, p_read_only: c_int, p_schemas: [*][*:0]const u8) ?*gst.Buffer;
pub const tagListToXmpBuffer = gst_tag_list_to_xmp_buffer;

/// Convenience function to parse a GST_TAG_EXTENDED_COMMENT string and
/// separate it into its components.
///
/// If successful, `key`, `lang` and/or `value` will be set to newly allocated
/// strings that you need to free with `glib.free` when done. `key` and `lang`
/// may also be set to NULL by this function if there is no key or no language
/// code in the extended comment string.
extern fn gst_tag_parse_extended_comment(p_ext_comment: [*:0]const u8, p_key: ?*[*:0]u8, p_lang: ?*[*:0]u8, p_value: *[*:0]u8, p_fail_if_no_key: c_int) c_int;
pub const tagParseExtendedComment = gst_tag_parse_extended_comment;

/// Registers additional musicbrainz-specific tags with the GStreamer tag
/// system. Plugins and applications that use these tags should call this
/// function before using them. Can be called multiple times.
extern fn gst_tag_register_musicbrainz_tags() void;
pub const tagRegisterMusicbrainzTags = gst_tag_register_musicbrainz_tags;

/// Looks up the ID3v2 tag for a GStreamer tag.
extern fn gst_tag_to_id3_tag(p_gst_tag: [*:0]const u8) ?[*:0]const u8;
pub const tagToId3Tag = gst_tag_to_id3_tag;

/// Creates a new tag list that contains the information parsed out of a
/// vorbiscomment packet.
extern fn gst_tag_to_vorbis_comments(p_list: *const gst.TagList, p_tag: [*:0]const u8) *glib.List;
pub const tagToVorbisComments = gst_tag_to_vorbis_comments;

/// Looks up the vorbiscomment tag for a GStreamer tag.
extern fn gst_tag_to_vorbis_tag(p_gst_tag: [*:0]const u8) ?[*:0]const u8;
pub const tagToVorbisTag = gst_tag_to_vorbis_tag;

/// Gets the list of supported schemas in the xmp lib
extern fn gst_tag_xmp_list_schemas() [*][*:0]const u8;
pub const tagXmpListSchemas = gst_tag_xmp_list_schemas;

/// Convenience function using `gsttag.tagFromVorbisTag`, parsing
/// a vorbis comment string into the right type and adding it to the
/// given taglist `list`.
///
/// Unknown vorbiscomment tags will be added to the tag list in form
/// of a `GST_TAG_EXTENDED_COMMENT`.
extern fn gst_vorbis_tag_add(p_list: *gst.TagList, p_tag: [*:0]const u8, p_value: [*:0]const u8) void;
pub const vorbisTagAdd = gst_vorbis_tag_add;

/// AcoustID Fingerprint (Chromaprint)
pub const TAG_ACOUSTID_FINGERPRINT = "chromaprint-fingerprint";
/// AcoustID Identifier
pub const TAG_ACOUSTID_ID = "acoustid-id";
/// Direction of contrast processing applied when capturing an image. (string)
///
/// The allowed values are:
///  "normal"
///  "soft"
///  "hard"
pub const TAG_CAPTURING_CONTRAST = "capturing-contrast";
/// Digital zoom ratio used when capturing an image. (double)
pub const TAG_CAPTURING_DIGITAL_ZOOM_RATIO = "capturing-digital-zoom-ratio";
/// Exposure compensation using when capturing an image in EV. (double)
pub const TAG_CAPTURING_EXPOSURE_COMPENSATION = "capturing-exposure-compensation";
/// Exposure mode used when capturing an image. (string)
///
/// The allowed values are:
///   "auto-exposure"
///   "manual-exposure"
///   "auto-bracket"
pub const TAG_CAPTURING_EXPOSURE_MODE = "capturing-exposure-mode";
/// Type of exposure control used when capturing an image. (string)
///
/// The allowed values are:
///   "undefined"
///   "manual"
///   "normal" - automatically controlled
///   "aperture-priority" - user selects aperture value
///   "shutter-priority" - user selects shutter speed
///   "creative" - biased towards depth of field
///   "action" - biased towards fast shutter speed
///   "portrait" - closeup, leaving background out of focus
///   "landscape" - landscape photos, background in focus
pub const TAG_CAPTURING_EXPOSURE_PROGRAM = "capturing-exposure-program";
/// If flash was fired during the capture of an image. (boolean)
///
/// Note that if this tag isn't present, it should not be assumed that
/// the flash did not fire. It should be treated as unknown.
pub const TAG_CAPTURING_FLASH_FIRED = "capturing-flash-fired";
/// The flash mode selected during the capture of an image. (string)
///
/// The allowed values are:
///  "auto"
///  "always"
///  "never"
pub const TAG_CAPTURING_FLASH_MODE = "capturing-flash-mode";
/// Focal length used when capturing an image, in mm. (double)
pub const TAG_CAPTURING_FOCAL_LENGTH = "capturing-focal-length";
/// 35 mm equivalent focal length used when capturing an image, in mm. (double)
pub const TAG_CAPTURING_FOCAL_LENGTH_35_MM = "capturing-focal-length-35mm";
/// Focal ratio (f-number) used when capturing an image. (double)
///
/// The value stored is the denominator of the focal ratio (f-number).
/// For example, if this tag value is 2, the focal ratio is f/2.
pub const TAG_CAPTURING_FOCAL_RATIO = "capturing-focal-ratio";
/// Gain adjustment applied to an image. (string)
///
/// The allowed values are:
///   "none"
///   "low-gain-up"
///   "high-gain-up"
///   "low-gain-down"
///   "high-gain-down"
pub const TAG_CAPTURING_GAIN_ADJUSTMENT = "capturing-gain-adjustment";
/// ISO speed used when capturing an image. (integer)
pub const TAG_CAPTURING_ISO_SPEED = "capturing-iso-speed";
/// Light source used when capturing an image. (string)
///
/// The allowed values are:
///   "unknown"
///   "daylight"
///   "fluorescent"
///   "tungsten"
///   "flash"
///   "fine-weather"
///   "cloudy-weather"
///   "shade"
///   "daylight-fluorescent"
///   "day-white-fluorescent"
///   "cool-white-fluorescent"
///   "white-fluorescent"
///   "warm-white-fluorescent"
///   "standard-light-A"
///   "standard-light-B"
///   "standard-light-C"
///   "D55"
///   "D65"
///   "D75"
///   "D50"
///   "iso-studio-tungsten"
///   "other"
pub const TAG_CAPTURING_LIGHT_SOURCE = "capturing-light-source";
/// Defines the way a camera determines the exposure. (string)
///
/// The allowed values are:
///   "unknown"
///   "average"
///   "center-weighted-average"
///   "spot"
///   "multi-spot"
///   "pattern"
///   "partial"
///   "other"
pub const TAG_CAPTURING_METERING_MODE = "capturing-metering-mode";
/// Direction of saturation processing applied when capturing an image. (string)
///
/// The allowed values are:
///  "normal"
///  "low-saturation"
///  "high-saturation"
pub const TAG_CAPTURING_SATURATION = "capturing-saturation";
/// Scene mode used when capturing an image. (string)
///
/// The allowed values are:
///   "standard"
///   "landscape"
///   "portrait"
///   "night-scene"
pub const TAG_CAPTURING_SCENE_CAPTURE_TYPE = "capturing-scene-capture-type";
/// Direction of sharpness processing applied when capturing an image. (string)
///
/// The allowed values are:
///  "normal"
///  "soft"
///  "hard"
pub const TAG_CAPTURING_SHARPNESS = "capturing-sharpness";
/// Shutter speed used when capturing an image, in seconds. (fraction)
pub const TAG_CAPTURING_SHUTTER_SPEED = "capturing-shutter-speed";
/// Indicates the source of capture. The device/medium used to do the
/// capture. (string)
///
/// Allowed values are:
///   "dsc" (= digital still camera)
///   "transparent-scanner"
///   "reflex-scanner"
///   "other"
pub const TAG_CAPTURING_SOURCE = "capturing-source";
/// White balance mode used when capturing an image. (string)
///
/// The allowed values are:
///   "auto"
///   "manual"
///   "daylight"
///   "cloudy"
///   "tungsten"
///   "fluorescent"
///   "fluorescent h" (newer daylight-calibrated fluorescents)
///   "flash"
pub const TAG_CAPTURING_WHITE_BALANCE = "capturing-white-balance";
/// CDDB disc id in its short form (e.g. 'aa063d0f')
pub const TAG_CDDA_CDDB_DISCID = "discid";
/// CDDB disc id including all details
pub const TAG_CDDA_CDDB_DISCID_FULL = "discid-full";
/// Musicbrainz disc id (e.g. 'ahg7JUcfR3vCYBphSDIogOOWrr0-')
pub const TAG_CDDA_MUSICBRAINZ_DISCID = "musicbrainz-discid";
/// Musicbrainz disc id details
pub const TAG_CDDA_MUSICBRAINZ_DISCID_FULL = "musicbrainz-discid-full";
/// Annodex CMML clip element tag
pub const TAG_CMML_CLIP = "cmml-clip";
/// Annodex CMML head element tag
pub const TAG_CMML_HEAD = "cmml-head";
/// Annodex CMML stream element tag
pub const TAG_CMML_STREAM = "cmml-stream";
/// ID3V2 header size considered minimum input for some functions such as
/// `gsttag.tagListFromId3v2Tag` and `gsttag.tagGetId3v2TagSize` for example.
pub const TAG_ID3V2_HEADER_SIZE = 10;
/// Media (image/video) intended horizontal pixel density in ppi. (double)
pub const TAG_IMAGE_HORIZONTAL_PPI = "image-horizontal-ppi";
/// Media (image/video) intended vertical pixel density in ppi. (double)
pub const TAG_IMAGE_VERTICAL_PPI = "image-vertical-ppi";
/// Musical key in which the sound starts. It is represented as a string
/// with a maximum length of three characters. The ground keys are
/// represented with "A","B","C","D","E", "F" and "G" and halfkeys
/// represented with "b" and "#". Minor is represented as "m" (e.g. "Dbm").
/// Off key is represented with an "o" only.
/// This notation might be extended in the future to support non-minor/major
/// keys.
pub const TAG_MUSICAL_KEY = "musical-key";
/// MusicBrainz album artist ID
pub const TAG_MUSICBRAINZ_ALBUMARTISTID = "musicbrainz-albumartistid";
/// MusicBrainz album ID
pub const TAG_MUSICBRAINZ_ALBUMID = "musicbrainz-albumid";
/// MusicBrainz artist ID
pub const TAG_MUSICBRAINZ_ARTISTID = "musicbrainz-artistid";
/// MusicBrainz Release Group ID
pub const TAG_MUSICBRAINZ_RELEASEGROUPID = "musicbrainz-releasegroupid";
/// MusicBrainz Release Track ID
pub const TAG_MUSICBRAINZ_RELEASETRACKID = "musicbrainz-releasetrackid";
/// MusicBrainz track ID
pub const TAG_MUSICBRAINZ_TRACKID = "musicbrainz-trackid";
/// MusicBrainz track TRM ID
pub const TAG_MUSICBRAINZ_TRMID = "musicbrainz-trmid";

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