diff options
author | Benjamin Otte <otte@redhat.com> | 2018-03-18 03:20:02 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2018-03-18 21:01:23 +0100 |
commit | 04a3b8b6df1d3b58e9187e11c7e77ad259ad9eec (patch) | |
tree | daeac1b4fb0251fc2de3bea6a4335273342f0eba | |
parent | 09a21f1cd26d331a43a03a9baa1b8912cbb1b282 (diff) | |
download | gtk+-04a3b8b6df1d3b58e9187e11c7e77ad259ad9eec.tar.gz |
mediastream: Add gtk_media_stream_realize/unrealize()
This allows widget to attach their streams to GdkWindow(s)
The idea is to allow attaching a stream to windowing system(s) so the
stream can make use of its resources, in particular GL contexts.
I am however unsure what to attach to:
- GtkWindow
- GdkWindow
- GtkWidget
- GskRenderer
Each of these provide advantages and disadvantages.
So I'm very much open to better suggestions.
-rw-r--r-- | gtk/gtkmediastream.c | 68 | ||||
-rw-r--r-- | gtk/gtkmediastream.h | 11 | ||||
-rw-r--r-- | gtk/gtkvideo.c | 52 |
3 files changed, 123 insertions, 8 deletions
diff --git a/gtk/gtkmediastream.c b/gtk/gtkmediastream.c index aadec85622..0688ed199c 100644 --- a/gtk/gtkmediastream.c +++ b/gtk/gtkmediastream.c @@ -128,6 +128,18 @@ gtk_media_stream_default_update_audio (GtkMediaStream *self, } static void +gtk_media_stream_default_realize (GtkMediaStream *self, + GdkWindow *window) +{ +} + +static void +gtk_media_stream_default_unrealize (GtkMediaStream *self, + GdkWindow *window) +{ +} + +static void gtk_media_stream_set_property (GObject *object, guint prop_id, const GValue *value, @@ -260,6 +272,8 @@ gtk_media_stream_class_init (GtkMediaStreamClass *class) class->pause = gtk_media_stream_default_pause; class->seek = gtk_media_stream_default_seek; class->update_audio = gtk_media_stream_default_update_audio; + class->realize = gtk_media_stream_default_realize; + class->unrealize = gtk_media_stream_default_unrealize; gobject_class->set_property = gtk_media_stream_set_property; gobject_class->get_property = gtk_media_stream_get_property; @@ -840,6 +854,60 @@ gtk_media_stream_set_volume (GtkMediaStream *self, } /** + * gtk_media_stream_realize: + * @self: a #GtkMediaStream + * @window: a #GdkWindow + * + * Called by users to attach the media stream to a #GdkWindow they manage. + * The stream can then access the resources of @window for its rendering + * purposes. In particular, media streams might want to create + * #GdkGLContexts or sync to the #GdkFrameClock. + * + * Whoever calls this function is responsible for calling + * gtk_media_stream_unrealize() before either the stream or @window get + * destroyed. + * + * Multiple calls to this function may happen from different users of the + * video, even with the same @window. Each of these calls must be followed + * by its own call to gtk_media_stream_unrealize(). + * + * It is not required to call this function to make a media stream work. + **/ +void +gtk_media_stream_realize (GtkMediaStream *self, + GdkWindow *window) +{ + g_return_if_fail (GTK_IS_MEDIA_STREAM (self)); + g_return_if_fail (GDK_IS_WINDOW (window)); + + g_object_ref (self); + g_object_ref (window); + + GTK_MEDIA_STREAM_GET_CLASS (self)->realize (self, window); +} + +/** + * gtk_media_stream_unrealize: + * @self: a #GtkMediaStream previously realized + * @window: the #GdkWindow the stream was realized with + * + * Undoes a previous call to gtk_media_stream_realize() and causes + * the stream to release all resources it had allocated from @window. + **/ +void +gtk_media_stream_unrealize (GtkMediaStream *self, + GdkWindow *window) +{ + g_return_if_fail (GTK_IS_MEDIA_STREAM (self)); + g_return_if_fail (GDK_IS_WINDOW (window)); + + GTK_MEDIA_STREAM_GET_CLASS (self)->unrealize (self, window); + + g_object_unref (window); + g_object_unref (self); +} + +/** * gtk_media_stream_prepared: * @self: a #GtkMediaStream * @has_audio: %TRUE if the stream should advertise audio support diff --git a/gtk/gtkmediastream.h b/gtk/gtkmediastream.h index 3029696518..a04fafd8fa 100644 --- a/gtk/gtkmediastream.h +++ b/gtk/gtkmediastream.h @@ -44,6 +44,11 @@ struct _GtkMediaStreamClass void (* update_audio) (GtkMediaStream *self, gboolean muted, double volume); + void (* realize) (GtkMediaStream *self, + GdkWindow *window); + void (* unrealize) (GtkMediaStream *self, + GdkWindow *window); + /* Padding for future expansion */ void (*_gtk_reserved1) (void); void (*_gtk_reserved2) (void); @@ -103,6 +108,12 @@ double gtk_media_stream_get_volume (GtkMediaStream GDK_AVAILABLE_IN_ALL void gtk_media_stream_set_volume (GtkMediaStream *self, double volume); +GDK_AVAILABLE_IN_ALL +void gtk_media_stream_realize (GtkMediaStream *self, + GdkWindow *window); +GDK_AVAILABLE_IN_ALL +void gtk_media_stream_unrealize (GtkMediaStream *self, + GdkWindow *window); /* for implementations only */ GDK_AVAILABLE_IN_ALL diff --git a/gtk/gtkvideo.c b/gtk/gtkvideo.c index bf51a236f8..755acdde98 100644 --- a/gtk/gtkvideo.c +++ b/gtk/gtkvideo.c @@ -96,6 +96,31 @@ gtk_video_size_allocate (GtkWidget *widget, } static void +gtk_video_realize (GtkWidget *widget) +{ + GtkVideo *self = GTK_VIDEO (widget); + + GTK_WIDGET_CLASS (gtk_video_parent_class)->realize (widget); + + if (self->media_stream) + gtk_media_stream_realize (self->media_stream, gtk_widget_get_window (GTK_WIDGET (self))); + + if (self->file) + gtk_media_file_set_file (GTK_MEDIA_FILE (self->media_stream), self->file); +} + +static void +gtk_video_unrealize (GtkWidget *widget) +{ + GtkVideo *self = GTK_VIDEO (widget); + + if (self->media_stream) + gtk_media_stream_unrealize (self->media_stream, gtk_widget_get_window (GTK_WIDGET (self))); + + GTK_WIDGET_CLASS (gtk_video_parent_class)->unrealize (widget); +} + +static void gtk_video_unmap (GtkWidget *widget) { GtkVideo *self = GTK_VIDEO (widget); @@ -181,6 +206,8 @@ gtk_video_class_init (GtkVideoClass *klass) widget_class->measure = gtk_video_measure; widget_class->size_allocate = gtk_video_size_allocate; + widget_class->realize = gtk_video_realize; + widget_class->unrealize = gtk_video_unrealize; widget_class->unmap = gtk_video_unmap; gobject_class->dispose = gtk_video_dispose; @@ -490,6 +517,8 @@ gtk_video_set_media_stream (GtkVideo *self, g_signal_handlers_disconnect_by_func (self->media_stream, gtk_video_notify_cb, self); + if (gtk_widget_get_realized (GTK_WIDGET (self))) + gtk_media_stream_unrealize (self->media_stream, gtk_widget_get_window (GTK_WIDGET (self))); g_object_unref (self->media_stream); self->media_stream = NULL; } @@ -497,6 +526,8 @@ gtk_video_set_media_stream (GtkVideo *self, if (stream) { self->media_stream = g_object_ref (stream); + if (gtk_widget_get_realized (GTK_WIDGET (self))) + gtk_media_stream_realize (stream, gtk_widget_get_window (GTK_WIDGET (self))); g_signal_connect (self->media_stream, "notify", G_CALLBACK (gtk_video_notify_cb), @@ -522,8 +553,6 @@ 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)); @@ -533,14 +562,21 @@ gtk_video_set_file (GtkVideo *self, g_object_freeze_notify (G_OBJECT (self)); if (file) - stream = gtk_media_file_new_for_file (file); - else - stream = NULL; + { + GtkMediaStream *stream; - gtk_video_set_media_stream (self, stream); + stream = gtk_media_file_new (); - if (stream) - g_object_unref (stream); + gtk_video_set_media_stream (self, stream); + if (gtk_widget_get_realized (GTK_WIDGET (self))) + gtk_media_file_set_file (GTK_MEDIA_FILE (stream), file); + + g_object_unref (stream); + } + else + { + gtk_video_set_media_stream (self, NULL); + } g_object_thaw_notify (G_OBJECT (self)); } |