From 4301a9a9fa170a645614f853f87f4731553b88e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Fri, 1 Aug 2025 16:17:27 +0200 Subject: [PATCH 1/8] clapper-gtk: video: Split code into subclass Create a base class called "ClapperGtkAv" and subclass it into "ClapperGtkVideo". This allows to have player and session inhibit logic in base class and share it with other subclassed widgets. --- src/lib/clapper-gtk/clapper-gtk-av.c | 645 ++++++++++++++++++++ src/lib/clapper-gtk/clapper-gtk-av.h | 60 ++ src/lib/clapper-gtk/clapper-gtk-utils.c | 14 +- src/lib/clapper-gtk/clapper-gtk-video.c | 379 ++---------- src/lib/clapper-gtk/clapper-gtk-video.h | 11 +- src/lib/clapper-gtk/clapper-gtk.h | 1 + src/lib/clapper-gtk/meson.build | 2 + src/lib/clapper-gtk/ui/clapper-gtk-video.ui | 2 +- 8 files changed, 788 insertions(+), 326 deletions(-) create mode 100644 src/lib/clapper-gtk/clapper-gtk-av.c create mode 100644 src/lib/clapper-gtk/clapper-gtk-av.h diff --git a/src/lib/clapper-gtk/clapper-gtk-av.c b/src/lib/clapper-gtk/clapper-gtk-av.c new file mode 100644 index 00000000..63471542 --- /dev/null +++ b/src/lib/clapper-gtk/clapper-gtk-av.c @@ -0,0 +1,645 @@ +/* Clapper GTK Integration Library + * Copyright (C) 2025 Rafał Dzięgiel + * + * 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 + * . + */ + +/** + * ClapperGtkAv: + * + * A base class for GTK audio and video widgets. + * + * See [class@ClapperGtk.Video]. + * + * # Actions + * + * #ClapperGtkAv defines a set of built-in actions: + * + * ```yaml + * - "av.toggle-play": toggle play/pause + * - "av.play": start/resume playback + * - "av.pause": pause playback + * - "av.stop": stop playback + * - "av.seek": seek to position (variant "d") + * - "av.seek-custom": seek to position using seek method (variant "(di)") + * - "av.toggle-mute": toggle mute state + * - "av.set-mute": set mute state (variant "b") + * - "av.volume-up": increase volume by 2% + * - "av.volume-down": decrease volume by 2% + * - "av.set-volume": set volume to specified value (variant "d") + * - "av.speed-up": increase speed (from 0.05x - 2x range to nearest quarter) + * - "av.speed-down": decrease speed (from 0.05x - 2x range to nearest quarter) + * - "av.set-speed": set speed to specified value (variant "d") + * - "av.previous-item": select previous item in queue + * - "av.next-item": select next item in queue + * - "av.select-item": select item at specified index in queue (variant "u") + * ``` + * + * Since: 0.10 + */ + +#include "config.h" + +#include + +#include "clapper-gtk-av.h" + +#define PERCENTAGE_ROUND(a) (round ((gdouble) a / 0.01) * 0.01) + +#define DEFAULT_AUTO_INHIBIT FALSE + +#define GST_CAT_DEFAULT clapper_gtk_av_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +typedef struct _ClapperGtkAvPrivate ClapperGtkAvPrivate; + +struct _ClapperGtkAvPrivate +{ + ClapperPlayer *player; + gboolean auto_inhibit; + + guint inhibit_cookie; +}; + +#define parent_class clapper_gtk_av_parent_class +G_DEFINE_TYPE_WITH_PRIVATE (ClapperGtkAv, clapper_gtk_av, GTK_TYPE_WIDGET) + +enum +{ + PROP_0, + PROP_PLAYER, + PROP_AUTO_INHIBIT, + PROP_INHIBITED, + PROP_LAST +}; + +static gboolean provider_added = FALSE; +static GParamSpec *param_specs[PROP_LAST] = { NULL, }; + +static void +toggle_play_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + + switch (clapper_player_get_state (player)) { + case CLAPPER_PLAYER_STATE_PLAYING: + clapper_player_pause (player); + break; + case CLAPPER_PLAYER_STATE_STOPPED: + case CLAPPER_PLAYER_STATE_PAUSED: + clapper_player_play (player); + break; + default: + break; + } +} + +static void +play_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + + clapper_player_play (player); +} + +static void +pause_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + + clapper_player_pause (player); +} + +static void +stop_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + + clapper_player_stop (player); +} + +static void +seek_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + gdouble position = g_variant_get_double (parameter); + + clapper_player_seek (player, position); +} + +static void +seek_custom_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + ClapperPlayerSeekMethod method = CLAPPER_PLAYER_SEEK_METHOD_NORMAL; + gdouble position = 0; + + g_variant_get (parameter, "(di)", &position, &method); + clapper_player_seek_custom (player, position, method); +} + +static void +toggle_mute_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + + clapper_player_set_mute (player, !clapper_player_get_mute (player)); +} + +static void +set_mute_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + gboolean mute = g_variant_get_boolean (parameter); + + clapper_player_set_mute (player, mute); +} + +static void +volume_up_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + gdouble volume = (clapper_player_get_volume (player) + 0.02); + + if (volume > 2.0) + volume = 2.0; + + clapper_player_set_volume (player, PERCENTAGE_ROUND (volume)); +} + +static void +volume_down_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + gdouble volume = (clapper_player_get_volume (player) - 0.02); + + if (volume < 0) + volume = 0; + + clapper_player_set_volume (player, PERCENTAGE_ROUND (volume)); +} + +static void +set_volume_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + gdouble volume = g_variant_get_double (parameter); + + clapper_player_set_volume (player, volume); +} + +static void +speed_up_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + gdouble dest, speed = clapper_player_get_speed (player); + + if (speed >= 2.0) + return; + + dest = 0.25; + while (speed >= dest) + dest += 0.25; + + if (dest > 2.0) + dest = 2.0; + + clapper_player_set_speed (player, dest); +} + +static void +speed_down_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + gdouble dest, speed = clapper_player_get_speed (player); + + if (speed <= 0.05) + return; + + dest = 2.0; + while (speed <= dest) + dest -= 0.25; + + if (dest < 0.05) + dest = 0.05; + + clapper_player_set_speed (player, dest); +} + +static void +set_speed_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + gdouble speed = g_variant_get_double (parameter); + + clapper_player_set_speed (player, speed); +} + +static void +previous_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + + clapper_queue_select_previous_item (clapper_player_get_queue (player)); +} + +static void +next_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + + clapper_queue_select_next_item (clapper_player_get_queue (player)); +} + +static void +select_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperPlayer *player = clapper_gtk_av_get_player (self); + guint index = g_variant_get_uint32 (parameter); + + clapper_queue_select_index (clapper_player_get_queue (player), index); +} + +static void +_ensure_css_provider (void) +{ + GdkDisplay *display; + + if (provider_added) + return; + + display = gdk_display_get_default (); + + if (G_LIKELY (display != NULL)) { + GtkCssProvider *provider = gtk_css_provider_new (); + gtk_css_provider_load_from_resource (provider, + CLAPPER_GTK_RESOURCE_PREFIX "/css/styles.css"); + + gtk_style_context_add_provider_for_display (display, + (GtkStyleProvider *) provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION - 1); + g_object_unref (provider); + + provider_added = TRUE; + } +} + +static inline void +_set_inhibit_session (ClapperGtkAv *self, gboolean inhibit) +{ + ClapperGtkAvPrivate *priv = clapper_gtk_av_get_instance_private (self); + GtkRoot *root; + GApplication *app; + gboolean inhibited = (priv->inhibit_cookie != 0); + + if (inhibited == inhibit) + return; + + GST_DEBUG_OBJECT (self, "Trying to %sinhibit session...", (inhibit) ? "" : "un"); + + root = gtk_widget_get_root (GTK_WIDGET (self)); + + if (!root && !GTK_IS_WINDOW (root)) { + GST_WARNING_OBJECT (self, "Cannot %sinhibit session " + "without root window", (inhibit) ? "" : "un"); + return; + } + + /* NOTE: Not using application from window prop, + * as it goes away early when unrooting */ + app = g_application_get_default (); + + if (!app && !GTK_IS_APPLICATION (app)) { + GST_WARNING_OBJECT (self, "Cannot %sinhibit session " + "without window application set", (inhibit) ? "" : "un"); + return; + } + + if (inhibited) { + gtk_application_uninhibit (GTK_APPLICATION (app), priv->inhibit_cookie); + priv->inhibit_cookie = 0; + } + if (inhibit) { + priv->inhibit_cookie = gtk_application_inhibit (GTK_APPLICATION (app), + GTK_WINDOW (root), GTK_APPLICATION_INHIBIT_IDLE, + "Media is playing"); + } + + GST_DEBUG_OBJECT (self, "Session %sinhibited", (inhibit) ? "" : "un"); + g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_INHIBITED]); +} + +static void +_player_state_changed_cb (ClapperPlayer *player, + GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkAv *self) +{ + ClapperGtkAvPrivate *priv = clapper_gtk_av_get_instance_private (self); + + if (priv->auto_inhibit) { + ClapperPlayerState state = clapper_player_get_state (player); + _set_inhibit_session (self, state == CLAPPER_PLAYER_STATE_PLAYING); + } +} + +/** + * clapper_gtk_av_get_player: + * @av: a #ClapperGtkAv + * + * Get #ClapperPlayer used by this #ClapperGtkAv instance. + * + * Returns: (transfer none): a #ClapperPlayer used by widget. + * + * Since: 0.10 + */ +ClapperPlayer * +clapper_gtk_av_get_player (ClapperGtkAv *self) +{ + ClapperGtkAvPrivate *priv; + + g_return_val_if_fail (CLAPPER_GTK_IS_AV (self), NULL); + + priv = clapper_gtk_av_get_instance_private (self); + + return priv->player; +} + +/** + * clapper_gtk_av_set_auto_inhibit: + * @av: a #ClapperGtkAv + * @inhibit: whether to enable automatic session inhibit + * + * Set whether widget should try to automatically inhibit session + * from idling (and possibly screen going black) when media is playing. + * + * Since: 0.10 + */ +void +clapper_gtk_av_set_auto_inhibit (ClapperGtkAv *self, gboolean inhibit) +{ + ClapperGtkAvPrivate *priv; + + g_return_if_fail (CLAPPER_GTK_IS_AV (self)); + + priv = clapper_gtk_av_get_instance_private (self); + + if (priv->auto_inhibit != inhibit) { + priv->auto_inhibit = inhibit; + + /* Uninhibit if we were auto inhibited earlier */ + if (!priv->auto_inhibit) + _set_inhibit_session (self, FALSE); + + g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_AUTO_INHIBIT]); + } +} + +/** + * clapper_gtk_av_get_auto_inhibit: + * @av: a #ClapperGtkAv + * + * Get whether automatic session inhibit is enabled. + * + * Returns: %TRUE if enabled, %FALSE otherwise. + * + * Since: 0.10 + */ +gboolean +clapper_gtk_av_get_auto_inhibit (ClapperGtkAv *self) +{ + ClapperGtkAvPrivate *priv; + + g_return_val_if_fail (CLAPPER_GTK_IS_AV (self), FALSE); + + priv = clapper_gtk_av_get_instance_private (self); + + return priv->auto_inhibit; +} + +/** + * clapper_gtk_av_get_inhibited: + * @av: a #ClapperGtkAv + * + * Get whether session is currently inhibited by + * [property@ClapperGtk.Av:auto-inhibit]. + * + * Returns: %TRUE if inhibited, %FALSE otherwise. + * + * Since: 0.10 + */ +gboolean +clapper_gtk_av_get_inhibited (ClapperGtkAv *self) +{ + ClapperGtkAvPrivate *priv; + + g_return_val_if_fail (CLAPPER_GTK_IS_AV (self), FALSE); + + priv = clapper_gtk_av_get_instance_private (self); + + return (priv->inhibit_cookie != 0); +} + +static void +clapper_gtk_av_root (GtkWidget *widget) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + ClapperGtkAvPrivate *priv = clapper_gtk_av_get_instance_private (self); + + _ensure_css_provider (); + + GTK_WIDGET_CLASS (parent_class)->root (widget); + + if (priv->auto_inhibit) { + ClapperPlayerState state = clapper_player_get_state (priv->player); + _set_inhibit_session (self, state == CLAPPER_PLAYER_STATE_PLAYING); + } +} + +static void +clapper_gtk_av_unroot (GtkWidget *widget) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget); + + _set_inhibit_session (self, FALSE); + + GTK_WIDGET_CLASS (parent_class)->unroot (widget); +} + +static void +clapper_gtk_av_init (ClapperGtkAv *self) +{ + ClapperGtkAvPrivate *priv = clapper_gtk_av_get_instance_private (self); + + priv->auto_inhibit = DEFAULT_AUTO_INHIBIT; +} + +static void +clapper_gtk_av_constructed (GObject *object) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (object); + ClapperGtkAvPrivate *priv = clapper_gtk_av_get_instance_private (self); + GstElement *afilter; + + priv->player = clapper_player_new (); + + g_signal_connect (priv->player, "notify::state", + G_CALLBACK (_player_state_changed_cb), self); + + afilter = gst_element_factory_make ("scaletempo", NULL); + if (G_LIKELY (afilter != NULL)) + clapper_player_set_audio_filter (priv->player, afilter); + + G_OBJECT_CLASS (parent_class)->constructed (object); +} + +static void +clapper_gtk_av_dispose (GObject *object) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (object); + ClapperGtkAvPrivate *priv = clapper_gtk_av_get_instance_private (self); + + /* Something else might still be holding a reference on the player, + * thus we should disconnect everything before disposing template */ + if (priv->player) { + g_signal_handlers_disconnect_by_func (priv->player, + _player_state_changed_cb, self); + } + + gst_clear_object (&priv->player); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +clapper_gtk_av_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (object); + + switch (prop_id) { + case PROP_PLAYER: + g_value_set_object (value, clapper_gtk_av_get_player (self)); + break; + case PROP_AUTO_INHIBIT: + g_value_set_boolean (value, clapper_gtk_av_get_auto_inhibit (self)); + break; + case PROP_INHIBITED: + g_value_set_boolean (value, clapper_gtk_av_get_inhibited (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clapper_gtk_av_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (object); + + switch (prop_id) { + case PROP_AUTO_INHIBIT: + clapper_gtk_av_set_auto_inhibit (self, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clapper_gtk_av_class_init (ClapperGtkAvClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GtkWidgetClass *widget_class = (GtkWidgetClass *) klass; + + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtkav", GST_DEBUG_FG_MAGENTA, + "Clapper GTK AV"); + + widget_class->root = clapper_gtk_av_root; + widget_class->unroot = clapper_gtk_av_unroot; + + gobject_class->constructed = clapper_gtk_av_constructed; + gobject_class->get_property = clapper_gtk_av_get_property; + gobject_class->set_property = clapper_gtk_av_set_property; + gobject_class->dispose = clapper_gtk_av_dispose; + + /** + * ClapperGtkAv:player: + * + * A #ClapperPlayer used by widget. + */ + param_specs[PROP_PLAYER] = g_param_spec_object ("player", + NULL, NULL, CLAPPER_TYPE_PLAYER, + G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + + /** + * ClapperGtkAv:auto-inhibit: + * + * Try to automatically inhibit session when media is playing. + */ + param_specs[PROP_AUTO_INHIBIT] = g_param_spec_boolean ("auto-inhibit", + NULL, NULL, DEFAULT_AUTO_INHIBIT, + G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + + /** + * ClapperGtkAv:inhibited: + * + * Get whether session is currently inhibited by playback. + */ + param_specs[PROP_INHIBITED] = g_param_spec_boolean ("inhibited", + NULL, NULL, FALSE, + G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, PROP_LAST, param_specs); + + gtk_widget_class_install_action (widget_class, "av.toggle-play", NULL, toggle_play_action_cb); + gtk_widget_class_install_action (widget_class, "av.play", NULL, play_action_cb); + gtk_widget_class_install_action (widget_class, "av.pause", NULL, pause_action_cb); + gtk_widget_class_install_action (widget_class, "av.stop", NULL, stop_action_cb); + gtk_widget_class_install_action (widget_class, "av.seek", "d", seek_action_cb); + gtk_widget_class_install_action (widget_class, "av.seek-custom", "(di)", seek_custom_action_cb); + gtk_widget_class_install_action (widget_class, "av.toggle-mute", NULL, toggle_mute_action_cb); + gtk_widget_class_install_action (widget_class, "av.set-mute", "b", set_mute_action_cb); + gtk_widget_class_install_action (widget_class, "av.volume-up", NULL, volume_up_action_cb); + gtk_widget_class_install_action (widget_class, "av.volume-down", NULL, volume_down_action_cb); + gtk_widget_class_install_action (widget_class, "av.set-volume", "d", set_volume_action_cb); + gtk_widget_class_install_action (widget_class, "av.speed-up", NULL, speed_up_action_cb); + gtk_widget_class_install_action (widget_class, "av.speed-down", NULL, speed_down_action_cb); + gtk_widget_class_install_action (widget_class, "av.set-speed", "d", set_speed_action_cb); + gtk_widget_class_install_action (widget_class, "av.previous-item", NULL, previous_item_action_cb); + gtk_widget_class_install_action (widget_class, "av.next-item", NULL, next_item_action_cb); + gtk_widget_class_install_action (widget_class, "av.select-item", "u", select_item_action_cb); + + gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); + gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GENERIC); + gtk_widget_class_set_css_name (widget_class, "clapper-gtk-av"); +} diff --git a/src/lib/clapper-gtk/clapper-gtk-av.h b/src/lib/clapper-gtk/clapper-gtk-av.h new file mode 100644 index 00000000..03552fc8 --- /dev/null +++ b/src/lib/clapper-gtk/clapper-gtk-av.h @@ -0,0 +1,60 @@ +/* Clapper GTK Integration Library + * Copyright (C) 2025 Rafał Dzięgiel + * + * 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 + * . + */ + +#pragma once + +#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include +#include +#include + +#include + +G_BEGIN_DECLS + +#define CLAPPER_GTK_TYPE_AV (clapper_gtk_av_get_type()) +#define CLAPPER_GTK_AV_CAST(obj) ((ClapperGtkAv *)(obj)) + +CLAPPER_GTK_API +G_DECLARE_DERIVABLE_TYPE (ClapperGtkAv, clapper_gtk_av, CLAPPER_GTK, AV, GtkWidget) + +struct _ClapperGtkAvClass +{ + GtkWidgetClass parent_class; + + /*< private >*/ + gpointer padding[4]; +}; + +CLAPPER_GTK_API +ClapperPlayer * clapper_gtk_av_get_player (ClapperGtkAv *av); + +CLAPPER_GTK_API +void clapper_gtk_av_set_auto_inhibit (ClapperGtkAv *av, gboolean inhibit); + +CLAPPER_GTK_API +gboolean clapper_gtk_av_get_auto_inhibit (ClapperGtkAv *av); + +CLAPPER_GTK_API +gboolean clapper_gtk_av_get_inhibited (ClapperGtkAv *av); + +G_END_DECLS diff --git a/src/lib/clapper-gtk/clapper-gtk-utils.c b/src/lib/clapper-gtk/clapper-gtk-utils.c index 30319235..1c4c78de 100644 --- a/src/lib/clapper-gtk/clapper-gtk-utils.c +++ b/src/lib/clapper-gtk/clapper-gtk-utils.c @@ -21,7 +21,7 @@ #include #include "clapper-gtk-utils-private.h" -#include "clapper-gtk-video.h" +#include "clapper-gtk-av.h" static gboolean initialized = FALSE; @@ -29,18 +29,18 @@ static gboolean initialized = FALSE; * clapper_gtk_get_player_from_ancestor: * @widget: a #GtkWidget * - * Get [class@Clapper.Player] used by [class@ClapperGtk.Video] ancestor of @widget. + * Get [class@Clapper.Player] used by [class@ClapperGtk.Av] ancestor of @widget. * * This utility is a convenience wrapper for calling [method@Gtk.Widget.get_ancestor] - * of type `CLAPPER_GTK_TYPE_VIDEO` and [method@ClapperGtk.Video.get_player] with + * of type `CLAPPER_GTK_TYPE_AV` and [method@ClapperGtk.Av.get_player] with * additional %NULL checking and type casting. * * This is meant to be used mainly for custom widget development as an easy access to the * underlying parent [class@Clapper.Player] object. If you want to get the player from - * [class@ClapperGtk.Video] widget itself, use [method@ClapperGtk.Video.get_player] instead. + * [class@ClapperGtk.Av] widget itself, use [method@ClapperGtk.Av.get_player] instead. * * Rememeber that this function will return %NULL when widget does not have - * a [class@ClapperGtk.Video] ancestor in widget hierarchy (widget is not yet placed). + * a [class@ClapperGtk.Av] ancestor in widget hierarchy (widget is not yet placed). * * Returns: (transfer none) (nullable): a #ClapperPlayer from ancestor of a @widget. */ @@ -52,8 +52,8 @@ clapper_gtk_get_player_from_ancestor (GtkWidget *widget) g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - if ((parent = gtk_widget_get_ancestor (widget, CLAPPER_GTK_TYPE_VIDEO))) - player = clapper_gtk_video_get_player (CLAPPER_GTK_VIDEO_CAST (parent)); + if ((parent = gtk_widget_get_ancestor (widget, CLAPPER_GTK_TYPE_AV))) + player = clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (parent)); return player; } diff --git a/src/lib/clapper-gtk/clapper-gtk-video.c b/src/lib/clapper-gtk/clapper-gtk-video.c index c30fb038..1b83c0b8 100644 --- a/src/lib/clapper-gtk/clapper-gtk-video.c +++ b/src/lib/clapper-gtk/clapper-gtk-video.c @@ -22,8 +22,8 @@ * A ready to be used GTK video widget implementing Clapper API. * * #ClapperGtkVideo is the main widget exposed by `ClapperGtk` API. It both displays - * videos played by [class@Clapper.Player] (exposed as its property) and manages - * revealing and fading of any additional widgets overlaid on top of it. + * videos played by [class@Clapper.Player] (exposed as [property@ClapperGtk.Av:player] property) + * and manages revealing and fading of any additional widgets overlaid on top of it. * * Other widgets provided by `ClapperGtk` library, once placed anywhere on video * (including nesting within another widget like [class@Gtk.Box]) will automatically @@ -34,7 +34,7 @@ * # Basic usage * * A typical use case is to embed video widget as part of your app where video playback - * is needed. Get the [class@Clapper.Player] belonging to the video widget and start adding + * is needed. Get the [class@Clapper.Player] belonging to the AV widget and start adding * new [class@Clapper.MediaItem] items to the [class@Clapper.Queue] for playback. * For more information please refer to the Clapper playback library documentation. * @@ -46,27 +46,8 @@ * * # Actions * - * #ClapperGtkVideo defines a set of built-in actions: - * - * ```yaml - * - "video.toggle-play": toggle play/pause - * - "video.play": start/resume playback - * - "video.pause": pause playback - * - "video.stop": stop playback - * - "video.seek": seek to position (variant "d") - * - "video.seek-custom": seek to position using seek method (variant "(di)") - * - "video.toggle-mute": toggle mute state - * - "video.set-mute": set mute state (variant "b") - * - "video.volume-up": increase volume by 2% - * - "video.volume-down": decrease volume by 2% - * - "video.set-volume": set volume to specified value (variant "d") - * - "video.speed-up": increase speed (from 0.05x - 2x range to nearest quarter) - * - "video.speed-down": decrease speed (from 0.05x - 2x range to nearest quarter) - * - "video.set-speed": set speed to specified value (variant "d") - * - "video.previous-item": select previous item in queue - * - "video.next-item": select next item in queue - * - "video.select-item": select item at specified index in queue (variant "u") - * ``` + * You can use built-in actions of parent [class@ClapperGtk.Av]. + * See its documentation, for the list of available ones. * * # ClapperGtkVideo as GtkBuildable * @@ -93,8 +74,6 @@ #include "config.h" -#include - #include "clapper-gtk-enums.h" #include "clapper-gtk-video.h" #include "clapper-gtk-lead-container.h" @@ -102,11 +81,8 @@ #include "clapper-gtk-buffering-animation-private.h" #include "clapper-gtk-video-placeholder-private.h" -#define PERCENTAGE_ROUND(a) (round ((gdouble) a / 0.01) * 0.01) - #define DEFAULT_FADE_DELAY 3000 #define DEFAULT_TOUCH_FADE_DELAY 5000 -#define DEFAULT_AUTO_INHIBIT FALSE #define MIN_MOTION_DELAY 100000 @@ -115,7 +91,7 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); struct _ClapperGtkVideo { - GtkWidget parent; + ClapperGtkAv parent; GtkWidget *overlay; GtkWidget *status; @@ -125,10 +101,8 @@ struct _ClapperGtkVideo GtkGesture *click_gesture; /* Props */ - ClapperPlayer *player; guint fade_delay; guint touch_fade_delay; - gboolean auto_inhibit; GPtrArray *overlays; GPtrArray *fading_overlays; @@ -140,8 +114,6 @@ struct _ClapperGtkVideo guint fade_timeout; gboolean reveal, revealed; - guint inhibit_cookie; - /* Current pointer coords and type */ gdouble x, y; gboolean is_touch; @@ -174,17 +146,14 @@ _buildable_iface_init (GtkBuildableIface *iface) } #define parent_class clapper_gtk_video_parent_class -G_DEFINE_TYPE_WITH_CODE (ClapperGtkVideo, clapper_gtk_video, GTK_TYPE_WIDGET, +G_DEFINE_TYPE_WITH_CODE (ClapperGtkVideo, clapper_gtk_video, CLAPPER_GTK_TYPE_AV, G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, _buildable_iface_init)) enum { PROP_0, - PROP_PLAYER, PROP_FADE_DELAY, PROP_TOUCH_FADE_DELAY, - PROP_AUTO_INHIBIT, - PROP_INHIBITED, PROP_LAST }; @@ -195,209 +164,111 @@ enum SIGNAL_LAST }; -static gboolean provider_added = FALSE; static GParamSpec *param_specs[PROP_LAST] = { NULL, }; static guint signals[SIGNAL_LAST] = { 0, }; +/* FIXME: 1.0: Remove these compat actions, since they were moved to base class */ + static void toggle_play_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - - switch (clapper_player_get_state (player)) { - case CLAPPER_PLAYER_STATE_PLAYING: - clapper_player_pause (player); - break; - case CLAPPER_PLAYER_STATE_STOPPED: - case CLAPPER_PLAYER_STATE_PAUSED: - clapper_player_play (player); - break; - default: - break; - } + gtk_widget_activate_action_variant (widget, "av.toggle-play", parameter); } static void play_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - - clapper_player_play (player); + gtk_widget_activate_action_variant (widget, "av.play", parameter); } static void pause_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - - clapper_player_pause (player); + gtk_widget_activate_action_variant (widget, "av.pause", parameter); } static void stop_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - - clapper_player_stop (player); + gtk_widget_activate_action_variant (widget, "av.stop", parameter); } static void seek_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - gdouble position = g_variant_get_double (parameter); - - clapper_player_seek (player, position); + gtk_widget_activate_action_variant (widget, "av.seek", parameter); } static void seek_custom_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - ClapperPlayerSeekMethod method = CLAPPER_PLAYER_SEEK_METHOD_NORMAL; - gdouble position = 0; - - g_variant_get (parameter, "(di)", &position, &method); - clapper_player_seek_custom (player, position, method); + gtk_widget_activate_action_variant (widget, "av.seek-custom", parameter); } static void toggle_mute_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - - clapper_player_set_mute (player, !clapper_player_get_mute (player)); + gtk_widget_activate_action_variant (widget, "av.toggle-mute", parameter); } static void set_mute_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - gboolean mute = g_variant_get_boolean (parameter); - - clapper_player_set_mute (player, mute); + gtk_widget_activate_action_variant (widget, "av.set-mute", parameter); } static void volume_up_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - gdouble volume = (clapper_player_get_volume (player) + 0.02); - - if (volume > 2.0) - volume = 2.0; - - clapper_player_set_volume (player, PERCENTAGE_ROUND (volume)); + gtk_widget_activate_action_variant (widget, "av.volume-up", parameter); } static void volume_down_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - gdouble volume = (clapper_player_get_volume (player) - 0.02); - - if (volume < 0) - volume = 0; - - clapper_player_set_volume (player, PERCENTAGE_ROUND (volume)); + gtk_widget_activate_action_variant (widget, "av.volume-down", parameter); } static void set_volume_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - gdouble volume = g_variant_get_double (parameter); - - clapper_player_set_volume (player, volume); + gtk_widget_activate_action_variant (widget, "av.set-volume", parameter); } static void speed_up_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - gdouble dest, speed = clapper_player_get_speed (player); - - if (speed >= 2.0) - return; - - dest = 0.25; - while (speed >= dest) - dest += 0.25; - - if (dest > 2.0) - dest = 2.0; - - clapper_player_set_speed (player, dest); + gtk_widget_activate_action_variant (widget, "av.speed-up", parameter); } static void speed_down_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - gdouble dest, speed = clapper_player_get_speed (player); - - if (speed <= 0.05) - return; - - dest = 2.0; - while (speed <= dest) - dest -= 0.25; - - if (dest < 0.05) - dest = 0.05; - - clapper_player_set_speed (player, dest); + gtk_widget_activate_action_variant (widget, "av.speed-down", parameter); } static void set_speed_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - gdouble speed = g_variant_get_double (parameter); - - clapper_player_set_speed (player, speed); + gtk_widget_activate_action_variant (widget, "av.set-speed", parameter); } static void previous_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - - clapper_queue_select_previous_item (clapper_player_get_queue (player)); + gtk_widget_activate_action_variant (widget, "av.previous-item", parameter); } static void next_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - - clapper_queue_select_next_item (clapper_player_get_queue (player)); + gtk_widget_activate_action_variant (widget, "av.next-item", parameter); } static void select_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) { - ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); - ClapperPlayer *player = clapper_gtk_video_get_player (self); - guint index = g_variant_get_uint32 (parameter); - - clapper_queue_select_index (clapper_player_get_queue (player), index); + gtk_widget_activate_action_variant (widget, "av.select-item", parameter); } static void @@ -871,73 +742,6 @@ touch_released_cb (GtkGestureClick *click, gint n_press, _reset_fade_timeout (self); } -static void -_ensure_css_provider (void) -{ - GdkDisplay *display; - - if (provider_added) - return; - - display = gdk_display_get_default (); - - if (G_LIKELY (display != NULL)) { - GtkCssProvider *provider = gtk_css_provider_new (); - gtk_css_provider_load_from_resource (provider, - CLAPPER_GTK_RESOURCE_PREFIX "/css/styles.css"); - - gtk_style_context_add_provider_for_display (display, - (GtkStyleProvider *) provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION - 1); - g_object_unref (provider); - - provider_added = TRUE; - } -} - -static inline void -_set_inhibit_session (ClapperGtkVideo *self, gboolean inhibit) -{ - GtkRoot *root; - GApplication *app; - gboolean inhibited = (self->inhibit_cookie != 0); - - if (inhibited == inhibit) - return; - - GST_DEBUG_OBJECT (self, "Trying to %sinhibit session...", (inhibit) ? "" : "un"); - - root = gtk_widget_get_root (GTK_WIDGET (self)); - - if (!root && !GTK_IS_WINDOW (root)) { - GST_WARNING_OBJECT (self, "Cannot %sinhibit session " - "without root window", (inhibit) ? "" : "un"); - return; - } - - /* NOTE: Not using application from window prop, - * as it goes away early when unrooting */ - app = g_application_get_default (); - - if (!app && !GTK_IS_APPLICATION (app)) { - GST_WARNING_OBJECT (self, "Cannot %sinhibit session " - "without window application set", (inhibit) ? "" : "un"); - return; - } - - if (inhibited) { - gtk_application_uninhibit (GTK_APPLICATION (app), self->inhibit_cookie); - self->inhibit_cookie = 0; - } - if (inhibit) { - self->inhibit_cookie = gtk_application_inhibit (GTK_APPLICATION (app), - GTK_WINDOW (root), GTK_APPLICATION_INHIBIT_IDLE, - "Video is playing"); - } - - GST_DEBUG_OBJECT (self, "Session %sinhibited", (inhibit) ? "" : "un"); - g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_INHIBITED]); -} - static inline void _set_buffering_animation_enabled (ClapperGtkVideo *self, gboolean enabled) { @@ -963,9 +767,6 @@ _player_state_changed_cb (ClapperPlayer *player, { ClapperPlayerState state = clapper_player_get_state (player); - if (self->auto_inhibit) - _set_inhibit_session (self, state == CLAPPER_PLAYER_STATE_PLAYING); - _set_buffering_animation_enabled (self, state == CLAPPER_PLAYER_STATE_BUFFERING); } @@ -1106,7 +907,7 @@ _fading_overlay_revealed_cb (GtkRevealer *revealer, * * Creates a new #ClapperGtkVideo instance. * - * Newly created video widget will also set some default GStreamer elements + * Newly created video widget will also have set some default GStreamer elements * on its [class@Clapper.Player]. This includes Clapper own video sink and * a "scaletempo" element as audio filter. Both can still be changed after * construction by setting corresponding player properties. @@ -1187,19 +988,21 @@ clapper_gtk_video_add_fading_overlay (ClapperGtkVideo *self, GtkWidget *widget) } /** - * clapper_gtk_video_get_player: + * clapper_gtk_video_get_player: (skip) * @video: a #ClapperGtkVideo * * Get #ClapperPlayer used by this #ClapperGtkVideo instance. * * Returns: (transfer none): a #ClapperPlayer used by video. + * + * Deprecated: 0.10: Use [method@ClapperGtk.Av.get_player] instead. */ ClapperPlayer * clapper_gtk_video_get_player (ClapperGtkVideo *self) { g_return_val_if_fail (CLAPPER_GTK_IS_VIDEO (self), NULL); - return self->player; + return clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (self)); } /** @@ -1275,60 +1078,58 @@ clapper_gtk_video_get_touch_fade_delay (ClapperGtkVideo *self) } /** - * clapper_gtk_video_set_auto_inhibit: + * clapper_gtk_video_set_auto_inhibit: (skip) * @video: a #ClapperGtkVideo * @inhibit: whether to enable automatic session inhibit * * Set whether video should try to automatically inhibit session * from idling (and possibly screen going black) when video is playing. + * + * Deprecated: 0.10: Use [method@ClapperGtk.Av.set_auto_inhibit] instead. */ void clapper_gtk_video_set_auto_inhibit (ClapperGtkVideo *self, gboolean inhibit) { g_return_if_fail (CLAPPER_GTK_IS_VIDEO (self)); - if (self->auto_inhibit != inhibit) { - self->auto_inhibit = inhibit; - - /* Uninhibit if we were auto inhibited earlier */ - if (!self->auto_inhibit) - _set_inhibit_session (self, FALSE); - - g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_AUTO_INHIBIT]); - } + clapper_gtk_av_set_auto_inhibit (CLAPPER_GTK_AV_CAST (self), inhibit); } /** - * clapper_gtk_video_get_auto_inhibit: + * clapper_gtk_video_get_auto_inhibit: (skip) * @video: a #ClapperGtkVideo * * Get whether automatic session inhibit is enabled. * * Returns: %TRUE if enabled, %FALSE otherwise. + * + * Deprecated: 0.10: Use [method@ClapperGtk.Av.get_auto_inhibit] instead. */ gboolean clapper_gtk_video_get_auto_inhibit (ClapperGtkVideo *self) { g_return_val_if_fail (CLAPPER_GTK_IS_VIDEO (self), FALSE); - return self->auto_inhibit; + return clapper_gtk_av_get_auto_inhibit (CLAPPER_GTK_AV_CAST (self)); } /** - * clapper_gtk_video_get_inhibited: + * clapper_gtk_video_get_inhibited: (skip) * @video: a #ClapperGtkVideo * * Get whether session is currently inhibited by - * [property@ClapperGtk.Video:auto-inhibit]. + * [property@ClapperGtk.Av:auto-inhibit]. * * Returns: %TRUE if inhibited, %FALSE otherwise. + * + * Deprecated: 0.10: Use [method@ClapperGtk.Av.get_inhibited] instead. */ gboolean clapper_gtk_video_get_inhibited (ClapperGtkVideo *self) { g_return_val_if_fail (CLAPPER_GTK_IS_VIDEO (self), FALSE); - return (self->inhibit_cookie != 0); + return clapper_gtk_av_get_inhibited (CLAPPER_GTK_AV_CAST (self)); } static void @@ -1337,8 +1138,6 @@ clapper_gtk_video_root (GtkWidget *widget) ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); GtkRoot *root; - _ensure_css_provider (); - GTK_WIDGET_CLASS (parent_class)->root (widget); root = gtk_widget_get_root (widget); @@ -1350,11 +1149,6 @@ clapper_gtk_video_root (GtkWidget *widget) G_CALLBACK (_window_is_active_cb), self); _window_is_active_cb (window, NULL, self); } - - if (self->auto_inhibit) { - ClapperPlayerState state = clapper_player_get_state (self->player); - _set_inhibit_session (self, state == CLAPPER_PLAYER_STATE_PLAYING); - } } static void @@ -1368,8 +1162,6 @@ clapper_gtk_video_unroot (GtkWidget *widget) _window_is_active_cb, self); } - _set_inhibit_session (self, FALSE); - GTK_WIDGET_CLASS (parent_class)->unroot (widget); } @@ -1385,7 +1177,6 @@ clapper_gtk_video_init (ClapperGtkVideo *self) self->fade_delay = DEFAULT_FADE_DELAY; self->touch_fade_delay = DEFAULT_TOUCH_FADE_DELAY; - self->auto_inhibit = DEFAULT_AUTO_INHIBIT; /* Ensure private types */ g_type_ensure (CLAPPER_GTK_TYPE_STATUS); @@ -1400,15 +1191,18 @@ static void clapper_gtk_video_constructed (GObject *object) { ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (object); - GstElement *afilter, *vsink; + GstElement *vsink; + ClapperPlayer *player; ClapperQueue *queue; - self->player = clapper_player_new (); - queue = clapper_player_get_queue (self->player); + G_OBJECT_CLASS (parent_class)->constructed (object); - g_signal_connect (self->player, "notify::state", + player = clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (self)); + queue = clapper_player_get_queue (player); + + g_signal_connect (player, "notify::state", G_CALLBACK (_player_state_changed_cb), self); - g_signal_connect (self->player, "notify::video-sink", + g_signal_connect (player, "notify::video-sink", G_CALLBACK (_video_sink_changed_cb), self); vsink = gst_element_factory_make ("clappersink", NULL); @@ -1428,28 +1222,23 @@ clapper_gtk_video_constructed (GObject *object) } } - clapper_player_set_video_sink (self->player, vsink); + clapper_player_set_video_sink (player, vsink); } - afilter = gst_element_factory_make ("scaletempo", NULL); - if (G_LIKELY (afilter != NULL)) - clapper_player_set_audio_filter (self->player, afilter); - - g_signal_connect (self->player, "error", + g_signal_connect (player, "error", G_CALLBACK (_player_error_cb), self); - g_signal_connect (self->player, "missing-plugin", + g_signal_connect (player, "missing-plugin", G_CALLBACK (_player_missing_plugin_cb), self); g_signal_connect (queue, "notify::current-item", G_CALLBACK (_queue_current_item_changed_cb), self); - - G_OBJECT_CLASS (parent_class)->constructed (object); } static void clapper_gtk_video_dispose (GObject *object) { ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (object); + ClapperPlayer *player; if (self->notify_revealed_id != 0) { GtkRevealer *revealer = GTK_REVEALER (g_ptr_array_index (self->fading_overlays, 0)); @@ -1460,18 +1249,20 @@ clapper_gtk_video_dispose (GObject *object) g_clear_handle_id (&self->fade_timeout, g_source_remove); + player = clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (self)); + /* Something else might still be holding a reference on the player, * thus we should disconnect everything before disposing template */ - if (self->player) { - ClapperQueue *queue = clapper_player_get_queue (self->player); + if (player) { // NULL if dispose run multiple times + ClapperQueue *queue = clapper_player_get_queue (player); - g_signal_handlers_disconnect_by_func (self->player, + g_signal_handlers_disconnect_by_func (player, _player_state_changed_cb, self); - g_signal_handlers_disconnect_by_func (self->player, + g_signal_handlers_disconnect_by_func (player, _video_sink_changed_cb, self); - g_signal_handlers_disconnect_by_func (self->player, + g_signal_handlers_disconnect_by_func (player, _player_error_cb, self); - g_signal_handlers_disconnect_by_func (self->player, + g_signal_handlers_disconnect_by_func (player, _player_missing_plugin_cb, self); g_signal_handlers_disconnect_by_func (queue, @@ -1481,7 +1272,6 @@ clapper_gtk_video_dispose (GObject *object) gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_GTK_TYPE_VIDEO); g_clear_pointer (&self->overlay, gtk_widget_unparent); - gst_clear_object (&self->player); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -1504,21 +1294,12 @@ clapper_gtk_video_get_property (GObject *object, guint prop_id, ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (object); switch (prop_id) { - case PROP_PLAYER: - g_value_set_object (value, clapper_gtk_video_get_player (self)); - break; case PROP_FADE_DELAY: g_value_set_uint (value, clapper_gtk_video_get_fade_delay (self)); break; case PROP_TOUCH_FADE_DELAY: g_value_set_uint (value, clapper_gtk_video_get_touch_fade_delay (self)); break; - case PROP_AUTO_INHIBIT: - g_value_set_boolean (value, clapper_gtk_video_get_auto_inhibit (self)); - break; - case PROP_INHIBITED: - g_value_set_boolean (value, clapper_gtk_video_get_inhibited (self)); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1538,9 +1319,6 @@ clapper_gtk_video_set_property (GObject *object, guint prop_id, case PROP_TOUCH_FADE_DELAY: clapper_gtk_video_set_touch_fade_delay (self, g_value_get_uint (value)); break; - case PROP_AUTO_INHIBIT: - clapper_gtk_video_set_auto_inhibit (self, g_value_get_boolean (value)); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1565,15 +1343,6 @@ clapper_gtk_video_class_init (ClapperGtkVideoClass *klass) gobject_class->dispose = clapper_gtk_video_dispose; gobject_class->finalize = clapper_gtk_video_finalize; - /** - * ClapperGtkVideo:player: - * - * A #ClapperPlayer used by video. - */ - param_specs[PROP_PLAYER] = g_param_spec_object ("player", - NULL, NULL, CLAPPER_TYPE_PLAYER, - G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); - /** * ClapperGtkVideo:fade-delay: * @@ -1593,24 +1362,6 @@ clapper_gtk_video_class_init (ClapperGtkVideoClass *klass) NULL, NULL, 1, G_MAXUINT, DEFAULT_TOUCH_FADE_DELAY, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); - /** - * ClapperGtkVideo:auto-inhibit: - * - * Try to automatically inhibit session when video is playing. - */ - param_specs[PROP_AUTO_INHIBIT] = g_param_spec_boolean ("auto-inhibit", - NULL, NULL, DEFAULT_AUTO_INHIBIT, - G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); - - /** - * ClapperGtkVideo:inhibited: - * - * Get whether session is currently inhibited by the video. - */ - param_specs[PROP_INHIBITED] = g_param_spec_boolean ("inhibited", - NULL, NULL, FALSE, - G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); - /** * ClapperGtkVideo::toggle-fullscreen: * @video: a #ClapperGtkVideo @@ -1642,6 +1393,8 @@ clapper_gtk_video_class_init (ClapperGtkVideoClass *klass) g_object_class_install_properties (gobject_class, PROP_LAST, param_specs); + /* FIXME: 1.0: Remove these actions, since they were moved to + * base class AV widget, but are here for compat reasons. */ gtk_widget_class_install_action (widget_class, "video.toggle-play", NULL, toggle_play_action_cb); gtk_widget_class_install_action (widget_class, "video.play", NULL, play_action_cb); gtk_widget_class_install_action (widget_class, "video.pause", NULL, pause_action_cb); diff --git a/src/lib/clapper-gtk/clapper-gtk-video.h b/src/lib/clapper-gtk/clapper-gtk-video.h index 3c0ce6fb..157f9ca3 100644 --- a/src/lib/clapper-gtk/clapper-gtk-video.h +++ b/src/lib/clapper-gtk/clapper-gtk-video.h @@ -27,6 +27,7 @@ #include #include +#include #include G_BEGIN_DECLS @@ -35,7 +36,7 @@ G_BEGIN_DECLS #define CLAPPER_GTK_VIDEO_CAST(obj) ((ClapperGtkVideo *)(obj)) CLAPPER_GTK_API -G_DECLARE_FINAL_TYPE (ClapperGtkVideo, clapper_gtk_video, CLAPPER_GTK, VIDEO, GtkWidget) +G_DECLARE_FINAL_TYPE (ClapperGtkVideo, clapper_gtk_video, CLAPPER_GTK, VIDEO, ClapperGtkAv) CLAPPER_GTK_API GtkWidget * clapper_gtk_video_new (void); @@ -46,7 +47,7 @@ void clapper_gtk_video_add_overlay (ClapperGtkVideo *video, GtkWidget *widget); CLAPPER_GTK_API void clapper_gtk_video_add_fading_overlay (ClapperGtkVideo *video, GtkWidget *widget); -CLAPPER_GTK_API +CLAPPER_GTK_DEPRECATED_FOR(clapper_gtk_av_get_player) ClapperPlayer * clapper_gtk_video_get_player (ClapperGtkVideo *video); CLAPPER_GTK_API @@ -61,13 +62,13 @@ void clapper_gtk_video_set_touch_fade_delay (ClapperGtkVideo *video, guint delay CLAPPER_GTK_API guint clapper_gtk_video_get_touch_fade_delay (ClapperGtkVideo *video); -CLAPPER_GTK_API +CLAPPER_GTK_DEPRECATED_FOR(clapper_gtk_av_set_auto_inhibit) void clapper_gtk_video_set_auto_inhibit (ClapperGtkVideo *video, gboolean inhibit); -CLAPPER_GTK_API +CLAPPER_GTK_DEPRECATED_FOR(clapper_gtk_av_get_auto_inhibit) gboolean clapper_gtk_video_get_auto_inhibit (ClapperGtkVideo *video); -CLAPPER_GTK_API +CLAPPER_GTK_DEPRECATED_FOR(clapper_gtk_av_get_inhibited) gboolean clapper_gtk_video_get_inhibited (ClapperGtkVideo *video); G_END_DECLS diff --git a/src/lib/clapper-gtk/clapper-gtk.h b/src/lib/clapper-gtk/clapper-gtk.h index dace6487..9ef16257 100644 --- a/src/lib/clapper-gtk/clapper-gtk.h +++ b/src/lib/clapper-gtk/clapper-gtk.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include diff --git a/src/lib/clapper-gtk/meson.build b/src/lib/clapper-gtk/meson.build index 026422dc..05ee6a41 100644 --- a/src/lib/clapper-gtk/meson.build +++ b/src/lib/clapper-gtk/meson.build @@ -90,6 +90,7 @@ clappergtk_conf_inc = [ clappergtk_headers = [ 'clapper-gtk.h', + 'clapper-gtk-av.h', 'clapper-gtk-enums.h', 'clapper-gtk-billboard.h', 'clapper-gtk-container.h', @@ -109,6 +110,7 @@ clappergtk_headers = [ clappergtk_visibility_header, ] clappergtk_sources = [ + 'clapper-gtk-av.c', 'clapper-gtk-billboard.c', 'clapper-gtk-buffering-animation.c', 'clapper-gtk-buffering-paintable.c', diff --git a/src/lib/clapper-gtk/ui/clapper-gtk-video.ui b/src/lib/clapper-gtk/ui/clapper-gtk-video.ui index 8ee8db7d..ddd2dcf7 100644 --- a/src/lib/clapper-gtk/ui/clapper-gtk-video.ui +++ b/src/lib/clapper-gtk/ui/clapper-gtk-video.ui @@ -1,6 +1,6 @@ -