forked from AuroraMiddleware/gtk
gtk: Add GtkVideo
GtkVideo is a simple video player widget. It probably needs some more configurability, but it does its job.
This commit is contained in:
parent
9700a98f48
commit
7cf6da60da
@ -228,6 +228,7 @@
|
||||
#include <gtk/gtktypebuiltins.h>
|
||||
#include <gtk/gtktypes.h>
|
||||
#include <gtk/gtkversion.h>
|
||||
#include <gtk/gtkvideo.h>
|
||||
#include <gtk/gtkviewport.h>
|
||||
#include <gtk/gtkvolumebutton.h>
|
||||
#include <gtk/gtkwidget.h>
|
||||
|
615
gtk/gtkvideo.c
Normal file
615
gtk/gtkvideo.c
Normal file
@ -0,0 +1,615 @@
|
||||
/*
|
||||
* Copyright © 2018 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkvideo.h"
|
||||
|
||||
#include "gtkeventcontrollermotion.h"
|
||||
#include "gtkimage.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkmediacontrols.h"
|
||||
#include "gtkmediafile.h"
|
||||
#include "gtkrevealer.h"
|
||||
|
||||
/**
|
||||
* SECTION:gtkvideo
|
||||
* @title: GtkVideo
|
||||
* @short_description: A widget for displaying video
|
||||
*
|
||||
* GtkVideo is a widget to show a #GtkMediaStream.
|
||||
*/
|
||||
|
||||
struct _GtkVideo
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GFile *file;
|
||||
GtkMediaStream *media_stream;
|
||||
|
||||
GtkEventController *motion_controller;
|
||||
|
||||
GtkWidget *box;
|
||||
GtkWidget *video_image;
|
||||
GtkWidget *overlay_icon;
|
||||
GtkWidget *controls_revealer;
|
||||
GtkWidget *controls;
|
||||
guint controls_hide_source;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_FILE,
|
||||
PROP_MEDIA_STREAM,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkVideo, gtk_video, GTK_TYPE_WIDGET)
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
gtk_video_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
GtkVideo *self = GTK_VIDEO (widget);
|
||||
|
||||
gtk_widget_measure (self->box,
|
||||
orientation,
|
||||
for_size,
|
||||
minimum, natural,
|
||||
minimum_baseline, natural_baseline);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_video_size_allocate (GtkWidget *widget,
|
||||
const GtkAllocation *allocation,
|
||||
int baseline,
|
||||
GtkAllocation *out_clip)
|
||||
{
|
||||
GtkVideo *self = GTK_VIDEO (widget);
|
||||
|
||||
gtk_widget_size_allocate (self->box, allocation, baseline, out_clip);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_video_unmap (GtkWidget *widget)
|
||||
{
|
||||
GtkVideo *self = GTK_VIDEO (widget);
|
||||
|
||||
if (self->controls_hide_source)
|
||||
{
|
||||
g_source_remove (self->controls_hide_source);
|
||||
self->controls_hide_source = 0;
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (self->controls_revealer), FALSE);
|
||||
}
|
||||
|
||||
/* XXX: pause video here? */
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_video_parent_class)->unmap (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_video_dispose (GObject *object)
|
||||
{
|
||||
GtkVideo *self = GTK_VIDEO (object);
|
||||
|
||||
gtk_video_set_media_stream (self, NULL);
|
||||
|
||||
g_clear_object (&self->motion_controller);
|
||||
g_clear_pointer (&self->box, gtk_widget_unparent);
|
||||
|
||||
G_OBJECT_CLASS (gtk_video_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_video_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkVideo *self = GTK_VIDEO (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FILE:
|
||||
g_value_set_object (value, self->file);
|
||||
break;
|
||||
|
||||
case PROP_MEDIA_STREAM:
|
||||
g_value_set_object (value, self->media_stream);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_video_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkVideo *self = GTK_VIDEO (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FILE:
|
||||
gtk_video_set_file (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_MEDIA_STREAM:
|
||||
gtk_video_set_media_stream (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_video_class_init (GtkVideoClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
widget_class->measure = gtk_video_measure;
|
||||
widget_class->size_allocate = gtk_video_size_allocate;
|
||||
widget_class->unmap = gtk_video_unmap;
|
||||
|
||||
gobject_class->dispose = gtk_video_dispose;
|
||||
gobject_class->get_property = gtk_video_get_property;
|
||||
gobject_class->set_property = gtk_video_set_property;
|
||||
|
||||
/**
|
||||
* GtkVideo:file:
|
||||
*
|
||||
* The file played by this video if the video is playing a file.
|
||||
*/
|
||||
properties[PROP_FILE] =
|
||||
g_param_spec_object ("file",
|
||||
P_("File"),
|
||||
P_("The video file played back"),
|
||||
G_TYPE_FILE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GtkVideo:media-stream:
|
||||
*
|
||||
* The media-stream played
|
||||
*/
|
||||
properties[PROP_MEDIA_STREAM] =
|
||||
g_param_spec_object ("media-stream",
|
||||
P_("Media Stream"),
|
||||
P_("The media stream played"),
|
||||
GTK_TYPE_MEDIA_STREAM,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/ui/gtkvideo.ui");
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkVideo, box);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkVideo, video_image);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkVideo, overlay_icon);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkVideo, controls);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkVideo, controls_revealer);
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, I_("video"));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_video_hide_controls (gpointer data)
|
||||
{
|
||||
GtkVideo *self = data;
|
||||
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (self->controls_revealer), FALSE);
|
||||
|
||||
self->controls_hide_source = 0;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_video_motion (GtkEventControllerMotion *motion,
|
||||
double x,
|
||||
double y,
|
||||
GtkVideo *self)
|
||||
{
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (self->controls_revealer), TRUE);
|
||||
if (self->controls_hide_source)
|
||||
g_source_remove (self->controls_hide_source);
|
||||
self->controls_hide_source = g_timeout_add (5 * 1000,
|
||||
gtk_video_hide_controls,
|
||||
self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_video_init (GtkVideo *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
|
||||
|
||||
self->motion_controller = gtk_event_controller_motion_new (GTK_WIDGET (self));
|
||||
g_signal_connect (self->motion_controller, "motion", G_CALLBACK (gtk_video_motion), self);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_video_new:
|
||||
*
|
||||
* Creates a new empty #GtkVideo.
|
||||
*
|
||||
* Returns: a new #GtkVideo
|
||||
**/
|
||||
GtkWidget *
|
||||
gtk_video_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_VIDEO, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_video_new_for_media_stream:
|
||||
* @stream: (allow-none): a #GtkMediaStream
|
||||
*
|
||||
* Creates a #GtkVideo to play back the given @stream.
|
||||
*
|
||||
* Returns: a new #GtkVideo
|
||||
**/
|
||||
GtkWidget *
|
||||
gtk_video_new_for_media_stream (GtkMediaStream *stream)
|
||||
{
|
||||
g_return_val_if_fail (stream == NULL || GTK_IS_MEDIA_STREAM (stream), NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_VIDEO,
|
||||
"media-stream", stream,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_video_new_for_file:
|
||||
* @file: (allow-none): a #GFile
|
||||
*
|
||||
* Creates a #GtkVideo to play back the given @file.
|
||||
*
|
||||
* Returns: a new #GtkVideo
|
||||
**/
|
||||
GtkWidget *
|
||||
gtk_video_new_for_file (GFile *file)
|
||||
{
|
||||
g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_VIDEO,
|
||||
"file", file,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_video_new_for_filename:
|
||||
* @filename: (allow-none): filename to play back
|
||||
*
|
||||
* Creates a #GtkVideo to play back the given @filename.
|
||||
*
|
||||
* This is a utility function that calls gtk_video_new_for_file(),
|
||||
*
|
||||
* Returns: a new #GtkVideo
|
||||
**/
|
||||
GtkWidget *
|
||||
gtk_video_new_for_filename (const char *filename)
|
||||
{
|
||||
GtkWidget *result;
|
||||
GFile *file;
|
||||
|
||||
if (filename)
|
||||
file = g_file_new_for_path (filename);
|
||||
else
|
||||
file = NULL;
|
||||
|
||||
result = gtk_video_new_for_file (file);
|
||||
|
||||
if (file)
|
||||
g_object_unref (file);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_video_new_for_resource:
|
||||
* @filename: (allow-none): resource path to play back
|
||||
*
|
||||
* Creates a #GtkVideo to play back the resource at the
|
||||
* given @resource_path.
|
||||
*
|
||||
* This is a utility function that calls gtk_video_new_for_file(),
|
||||
*
|
||||
* Returns: a new #GtkVideo
|
||||
**/
|
||||
GtkWidget *
|
||||
gtk_video_new_for_resource (const char *resource_path)
|
||||
{
|
||||
GtkWidget *result;
|
||||
GFile *file;
|
||||
|
||||
if (resource_path)
|
||||
{
|
||||
char *uri, *escaped;
|
||||
|
||||
escaped = g_uri_escape_string (resource_path,
|
||||
G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
|
||||
uri = g_strconcat ("resource://", escaped, NULL);
|
||||
g_free (escaped);
|
||||
|
||||
file = g_file_new_for_uri (uri);
|
||||
g_free (uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
result = gtk_video_new_for_file (file);
|
||||
|
||||
if (file)
|
||||
g_object_unref (file);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_video_get_media_stream:
|
||||
* @self: a #GtkVideo
|
||||
*
|
||||
* Gets the media stream managed by @self or %NULL if none.
|
||||
*
|
||||
* Returns: (nullable): The media stream managed by @self
|
||||
**/
|
||||
GtkMediaStream *
|
||||
gtk_video_get_media_stream (GtkVideo *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_VIDEO (self), NULL);
|
||||
|
||||
return self->media_stream;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_video_update_overlay_icon (GtkVideo *self)
|
||||
{
|
||||
const char *icon_name;
|
||||
const GError *error = NULL;
|
||||
|
||||
if (self->media_stream == NULL)
|
||||
icon_name = "media-eject-symbolic";
|
||||
else if ((error = gtk_media_stream_get_error (self->media_stream)))
|
||||
icon_name = "dialog-error-symbolic";
|
||||
else if (gtk_media_stream_get_ended (self->media_stream))
|
||||
icon_name = "media-playlist-repeat-symbolic";
|
||||
else
|
||||
icon_name = "media-playback-start-symbolic";
|
||||
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (self->overlay_icon), icon_name);
|
||||
if (error)
|
||||
gtk_widget_set_tooltip_text (self->overlay_icon, error->message);
|
||||
else
|
||||
gtk_widget_set_tooltip_text (self->overlay_icon, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_video_update_ended (GtkVideo *self)
|
||||
{
|
||||
gtk_video_update_overlay_icon (self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_video_update_error (GtkVideo *self)
|
||||
{
|
||||
gtk_video_update_overlay_icon (self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_video_update_playing (GtkVideo *self)
|
||||
{
|
||||
gboolean playing;
|
||||
|
||||
if (self->media_stream != NULL)
|
||||
playing = gtk_media_stream_get_playing (self->media_stream);
|
||||
else
|
||||
playing = FALSE;
|
||||
|
||||
gtk_widget_set_visible (self->overlay_icon, !playing);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_video_update_all (GtkVideo *self)
|
||||
{
|
||||
gtk_video_update_ended (self);
|
||||
gtk_video_update_error (self);
|
||||
gtk_video_update_playing (self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_video_notify_cb (GtkMediaStream *stream,
|
||||
GParamSpec *pspec,
|
||||
GtkVideo *self)
|
||||
{
|
||||
if (g_str_equal (pspec->name, "ended"))
|
||||
gtk_video_update_ended (self);
|
||||
if (g_str_equal (pspec->name, "error"))
|
||||
gtk_video_update_error (self);
|
||||
if (g_str_equal (pspec->name, "playing"))
|
||||
gtk_video_update_playing (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_video_set_media_stream:
|
||||
* @self: a #GtkVideo
|
||||
* @stream: (allow-none): The media stream to play or %NULL to unset
|
||||
*
|
||||
* Sets the media stream to be played back. @self will take full control
|
||||
* of managing the media stream. If you want to manage a media stream
|
||||
* yourself, consider using a #GtkImage for display.
|
||||
*
|
||||
* If you want to display a file, consider using gtk_video_set_file()
|
||||
* instead.
|
||||
**/
|
||||
void
|
||||
gtk_video_set_media_stream (GtkVideo *self,
|
||||
GtkMediaStream *stream)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_VIDEO (self));
|
||||
g_return_if_fail (stream == NULL || GTK_IS_MEDIA_STREAM (stream));
|
||||
|
||||
if (self->media_stream == stream)
|
||||
return;
|
||||
|
||||
if (self->media_stream)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (self->media_stream,
|
||||
gtk_video_notify_cb,
|
||||
self);
|
||||
g_object_unref (self->media_stream);
|
||||
self->media_stream = NULL;
|
||||
}
|
||||
|
||||
if (stream)
|
||||
{
|
||||
self->media_stream = g_object_ref (stream);
|
||||
g_signal_connect (self->media_stream,
|
||||
"notify",
|
||||
G_CALLBACK (gtk_video_notify_cb),
|
||||
self);
|
||||
}
|
||||
|
||||
gtk_media_controls_set_media_stream (GTK_MEDIA_CONTROLS (self->controls), stream);
|
||||
gtk_image_set_from_paintable (GTK_IMAGE (self->video_image), GDK_PAINTABLE (stream));
|
||||
|
||||
gtk_video_update_all (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MEDIA_STREAM]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_video_set_file:
|
||||
* @self: a #GtkVideo
|
||||
* @file: (allow-none): the file to play
|
||||
*
|
||||
* Makes @self play the given @file.
|
||||
**/
|
||||
void
|
||||
gtk_video_set_file (GtkVideo *self,
|
||||
GFile *file)
|
||||
{
|
||||
GtkMediaStream *stream;
|
||||
|
||||
g_return_if_fail (GTK_IS_VIDEO (self));
|
||||
g_return_if_fail (file == NULL || G_IS_FILE (file));
|
||||
|
||||
if (!g_set_object (&self->file, file))
|
||||
return;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
if (file)
|
||||
stream = gtk_media_file_new_for_file (file);
|
||||
else
|
||||
stream = NULL;
|
||||
|
||||
gtk_video_set_media_stream (self, stream);
|
||||
|
||||
if (stream)
|
||||
g_object_unref (stream);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_video_set_resource:
|
||||
* @self: a #GtkVideo
|
||||
* @filename: (allow-none): the filename to play
|
||||
*
|
||||
* Makes @self play the given @filename.
|
||||
*
|
||||
* This is a utility function that calls gtk_video_set_file(),
|
||||
**/
|
||||
void
|
||||
gtk_video_set_filename (GtkVideo *self,
|
||||
const char *filename)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
g_return_if_fail (GTK_IS_VIDEO (self));
|
||||
|
||||
if (filename)
|
||||
file = g_file_new_for_path (filename);
|
||||
else
|
||||
file = NULL;
|
||||
|
||||
gtk_video_set_file (self, file);
|
||||
|
||||
if (file)
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_video_set_resource:
|
||||
* @self: a #GtkVideo
|
||||
* @resource_path: (allow-none): the resource to set
|
||||
*
|
||||
* Makes @self play the resource at the given @resource_path.
|
||||
*
|
||||
* This is a utility function that calls gtk_video_set_file(),
|
||||
**/
|
||||
void
|
||||
gtk_video_set_resource (GtkVideo *self,
|
||||
const char *resource_path)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
g_return_if_fail (GTK_IS_VIDEO (self));
|
||||
|
||||
if (resource_path)
|
||||
{
|
||||
char *uri, *escaped;
|
||||
|
||||
escaped = g_uri_escape_string (resource_path,
|
||||
G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
|
||||
uri = g_strconcat ("resource://", escaped, NULL);
|
||||
g_free (escaped);
|
||||
|
||||
file = g_file_new_for_uri (uri);
|
||||
g_free (uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
gtk_video_set_file (self, file);
|
||||
|
||||
if (file)
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
64
gtk/gtkvideo.h
Normal file
64
gtk/gtkvideo.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright © 2018 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_VIDEO_H__
|
||||
#define __GTK_VIDEO_H__
|
||||
|
||||
#include <gtk/gtkmediastream.h>
|
||||
#include <gtk/gtkwidget.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_VIDEO (gtk_video_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkVideo, gtk_video, GTK, VIDEO, GtkWidget)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_video_new (void);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_video_new_for_media_stream (GtkMediaStream *stream);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_video_new_for_file (GFile *file);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_video_new_for_filename (const char *filename);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_video_new_for_resource (const char *resource_path);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkMediaStream *gtk_video_get_media_stream (GtkVideo *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_video_set_media_stream (GtkVideo *self,
|
||||
GtkMediaStream *stream);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GFile * gtk_video_get_file (GtkVideo *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_video_set_file (GtkVideo *self,
|
||||
GFile *file);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_video_set_filename (GtkVideo *self,
|
||||
const char *filename);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_video_set_resource (GtkVideo *self,
|
||||
const char *resource_path);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_VIDEO_H__ */
|
@ -358,6 +358,7 @@ gtk_public_sources = files([
|
||||
'gtktreeview.c',
|
||||
'gtktreeviewcolumn.c',
|
||||
'gtkutils.c',
|
||||
'gtkvideo.c',
|
||||
'gtkviewport.c',
|
||||
'gtkvolumebutton.c',
|
||||
'gtkwidget.c',
|
||||
@ -573,6 +574,7 @@ gtk_public_headers = files([
|
||||
'gtktreeview.h',
|
||||
'gtktreeviewcolumn.h',
|
||||
'gtktypes.h',
|
||||
'gtkvideo.h',
|
||||
'gtkviewport.h',
|
||||
'gtkvolumebutton.h',
|
||||
'gtkwidget.h',
|
||||
|
@ -3998,6 +3998,19 @@ paned {
|
||||
}
|
||||
|
||||
|
||||
/**************
|
||||
* GtkVideo *
|
||||
**************/
|
||||
|
||||
video {
|
||||
& image.osd {
|
||||
min-width: 64px;
|
||||
min-height: 64px;
|
||||
border-radius: 32px;
|
||||
}
|
||||
background: black;
|
||||
}
|
||||
|
||||
/**************
|
||||
* GtkInfoBar *
|
||||
**************/
|
||||
|
47
gtk/ui/gtkvideo.ui
Normal file
47
gtk/ui/gtkvideo.ui
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="gtk40">
|
||||
<!-- interface-requires gtk+ 3.6 -->
|
||||
<template class="GtkVideo" parent="GtkWidget">
|
||||
<child>
|
||||
<object class="GtkOverlay" id="box">
|
||||
<child>
|
||||
<object class="GtkImage" id="video_image">
|
||||
<property name="can-shrink">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="overlay">
|
||||
<object class="GtkImage" id="overlay_icon">
|
||||
<style>
|
||||
<class name="osd"/>
|
||||
<class name="circular"/>
|
||||
</style>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="icon-name">media-playback-start-symbolic</property>
|
||||
<property name="icon-size">large</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="measure">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="overlay">
|
||||
<object class="GtkRevealer" id="controls_revealer">
|
||||
<property name="reveal-child">0</property>
|
||||
<property name="valign">end</property>
|
||||
<child>
|
||||
<object class="GtkMediaControls" id="controls">
|
||||
<style>
|
||||
<class name="osd"/>
|
||||
<class name="bottom"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="measure">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
Loading…
Reference in New Issue
Block a user