diff --git a/src/lib/clapper-gtk/clapper-gtk-audio.c b/src/lib/clapper-gtk/clapper-gtk-audio.c new file mode 100644 index 00000000..ffb1038a --- /dev/null +++ b/src/lib/clapper-gtk/clapper-gtk-audio.c @@ -0,0 +1,268 @@ +/* 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 + * . + */ + +/** + * ClapperGtkAudio: + * + * A GTK widget for audio playback with Clapper API. + * + * #ClapperGtkAudio is a widget meant for integrating audio playback + * within GTK application. It exposes [class@Clapper.Player] through its + * base class [property@ClapperGtk.Av:player] property. + * + * Other widgets (buttons, seek bar, etc.) provided by `ClapperGtk` library, once placed + * anywhere inside audio container (including nesting within another widget like [class@Gtk.Box]) + * will automatically control #ClapperGtkAudio they are within. This allows to freely create + * custom UI best suited for specific application. + * + * # Basic usage + * + * A typical use case is to embed audio widget as part of your app where audio playback + * is needed (can be even the very first child of the window). 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. + * + * # Actions + * + * You can use built-in actions of parent [class@ClapperGtk.Av]. + * See its documentation for the list of available ones. + * + * # ClapperGtkAudio as GtkBuildable + * + * #ClapperGtkAudio implementation of the [iface@Gtk.Buildable] interface supports + * placing a single widget (which might then hold multiple widgets) as `` element. + * + * ```xml + * + * + * + * horizontal + * + * + * + * + * + * + * + * + * + * + * + * + * ``` + * + * Since: 0.10 + */ + +#include "config.h" + +#include "clapper-gtk-audio.h" + +#define GST_CAT_DEFAULT clapper_gtk_audio_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +struct _ClapperGtkAudio +{ + ClapperGtkAv parent; + + GtkWidget *child; +}; + +static void +clapper_gtk_audio_add_child (GtkBuildable *buildable, + GtkBuilder *builder, GObject *child, const char *type) +{ + if (GTK_IS_WIDGET (child)) { + clapper_gtk_audio_set_child (CLAPPER_GTK_AUDIO (buildable), GTK_WIDGET (child)); + } else { + GtkBuildableIface *parent_iface = g_type_interface_peek_parent (GTK_BUILDABLE_GET_IFACE (buildable)); + parent_iface->add_child (buildable, builder, child, type); + } +} + +static void +_buildable_iface_init (GtkBuildableIface *iface) +{ + iface->add_child = clapper_gtk_audio_add_child; +} + +#define parent_class clapper_gtk_audio_parent_class +G_DEFINE_TYPE_WITH_CODE (ClapperGtkAudio, clapper_gtk_audio, CLAPPER_GTK_TYPE_AV, + G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, _buildable_iface_init)) + +enum +{ + PROP_0, + PROP_CHILD, + PROP_LAST +}; + +static GParamSpec *param_specs[PROP_LAST] = { NULL, }; + +static inline void +_unparent_child (ClapperGtkAudio *self) +{ + GtkWidget *child; + + if ((child = gtk_widget_get_first_child (GTK_WIDGET (self)))) + gtk_widget_unparent (child); +} + +/** + * clapper_gtk_audio_new: + * + * Creates a new #ClapperGtkAudio instance. + * + * Newly created audio widget will also have set "scaletempo" GStreamer element + * as default audio filter on its [class@Clapper.Player] and disable video and + * subtitle streams. This can be changed after construction by setting + * corresponding player properties. + * + * Returns: a new audio #GtkWidget. + */ +GtkWidget * +clapper_gtk_audio_new (void) +{ + return g_object_new (CLAPPER_GTK_TYPE_AUDIO, NULL); +} + +/** + * clapper_gtk_audio_set_child: + * @audio: a #ClapperGtkAudio + * @child: (nullable): a #GtkWidget + * + * Set a child #GtkWidget of @audio. + */ +void +clapper_gtk_audio_set_child (ClapperGtkAudio *self, GtkWidget *child) +{ + g_return_if_fail (CLAPPER_GTK_IS_AUDIO (self)); + g_return_if_fail (GTK_IS_WIDGET (child)); + + _unparent_child (self); + if (child) + gtk_widget_set_parent (child, GTK_WIDGET (self)); +} + +/** + * clapper_gtk_audio_get_child: + * @audio: a #ClapperGtkAudio + * + * Get a child #GtkWidget of @audio. + * + * Returns: (transfer none) (nullable): #GtkWidget set as child. + */ +GtkWidget * +clapper_gtk_audio_get_child (ClapperGtkAudio *self) +{ + g_return_val_if_fail (CLAPPER_GTK_IS_AUDIO (self), NULL); + + return gtk_widget_get_first_child (GTK_WIDGET (self)); +} + +static void +clapper_gtk_audio_init (ClapperGtkAudio *self) +{ +} + +static void +clapper_gtk_audio_constructed (GObject *object) +{ + ClapperGtkAudio *self = CLAPPER_GTK_AUDIO_CAST (object); + ClapperPlayer *player; + + G_OBJECT_CLASS (parent_class)->constructed (object); + + player = clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (self)); + + clapper_player_set_video_enabled (player, FALSE); + clapper_player_set_subtitles_enabled (player, FALSE); +} + +static void +clapper_gtk_audio_dispose (GObject *object) +{ + ClapperGtkAudio *self = CLAPPER_GTK_AUDIO_CAST (object); + + _unparent_child (self); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +clapper_gtk_audio_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + ClapperGtkAudio *self = CLAPPER_GTK_AUDIO_CAST (object); + + switch (prop_id) { + case PROP_CHILD: + g_value_set_object (value, clapper_gtk_audio_get_child (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clapper_gtk_audio_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + ClapperGtkAudio *self = CLAPPER_GTK_AUDIO_CAST (object); + + switch (prop_id) { + case PROP_CHILD: + clapper_gtk_audio_set_child (self, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clapper_gtk_audio_class_init (ClapperGtkAudioClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GtkWidgetClass *widget_class = (GtkWidgetClass *) klass; + + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtkaudio", GST_DEBUG_FG_MAGENTA, + "Clapper GTK Audio"); + + gobject_class->constructed = clapper_gtk_audio_constructed; + gobject_class->get_property = clapper_gtk_audio_get_property; + gobject_class->set_property = clapper_gtk_audio_set_property; + gobject_class->dispose = clapper_gtk_audio_dispose; + + /** + * ClapperGtkAudio:child: + * + * The child widget of `ClapperGtkAudio`. + */ + param_specs[PROP_CHILD] = g_param_spec_object ("child", + NULL, NULL, GTK_TYPE_WIDGET, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, PROP_LAST, param_specs); + + 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-audio"); +} diff --git a/src/lib/clapper-gtk/clapper-gtk-audio.h b/src/lib/clapper-gtk/clapper-gtk-audio.h new file mode 100644 index 00000000..12ae4397 --- /dev/null +++ b/src/lib/clapper-gtk/clapper-gtk-audio.h @@ -0,0 +1,49 @@ +/* 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_AUDIO (clapper_gtk_audio_get_type()) +#define CLAPPER_GTK_AUDIO_CAST(obj) ((ClapperGtkAudio *)(obj)) + +CLAPPER_GTK_API +G_DECLARE_FINAL_TYPE (ClapperGtkAudio, clapper_gtk_audio, CLAPPER_GTK, AUDIO, ClapperGtkAv) + +CLAPPER_GTK_API +GtkWidget * clapper_gtk_audio_new (void); + +CLAPPER_GTK_API +void clapper_gtk_audio_set_child (ClapperGtkAudio *audio, GtkWidget *child); + +CLAPPER_GTK_API +GtkWidget * clapper_gtk_audio_get_child (ClapperGtkAudio *audio); + +G_END_DECLS diff --git a/src/lib/clapper-gtk/clapper-gtk-av.c b/src/lib/clapper-gtk/clapper-gtk-av.c index 63471542..ffd686b3 100644 --- a/src/lib/clapper-gtk/clapper-gtk-av.c +++ b/src/lib/clapper-gtk/clapper-gtk-av.c @@ -21,7 +21,7 @@ * * A base class for GTK audio and video widgets. * - * See [class@ClapperGtk.Video]. + * See its descendants: [class@ClapperGtk.Audio] and [class@ClapperGtk.Video]. * * # Actions * diff --git a/src/lib/clapper-gtk/clapper-gtk.h b/src/lib/clapper-gtk/clapper-gtk.h index 9ef16257..c22e67f8 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 05ee6a41..1cc234c9 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-audio.h', 'clapper-gtk-av.h', 'clapper-gtk-enums.h', 'clapper-gtk-billboard.h', @@ -110,6 +111,7 @@ clappergtk_headers = [ clappergtk_visibility_header, ] clappergtk_sources = [ + 'clapper-gtk-audio.c', 'clapper-gtk-av.c', 'clapper-gtk-billboard.c', 'clapper-gtk-buffering-animation.c',