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

const std = @import("std");
const compat = @import("compat");
const gstvideo = @import("gstvideo1");
const gstbase = @import("gstbase1");
const gst = @import("gst1");
const gobject = @import("gobject2");
const glib = @import("glib2");
const gmodule = @import("gmodule2");
const gsttag = @import("gsttag1");
const gstpbutils = @import("gstpbutils1");
const gstaudio = @import("gstaudio1");
/// The goal of the GstPlay library is to ease the integration of multimedia
/// playback features in applications. Thus, if you need to build a media player
/// from the ground-up, GstPlay provides the features you will most likely need.
///
/// An example player is available in gst-examples/playback/player/gst-play/.
///
/// Internally the GstPlay makes use of the `playbin3` element. The legacy
/// `playbin2` can be selected if the `GST_PLAY_USE_PLAYBIN3=0` environment
/// variable has been set.
///
/// **Important note**: If your application relies on the GstBus to get
/// notifications from GstPlay, you need to add some explicit clean-up code in
/// order to prevent the GstPlay object from leaking. See below for the details.
/// If you use the GstPlaySignalAdapter, no special clean-up is required.
///
/// When the GstPlaySignalAdapter is not used, the GstBus owned by GstPlay should
/// be set to flushing state before any attempt to drop the last reference of the
/// GstPlay object. An example in C:
///
/// ```c
/// ...
/// GstBus *bus = gst_play_get_message_bus (player);
/// gst_bus_set_flushing (bus, TRUE);
/// gst_object_unref (bus);
/// gst_object_unref (player);
/// ```
///
/// The messages managed by the player contain a reference to itself, and if the
/// bus watch is just removed together with dropping the player then the bus will
/// simply keep them around forever (and the bus never goes away because the
/// player has a strong reference to it, so there's a reference cycle as long as
/// there are messages). Setting the bus to flushing state forces it to get rid
/// of its queued messages, thus breaking any possible reference cycle.
pub const Play = opaque {
    pub const Parent = gst.Object;
    pub const Implements = [_]type{};
    pub const Class = gstplay.PlayClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {
        pub const audio_video_offset = struct {
            pub const name = "audio-video-offset";

            pub const Type = i64;
        };

        pub const current_audio_track = struct {
            pub const name = "current-audio-track";

            pub const Type = ?*gstplay.PlayAudioInfo;
        };

        pub const current_subtitle_track = struct {
            pub const name = "current-subtitle-track";

            pub const Type = ?*gstplay.PlaySubtitleInfo;
        };

        pub const current_video_track = struct {
            pub const name = "current-video-track";

            pub const Type = ?*gstplay.PlayVideoInfo;
        };

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

            pub const Type = u64;
        };

        pub const media_info = struct {
            pub const name = "media-info";

            pub const Type = ?*gstplay.PlayMediaInfo;
        };

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

            pub const Type = c_int;
        };

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

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

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

            pub const Type = u64;
        };

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

            pub const Type = f64;
        };

        pub const subtitle_video_offset = struct {
            pub const name = "subtitle-video-offset";

            pub const Type = i64;
        };

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

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

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

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

        pub const video_multiview_flags = struct {
            pub const name = "video-multiview-flags";

            pub const Type = gstvideo.VideoMultiviewFlags;
        };

        pub const video_multiview_mode = struct {
            pub const name = "video-multiview-mode";

            pub const Type = gstvideo.VideoMultiviewFramePacking;
        };

        pub const video_renderer = struct {
            pub const name = "video-renderer";

            pub const Type = ?*gstplay.PlayVideoRenderer;
        };

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

            pub const Type = f64;
        };
    };

    pub const signals = struct {};

    extern fn gst_play_config_get_pipeline_dump_in_error_details(p_config: *const gst.Structure) c_int;
    pub const configGetPipelineDumpInErrorDetails = gst_play_config_get_pipeline_dump_in_error_details;

    extern fn gst_play_config_get_position_update_interval(p_config: *const gst.Structure) c_uint;
    pub const configGetPositionUpdateInterval = gst_play_config_get_position_update_interval;

    extern fn gst_play_config_get_seek_accurate(p_config: *const gst.Structure) c_int;
    pub const configGetSeekAccurate = gst_play_config_get_seek_accurate;

    /// Return the user agent which has been configured using
    /// `gstplay.Play.configSetUserAgent` if any.
    extern fn gst_play_config_get_user_agent(p_config: *const gst.Structure) ?[*:0]u8;
    pub const configGetUserAgent = gst_play_config_get_user_agent;

    /// When enabled, the error message emitted by `gstplay.Play` will include a pipeline
    /// dump (in Graphviz DOT format) in the error details `gst.Structure`. The field
    /// name is `pipeline-dump`.
    ///
    /// This option is disabled by default.
    extern fn gst_play_config_set_pipeline_dump_in_error_details(p_config: *gst.Structure, p_value: c_int) void;
    pub const configSetPipelineDumpInErrorDetails = gst_play_config_set_pipeline_dump_in_error_details;

    /// Set desired interval in milliseconds between two position-updated messages.
    /// Pass 0 to stop updating the position.
    extern fn gst_play_config_set_position_update_interval(p_config: *gst.Structure, p_interval: c_uint) void;
    pub const configSetPositionUpdateInterval = gst_play_config_set_position_update_interval;

    /// Enable or disable accurate seeking. When enabled, elements will try harder
    /// to seek as accurately as possible to the requested seek position. Generally
    /// it will be slower especially for formats that don't have any indexes or
    /// timestamp markers in the stream.
    ///
    /// If accurate seeking is disabled, elements will seek as close as the request
    /// position without slowing down seeking too much.
    ///
    /// Accurate seeking is disabled by default.
    extern fn gst_play_config_set_seek_accurate(p_config: *gst.Structure, p_accurate: c_int) void;
    pub const configSetSeekAccurate = gst_play_config_set_seek_accurate;

    /// Set the user agent to pass to the server if `play` needs to connect
    /// to a server during playback. This is typically used when playing HTTP
    /// or RTSP streams.
    extern fn gst_play_config_set_user_agent(p_config: *gst.Structure, p_agent: ?[*:0]const u8) void;
    pub const configSetUserAgent = gst_play_config_set_user_agent;

    extern fn gst_play_get_audio_streams(p_info: *const gstplay.PlayMediaInfo) *glib.List;
    pub const getAudioStreams = gst_play_get_audio_streams;

    extern fn gst_play_get_subtitle_streams(p_info: *const gstplay.PlayMediaInfo) *glib.List;
    pub const getSubtitleStreams = gst_play_get_subtitle_streams;

    extern fn gst_play_get_video_streams(p_info: *const gstplay.PlayMediaInfo) *glib.List;
    pub const getVideoStreams = gst_play_get_video_streams;

    extern fn gst_play_is_play_message(p_msg: *gst.Message) c_int;
    pub const isPlayMessage = gst_play_is_play_message;

    /// Frees a `NULL` terminated array of `gstplay.PlayVisualization`.
    extern fn gst_play_visualizations_free(p_viss: **gstplay.PlayVisualization) void;
    pub const visualizationsFree = gst_play_visualizations_free;

    extern fn gst_play_visualizations_get() [*]*gstplay.PlayVisualization;
    pub const visualizationsGet = gst_play_visualizations_get;

    /// Creates a new `gstplay.Play` instance.
    ///
    /// Video is going to be rendered by `video_renderer`, or if `NULL` is provided
    /// no special video set up will be done and some default handling will be
    /// performed.
    ///
    /// This also initializes GStreamer via ``gst.init`` on the first call if this
    /// didn't happen before.
    extern fn gst_play_new(p_video_renderer: ?*gstplay.PlayVideoRenderer) *gstplay.Play;
    pub const new = gst_play_new;

    /// Retrieve the current value of audio-video-offset property
    extern fn gst_play_get_audio_video_offset(p_play: *Play) i64;
    pub const getAudioVideoOffset = gst_play_get_audio_video_offset;

    /// Retrieve the current value of the indicated `type`.
    extern fn gst_play_get_color_balance(p_play: *Play, p_type: gstplay.PlayColorBalanceType) f64;
    pub const getColorBalance = gst_play_get_color_balance;

    /// Get a copy of the current configuration of the play. This configuration
    /// can either be modified and used for the `gstplay.Play.setConfig` call
    /// or it must be freed after usage.
    extern fn gst_play_get_config(p_play: *Play) *gst.Structure;
    pub const getConfig = gst_play_get_config;

    /// A Function to get current audio `gstplay.PlayAudioInfo` instance.
    extern fn gst_play_get_current_audio_track(p_play: *Play) ?*gstplay.PlayAudioInfo;
    pub const getCurrentAudioTrack = gst_play_get_current_audio_track;

    /// A Function to get current subtitle `gstplay.PlaySubtitleInfo` instance.
    extern fn gst_play_get_current_subtitle_track(p_play: *Play) ?*gstplay.PlaySubtitleInfo;
    pub const getCurrentSubtitleTrack = gst_play_get_current_subtitle_track;

    /// A Function to get current video `gstplay.PlayVideoInfo` instance.
    extern fn gst_play_get_current_video_track(p_play: *Play) ?*gstplay.PlayVideoInfo;
    pub const getCurrentVideoTrack = gst_play_get_current_video_track;

    extern fn gst_play_get_current_visualization(p_play: *Play) ?[*:0]u8;
    pub const getCurrentVisualization = gst_play_get_current_visualization;

    /// Retrieves the duration of the media stream that self represents.
    extern fn gst_play_get_duration(p_play: *Play) gst.ClockTime;
    pub const getDuration = gst_play_get_duration;

    /// A Function to get the current media info `gstplay.PlayMediaInfo` instance.
    extern fn gst_play_get_media_info(p_play: *Play) ?*gstplay.PlayMediaInfo;
    pub const getMediaInfo = gst_play_get_media_info;

    /// GstPlay API exposes a `gst.Bus` instance which purpose is to provide data
    /// structures representing play-internal events in form of `gst.Message`<!-- -->s of
    /// type GST_MESSAGE_APPLICATION.
    ///
    /// Each message carries a "play-message" field of type `gstplay.PlayMessage`.
    /// Further fields of the message data are specific to each possible value of
    /// that enumeration.
    ///
    /// Applications can consume the messages asynchronously within their own
    /// event-loop / UI-thread etc. Note that in case the application does not
    /// consume the messages, the bus will accumulate these internally and eventually
    /// fill memory. To avoid that, the bus has to be set "flushing".
    extern fn gst_play_get_message_bus(p_play: *Play) *gst.Bus;
    pub const getMessageBus = gst_play_get_message_bus;

    /// Retrieve the current value of the indicated `type`.
    extern fn gst_play_get_multiview_flags(p_play: *Play) gstvideo.VideoMultiviewFlags;
    pub const getMultiviewFlags = gst_play_get_multiview_flags;

    /// Retrieve the current value of the indicated `type`.
    extern fn gst_play_get_multiview_mode(p_play: *Play) gstvideo.VideoMultiviewFramePacking;
    pub const getMultiviewMode = gst_play_get_multiview_mode;

    extern fn gst_play_get_mute(p_play: *Play) c_int;
    pub const getMute = gst_play_get_mute;

    extern fn gst_play_get_pipeline(p_play: *Play) *gst.Element;
    pub const getPipeline = gst_play_get_pipeline;

    extern fn gst_play_get_position(p_play: *Play) gst.ClockTime;
    pub const getPosition = gst_play_get_position;

    extern fn gst_play_get_rate(p_play: *Play) f64;
    pub const getRate = gst_play_get_rate;

    /// Current subtitle URI
    extern fn gst_play_get_subtitle_uri(p_play: *Play) ?[*:0]u8;
    pub const getSubtitleUri = gst_play_get_subtitle_uri;

    /// Retrieve the current value of subtitle-video-offset property
    extern fn gst_play_get_subtitle_video_offset(p_play: *Play) i64;
    pub const getSubtitleVideoOffset = gst_play_get_subtitle_video_offset;

    /// Gets the URI of the currently-playing stream.
    extern fn gst_play_get_uri(p_play: *Play) ?[*:0]u8;
    pub const getUri = gst_play_get_uri;

    /// Get a snapshot of the currently selected video stream, if any. The format can be
    /// selected with `format` and optional configuration is possible with `config`.
    /// Currently supported settings are:
    /// - width, height of type G_TYPE_INT
    /// - pixel-aspect-ratio of type GST_TYPE_FRACTION
    ///  Except for GST_PLAY_THUMBNAIL_RAW_NATIVE format, if no config is set, pixel-aspect-ratio would be 1/1
    extern fn gst_play_get_video_snapshot(p_play: *Play, p_format: gstplay.PlaySnapshotFormat, p_config: ?*const gst.Structure) ?*gst.Sample;
    pub const getVideoSnapshot = gst_play_get_video_snapshot;

    /// Returns the current volume level, as a percentage between 0 and 1.
    extern fn gst_play_get_volume(p_play: *Play) f64;
    pub const getVolume = gst_play_get_volume;

    /// Checks whether the `play` has color balance support available.
    extern fn gst_play_has_color_balance(p_play: *Play) c_int;
    pub const hasColorBalance = gst_play_has_color_balance;

    /// Pauses the current stream.
    extern fn gst_play_pause(p_play: *Play) void;
    pub const pause = gst_play_pause;

    /// Request to play the loaded stream.
    extern fn gst_play_play(p_play: *Play) void;
    pub const play = gst_play_play;

    /// Seeks the currently-playing stream to the absolute `position` time
    /// in nanoseconds.
    extern fn gst_play_seek(p_play: *Play, p_position: gst.ClockTime) void;
    pub const seek = gst_play_seek;

    extern fn gst_play_set_audio_track(p_play: *Play, p_stream_index: c_int) c_int;
    pub const setAudioTrack = gst_play_set_audio_track;

    /// Enable or disable the current audio track.
    extern fn gst_play_set_audio_track_enabled(p_play: *Play, p_enabled: c_int) void;
    pub const setAudioTrackEnabled = gst_play_set_audio_track_enabled;

    extern fn gst_play_set_audio_track_id(p_play: *Play, p_stream_id: ?[*:0]const u8) c_int;
    pub const setAudioTrackId = gst_play_set_audio_track_id;

    /// Sets audio-video-offset property by value of `offset`
    extern fn gst_play_set_audio_video_offset(p_play: *Play, p_offset: i64) void;
    pub const setAudioVideoOffset = gst_play_set_audio_video_offset;

    /// Sets the current value of the indicated channel `type` to the passed
    /// value.
    extern fn gst_play_set_color_balance(p_play: *Play, p_type: gstplay.PlayColorBalanceType, p_value: f64) void;
    pub const setColorBalance = gst_play_set_color_balance;

    /// Set the configuration of the play. If the play is already configured, and
    /// the configuration hasn't changed, this function will return `TRUE`. If the
    /// play is not in the GST_PLAY_STATE_STOPPED, this method will return `FALSE`
    /// and active configuration will remain.
    ///
    /// `config` is a `gst.Structure` that contains the configuration parameters for
    /// the play.
    ///
    /// This function takes ownership of `config`.
    extern fn gst_play_set_config(p_play: *Play, p_config: *gst.Structure) c_int;
    pub const setConfig = gst_play_set_config;

    /// Sets the current value of the indicated mode `type` to the passed
    /// value.
    extern fn gst_play_set_multiview_flags(p_play: *Play, p_flags: gstvideo.VideoMultiviewFlags) void;
    pub const setMultiviewFlags = gst_play_set_multiview_flags;

    /// Sets the current value of the indicated mode `type` to the passed
    /// value.
    extern fn gst_play_set_multiview_mode(p_play: *Play, p_mode: gstvideo.VideoMultiviewFramePacking) void;
    pub const setMultiviewMode = gst_play_set_multiview_mode;

    /// `TRUE` if the currently-playing stream should be muted.
    extern fn gst_play_set_mute(p_play: *Play, p_val: c_int) void;
    pub const setMute = gst_play_set_mute;

    /// Playback at specified rate
    extern fn gst_play_set_rate(p_play: *Play, p_rate: f64) void;
    pub const setRate = gst_play_set_rate;

    extern fn gst_play_set_subtitle_track(p_play: *Play, p_stream_index: c_int) c_int;
    pub const setSubtitleTrack = gst_play_set_subtitle_track;

    /// Enable or disable the current subtitle track.
    extern fn gst_play_set_subtitle_track_enabled(p_play: *Play, p_enabled: c_int) void;
    pub const setSubtitleTrackEnabled = gst_play_set_subtitle_track_enabled;

    extern fn gst_play_set_subtitle_track_id(p_play: *Play, p_stream_id: ?[*:0]const u8) c_int;
    pub const setSubtitleTrackId = gst_play_set_subtitle_track_id;

    /// Sets the external subtitle URI. This should be combined with a call to
    /// gst_play_set_subtitle_track_enabled(`play`, TRUE) so the subtitles are actually
    /// rendered.
    extern fn gst_play_set_subtitle_uri(p_play: *Play, p_uri: ?[*:0]const u8) void;
    pub const setSubtitleUri = gst_play_set_subtitle_uri;

    /// Sets subtitle-video-offset property by value of `offset`
    extern fn gst_play_set_subtitle_video_offset(p_play: *Play, p_offset: i64) void;
    pub const setSubtitleVideoOffset = gst_play_set_subtitle_video_offset;

    extern fn gst_play_set_track_ids(p_play: *Play, p_audio_stream_id: ?[*:0]const u8, p_video_stream_id: ?[*:0]const u8, p_subtitle_stream_id: ?[*:0]const u8) c_int;
    pub const setTrackIds = gst_play_set_track_ids;

    /// Sets the next URI to play.
    extern fn gst_play_set_uri(p_play: *Play, p_uri: ?[*:0]const u8) void;
    pub const setUri = gst_play_set_uri;

    extern fn gst_play_set_video_track(p_play: *Play, p_stream_index: c_int) c_int;
    pub const setVideoTrack = gst_play_set_video_track;

    /// Enable or disable the current video track.
    extern fn gst_play_set_video_track_enabled(p_play: *Play, p_enabled: c_int) void;
    pub const setVideoTrackEnabled = gst_play_set_video_track_enabled;

    extern fn gst_play_set_video_track_id(p_play: *Play, p_stream_id: ?[*:0]const u8) c_int;
    pub const setVideoTrackId = gst_play_set_video_track_id;

    extern fn gst_play_set_visualization(p_play: *Play, p_name: ?[*:0]const u8) c_int;
    pub const setVisualization = gst_play_set_visualization;

    /// Enable or disable the visualization.
    extern fn gst_play_set_visualization_enabled(p_play: *Play, p_enabled: c_int) void;
    pub const setVisualizationEnabled = gst_play_set_visualization_enabled;

    /// Sets the volume level of the stream as a percentage between 0 and 1.
    extern fn gst_play_set_volume(p_play: *Play, p_val: f64) void;
    pub const setVolume = gst_play_set_volume;

    /// Stops playing the current stream and resets to the first position
    /// in the stream.
    extern fn gst_play_stop(p_play: *Play) void;
    pub const stop = gst_play_stop;

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

    extern fn g_object_ref(p_self: *gstplay.Play) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstplay.Play) void;
    pub const unref = g_object_unref;

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

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

/// `gstplay.PlayStreamInfo` specific to audio streams.
pub const PlayAudioInfo = opaque {
    pub const Parent = gstplay.PlayStreamInfo;
    pub const Implements = [_]type{};
    pub const Class = gstplay.PlayAudioInfoClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    extern fn gst_play_audio_info_get_bitrate(p_info: *const PlayAudioInfo) c_int;
    pub const getBitrate = gst_play_audio_info_get_bitrate;

    extern fn gst_play_audio_info_get_channels(p_info: *const PlayAudioInfo) c_int;
    pub const getChannels = gst_play_audio_info_get_channels;

    extern fn gst_play_audio_info_get_language(p_info: *const PlayAudioInfo) ?[*:0]const u8;
    pub const getLanguage = gst_play_audio_info_get_language;

    extern fn gst_play_audio_info_get_max_bitrate(p_info: *const PlayAudioInfo) c_int;
    pub const getMaxBitrate = gst_play_audio_info_get_max_bitrate;

    extern fn gst_play_audio_info_get_sample_rate(p_info: *const PlayAudioInfo) c_int;
    pub const getSampleRate = gst_play_audio_info_get_sample_rate;

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

    extern fn g_object_ref(p_self: *gstplay.PlayAudioInfo) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstplay.PlayAudioInfo) void;
    pub const unref = g_object_unref;

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

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

/// Structure containing the media information of a URI.
pub const PlayMediaInfo = opaque {
    pub const Parent = gobject.Object;
    pub const Implements = [_]type{};
    pub const Class = gstplay.PlayMediaInfoClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    extern fn gst_play_media_info_get_audio_streams(p_info: *const PlayMediaInfo) *glib.List;
    pub const getAudioStreams = gst_play_media_info_get_audio_streams;

    extern fn gst_play_media_info_get_container_format(p_info: *const PlayMediaInfo) ?[*:0]const u8;
    pub const getContainerFormat = gst_play_media_info_get_container_format;

    extern fn gst_play_media_info_get_duration(p_info: *const PlayMediaInfo) gst.ClockTime;
    pub const getDuration = gst_play_media_info_get_duration;

    /// Function to get the image (or preview-image) stored in taglist.
    /// Application can use `gst_sample_*`_`` API's to get caps, buffer etc.
    extern fn gst_play_media_info_get_image_sample(p_info: *const PlayMediaInfo) ?*gst.Sample;
    pub const getImageSample = gst_play_media_info_get_image_sample;

    extern fn gst_play_media_info_get_number_of_audio_streams(p_info: *const PlayMediaInfo) c_uint;
    pub const getNumberOfAudioStreams = gst_play_media_info_get_number_of_audio_streams;

    extern fn gst_play_media_info_get_number_of_streams(p_info: *const PlayMediaInfo) c_uint;
    pub const getNumberOfStreams = gst_play_media_info_get_number_of_streams;

    extern fn gst_play_media_info_get_number_of_subtitle_streams(p_info: *const PlayMediaInfo) c_uint;
    pub const getNumberOfSubtitleStreams = gst_play_media_info_get_number_of_subtitle_streams;

    extern fn gst_play_media_info_get_number_of_video_streams(p_info: *const PlayMediaInfo) c_uint;
    pub const getNumberOfVideoStreams = gst_play_media_info_get_number_of_video_streams;

    extern fn gst_play_media_info_get_stream_list(p_info: *const PlayMediaInfo) *glib.List;
    pub const getStreamList = gst_play_media_info_get_stream_list;

    extern fn gst_play_media_info_get_subtitle_streams(p_info: *const PlayMediaInfo) *glib.List;
    pub const getSubtitleStreams = gst_play_media_info_get_subtitle_streams;

    extern fn gst_play_media_info_get_tags(p_info: *const PlayMediaInfo) ?*gst.TagList;
    pub const getTags = gst_play_media_info_get_tags;

    extern fn gst_play_media_info_get_title(p_info: *const PlayMediaInfo) ?[*:0]const u8;
    pub const getTitle = gst_play_media_info_get_title;

    extern fn gst_play_media_info_get_uri(p_info: *const PlayMediaInfo) [*:0]const u8;
    pub const getUri = gst_play_media_info_get_uri;

    extern fn gst_play_media_info_get_video_streams(p_info: *const PlayMediaInfo) *glib.List;
    pub const getVideoStreams = gst_play_media_info_get_video_streams;

    extern fn gst_play_media_info_is_live(p_info: *const PlayMediaInfo) c_int;
    pub const isLive = gst_play_media_info_is_live;

    extern fn gst_play_media_info_is_seekable(p_info: *const PlayMediaInfo) c_int;
    pub const isSeekable = gst_play_media_info_is_seekable;

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

    extern fn g_object_ref(p_self: *gstplay.PlayMediaInfo) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstplay.PlayMediaInfo) void;
    pub const unref = g_object_unref;

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

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

pub const PlaySignalAdapter = opaque {
    pub const Parent = gobject.Object;
    pub const Implements = [_]type{};
    pub const Class = gstplay.PlaySignalAdapterClass;
    pub const virtual_methods = struct {};

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

            pub const Type = ?*gstplay.Play;
        };
    };

    pub const signals = struct {
        pub const buffering = struct {
            pub const name = "buffering";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_object: c_int, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(PlaySignalAdapter, p_instance))),
                    gobject.signalLookup("buffering", PlaySignalAdapter.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        pub const duration_changed = struct {
            pub const name = "duration-changed";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_object: u64, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(PlaySignalAdapter, p_instance))),
                    gobject.signalLookup("duration-changed", PlaySignalAdapter.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        pub const end_of_stream = struct {
            pub const name = "end-of-stream";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(PlaySignalAdapter, p_instance))),
                    gobject.signalLookup("end-of-stream", PlaySignalAdapter.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        /// Emitted on errors.
        pub const @"error" = struct {
            pub const name = "error";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_error: *glib.Error, p_details: ?*gst.Structure, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(PlaySignalAdapter, p_instance))),
                    gobject.signalLookup("error", PlaySignalAdapter.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        pub const media_info_updated = struct {
            pub const name = "media-info-updated";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_object: *gstplay.PlayMediaInfo, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(PlaySignalAdapter, p_instance))),
                    gobject.signalLookup("media-info-updated", PlaySignalAdapter.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        pub const mute_changed = struct {
            pub const name = "mute-changed";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_object: c_int, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(PlaySignalAdapter, p_instance))),
                    gobject.signalLookup("mute-changed", PlaySignalAdapter.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        pub const position_updated = struct {
            pub const name = "position-updated";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_object: u64, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(PlaySignalAdapter, p_instance))),
                    gobject.signalLookup("position-updated", PlaySignalAdapter.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        pub const seek_done = struct {
            pub const name = "seek-done";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_object: u64, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(PlaySignalAdapter, p_instance))),
                    gobject.signalLookup("seek-done", PlaySignalAdapter.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        pub const state_changed = struct {
            pub const name = "state-changed";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_object: gstplay.PlayState, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(PlaySignalAdapter, p_instance))),
                    gobject.signalLookup("state-changed", PlaySignalAdapter.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        pub const uri_loaded = struct {
            pub const name = "uri-loaded";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_object: [*:0]u8, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(PlaySignalAdapter, p_instance))),
                    gobject.signalLookup("uri-loaded", PlaySignalAdapter.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        pub const video_dimensions_changed = struct {
            pub const name = "video-dimensions-changed";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_object: c_uint, p_p0: c_uint, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(PlaySignalAdapter, p_instance))),
                    gobject.signalLookup("video-dimensions-changed", PlaySignalAdapter.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        pub const volume_changed = struct {
            pub const name = "volume-changed";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_object: f64, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(PlaySignalAdapter, p_instance))),
                    gobject.signalLookup("volume-changed", PlaySignalAdapter.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        /// Emitted on warnings.
        pub const warning = struct {
            pub const name = "warning";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_error: *glib.Error, p_details: ?*gst.Structure, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(PlaySignalAdapter, p_instance))),
                    gobject.signalLookup("warning", PlaySignalAdapter.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };
    };

    /// A bus-watching `glib.Source` will be created and attached to the the
    /// thread-default `glib.MainContext`. The attached callback will emit the
    /// corresponding signal for the message received. Matching signals for play
    /// messages from the bus will be emitted by it on the created adapter object.
    extern fn gst_play_signal_adapter_new(p_play: *gstplay.Play) *gstplay.PlaySignalAdapter;
    pub const new = gst_play_signal_adapter_new;

    /// Create an adapter that synchronously emits its signals, from the thread in
    /// which the messages have been posted.
    extern fn gst_play_signal_adapter_new_sync_emit(p_play: *gstplay.Play) *gstplay.PlaySignalAdapter;
    pub const newSyncEmit = gst_play_signal_adapter_new_sync_emit;

    /// A bus-watching `glib.Source` will be created and attached to the `context`. The
    /// attached callback will emit the corresponding signal for the message
    /// received. Matching signals for play messages from the bus will be emitted by
    /// it on the created adapter object.
    extern fn gst_play_signal_adapter_new_with_main_context(p_play: *gstplay.Play, p_context: *glib.MainContext) *gstplay.PlaySignalAdapter;
    pub const newWithMainContext = gst_play_signal_adapter_new_with_main_context;

    extern fn gst_play_signal_adapter_get_play(p_adapter: *PlaySignalAdapter) *gstplay.Play;
    pub const getPlay = gst_play_signal_adapter_get_play;

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

    extern fn g_object_ref(p_self: *gstplay.PlaySignalAdapter) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstplay.PlaySignalAdapter) void;
    pub const unref = g_object_unref;

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

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

/// Base structure for information concerning a media stream. Depending on
/// the stream type, one can find more media-specific information in
/// `gstplay.PlayVideoInfo`, `gstplay.PlayAudioInfo`, `gstplay.PlaySubtitleInfo`.
pub const PlayStreamInfo = opaque {
    pub const Parent = gobject.Object;
    pub const Implements = [_]type{};
    pub const Class = gstplay.PlayStreamInfoClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    extern fn gst_play_stream_info_get_caps(p_info: *const PlayStreamInfo) ?*gst.Caps;
    pub const getCaps = gst_play_stream_info_get_caps;

    /// A string describing codec used in `gstplay.PlayStreamInfo`.
    extern fn gst_play_stream_info_get_codec(p_info: *const PlayStreamInfo) ?[*:0]const u8;
    pub const getCodec = gst_play_stream_info_get_codec;

    /// Function to get stream index from `gstplay.PlayStreamInfo` instance or -1 if
    /// unknown.
    extern fn gst_play_stream_info_get_index(p_info: *const PlayStreamInfo) c_int;
    pub const getIndex = gst_play_stream_info_get_index;

    /// A string stream id identifying this `gstplay.PlayStreamInfo`.
    extern fn gst_play_stream_info_get_stream_id(p_info: *const PlayStreamInfo) [*:0]const u8;
    pub const getStreamId = gst_play_stream_info_get_stream_id;

    /// Function to return human readable name for the stream type
    /// of the given `info` (ex: "audio", "video", "subtitle")
    extern fn gst_play_stream_info_get_stream_type(p_info: *const PlayStreamInfo) [*:0]const u8;
    pub const getStreamType = gst_play_stream_info_get_stream_type;

    extern fn gst_play_stream_info_get_tags(p_info: *const PlayStreamInfo) ?*gst.TagList;
    pub const getTags = gst_play_stream_info_get_tags;

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

    extern fn g_object_ref(p_self: *gstplay.PlayStreamInfo) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstplay.PlayStreamInfo) void;
    pub const unref = g_object_unref;

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

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

/// `gstplay.PlayStreamInfo` specific to subtitle streams.
pub const PlaySubtitleInfo = opaque {
    pub const Parent = gstplay.PlayStreamInfo;
    pub const Implements = [_]type{};
    pub const Class = gstplay.PlaySubtitleInfoClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    extern fn gst_play_subtitle_info_get_language(p_info: *const PlaySubtitleInfo) ?[*:0]const u8;
    pub const getLanguage = gst_play_subtitle_info_get_language;

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

    extern fn g_object_ref(p_self: *gstplay.PlaySubtitleInfo) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstplay.PlaySubtitleInfo) void;
    pub const unref = g_object_unref;

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

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

/// `gstplay.PlayStreamInfo` specific to video streams.
pub const PlayVideoInfo = opaque {
    pub const Parent = gstplay.PlayStreamInfo;
    pub const Implements = [_]type{};
    pub const Class = gstplay.PlayVideoInfoClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    extern fn gst_play_video_info_get_bitrate(p_info: *const PlayVideoInfo) c_int;
    pub const getBitrate = gst_play_video_info_get_bitrate;

    extern fn gst_play_video_info_get_framerate(p_info: *const PlayVideoInfo, p_fps_n: *c_int, p_fps_d: *c_int) void;
    pub const getFramerate = gst_play_video_info_get_framerate;

    extern fn gst_play_video_info_get_height(p_info: *const PlayVideoInfo) c_int;
    pub const getHeight = gst_play_video_info_get_height;

    extern fn gst_play_video_info_get_max_bitrate(p_info: *const PlayVideoInfo) c_int;
    pub const getMaxBitrate = gst_play_video_info_get_max_bitrate;

    /// Returns the pixel aspect ratio in `par_n` and `par_d`
    extern fn gst_play_video_info_get_pixel_aspect_ratio(p_info: *const PlayVideoInfo, p_par_n: *c_uint, p_par_d: *c_uint) void;
    pub const getPixelAspectRatio = gst_play_video_info_get_pixel_aspect_ratio;

    extern fn gst_play_video_info_get_width(p_info: *const PlayVideoInfo) c_int;
    pub const getWidth = gst_play_video_info_get_width;

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

    extern fn g_object_ref(p_self: *gstplay.PlayVideoInfo) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstplay.PlayVideoInfo) void;
    pub const unref = g_object_unref;

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

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

pub const PlayVideoOverlayVideoRenderer = opaque {
    pub const Parent = gobject.Object;
    pub const Implements = [_]type{gstplay.PlayVideoRenderer};
    pub const Class = gstplay.PlayVideoOverlayVideoRendererClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {
        pub const video_sink = struct {
            pub const name = "video-sink";

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

        pub const window_handle = struct {
            pub const name = "window-handle";

            pub const Type = ?*anyopaque;
        };
    };

    pub const signals = struct {};

    extern fn gst_play_video_overlay_video_renderer_new(p_window_handle: ?*anyopaque) *gstplay.PlayVideoRenderer;
    pub const new = gst_play_video_overlay_video_renderer_new;

    extern fn gst_play_video_overlay_video_renderer_new_with_sink(p_window_handle: ?*anyopaque, p_video_sink: *gst.Element) *gstplay.PlayVideoRenderer;
    pub const newWithSink = gst_play_video_overlay_video_renderer_new_with_sink;

    /// Tell an overlay that it has been exposed. This will redraw the current frame
    /// in the drawable even if the pipeline is PAUSED.
    extern fn gst_play_video_overlay_video_renderer_expose(p_self: *PlayVideoOverlayVideoRenderer) void;
    pub const expose = gst_play_video_overlay_video_renderer_expose;

    /// Return the currently configured render rectangle. See `gstplay.PlayVideoOverlayVideoRenderer.setRenderRectangle`
    /// for details.
    extern fn gst_play_video_overlay_video_renderer_get_render_rectangle(p_self: *PlayVideoOverlayVideoRenderer, p_x: ?*c_int, p_y: ?*c_int, p_width: ?*c_int, p_height: ?*c_int) void;
    pub const getRenderRectangle = gst_play_video_overlay_video_renderer_get_render_rectangle;

    extern fn gst_play_video_overlay_video_renderer_get_window_handle(p_self: *PlayVideoOverlayVideoRenderer) ?*anyopaque;
    pub const getWindowHandle = gst_play_video_overlay_video_renderer_get_window_handle;

    /// Configure a subregion as a video target within the window set by
    /// `gstplay.PlayVideoOverlayVideoRenderer.setWindowHandle`. If this is not
    /// used or not supported the video will fill the area of the window set as the
    /// overlay to 100%. By specifying the rectangle, the video can be overlaid to
    /// a specific region of that window only. After setting the new rectangle one
    /// should call `gstplay.PlayVideoOverlayVideoRenderer.expose` to force a
    /// redraw. To unset the region pass -1 for the `width` and `height` parameters.
    ///
    /// This method is needed for non fullscreen video overlay in UI toolkits that
    /// do not support subwindows.
    extern fn gst_play_video_overlay_video_renderer_set_render_rectangle(p_self: *PlayVideoOverlayVideoRenderer, p_x: c_int, p_y: c_int, p_width: c_int, p_height: c_int) void;
    pub const setRenderRectangle = gst_play_video_overlay_video_renderer_set_render_rectangle;

    /// Sets the platform specific window handle into which the video
    /// should be rendered
    extern fn gst_play_video_overlay_video_renderer_set_window_handle(p_self: *PlayVideoOverlayVideoRenderer, p_window_handle: ?*anyopaque) void;
    pub const setWindowHandle = gst_play_video_overlay_video_renderer_set_window_handle;

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

    extern fn g_object_ref(p_self: *gstplay.PlayVideoOverlayVideoRenderer) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstplay.PlayVideoOverlayVideoRenderer) void;
    pub const unref = g_object_unref;

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

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

pub const PlayVideoRenderer = opaque {
    pub const Prerequisites = [_]type{gobject.Object};
    pub const Iface = gstplay.PlayVideoRendererInterface;
    pub const virtual_methods = struct {
        pub const create_video_sink = struct {
            pub fn call(p_class: anytype, p_self: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_play: *gstplay.Play) *gst.Element {
                return gobject.ext.as(PlayVideoRenderer.Iface, p_class).f_create_video_sink.?(gobject.ext.as(PlayVideoRenderer, p_self), p_play);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_self: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_play: *gstplay.Play) callconv(.c) *gst.Element) void {
                gobject.ext.as(PlayVideoRenderer.Iface, p_class).f_create_video_sink = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {};

    pub const signals = struct {};

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

    extern fn g_object_ref(p_self: *gstplay.PlayVideoRenderer) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstplay.PlayVideoRenderer) void;
    pub const unref = g_object_unref;

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

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

pub const PlayAudioInfoClass = opaque {
    pub const Instance = gstplay.PlayAudioInfo;

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

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

pub const PlayClass = opaque {
    pub const Instance = gstplay.Play;

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

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

pub const PlayMediaInfoClass = opaque {
    pub const Instance = gstplay.PlayMediaInfo;

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

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

pub const PlaySignalAdapterClass = opaque {
    pub const Instance = gstplay.PlaySignalAdapter;

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

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

pub const PlayStreamInfoClass = opaque {
    pub const Instance = gstplay.PlayStreamInfo;

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

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

pub const PlaySubtitleInfoClass = opaque {
    pub const Instance = gstplay.PlaySubtitleInfo;

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

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

pub const PlayVideoInfoClass = opaque {
    pub const Instance = gstplay.PlayVideoInfo;

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

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

pub const PlayVideoOverlayVideoRendererClass = opaque {
    pub const Instance = gstplay.PlayVideoOverlayVideoRenderer;

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

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

pub const PlayVideoRendererInterface = extern struct {
    pub const Instance = gstplay.PlayVideoRenderer;

    f_parent_iface: gobject.TypeInterface,
    f_create_video_sink: ?*const fn (p_self: *gstplay.PlayVideoRenderer, p_play: *gstplay.Play) callconv(.c) *gst.Element,

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

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

/// A `gstplay.PlayVisualization` descriptor.
pub const PlayVisualization = extern struct {
    /// name of the visualization.
    f_name: ?[*:0]u8,
    /// description of the visualization.
    f_description: ?[*:0]u8,

    /// Makes a copy of the `gstplay.PlayVisualization`. The result must be
    /// freed using `gstplay.PlayVisualization.free`.
    extern fn gst_play_visualization_copy(p_vis: *const PlayVisualization) *gstplay.PlayVisualization;
    pub const copy = gst_play_visualization_copy;

    /// Frees a `gstplay.PlayVisualization`.
    extern fn gst_play_visualization_free(p_vis: *PlayVisualization) void;
    pub const free = gst_play_visualization_free;

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

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

pub const PlayColorBalanceType = enum(c_int) {
    hue = 3,
    brightness = 0,
    saturation = 2,
    contrast = 1,
    _,

    /// Gets a string representing the given color balance type.
    extern fn gst_play_color_balance_type_get_name(p_type: gstplay.PlayColorBalanceType) [*:0]const u8;
    pub const getName = gst_play_color_balance_type_get_name;

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

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

pub const PlayError = enum(c_int) {
    failed = 0,
    _,

    /// Gets a string representing the given error.
    extern fn gst_play_error_get_name(p_error: gstplay.PlayError) [*:0]const u8;
    pub const getName = gst_play_error_get_name;

    extern fn gst_play_error_quark() glib.Quark;
    pub const quark = gst_play_error_quark;

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

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

pub const PlayMessage = enum(c_int) {
    uri_loaded = 0,
    position_updated = 1,
    duration_changed = 2,
    state_changed = 3,
    buffering = 4,
    end_of_stream = 5,
    @"error" = 6,
    warning = 7,
    video_dimensions_changed = 8,
    media_info_updated = 9,
    volume_changed = 10,
    mute_changed = 11,
    seek_done = 12,
    _,

    extern fn gst_play_message_get_name(p_message_type: gstplay.PlayMessage) [*:0]const u8;
    pub const getName = gst_play_message_get_name;

    /// Reads the stream ID the play message `msg` applies to, if any.
    extern fn gst_play_message_get_stream_id(p_msg: *gst.Message) ?[*:0]const u8;
    pub const getStreamId = gst_play_message_get_stream_id;

    /// Reads the URI the play message `msg` applies to.
    extern fn gst_play_message_get_uri(p_msg: *gst.Message) [*:0]const u8;
    pub const getUri = gst_play_message_get_uri;

    /// Parse the given buffering `msg` and extract the corresponding value
    extern fn gst_play_message_parse_buffering(p_msg: *gst.Message, p_percent: ?*c_uint) void;
    pub const parseBuffering = gst_play_message_parse_buffering;

    /// Parse the given buffering `msg` and extract the corresponding value
    extern fn gst_play_message_parse_buffering_percent(p_msg: *gst.Message, p_percent: ?*c_uint) void;
    pub const parseBufferingPercent = gst_play_message_parse_buffering_percent;

    /// Parse the given duration-changed `msg` and extract the corresponding `gst.ClockTime`
    extern fn gst_play_message_parse_duration_changed(p_msg: *gst.Message, p_duration: ?*gst.ClockTime) void;
    pub const parseDurationChanged = gst_play_message_parse_duration_changed;

    /// Parse the given duration-changed `msg` and extract the corresponding `gst.ClockTime`
    extern fn gst_play_message_parse_duration_updated(p_msg: *gst.Message, p_duration: ?*gst.ClockTime) void;
    pub const parseDurationUpdated = gst_play_message_parse_duration_updated;

    /// Parse the given error `msg` and extract the corresponding `glib.Error`.
    ///
    /// Since 1.26 the details will always contain the URI this refers to in an
    /// "uri" field of type string, and (if known) the string "stream-id" it is
    /// referring to.
    extern fn gst_play_message_parse_error(p_msg: *gst.Message, p_error: ?**glib.Error, p_details: ?**gst.Structure) void;
    pub const parseError = gst_play_message_parse_error;

    /// Parses missing plugin descriptions and installer details from a
    /// GST_PLAY_ERROR_MISSING_PLUGIN error message.
    ///
    /// Both arrays will have the same length, and strings at the same index
    /// correspond to each other.
    ///
    /// The installer details can be passed to `gstpbutils.installPluginsSync` or
    /// `gstpbutils.installPluginsAsync`.
    extern fn gst_play_message_parse_error_missing_plugin(p_msg: *gst.Message, p_descriptions: ?*[*][*:0]u8, p_installer_details: ?*[*][*:0]u8) c_int;
    pub const parseErrorMissingPlugin = gst_play_message_parse_error_missing_plugin;

    /// Parse the given media-info-updated `msg` and extract the corresponding media information
    extern fn gst_play_message_parse_media_info_updated(p_msg: *gst.Message, p_info: ?**gstplay.PlayMediaInfo) void;
    pub const parseMediaInfoUpdated = gst_play_message_parse_media_info_updated;

    /// Parse the given mute-changed `msg` and extract the corresponding audio muted state
    extern fn gst_play_message_parse_muted_changed(p_msg: *gst.Message, p_muted: ?*c_int) void;
    pub const parseMutedChanged = gst_play_message_parse_muted_changed;

    /// Parse the given position-updated `msg` and extract the corresponding `gst.ClockTime`
    extern fn gst_play_message_parse_position_updated(p_msg: *gst.Message, p_position: ?*gst.ClockTime) void;
    pub const parsePositionUpdated = gst_play_message_parse_position_updated;

    /// Parse the given seek-done `msg` and extract the corresponding `gst.ClockTime`
    extern fn gst_play_message_parse_seek_done(p_msg: *gst.Message, p_position: ?*gst.ClockTime) void;
    pub const parseSeekDone = gst_play_message_parse_seek_done;

    /// Parse the given state-changed `msg` and extract the corresponding `gstplay.PlayState`
    extern fn gst_play_message_parse_state_changed(p_msg: *gst.Message, p_state: ?*gstplay.PlayState) void;
    pub const parseStateChanged = gst_play_message_parse_state_changed;

    /// Parse the given `msg` and extract its `gstplay.PlayMessage` type.
    extern fn gst_play_message_parse_type(p_msg: *gst.Message, p_type: ?*gstplay.PlayMessage) void;
    pub const parseType = gst_play_message_parse_type;

    /// Parse the given uri-loaded `msg` and extract the corresponding value
    extern fn gst_play_message_parse_uri_loaded(p_msg: *gst.Message, p_uri: ?*[*:0]u8) void;
    pub const parseUriLoaded = gst_play_message_parse_uri_loaded;

    /// Parse the given video-dimensions-changed `msg` and extract the corresponding video dimensions
    extern fn gst_play_message_parse_video_dimensions_changed(p_msg: *gst.Message, p_width: ?*c_uint, p_height: ?*c_uint) void;
    pub const parseVideoDimensionsChanged = gst_play_message_parse_video_dimensions_changed;

    /// Parse the given volume-changed `msg` and extract the corresponding audio volume
    extern fn gst_play_message_parse_volume_changed(p_msg: *gst.Message, p_volume: ?*f64) void;
    pub const parseVolumeChanged = gst_play_message_parse_volume_changed;

    /// Parse the given warning `msg` and extract the corresponding `glib.Error`.
    ///
    /// Since 1.26 the details will always contain the URI this refers to in an
    /// "uri" field of type string, and (if known) the string "stream-id" it is
    /// referring to.
    extern fn gst_play_message_parse_warning(p_msg: *gst.Message, p_error: ?**glib.Error, p_details: ?**gst.Structure) void;
    pub const parseWarning = gst_play_message_parse_warning;

    /// Parses missing plugin descriptions and installer details from a
    /// GST_PLAY_ERROR_MISSING_PLUGIN warning message.
    ///
    /// Both arrays will have the same length, and strings at the same index
    /// correspond to each other.
    ///
    /// The installer details can be passed to `gstpbutils.installPluginsSync` or
    /// `gstpbutils.installPluginsAsync`.
    extern fn gst_play_message_parse_warning_missing_plugin(p_msg: *gst.Message, p_descriptions: ?*[*][*:0]u8, p_installer_details: ?*[*][*:0]u8) c_int;
    pub const parseWarningMissingPlugin = gst_play_message_parse_warning_missing_plugin;

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

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

pub const PlaySnapshotFormat = enum(c_int) {
    raw_native = 0,
    raw_xrgb = 1,
    raw_bgrx = 2,
    jpg = 3,
    png = 4,
    _,

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

pub const PlayState = enum(c_int) {
    stopped = 0,
    buffering = 1,
    paused = 2,
    playing = 3,
    _,

    /// Gets a string representing the given state.
    extern fn gst_play_state_get_name(p_state: gstplay.PlayState) [*:0]const u8;
    pub const getName = gst_play_state_get_name;

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

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

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