mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-29 15:22:11 +02:00
lib: Introduce Clapper GTK integration library
An easy to use GTK integration library. Meant as a GtkVideo alternative. While GtkVideo is more of a simple example of video playback under GTK4, this acts as a full-fledged video player in the form of a GtkWidget that can be placed anywhere within application. The widget offers customization options for both top header and bottom playback controls panels. The Clapper playback API is exposed under widget "player" property making it easy for the programmer to set media and control playback programically. The new library will be distributed with Clapper player. This includes public headers and GObject Introspection support. Licensed under LGPL-2.1-or-later.
This commit is contained in:
63
doc/reference/clapper-gtk/clapper-gtk.toml.in
Normal file
63
doc/reference/clapper-gtk/clapper-gtk.toml.in
Normal file
@@ -0,0 +1,63 @@
|
||||
[library]
|
||||
version = "@CLAPPER_VERSION@"
|
||||
browse_url = "https://github.com/Rafostar/clapper/"
|
||||
repository_url = "https://github.com/Rafostar/clapper.git"
|
||||
website_url = "https://rafostar.github.io/clapper/"
|
||||
docs_url = "https://rafostar.github.io/clapper/doc/clapper-gtk/"
|
||||
authors = "Rafał Dzięgiel"
|
||||
logo_url = "clapper-logo.svg"
|
||||
license = "LGPL-2.1-or-later"
|
||||
description = "Clapper GTK integration library"
|
||||
devhelp = true
|
||||
search_index = true
|
||||
|
||||
dependencies = ["Clapper@CLAPPER_VERSION_SUFFIX@", "Gtk-4.0"]
|
||||
|
||||
[dependencies."Clapper@CLAPPER_VERSION_SUFFIX@"]
|
||||
name = "Clapper"
|
||||
description = "Clapper playback library"
|
||||
docs_url = "https://rafostar.github.io/clapper/doc/clapper/"
|
||||
|
||||
[dependencies."Gtk-4.0"]
|
||||
name = "Gtk"
|
||||
description = "The GTK toolkit"
|
||||
docs_url = "https://docs.gtk.org/gtk4/"
|
||||
|
||||
related = ["GLib-2.0", "GObject-2.0", "Gio-2.0", "Gst-1.0"]
|
||||
|
||||
[related."GLib-2.0"]
|
||||
name = "GLib"
|
||||
description = "A general-purpose, portable utility library"
|
||||
docs_url = "https://docs.gtk.org/glib/"
|
||||
|
||||
[related."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
|
||||
[related."Gio-2.0"]
|
||||
name = "Gio"
|
||||
description = "GObject Interfaces and Objects, Networking, IPC, and I/O"
|
||||
docs_url = "https://docs.gtk.org/gio/"
|
||||
|
||||
[related."Gst-1.0"]
|
||||
name = "Gst"
|
||||
description = "GStreamer core library"
|
||||
docs_url = "https://gstreamer.freedesktop.org/documentation/gstreamer/gi-index.html"
|
||||
|
||||
[theme]
|
||||
name = "basic"
|
||||
show_index_summary = true
|
||||
show_class_hierarchy = true
|
||||
|
||||
[source-location]
|
||||
base_url = "https://github.com/Rafostar/clapper/tree/master/"
|
||||
|
||||
[extra]
|
||||
# The same order will be used when generating the index
|
||||
content_files = [
|
||||
]
|
||||
content_images = [
|
||||
"images/clapper-logo.svg",
|
||||
]
|
||||
urlmap_file = "urlmap.js"
|
29
doc/reference/clapper-gtk/images/clapper-logo.svg
Normal file
29
doc/reference/clapper-gtk/images/clapper-logo.svg
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 256 256" width="256" height="256">
|
||||
<defs>
|
||||
<path id="b1nGq5BrLC" d="M27.2 243.52C27.2 236.16 27.2 199.83 27.2 134.22C47.64 134.22 211.12 134.22 231.56 134.22C231.56 199.83 231.56 236.16 231.56 243.52C231.56 250.4 225.96 256 218.92 256C183.07 256 57.77 256 39.84 256C32.8 256 27.2 250.4 27.2 243.52Z"></path>
|
||||
<path id="a3jkaoNn4k" d="M24.32 103.65C24.32 106.22 24.32 127.02 24.32 129.58C24.32 132.78 26.72 135.18 29.92 135.18C50.41 135.18 215.08 135.18 235.72 135.18C238.76 135.18 241.32 132.78 241.32 129.58C241.32 127.02 241.32 106.22 241.32 103.65C241.32 100.45 238.76 98.05 235.72 98.05C194.59 98.05 50.41 98.05 29.92 98.05C26.72 98.05 24.32 100.45 24.32 103.65Z"></path>
|
||||
<path id="atpVQ8mnd" d="M174.59 135.18L211.87 98.05L171.07 98.05L133.78 135.18L174.59 135.18Z"></path>
|
||||
<path id="bMtYoNHu0" d="M76.81 135.18L114.1 98.05L73.13 98.05L35.84 135.18L76.81 135.18Z"></path>
|
||||
<path id="b5oP0Glp4" d="M19.04 69.41C19.84 71.97 25.92 91.97 26.72 94.37C27.68 97.41 30.72 99.01 33.76 98.05C54.09 91.81 216.68 42.04 237 35.8C240.04 35 241.64 31.8 240.84 28.92C240.04 26.36 233.96 6.36 233.16 3.96C232.2 0.92 229.16 -0.68 226.12 0.28C185.47 12.6 43.21 56.29 22.88 62.53C19.84 63.33 18.24 66.53 19.04 69.41Z"></path>
|
||||
<path id="lwBgev6DR" d="M176.51 54.37L129.94 29.4L169.15 17.56L215.72 42.52L176.51 54.37Z"></path>
|
||||
<path id="cUsjEMRUu" d="M81.61 83.49L35.04 58.69L74.25 46.69L120.82 71.49L81.61 83.49Z"></path>
|
||||
<path id="c1bcHZGXe" d="M14.72 66.69C14.72 72.93 14.72 123.02 14.72 129.26C14.72 132.62 17.44 135.18 20.64 135.18C26.56 135.18 74.09 135.18 80.01 135.18C84.33 135.18 87.21 130.86 85.61 127.02C82.89 120.78 61.45 70.53 58.73 64.29C57.77 62.05 55.69 60.77 53.29 60.77C46.73 60.77 24 60.77 20.64 60.77C17.44 60.77 14.72 63.33 14.72 66.69Z"></path>
|
||||
<path id="f2PtH0V1vC" d="M32.64 60.61C31.52 60.61 21.92 60.61 20.64 60.61C17.44 60.61 14.72 63.33 14.72 66.53C14.72 72.77 14.72 123.02 14.72 129.26C14.72 132.46 17.44 135.18 20.64 135.18C21.92 135.18 31.52 135.18 32.64 135.18C29.44 135.18 26.72 132.46 26.72 129.26C26.72 116.62 26.72 72.77 26.72 66.53C26.72 63.33 29.44 60.61 32.64 60.61Z"></path>
|
||||
<path id="a1SvrrkqVm" d="M231.56 135.18C231.56 143.82 231.56 148.46 231.56 149.42C231.56 149.42 231.56 149.42 231.56 149.42C108.98 149.42 40.8 149.42 27.2 149.42C27.2 149.42 27.2 149.42 27.2 149.42C27.2 140.94 27.2 136.14 27.2 135.18C27.2 135.18 27.2 135.18 27.2 135.18C149.78 135.18 217.96 135.18 231.56 135.18C231.56 135.18 231.56 135.18 231.56 135.18Z"></path>
|
||||
<path id="agXcvKqh8" d="M104.22 162.46L104.22 234.46L163.22 198.54L104.22 162.46Z"></path>
|
||||
</defs>
|
||||
<g>
|
||||
<g><use xlink:href="#b1nGq5BrLC" fill="#4747d1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
|
||||
<g><use xlink:href="#a3jkaoNn4k" fill="#4747d1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
|
||||
<g><use xlink:href="#atpVQ8mnd" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
|
||||
<g><use xlink:href="#bMtYoNHu0" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
|
||||
<g><use xlink:href="#b5oP0Glp4" fill="#4747d1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
|
||||
<g><use xlink:href="#lwBgev6DR" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
|
||||
<g><use xlink:href="#cUsjEMRUu" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
|
||||
<g><use xlink:href="#c1bcHZGXe" fill="#a9a9a9" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
|
||||
<g><use xlink:href="#f2PtH0V1vC" opacity="0.2" fill="#000000" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
|
||||
<g><use xlink:href="#a1SvrrkqVm" opacity="0.2" fill="#000000" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
|
||||
<g><use xlink:href="#agXcvKqh8" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.8 KiB |
29
doc/reference/clapper-gtk/meson.build
Normal file
29
doc/reference/clapper-gtk/meson.build
Normal file
@@ -0,0 +1,29 @@
|
||||
clappergtk_toml = configure_file(
|
||||
input: 'clapper-gtk.toml.in',
|
||||
output: 'clapper-gtk.toml',
|
||||
configuration: doc_version_conf,
|
||||
install: true,
|
||||
install_dir: join_paths(datadir, 'doc', 'clapper-gtk'),
|
||||
)
|
||||
|
||||
custom_target('clapper-gtk-doc',
|
||||
input: [
|
||||
clappergtk_toml,
|
||||
clappergtk_gir[0],
|
||||
],
|
||||
output: 'clapper-gtk',
|
||||
command: [
|
||||
gi_docgen,
|
||||
'generate',
|
||||
gi_docgen_common_args,
|
||||
'--add-include-path=@0@'.format(join_paths(meson.project_build_root(), 'src', 'lib', 'clapper-gtk')),
|
||||
'--config=@INPUT0@',
|
||||
'--output-dir=@OUTPUT@',
|
||||
'--content-dir=@0@'.format(meson.current_build_dir()),
|
||||
'--content-dir=@0@'.format(meson.current_source_dir()),
|
||||
'@INPUT1@',
|
||||
],
|
||||
build_by_default: true,
|
||||
install: true,
|
||||
install_dir: join_paths(datadir, 'doc'),
|
||||
)
|
8
doc/reference/clapper-gtk/urlmap.js
Normal file
8
doc/reference/clapper-gtk/urlmap.js
Normal file
@@ -0,0 +1,8 @@
|
||||
baseURLs = [
|
||||
['GLib', 'https://docs.gtk.org/glib/'],
|
||||
['GObject', 'https://docs.gtk.org/gobject/'],
|
||||
['Gio', 'https://docs.gtk.org/gio/'],
|
||||
['Gtk', 'https://docs.gtk.org/gtk4/'],
|
||||
['Gst', 'https://gstreamer.freedesktop.org/documentation/gstreamer/gi-index.html?'],
|
||||
['Clapper', 'https://rafostar.github.io/clapper/doc/clapper/'],
|
||||
]
|
@@ -13,3 +13,6 @@ endif
|
||||
if build_clapper
|
||||
subdir('clapper')
|
||||
endif
|
||||
if build_clappergtk
|
||||
subdir('clapper-gtk')
|
||||
endif
|
||||
|
@@ -130,6 +130,7 @@ summary({
|
||||
}, section: 'Directories')
|
||||
|
||||
summary('clapper', build_clapper ? 'Yes' : 'No', section: 'Build')
|
||||
summary('clapper-gtk', build_clappergtk ? 'Yes' : 'No', section: 'Build')
|
||||
summary('gst-plugin', build_gst_plugin ? 'Yes' : 'No', section: 'Build')
|
||||
summary('introspection', build_gir ? 'Yes' : 'No', section: 'Build')
|
||||
summary('vapi', build_vapi ? 'Yes' : 'No', section: 'Build')
|
||||
|
@@ -4,6 +4,11 @@ option('clapper',
|
||||
value: 'auto',
|
||||
description: 'Build Clapper library'
|
||||
)
|
||||
option('clapper-gtk',
|
||||
type: 'feature',
|
||||
value: 'auto',
|
||||
description: 'Build Clapper GTK integration library'
|
||||
)
|
||||
option('gst-plugin',
|
||||
type: 'feature',
|
||||
value: 'auto',
|
||||
|
464
src/lib/clapper-gtk/clapper-gtk-billboard.c
Normal file
464
src/lib/clapper-gtk/clapper-gtk-billboard.c
Normal file
@@ -0,0 +1,464 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClapperGtkBillboard:
|
||||
*
|
||||
* A layer where various messages can be displayed.
|
||||
*
|
||||
* #ClapperGtkBillboard widget is meant to be overlaid on top of
|
||||
* [class@ClapperGtk.Video] as a normal (non-fading) overlay.
|
||||
*
|
||||
* It is used to display various messages/announcements and later
|
||||
* takes care of fading them on its own.
|
||||
*
|
||||
* If automatic volume/speed change notifications when their values do
|
||||
* change are desired, functions for announcing them can be run in callbacks
|
||||
* to corresponding property notify signals on the [class@Clapper.Player].
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "clapper-gtk-billboard.h"
|
||||
#include "clapper-gtk-utils-private.h"
|
||||
|
||||
#define PERCENTAGE_ROUND(a) (round ((gdouble) a / 0.01) * 0.01)
|
||||
#define WORDS_PER_MSECOND 0.004
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_gtk_billboard_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
struct _ClapperGtkBillboard
|
||||
{
|
||||
ClapperGtkContainer parent;
|
||||
|
||||
GtkWidget *side_revealer;
|
||||
GtkWidget *progress_revealer;
|
||||
GtkWidget *progress_box;
|
||||
GtkWidget *top_progress;
|
||||
GtkWidget *bottom_progress;
|
||||
GtkWidget *progress_image;
|
||||
GtkWidget *progress_label;
|
||||
|
||||
GtkWidget *message_revealer;
|
||||
GtkWidget *message_image;
|
||||
GtkWidget *message_label;
|
||||
|
||||
gboolean mute;
|
||||
|
||||
gboolean has_pinned;
|
||||
|
||||
guint side_timeout;
|
||||
guint message_timeout;
|
||||
|
||||
ClapperPlayer *player;
|
||||
};
|
||||
|
||||
#define parent_class clapper_gtk_billboard_parent_class
|
||||
G_DEFINE_TYPE (ClapperGtkBillboard, clapper_gtk_billboard, CLAPPER_GTK_TYPE_CONTAINER)
|
||||
|
||||
/* We calculate estimated read time. This allows
|
||||
* translated text to be displayed as long as
|
||||
* necessary without app developer caring. */
|
||||
static guint
|
||||
_estimate_read_time (const gchar *text)
|
||||
{
|
||||
guint i, n_words = 1;
|
||||
guint read_time;
|
||||
|
||||
for (i = 0; text[i] != '\0'; ++i) {
|
||||
if (text[i] == ' ' || text[i] == '\n')
|
||||
n_words++;
|
||||
}
|
||||
|
||||
read_time = MAX (1500, (n_words / WORDS_PER_MSECOND) + 500);
|
||||
GST_DEBUG ("Estimated message read time: %u", read_time);
|
||||
|
||||
return read_time;
|
||||
}
|
||||
|
||||
static void
|
||||
_unreveal_side_delay_cb (ClapperGtkBillboard *self)
|
||||
{
|
||||
GST_LOG_OBJECT (self, "Unreveal side handler reached");
|
||||
self->side_timeout = 0;
|
||||
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (self->side_revealer), FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
_unreveal_message_delay_cb (ClapperGtkBillboard *self)
|
||||
{
|
||||
GST_LOG_OBJECT (self, "Unreveal message handler reached");
|
||||
self->message_timeout = 0;
|
||||
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (self->message_revealer), FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
_reset_fade_side_timeout (ClapperGtkBillboard *self)
|
||||
{
|
||||
GST_TRACE_OBJECT (self, "Fade side timeout reset");
|
||||
|
||||
g_clear_handle_id (&self->side_timeout, g_source_remove);
|
||||
self->side_timeout = g_timeout_add_once (1500,
|
||||
(GSourceOnceFunc) _unreveal_side_delay_cb, self);
|
||||
}
|
||||
|
||||
static void
|
||||
_reset_fade_message_timeout (ClapperGtkBillboard *self)
|
||||
{
|
||||
const gchar *text = gtk_label_get_text (GTK_LABEL (self->message_label));
|
||||
|
||||
GST_TRACE_OBJECT (self, "Fade side timeout reset");
|
||||
|
||||
g_clear_handle_id (&self->message_timeout, g_source_remove);
|
||||
self->message_timeout = g_timeout_add_once (
|
||||
_estimate_read_time (text),
|
||||
(GSourceOnceFunc) _unreveal_message_delay_cb, self);
|
||||
}
|
||||
|
||||
static void
|
||||
adapt_cb (ClapperGtkContainer *container, gboolean adapt,
|
||||
ClapperGtkBillboard *self)
|
||||
{
|
||||
GST_DEBUG_OBJECT (self, "Adapted: %s", (adapt) ? "yes" : "no");
|
||||
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (self->progress_revealer), !adapt);
|
||||
}
|
||||
|
||||
static void
|
||||
revealer_revealed_cb (GtkRevealer *revealer,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkBillboard *self)
|
||||
{
|
||||
if (!gtk_revealer_get_child_revealed (revealer)) {
|
||||
GtkWidget *other_revealer = (GTK_WIDGET (revealer) == self->side_revealer)
|
||||
? self->message_revealer
|
||||
: self->side_revealer;
|
||||
|
||||
gtk_widget_set_visible (GTK_WIDGET (revealer), FALSE);
|
||||
|
||||
/* We only hide here when nothing is posted on the board,
|
||||
* visiblity is set to TRUE when post is made */
|
||||
if (!gtk_revealer_get_child_revealed (GTK_REVEALER (other_revealer)))
|
||||
gtk_widget_set_visible (GTK_WIDGET (self), FALSE);
|
||||
} else {
|
||||
if ((GTK_WIDGET (revealer) == self->side_revealer))
|
||||
_reset_fade_side_timeout (self);
|
||||
else if (!self->has_pinned)
|
||||
_reset_fade_message_timeout (self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
reveal_side (ClapperGtkBillboard *self)
|
||||
{
|
||||
g_clear_handle_id (&self->side_timeout, g_source_remove);
|
||||
|
||||
gtk_widget_set_visible (GTK_WIDGET (self), TRUE);
|
||||
gtk_widget_set_visible (self->side_revealer, TRUE);
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (self->side_revealer), TRUE);
|
||||
|
||||
if (gtk_revealer_get_child_revealed (GTK_REVEALER (self->side_revealer)))
|
||||
_reset_fade_side_timeout (self);
|
||||
}
|
||||
|
||||
static void
|
||||
_post_message_internal (ClapperGtkBillboard *self,
|
||||
const gchar *icon_name, const gchar *message, gboolean pin)
|
||||
{
|
||||
if (self->has_pinned)
|
||||
return;
|
||||
|
||||
self->has_pinned = pin;
|
||||
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (self->message_image), icon_name);
|
||||
gtk_label_set_label (GTK_LABEL (self->message_label), message);
|
||||
|
||||
g_clear_handle_id (&self->message_timeout, g_source_remove);
|
||||
|
||||
gtk_widget_set_visible (GTK_WIDGET (self), TRUE);
|
||||
gtk_widget_set_visible (self->message_revealer, TRUE);
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (self->message_revealer), TRUE);
|
||||
|
||||
if (!self->has_pinned
|
||||
&& gtk_revealer_get_child_revealed (GTK_REVEALER (self->message_revealer)))
|
||||
_reset_fade_message_timeout (self);
|
||||
}
|
||||
|
||||
static void
|
||||
_player_mute_changed_cb (ClapperPlayer *player,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkBillboard *self)
|
||||
{
|
||||
self->mute = clapper_player_get_mute (player);
|
||||
|
||||
clapper_gtk_billboard_announce_volume (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_billboard_new:
|
||||
*
|
||||
* Creates a new #ClapperGtkBillboard instance.
|
||||
*
|
||||
* Returns: a new billboard #GtkWidget.
|
||||
*/
|
||||
GtkWidget *
|
||||
clapper_gtk_billboard_new (void)
|
||||
{
|
||||
return g_object_new (CLAPPER_GTK_TYPE_BILLBOARD, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_billboard_post_message:
|
||||
* @billboard: a #ClapperGtkBillboard
|
||||
* @icon_name: an icon name
|
||||
* @message: a message text
|
||||
*
|
||||
* Posts a temporary message on the @billboard.
|
||||
*
|
||||
* Duration how long a message will stay is automatically
|
||||
* calculated based on amount of text.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_billboard_post_message (ClapperGtkBillboard *self,
|
||||
const gchar *icon_name, const gchar *message)
|
||||
{
|
||||
_post_message_internal (self, icon_name, message, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_billboard_pin_message:
|
||||
* @billboard: a #ClapperGtkBillboard
|
||||
* @icon_name: an icon name
|
||||
* @message: a message text
|
||||
*
|
||||
* Pins a permanent message on the @billboard.
|
||||
*
|
||||
* The message will stay on the @billboard until a
|
||||
* [method@ClapperGtk.Billboard.unpin_pinned_message] is called.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_billboard_pin_message (ClapperGtkBillboard *self,
|
||||
const gchar *icon_name, const gchar *message)
|
||||
{
|
||||
_post_message_internal (self, icon_name, message, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_billboard_unpin_pinned_message:
|
||||
* @billboard: a #ClapperGtkBillboard
|
||||
*
|
||||
* Unpins previously pinned message on the @billboard.
|
||||
*
|
||||
* If no message was pinned this function will do nothing,
|
||||
* so it is safe to call when unsure.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_billboard_unpin_pinned_message (ClapperGtkBillboard *self)
|
||||
{
|
||||
if (!self->has_pinned)
|
||||
return;
|
||||
|
||||
_unreveal_message_delay_cb (self);
|
||||
self->has_pinned = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_billboard_announce_volume:
|
||||
* @billboard: a #ClapperGtkBillboard
|
||||
*
|
||||
* Temporarily displays current volume level on the
|
||||
* side of @billboard.
|
||||
*
|
||||
* Use this if you want to present current volume level to the user.
|
||||
* Note that @billboard also automatically announces volume changes.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_billboard_announce_volume (ClapperGtkBillboard *self)
|
||||
{
|
||||
gdouble volume = PERCENTAGE_ROUND (clapper_player_get_volume (self->player));
|
||||
gchar *percent_str;
|
||||
gboolean has_overamp;
|
||||
|
||||
/* Revert popup_speed changes */
|
||||
gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (self->bottom_progress), TRUE);
|
||||
|
||||
has_overamp = gtk_widget_has_css_class (self->progress_box, "overamp");
|
||||
percent_str = g_strdup_printf ("%.0lf%%", volume * 100);
|
||||
|
||||
if (volume <= 1.0) {
|
||||
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (self->top_progress), 0.0);
|
||||
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (self->bottom_progress), volume);
|
||||
|
||||
if (has_overamp)
|
||||
gtk_widget_remove_css_class (self->progress_box, "overamp");
|
||||
} else {
|
||||
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (self->top_progress), volume - 1.0);
|
||||
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (self->bottom_progress), 1.0);
|
||||
|
||||
if (!has_overamp)
|
||||
gtk_widget_add_css_class (self->progress_box, "overamp");
|
||||
}
|
||||
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (self->progress_image),
|
||||
clapper_gtk_get_icon_name_for_volume ((!self->mute) ? volume : 0));
|
||||
gtk_label_set_label (GTK_LABEL (self->progress_label), percent_str);
|
||||
|
||||
g_free (percent_str);
|
||||
|
||||
reveal_side (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_billboard_announce_speed:
|
||||
* @billboard: a #ClapperGtkBillboard
|
||||
*
|
||||
* Temporarily displays current speed value on the
|
||||
* side of @billboard.
|
||||
*
|
||||
* Use this if you want to present current speed value to the user.
|
||||
* Note that @billboard also automatically announces speed changes.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_billboard_announce_speed (ClapperGtkBillboard *self)
|
||||
{
|
||||
gdouble speed = PERCENTAGE_ROUND (clapper_player_get_speed (self->player));
|
||||
gchar *speed_str;
|
||||
|
||||
/* Revert popup_volume changes */
|
||||
if (gtk_widget_has_css_class (self->progress_box, "overamp"))
|
||||
gtk_widget_remove_css_class (self->progress_box, "overamp");
|
||||
|
||||
gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (self->bottom_progress), FALSE);
|
||||
|
||||
speed_str = g_strdup_printf ("%.2lfx", speed);
|
||||
|
||||
if (speed <= 1.0) {
|
||||
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (self->top_progress), 0.0);
|
||||
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (self->bottom_progress), 1.0 - speed);
|
||||
} else {
|
||||
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (self->top_progress), speed - 1.0);
|
||||
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (self->bottom_progress), 0.0);
|
||||
}
|
||||
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (self->progress_image),
|
||||
clapper_gtk_get_icon_name_for_speed (speed));
|
||||
gtk_label_set_label (GTK_LABEL (self->progress_label), speed_str);
|
||||
|
||||
g_free (speed_str);
|
||||
|
||||
reveal_side (self);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_billboard_root (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkBillboard *self = CLAPPER_GTK_BILLBOARD_CAST (widget);
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->root (widget);
|
||||
|
||||
if ((self->player = clapper_gtk_get_player_from_ancestor (widget))) {
|
||||
g_signal_connect (self->player, "notify::mute",
|
||||
G_CALLBACK (_player_mute_changed_cb), self);
|
||||
self->mute = clapper_player_get_mute (self->player);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_billboard_unroot (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkBillboard *self = CLAPPER_GTK_BILLBOARD_CAST (widget);
|
||||
|
||||
if (self->player) {
|
||||
g_signal_handlers_disconnect_by_func (self->player, _player_mute_changed_cb, self);
|
||||
|
||||
self->player = NULL;
|
||||
}
|
||||
|
||||
/* Reset in case of rooted again not within video widget */
|
||||
self->mute = FALSE;
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->unroot (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_billboard_init (ClapperGtkBillboard *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_billboard_dispose (GObject *object)
|
||||
{
|
||||
gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_GTK_TYPE_BILLBOARD);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_billboard_finalize (GObject *object)
|
||||
{
|
||||
ClapperGtkBillboard *self = CLAPPER_GTK_BILLBOARD_CAST (object);
|
||||
|
||||
g_clear_handle_id (&self->side_timeout, g_source_remove);
|
||||
g_clear_handle_id (&self->message_timeout, g_source_remove);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_billboard_class_init (ClapperGtkBillboardClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtkbillboard", 0,
|
||||
"Clapper GTK Billboard");
|
||||
|
||||
gobject_class->dispose = clapper_gtk_billboard_dispose;
|
||||
gobject_class->finalize = clapper_gtk_billboard_finalize;
|
||||
|
||||
/* Using root/unroot since initially invisible (unrealized)
|
||||
* and we want for signals to stay connected as long as parented */
|
||||
widget_class->root = clapper_gtk_billboard_root;
|
||||
widget_class->unroot = clapper_gtk_billboard_unroot;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class,
|
||||
CLAPPER_GTK_RESOURCE_PREFIX "/ui/clapper-gtk-billboard.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkBillboard, side_revealer);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkBillboard, progress_box);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkBillboard, progress_revealer);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkBillboard, top_progress);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkBillboard, bottom_progress);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkBillboard, progress_image);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkBillboard, progress_label);
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkBillboard, message_revealer);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkBillboard, message_image);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkBillboard, message_label);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, adapt_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, revealer_revealed_cb);
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, "clapper-gtk-billboard");
|
||||
}
|
51
src/lib/clapper-gtk/clapper-gtk-billboard.h
Normal file
51
src/lib/clapper-gtk/clapper-gtk-billboard.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <clapper-gtk/clapper-gtk-container.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_BILLBOARD (clapper_gtk_billboard_get_type())
|
||||
#define CLAPPER_GTK_BILLBOARD_CAST(obj) ((ClapperGtkBillboard *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkBillboard, clapper_gtk_billboard, CLAPPER_GTK, BILLBOARD, ClapperGtkContainer)
|
||||
|
||||
GtkWidget * clapper_gtk_billboard_new (void);
|
||||
|
||||
void clapper_gtk_billboard_post_message (ClapperGtkBillboard *billboard, const gchar *icon_name, const gchar *message);
|
||||
|
||||
void clapper_gtk_billboard_pin_message (ClapperGtkBillboard *billboard, const gchar *icon_name, const gchar *message);
|
||||
|
||||
void clapper_gtk_billboard_unpin_pinned_message (ClapperGtkBillboard *billboard);
|
||||
|
||||
void clapper_gtk_billboard_announce_volume (ClapperGtkBillboard *billboard);
|
||||
|
||||
void clapper_gtk_billboard_announce_speed (ClapperGtkBillboard *billboard);
|
||||
|
||||
G_END_DECLS
|
@@ -0,0 +1,41 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "clapper-gtk-container.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_BUFFERING_ANIMATION (clapper_gtk_buffering_animation_get_type())
|
||||
#define CLAPPER_GTK_BUFFERING_ANIMATION_CAST(obj) ((ClapperGtkBufferingAnimation *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkBufferingAnimation, clapper_gtk_buffering_animation, CLAPPER_GTK, BUFFERING_ANIMATION, ClapperGtkContainer)
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_gtk_buffering_animation_start (ClapperGtkBufferingAnimation *animation);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_gtk_buffering_animation_stop (ClapperGtkBufferingAnimation *animation);
|
||||
|
||||
G_END_DECLS
|
140
src/lib/clapper-gtk/clapper-gtk-buffering-animation.c
Normal file
140
src/lib/clapper-gtk/clapper-gtk-buffering-animation.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <clapper/clapper.h>
|
||||
|
||||
#include "clapper-gtk-buffering-animation-private.h"
|
||||
#include "clapper-gtk-buffering-paintable-private.h"
|
||||
|
||||
#define MIN_STEP_DELAY 30000
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_gtk_buffering_animation_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
struct _ClapperGtkBufferingAnimation
|
||||
{
|
||||
ClapperGtkContainer parent;
|
||||
|
||||
ClapperGtkBufferingPaintable *buffering_paintable;
|
||||
|
||||
guint tick_id;
|
||||
gint64 last_tick;
|
||||
};
|
||||
|
||||
#define parent_class clapper_gtk_buffering_animation_parent_class
|
||||
G_DEFINE_TYPE (ClapperGtkBufferingAnimation, clapper_gtk_buffering_animation, CLAPPER_GTK_TYPE_CONTAINER)
|
||||
|
||||
static gboolean
|
||||
_animation_tick (GtkWidget *picture, GdkFrameClock *frame_clock, ClapperGtkBufferingAnimation *self)
|
||||
{
|
||||
gint64 now = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
|
||||
/* We do not want for this animation to move too fast */
|
||||
if (now - self->last_tick >= MIN_STEP_DELAY) {
|
||||
GST_LOG_OBJECT (self, "Animation step, last: %" G_GINT64_FORMAT
|
||||
", now: %" G_GINT64_FORMAT, self->last_tick, now);
|
||||
clapper_gtk_buffering_paintable_step (self->buffering_paintable);
|
||||
self->last_tick = now;
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
void
|
||||
clapper_gtk_buffering_animation_start (ClapperGtkBufferingAnimation *self)
|
||||
{
|
||||
GtkWidget *picture;
|
||||
|
||||
if (self->tick_id != 0)
|
||||
return;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Animation start");
|
||||
|
||||
picture = clapper_gtk_container_get_child (CLAPPER_GTK_CONTAINER (self));
|
||||
self->tick_id = gtk_widget_add_tick_callback (picture,
|
||||
(GtkTickCallback) _animation_tick, self, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
clapper_gtk_buffering_animation_stop (ClapperGtkBufferingAnimation *self)
|
||||
{
|
||||
GtkWidget *picture;
|
||||
|
||||
if (self->tick_id == 0)
|
||||
return;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Animation stop");
|
||||
|
||||
picture = clapper_gtk_container_get_child (CLAPPER_GTK_CONTAINER (self));
|
||||
gtk_widget_remove_tick_callback (picture, self->tick_id);
|
||||
|
||||
self->tick_id = 0;
|
||||
self->last_tick = 0;
|
||||
clapper_gtk_buffering_paintable_reset (self->buffering_paintable);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_buffering_animation_init (ClapperGtkBufferingAnimation *self)
|
||||
{
|
||||
GtkWidget *picture = gtk_picture_new ();
|
||||
self->buffering_paintable = clapper_gtk_buffering_paintable_new ();
|
||||
|
||||
gtk_picture_set_paintable (GTK_PICTURE (picture),
|
||||
GDK_PAINTABLE (self->buffering_paintable));
|
||||
|
||||
clapper_gtk_container_set_child (CLAPPER_GTK_CONTAINER (self), picture);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_buffering_animation_unmap (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkBufferingAnimation *self = CLAPPER_GTK_BUFFERING_ANIMATION_CAST (widget);
|
||||
|
||||
clapper_gtk_buffering_animation_stop (self);
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->unmap (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_buffering_animation_finalize (GObject *object)
|
||||
{
|
||||
ClapperGtkBufferingAnimation *self = CLAPPER_GTK_BUFFERING_ANIMATION_CAST (object);
|
||||
|
||||
GST_TRACE_OBJECT (self, "Finalize");
|
||||
|
||||
g_object_unref (self->buffering_paintable);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_buffering_animation_class_init (ClapperGtkBufferingAnimationClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtkbufferinganimation", 0,
|
||||
"Clapper GTK Buffering Animation");
|
||||
|
||||
gobject_class->finalize = clapper_gtk_buffering_animation_finalize;
|
||||
|
||||
widget_class->unmap = clapper_gtk_buffering_animation_unmap;
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, "clapper-gtk-buffering-animation");
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_BUFFERING_PAINTABLE (clapper_gtk_buffering_paintable_get_type())
|
||||
#define CLAPPER_GTK_BUFFERING_PAINTABLE_CAST(obj) ((ClapperGtkBufferingPaintable *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkBufferingPaintable, clapper_gtk_buffering_paintable, CLAPPER_GTK, BUFFERING_PAINTABLE, GObject)
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
ClapperGtkBufferingPaintable * clapper_gtk_buffering_paintable_new (void);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_gtk_buffering_paintable_step (ClapperGtkBufferingPaintable *buffering_paintable);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_gtk_buffering_paintable_reset (ClapperGtkBufferingPaintable *buffering_paintable);
|
||||
|
||||
G_END_DECLS
|
177
src/lib/clapper-gtk/clapper-gtk-buffering-paintable.c
Normal file
177
src/lib/clapper-gtk/clapper-gtk-buffering-paintable.c
Normal file
@@ -0,0 +1,177 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "clapper-gtk-buffering-paintable-private.h"
|
||||
|
||||
#define CIRCLE_MAX_SIZE 48
|
||||
#define CIRCLE_SPACING 10
|
||||
#define CIRCLE_OUTLINE 2
|
||||
#define INTRINSIC_SIZE 184 // 3 * CIRCLE_MAX_SIZE + 4 * CIRCLE_SPACING
|
||||
|
||||
#define BLACK ((GdkRGBA) { 0, 0, 0, 1 })
|
||||
#define WHITE ((GdkRGBA) { 1, 1, 1, 1 })
|
||||
|
||||
struct _ClapperGtkBufferingPaintable
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
gfloat sizes[3]; // current size of each circle
|
||||
gboolean reverses[3]; // grow/shrink direction
|
||||
gboolean initialized[3]; // big enough to start growing the next one
|
||||
};
|
||||
|
||||
static GdkPaintableFlags
|
||||
clapper_gtk_buffering_paintable_get_flags (GdkPaintable *paintable)
|
||||
{
|
||||
return GDK_PAINTABLE_STATIC_SIZE;
|
||||
}
|
||||
|
||||
static gint
|
||||
clapper_gtk_buffering_paintable_get_intrinsic_size (GdkPaintable *paintable)
|
||||
{
|
||||
return INTRINSIC_SIZE;
|
||||
}
|
||||
|
||||
static void
|
||||
_draw_scaled_circle (GdkSnapshot *snapshot, gfloat scale)
|
||||
{
|
||||
GskRoundedRect outline;
|
||||
gfloat half_size = ((gfloat) CIRCLE_MAX_SIZE / 2) * scale;
|
||||
gfloat inside_size = ((gfloat) (CIRCLE_MAX_SIZE - 2 * CIRCLE_OUTLINE) / 2) * scale;
|
||||
|
||||
/* Draw white inner circle */
|
||||
gsk_rounded_rect_init_from_rect (&outline,
|
||||
&GRAPHENE_RECT_INIT (-inside_size, -inside_size, 2 * inside_size, 2 * inside_size), inside_size);
|
||||
gtk_snapshot_append_border (snapshot, &outline,
|
||||
(gfloat[4]) { inside_size, inside_size, inside_size, inside_size },
|
||||
(GdkRGBA[4]) { WHITE, WHITE, WHITE, WHITE });
|
||||
|
||||
/* Draw black circle border */
|
||||
gsk_rounded_rect_init_from_rect (&outline,
|
||||
&GRAPHENE_RECT_INIT (-half_size, -half_size, 2 * half_size, 2 * half_size), half_size);
|
||||
gtk_snapshot_append_border (snapshot, &outline,
|
||||
(gfloat[4]) { CIRCLE_OUTLINE, CIRCLE_OUTLINE, CIRCLE_OUTLINE, CIRCLE_OUTLINE },
|
||||
(GdkRGBA[4]) { BLACK, BLACK, BLACK, BLACK });
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_buffering_paintable_snapshot (GdkPaintable *paintable,
|
||||
GdkSnapshot *snapshot, gdouble width, gdouble height)
|
||||
{
|
||||
ClapperGtkBufferingPaintable *self = CLAPPER_GTK_BUFFERING_PAINTABLE_CAST (paintable);
|
||||
guint i;
|
||||
|
||||
gtk_snapshot_save (snapshot);
|
||||
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (0, height / 2));
|
||||
gtk_snapshot_scale (snapshot, MIN (width, height) / INTRINSIC_SIZE, MIN (width, height) / INTRINSIC_SIZE);
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (CIRCLE_SPACING + CIRCLE_MAX_SIZE / 2, 0));
|
||||
_draw_scaled_circle (snapshot, self->sizes[i]);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (CIRCLE_MAX_SIZE / 2, 0));
|
||||
}
|
||||
|
||||
gtk_snapshot_restore (snapshot);
|
||||
}
|
||||
|
||||
static GdkPaintable *
|
||||
clapper_gtk_buffering_paintable_get_current_image (GdkPaintable *paintable)
|
||||
{
|
||||
ClapperGtkBufferingPaintable *self = CLAPPER_GTK_BUFFERING_PAINTABLE_CAST (paintable);
|
||||
ClapperGtkBufferingPaintable *copy = clapper_gtk_buffering_paintable_new ();
|
||||
guint i;
|
||||
|
||||
/* Only current sizes are needed for static image */
|
||||
for (i = 0; i < 3; ++i)
|
||||
copy->sizes[i] = self->sizes[i];
|
||||
|
||||
return GDK_PAINTABLE (copy);
|
||||
}
|
||||
|
||||
static void
|
||||
_paintable_iface_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
iface->get_flags = clapper_gtk_buffering_paintable_get_flags;
|
||||
iface->get_intrinsic_width = clapper_gtk_buffering_paintable_get_intrinsic_size;
|
||||
iface->get_intrinsic_height = clapper_gtk_buffering_paintable_get_intrinsic_size;
|
||||
iface->snapshot = clapper_gtk_buffering_paintable_snapshot;
|
||||
iface->get_current_image = clapper_gtk_buffering_paintable_get_current_image;
|
||||
}
|
||||
|
||||
#define parent_class clapper_gtk_buffering_paintable_parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE (ClapperGtkBufferingPaintable, clapper_gtk_buffering_paintable, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE, _paintable_iface_init))
|
||||
|
||||
ClapperGtkBufferingPaintable *
|
||||
clapper_gtk_buffering_paintable_new (void)
|
||||
{
|
||||
return g_object_new (CLAPPER_GTK_TYPE_BUFFERING_PAINTABLE, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
clapper_gtk_buffering_paintable_step (ClapperGtkBufferingPaintable *self)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
/* If previous circle is not big enough
|
||||
* do not start animating the next one */
|
||||
if (i > 0 && !self->initialized[i - 1])
|
||||
break;
|
||||
|
||||
if (!self->initialized[i] && self->sizes[i] >= 0.3)
|
||||
self->initialized[i] = TRUE;
|
||||
|
||||
self->sizes[i] += (self->reverses[i]) ? -0.04 : 0.04;
|
||||
if (self->sizes[i] > 1.0) {
|
||||
self->sizes[i] = 1.0;
|
||||
self->reverses[i] = TRUE;
|
||||
} else if (self->sizes[i] < 0.0) {
|
||||
self->sizes[i] = 0.0;
|
||||
self->reverses[i] = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gdk_paintable_invalidate_contents ((GdkPaintable *) self);
|
||||
}
|
||||
|
||||
void
|
||||
clapper_gtk_buffering_paintable_reset (ClapperGtkBufferingPaintable *self)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
self->sizes[i] = 0;
|
||||
self->reverses[i] = FALSE;
|
||||
self->initialized[i] = FALSE;
|
||||
}
|
||||
|
||||
gdk_paintable_invalidate_contents ((GdkPaintable *) self);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_buffering_paintable_init (ClapperGtkBufferingPaintable *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_buffering_paintable_class_init (ClapperGtkBufferingPaintableClass *klass)
|
||||
{
|
||||
}
|
28
src/lib/clapper-gtk/clapper-gtk-container-private.h
Normal file
28
src/lib/clapper-gtk/clapper-gtk-container-private.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "clapper-gtk-container.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void clapper_gtk_container_emit_adapt (ClapperGtkContainer *container, gboolean adapt);
|
||||
|
||||
G_END_DECLS
|
413
src/lib/clapper-gtk/clapper-gtk-container.c
Normal file
413
src/lib/clapper-gtk/clapper-gtk-container.c
Normal file
@@ -0,0 +1,413 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClapperGtkContainer:
|
||||
*
|
||||
* A simple container widget that holds just one child.
|
||||
*
|
||||
* It is designed to work well with OSD overlay, adding some useful functionalities
|
||||
* to it, such as width and height that widget should target. This helps with
|
||||
* implementing simple adaptive widgets by observing its own width and signalling
|
||||
* when adaptive threshold is reached.
|
||||
*
|
||||
* You can use this when you need to create a widget that is adaptive or should have
|
||||
* a limited maximal width/height.
|
||||
*
|
||||
* If you need to have more then single widget as child, place a widget that
|
||||
* can hold multiple children such as [class@Gtk.Box] as a single conatiner child
|
||||
* and then your widgets into that child.
|
||||
*/
|
||||
|
||||
#include "clapper-gtk-container.h"
|
||||
#include "clapper-gtk-container-private.h"
|
||||
#include "clapper-gtk-limited-layout-private.h"
|
||||
|
||||
#define parent_class clapper_gtk_container_parent_class
|
||||
G_DEFINE_TYPE (ClapperGtkContainer, clapper_gtk_container, GTK_TYPE_WIDGET)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_WIDTH_TARGET,
|
||||
PROP_HEIGHT_TARGET,
|
||||
PROP_ADAPTIVE_WIDTH,
|
||||
PROP_ADAPTIVE_HEIGHT,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SIGNAL_ADAPT,
|
||||
SIGNAL_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
|
||||
static guint signals[SIGNAL_LAST] = { 0, };
|
||||
|
||||
static inline void
|
||||
_unparent_child (ClapperGtkContainer *self)
|
||||
{
|
||||
GtkWidget *child;
|
||||
|
||||
if ((child = gtk_widget_get_first_child (GTK_WIDGET (self))))
|
||||
gtk_widget_unparent (child);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_container_new:
|
||||
*
|
||||
* Creates a new #ClapperGtkContainer instance.
|
||||
*
|
||||
* Returns: a new container #GtkWidget.
|
||||
*/
|
||||
GtkWidget *
|
||||
clapper_gtk_container_new (void)
|
||||
{
|
||||
return g_object_new (CLAPPER_GTK_TYPE_CONTAINER, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_container_set_child:
|
||||
* @container: a #ClapperGtkContainer
|
||||
*
|
||||
* Set a child #GtkWidget of @container.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_container_set_child (ClapperGtkContainer *self, GtkWidget *child)
|
||||
{
|
||||
g_return_if_fail (CLAPPER_GTK_IS_CONTAINER (self));
|
||||
g_return_if_fail (GTK_IS_WIDGET (child));
|
||||
|
||||
_unparent_child (self);
|
||||
gtk_widget_set_parent (child, GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_container_get_child:
|
||||
* @container: a #ClapperGtkContainer
|
||||
*
|
||||
* Get a child #GtkWidget of @container.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): #GtkWidget set as child.
|
||||
*/
|
||||
GtkWidget *
|
||||
clapper_gtk_container_get_child (ClapperGtkContainer *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_CONTAINER (self), NULL);
|
||||
|
||||
return gtk_widget_get_first_child (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_container_set_width_target:
|
||||
* @container: a #ClapperGtkContainer
|
||||
* @width: width to target -1 to restore default behavior
|
||||
*
|
||||
* Set a width that @container should target. When set container
|
||||
* will not stretch beyond set @width while still expanding into
|
||||
* possible boundaries trying to reach its target.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_container_set_width_target (ClapperGtkContainer *self, gint width)
|
||||
{
|
||||
GtkLayoutManager *layout;
|
||||
|
||||
g_return_if_fail (CLAPPER_GTK_IS_CONTAINER (self));
|
||||
|
||||
layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
clapper_gtk_limited_layout_set_max_width (CLAPPER_GTK_LIMITED_LAYOUT_CAST (layout), width);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_container_get_width_target:
|
||||
* @container: a #ClapperGtkContainer
|
||||
*
|
||||
* Get a @container width target.
|
||||
*
|
||||
* Returns: width target set by user or -1 when none.
|
||||
*/
|
||||
gint
|
||||
clapper_gtk_container_get_width_target (ClapperGtkContainer *self)
|
||||
{
|
||||
GtkLayoutManager *layout;
|
||||
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_CONTAINER (self), -1);
|
||||
|
||||
layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
return clapper_gtk_limited_layout_get_max_width (CLAPPER_GTK_LIMITED_LAYOUT_CAST (layout));
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_container_set_height_target:
|
||||
* @container: a #ClapperGtkContainer
|
||||
* @height: height to target or -1 to restore default behavior
|
||||
*
|
||||
* Same as clapper_gtk_container_set_width_target() but for widget height.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_container_set_height_target (ClapperGtkContainer *self, gint height)
|
||||
{
|
||||
GtkLayoutManager *layout;
|
||||
|
||||
g_return_if_fail (CLAPPER_GTK_IS_CONTAINER (self));
|
||||
|
||||
layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
clapper_gtk_limited_layout_set_max_height (CLAPPER_GTK_LIMITED_LAYOUT_CAST (layout), height);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_container_get_height_target:
|
||||
* @container: a #ClapperGtkContainer
|
||||
*
|
||||
* Get a @container height target.
|
||||
*
|
||||
* Returns: height target set by user or -1 when none.
|
||||
*/
|
||||
gint
|
||||
clapper_gtk_container_get_height_target (ClapperGtkContainer *self)
|
||||
{
|
||||
GtkLayoutManager *layout;
|
||||
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_CONTAINER (self), -1);
|
||||
|
||||
layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
return clapper_gtk_limited_layout_get_max_height (CLAPPER_GTK_LIMITED_LAYOUT_CAST (layout));
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_container_set_adaptive_width:
|
||||
* @container: a #ClapperGtkContainer
|
||||
* @width: a threshold on which adapt signal should be triggered or -1 to disable.
|
||||
*
|
||||
* Set an adaptive width threshold. When widget is resized to value or lower,
|
||||
* an [signal@ClapperGtk.Container::adapt] signal will be emitted with %TRUE to
|
||||
* notify implementation about mobile adaptation request, otherwise %FALSE when
|
||||
* both threshold values are exceeded.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_container_set_adaptive_width (ClapperGtkContainer *self, gint width)
|
||||
{
|
||||
GtkLayoutManager *layout;
|
||||
|
||||
g_return_if_fail (CLAPPER_GTK_IS_CONTAINER (self));
|
||||
|
||||
layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
clapper_gtk_limited_layout_set_adaptive_width (
|
||||
CLAPPER_GTK_LIMITED_LAYOUT_CAST (layout), width);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_container_get_adaptive_width:
|
||||
* @container: a #ClapperGtkContainer
|
||||
*
|
||||
* Get a @container adaptive width threshold.
|
||||
*
|
||||
* Returns: adaptive width set by user or -1 when none.
|
||||
*/
|
||||
gint
|
||||
clapper_gtk_container_get_adaptive_width (ClapperGtkContainer *self)
|
||||
{
|
||||
GtkLayoutManager *layout;
|
||||
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_CONTAINER (self), -1);
|
||||
|
||||
layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
return clapper_gtk_limited_layout_get_adaptive_width (CLAPPER_GTK_LIMITED_LAYOUT_CAST (layout));
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_container_set_adaptive_height:
|
||||
* @container: a #ClapperGtkContainer
|
||||
* @height: a threshold on which adapt signal should be triggered or -1 to disable.
|
||||
*
|
||||
* Set an adaptive height threshold. When widget is resized to value or lower,
|
||||
* an [signal@ClapperGtk.Container::adapt] signal will be emitted with %TRUE to
|
||||
* notify implementation about mobile adaptation request, otherwise %FALSE when
|
||||
* both threshold values are exceeded.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_container_set_adaptive_height (ClapperGtkContainer *self, gint height)
|
||||
{
|
||||
GtkLayoutManager *layout;
|
||||
|
||||
g_return_if_fail (CLAPPER_GTK_IS_CONTAINER (self));
|
||||
|
||||
layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
clapper_gtk_limited_layout_set_adaptive_height (
|
||||
CLAPPER_GTK_LIMITED_LAYOUT_CAST (layout), height);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_container_get_adaptive_height:
|
||||
* @container: a #ClapperGtkContainer
|
||||
*
|
||||
* Get a @container adaptive height threshold.
|
||||
*
|
||||
* Returns: adaptive height set by user or -1 when none.
|
||||
*/
|
||||
gint
|
||||
clapper_gtk_container_get_adaptive_height (ClapperGtkContainer *self)
|
||||
{
|
||||
GtkLayoutManager *layout;
|
||||
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_CONTAINER (self), -1);
|
||||
|
||||
layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
return clapper_gtk_limited_layout_get_adaptive_height (CLAPPER_GTK_LIMITED_LAYOUT_CAST (layout));
|
||||
}
|
||||
|
||||
void
|
||||
clapper_gtk_container_emit_adapt (ClapperGtkContainer *self, gboolean adapt)
|
||||
{
|
||||
if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
|
||||
signals[SIGNAL_ADAPT], 0, NULL, NULL, NULL) != 0) {
|
||||
g_signal_emit (self, signals[SIGNAL_ADAPT], 0, adapt);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_container_init (ClapperGtkContainer *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_container_dispose (GObject *object)
|
||||
{
|
||||
ClapperGtkContainer *self = CLAPPER_GTK_CONTAINER_CAST (object);
|
||||
|
||||
_unparent_child (self);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_container_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkContainer *self = CLAPPER_GTK_CONTAINER_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_WIDTH_TARGET:
|
||||
g_value_set_int (value, clapper_gtk_container_get_width_target (self));
|
||||
break;
|
||||
case PROP_HEIGHT_TARGET:
|
||||
g_value_set_int (value, clapper_gtk_container_get_height_target (self));
|
||||
break;
|
||||
case PROP_ADAPTIVE_WIDTH:
|
||||
g_value_set_int (value, clapper_gtk_container_get_adaptive_width (self));
|
||||
break;
|
||||
case PROP_ADAPTIVE_HEIGHT:
|
||||
g_value_set_int (value, clapper_gtk_container_get_adaptive_height (self));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_container_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkContainer *self = CLAPPER_GTK_CONTAINER_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_WIDTH_TARGET:
|
||||
clapper_gtk_container_set_width_target (self, g_value_get_int (value));
|
||||
break;
|
||||
case PROP_HEIGHT_TARGET:
|
||||
clapper_gtk_container_set_height_target (self, g_value_get_int (value));
|
||||
break;
|
||||
case PROP_ADAPTIVE_WIDTH:
|
||||
clapper_gtk_container_set_adaptive_width (self, g_value_get_int (value));
|
||||
break;
|
||||
case PROP_ADAPTIVE_HEIGHT:
|
||||
clapper_gtk_container_set_adaptive_height (self, g_value_get_int (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_container_class_init (ClapperGtkContainerClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
|
||||
gobject_class->get_property = clapper_gtk_container_get_property;
|
||||
gobject_class->set_property = clapper_gtk_container_set_property;
|
||||
gobject_class->dispose = clapper_gtk_container_dispose;
|
||||
|
||||
/**
|
||||
* ClapperGtkContainer:width-target:
|
||||
*
|
||||
* Width that container should target.
|
||||
*/
|
||||
param_specs[PROP_WIDTH_TARGET] = g_param_spec_int ("width-target",
|
||||
NULL, NULL, -1, G_MAXINT, -1,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClapperGtkContainer:height-target:
|
||||
*
|
||||
* Height that container should target.
|
||||
*/
|
||||
param_specs[PROP_HEIGHT_TARGET] = g_param_spec_int ("height-target",
|
||||
NULL, NULL, -1, G_MAXINT, -1,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClapperGtkContainer:adaptive-width:
|
||||
*
|
||||
* Adaptive width threshold that triggers [signal@ClapperGtk.Container::adapt] signal.
|
||||
*/
|
||||
param_specs[PROP_ADAPTIVE_WIDTH] = g_param_spec_int ("adaptive-width",
|
||||
NULL, NULL, -1, G_MAXINT, -1,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClapperGtkContainer:adaptive-height:
|
||||
*
|
||||
* Adaptive height threshold that triggers [signal@ClapperGtk.Container::adapt] signal.
|
||||
*/
|
||||
param_specs[PROP_ADAPTIVE_HEIGHT] = g_param_spec_int ("adaptive-height",
|
||||
NULL, NULL, -1, G_MAXINT, -1,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClapperGtkContainer::adapt:
|
||||
* @container: a #ClapperGtkContainer
|
||||
* @adapt: %TRUE if narrowness reached adaptive threshold, %FALSE otherwise
|
||||
*
|
||||
* A helper signal for implementing mobile/narrow adaptive
|
||||
* behavior on descendants.
|
||||
*/
|
||||
signals[SIGNAL_ADAPT] = g_signal_new ("adapt",
|
||||
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
|
||||
0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, CLAPPER_GTK_TYPE_LIMITED_LAYOUT);
|
||||
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GENERIC);
|
||||
gtk_widget_class_set_css_name (widget_class, "clapper-gtk-container");
|
||||
}
|
67
src/lib/clapper-gtk/clapper-gtk-container.h
Normal file
67
src/lib/clapper-gtk/clapper-gtk-container.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_CONTAINER (clapper_gtk_container_get_type())
|
||||
#define CLAPPER_GTK_CONTAINER_CAST(obj) ((ClapperGtkContainer *)(obj))
|
||||
|
||||
G_DECLARE_DERIVABLE_TYPE (ClapperGtkContainer, clapper_gtk_container, CLAPPER_GTK, CONTAINER, GtkWidget)
|
||||
|
||||
struct _ClapperGtkContainerClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
gpointer padding[4];
|
||||
};
|
||||
|
||||
GtkWidget * clapper_gtk_container_new (void);
|
||||
|
||||
void clapper_gtk_container_set_child (ClapperGtkContainer *container, GtkWidget *child);
|
||||
|
||||
GtkWidget * clapper_gtk_container_get_child (ClapperGtkContainer *container);
|
||||
|
||||
void clapper_gtk_container_set_width_target (ClapperGtkContainer *container, gint width);
|
||||
|
||||
gint clapper_gtk_container_get_width_target (ClapperGtkContainer *container);
|
||||
|
||||
void clapper_gtk_container_set_height_target (ClapperGtkContainer *container, gint height);
|
||||
|
||||
gint clapper_gtk_container_get_height_target (ClapperGtkContainer *container);
|
||||
|
||||
void clapper_gtk_container_set_adaptive_width (ClapperGtkContainer *container, gint width);
|
||||
|
||||
gint clapper_gtk_container_get_adaptive_width (ClapperGtkContainer *container);
|
||||
|
||||
void clapper_gtk_container_set_adaptive_height (ClapperGtkContainer *container, gint height);
|
||||
|
||||
gint clapper_gtk_container_get_adaptive_height (ClapperGtkContainer *container);
|
||||
|
||||
G_END_DECLS
|
50
src/lib/clapper-gtk/clapper-gtk-enums.h
Normal file
50
src/lib/clapper-gtk/clapper-gtk-enums.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <clapper-gtk/clapper-gtk-enum-types.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* ClapperGtkVideoActionMask:
|
||||
* @CLAPPER_GTK_VIDEO_ACTION_NONE: No action
|
||||
* @CLAPPER_GTK_VIDEO_ACTION_REVEAL_OVERLAYS: Reveal fading overlays
|
||||
* @CLAPPER_GTK_VIDEO_ACTION_TOGGLE_PLAY: Toggle playback (triggered by single click/tap)
|
||||
* @CLAPPER_GTK_VIDEO_ACTION_TOGGLE_FULLSCREEN: Toggle fullscreen (triggered by double click/tap)
|
||||
* @CLAPPER_GTK_VIDEO_ACTION_SEEK_REQUEST: Seek request (triggered by double tap on screen side)
|
||||
* @CLAPPER_GTK_VIDEO_ACTION_ANY: All of the above
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CLAPPER_GTK_VIDEO_ACTION_NONE = 0,
|
||||
CLAPPER_GTK_VIDEO_ACTION_REVEAL_OVERLAYS = 1 << 0,
|
||||
CLAPPER_GTK_VIDEO_ACTION_TOGGLE_PLAY = 1 << 1,
|
||||
CLAPPER_GTK_VIDEO_ACTION_TOGGLE_FULLSCREEN = 1 << 2,
|
||||
CLAPPER_GTK_VIDEO_ACTION_SEEK_REQUEST = 1 << 3,
|
||||
CLAPPER_GTK_VIDEO_ACTION_ANY = 0x3FFFFFF
|
||||
} ClapperGtkVideoActionMask;
|
||||
|
||||
G_END_DECLS
|
801
src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c
Normal file
801
src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c
Normal file
@@ -0,0 +1,801 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClapperGtkExtraMenuButton:
|
||||
*
|
||||
* A menu button with extra options.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <clapper/clapper.h>
|
||||
|
||||
#include "clapper-gtk-extra-menu-button.h"
|
||||
#include "clapper-gtk-utils-private.h"
|
||||
|
||||
#define PERCENTAGE_ROUND(a) (round ((gdouble) a / 0.01) * 0.01)
|
||||
|
||||
#define DEFAULT_CAN_OPEN_SUBTITLES FALSE
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_gtk_extra_menu_button_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
struct _ClapperGtkExtraMenuButton
|
||||
{
|
||||
GtkWidget parent;
|
||||
|
||||
GtkWidget *menu_button;
|
||||
|
||||
GtkWidget *volume_box;
|
||||
GtkWidget *volume_button;
|
||||
GtkWidget *volume_spin;
|
||||
|
||||
GtkWidget *speed_box;
|
||||
GtkWidget *speed_button;
|
||||
GtkWidget *speed_spin;
|
||||
|
||||
GtkWidget *top_separator;
|
||||
|
||||
GtkWidget *video_list_view;
|
||||
GtkScrolledWindow *video_sw;
|
||||
|
||||
GtkWidget *audio_list_view;
|
||||
GtkScrolledWindow *audio_sw;
|
||||
|
||||
GtkWidget *subtitle_list_view;
|
||||
GtkScrolledWindow *subtitle_sw;
|
||||
|
||||
ClapperPlayer *player;
|
||||
ClapperMediaItem *current_item;
|
||||
|
||||
GSimpleActionGroup *action_group;
|
||||
|
||||
gboolean mute;
|
||||
|
||||
GBinding *volume_binding;
|
||||
GBinding *speed_binding;
|
||||
|
||||
GBinding *video_binding;
|
||||
GBinding *audio_binding;
|
||||
GBinding *subtitle_binding;
|
||||
|
||||
gboolean can_open_subtitles;
|
||||
};
|
||||
|
||||
#define parent_class clapper_gtk_extra_menu_button_parent_class
|
||||
G_DEFINE_TYPE (ClapperGtkExtraMenuButton, clapper_gtk_extra_menu_button, GTK_TYPE_WIDGET)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_VOLUME_VISIBLE,
|
||||
PROP_SPEED_VISIBLE,
|
||||
PROP_CAN_OPEN_SUBTITLES,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SIGNAL_OPEN_SUBTITLES,
|
||||
SIGNAL_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
|
||||
static guint signals[SIGNAL_LAST] = { 0, };
|
||||
|
||||
static void
|
||||
_set_action_enabled (ClapperGtkExtraMenuButton *self, const gchar *name, gboolean enabled)
|
||||
{
|
||||
GAction *action = g_action_map_lookup_action (G_ACTION_MAP (self->action_group), name);
|
||||
gboolean was_enabled = g_action_get_enabled (action);
|
||||
|
||||
if (was_enabled == enabled)
|
||||
return;
|
||||
|
||||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enabled);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_double_transform_func (GBinding *binding, const GValue *from_value,
|
||||
GValue *to_value, gpointer user_data G_GNUC_UNUSED)
|
||||
{
|
||||
gdouble val_dbl = g_value_get_double (from_value);
|
||||
|
||||
g_value_set_double (to_value, PERCENTAGE_ROUND (val_dbl));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
volume_spin_input_cb (GtkSpinButton *spin_button, gdouble *value, ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
const gchar *text = gtk_editable_get_text (GTK_EDITABLE (spin_button));
|
||||
gchar *sign = NULL;
|
||||
gdouble volume = g_ascii_strtod (text, &sign);
|
||||
|
||||
if (volume < 0 || volume > 200
|
||||
|| (sign && sign[0] != '\0' && sign[0] != '%'))
|
||||
return GTK_INPUT_ERROR;
|
||||
|
||||
volume /= 100.0;
|
||||
|
||||
if (volume > 0.99 && volume < 1.01)
|
||||
volume = 1.0;
|
||||
|
||||
*value = volume;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
volume_spin_output_cb (GtkSpinButton *spin_button, ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin_button);
|
||||
gdouble volume = gtk_adjustment_get_value (adjustment);
|
||||
gchar *volume_str;
|
||||
|
||||
volume_str = g_strdup_printf ("%.0lf%%", volume * 100);
|
||||
gtk_editable_set_text (GTK_EDITABLE (spin_button), volume_str);
|
||||
g_free (volume_str);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
volume_spin_changed_cb (GtkSpinButton *spin_button, ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin_button);
|
||||
gdouble volume = gtk_adjustment_get_value (adjustment);
|
||||
|
||||
gtk_button_set_icon_name (GTK_BUTTON (self->volume_button),
|
||||
clapper_gtk_get_icon_name_for_volume ((!self->mute) ? volume : 0));
|
||||
}
|
||||
|
||||
static gint
|
||||
speed_spin_input_cb (GtkSpinButton *spin_button, gdouble *value, ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
const gchar *text = gtk_editable_get_text (GTK_EDITABLE (spin_button));
|
||||
gchar *sign = NULL;
|
||||
gdouble speed = g_ascii_strtod (text, &sign);
|
||||
|
||||
if (speed < 0.05 || speed > 2.0
|
||||
|| (sign && sign[0] != '\0' && sign[0] != 'x'))
|
||||
return GTK_INPUT_ERROR;
|
||||
|
||||
if (speed > 0.99 && speed < 1.01)
|
||||
speed = 1.0;
|
||||
|
||||
*value = speed;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
speed_spin_output_cb (GtkSpinButton *spin_button, ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin_button);
|
||||
gdouble speed = gtk_adjustment_get_value (adjustment);
|
||||
gchar *speed_str;
|
||||
|
||||
speed_str = g_strdup_printf ("%.2lfx", speed);
|
||||
gtk_editable_set_text (GTK_EDITABLE (spin_button), speed_str);
|
||||
g_free (speed_str);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
speed_spin_changed_cb (GtkSpinButton *spin_button, ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin_button);
|
||||
gdouble speed = gtk_adjustment_get_value (adjustment);
|
||||
|
||||
gtk_button_set_icon_name (GTK_BUTTON (self->speed_button),
|
||||
clapper_gtk_get_icon_name_for_speed (speed));
|
||||
}
|
||||
|
||||
static void
|
||||
visible_submenu_changed_cb (GtkPopoverMenu *popover_menu,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
gchar *name = NULL;
|
||||
gboolean in_video, in_audio, in_subtitles;
|
||||
|
||||
g_object_get (popover_menu, "visible-submenu", &name, NULL);
|
||||
|
||||
/* TODO: Check if we have to compare translated strings here */
|
||||
GST_DEBUG ("Visible submenu changed to: \"%s\"", name);
|
||||
|
||||
in_video = (g_strcmp0 (name, _("Video")) == 0);
|
||||
in_audio = (g_strcmp0 (name, _("Audio")) == 0);
|
||||
in_subtitles = (g_strcmp0 (name, _("Subtitles")) == 0);
|
||||
|
||||
/* XXX: This works around the issue where popover does not adapt its
|
||||
* width when navigating submenus making spin buttons unnecesary centered */
|
||||
gtk_scrolled_window_set_propagate_natural_width (self->video_sw, in_video);
|
||||
gtk_scrolled_window_set_propagate_natural_width (self->audio_sw, in_audio);
|
||||
gtk_scrolled_window_set_propagate_natural_width (self->subtitle_sw, in_subtitles);
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
static void
|
||||
_subtitles_enabled_changed_cb (ClapperPlayer *player,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
GAction *action = g_action_map_lookup_action (
|
||||
G_ACTION_MAP (self->action_group), "subtitle-stream-enabled");
|
||||
GVariant *variant = g_action_get_state (action);
|
||||
gboolean was_enabled, enabled;
|
||||
|
||||
was_enabled = g_variant_get_boolean (variant);
|
||||
enabled = clapper_player_get_subtitles_enabled (player);
|
||||
|
||||
g_variant_unref (variant);
|
||||
|
||||
if (was_enabled == enabled)
|
||||
return;
|
||||
|
||||
variant = g_variant_ref_sink (g_variant_new_boolean (enabled));
|
||||
|
||||
g_simple_action_set_state (G_SIMPLE_ACTION (action), variant);
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
static void
|
||||
_player_mute_changed_cb (ClapperPlayer *player,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
self->mute = clapper_player_get_mute (player);
|
||||
|
||||
volume_spin_changed_cb (GTK_SPIN_BUTTON (self->volume_spin), self);
|
||||
}
|
||||
|
||||
static void
|
||||
_queue_current_item_changed_cb (ClapperQueue *queue,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
ClapperMediaItem *current_item = clapper_queue_get_current_item (queue);
|
||||
|
||||
/* NOTE: This is also called after popover "map" signal */
|
||||
|
||||
if (gst_object_replace ((GstObject **) &self->current_item, GST_OBJECT_CAST (current_item))) {
|
||||
_set_action_enabled (self, "open-subtitle-stream",
|
||||
(self->can_open_subtitles && self->current_item != NULL));
|
||||
}
|
||||
|
||||
gst_clear_object (¤t_item);
|
||||
}
|
||||
|
||||
static void
|
||||
change_subtitle_stream_enabled (GSimpleAction *action, GVariant *value, gpointer user_data)
|
||||
{
|
||||
ClapperGtkExtraMenuButton *self = CLAPPER_GTK_EXTRA_MENU_BUTTON_CAST (user_data);
|
||||
gboolean enable = g_variant_get_boolean (value);
|
||||
|
||||
if (G_LIKELY (self->player != NULL))
|
||||
clapper_player_set_subtitles_enabled (self->player, enable);
|
||||
|
||||
g_simple_action_set_state (action, value);
|
||||
}
|
||||
|
||||
static void
|
||||
open_subtitle_stream (GSimpleAction *action, GVariant *param, gpointer user_data)
|
||||
{
|
||||
ClapperGtkExtraMenuButton *self = CLAPPER_GTK_EXTRA_MENU_BUTTON_CAST (user_data);
|
||||
|
||||
/* We should not be here otherwise */
|
||||
if (G_LIKELY (self->can_open_subtitles && self->current_item != NULL))
|
||||
g_signal_emit (self, signals[SIGNAL_OPEN_SUBTITLES], 0, self->current_item);
|
||||
}
|
||||
|
||||
static void
|
||||
_determine_top_separator_visibility (ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
gboolean visible = gtk_widget_get_visible (self->volume_box)
|
||||
|| gtk_widget_get_visible (self->speed_box);
|
||||
|
||||
gtk_widget_set_visible (self->top_separator, visible);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_extra_menu_button_new:
|
||||
*
|
||||
* Creates a new #ClapperGtkExtraMenuButton instance.
|
||||
*
|
||||
* Returns: a new extra menu button #GtkWidget.
|
||||
*/
|
||||
GtkWidget *
|
||||
clapper_gtk_extra_menu_button_new (void)
|
||||
{
|
||||
return g_object_new (CLAPPER_GTK_TYPE_EXTRA_MENU_BUTTON, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_extra_menu_button_set_volume_visible:
|
||||
* @button: a #ClapperGtkExtraMenuButton
|
||||
* @visible: whether visible
|
||||
*
|
||||
* Set whether volume control inside popover should be visible.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_extra_menu_button_set_volume_visible (ClapperGtkExtraMenuButton *self, gboolean visible)
|
||||
{
|
||||
g_return_if_fail (CLAPPER_GTK_IS_EXTRA_MENU_BUTTON (self));
|
||||
|
||||
if (gtk_widget_get_visible (self->volume_box) != visible) {
|
||||
gtk_widget_set_visible (self->volume_box, visible);
|
||||
_determine_top_separator_visibility (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_VOLUME_VISIBLE]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_extra_menu_button_get_volume_visible:
|
||||
* @button: a #ClapperGtkExtraMenuButton
|
||||
*
|
||||
* Get whether volume control inside popover is visible.
|
||||
*
|
||||
* Returns: TRUE if volume control is visible, %FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
clapper_gtk_extra_menu_button_get_volume_visible (ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_EXTRA_MENU_BUTTON (self), FALSE);
|
||||
|
||||
return gtk_widget_get_visible (self->volume_box);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_extra_menu_button_set_speed_visible:
|
||||
* @button: a #ClapperGtkExtraMenuButton
|
||||
* @visible: whether visible
|
||||
*
|
||||
* Set whether speed control inside popover should be visible.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_extra_menu_button_set_speed_visible (ClapperGtkExtraMenuButton *self, gboolean visible)
|
||||
{
|
||||
g_return_if_fail (CLAPPER_GTK_IS_EXTRA_MENU_BUTTON (self));
|
||||
|
||||
if (gtk_widget_get_visible (self->speed_box) != visible) {
|
||||
gtk_widget_set_visible (self->speed_box, visible);
|
||||
_determine_top_separator_visibility (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_SPEED_VISIBLE]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_extra_menu_button_get_speed_visible:
|
||||
* @button: a #ClapperGtkExtraMenuButton
|
||||
*
|
||||
* Get whether speed control inside popover is visible.
|
||||
*
|
||||
* Returns: %TRUE if speed control is visible, %FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
clapper_gtk_extra_menu_button_get_speed_visible (ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_EXTRA_MENU_BUTTON (self), FALSE);
|
||||
|
||||
return gtk_widget_get_visible (self->speed_box);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_extra_menu_button_set_can_open_subtitles:
|
||||
* @button: a #ClapperGtkExtraMenuButton
|
||||
* @allowed: whether opening subtitles should be allowed
|
||||
*
|
||||
* Set whether an option to open external subtitle stream should be allowed.
|
||||
*
|
||||
* Note that this [class@Gtk.Widget] can only add subtitles to currently playing
|
||||
* [class@Clapper.MediaItem]. When no media is selected, option to open subtitles
|
||||
* will not be shown regardless how this option is set.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_extra_menu_button_set_can_open_subtitles (ClapperGtkExtraMenuButton *self, gboolean allowed)
|
||||
{
|
||||
gboolean changed;
|
||||
|
||||
g_return_if_fail (CLAPPER_GTK_IS_EXTRA_MENU_BUTTON (self));
|
||||
|
||||
if ((changed = self->can_open_subtitles != allowed)) {
|
||||
self->can_open_subtitles = allowed;
|
||||
|
||||
_set_action_enabled (self, "open-subtitle-stream",
|
||||
(self->can_open_subtitles && self->current_item != NULL));
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_CAN_OPEN_SUBTITLES]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_extra_menu_button_get_can_open_subtitles:
|
||||
* @button: a #ClapperGtkExtraMenuButton
|
||||
*
|
||||
* Get whether an option to open external subtitle stream inside popover is visible.
|
||||
*
|
||||
* Returns: %TRUE if open subtitles is visible, %FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
clapper_gtk_extra_menu_button_get_can_open_subtitles (ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_EXTRA_MENU_BUTTON (self), FALSE);
|
||||
|
||||
return self->can_open_subtitles;
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_extra_menu_button_init (ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
static GActionEntry action_entries[] = {
|
||||
{ "subtitle-stream-enabled", NULL, NULL, "true", change_subtitle_stream_enabled },
|
||||
{ "open-subtitle-stream", open_subtitle_stream, NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
self->action_group = g_simple_action_group_new ();
|
||||
|
||||
g_object_bind_property (self, "css-classes", self->menu_button,
|
||||
"css-classes", G_BINDING_DEFAULT);
|
||||
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (self->action_group),
|
||||
action_entries, G_N_ELEMENTS (action_entries), self);
|
||||
gtk_widget_insert_action_group (GTK_WIDGET (self),
|
||||
"clappergtk", G_ACTION_GROUP (self->action_group));
|
||||
|
||||
/* Set default values */
|
||||
self->can_open_subtitles = DEFAULT_CAN_OPEN_SUBTITLES;
|
||||
_set_action_enabled (self, "open-subtitle-stream", self->can_open_subtitles);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_extra_menu_button_compute_expand (GtkWidget *widget,
|
||||
gboolean *hexpand_p, gboolean *vexpand_p)
|
||||
{
|
||||
GtkWidget *child;
|
||||
gboolean hexpand = FALSE;
|
||||
gboolean vexpand = FALSE;
|
||||
|
||||
if ((child = gtk_widget_get_first_child (widget))) {
|
||||
hexpand = gtk_widget_compute_expand (child, GTK_ORIENTATION_HORIZONTAL);
|
||||
vexpand = gtk_widget_compute_expand (child, GTK_ORIENTATION_VERTICAL);
|
||||
}
|
||||
|
||||
*hexpand_p = hexpand;
|
||||
*vexpand_p = vexpand;
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_extra_menu_button_realize (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkExtraMenuButton *self = CLAPPER_GTK_EXTRA_MENU_BUTTON_CAST (widget);
|
||||
|
||||
GST_TRACE_OBJECT (self, "Realize");
|
||||
|
||||
if ((self->player = clapper_gtk_get_player_from_ancestor (GTK_WIDGET (self)))) {
|
||||
ClapperStreamList *stream_list;
|
||||
GtkSingleSelection *selection;
|
||||
|
||||
g_signal_connect (self->player, "notify::mute",
|
||||
G_CALLBACK (_player_mute_changed_cb), self);
|
||||
self->mute = clapper_player_get_mute (self->player);
|
||||
|
||||
stream_list = clapper_player_get_video_streams (self->player);
|
||||
selection = gtk_single_selection_new (gst_object_ref (stream_list));
|
||||
gtk_single_selection_set_autoselect (selection, FALSE);
|
||||
|
||||
self->video_binding = g_object_bind_property (stream_list, "current-index",
|
||||
selection, "selected", G_BINDING_SYNC_CREATE);
|
||||
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (self->video_list_view),
|
||||
GTK_SELECTION_MODEL (selection));
|
||||
g_object_unref (selection);
|
||||
|
||||
stream_list = clapper_player_get_audio_streams (self->player);
|
||||
selection = gtk_single_selection_new (gst_object_ref (stream_list));
|
||||
gtk_single_selection_set_autoselect (selection, FALSE);
|
||||
|
||||
self->audio_binding = g_object_bind_property (stream_list, "current-index",
|
||||
selection, "selected", G_BINDING_SYNC_CREATE);
|
||||
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (self->audio_list_view),
|
||||
GTK_SELECTION_MODEL (selection));
|
||||
g_object_unref (selection);
|
||||
|
||||
stream_list = clapper_player_get_subtitle_streams (self->player);
|
||||
selection = gtk_single_selection_new (gst_object_ref (stream_list));
|
||||
gtk_single_selection_set_autoselect (selection, FALSE);
|
||||
|
||||
self->subtitle_binding = g_object_bind_property (stream_list, "current-index",
|
||||
selection, "selected", G_BINDING_SYNC_CREATE);
|
||||
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (self->subtitle_list_view),
|
||||
GTK_SELECTION_MODEL (selection));
|
||||
g_object_unref (selection);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->realize (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_extra_menu_button_unrealize (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkExtraMenuButton *self = CLAPPER_GTK_EXTRA_MENU_BUTTON_CAST (widget);
|
||||
|
||||
GST_TRACE_OBJECT (self, "Unrealize");
|
||||
|
||||
g_clear_pointer (&self->video_binding, g_binding_unbind);
|
||||
g_clear_pointer (&self->audio_binding, g_binding_unbind);
|
||||
g_clear_pointer (&self->subtitle_binding, g_binding_unbind);
|
||||
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (self->video_list_view), NULL);
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (self->audio_list_view), NULL);
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (self->subtitle_list_view), NULL);
|
||||
|
||||
if (self->player) {
|
||||
g_signal_handlers_disconnect_by_func (self->player, _player_mute_changed_cb, self);
|
||||
|
||||
self->player = NULL;
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
popover_map_cb (GtkWidget *widget, ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
ClapperQueue *queue;
|
||||
|
||||
GST_TRACE_OBJECT (self, "Popover map");
|
||||
|
||||
if (G_UNLIKELY (self->player == NULL))
|
||||
return;
|
||||
|
||||
queue = clapper_player_get_queue (self->player);
|
||||
|
||||
self->volume_binding = g_object_bind_property_full (self->player, "volume",
|
||||
self->volume_spin, "value",
|
||||
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE,
|
||||
(GBindingTransformFunc) _double_transform_func,
|
||||
(GBindingTransformFunc) _double_transform_func,
|
||||
NULL, NULL);
|
||||
self->speed_binding = g_object_bind_property_full (self->player, "speed",
|
||||
self->speed_spin, "value",
|
||||
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE,
|
||||
(GBindingTransformFunc) _double_transform_func,
|
||||
(GBindingTransformFunc) _double_transform_func,
|
||||
NULL, NULL);
|
||||
|
||||
g_signal_connect (self->player, "notify::subtitles-enabled",
|
||||
G_CALLBACK (_subtitles_enabled_changed_cb), self);
|
||||
_subtitles_enabled_changed_cb (self->player, NULL, self);
|
||||
|
||||
g_signal_connect (queue, "notify::current-item",
|
||||
G_CALLBACK (_queue_current_item_changed_cb), self);
|
||||
_queue_current_item_changed_cb (queue, NULL, self);
|
||||
}
|
||||
|
||||
static void
|
||||
popover_unmap_cb (GtkWidget *widget, ClapperGtkExtraMenuButton *self)
|
||||
{
|
||||
ClapperQueue *queue;
|
||||
|
||||
GST_TRACE_OBJECT (self, "Popover unmap");
|
||||
|
||||
if (G_UNLIKELY (self->player == NULL))
|
||||
return;
|
||||
|
||||
queue = clapper_player_get_queue (self->player);
|
||||
|
||||
g_clear_pointer (&self->volume_binding, g_binding_unbind);
|
||||
g_clear_pointer (&self->speed_binding, g_binding_unbind);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (self->player, _subtitles_enabled_changed_cb, self);
|
||||
g_signal_handlers_disconnect_by_func (queue, _queue_current_item_changed_cb, self);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_extra_menu_button_dispose (GObject *object)
|
||||
{
|
||||
ClapperGtkExtraMenuButton *self = CLAPPER_GTK_EXTRA_MENU_BUTTON_CAST (object);
|
||||
|
||||
gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_GTK_TYPE_EXTRA_MENU_BUTTON);
|
||||
|
||||
g_clear_pointer (&self->menu_button, gtk_widget_unparent);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_extra_menu_button_finalize (GObject *object)
|
||||
{
|
||||
ClapperGtkExtraMenuButton *self = CLAPPER_GTK_EXTRA_MENU_BUTTON_CAST (object);
|
||||
|
||||
GST_TRACE_OBJECT (self, "Finalize");
|
||||
|
||||
gst_clear_object (&self->current_item);
|
||||
g_object_unref (self->action_group);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_extra_menu_button_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkExtraMenuButton *self = CLAPPER_GTK_EXTRA_MENU_BUTTON_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_VOLUME_VISIBLE:
|
||||
g_value_set_boolean (value, clapper_gtk_extra_menu_button_get_volume_visible (self));
|
||||
break;
|
||||
case PROP_SPEED_VISIBLE:
|
||||
g_value_set_boolean (value, clapper_gtk_extra_menu_button_get_speed_visible (self));
|
||||
break;
|
||||
case PROP_CAN_OPEN_SUBTITLES:
|
||||
g_value_set_boolean (value, clapper_gtk_extra_menu_button_get_can_open_subtitles (self));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_extra_menu_button_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkExtraMenuButton *self = CLAPPER_GTK_EXTRA_MENU_BUTTON_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_VOLUME_VISIBLE:
|
||||
clapper_gtk_extra_menu_button_set_volume_visible (self, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_SPEED_VISIBLE:
|
||||
clapper_gtk_extra_menu_button_set_speed_visible (self, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_CAN_OPEN_SUBTITLES:
|
||||
clapper_gtk_extra_menu_button_set_can_open_subtitles (self, g_value_get_boolean (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_extra_menu_button_class_init (ClapperGtkExtraMenuButtonClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtkextramenubutton", 0,
|
||||
"Clapper GTK Extra Menu Button");
|
||||
clapper_gtk_init_translations ();
|
||||
|
||||
gobject_class->get_property = clapper_gtk_extra_menu_button_get_property;
|
||||
gobject_class->set_property = clapper_gtk_extra_menu_button_set_property;
|
||||
gobject_class->dispose = clapper_gtk_extra_menu_button_dispose;
|
||||
gobject_class->finalize = clapper_gtk_extra_menu_button_finalize;
|
||||
|
||||
widget_class->compute_expand = clapper_gtk_extra_menu_button_compute_expand;
|
||||
widget_class->realize = clapper_gtk_extra_menu_button_realize;
|
||||
widget_class->unrealize = clapper_gtk_extra_menu_button_unrealize;
|
||||
|
||||
/**
|
||||
* ClapperGtkExtraMenuButton:volume-visible:
|
||||
*
|
||||
* Visibility of volume control inside popover.
|
||||
*/
|
||||
param_specs[PROP_VOLUME_VISIBLE] = g_param_spec_boolean ("volume-visible",
|
||||
NULL, NULL, TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClapperGtkExtraMenuButton:speed-visible:
|
||||
*
|
||||
* Visibility of speed control inside popover.
|
||||
*/
|
||||
param_specs[PROP_SPEED_VISIBLE] = g_param_spec_boolean ("speed-visible",
|
||||
NULL, NULL, TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClapperGtkExtraMenuButton:can-open-subtitles:
|
||||
*
|
||||
* Visibility of open subtitles option inside popover.
|
||||
*/
|
||||
param_specs[PROP_CAN_OPEN_SUBTITLES] = g_param_spec_boolean ("can-open-subtitles",
|
||||
NULL, NULL, FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClapperGtkExtraMenuButton::open-subtitles:
|
||||
* @button: a #ClapperGtkExtraMenuButton
|
||||
* @item: a #ClapperMediaItem
|
||||
*
|
||||
* A signal that user wants to open subtitles file.
|
||||
*
|
||||
* Implementation should add a way for user to select subtitles to open
|
||||
* such as by e.g. using [class@Gtk.FileDialog] and then add them to the
|
||||
* @item using [method@Clapper.MediaItem.set_suburi] method.
|
||||
*
|
||||
* This signal will pass the [class@Clapper.MediaItem] that was current when
|
||||
* user clicked the open button and subtitles should be added to this @item.
|
||||
* This avoids situations where another item starts playing before user selects
|
||||
* subtitles file to be opened. When using asynchronous operations to open file,
|
||||
* implementation should [method@GObject.Object.ref] the item to ensure that it
|
||||
* stays valid until finish.
|
||||
*
|
||||
* Note that this signal will not be emitted if open button is not visible by
|
||||
* setting [method@ClapperGtk.ExtraMenuButton.set_can_open_subtitles] to %TRUE,
|
||||
* so you do not have to implement handler for it otherwise.
|
||||
*/
|
||||
signals[SIGNAL_OPEN_SUBTITLES] = g_signal_new ("open-subtitles",
|
||||
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
|
||||
0, NULL, NULL, NULL, G_TYPE_NONE, 1, CLAPPER_TYPE_MEDIA_ITEM);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class,
|
||||
CLAPPER_GTK_RESOURCE_PREFIX "/ui/clapper-gtk-extra-menu-button.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkExtraMenuButton, menu_button);
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkExtraMenuButton, volume_box);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkExtraMenuButton, volume_button);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkExtraMenuButton, volume_spin);
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkExtraMenuButton, speed_box);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkExtraMenuButton, speed_button);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkExtraMenuButton, speed_spin);
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkExtraMenuButton, top_separator);
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkExtraMenuButton, video_list_view);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkExtraMenuButton, video_sw);
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkExtraMenuButton, audio_list_view);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkExtraMenuButton, audio_sw);
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkExtraMenuButton, subtitle_list_view);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkExtraMenuButton, subtitle_sw);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, volume_spin_input_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, volume_spin_output_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, volume_spin_changed_cb);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, speed_spin_input_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, speed_spin_output_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, speed_spin_changed_cb);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, popover_map_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, popover_unmap_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, visible_submenu_changed_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_BUTTON);
|
||||
gtk_widget_class_set_css_name (widget_class, "clapper-gtk-extra-menu-button");
|
||||
}
|
51
src/lib/clapper-gtk/clapper-gtk-extra-menu-button.h
Normal file
51
src/lib/clapper-gtk/clapper-gtk-extra-menu-button.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_EXTRA_MENU_BUTTON (clapper_gtk_extra_menu_button_get_type())
|
||||
#define CLAPPER_GTK_EXTRA_MENU_BUTTON_CAST(obj) ((ClapperGtkExtraMenuButton *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkExtraMenuButton, clapper_gtk_extra_menu_button, CLAPPER_GTK, EXTRA_MENU_BUTTON, GtkWidget)
|
||||
|
||||
GtkWidget * clapper_gtk_extra_menu_button_new (void);
|
||||
|
||||
void clapper_gtk_extra_menu_button_set_volume_visible (ClapperGtkExtraMenuButton *button, gboolean visible);
|
||||
|
||||
gboolean clapper_gtk_extra_menu_button_get_volume_visible (ClapperGtkExtraMenuButton *button);
|
||||
|
||||
void clapper_gtk_extra_menu_button_set_speed_visible (ClapperGtkExtraMenuButton *button, gboolean visible);
|
||||
|
||||
gboolean clapper_gtk_extra_menu_button_get_speed_visible (ClapperGtkExtraMenuButton *button);
|
||||
|
||||
void clapper_gtk_extra_menu_button_set_can_open_subtitles (ClapperGtkExtraMenuButton *button, gboolean allowed);
|
||||
|
||||
gboolean clapper_gtk_extra_menu_button_get_can_open_subtitles (ClapperGtkExtraMenuButton *button);
|
||||
|
||||
G_END_DECLS
|
235
src/lib/clapper-gtk/clapper-gtk-lead-container.c
Normal file
235
src/lib/clapper-gtk/clapper-gtk-lead-container.c
Normal file
@@ -0,0 +1,235 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClapperGtkLeadContainer:
|
||||
*
|
||||
* A #ClapperGtkContainer that can take priority in user interactions with the #ClapperGtkVideo.
|
||||
*
|
||||
* #ClapperGtkLeadContainer is a special type of [class@ClapperGtk.Container] that can
|
||||
* lead in interaction events. When "leading", it is assumed that user interactions
|
||||
* over it which would normally trigger actions can be blocked/ignored when set in mask
|
||||
* of actions that this widget should block.
|
||||
*
|
||||
* This kind of container is useful when creating some statically visible overlays
|
||||
* covering top of [class@ClapperGtk.Video] that you want to take priority instead of
|
||||
* triggering default actions such as toggle play on click or revealing fading overlays.
|
||||
*
|
||||
* For more info how container widget works see [class@ClapperGtk.Container] documentation.
|
||||
*/
|
||||
|
||||
#include "clapper-gtk-lead-container.h"
|
||||
|
||||
#define DEFAULT_LEADING TRUE
|
||||
#define DEFAULT_BLOCKED_ACTIONS CLAPPER_GTK_VIDEO_ACTION_NONE
|
||||
|
||||
typedef struct _ClapperGtkLeadContainerPrivate ClapperGtkLeadContainerPrivate;
|
||||
|
||||
struct _ClapperGtkLeadContainerPrivate
|
||||
{
|
||||
gboolean leading;
|
||||
ClapperGtkVideoActionMask blocked_actions;
|
||||
};
|
||||
|
||||
#define parent_class clapper_gtk_lead_container_parent_class
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (ClapperGtkLeadContainer, clapper_gtk_lead_container, CLAPPER_GTK_TYPE_CONTAINER)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_LEADING,
|
||||
PROP_BLOCKED_ACTIONS,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
|
||||
|
||||
/**
|
||||
* clapper_gtk_lead_container_new:
|
||||
*
|
||||
* Creates a new #ClapperGtkLeadContainer instance.
|
||||
*
|
||||
* Returns: a new lead container #GtkWidget.
|
||||
*/
|
||||
GtkWidget *
|
||||
clapper_gtk_lead_container_new (void)
|
||||
{
|
||||
return g_object_new (CLAPPER_GTK_TYPE_LEAD_CONTAINER, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_lead_container_set_leading:
|
||||
* @lead_container: a #ClapperGtkLeadContainer
|
||||
* @leading: enable leadership
|
||||
*
|
||||
* Set if @lead_container leadership should be enabled.
|
||||
*
|
||||
* When enabled, interactions with @lead_container will not trigger
|
||||
* their default behavior, instead container and its contents will take priority.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_lead_container_set_leading (ClapperGtkLeadContainer *self, gboolean leading)
|
||||
{
|
||||
ClapperGtkLeadContainerPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLAPPER_GTK_IS_LEAD_CONTAINER (self));
|
||||
|
||||
priv = clapper_gtk_lead_container_get_instance_private (self);
|
||||
|
||||
priv->leading = leading;
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_lead_container_get_leading:
|
||||
* @lead_container: a #ClapperGtkLeadContainer
|
||||
*
|
||||
* Get a whenever @lead_container has leadership set.
|
||||
*
|
||||
* Returns: %TRUE if container is leading, %FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
clapper_gtk_lead_container_get_leading (ClapperGtkLeadContainer *self)
|
||||
{
|
||||
ClapperGtkLeadContainerPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_LEAD_CONTAINER (self), FALSE);
|
||||
|
||||
priv = clapper_gtk_lead_container_get_instance_private (self);
|
||||
|
||||
return priv->leading;
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_lead_container_set_blocked_actions:
|
||||
* @lead_container: a #ClapperGtkLeadContainer
|
||||
* @actions: a #ClapperGtkVideoActionMask of actions to block
|
||||
*
|
||||
* Set @actions that #ClapperGtkVideo should skip when #GdkEvent which
|
||||
* would normally trigger them happens inside @lead_container.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_lead_container_set_blocked_actions (ClapperGtkLeadContainer *self, ClapperGtkVideoActionMask actions)
|
||||
{
|
||||
ClapperGtkLeadContainerPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLAPPER_GTK_IS_LEAD_CONTAINER (self));
|
||||
|
||||
priv = clapper_gtk_lead_container_get_instance_private (self);
|
||||
|
||||
priv->blocked_actions = actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_lead_container_get_blocked_actions:
|
||||
* @lead_container: a #ClapperGtkLeadContainer
|
||||
*
|
||||
* Get @actions that were set for this @lead_container to block.
|
||||
*
|
||||
* Returns: a mask of actions that container blocks from being triggered on video.
|
||||
*/
|
||||
ClapperGtkVideoActionMask
|
||||
clapper_gtk_lead_container_get_blocked_actions (ClapperGtkLeadContainer *self)
|
||||
{
|
||||
ClapperGtkLeadContainerPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_LEAD_CONTAINER (self), 0);
|
||||
|
||||
priv = clapper_gtk_lead_container_get_instance_private (self);
|
||||
|
||||
return priv->blocked_actions;
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_lead_container_init (ClapperGtkLeadContainer *self)
|
||||
{
|
||||
ClapperGtkLeadContainerPrivate *priv = clapper_gtk_lead_container_get_instance_private (self);
|
||||
|
||||
priv->leading = DEFAULT_LEADING;
|
||||
priv->blocked_actions = DEFAULT_BLOCKED_ACTIONS;
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_lead_container_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkLeadContainer *self = CLAPPER_GTK_LEAD_CONTAINER_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_LEADING:
|
||||
g_value_set_boolean (value, clapper_gtk_lead_container_get_leading (self));
|
||||
break;
|
||||
case PROP_BLOCKED_ACTIONS:
|
||||
g_value_set_flags (value, clapper_gtk_lead_container_get_blocked_actions (self));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_lead_container_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkLeadContainer *self = CLAPPER_GTK_LEAD_CONTAINER_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_LEADING:
|
||||
clapper_gtk_lead_container_set_leading (self, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_BLOCKED_ACTIONS:
|
||||
clapper_gtk_lead_container_set_blocked_actions (self, g_value_get_flags (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_lead_container_class_init (ClapperGtkLeadContainerClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
|
||||
gobject_class->get_property = clapper_gtk_lead_container_get_property;
|
||||
gobject_class->set_property = clapper_gtk_lead_container_set_property;
|
||||
|
||||
/**
|
||||
* ClapperGtkLeadContainer:leading:
|
||||
*
|
||||
* Width that container should target.
|
||||
*/
|
||||
param_specs[PROP_LEADING] = g_param_spec_boolean ("leading",
|
||||
NULL, NULL, DEFAULT_LEADING,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClapperGtkLeadContainer:blocked-actions:
|
||||
*
|
||||
* Mask of actions that container blocks from being triggered on video.
|
||||
*/
|
||||
param_specs[PROP_BLOCKED_ACTIONS] = g_param_spec_flags ("blocked-actions",
|
||||
NULL, NULL, CLAPPER_GTK_TYPE_VIDEO_ACTION_MASK, DEFAULT_BLOCKED_ACTIONS,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, "clapper-gtk-lead-container");
|
||||
}
|
58
src/lib/clapper-gtk/clapper-gtk-lead-container.h
Normal file
58
src/lib/clapper-gtk/clapper-gtk-lead-container.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <clapper-gtk/clapper-gtk-enums.h>
|
||||
#include <clapper-gtk/clapper-gtk-container.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_LEAD_CONTAINER (clapper_gtk_lead_container_get_type())
|
||||
#define CLAPPER_GTK_LEAD_CONTAINER_CAST(obj) ((ClapperGtkLeadContainer *)(obj))
|
||||
|
||||
G_DECLARE_DERIVABLE_TYPE (ClapperGtkLeadContainer, clapper_gtk_lead_container, CLAPPER_GTK, LEAD_CONTAINER, ClapperGtkContainer)
|
||||
|
||||
struct _ClapperGtkLeadContainerClass
|
||||
{
|
||||
ClapperGtkContainerClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
gpointer padding[4];
|
||||
};
|
||||
|
||||
GtkWidget * clapper_gtk_lead_container_new (void);
|
||||
|
||||
void clapper_gtk_lead_container_set_leading (ClapperGtkLeadContainer *lead_container, gboolean leading);
|
||||
|
||||
gboolean clapper_gtk_lead_container_get_leading (ClapperGtkLeadContainer *lead_container);
|
||||
|
||||
void clapper_gtk_lead_container_set_blocked_actions (ClapperGtkLeadContainer *lead_container, ClapperGtkVideoActionMask actions);
|
||||
|
||||
ClapperGtkVideoActionMask clapper_gtk_lead_container_get_blocked_actions (ClapperGtkLeadContainer *lead_container);
|
||||
|
||||
G_END_DECLS
|
57
src/lib/clapper-gtk/clapper-gtk-limited-layout-private.h
Normal file
57
src/lib/clapper-gtk/clapper-gtk-limited-layout-private.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_LIMITED_LAYOUT (clapper_gtk_limited_layout_get_type())
|
||||
#define CLAPPER_GTK_LIMITED_LAYOUT_CAST(obj) ((ClapperGtkLimitedLayout *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkLimitedLayout, clapper_gtk_limited_layout, CLAPPER_GTK, LIMITED_LAYOUT, GtkLayoutManager)
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_gtk_limited_layout_set_max_width (ClapperGtkLimitedLayout *layout, gint max_width);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
gint clapper_gtk_limited_layout_get_max_width (ClapperGtkLimitedLayout *layout);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_gtk_limited_layout_set_max_height (ClapperGtkLimitedLayout *layout, gint max_height);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
gint clapper_gtk_limited_layout_get_max_height (ClapperGtkLimitedLayout *layout);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_gtk_limited_layout_set_adaptive_width (ClapperGtkLimitedLayout *layout, gint width);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
gint clapper_gtk_limited_layout_get_adaptive_width (ClapperGtkLimitedLayout *layout);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_gtk_limited_layout_set_adaptive_height (ClapperGtkLimitedLayout *layout, gint height);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
gint clapper_gtk_limited_layout_get_adaptive_height (ClapperGtkLimitedLayout *layout);
|
||||
|
||||
G_END_DECLS
|
159
src/lib/clapper-gtk/clapper-gtk-limited-layout.c
Normal file
159
src/lib/clapper-gtk/clapper-gtk-limited-layout.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <clapper/clapper.h>
|
||||
|
||||
#include "clapper-gtk-limited-layout-private.h"
|
||||
#include "clapper-gtk-container-private.h"
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_gtk_limited_layout_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
struct _ClapperGtkLimitedLayout
|
||||
{
|
||||
GtkLayoutManager parent;
|
||||
|
||||
gint max_width;
|
||||
gint max_height;
|
||||
|
||||
gint adaptive_width;
|
||||
gint adaptive_height;
|
||||
|
||||
gboolean adapt;
|
||||
};
|
||||
|
||||
#define parent_class clapper_gtk_limited_layout_parent_class
|
||||
G_DEFINE_TYPE (ClapperGtkLimitedLayout, clapper_gtk_limited_layout, GTK_TYPE_LAYOUT_MANAGER)
|
||||
|
||||
void
|
||||
clapper_gtk_limited_layout_set_max_width (ClapperGtkLimitedLayout *self, gint max_width)
|
||||
{
|
||||
self->max_width = max_width;
|
||||
}
|
||||
|
||||
gint
|
||||
clapper_gtk_limited_layout_get_max_width (ClapperGtkLimitedLayout *self)
|
||||
{
|
||||
return self->max_width;
|
||||
}
|
||||
|
||||
void
|
||||
clapper_gtk_limited_layout_set_max_height (ClapperGtkLimitedLayout *self, gint max_height)
|
||||
{
|
||||
self->max_height = max_height;
|
||||
}
|
||||
|
||||
gint
|
||||
clapper_gtk_limited_layout_get_max_height (ClapperGtkLimitedLayout *self)
|
||||
{
|
||||
return self->max_height;
|
||||
}
|
||||
|
||||
void
|
||||
clapper_gtk_limited_layout_set_adaptive_width (ClapperGtkLimitedLayout *self, gint width)
|
||||
{
|
||||
self->adaptive_width = width;
|
||||
}
|
||||
|
||||
gint
|
||||
clapper_gtk_limited_layout_get_adaptive_width (ClapperGtkLimitedLayout *self)
|
||||
{
|
||||
return self->adaptive_width;
|
||||
}
|
||||
|
||||
void
|
||||
clapper_gtk_limited_layout_set_adaptive_height (ClapperGtkLimitedLayout *self, gint height)
|
||||
{
|
||||
self->adaptive_height = height;
|
||||
}
|
||||
|
||||
gint
|
||||
clapper_gtk_limited_layout_get_adaptive_height (ClapperGtkLimitedLayout *self)
|
||||
{
|
||||
return self->adaptive_height;
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_limited_layout_measure (GtkLayoutManager *layout_manager,
|
||||
GtkWidget *widget, GtkOrientation orientation, gint for_size,
|
||||
gint *minimum, gint *natural, gint *minimum_baseline, gint *natural_baseline)
|
||||
{
|
||||
ClapperGtkLimitedLayout *self = CLAPPER_GTK_LIMITED_LAYOUT_CAST (layout_manager);
|
||||
GtkWidget *child = gtk_widget_get_first_child (widget);
|
||||
|
||||
if (child && gtk_widget_should_layout (child)) {
|
||||
gint child_min = 0, child_nat = 0;
|
||||
gint child_min_baseline = -1, child_nat_baseline = -1;
|
||||
|
||||
gtk_widget_measure (child, orientation, for_size,
|
||||
&child_min, &child_nat,
|
||||
&child_min_baseline, &child_nat_baseline);
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
*natural = (self->max_width < 0) ? MAX (*natural, child_nat) : self->max_width;
|
||||
else if (orientation == GTK_ORIENTATION_VERTICAL)
|
||||
*natural = (self->max_height < 0) ? MAX (*natural, child_nat) : self->max_height;
|
||||
|
||||
*minimum = MAX (*minimum, child_min);
|
||||
|
||||
if (child_min_baseline > -1)
|
||||
*minimum_baseline = MAX (*minimum_baseline, child_min_baseline);
|
||||
if (child_nat_baseline > -1)
|
||||
*natural_baseline = MAX (*natural_baseline, child_nat_baseline);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_limited_layout_allocate (GtkLayoutManager *layout_manager,
|
||||
GtkWidget *widget, gint width, gint height, gint baseline)
|
||||
{
|
||||
ClapperGtkLimitedLayout *self = CLAPPER_GTK_LIMITED_LAYOUT_CAST (layout_manager);
|
||||
GtkWidget *child = gtk_widget_get_first_child (widget);
|
||||
gboolean adapt = (width <= self->adaptive_width || height <= self->adaptive_height);
|
||||
|
||||
if (child && gtk_widget_should_layout (child))
|
||||
gtk_widget_allocate (child, width, height, baseline, NULL);
|
||||
|
||||
if (G_UNLIKELY (self->adapt != adapt)) {
|
||||
self->adapt = adapt;
|
||||
clapper_gtk_container_emit_adapt (CLAPPER_GTK_CONTAINER_CAST (widget), adapt);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_limited_layout_init (ClapperGtkLimitedLayout *self)
|
||||
{
|
||||
self->max_width = -1;
|
||||
self->max_height = -1;
|
||||
|
||||
self->adaptive_width = -1;
|
||||
self->adaptive_height = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_limited_layout_class_init (ClapperGtkLimitedLayoutClass *klass)
|
||||
{
|
||||
GtkLayoutManagerClass *layout_manager_class = (GtkLayoutManagerClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtklimitedlayout", 0,
|
||||
"Clapper GTK Limited Layout");
|
||||
|
||||
layout_manager_class->measure = clapper_gtk_limited_layout_measure;
|
||||
layout_manager_class->allocate = clapper_gtk_limited_layout_allocate;
|
||||
}
|
132
src/lib/clapper-gtk/clapper-gtk-next-item-button.c
Normal file
132
src/lib/clapper-gtk/clapper-gtk-next-item-button.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClapperGtkNextItemButton:
|
||||
*
|
||||
* A #GtkButton for selecting next queue item.
|
||||
*/
|
||||
|
||||
#include <clapper/clapper.h>
|
||||
|
||||
#include "clapper-gtk-next-item-button.h"
|
||||
#include "clapper-gtk-utils.h"
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_gtk_next_item_button_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
struct _ClapperGtkNextItemButton
|
||||
{
|
||||
GtkButton parent;
|
||||
|
||||
GBinding *n_items_binding;
|
||||
GBinding *current_index_binding;
|
||||
};
|
||||
|
||||
#define parent_class clapper_gtk_next_item_button_parent_class
|
||||
G_DEFINE_TYPE (ClapperGtkNextItemButton, clapper_gtk_next_item_button, GTK_TYPE_BUTTON)
|
||||
|
||||
static gboolean
|
||||
_transform_sensitive_func (GBinding *binding, const GValue *from_value,
|
||||
GValue *to_value, ClapperGtkNextItemButton *self)
|
||||
{
|
||||
ClapperQueue *queue = CLAPPER_QUEUE_CAST (g_binding_dup_source (binding));
|
||||
guint current_index;
|
||||
gboolean can_skip;
|
||||
|
||||
if (G_UNLIKELY (queue == NULL))
|
||||
return FALSE;
|
||||
|
||||
current_index = clapper_queue_get_current_index (queue);
|
||||
|
||||
can_skip = (current_index != CLAPPER_QUEUE_INVALID_POSITION
|
||||
&& current_index < clapper_queue_get_n_items (queue) - 1);
|
||||
gst_object_unref (queue);
|
||||
|
||||
g_value_set_boolean (to_value, can_skip);
|
||||
GST_DEBUG_OBJECT (self, "Set sensitive: %s", (can_skip) ? "yes" : "no");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_next_item_button_new:
|
||||
*
|
||||
* Creates a new #ClapperGtkNextItemButton to play next #ClapperMediaItem.
|
||||
*
|
||||
* Returns: a new next item button #GtkWidget.
|
||||
*/
|
||||
GtkWidget *
|
||||
clapper_gtk_next_item_button_new (void)
|
||||
{
|
||||
return g_object_new (CLAPPER_GTK_TYPE_NEXT_ITEM_BUTTON, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_next_item_button_init (ClapperGtkNextItemButton *self)
|
||||
{
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
|
||||
gtk_button_set_icon_name (GTK_BUTTON (self), "media-skip-forward-symbolic");
|
||||
gtk_actionable_set_action_name (GTK_ACTIONABLE (self), "video.next-item");
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_next_item_button_map (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkNextItemButton *self = CLAPPER_GTK_NEXT_ITEM_BUTTON_CAST (widget);
|
||||
ClapperPlayer *player;
|
||||
|
||||
if ((player = clapper_gtk_get_player_from_ancestor (widget))) {
|
||||
ClapperQueue *queue = clapper_player_get_queue (player);
|
||||
|
||||
self->n_items_binding = g_object_bind_property_full (queue, "n-items",
|
||||
self, "sensitive", G_BINDING_DEFAULT, // Since we sync below, no need to do it twice
|
||||
(GBindingTransformFunc) _transform_sensitive_func,
|
||||
NULL, self, NULL);
|
||||
self->current_index_binding = g_object_bind_property_full (queue, "current-index",
|
||||
self, "sensitive", G_BINDING_SYNC_CREATE,
|
||||
(GBindingTransformFunc) _transform_sensitive_func,
|
||||
NULL, self, NULL);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->map (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_next_item_button_unmap (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkNextItemButton *self = CLAPPER_GTK_NEXT_ITEM_BUTTON_CAST (widget);
|
||||
|
||||
g_clear_pointer (&self->n_items_binding, g_binding_unbind);
|
||||
g_clear_pointer (&self->current_index_binding, g_binding_unbind);
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->unmap (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_next_item_button_class_init (ClapperGtkNextItemButtonClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtknextitembutton", 0,
|
||||
"Clapper GTK Next Item Button");
|
||||
|
||||
widget_class->map = clapper_gtk_next_item_button_map;
|
||||
widget_class->unmap = clapper_gtk_next_item_button_unmap;
|
||||
}
|
39
src/lib/clapper-gtk/clapper-gtk-next-item-button.h
Normal file
39
src/lib/clapper-gtk/clapper-gtk-next-item-button.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_NEXT_ITEM_BUTTON (clapper_gtk_next_item_button_get_type())
|
||||
#define CLAPPER_GTK_NEXT_ITEM_BUTTON_CAST(obj) ((ClapperGtkNextItemButton *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkNextItemButton, clapper_gtk_next_item_button, CLAPPER_GTK, NEXT_ITEM_BUTTON, GtkButton)
|
||||
|
||||
GtkWidget * clapper_gtk_next_item_button_new (void);
|
||||
|
||||
G_END_DECLS
|
132
src/lib/clapper-gtk/clapper-gtk-previous-item-button.c
Normal file
132
src/lib/clapper-gtk/clapper-gtk-previous-item-button.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClapperGtkPreviousItemButton:
|
||||
*
|
||||
* A #GtkButton for selecting previous queue item.
|
||||
*/
|
||||
|
||||
#include <clapper/clapper.h>
|
||||
|
||||
#include "clapper-gtk-previous-item-button.h"
|
||||
#include "clapper-gtk-utils.h"
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_gtk_previous_item_button_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
struct _ClapperGtkPreviousItemButton
|
||||
{
|
||||
GtkButton parent;
|
||||
|
||||
GBinding *n_items_binding;
|
||||
GBinding *current_index_binding;
|
||||
};
|
||||
|
||||
#define parent_class clapper_gtk_previous_item_button_parent_class
|
||||
G_DEFINE_TYPE (ClapperGtkPreviousItemButton, clapper_gtk_previous_item_button, GTK_TYPE_BUTTON)
|
||||
|
||||
static gboolean
|
||||
_transform_sensitive_func (GBinding *binding, const GValue *from_value,
|
||||
GValue *to_value, ClapperGtkPreviousItemButton *self)
|
||||
{
|
||||
ClapperQueue *queue = CLAPPER_QUEUE_CAST (g_binding_dup_source (binding));
|
||||
guint current_index;
|
||||
gboolean can_skip;
|
||||
|
||||
if (G_UNLIKELY (queue == NULL))
|
||||
return FALSE;
|
||||
|
||||
current_index = clapper_queue_get_current_index (queue);
|
||||
|
||||
can_skip = (current_index != CLAPPER_QUEUE_INVALID_POSITION
|
||||
&& current_index > 0);
|
||||
gst_object_unref (queue);
|
||||
|
||||
g_value_set_boolean (to_value, can_skip);
|
||||
GST_DEBUG_OBJECT (self, "Set sensitive: %s", (can_skip) ? "yes" : "no");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_previous_item_button_new:
|
||||
*
|
||||
* Creates a new #ClapperGtkPreviousItemButton to play previous #ClapperMediaItem.
|
||||
*
|
||||
* Returns: a new previous item button #GtkWidget.
|
||||
*/
|
||||
GtkWidget *
|
||||
clapper_gtk_previous_item_button_new (void)
|
||||
{
|
||||
return g_object_new (CLAPPER_GTK_TYPE_PREVIOUS_ITEM_BUTTON, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_previous_item_button_init (ClapperGtkPreviousItemButton *self)
|
||||
{
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
|
||||
gtk_button_set_icon_name (GTK_BUTTON (self), "media-skip-backward-symbolic");
|
||||
gtk_actionable_set_action_name (GTK_ACTIONABLE (self), "video.previous-item");
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_previous_item_button_map (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkPreviousItemButton *self = CLAPPER_GTK_PREVIOUS_ITEM_BUTTON_CAST (widget);
|
||||
ClapperPlayer *player;
|
||||
|
||||
if ((player = clapper_gtk_get_player_from_ancestor (widget))) {
|
||||
ClapperQueue *queue = clapper_player_get_queue (player);
|
||||
|
||||
self->n_items_binding = g_object_bind_property_full (queue, "n-items",
|
||||
self, "sensitive", G_BINDING_DEFAULT, // Since we sync below, no need to do it twice
|
||||
(GBindingTransformFunc) _transform_sensitive_func,
|
||||
NULL, self, NULL);
|
||||
self->current_index_binding = g_object_bind_property_full (queue, "current-index",
|
||||
self, "sensitive", G_BINDING_SYNC_CREATE,
|
||||
(GBindingTransformFunc) _transform_sensitive_func,
|
||||
NULL, self, NULL);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->map (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_previous_item_button_unmap (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkPreviousItemButton *self = CLAPPER_GTK_PREVIOUS_ITEM_BUTTON_CAST (widget);
|
||||
|
||||
g_clear_pointer (&self->n_items_binding, g_binding_unbind);
|
||||
g_clear_pointer (&self->current_index_binding, g_binding_unbind);
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->unmap (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_previous_item_button_class_init (ClapperGtkPreviousItemButtonClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtkpreviousitembutton", 0,
|
||||
"Clapper GTK Previous Item Button");
|
||||
|
||||
widget_class->map = clapper_gtk_previous_item_button_map;
|
||||
widget_class->unmap = clapper_gtk_previous_item_button_unmap;
|
||||
}
|
39
src/lib/clapper-gtk/clapper-gtk-previous-item-button.h
Normal file
39
src/lib/clapper-gtk/clapper-gtk-previous-item-button.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_PREVIOUS_ITEM_BUTTON (clapper_gtk_previous_item_button_get_type())
|
||||
#define CLAPPER_GTK_PREVIOUS_ITEM_BUTTON_CAST(obj) ((ClapperGtkPreviousItemButton *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkPreviousItemButton, clapper_gtk_previous_item_button, CLAPPER_GTK, PREVIOUS_ITEM_BUTTON, GtkButton)
|
||||
|
||||
GtkWidget * clapper_gtk_previous_item_button_new (void);
|
||||
|
||||
G_END_DECLS
|
783
src/lib/clapper-gtk/clapper-gtk-seek-bar.c
Normal file
783
src/lib/clapper-gtk/clapper-gtk-seek-bar.c
Normal file
@@ -0,0 +1,783 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClapperGtkSeekBar:
|
||||
*
|
||||
* A bar for seeking and displaying playback position.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <clapper/clapper.h>
|
||||
|
||||
#include "clapper-gtk-seek-bar.h"
|
||||
#include "clapper-gtk-container.h"
|
||||
#include "clapper-gtk-utils.h"
|
||||
|
||||
#define DEFAULT_REVEAL_LABELS TRUE
|
||||
#define DEFAULT_SEEK_METHOD CLAPPER_PLAYER_SEEK_METHOD_NORMAL
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_gtk_seek_bar_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
struct _ClapperGtkSeekBar
|
||||
{
|
||||
GtkWidget parent;
|
||||
|
||||
GtkWidget *position_revealer;
|
||||
GtkWidget *position_label;
|
||||
|
||||
GtkWidget *scale;
|
||||
|
||||
GtkPopover *popover;
|
||||
GtkLabel *popover_label;
|
||||
|
||||
GtkWidget *duration_revealer;
|
||||
GtkWidget *duration_label;
|
||||
|
||||
gboolean has_hours;
|
||||
gboolean has_markers;
|
||||
|
||||
gboolean dragging;
|
||||
guint position_uint;
|
||||
|
||||
gulong position_signal_id;
|
||||
|
||||
gboolean reveal_labels;
|
||||
ClapperPlayerSeekMethod seek_method;
|
||||
|
||||
ClapperPlayer *player;
|
||||
ClapperMediaItem *current_item;
|
||||
|
||||
/* Cache */
|
||||
gdouble curr_marker_start;
|
||||
gdouble next_marker_start;
|
||||
};
|
||||
|
||||
static void
|
||||
clapper_gtk_seek_bar_add_child (GtkBuildable *buildable,
|
||||
GtkBuilder *builder, GObject *child, const char *type)
|
||||
{
|
||||
if (GTK_IS_WIDGET (child)) {
|
||||
gtk_widget_insert_before (GTK_WIDGET (child), GTK_WIDGET (buildable), NULL);
|
||||
} 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_seek_bar_add_child;
|
||||
}
|
||||
|
||||
#define parent_class clapper_gtk_seek_bar_parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE (ClapperGtkSeekBar, clapper_gtk_seek_bar, GTK_TYPE_WIDGET,
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, _buildable_iface_init))
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_REVEAL_LABELS,
|
||||
PROP_SEEK_METHOD,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
|
||||
|
||||
static inline gboolean
|
||||
_prepare_popover (ClapperGtkSeekBar *self, gdouble x,
|
||||
gdouble pointing_val, gdouble upper)
|
||||
{
|
||||
/* Avoid iterating through markers if within last marker range
|
||||
* (currently set title label remains the same) */
|
||||
gboolean found_title = (pointing_val >= self->curr_marker_start
|
||||
&& pointing_val < self->next_marker_start);
|
||||
|
||||
if (!found_title) {
|
||||
ClapperTimeline *timeline = clapper_media_item_get_timeline (self->current_item);
|
||||
guint i = clapper_timeline_get_n_markers (timeline);
|
||||
|
||||
GST_DEBUG ("Searching for marker at: %lf", pointing_val);
|
||||
|
||||
/* We start from the end of scale */
|
||||
self->next_marker_start = upper;
|
||||
|
||||
while (i--) {
|
||||
ClapperMarker *marker = clapper_timeline_get_marker (timeline, i);
|
||||
self->curr_marker_start = clapper_marker_get_start (marker);
|
||||
|
||||
if (self->curr_marker_start <= pointing_val) {
|
||||
const gchar *title = clapper_marker_get_title (marker);
|
||||
|
||||
GST_DEBUG ("Found marker, range: (%lf-%lf), title: \"%s\"",
|
||||
self->curr_marker_start, self->next_marker_start,
|
||||
GST_STR_NULL (title));
|
||||
|
||||
/* XXX: It does string comparison internally, so its more efficient
|
||||
* for us and we do not have to compare strings here too */
|
||||
gtk_label_set_label (self->popover_label, title);
|
||||
found_title = (title != NULL);
|
||||
}
|
||||
|
||||
gst_object_unref (marker);
|
||||
|
||||
if (found_title)
|
||||
break;
|
||||
|
||||
self->next_marker_start = self->curr_marker_start;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_popover_set_pointing_to (self->popover,
|
||||
&(const GdkRectangle){ x, 0, 1, 1 });
|
||||
|
||||
return found_title;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
_compute_scale_coords (ClapperGtkSeekBar *self,
|
||||
gdouble *min_pointing_val, gdouble *max_pointing_val)
|
||||
{
|
||||
graphene_rect_t slider_bounds;
|
||||
|
||||
if (!gtk_widget_compute_bounds (GTK_WIDGET (self), self->scale, &slider_bounds))
|
||||
return FALSE;
|
||||
|
||||
/* XXX: Number "2" is the correction for range protruding rounded sides
|
||||
* compared to how marks above/below it are positioned */
|
||||
*min_pointing_val = -slider_bounds.origin.x + 2;
|
||||
*max_pointing_val = slider_bounds.size.width + slider_bounds.origin.x - 2;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_player_position_changed_cb (ClapperPlayer *player,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkSeekBar *self)
|
||||
{
|
||||
GtkAdjustment *adjustment;
|
||||
gdouble position;
|
||||
|
||||
if (self->dragging)
|
||||
return;
|
||||
|
||||
position = clapper_player_get_position (player);
|
||||
|
||||
if (ABS (self->position_uint - position) < 1)
|
||||
return;
|
||||
|
||||
GST_LOG_OBJECT (self, "Position changed: %lf", position);
|
||||
|
||||
self->position_uint = (guint) position;
|
||||
|
||||
adjustment = gtk_range_get_adjustment (GTK_RANGE (self->scale));
|
||||
gtk_adjustment_set_value (adjustment, position);
|
||||
}
|
||||
|
||||
static void
|
||||
_player_state_changed_cb (ClapperPlayer *player,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkSeekBar *self)
|
||||
{
|
||||
switch (clapper_player_get_state (player)) {
|
||||
case CLAPPER_PLAYER_STATE_PAUSED:
|
||||
/* Force refresh, so scale always reaches end after playback */
|
||||
self->position_uint = G_MAXUINT;
|
||||
_player_position_changed_cb (player, NULL, self);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_player_seek_done_cb (ClapperPlayer *player, ClapperGtkSeekBar *self)
|
||||
{
|
||||
GST_DEBUG ("Seek done");
|
||||
|
||||
if (self->position_signal_id == 0) {
|
||||
self->position_signal_id = g_signal_connect (self->player,
|
||||
"notify::position", G_CALLBACK (_player_position_changed_cb), self);
|
||||
}
|
||||
_player_position_changed_cb (player, NULL, self);
|
||||
}
|
||||
|
||||
static void
|
||||
scale_value_changed_cb (GtkRange *range, ClapperGtkSeekBar *self)
|
||||
{
|
||||
gdouble value = gtk_range_get_value (range);
|
||||
gchar *position_str = g_strdup_printf ("%" CLAPPER_TIME_FORMAT, CLAPPER_TIME_ARGS (value));
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (self->position_label),
|
||||
(self->has_hours) ? position_str : position_str + 3);
|
||||
g_free (position_str);
|
||||
|
||||
if (self->dragging && self->has_markers) {
|
||||
gdouble min_pointing_val, max_pointing_val;
|
||||
gdouble x, upper, scaling;
|
||||
|
||||
if (!_compute_scale_coords (self, &min_pointing_val, &max_pointing_val)) {
|
||||
gtk_popover_popdown (self->popover);
|
||||
return;
|
||||
}
|
||||
|
||||
upper = gtk_adjustment_get_upper (
|
||||
gtk_range_get_adjustment (GTK_RANGE (self->scale)));
|
||||
scaling = (upper / (max_pointing_val - min_pointing_val));
|
||||
|
||||
x = min_pointing_val + (value / scaling);
|
||||
|
||||
if (_prepare_popover (self, x, value, upper))
|
||||
gtk_popover_popup (self->popover);
|
||||
else
|
||||
gtk_popover_popdown (self->popover);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
scale_css_classes_changed_cb (GtkWidget *widget,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkSeekBar *self)
|
||||
{
|
||||
const gboolean dragging = gtk_widget_has_css_class (widget, "dragging");
|
||||
gdouble value;
|
||||
|
||||
if (self->dragging == dragging)
|
||||
return;
|
||||
|
||||
if ((self->dragging = dragging)) {
|
||||
GST_DEBUG_OBJECT (self, "Scale drag started");
|
||||
return;
|
||||
}
|
||||
|
||||
value = gtk_range_get_value (GTK_RANGE (widget));
|
||||
GST_DEBUG_OBJECT (self, "Scale dropped at: %lf", value);
|
||||
|
||||
if (G_UNLIKELY (self->player == NULL))
|
||||
return;
|
||||
|
||||
if (self->position_signal_id != 0) {
|
||||
g_signal_handler_disconnect (self->player, self->position_signal_id);
|
||||
self->position_signal_id = 0;
|
||||
}
|
||||
|
||||
/* We should be ALWAYS doing normal seeks if dropped at marker position */
|
||||
if (self->has_markers
|
||||
&& G_APPROX_VALUE (self->curr_marker_start, value, FLT_EPSILON)) {
|
||||
GST_DEBUG ("Seeking to marker");
|
||||
clapper_player_seek (self->player, value);
|
||||
} else {
|
||||
clapper_player_seek_custom (self->player, value, self->seek_method);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
motion_cb (GtkEventControllerMotion *motion,
|
||||
gdouble x, gdouble y, ClapperGtkSeekBar *self)
|
||||
{
|
||||
gdouble min_pointing_val, max_pointing_val, pointing_val;
|
||||
gdouble upper, scaling;
|
||||
|
||||
/* If no markers, popover should never popup,
|
||||
* so we do not try to pop it down here */
|
||||
if (!self->has_markers)
|
||||
return;
|
||||
|
||||
if (!_compute_scale_coords (self, &min_pointing_val, &max_pointing_val)
|
||||
|| (x < min_pointing_val || x > max_pointing_val)) {
|
||||
gtk_popover_popdown (self->popover);
|
||||
return;
|
||||
}
|
||||
|
||||
upper = gtk_adjustment_get_upper (
|
||||
gtk_range_get_adjustment (GTK_RANGE (self->scale)));
|
||||
scaling = (upper / (max_pointing_val - min_pointing_val));
|
||||
|
||||
pointing_val = (x - min_pointing_val) * scaling;
|
||||
GST_LOG ("Cursor pointing to: %lf", pointing_val);
|
||||
|
||||
if (_prepare_popover (self, x, pointing_val, upper))
|
||||
gtk_popover_popup (self->popover);
|
||||
else
|
||||
gtk_popover_popdown (self->popover);
|
||||
}
|
||||
|
||||
static void
|
||||
motion_leave_cb (GtkEventControllerMotion *motion, ClapperGtkSeekBar *self)
|
||||
{
|
||||
gtk_popover_popdown (self->popover);
|
||||
}
|
||||
|
||||
static void
|
||||
touch_released_cb (GtkGestureClick *click, gint n_press,
|
||||
gdouble x, gdouble y, ClapperGtkSeekBar *self)
|
||||
{
|
||||
gtk_popover_popdown (self->popover);
|
||||
}
|
||||
|
||||
static void
|
||||
_update_duration_label (ClapperGtkSeekBar *self, gdouble duration)
|
||||
{
|
||||
GtkAdjustment *adjustment = gtk_range_get_adjustment (GTK_RANGE (self->scale));
|
||||
gchar *duration_str = g_strdup_printf ("%" CLAPPER_TIME_FORMAT, CLAPPER_TIME_ARGS (duration));
|
||||
gboolean has_hours = (duration >= 3600);
|
||||
|
||||
GST_LOG_OBJECT (self, "Duration changed: %lf", duration);
|
||||
|
||||
/* Refresh position label when changing text length */
|
||||
if (has_hours != self->has_hours) {
|
||||
self->has_hours = has_hours;
|
||||
scale_value_changed_cb (GTK_RANGE (self->scale), self);
|
||||
}
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (self->duration_label),
|
||||
(self->has_hours) ? duration_str : duration_str + 3);
|
||||
g_free (duration_str);
|
||||
|
||||
gtk_adjustment_set_upper (adjustment, duration);
|
||||
}
|
||||
|
||||
static void
|
||||
_update_scale_marks (ClapperGtkSeekBar *self, ClapperTimeline *timeline)
|
||||
{
|
||||
GtkAdjustment *adjustment;
|
||||
guint i, n_markers = clapper_timeline_get_n_markers (timeline);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Placing %u markers on scale", n_markers);
|
||||
|
||||
gtk_scale_clear_marks (GTK_SCALE (self->scale));
|
||||
|
||||
self->curr_marker_start = -1;
|
||||
self->next_marker_start = -1;
|
||||
self->has_markers = FALSE;
|
||||
|
||||
if (n_markers == 0) {
|
||||
gtk_popover_popdown (self->popover);
|
||||
return;
|
||||
}
|
||||
|
||||
adjustment = gtk_range_get_adjustment (GTK_RANGE (self->scale));
|
||||
|
||||
/* Avoid placing marks when duration is zero. Otherwise we may
|
||||
* end up with a single mark at zero until another refresh. */
|
||||
if (gtk_adjustment_get_upper (adjustment) <= 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < n_markers; ++i) {
|
||||
ClapperMarker *marker = clapper_timeline_get_marker (timeline, i);
|
||||
gdouble start = clapper_marker_get_start (marker);
|
||||
|
||||
gtk_scale_add_mark (GTK_SCALE (self->scale), start, GTK_POS_TOP, NULL);
|
||||
gtk_scale_add_mark (GTK_SCALE (self->scale), start, GTK_POS_BOTTOM, NULL);
|
||||
|
||||
gst_object_unref (marker);
|
||||
}
|
||||
|
||||
self->has_markers = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_current_item_duration_changed_cb (ClapperMediaItem *current_item,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkSeekBar *self)
|
||||
{
|
||||
/* GtkScale ignores markers placed post its adjustment upper range.
|
||||
* We need to place them again on scale AFTER duration changes. */
|
||||
_update_duration_label (self, clapper_media_item_get_duration (current_item));
|
||||
_update_scale_marks (self, clapper_media_item_get_timeline (current_item));
|
||||
}
|
||||
|
||||
static void
|
||||
_timeline_markers_changed_cb (GListModel *list_model, guint position,
|
||||
guint removed, guint added, ClapperGtkSeekBar *self)
|
||||
{
|
||||
_update_scale_marks (self, CLAPPER_TIMELINE (list_model));
|
||||
}
|
||||
|
||||
static void
|
||||
_queue_current_item_changed_cb (ClapperQueue *queue,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkSeekBar *self)
|
||||
{
|
||||
ClapperMediaItem *current_item = clapper_queue_get_current_item (queue);
|
||||
|
||||
/* Disconnect signals from old item */
|
||||
if (self->current_item) {
|
||||
ClapperTimeline *timeline = clapper_media_item_get_timeline (self->current_item);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (self->current_item,
|
||||
_current_item_duration_changed_cb, self);
|
||||
g_signal_handlers_disconnect_by_func (timeline,
|
||||
_timeline_markers_changed_cb, self);
|
||||
}
|
||||
|
||||
gst_object_replace ((GstObject **) &self->current_item, GST_OBJECT_CAST (current_item));
|
||||
gst_clear_object (¤t_item);
|
||||
|
||||
/* Reconnect signals to new item */
|
||||
if (self->current_item) {
|
||||
ClapperTimeline *timeline = clapper_media_item_get_timeline (self->current_item);
|
||||
|
||||
g_signal_connect (self->current_item, "notify::duration",
|
||||
G_CALLBACK (_current_item_duration_changed_cb), self);
|
||||
g_signal_connect (timeline, "items-changed",
|
||||
G_CALLBACK (_timeline_markers_changed_cb), self);
|
||||
|
||||
_update_duration_label (self, clapper_media_item_get_duration (self->current_item));
|
||||
_update_scale_marks (self, timeline);
|
||||
} else {
|
||||
gtk_scale_clear_marks (GTK_SCALE (self->scale));
|
||||
_update_duration_label (self, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_seek_bar_new:
|
||||
*
|
||||
* Creates a new #ClapperGtkSeekBar instance.
|
||||
*
|
||||
* Returns: a new seek bar #GtkWidget.
|
||||
*/
|
||||
GtkWidget *
|
||||
clapper_gtk_seek_bar_new (void)
|
||||
{
|
||||
return g_object_new (CLAPPER_GTK_TYPE_SEEK_BAR, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_seek_bar_set_reveal_labels:
|
||||
* @seek_bar: a #ClapperGtkSeekBar
|
||||
* @reveal: whether to reveal labels
|
||||
*
|
||||
* Set whether the position and duration labels should be revealed.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_seek_bar_set_reveal_labels (ClapperGtkSeekBar *self, gboolean reveal)
|
||||
{
|
||||
g_return_if_fail (CLAPPER_GTK_IS_SEEK_BAR (self));
|
||||
|
||||
if (self->reveal_labels != reveal) {
|
||||
self->reveal_labels = reveal;
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (self->position_revealer), reveal);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_REVEAL_LABELS]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_seek_bar_get_reveal_labels:
|
||||
* @seek_bar: a #ClapperGtkSeekBar
|
||||
*
|
||||
* Get whether the position and duration labels are going to be revealed.
|
||||
*
|
||||
* Returns: TRUE if the labels are going to be revealed, %FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
clapper_gtk_seek_bar_get_reveal_labels (ClapperGtkSeekBar *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_SEEK_BAR (self), FALSE);
|
||||
|
||||
return self->reveal_labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_seek_bar_set_seek_method:
|
||||
* @seek_bar: a #ClapperGtkSeekBar
|
||||
* @method: a #ClapperPlayerSeekMethod
|
||||
*
|
||||
* Set [enum@Clapper.PlayerSeekMethod] to use when seeking with seek bar.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_seek_bar_set_seek_method (ClapperGtkSeekBar *self, ClapperPlayerSeekMethod method)
|
||||
{
|
||||
g_return_if_fail (CLAPPER_GTK_IS_SEEK_BAR (self));
|
||||
|
||||
if (self->seek_method != method) {
|
||||
self->seek_method = method;
|
||||
GST_DEBUG_OBJECT (self, "Set seek method to: %i", self->seek_method);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_SEEK_METHOD]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_seek_bar_get_seek_method:
|
||||
* @seek_bar: a #ClapperGtkSeekBar
|
||||
*
|
||||
* Get [enum@Clapper.PlayerSeekMethod] used when seeking with seek bar.
|
||||
*
|
||||
* Returns: #ClapperPlayerSeekMethod used for seeking.
|
||||
*/
|
||||
ClapperPlayerSeekMethod
|
||||
clapper_gtk_seek_bar_get_seek_method (ClapperGtkSeekBar *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_SEEK_BAR (self), DEFAULT_SEEK_METHOD);
|
||||
|
||||
return self->seek_method;
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_seek_bar_init (ClapperGtkSeekBar *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
self->reveal_labels = DEFAULT_REVEAL_LABELS;
|
||||
self->seek_method = DEFAULT_SEEK_METHOD;
|
||||
|
||||
self->curr_marker_start = -1;
|
||||
self->next_marker_start = -1;
|
||||
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (self->position_revealer), self->reveal_labels);
|
||||
|
||||
/* Correction for calculated popover position when marks are drawn */
|
||||
gtk_popover_set_offset (self->popover, 0, -2);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_seek_bar_compute_expand (GtkWidget *widget,
|
||||
gboolean *hexpand_p, gboolean *vexpand_p)
|
||||
{
|
||||
GtkWidget *w;
|
||||
gboolean hexpand = FALSE;
|
||||
gboolean vexpand = FALSE;
|
||||
|
||||
for (w = gtk_widget_get_first_child (widget); w != NULL; w = gtk_widget_get_next_sibling (w)) {
|
||||
hexpand = (hexpand || gtk_widget_compute_expand (w, GTK_ORIENTATION_HORIZONTAL));
|
||||
vexpand = (vexpand || gtk_widget_compute_expand (w, GTK_ORIENTATION_VERTICAL));
|
||||
}
|
||||
|
||||
*hexpand_p = hexpand;
|
||||
*vexpand_p = vexpand;
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_seek_bar_size_allocate (GtkWidget *widget,
|
||||
gint width, gint height, gint baseline)
|
||||
{
|
||||
ClapperGtkSeekBar *self = CLAPPER_GTK_SEEK_BAR_CAST (widget);
|
||||
|
||||
gtk_popover_present (self->popover);
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, width, height, baseline);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_seek_bar_realize (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkSeekBar *self = CLAPPER_GTK_SEEK_BAR_CAST (widget);
|
||||
|
||||
if ((self->player = clapper_gtk_get_player_from_ancestor (widget))) {
|
||||
ClapperQueue *queue = clapper_player_get_queue (self->player);
|
||||
|
||||
g_signal_connect (queue, "notify::current-item",
|
||||
G_CALLBACK (_queue_current_item_changed_cb), self);
|
||||
_queue_current_item_changed_cb (queue, NULL, self);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->realize (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_seek_bar_unrealize (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkSeekBar *self = CLAPPER_GTK_SEEK_BAR_CAST (widget);
|
||||
|
||||
if (self->player) {
|
||||
ClapperQueue *queue = clapper_player_get_queue (self->player);
|
||||
|
||||
if (self->position_signal_id != 0) {
|
||||
g_signal_handler_disconnect (self->player, self->position_signal_id);
|
||||
self->position_signal_id = 0;
|
||||
}
|
||||
g_signal_handlers_disconnect_by_func (queue, _queue_current_item_changed_cb, self);
|
||||
|
||||
self->player = NULL;
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_seek_bar_map (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkSeekBar *self = CLAPPER_GTK_SEEK_BAR_CAST (widget);
|
||||
|
||||
if (self->player) {
|
||||
if (self->position_signal_id == 0) {
|
||||
self->position_signal_id = g_signal_connect (self->player,
|
||||
"notify::position", G_CALLBACK (_player_position_changed_cb), self);
|
||||
}
|
||||
g_signal_connect (self->player, "notify::state",
|
||||
G_CALLBACK (_player_state_changed_cb), self);
|
||||
g_signal_connect (self->player, "seek-done",
|
||||
G_CALLBACK (_player_seek_done_cb), self);
|
||||
|
||||
_player_position_changed_cb (self->player, NULL, self);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->map (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_seek_bar_unmap (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkSeekBar *self = CLAPPER_GTK_SEEK_BAR_CAST (widget);
|
||||
|
||||
if (self->player) {
|
||||
if (self->position_signal_id != 0) {
|
||||
g_signal_handler_disconnect (self->player, self->position_signal_id);
|
||||
self->position_signal_id = 0;
|
||||
}
|
||||
g_signal_handlers_disconnect_by_func (self->player, _player_state_changed_cb, self);
|
||||
g_signal_handlers_disconnect_by_func (self->player, _player_seek_done_cb, self);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->unmap (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
_popover_unparent (GtkPopover *popover)
|
||||
{
|
||||
gtk_widget_unparent (GTK_WIDGET (popover));
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_seek_bar_dispose (GObject *object)
|
||||
{
|
||||
ClapperGtkSeekBar *self = CLAPPER_GTK_SEEK_BAR_CAST (object);
|
||||
|
||||
gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_GTK_TYPE_SEEK_BAR);
|
||||
|
||||
g_clear_pointer (&self->position_revealer, gtk_widget_unparent);
|
||||
g_clear_pointer (&self->scale, gtk_widget_unparent);
|
||||
g_clear_pointer (&self->popover, _popover_unparent);
|
||||
g_clear_pointer (&self->duration_revealer, gtk_widget_unparent);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_seek_bar_finalize (GObject *object)
|
||||
{
|
||||
ClapperGtkSeekBar *self = CLAPPER_GTK_SEEK_BAR_CAST (object);
|
||||
|
||||
GST_TRACE_OBJECT (self, "Finalize");
|
||||
|
||||
gst_clear_object (&self->current_item);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_seek_bar_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkSeekBar *self = CLAPPER_GTK_SEEK_BAR_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_REVEAL_LABELS:
|
||||
g_value_set_boolean (value, clapper_gtk_seek_bar_get_reveal_labels (self));
|
||||
break;
|
||||
case PROP_SEEK_METHOD:
|
||||
g_value_set_enum (value, clapper_gtk_seek_bar_get_seek_method (self));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_seek_bar_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkSeekBar *self = CLAPPER_GTK_SEEK_BAR_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_REVEAL_LABELS:
|
||||
clapper_gtk_seek_bar_set_reveal_labels (self, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_SEEK_METHOD:
|
||||
clapper_gtk_seek_bar_set_seek_method (self, g_value_get_enum (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_seek_bar_class_init (ClapperGtkSeekBarClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtkseekbar", 0,
|
||||
"Clapper GTK Seek Bar");
|
||||
|
||||
gobject_class->get_property = clapper_gtk_seek_bar_get_property;
|
||||
gobject_class->set_property = clapper_gtk_seek_bar_set_property;
|
||||
gobject_class->dispose = clapper_gtk_seek_bar_dispose;
|
||||
gobject_class->finalize = clapper_gtk_seek_bar_finalize;
|
||||
|
||||
widget_class->compute_expand = clapper_gtk_seek_bar_compute_expand;
|
||||
widget_class->size_allocate = clapper_gtk_seek_bar_size_allocate;
|
||||
widget_class->realize = clapper_gtk_seek_bar_realize;
|
||||
widget_class->unrealize = clapper_gtk_seek_bar_unrealize;
|
||||
widget_class->map = clapper_gtk_seek_bar_map;
|
||||
widget_class->unmap = clapper_gtk_seek_bar_unmap;
|
||||
|
||||
/**
|
||||
* ClapperGtkSeekBar:reveal-labels:
|
||||
*
|
||||
* Reveal state of the position and duration labels.
|
||||
*/
|
||||
param_specs[PROP_REVEAL_LABELS] = g_param_spec_boolean ("reveal-labels",
|
||||
NULL, NULL, DEFAULT_REVEAL_LABELS,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClapperGtkSeekBar:seek-method:
|
||||
*
|
||||
* Method used for seeking.
|
||||
*/
|
||||
param_specs[PROP_SEEK_METHOD] = g_param_spec_enum ("seek-method",
|
||||
NULL, NULL, CLAPPER_TYPE_PLAYER_SEEK_METHOD, DEFAULT_SEEK_METHOD,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class,
|
||||
CLAPPER_GTK_RESOURCE_PREFIX "/ui/clapper-gtk-seek-bar.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkSeekBar, position_revealer);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkSeekBar, position_label);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkSeekBar, scale);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkSeekBar, popover);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkSeekBar, popover_label);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkSeekBar, duration_revealer);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkSeekBar, duration_label);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, scale_value_changed_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, scale_css_classes_changed_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, motion_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, motion_leave_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, touch_released_cb);
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
|
||||
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GENERIC);
|
||||
gtk_widget_class_set_css_name (widget_class, "clapper-gtk-seek-bar");
|
||||
}
|
48
src/lib/clapper-gtk/clapper-gtk-seek-bar.h
Normal file
48
src/lib/clapper-gtk/clapper-gtk-seek-bar.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <clapper/clapper.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_SEEK_BAR (clapper_gtk_seek_bar_get_type())
|
||||
#define CLAPPER_GTK_SEEK_BAR_CAST(obj) ((ClapperGtkSeekBar *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkSeekBar, clapper_gtk_seek_bar, CLAPPER_GTK, SEEK_BAR, GtkWidget)
|
||||
|
||||
GtkWidget * clapper_gtk_seek_bar_new (void);
|
||||
|
||||
void clapper_gtk_seek_bar_set_reveal_labels (ClapperGtkSeekBar *seek_bar, gboolean reveal);
|
||||
|
||||
gboolean clapper_gtk_seek_bar_get_reveal_labels (ClapperGtkSeekBar *seek_bar);
|
||||
|
||||
void clapper_gtk_seek_bar_set_seek_method (ClapperGtkSeekBar *seek_bar, ClapperPlayerSeekMethod method);
|
||||
|
||||
ClapperPlayerSeekMethod clapper_gtk_seek_bar_get_seek_method (ClapperGtkSeekBar *seek_bar);
|
||||
|
||||
G_END_DECLS
|
344
src/lib/clapper-gtk/clapper-gtk-simple-controls.c
Normal file
344
src/lib/clapper-gtk/clapper-gtk-simple-controls.c
Normal file
@@ -0,0 +1,344 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClapperGtkSimpleControls:
|
||||
*
|
||||
* A minimalistic playback controls panel widget.
|
||||
*
|
||||
* #ClapperGtkSimpleControls is a simple, ready to be used playback controls widget.
|
||||
* It is meant to be placed as an overlay (either fading or not) of [class@ClapperGtk.Video]
|
||||
* as-is, providing minimal yet universal playback controls for your app.
|
||||
*
|
||||
* If you need a further customized controls, please use individual widgets this
|
||||
* widget consists of to build your own controls implementation instead.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <clapper/clapper.h>
|
||||
|
||||
#include "clapper-gtk-simple-controls.h"
|
||||
#include "clapper-gtk-seek-bar.h"
|
||||
|
||||
#define DEFAULT_FULLSCREENABLE TRUE
|
||||
#define DEFAULT_SEEK_METHOD CLAPPER_PLAYER_SEEK_METHOD_NORMAL
|
||||
|
||||
#define IS_REVEALED(widget) (gtk_revealer_get_child_revealed ((GtkRevealer *) (widget)))
|
||||
#define IS_REVEAL(widget) (gtk_revealer_get_reveal_child ((GtkRevealer *) (widget)))
|
||||
#define SET_REVEAL(widget,reveal) (gtk_revealer_set_reveal_child ((GtkRevealer *) (widget), reveal))
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_gtk_simple_controls_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
struct _ClapperGtkSimpleControls
|
||||
{
|
||||
ClapperGtkContainer parent;
|
||||
|
||||
GtkWidget *seek_bar;
|
||||
GtkWidget *extra_menu_button;
|
||||
GtkWidget *fullscreen_top_revealer;
|
||||
GtkWidget *fullscreen_bottom_revealer;
|
||||
GtkWidget *controls_slide_revealer;
|
||||
|
||||
gboolean fullscreenable;
|
||||
ClapperPlayerSeekMethod seek_method;
|
||||
|
||||
gboolean adapt;
|
||||
};
|
||||
|
||||
#define parent_class clapper_gtk_simple_controls_parent_class
|
||||
G_DEFINE_TYPE (ClapperGtkSimpleControls, clapper_gtk_simple_controls, CLAPPER_GTK_TYPE_CONTAINER)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_FULLSCREENABLE,
|
||||
PROP_SEEK_METHOD,
|
||||
PROP_EXTRA_MENU_BUTTON,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
|
||||
|
||||
static void
|
||||
initial_adapt_cb (ClapperGtkContainer *container, gboolean adapt,
|
||||
ClapperGtkSimpleControls *self)
|
||||
{
|
||||
GST_DEBUG_OBJECT (self, "Initially adapted: %s", (adapt) ? "yes" : "no");
|
||||
|
||||
clapper_gtk_seek_bar_set_reveal_labels (CLAPPER_GTK_SEEK_BAR (self->seek_bar), !adapt);
|
||||
}
|
||||
|
||||
static void
|
||||
full_adapt_cb (ClapperGtkContainer *container, gboolean adapt,
|
||||
ClapperGtkSimpleControls *self)
|
||||
{
|
||||
self->adapt = adapt;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Width adapted: %s", (self->adapt) ? "yes" : "no");
|
||||
|
||||
/* Take different action, depending on transition step we are currently at */
|
||||
if (self->adapt) {
|
||||
if (IS_REVEAL (self->fullscreen_bottom_revealer))
|
||||
SET_REVEAL (self->fullscreen_bottom_revealer, FALSE);
|
||||
else if (IS_REVEAL (self->controls_slide_revealer))
|
||||
SET_REVEAL (self->controls_slide_revealer, FALSE);
|
||||
else
|
||||
SET_REVEAL (self->fullscreen_top_revealer, TRUE);
|
||||
} else {
|
||||
if (IS_REVEAL (self->fullscreen_top_revealer))
|
||||
SET_REVEAL (self->fullscreen_top_revealer, FALSE);
|
||||
else if (!IS_REVEAL (self->controls_slide_revealer))
|
||||
SET_REVEAL (self->controls_slide_revealer, TRUE);
|
||||
else
|
||||
SET_REVEAL (self->fullscreen_bottom_revealer, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
controls_revealed_cb (GtkRevealer *revealer,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkSimpleControls *self)
|
||||
{
|
||||
gboolean revealed = IS_REVEALED (revealer);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Slide revealed: %s", (revealed) ? "yes" : "no");
|
||||
|
||||
/* We should be hidden when adapted, otherwise go back */
|
||||
if (G_UNLIKELY (revealed == self->adapt))
|
||||
gtk_revealer_set_reveal_child (revealer, !revealed);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_simple_controls_new:
|
||||
*
|
||||
* Creates a new #ClapperGtkSimpleControls instance.
|
||||
*
|
||||
* Returns: a new simple controls #GtkWidget.
|
||||
*/
|
||||
GtkWidget *
|
||||
clapper_gtk_simple_controls_new (void)
|
||||
{
|
||||
return g_object_new (CLAPPER_GTK_TYPE_SIMPLE_CONTROLS, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_simple_controls_set_fullscreenable:
|
||||
* @controls: a #ClapperGtkSimpleControls
|
||||
* @fullscreenable: whether show button for toggling fullscreen state
|
||||
*
|
||||
* Set whether [class@ClapperGtk.ToggleFullscreenButton] button in the @controls
|
||||
* should be visible.
|
||||
*
|
||||
* You might want to consider setting this to %FALSE, if your application
|
||||
* does not implement [signal@ClapperGtk.Video::toggle-fullscreen] signal.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_simple_controls_set_fullscreenable (ClapperGtkSimpleControls *self, gboolean fullscreenable)
|
||||
{
|
||||
g_return_if_fail (CLAPPER_GTK_IS_SIMPLE_CONTROLS (self));
|
||||
|
||||
if (self->fullscreenable != fullscreenable) {
|
||||
self->fullscreenable = fullscreenable;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_FULLSCREENABLE]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_simple_controls_get_fullscreenable:
|
||||
* @controls: a #ClapperGtkSimpleControls
|
||||
*
|
||||
* Get whether [class@ClapperGtk.ToggleFullscreenButton] button in the @controls
|
||||
* is set to be visible.
|
||||
*/
|
||||
gboolean
|
||||
clapper_gtk_simple_controls_get_fullscreenable (ClapperGtkSimpleControls *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_SIMPLE_CONTROLS (self), FALSE);
|
||||
|
||||
return self->fullscreenable;
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_simple_controls_set_seek_method:
|
||||
* @controls: a #ClapperGtkSimpleControls
|
||||
* @method: a #ClapperPlayerSeekMethod
|
||||
*
|
||||
* Set [enum@Clapper.PlayerSeekMethod] to use when seeking with progress bar.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_simple_controls_set_seek_method (ClapperGtkSimpleControls *self,
|
||||
ClapperPlayerSeekMethod method)
|
||||
{
|
||||
g_return_if_fail (CLAPPER_GTK_IS_SIMPLE_CONTROLS (self));
|
||||
|
||||
clapper_gtk_seek_bar_set_seek_method (CLAPPER_GTK_SEEK_BAR (self->seek_bar), method);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_simple_controls_get_seek_method:
|
||||
* @controls: a #ClapperGtkSimpleControls
|
||||
*
|
||||
* Get [enum@Clapper.PlayerSeekMethod] used when seeking with progress bar.
|
||||
*
|
||||
* Returns: #ClapperPlayerSeekMethod used for seeking.
|
||||
*/
|
||||
ClapperPlayerSeekMethod
|
||||
clapper_gtk_simple_controls_get_seek_method (ClapperGtkSimpleControls *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_SIMPLE_CONTROLS (self), DEFAULT_SEEK_METHOD);
|
||||
|
||||
return clapper_gtk_seek_bar_get_seek_method (CLAPPER_GTK_SEEK_BAR (self->seek_bar));
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_simple_controls_get_extra_menu_button:
|
||||
* @controls: a #ClapperGtkSimpleControls
|
||||
*
|
||||
* Get [class@ClapperGtk.ExtraMenuButton] that resides within @controls.
|
||||
*
|
||||
* Returns: (transfer none): #ClapperGtkExtraMenuButton within simple controls panel.
|
||||
*/
|
||||
ClapperGtkExtraMenuButton *
|
||||
clapper_gtk_simple_controls_get_extra_menu_button (ClapperGtkSimpleControls *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_SIMPLE_CONTROLS (self), NULL);
|
||||
|
||||
return CLAPPER_GTK_EXTRA_MENU_BUTTON (self->extra_menu_button);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_simple_controls_init (ClapperGtkSimpleControls *self)
|
||||
{
|
||||
self->fullscreenable = DEFAULT_FULLSCREENABLE;
|
||||
self->seek_method = DEFAULT_SEEK_METHOD;
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
/* Set our defaults to children */
|
||||
clapper_gtk_seek_bar_set_seek_method (
|
||||
CLAPPER_GTK_SEEK_BAR_CAST (self->seek_bar), self->seek_method);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_simple_controls_dispose (GObject *object)
|
||||
{
|
||||
gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_GTK_TYPE_SIMPLE_CONTROLS);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_simple_controls_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkSimpleControls *self = CLAPPER_GTK_SIMPLE_CONTROLS_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_FULLSCREENABLE:
|
||||
g_value_set_boolean (value, clapper_gtk_simple_controls_get_fullscreenable (self));
|
||||
break;
|
||||
case PROP_SEEK_METHOD:
|
||||
g_value_set_enum (value, clapper_gtk_simple_controls_get_seek_method (self));
|
||||
break;
|
||||
case PROP_EXTRA_MENU_BUTTON:
|
||||
g_value_set_object (value, clapper_gtk_simple_controls_get_extra_menu_button (self));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_simple_controls_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkSimpleControls *self = CLAPPER_GTK_SIMPLE_CONTROLS_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_FULLSCREENABLE:
|
||||
clapper_gtk_simple_controls_set_fullscreenable (self, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_SEEK_METHOD:
|
||||
clapper_gtk_simple_controls_set_seek_method (self, g_value_get_enum (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_simple_controls_class_init (ClapperGtkSimpleControlsClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtksimplecontrols", 0,
|
||||
"Clapper GTK Simple Controls");
|
||||
|
||||
gobject_class->get_property = clapper_gtk_simple_controls_get_property;
|
||||
gobject_class->set_property = clapper_gtk_simple_controls_set_property;
|
||||
gobject_class->dispose = clapper_gtk_simple_controls_dispose;
|
||||
|
||||
/**
|
||||
* ClapperGtkSimpleControls:fullscreenable:
|
||||
*
|
||||
* Whether toggle fullscreen button should be visible.
|
||||
*/
|
||||
param_specs[PROP_FULLSCREENABLE] = g_param_spec_boolean ("fullscreenable",
|
||||
NULL, NULL, DEFAULT_FULLSCREENABLE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClapperGtkSimpleControls:seek-method:
|
||||
*
|
||||
* Method used for seeking.
|
||||
*/
|
||||
param_specs[PROP_SEEK_METHOD] = g_param_spec_enum ("seek-method",
|
||||
NULL, NULL, CLAPPER_TYPE_PLAYER_SEEK_METHOD, DEFAULT_SEEK_METHOD,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClapperGtkSimpleControls:extra-menu-button:
|
||||
*
|
||||
* Access to extra menu button within controls.
|
||||
*/
|
||||
param_specs[PROP_EXTRA_MENU_BUTTON] = g_param_spec_object ("extra-menu-button",
|
||||
NULL, NULL, CLAPPER_GTK_TYPE_EXTRA_MENU_BUTTON,
|
||||
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_set_template_from_resource (widget_class,
|
||||
CLAPPER_GTK_RESOURCE_PREFIX "/ui/clapper-gtk-simple-controls.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkSimpleControls, seek_bar);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkSimpleControls, extra_menu_button);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkSimpleControls, fullscreen_top_revealer);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkSimpleControls, fullscreen_bottom_revealer);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkSimpleControls, controls_slide_revealer);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, initial_adapt_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, full_adapt_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, controls_revealed_cb);
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, "clapper-gtk-simple-controls");
|
||||
}
|
51
src/lib/clapper-gtk/clapper-gtk-simple-controls.h
Normal file
51
src/lib/clapper-gtk/clapper-gtk-simple-controls.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <clapper-gtk/clapper-gtk-container.h>
|
||||
#include <clapper-gtk/clapper-gtk-extra-menu-button.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_SIMPLE_CONTROLS (clapper_gtk_simple_controls_get_type())
|
||||
#define CLAPPER_GTK_SIMPLE_CONTROLS_CAST(obj) ((ClapperGtkSimpleControls *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkSimpleControls, clapper_gtk_simple_controls, CLAPPER_GTK, SIMPLE_CONTROLS, ClapperGtkContainer)
|
||||
|
||||
GtkWidget * clapper_gtk_simple_controls_new (void);
|
||||
|
||||
void clapper_gtk_simple_controls_set_fullscreenable (ClapperGtkSimpleControls *controls, gboolean fullscreenable);
|
||||
|
||||
gboolean clapper_gtk_simple_controls_get_fullscreenable (ClapperGtkSimpleControls *controls);
|
||||
|
||||
void clapper_gtk_simple_controls_set_seek_method (ClapperGtkSimpleControls *controls, ClapperPlayerSeekMethod method);
|
||||
|
||||
ClapperPlayerSeekMethod clapper_gtk_simple_controls_get_seek_method (ClapperGtkSimpleControls *controls);
|
||||
|
||||
ClapperGtkExtraMenuButton * clapper_gtk_simple_controls_get_extra_menu_button (ClapperGtkSimpleControls *controls);
|
||||
|
||||
G_END_DECLS
|
44
src/lib/clapper-gtk/clapper-gtk-status-private.h
Normal file
44
src/lib/clapper-gtk/clapper-gtk-status-private.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "clapper-gtk-container.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_STATUS (clapper_gtk_status_get_type())
|
||||
#define CLAPPER_GTK_STATUS_CAST(obj) ((ClapperGtkStatus *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkStatus, clapper_gtk_status, CLAPPER_GTK, STATUS, ClapperGtkContainer)
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_gtk_status_set_error (ClapperGtkStatus *status, const GError *error);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_gtk_status_set_missing_plugin (ClapperGtkStatus *status, const gchar *name);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_gtk_status_clear (ClapperGtkStatus *status);
|
||||
|
||||
G_END_DECLS
|
137
src/lib/clapper-gtk/clapper-gtk-status.c
Normal file
137
src/lib/clapper-gtk/clapper-gtk-status.c
Normal file
@@ -0,0 +1,137 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "clapper-gtk-status-private.h"
|
||||
|
||||
#define NORMAL_SPACING 16
|
||||
#define ADAPT_SPACING 8
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_gtk_status_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
struct _ClapperGtkStatus
|
||||
{
|
||||
ClapperGtkContainer parent;
|
||||
|
||||
GtkWidget *status_box;
|
||||
GtkWidget *image;
|
||||
GtkWidget *title_label;
|
||||
GtkWidget *description_label;
|
||||
};
|
||||
|
||||
#define parent_class clapper_gtk_status_parent_class
|
||||
G_DEFINE_TYPE (ClapperGtkStatus, clapper_gtk_status, CLAPPER_GTK_TYPE_CONTAINER)
|
||||
|
||||
static void
|
||||
adapt_cb (ClapperGtkContainer *container, gboolean adapt,
|
||||
ClapperGtkStatus *self)
|
||||
{
|
||||
GST_DEBUG_OBJECT (self, "Adapted: %s", (adapt) ? "yes" : "no");
|
||||
|
||||
gtk_box_set_spacing (GTK_BOX (self->status_box), (adapt) ? ADAPT_SPACING : NORMAL_SPACING);
|
||||
|
||||
if (adapt) {
|
||||
gtk_widget_add_css_class (GTK_WIDGET (self), "adapted");
|
||||
gtk_widget_add_css_class (GTK_WIDGET (self->title_label), "title-2");
|
||||
} else {
|
||||
gtk_widget_remove_css_class (GTK_WIDGET (self), "adapted");
|
||||
gtk_widget_remove_css_class (GTK_WIDGET (self->title_label), "title-2");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_set_status (ClapperGtkStatus *self, const gchar *icon_name,
|
||||
const gchar *title, const gchar *description)
|
||||
{
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (self->image), icon_name);
|
||||
gtk_label_set_label (GTK_LABEL (self->title_label), title);
|
||||
gtk_label_set_label (GTK_LABEL (self->description_label), description);
|
||||
|
||||
gtk_widget_set_visible (GTK_WIDGET (self), TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
clapper_gtk_status_set_error (ClapperGtkStatus *self, const GError *error)
|
||||
{
|
||||
GST_DEBUG_OBJECT (self, "Status set to \"error\"");
|
||||
_set_status (self, "dialog-warning-symbolic", "Unplayable Content", error->message);
|
||||
}
|
||||
|
||||
void
|
||||
clapper_gtk_status_set_missing_plugin (ClapperGtkStatus *self, const gchar *name)
|
||||
{
|
||||
gchar *description;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Status set to \"missing-plugin\"");
|
||||
description = g_strdup_printf ("Your GStreamer installation is missing a plugin: %s", name);
|
||||
_set_status (self, "dialog-information-symbolic", "Missing Plugin", description);
|
||||
|
||||
g_free (description);
|
||||
}
|
||||
|
||||
void
|
||||
clapper_gtk_status_clear (ClapperGtkStatus *self)
|
||||
{
|
||||
GST_DEBUG_OBJECT (self, "Status cleared");
|
||||
gtk_widget_set_visible (GTK_WIDGET (self), FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_status_init (ClapperGtkStatus *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
gtk_box_set_spacing (GTK_BOX (self->status_box), NORMAL_SPACING);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_status_dispose (GObject *object)
|
||||
{
|
||||
gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_GTK_TYPE_STATUS);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_status_class_init (ClapperGtkStatusClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtkstatus", 0,
|
||||
"Clapper GTK Status");
|
||||
|
||||
gobject_class->dispose = clapper_gtk_status_dispose;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class,
|
||||
CLAPPER_GTK_RESOURCE_PREFIX "/ui/clapper-gtk-status.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkStatus, status_box);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkStatus, image);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkStatus, title_label);
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkStatus, description_label);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, adapt_cb);
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, "clapper-gtk-status");
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_STREAM_CHECK_BUTTON (clapper_gtk_stream_check_button_get_type())
|
||||
#define CLAPPER_GTK_STREAM_CHECK_BUTTON_CAST(obj) ((ClapperGtkStreamCheckButton *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkStreamCheckButton, clapper_gtk_stream_check_button, CLAPPER_GTK, STREAM_CHECK_BUTTON, GtkCheckButton)
|
||||
|
||||
G_END_DECLS
|
284
src/lib/clapper-gtk/clapper-gtk-stream-check-button.c
Normal file
284
src/lib/clapper-gtk/clapper-gtk-stream-check-button.c
Normal file
@@ -0,0 +1,284 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <clapper/clapper.h>
|
||||
|
||||
#include "clapper-gtk-stream-check-button-private.h"
|
||||
#include "clapper-gtk-utils-private.h"
|
||||
|
||||
#define MAX_SIGNALS 4
|
||||
|
||||
struct _ClapperGtkStreamCheckButton
|
||||
{
|
||||
GtkCheckButton parent;
|
||||
|
||||
ClapperStream *stream;
|
||||
|
||||
GtkWidget *fallback_check_button;
|
||||
|
||||
gulong signal_ids[MAX_SIGNALS];
|
||||
gboolean grouped;
|
||||
};
|
||||
|
||||
#define parent_class clapper_gtk_stream_check_button_parent_class
|
||||
G_DEFINE_TYPE (ClapperGtkStreamCheckButton, clapper_gtk_stream_check_button, GTK_TYPE_CHECK_BUTTON)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_STREAM,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
|
||||
|
||||
static inline gchar *
|
||||
_get_video_stream_label (ClapperVideoStream *vstream)
|
||||
{
|
||||
gchar *label, *codec = clapper_video_stream_get_codec (vstream);
|
||||
gint height = clapper_video_stream_get_height (vstream);
|
||||
gdouble fps = clapper_video_stream_get_fps (vstream);
|
||||
|
||||
if (codec) {
|
||||
label = g_strdup_printf ("%ip@%.3f [%s]", height, fps, codec);
|
||||
g_free (codec);
|
||||
} else {
|
||||
label = g_strdup_printf ("%ip@%.3f", height, fps);
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
static inline gchar *
|
||||
_get_audio_stream_label (ClapperAudioStream *astream)
|
||||
{
|
||||
gchar *label, *title, *codec = clapper_audio_stream_get_codec (astream);
|
||||
gint channels = clapper_audio_stream_get_channels (astream);
|
||||
|
||||
if (!(title = clapper_stream_get_title (CLAPPER_STREAM_CAST (astream))))
|
||||
title = clapper_audio_stream_get_lang_name (astream);
|
||||
|
||||
if (codec) {
|
||||
label = g_strdup_printf ("%s [%s, %i %s]",
|
||||
(title) ? title : _("Undetermined"), codec, channels, _("Channels"));
|
||||
g_free (title);
|
||||
g_free (codec);
|
||||
} else {
|
||||
label = title;
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
static inline gchar *
|
||||
_get_subtitle_stream_label (ClapperSubtitleStream *sstream)
|
||||
{
|
||||
gchar *title;
|
||||
|
||||
if (!(title = clapper_stream_get_title (CLAPPER_STREAM_CAST (sstream))))
|
||||
title = clapper_subtitle_stream_get_lang_name (sstream);
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
static void
|
||||
_refresh_label_cb (ClapperStream *stream,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkStreamCheckButton *self)
|
||||
{
|
||||
gchar *label = NULL;
|
||||
|
||||
if (stream) {
|
||||
switch (clapper_stream_get_stream_type (stream)) {
|
||||
case CLAPPER_STREAM_TYPE_VIDEO:
|
||||
label = _get_video_stream_label (CLAPPER_VIDEO_STREAM (stream));
|
||||
break;
|
||||
case CLAPPER_STREAM_TYPE_AUDIO:
|
||||
label = _get_audio_stream_label (CLAPPER_AUDIO_STREAM (stream));
|
||||
break;
|
||||
case CLAPPER_STREAM_TYPE_SUBTITLE:
|
||||
label = _get_subtitle_stream_label (CLAPPER_SUBTITLE_STREAM (stream));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_check_button_set_label (GTK_CHECK_BUTTON (self),
|
||||
(label != NULL) ? label : _("Undetermined"));
|
||||
g_free (label);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_disconnect_current_signals (ClapperGtkStreamCheckButton *self)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < MAX_SIGNALS; ++i) {
|
||||
/* No more signals connected */
|
||||
if (self->signal_ids[i] == 0)
|
||||
break;
|
||||
|
||||
g_signal_handler_disconnect (self->stream, self->signal_ids[i]);
|
||||
self->signal_ids[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
clapper_gtk_stream_check_button_set_stream (ClapperGtkStreamCheckButton *self, ClapperStream *stream)
|
||||
{
|
||||
guint i = 0;
|
||||
|
||||
_disconnect_current_signals (self);
|
||||
gst_object_replace ((GstObject **) &self->stream, GST_OBJECT_CAST (stream));
|
||||
|
||||
if (!self->stream)
|
||||
return;
|
||||
|
||||
switch (clapper_stream_get_stream_type (stream)) {
|
||||
case CLAPPER_STREAM_TYPE_VIDEO:
|
||||
self->signal_ids[i++] = g_signal_connect (self->stream, "notify::codec",
|
||||
G_CALLBACK (_refresh_label_cb), self);
|
||||
self->signal_ids[i++] = g_signal_connect (self->stream, "notify::height",
|
||||
G_CALLBACK (_refresh_label_cb), self);
|
||||
self->signal_ids[i++] = g_signal_connect (self->stream, "notify::fps",
|
||||
G_CALLBACK (_refresh_label_cb), self);
|
||||
break;
|
||||
case CLAPPER_STREAM_TYPE_AUDIO:
|
||||
self->signal_ids[i++] = g_signal_connect (self->stream, "notify::codec",
|
||||
G_CALLBACK (_refresh_label_cb), self);
|
||||
self->signal_ids[i++] = g_signal_connect (self->stream, "notify::channels",
|
||||
G_CALLBACK (_refresh_label_cb), self);
|
||||
G_GNUC_FALLTHROUGH;
|
||||
case CLAPPER_STREAM_TYPE_SUBTITLE:
|
||||
self->signal_ids[i++] = g_signal_connect (self->stream, "notify::title",
|
||||
G_CALLBACK (_refresh_label_cb), self);
|
||||
self->signal_ids[i++] = g_signal_connect (self->stream, "notify::lang-name",
|
||||
G_CALLBACK (_refresh_label_cb), self);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_refresh_label_cb (self->stream, NULL, self);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_stream_check_button_realize (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkStreamCheckButton *self = CLAPPER_GTK_STREAM_CHECK_BUTTON_CAST (widget);
|
||||
GtkWidget *other_widget;
|
||||
|
||||
GST_TRACE_OBJECT (self, "Realize");
|
||||
|
||||
/* Set same group as previous check button in the same list view */
|
||||
if (!self->grouped) {
|
||||
if ((other_widget = gtk_widget_get_parent (widget))
|
||||
&& (other_widget = gtk_widget_get_prev_sibling (other_widget))
|
||||
&& (other_widget = gtk_widget_get_first_child (other_widget))
|
||||
&& CLAPPER_GTK_IS_STREAM_CHECK_BUTTON (other_widget)) {
|
||||
gtk_check_button_set_group (GTK_CHECK_BUTTON (self), GTK_CHECK_BUTTON (other_widget));
|
||||
} else {
|
||||
if (!self->fallback_check_button)
|
||||
self->fallback_check_button = g_object_ref_sink (gtk_check_button_new ());
|
||||
|
||||
gtk_check_button_set_group (GTK_CHECK_BUTTON (self), GTK_CHECK_BUTTON (self->fallback_check_button));
|
||||
}
|
||||
self->grouped = TRUE;
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->realize (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_stream_check_button_toggled (GtkCheckButton *check_button)
|
||||
{
|
||||
ClapperGtkStreamCheckButton *self = CLAPPER_GTK_STREAM_CHECK_BUTTON_CAST (check_button);
|
||||
|
||||
if (gtk_check_button_get_active (check_button) && self->stream) {
|
||||
ClapperStreamList *stream_list = CLAPPER_STREAM_LIST (gst_object_get_parent (GST_OBJECT (self->stream)));
|
||||
|
||||
if (G_LIKELY (stream_list != NULL)) {
|
||||
GST_INFO_OBJECT (self, "Toggled: %" GST_PTR_FORMAT, self->stream);
|
||||
clapper_stream_list_select_stream (stream_list, self->stream);
|
||||
gst_object_unref (stream_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_stream_check_button_init (ClapperGtkStreamCheckButton *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_stream_check_button_finalize (GObject *object)
|
||||
{
|
||||
ClapperGtkStreamCheckButton *self = CLAPPER_GTK_STREAM_CHECK_BUTTON_CAST (object);
|
||||
|
||||
GST_TRACE_OBJECT (self, "Finalize");
|
||||
|
||||
_disconnect_current_signals (self);
|
||||
gst_clear_object (&self->stream);
|
||||
|
||||
g_clear_object (&self->fallback_check_button);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_stream_check_button_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkStreamCheckButton *self = CLAPPER_GTK_STREAM_CHECK_BUTTON_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_STREAM:
|
||||
clapper_gtk_stream_check_button_set_stream (self, g_value_get_object (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_stream_check_button_class_init (ClapperGtkStreamCheckButtonClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
GtkCheckButtonClass *check_button_class = (GtkCheckButtonClass *) klass;
|
||||
|
||||
clapper_gtk_init_translations ();
|
||||
|
||||
gobject_class->set_property = clapper_gtk_stream_check_button_set_property;
|
||||
gobject_class->finalize = clapper_gtk_stream_check_button_finalize;
|
||||
|
||||
widget_class->realize = clapper_gtk_stream_check_button_realize;
|
||||
|
||||
check_button_class->toggled = clapper_gtk_stream_check_button_toggled;
|
||||
|
||||
param_specs[PROP_STREAM] = g_param_spec_object ("stream",
|
||||
NULL, NULL, CLAPPER_TYPE_STREAM,
|
||||
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
|
||||
}
|
228
src/lib/clapper-gtk/clapper-gtk-title-header.c
Normal file
228
src/lib/clapper-gtk/clapper-gtk-title-header.c
Normal file
@@ -0,0 +1,228 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClapperGtkTitleHeader:
|
||||
*
|
||||
* A header panel widget that displays current media title.
|
||||
*
|
||||
* #ClapperGtkTitleHeader is a simple, ready to be used header widget that
|
||||
* displays current media title. It can be placed as-is as a [class@ClapperGtk.Video]
|
||||
* overlay (either fading or not).
|
||||
*
|
||||
* If you need a further customized header, you can use [class@ClapperGtk.TitleLabel]
|
||||
* which is used by this widget to build your own implementation instead.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "clapper-gtk-title-header.h"
|
||||
#include "clapper-gtk-title-label.h"
|
||||
|
||||
#define DEFAULT_FALLBACK_TO_URI FALSE
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_gtk_title_header_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
struct _ClapperGtkTitleHeader
|
||||
{
|
||||
ClapperGtkLeadContainer parent;
|
||||
|
||||
ClapperGtkTitleLabel *label;
|
||||
};
|
||||
|
||||
#define parent_class clapper_gtk_title_header_parent_class
|
||||
G_DEFINE_TYPE (ClapperGtkTitleHeader, clapper_gtk_title_header, CLAPPER_GTK_TYPE_LEAD_CONTAINER)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_CURRENT_TITLE,
|
||||
PROP_FALLBACK_TO_URI,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
|
||||
|
||||
static void
|
||||
_label_current_title_changed_cb (ClapperGtkTitleLabel *label G_GNUC_UNUSED,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkTitleHeader *self)
|
||||
{
|
||||
/* Forward current title changed notify from internal label */
|
||||
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_CURRENT_TITLE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_title_header_new:
|
||||
*
|
||||
* Creates a new #ClapperGtkTitleHeader instance.
|
||||
*
|
||||
* Returns: a new title header #GtkWidget.
|
||||
*/
|
||||
GtkWidget *
|
||||
clapper_gtk_title_header_new (void)
|
||||
{
|
||||
return g_object_new (CLAPPER_GTK_TYPE_TITLE_HEADER, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_title_header_get_current_title:
|
||||
* @header: a #ClapperGtkTitleHeader
|
||||
*
|
||||
* Get currently displayed title by @header.
|
||||
*
|
||||
* Returns: (transfer none): text of title label.
|
||||
*/
|
||||
const gchar *
|
||||
clapper_gtk_title_header_get_current_title (ClapperGtkTitleHeader *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_TITLE_HEADER (self), NULL);
|
||||
|
||||
return clapper_gtk_title_label_get_current_title (self->label);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_title_header_set_fallback_to_uri:
|
||||
* @header: a #ClapperGtkTitleHeader
|
||||
* @enabled: whether enabled
|
||||
*
|
||||
* Set whether a [property@Clapper.MediaItem:uri] property should
|
||||
* be displayed as a header text when no other title could be determined.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_title_header_set_fallback_to_uri (ClapperGtkTitleHeader *self, gboolean enabled)
|
||||
{
|
||||
g_return_if_fail (CLAPPER_GTK_IS_TITLE_HEADER (self));
|
||||
|
||||
clapper_gtk_title_label_set_fallback_to_uri (self->label, enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_title_header_get_fallback_to_uri:
|
||||
* @header: a #ClapperGtkTitleHeader
|
||||
*
|
||||
* Get whether a [property@Clapper.MediaItem:uri] property is going
|
||||
* be displayed as a header text when no other title could be determined.
|
||||
*/
|
||||
gboolean
|
||||
clapper_gtk_title_header_get_fallback_to_uri (ClapperGtkTitleHeader *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_TITLE_HEADER (self), FALSE);
|
||||
|
||||
return clapper_gtk_title_label_get_fallback_to_uri (self->label);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_title_header_init (ClapperGtkTitleHeader *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
clapper_gtk_title_label_set_fallback_to_uri (self->label, DEFAULT_FALLBACK_TO_URI);
|
||||
|
||||
g_object_bind_property (self->label, "fallback-to-uri",
|
||||
self, "fallback-to-uri", G_BINDING_DEFAULT);
|
||||
g_signal_connect (self->label, "notify::current-title",
|
||||
G_CALLBACK (_label_current_title_changed_cb), self);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_title_header_dispose (GObject *object)
|
||||
{
|
||||
gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_GTK_TYPE_TITLE_HEADER);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_title_header_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkTitleHeader *self = CLAPPER_GTK_TITLE_HEADER_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CURRENT_TITLE:
|
||||
g_value_set_string (value, clapper_gtk_title_header_get_current_title (self));
|
||||
break;
|
||||
case PROP_FALLBACK_TO_URI:
|
||||
g_value_set_boolean (value, clapper_gtk_title_header_get_fallback_to_uri (self));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_title_header_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkTitleHeader *self = CLAPPER_GTK_TITLE_HEADER_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_FALLBACK_TO_URI:
|
||||
clapper_gtk_title_header_set_fallback_to_uri (self, g_value_get_boolean (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_title_header_class_init (ClapperGtkTitleHeaderClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtktitleheader", 0,
|
||||
"Clapper GTK Title Header");
|
||||
|
||||
gobject_class->get_property = clapper_gtk_title_header_get_property;
|
||||
gobject_class->set_property = clapper_gtk_title_header_set_property;
|
||||
gobject_class->dispose = clapper_gtk_title_header_dispose;
|
||||
|
||||
/**
|
||||
* ClapperGtkTitleHeader:current-title:
|
||||
*
|
||||
* Currently displayed title.
|
||||
*/
|
||||
param_specs[PROP_CURRENT_TITLE] = g_param_spec_string ("current-title",
|
||||
NULL, NULL, NULL,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClapperGtkTitleHeader:fallback-to-uri:
|
||||
*
|
||||
* When title cannot be determined, show URI instead.
|
||||
*/
|
||||
param_specs[PROP_FALLBACK_TO_URI] = g_param_spec_boolean ("fallback-to-uri",
|
||||
NULL, NULL, DEFAULT_FALLBACK_TO_URI,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class,
|
||||
CLAPPER_GTK_RESOURCE_PREFIX "/ui/clapper-gtk-title-header.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ClapperGtkTitleHeader, label);
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, "clapper-gtk-title-header");
|
||||
}
|
46
src/lib/clapper-gtk/clapper-gtk-title-header.h
Normal file
46
src/lib/clapper-gtk/clapper-gtk-title-header.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <clapper-gtk/clapper-gtk-lead-container.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_TITLE_HEADER (clapper_gtk_title_header_get_type())
|
||||
#define CLAPPER_GTK_TITLE_HEADER_CAST(obj) ((ClapperGtkTitleHeader *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkTitleHeader, clapper_gtk_title_header, CLAPPER_GTK, TITLE_HEADER, ClapperGtkLeadContainer)
|
||||
|
||||
GtkWidget * clapper_gtk_title_header_new (void);
|
||||
|
||||
const gchar * clapper_gtk_title_header_get_current_title (ClapperGtkTitleHeader *header);
|
||||
|
||||
void clapper_gtk_title_header_set_fallback_to_uri (ClapperGtkTitleHeader *header, gboolean enabled);
|
||||
|
||||
gboolean clapper_gtk_title_header_get_fallback_to_uri (ClapperGtkTitleHeader *header);
|
||||
|
||||
G_END_DECLS
|
488
src/lib/clapper-gtk/clapper-gtk-title-label.c
Normal file
488
src/lib/clapper-gtk/clapper-gtk-title-label.c
Normal file
@@ -0,0 +1,488 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClapperGtkTitleLabel:
|
||||
*
|
||||
* A label showing an up to date title of media item.
|
||||
*
|
||||
* By default #ClapperGtkTitleLabel will automatically show title
|
||||
* of [property@Clapper.Queue:current-item] when placed within
|
||||
* [class@ClapperGtk.Video] widget hierarchy.
|
||||
*
|
||||
* Setting [property@ClapperGtk.TitleLabel:media-item] property will
|
||||
* make it show title of that particular [class@Clapper.MediaItem]
|
||||
* instead. Providing an item to read title from also allows using
|
||||
* this [class@Gtk.Widget] outside of [class@ClapperGtk.Video].
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "clapper-gtk-title-label.h"
|
||||
#include "clapper-gtk-utils-private.h"
|
||||
|
||||
#define DEFAULT_FALLBACK_TO_URI FALSE
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_gtk_title_label_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
struct _ClapperGtkTitleLabel
|
||||
{
|
||||
GtkWidget parent;
|
||||
|
||||
GtkLabel *label;
|
||||
|
||||
ClapperMediaItem *current_item;
|
||||
ClapperMediaItem *custom_item;
|
||||
gboolean fallback_to_uri;
|
||||
|
||||
ClapperPlayer *player;
|
||||
};
|
||||
|
||||
#define parent_class clapper_gtk_title_label_parent_class
|
||||
G_DEFINE_TYPE (ClapperGtkTitleLabel, clapper_gtk_title_label, GTK_TYPE_WIDGET)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_MEDIA_ITEM,
|
||||
PROP_CURRENT_TITLE,
|
||||
PROP_FALLBACK_TO_URI,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
|
||||
|
||||
static void
|
||||
_label_changed_cb (GtkLabel *label G_GNUC_UNUSED,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkTitleLabel *self)
|
||||
{
|
||||
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_CURRENT_TITLE]);
|
||||
}
|
||||
|
||||
static void
|
||||
_refresh_title (ClapperGtkTitleLabel *self)
|
||||
{
|
||||
ClapperMediaItem *item;
|
||||
gchar *title;
|
||||
|
||||
item = (self->custom_item) ? self->custom_item : self->current_item;
|
||||
|
||||
if (!item) {
|
||||
gtk_label_set_label (self->label, _("No media"));
|
||||
return;
|
||||
}
|
||||
|
||||
title = clapper_media_item_get_title (item);
|
||||
|
||||
if (title) {
|
||||
gtk_label_set_label (self->label, title);
|
||||
g_free (title);
|
||||
} else if (self->fallback_to_uri) {
|
||||
gtk_label_set_label (self->label, clapper_media_item_get_uri (item));
|
||||
} else {
|
||||
gtk_label_set_label (self->label, _("Unknown title"));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_media_item_title_changed_cb (ClapperMediaItem *item G_GNUC_UNUSED,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkTitleLabel *self)
|
||||
{
|
||||
_refresh_title (self);
|
||||
}
|
||||
|
||||
static void
|
||||
_set_current_item (ClapperGtkTitleLabel *self, ClapperMediaItem *current_item)
|
||||
{
|
||||
/* Disconnect signal from old item */
|
||||
if (self->current_item) {
|
||||
g_signal_handlers_disconnect_by_func (self->current_item,
|
||||
_media_item_title_changed_cb, self);
|
||||
}
|
||||
|
||||
gst_object_replace ((GstObject **) &self->current_item, GST_OBJECT_CAST (current_item));
|
||||
GST_DEBUG ("Current item changed to: %" GST_PTR_FORMAT, self->current_item);
|
||||
|
||||
/* Reconnect signal to new item */
|
||||
if (self->current_item) {
|
||||
g_signal_connect (self->current_item, "notify::title",
|
||||
G_CALLBACK (_media_item_title_changed_cb), self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_queue_current_item_changed_cb (ClapperQueue *queue,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkTitleLabel *self)
|
||||
{
|
||||
ClapperMediaItem *current_item = clapper_queue_get_current_item (queue);
|
||||
|
||||
_set_current_item (self, current_item);
|
||||
_refresh_title (self);
|
||||
|
||||
gst_clear_object (¤t_item);
|
||||
}
|
||||
|
||||
static void
|
||||
_bind_current_item (ClapperGtkTitleLabel *self)
|
||||
{
|
||||
ClapperQueue *queue = clapper_player_get_queue (self->player);
|
||||
ClapperMediaItem *current_item;
|
||||
|
||||
GST_DEBUG ("Binding current item");
|
||||
|
||||
g_signal_connect (queue, "notify::current-item",
|
||||
G_CALLBACK (_queue_current_item_changed_cb), self);
|
||||
|
||||
current_item = clapper_queue_get_current_item (queue);
|
||||
_set_current_item (self, current_item);
|
||||
gst_clear_object (¤t_item);
|
||||
}
|
||||
|
||||
static void
|
||||
_unbind_current_item (ClapperGtkTitleLabel *self)
|
||||
{
|
||||
ClapperQueue *queue = clapper_player_get_queue (self->player);
|
||||
|
||||
GST_DEBUG ("Unbinding current item");
|
||||
|
||||
g_signal_handlers_disconnect_by_func (queue,
|
||||
_queue_current_item_changed_cb, self);
|
||||
_set_current_item (self, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_title_label_new:
|
||||
*
|
||||
* Creates a new #ClapperGtkTitleLabel instance.
|
||||
*
|
||||
* Returns: a new title label #GtkWidget.
|
||||
*/
|
||||
GtkWidget *
|
||||
clapper_gtk_title_label_new (void)
|
||||
{
|
||||
return g_object_new (CLAPPER_GTK_TYPE_TITLE_LABEL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_title_label_set_media_item:
|
||||
* @label: a #ClapperGtkTitleLabel
|
||||
* @item: (nullable): a #ClapperMediaItem
|
||||
*
|
||||
* Set a media item to display title of as label. When set to %NULL,
|
||||
* @label will use default behavior (showing title of current queue item).
|
||||
*/
|
||||
void
|
||||
clapper_gtk_title_label_set_media_item (ClapperGtkTitleLabel *self, ClapperMediaItem *item)
|
||||
{
|
||||
g_return_if_fail (CLAPPER_GTK_IS_TITLE_LABEL (self));
|
||||
g_return_if_fail (item == NULL || CLAPPER_IS_MEDIA_ITEM (item));
|
||||
|
||||
if (self->custom_item == item)
|
||||
return;
|
||||
|
||||
if (self->player) {
|
||||
_unbind_current_item (self);
|
||||
self->player = NULL;
|
||||
}
|
||||
if (self->custom_item) {
|
||||
g_signal_handlers_disconnect_by_func (self->custom_item,
|
||||
_media_item_title_changed_cb, self);
|
||||
}
|
||||
|
||||
gst_object_replace ((GstObject **) &self->custom_item, GST_OBJECT_CAST (item));
|
||||
|
||||
GST_DEBUG ("Set media item: %" GST_PTR_FORMAT, self->custom_item);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_MEDIA_ITEM]);
|
||||
|
||||
if (self->custom_item) {
|
||||
g_signal_connect (self->custom_item, "notify::title",
|
||||
G_CALLBACK (_media_item_title_changed_cb), self);
|
||||
} else if ((self->player = clapper_gtk_get_player_from_ancestor (GTK_WIDGET (self)))) {
|
||||
_bind_current_item (self);
|
||||
}
|
||||
|
||||
_refresh_title (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_title_label_get_media_item:
|
||||
* @label: a #ClapperGtkTitleLabel
|
||||
*
|
||||
* Get currently set media item to display title of.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): currently set media item.
|
||||
*/
|
||||
ClapperMediaItem *
|
||||
clapper_gtk_title_label_get_media_item (ClapperGtkTitleLabel *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_TITLE_LABEL (self), NULL);
|
||||
|
||||
return self->custom_item;
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_title_label_get_current_title:
|
||||
* @label: a #ClapperGtkTitleLabel
|
||||
*
|
||||
* Get currently displayed title by @label.
|
||||
*
|
||||
* Returns: (transfer none): text of title label.
|
||||
*/
|
||||
const gchar *
|
||||
clapper_gtk_title_label_get_current_title (ClapperGtkTitleLabel *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_TITLE_LABEL (self), NULL);
|
||||
|
||||
return gtk_label_get_label (self->label);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_title_label_set_fallback_to_uri:
|
||||
* @label: a #ClapperGtkTitleLabel
|
||||
* @enabled: whether enabled
|
||||
*
|
||||
* Set whether a [property@Clapper.MediaItem:uri] property should
|
||||
* be displayed as a label text when no other title could be determined.
|
||||
*/
|
||||
void
|
||||
clapper_gtk_title_label_set_fallback_to_uri (ClapperGtkTitleLabel *self, gboolean enabled)
|
||||
{
|
||||
g_return_if_fail (CLAPPER_GTK_IS_TITLE_LABEL (self));
|
||||
|
||||
if (self->fallback_to_uri != enabled) {
|
||||
self->fallback_to_uri = enabled;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_FALLBACK_TO_URI]);
|
||||
|
||||
_refresh_title (self);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_title_label_get_fallback_to_uri:
|
||||
* @label: a #ClapperGtkTitleLabel
|
||||
*
|
||||
* Get whether a [property@Clapper.MediaItem:uri] property is going
|
||||
* be displayed as a label text when no other title could be determined.
|
||||
*/
|
||||
gboolean
|
||||
clapper_gtk_title_label_get_fallback_to_uri (ClapperGtkTitleLabel *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_GTK_IS_TITLE_LABEL (self), FALSE);
|
||||
|
||||
return self->fallback_to_uri;
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_title_label_init (ClapperGtkTitleLabel *self)
|
||||
{
|
||||
self->label = GTK_LABEL (gtk_label_new (NULL));
|
||||
gtk_label_set_single_line_mode (self->label, TRUE);
|
||||
gtk_label_set_ellipsize (self->label, PANGO_ELLIPSIZE_END);
|
||||
gtk_widget_set_can_target (GTK_WIDGET (self->label), FALSE);
|
||||
gtk_widget_set_parent (GTK_WIDGET (self->label), GTK_WIDGET (self));
|
||||
|
||||
self->fallback_to_uri = DEFAULT_FALLBACK_TO_URI;
|
||||
|
||||
/* Apply CSS styles to internal label */
|
||||
g_object_bind_property (self, "css-classes",
|
||||
self->label, "css-classes", G_BINDING_DEFAULT);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_title_label_constructed (GObject *object)
|
||||
{
|
||||
ClapperGtkTitleLabel *self = CLAPPER_GTK_TITLE_LABEL_CAST (object);
|
||||
|
||||
/* Ensure label if no custom item set yet */
|
||||
if (!self->custom_item)
|
||||
_refresh_title (self);
|
||||
|
||||
/* This avoids us from comparing label changes as GTK will do this
|
||||
* for us and emit this signal only when label text actually changes. */
|
||||
g_signal_connect (self->label, "notify::label",
|
||||
G_CALLBACK (_label_changed_cb), self);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_title_label_compute_expand (GtkWidget *widget,
|
||||
gboolean *hexpand_p, gboolean *vexpand_p)
|
||||
{
|
||||
ClapperGtkTitleLabel *self = CLAPPER_GTK_TITLE_LABEL_CAST (widget);
|
||||
|
||||
*hexpand_p = gtk_widget_compute_expand ((GtkWidget *) self->label, GTK_ORIENTATION_HORIZONTAL);
|
||||
*vexpand_p = gtk_widget_compute_expand ((GtkWidget *) self->label, GTK_ORIENTATION_VERTICAL);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_title_label_root (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkTitleLabel *self = CLAPPER_GTK_TITLE_LABEL_CAST (widget);
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->root (widget);
|
||||
|
||||
if (!self->custom_item
|
||||
&& (self->player = clapper_gtk_get_player_from_ancestor (widget))) {
|
||||
GST_LOG ("Label placed without media item set");
|
||||
_bind_current_item (self);
|
||||
_refresh_title (self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_title_label_unroot (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkTitleLabel *self = CLAPPER_GTK_TITLE_LABEL_CAST (widget);
|
||||
|
||||
if (self->player) {
|
||||
_unbind_current_item (self);
|
||||
self->player = NULL;
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->unroot (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
_label_unparent (GtkLabel *label)
|
||||
{
|
||||
gtk_widget_unparent (GTK_WIDGET (label));
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_title_label_dispose (GObject *object)
|
||||
{
|
||||
ClapperGtkTitleLabel *self = CLAPPER_GTK_TITLE_LABEL_CAST (object);
|
||||
|
||||
if (self->custom_item) {
|
||||
g_signal_handlers_disconnect_by_func (self->custom_item,
|
||||
_media_item_title_changed_cb, self);
|
||||
}
|
||||
if (self->label) {
|
||||
g_signal_handlers_disconnect_by_func (self->label,
|
||||
_label_changed_cb, self);
|
||||
}
|
||||
|
||||
gst_clear_object (&self->current_item);
|
||||
gst_clear_object (&self->custom_item);
|
||||
g_clear_pointer (&self->label, _label_unparent);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_title_label_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkTitleLabel *self = CLAPPER_GTK_TITLE_LABEL_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_MEDIA_ITEM:
|
||||
g_value_set_object (value, clapper_gtk_title_label_get_media_item (self));
|
||||
break;
|
||||
case PROP_CURRENT_TITLE:
|
||||
g_value_set_string (value, clapper_gtk_title_label_get_current_title (self));
|
||||
break;
|
||||
case PROP_FALLBACK_TO_URI:
|
||||
g_value_set_boolean (value, clapper_gtk_title_label_get_fallback_to_uri (self));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_title_label_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ClapperGtkTitleLabel *self = CLAPPER_GTK_TITLE_LABEL_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_MEDIA_ITEM:
|
||||
clapper_gtk_title_label_set_media_item (self, g_value_get_object (value));
|
||||
break;
|
||||
case PROP_FALLBACK_TO_URI:
|
||||
clapper_gtk_title_label_set_fallback_to_uri (self, g_value_get_boolean (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_title_label_class_init (ClapperGtkTitleLabelClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtktitlelabel", 0,
|
||||
"Clapper GTK Title Label");
|
||||
clapper_gtk_init_translations ();
|
||||
|
||||
gobject_class->constructed = clapper_gtk_title_label_constructed;
|
||||
gobject_class->get_property = clapper_gtk_title_label_get_property;
|
||||
gobject_class->set_property = clapper_gtk_title_label_set_property;
|
||||
gobject_class->dispose = clapper_gtk_title_label_dispose;
|
||||
|
||||
widget_class->compute_expand = clapper_gtk_title_label_compute_expand;
|
||||
|
||||
/* Using root/unroot so label "current-title" is immediately
|
||||
* updated and can be accessed before label was made visible */
|
||||
widget_class->root = clapper_gtk_title_label_root;
|
||||
widget_class->unroot = clapper_gtk_title_label_unroot;
|
||||
|
||||
/**
|
||||
* ClapperGtkTitleLabel:media-item:
|
||||
*
|
||||
* Currently set media item to display title of.
|
||||
*/
|
||||
param_specs[PROP_MEDIA_ITEM] = g_param_spec_object ("media-item",
|
||||
NULL, NULL, CLAPPER_TYPE_MEDIA_ITEM,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClapperGtkTitleLabel:current-title:
|
||||
*
|
||||
* Currently displayed title.
|
||||
*/
|
||||
param_specs[PROP_CURRENT_TITLE] = g_param_spec_string ("current-title",
|
||||
NULL, NULL, NULL,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClapperGtkTitleLabel:fallback-to-uri:
|
||||
*
|
||||
* When title cannot be determined, show URI instead.
|
||||
*/
|
||||
param_specs[PROP_FALLBACK_TO_URI] = g_param_spec_boolean ("fallback-to-uri",
|
||||
NULL, NULL, DEFAULT_FALLBACK_TO_URI,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | 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-title-label");
|
||||
}
|
50
src/lib/clapper-gtk/clapper-gtk-title-label.h
Normal file
50
src/lib/clapper-gtk/clapper-gtk-title-label.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <clapper/clapper.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_TITLE_LABEL (clapper_gtk_title_label_get_type())
|
||||
#define CLAPPER_GTK_TITLE_LABEL_CAST(obj) ((ClapperGtkTitleLabel *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkTitleLabel, clapper_gtk_title_label, CLAPPER_GTK, TITLE_LABEL, GtkWidget)
|
||||
|
||||
GtkWidget * clapper_gtk_title_label_new (void);
|
||||
|
||||
void clapper_gtk_title_label_set_media_item (ClapperGtkTitleLabel *label, ClapperMediaItem *item);
|
||||
|
||||
ClapperMediaItem * clapper_gtk_title_label_get_media_item (ClapperGtkTitleLabel *label);
|
||||
|
||||
const gchar * clapper_gtk_title_label_get_current_title (ClapperGtkTitleLabel *label);
|
||||
|
||||
void clapper_gtk_title_label_set_fallback_to_uri (ClapperGtkTitleLabel *label, gboolean enabled);
|
||||
|
||||
gboolean clapper_gtk_title_label_get_fallback_to_uri (ClapperGtkTitleLabel *label);
|
||||
|
||||
G_END_DECLS
|
154
src/lib/clapper-gtk/clapper-gtk-toggle-fullscreen-button.c
Normal file
154
src/lib/clapper-gtk/clapper-gtk-toggle-fullscreen-button.c
Normal file
@@ -0,0 +1,154 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClapperGtkToggleFullscreenButton:
|
||||
*
|
||||
* A #GtkButton for toggling fullscreen state.
|
||||
*/
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "clapper-gtk-toggle-fullscreen-button.h"
|
||||
#include "clapper-gtk-video.h"
|
||||
|
||||
#define ENTER_FULLSCREEN_ICON_NAME "view-fullscreen-symbolic"
|
||||
#define LEAVE_FULLSCREEN_ICON_NAME "view-restore-symbolic"
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_gtk_toggle_fullscreen_button_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
struct _ClapperGtkToggleFullscreenButton
|
||||
{
|
||||
GtkButton parent;
|
||||
|
||||
gboolean is_fullscreen;
|
||||
};
|
||||
|
||||
#define parent_class clapper_gtk_toggle_fullscreen_button_parent_class
|
||||
G_DEFINE_TYPE (ClapperGtkToggleFullscreenButton, clapper_gtk_toggle_fullscreen_button, GTK_TYPE_BUTTON)
|
||||
|
||||
static void
|
||||
_toplevel_state_changed_cb (GdkToplevel *toplevel,
|
||||
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkToggleFullscreenButton *self)
|
||||
{
|
||||
GdkToplevelState state = gdk_toplevel_get_state (toplevel);
|
||||
gboolean is_fullscreen = (state & GDK_TOPLEVEL_STATE_FULLSCREEN);
|
||||
|
||||
if (self->is_fullscreen == is_fullscreen)
|
||||
return;
|
||||
|
||||
self->is_fullscreen = is_fullscreen;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Toplevel state changed, fullscreen: %s",
|
||||
(self->is_fullscreen) ? "yes" : "no");
|
||||
|
||||
gtk_button_set_icon_name (GTK_BUTTON (self),
|
||||
(!self->is_fullscreen) ? ENTER_FULLSCREEN_ICON_NAME : LEAVE_FULLSCREEN_ICON_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_toggle_fullscreen_button_new:
|
||||
*
|
||||
* Creates a new #ClapperGtkToggleFullscreenButton instance.
|
||||
*
|
||||
* Returns: a new toggle fullscreen button #GtkWidget.
|
||||
*/
|
||||
GtkWidget *
|
||||
clapper_gtk_toggle_fullscreen_button_new (void)
|
||||
{
|
||||
return g_object_new (CLAPPER_GTK_TYPE_TOGGLE_FULLSCREEN_BUTTON, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_toggle_fullscreen_button_init (ClapperGtkToggleFullscreenButton *self)
|
||||
{
|
||||
gtk_button_set_icon_name (GTK_BUTTON (self), ENTER_FULLSCREEN_ICON_NAME);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_toggle_fullscreen_button_map (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkToggleFullscreenButton *self = CLAPPER_GTK_TOGGLE_FULLSCREEN_BUTTON_CAST (widget);
|
||||
GtkRoot *root;
|
||||
GdkSurface *surface;
|
||||
|
||||
GST_TRACE_OBJECT (self, "Map");
|
||||
|
||||
root = gtk_widget_get_root (widget);
|
||||
surface = gtk_native_get_surface (GTK_NATIVE (root));
|
||||
|
||||
if (G_LIKELY (GDK_IS_TOPLEVEL (surface))) {
|
||||
GdkToplevel *toplevel = GDK_TOPLEVEL (surface);
|
||||
|
||||
g_signal_connect (toplevel, "notify::state",
|
||||
G_CALLBACK (_toplevel_state_changed_cb), self);
|
||||
_toplevel_state_changed_cb (toplevel, NULL, self);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->map (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_toggle_fullscreen_button_unmap (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkToggleFullscreenButton *self = CLAPPER_GTK_TOGGLE_FULLSCREEN_BUTTON_CAST (widget);
|
||||
GtkRoot *root;
|
||||
GdkSurface *surface;
|
||||
|
||||
GST_TRACE_OBJECT (self, "Unmap");
|
||||
|
||||
root = gtk_widget_get_root (widget);
|
||||
surface = gtk_native_get_surface (GTK_NATIVE (root));
|
||||
|
||||
if (G_LIKELY (GDK_IS_TOPLEVEL (surface))) {
|
||||
GdkToplevel *toplevel = GDK_TOPLEVEL (surface);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (toplevel,
|
||||
_toplevel_state_changed_cb, self);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->unmap (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_toggle_fullscreen_button_clicked (GtkButton* button)
|
||||
{
|
||||
GtkWidget *video;
|
||||
|
||||
GST_DEBUG_OBJECT (button, "Clicked");
|
||||
|
||||
if ((video = gtk_widget_get_ancestor (GTK_WIDGET (button), CLAPPER_GTK_TYPE_VIDEO)))
|
||||
g_signal_emit_by_name (video, "toggle-fullscreen");
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_toggle_fullscreen_button_class_init (ClapperGtkToggleFullscreenButtonClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
GtkButtonClass *button_class = (GtkButtonClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtktogglefullscreenbutton", 0,
|
||||
"Clapper GTK Toggle Fullscreen Button");
|
||||
|
||||
widget_class->map = clapper_gtk_toggle_fullscreen_button_map;
|
||||
widget_class->unmap = clapper_gtk_toggle_fullscreen_button_unmap;
|
||||
|
||||
button_class->clicked = clapper_gtk_toggle_fullscreen_button_clicked;
|
||||
}
|
39
src/lib/clapper-gtk/clapper-gtk-toggle-fullscreen-button.h
Normal file
39
src/lib/clapper-gtk/clapper-gtk-toggle-fullscreen-button.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_TOGGLE_FULLSCREEN_BUTTON (clapper_gtk_toggle_fullscreen_button_get_type())
|
||||
#define CLAPPER_GTK_TOGGLE_FULLSCREEN_BUTTON_CAST(obj) ((ClapperGtkToggleFullscreenButton *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkToggleFullscreenButton, clapper_gtk_toggle_fullscreen_button, CLAPPER_GTK, TOGGLE_FULLSCREEN_BUTTON, GtkButton)
|
||||
|
||||
GtkWidget * clapper_gtk_toggle_fullscreen_button_new (void);
|
||||
|
||||
G_END_DECLS
|
126
src/lib/clapper-gtk/clapper-gtk-toggle-play-button.c
Normal file
126
src/lib/clapper-gtk/clapper-gtk-toggle-play-button.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClapperGtkTogglePlayButton:
|
||||
*
|
||||
* A #GtkButton for toggling play/pause of playback.
|
||||
*/
|
||||
|
||||
#include <clapper/clapper.h>
|
||||
|
||||
#include "clapper-gtk-toggle-play-button.h"
|
||||
#include "clapper-gtk-utils.h"
|
||||
|
||||
#define PLAY_ICON_NAME "media-playback-start-symbolic"
|
||||
#define PAUSE_ICON_NAME "media-playback-pause-symbolic"
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_gtk_toggle_play_button_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
struct _ClapperGtkTogglePlayButton
|
||||
{
|
||||
GtkButton parent;
|
||||
|
||||
GBinding *state_binding;
|
||||
};
|
||||
|
||||
#define parent_class clapper_gtk_toggle_play_button_parent_class
|
||||
G_DEFINE_TYPE (ClapperGtkTogglePlayButton, clapper_gtk_toggle_play_button, GTK_TYPE_BUTTON)
|
||||
|
||||
static gboolean
|
||||
_transform_state_func (GBinding *binding, const GValue *from_value,
|
||||
GValue *to_value, ClapperGtkTogglePlayButton *self)
|
||||
{
|
||||
ClapperPlayerState state = g_value_get_enum (from_value);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Reflecting player state change, now: %i", state);
|
||||
|
||||
switch (state) {
|
||||
case CLAPPER_PLAYER_STATE_STOPPED:
|
||||
case CLAPPER_PLAYER_STATE_PAUSED:
|
||||
g_value_set_string (to_value, PLAY_ICON_NAME);
|
||||
break;
|
||||
case CLAPPER_PLAYER_STATE_PLAYING:
|
||||
g_value_set_string (to_value, PAUSE_ICON_NAME);
|
||||
break;
|
||||
default:
|
||||
return FALSE; // no change
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_gtk_toggle_play_button_new:
|
||||
*
|
||||
* Creates a new #ClapperGtkTogglePlayButton instance.
|
||||
*
|
||||
* Returns: a new toggle play button #GtkWidget.
|
||||
*/
|
||||
GtkWidget *
|
||||
clapper_gtk_toggle_play_button_new (void)
|
||||
{
|
||||
return g_object_new (CLAPPER_GTK_TYPE_TOGGLE_PLAY_BUTTON, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_toggle_play_button_init (ClapperGtkTogglePlayButton *self)
|
||||
{
|
||||
gtk_button_set_icon_name (GTK_BUTTON (self), PLAY_ICON_NAME);
|
||||
gtk_actionable_set_action_name (GTK_ACTIONABLE (self), "video.toggle-play");
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_toggle_play_button_map (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkTogglePlayButton *self = CLAPPER_GTK_TOGGLE_PLAY_BUTTON_CAST (widget);
|
||||
ClapperPlayer *player;
|
||||
|
||||
if ((player = clapper_gtk_get_player_from_ancestor (widget))) {
|
||||
self->state_binding = g_object_bind_property_full (player, "state",
|
||||
self, "icon-name", G_BINDING_SYNC_CREATE,
|
||||
(GBindingTransformFunc) _transform_state_func,
|
||||
NULL, self, NULL);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->map (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_toggle_play_button_unmap (GtkWidget *widget)
|
||||
{
|
||||
ClapperGtkTogglePlayButton *self = CLAPPER_GTK_TOGGLE_PLAY_BUTTON_CAST (widget);
|
||||
|
||||
g_clear_pointer (&self->state_binding, g_binding_unbind);
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->unmap (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_gtk_toggle_play_button_class_init (ClapperGtkTogglePlayButtonClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtktoggleplaybutton", 0,
|
||||
"Clapper GTK Toggle Play Button");
|
||||
|
||||
widget_class->map = clapper_gtk_toggle_play_button_map;
|
||||
widget_class->unmap = clapper_gtk_toggle_play_button_unmap;
|
||||
}
|
39
src/lib/clapper-gtk/clapper-gtk-toggle-play-button.h
Normal file
39
src/lib/clapper-gtk/clapper-gtk-toggle-play-button.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_TOGGLE_PLAY_BUTTON (clapper_gtk_toggle_play_button_get_type())
|
||||
#define CLAPPER_GTK_TOGGLE_PLAY_BUTTON_CAST(obj) ((ClapperGtkTogglePlayButton *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkTogglePlayButton, clapper_gtk_toggle_play_button, CLAPPER_GTK, TOGGLE_PLAY_BUTTON, GtkButton)
|
||||
|
||||
GtkWidget * clapper_gtk_toggle_play_button_new (void);
|
||||
|
||||
G_END_DECLS
|
35
src/lib/clapper-gtk/clapper-gtk-utils-private.h
Normal file
35
src/lib/clapper-gtk/clapper-gtk-utils-private.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "clapper-gtk-utils.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_gtk_init_translations (void);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
const gchar * clapper_gtk_get_icon_name_for_volume (gfloat volume);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
const gchar * clapper_gtk_get_icon_name_for_speed (gfloat speed);
|
||||
|
||||
G_END_DECLS
|
96
src/lib/clapper-gtk/clapper-gtk-utils.c
Normal file
96
src/lib/clapper-gtk/clapper-gtk-utils.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
#include "clapper-gtk-utils-private.h"
|
||||
#include "clapper-gtk-video.h"
|
||||
|
||||
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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* 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).
|
||||
*
|
||||
* Returns: (transfer none) (nullable): a #ClapperPlayer from ancestor of a @widget.
|
||||
*/
|
||||
ClapperPlayer *
|
||||
clapper_gtk_get_player_from_ancestor (GtkWidget *widget)
|
||||
{
|
||||
GtkWidget *parent;
|
||||
ClapperPlayer *player = NULL;
|
||||
|
||||
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));
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
void
|
||||
clapper_gtk_init_translations (void)
|
||||
{
|
||||
if (initialized)
|
||||
return;
|
||||
|
||||
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
clapper_gtk_get_icon_name_for_volume (gfloat volume)
|
||||
{
|
||||
return (volume <= 0.0f)
|
||||
? "audio-volume-muted-symbolic"
|
||||
: (volume <= 0.3f)
|
||||
? "audio-volume-low-symbolic"
|
||||
: (volume <= 0.7f)
|
||||
? "audio-volume-medium-symbolic"
|
||||
: (volume <= 1.0f)
|
||||
? "audio-volume-high-symbolic"
|
||||
: "audio-volume-overamplified-symbolic";
|
||||
}
|
||||
|
||||
const gchar *
|
||||
clapper_gtk_get_icon_name_for_speed (gfloat speed)
|
||||
{
|
||||
return (speed < 1.0f)
|
||||
? "power-profile-power-saver-symbolic"
|
||||
: (speed == 1.0f)
|
||||
? "power-profile-balanced-symbolic"
|
||||
: "power-profile-performance-symbolic";
|
||||
}
|
34
src/lib/clapper-gtk/clapper-gtk-utils.h
Normal file
34
src/lib/clapper-gtk/clapper-gtk-utils.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <clapper/clapper.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
ClapperPlayer * clapper_gtk_get_player_from_ancestor (GtkWidget *widget);
|
||||
|
||||
G_END_DECLS
|
76
src/lib/clapper-gtk/clapper-gtk-version.h.in
Normal file
76
src/lib/clapper-gtk/clapper-gtk-version.h.in
Normal file
@@ -0,0 +1,76 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* CLAPPER_GTK_MAJOR_VERSION:
|
||||
*
|
||||
* ClapperGtk major version component
|
||||
*/
|
||||
#define CLAPPER_GTK_MAJOR_VERSION (@CLAPPER_GTK_MAJOR_VERSION@)
|
||||
|
||||
/**
|
||||
* CLAPPER_GTK_MINOR_VERSION:
|
||||
*
|
||||
* ClapperGtk minor version component
|
||||
*/
|
||||
#define CLAPPER_GTK_MINOR_VERSION (@CLAPPER_GTK_MINOR_VERSION@)
|
||||
|
||||
/**
|
||||
* CLAPPER_GTK_MICRO_VERSION:
|
||||
*
|
||||
* ClapperGtk micro version component
|
||||
*/
|
||||
#define CLAPPER_GTK_MICRO_VERSION (@CLAPPER_GTK_MICRO_VERSION@)
|
||||
|
||||
/**
|
||||
* CLAPPER_GTK_VERSION:
|
||||
*
|
||||
* ClapperGtk version
|
||||
*/
|
||||
#define CLAPPER_GTK_VERSION (@CLAPPER_GTK_VERSION@)
|
||||
|
||||
/**
|
||||
* CLAPPER_GTK_VERSION_S:
|
||||
*
|
||||
* ClapperGtk version, encoded as a string
|
||||
*/
|
||||
#define CLAPPER_GTK_VERSION_S "@CLAPPER_GTK_VERSION@"
|
||||
|
||||
#define CLAPPER_GTK_ENCODE_VERSION(major,minor,micro) \
|
||||
((major) << 24 | (minor) << 16 | (micro) << 8)
|
||||
|
||||
/**
|
||||
* CLAPPER_GTK_VERSION_HEX:
|
||||
*
|
||||
* ClapperGtk version, encoded as an hexadecimal number, useful for integer comparisons.
|
||||
*/
|
||||
#define CLAPPER_GTK_VERSION_HEX \
|
||||
(CLAPPER_GTK_ENCODE_VERSION (CLAPPER_GTK_MAJOR_VERSION, CLAPPER_GTK_MINOR_VERSION, CLAPPER_GTK_MICRO_VERSION))
|
||||
|
||||
#define CLAPPER_GTK_CHECK_VERSION(major, minor, micro) \
|
||||
(CLAPPER_GTK_MAJOR_VERSION > (major) || \
|
||||
(CLAPPER_GTK_MAJOR_VERSION == (major) && CLAPPER_GTK_MINOR_VERSION > (minor)) || \
|
||||
(CLAPPER_GTK_MAJOR_VERSION == (major) && CLAPPER_GTK_MINOR_VERSION == (minor) && \
|
||||
CLAPPER_GTK_MICRO_VERSION >= (micro)))
|
1601
src/lib/clapper-gtk/clapper-gtk-video.c
Normal file
1601
src/lib/clapper-gtk/clapper-gtk-video.c
Normal file
File diff suppressed because it is too large
Load Diff
60
src/lib/clapper-gtk/clapper-gtk-video.h
Normal file
60
src/lib/clapper-gtk/clapper-gtk-video.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
|
||||
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <clapper/clapper.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_GTK_TYPE_VIDEO (clapper_gtk_video_get_type())
|
||||
#define CLAPPER_GTK_VIDEO_CAST(obj) ((ClapperGtkVideo *)(obj))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClapperGtkVideo, clapper_gtk_video, CLAPPER_GTK, VIDEO, GtkWidget)
|
||||
|
||||
GtkWidget * clapper_gtk_video_new (void);
|
||||
|
||||
void clapper_gtk_video_add_overlay (ClapperGtkVideo *video, GtkWidget *widget);
|
||||
|
||||
void clapper_gtk_video_add_fading_overlay (ClapperGtkVideo *video, GtkWidget *widget);
|
||||
|
||||
ClapperPlayer * clapper_gtk_video_get_player (ClapperGtkVideo *video);
|
||||
|
||||
void clapper_gtk_video_set_fade_delay (ClapperGtkVideo *video, guint delay);
|
||||
|
||||
guint clapper_gtk_video_get_fade_delay (ClapperGtkVideo *video);
|
||||
|
||||
void clapper_gtk_video_set_touch_fade_delay (ClapperGtkVideo *video, guint delay);
|
||||
|
||||
guint clapper_gtk_video_get_touch_fade_delay (ClapperGtkVideo *video);
|
||||
|
||||
void clapper_gtk_video_set_auto_inhibit (ClapperGtkVideo *video, gboolean inhibit);
|
||||
|
||||
gboolean clapper_gtk_video_get_auto_inhibit (ClapperGtkVideo *video);
|
||||
|
||||
gboolean clapper_gtk_video_get_inhibited (ClapperGtkVideo *video);
|
||||
|
||||
G_END_DECLS
|
14
src/lib/clapper-gtk/clapper-gtk.gresources.xml
Normal file
14
src/lib/clapper-gtk/clapper-gtk.gresources.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/com/github/rafostar/Clapper/clapper-gtk">
|
||||
<file preprocess="xml-stripblanks">ui/clapper-gtk-billboard.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/clapper-gtk-extra-menu-button.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/clapper-gtk-seek-bar.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/clapper-gtk-simple-controls.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/clapper-gtk-status.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/clapper-gtk-stream-list-item.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/clapper-gtk-title-header.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/clapper-gtk-video.ui</file>
|
||||
<file compressed="true">css/styles.css</file>
|
||||
</gresource>
|
||||
</gresources>
|
42
src/lib/clapper-gtk/clapper-gtk.h
Normal file
42
src/lib/clapper-gtk/clapper-gtk.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* Clapper GTK Integration Library
|
||||
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define __CLAPPER_GTK_INSIDE__
|
||||
|
||||
#include <clapper-gtk/clapper-gtk-enums.h>
|
||||
#include <clapper-gtk/clapper-gtk-version.h>
|
||||
|
||||
#include <clapper-gtk/clapper-gtk-billboard.h>
|
||||
#include <clapper-gtk/clapper-gtk-container.h>
|
||||
#include <clapper-gtk/clapper-gtk-extra-menu-button.h>
|
||||
#include <clapper-gtk/clapper-gtk-lead-container.h>
|
||||
#include <clapper-gtk/clapper-gtk-next-item-button.h>
|
||||
#include <clapper-gtk/clapper-gtk-previous-item-button.h>
|
||||
#include <clapper-gtk/clapper-gtk-seek-bar.h>
|
||||
#include <clapper-gtk/clapper-gtk-simple-controls.h>
|
||||
#include <clapper-gtk/clapper-gtk-title-header.h>
|
||||
#include <clapper-gtk/clapper-gtk-title-label.h>
|
||||
#include <clapper-gtk/clapper-gtk-toggle-fullscreen-button.h>
|
||||
#include <clapper-gtk/clapper-gtk-toggle-play-button.h>
|
||||
#include <clapper-gtk/clapper-gtk-utils.h>
|
||||
#include <clapper-gtk/clapper-gtk-video.h>
|
||||
|
||||
#undef __CLAPPER_GTK_INSIDE__
|
153
src/lib/clapper-gtk/css/styles.css
Normal file
153
src/lib/clapper-gtk/css/styles.css
Normal file
@@ -0,0 +1,153 @@
|
||||
/* Adwaita OSD background color is unacceptable:
|
||||
* https://gitlab.gnome.org/GNOME/libadwaita/-/issues/454 */
|
||||
clapper-gtk-video menubutton.osd,
|
||||
clapper-gtk-video button.osd,
|
||||
clapper-gtk-video box.osd,
|
||||
clapper-gtk-video clapper-gtk-title-header.osd,
|
||||
clapper-gtk-video .osd popover contents,
|
||||
clapper-gtk-video .osd popover arrow {
|
||||
background-color: rgba(38,38,38,0.8);
|
||||
}
|
||||
clapper-gtk-video button.osd:hover,
|
||||
clapper-gtk-video button.osd:checked {
|
||||
background-color: rgba(63,63,63,0.8);
|
||||
}
|
||||
clapper-gtk-video button.osd:active {
|
||||
background-color: rgba(82,82,82,0.8);
|
||||
}
|
||||
clapper-gtk-video box.osd listview.osd {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
clapper-gtk-status box {
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
clapper-gtk-status box image {
|
||||
-gtk-icon-size: 128px;
|
||||
-gtk-icon-filter: opacity(0.6);
|
||||
}
|
||||
clapper-gtk-status.adapted box image {
|
||||
-gtk-icon-size: 96px;
|
||||
}
|
||||
|
||||
clapper-gtk-billboard .sidebox {
|
||||
padding: 12px;
|
||||
border-radius: 9999px;
|
||||
}
|
||||
clapper-gtk-billboard .sidebox:dir(ltr) {
|
||||
margin-left: 6px;
|
||||
}
|
||||
clapper-gtk-billboard .sidebox:dir(rtl) {
|
||||
margin-right: 6px;
|
||||
}
|
||||
clapper-gtk-billboard .sidebox .progressbox {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
clapper-gtk-billboard .sidebox .progressbox progressbar {
|
||||
min-height: 90px;
|
||||
}
|
||||
clapper-gtk-billboard .sidebox .progressbox.overamp progress {
|
||||
background: #c01c28;
|
||||
}
|
||||
clapper-gtk-billboard .sidebox .progresslabel:dir(ltr) {
|
||||
margin-left: 6px;
|
||||
}
|
||||
clapper-gtk-billboard .sidebox .progresslabel:dir(rtl) {
|
||||
margin-right: 6px;
|
||||
}
|
||||
clapper-gtk-billboard .messagebox {
|
||||
margin: 6px;
|
||||
padding: 12px;
|
||||
min-width: 92px;
|
||||
}
|
||||
clapper-gtk-billboard .messagebox image {
|
||||
-gtk-icon-size: 48px;
|
||||
}
|
||||
|
||||
menubutton.circular,
|
||||
dropdown.circular button.toggle {
|
||||
border-radius: 9999px;
|
||||
}
|
||||
.rounded {
|
||||
border-radius: 19px;
|
||||
}
|
||||
|
||||
clapper-gtk-title-header {
|
||||
margin: 6px;
|
||||
min-height: 38px;
|
||||
}
|
||||
clapper-gtk-title-header label {
|
||||
margin-left: 12px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
clapper-gtk-simple-controls .centerbox {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
clapper-gtk-simple-controls .mainbox {
|
||||
margin-left: 6px;
|
||||
margin-right: 6px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
clapper-gtk-simple-controls .mainbox button {
|
||||
margin: 2px;
|
||||
}
|
||||
clapper-gtk-simple-controls .mainbox scale {
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
clapper-gtk-simple-controls .mainbox popover button {
|
||||
margin: 0px;
|
||||
}
|
||||
clapper-gtk-simple-controls .fullscreenbutton {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
clapper-gtk-simple-controls .fullscreenbutton:dir(ltr) {
|
||||
margin-right: 6px;
|
||||
}
|
||||
clapper-gtk-simple-controls .fullscreenbutton:dir(rtl) {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
clapper-gtk-seek-bar scale trough highlight {
|
||||
min-height: 6px;
|
||||
}
|
||||
clapper-gtk-seek-bar label {
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
clapper-gtk-extra-menu-button popover .spinsidebutton {
|
||||
min-width: 28px;
|
||||
min-height: 28px;
|
||||
}
|
||||
clapper-gtk-extra-menu-button popover .spinsidebutton:dir(ltr) {
|
||||
margin-right: 2px;
|
||||
}
|
||||
clapper-gtk-extra-menu-button popover .spinsidebutton:dir(rtl) {
|
||||
margin-left: 2px;
|
||||
}
|
||||
clapper-gtk-extra-menu-button popover spinbutton {
|
||||
border-radius: 9999px;
|
||||
}
|
||||
clapper-gtk-extra-menu-button popover spinbutton button.up:dir(ltr) {
|
||||
border-radius: 0px 9999px 9999px 0px;
|
||||
}
|
||||
clapper-gtk-extra-menu-button popover spinbutton button.up:dir(rtl) {
|
||||
border-radius: 9999px 0px 0px 9999px;
|
||||
}
|
||||
clapper-gtk-extra-menu-button popover spinbutton button.up:dir(ltr) {
|
||||
padding-right: 6px;
|
||||
}
|
||||
clapper-gtk-extra-menu-button popover spinbutton button.up:dir(rtl) {
|
||||
padding-left: 6px;
|
||||
}
|
||||
clapper-gtk-menu-scrolled-window listview row {
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
clapper-gtk-menu-scrolled-window listview row checkbutton label {
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
}
|
221
src/lib/clapper-gtk/meson.build
Normal file
221
src/lib/clapper-gtk/meson.build
Normal file
@@ -0,0 +1,221 @@
|
||||
clappergtk_dep = dependency('', required: false)
|
||||
clappergtk_option = get_option('clapper-gtk')
|
||||
clappergtk_api_name = meson.project_name() + '-gtk' + clapper_version_suffix
|
||||
clappergtk_resource_prefix = '/com/github/rafostar/Clapper/clapper-gtk'
|
||||
build_clappergtk = false
|
||||
|
||||
if clappergtk_option.disabled()
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
clappergtk_deps = [
|
||||
clapper_dep,
|
||||
gst_dep,
|
||||
gst_clapper_sink_dep,
|
||||
gtk4_dep,
|
||||
glib_dep,
|
||||
gobject_dep,
|
||||
libm,
|
||||
]
|
||||
|
||||
foreach dep : clappergtk_deps
|
||||
if not dep.found()
|
||||
if clappergtk_option.enabled()
|
||||
error('clapper-gtk option was enabled, but required dependencies were not found')
|
||||
endif
|
||||
subdir_done()
|
||||
endif
|
||||
endforeach
|
||||
|
||||
subdir('po')
|
||||
|
||||
config_h = configuration_data()
|
||||
config_h.set_quoted('GETTEXT_PACKAGE', meson.project_name() + '-app')
|
||||
config_h.set_quoted('LOCALEDIR', join_paths (prefix, localedir))
|
||||
config_h.set_quoted('CLAPPER_GTK_RESOURCE_PREFIX', clappergtk_resource_prefix)
|
||||
|
||||
configure_file(
|
||||
output: 'config.h',
|
||||
configuration: config_h,
|
||||
)
|
||||
|
||||
version_conf = configuration_data()
|
||||
|
||||
version_conf.set(
|
||||
'CLAPPER_GTK_VERSION',
|
||||
meson.project_version(),
|
||||
)
|
||||
version_conf.set(
|
||||
'CLAPPER_GTK_MAJOR_VERSION',
|
||||
version_array[0].to_int(),
|
||||
)
|
||||
version_conf.set(
|
||||
'CLAPPER_GTK_MINOR_VERSION',
|
||||
version_array[1].to_int(),
|
||||
)
|
||||
version_conf.set(
|
||||
'CLAPPER_GTK_MICRO_VERSION',
|
||||
version_array[2].to_int(),
|
||||
)
|
||||
|
||||
clappergtk_version_header = configure_file(
|
||||
input: 'clapper-gtk-version.h.in',
|
||||
output: 'clapper-gtk-version.h',
|
||||
configuration: version_conf,
|
||||
)
|
||||
clappergtk_resources = gnome.compile_resources(
|
||||
'clapper-gtk-resources',
|
||||
'clapper-gtk.gresources.xml',
|
||||
c_name: 'clapper_gtk',
|
||||
)
|
||||
|
||||
# Include the generated headers
|
||||
clappergtk_conf_inc = [
|
||||
include_directories('.'),
|
||||
include_directories('..'),
|
||||
]
|
||||
|
||||
clappergtk_headers = [
|
||||
'clapper-gtk.h',
|
||||
'clapper-gtk-enums.h',
|
||||
'clapper-gtk-billboard.h',
|
||||
'clapper-gtk-container.h',
|
||||
'clapper-gtk-extra-menu-button.h',
|
||||
'clapper-gtk-lead-container.h',
|
||||
'clapper-gtk-next-item-button.h',
|
||||
'clapper-gtk-previous-item-button.h',
|
||||
'clapper-gtk-seek-bar.h',
|
||||
'clapper-gtk-simple-controls.h',
|
||||
'clapper-gtk-title-header.h',
|
||||
'clapper-gtk-title-label.h',
|
||||
'clapper-gtk-toggle-fullscreen-button.h',
|
||||
'clapper-gtk-toggle-play-button.h',
|
||||
'clapper-gtk-utils.h',
|
||||
'clapper-gtk-video.h',
|
||||
clappergtk_version_header,
|
||||
]
|
||||
clappergtk_sources = [
|
||||
'clapper-gtk-billboard.c',
|
||||
'clapper-gtk-buffering-animation.c',
|
||||
'clapper-gtk-buffering-paintable.c',
|
||||
'clapper-gtk-container.c',
|
||||
'clapper-gtk-extra-menu-button.c',
|
||||
'clapper-gtk-lead-container.c',
|
||||
'clapper-gtk-limited-layout.c',
|
||||
'clapper-gtk-next-item-button.c',
|
||||
'clapper-gtk-previous-item-button.c',
|
||||
'clapper-gtk-seek-bar.c',
|
||||
'clapper-gtk-simple-controls.c',
|
||||
'clapper-gtk-status.c',
|
||||
'clapper-gtk-stream-check-button.c',
|
||||
'clapper-gtk-title-header.c',
|
||||
'clapper-gtk-title-label.c',
|
||||
'clapper-gtk-toggle-fullscreen-button.c',
|
||||
'clapper-gtk-toggle-play-button.c',
|
||||
'clapper-gtk-utils.c',
|
||||
'clapper-gtk-video.c',
|
||||
clappergtk_resources,
|
||||
]
|
||||
clappergtk_c_args = [
|
||||
'-DG_LOG_DOMAIN="ClapperGtk"',
|
||||
'-DCLAPPER_GTK_COMPILATION',
|
||||
'-DGST_USE_UNSTABLE_API',
|
||||
]
|
||||
|
||||
clappergtk_headers_dir = join_paths(includedir, clapper_api_name, 'clapper-gtk')
|
||||
|
||||
clappergtk_enums = gnome.mkenums_simple(
|
||||
'clapper-gtk-enum-types',
|
||||
sources: clappergtk_headers,
|
||||
identifier_prefix: 'ClapperGtk',
|
||||
symbol_prefix: 'clapper_gtk',
|
||||
install_header: true,
|
||||
install_dir: clappergtk_headers_dir,
|
||||
)
|
||||
|
||||
clappergtk_lib = library(
|
||||
clappergtk_api_name,
|
||||
clappergtk_sources + clappergtk_enums,
|
||||
dependencies: clappergtk_deps,
|
||||
include_directories: clappergtk_conf_inc,
|
||||
c_args: clappergtk_c_args,
|
||||
version: clapper_version,
|
||||
install: true,
|
||||
)
|
||||
install_headers(clappergtk_headers,
|
||||
install_dir: clappergtk_headers_dir,
|
||||
)
|
||||
build_clappergtk = true
|
||||
|
||||
if build_gir
|
||||
clappergtk_gir = gnome.generate_gir(clappergtk_lib,
|
||||
sources: [
|
||||
clappergtk_sources,
|
||||
clappergtk_headers,
|
||||
clappergtk_enums,
|
||||
],
|
||||
extra_args: [
|
||||
gir_init_section,
|
||||
'--quiet',
|
||||
'--warn-all',
|
||||
'-DCLAPPER_GTK_COMPILATION',
|
||||
'-DGST_USE_UNSTABLE_API',
|
||||
],
|
||||
nsversion: version_array[0] + '.0',
|
||||
namespace: 'ClapperGtk',
|
||||
identifier_prefix: 'ClapperGtk',
|
||||
symbol_prefix: 'clapper_gtk',
|
||||
export_packages: clappergtk_api_name,
|
||||
install: true,
|
||||
includes: [
|
||||
clapper_gir[0],
|
||||
'Gst-1.0',
|
||||
'Gtk-4.0',
|
||||
'GLib-2.0',
|
||||
'GObject-2.0',
|
||||
],
|
||||
header: join_paths(meson.project_name() + '-gtk', 'clapper-gtk.h'),
|
||||
)
|
||||
endif
|
||||
|
||||
if build_vapi
|
||||
if not build_gir
|
||||
if get_option('vapi').enabled()
|
||||
error('Cannot build "vapi" without "introspection"')
|
||||
endif
|
||||
else
|
||||
gnome.generate_vapi(clappergtk_api_name,
|
||||
sources: clappergtk_gir[0],
|
||||
packages: clapper_pkg_reqs + [
|
||||
clapper_vapi,
|
||||
'gtk4',
|
||||
],
|
||||
install: true,
|
||||
)
|
||||
endif
|
||||
endif
|
||||
|
||||
pkgconfig.generate(clappergtk_lib,
|
||||
subdirs: [clappergtk_api_name],
|
||||
filebase: clappergtk_api_name,
|
||||
name: meson.project_name() + '-gtk',
|
||||
version: meson.project_version(),
|
||||
description: 'Clapper GTK integration library',
|
||||
requires: [
|
||||
clapper_lib,
|
||||
'gstreamer-1.0',
|
||||
'gtk4',
|
||||
'glib-2.0',
|
||||
'gobject-2.0',
|
||||
],
|
||||
)
|
||||
|
||||
clappergtk_dep = declare_dependency(
|
||||
link_with: clappergtk_lib,
|
||||
include_directories: clappergtk_conf_inc,
|
||||
dependencies: clappergtk_deps,
|
||||
sources: [
|
||||
clappergtk_version_header,
|
||||
clappergtk_enums[1],
|
||||
],
|
||||
)
|
1
src/lib/clapper-gtk/po/LINGUAS
Normal file
1
src/lib/clapper-gtk/po/LINGUAS
Normal file
@@ -0,0 +1 @@
|
||||
ar ast ca cs de es eu fa fi fr he hr hu it ja lt nl pl pt pt_BR ru sk sv tr zh_CN
|
5
src/lib/clapper-gtk/po/POTFILES
Normal file
5
src/lib/clapper-gtk/po/POTFILES
Normal file
@@ -0,0 +1,5 @@
|
||||
src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui
|
||||
|
||||
src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c
|
||||
src/lib/clapper-gtk/clapper-gtk-stream-check-button.c
|
||||
src/lib/clapper-gtk/clapper-gtk-title-label.c
|
65
src/lib/clapper-gtk/po/ar.po
Normal file
65
src/lib/clapper-gtk/po/ar.po
Normal file
@@ -0,0 +1,65 @@
|
||||
# Arabic translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: ar\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
65
src/lib/clapper-gtk/po/ast.po
Normal file
65
src/lib/clapper-gtk/po/ast.po
Normal file
@@ -0,0 +1,65 @@
|
||||
# Asturian translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: ast\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/ca.po
Normal file
66
src/lib/clapper-gtk/po/ca.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# Catalan translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: ca\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/clapper-gtk.pot
Normal file
66
src/lib/clapper-gtk/po/clapper-gtk.pot
Normal file
@@ -0,0 +1,66 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/cs.po
Normal file
66
src/lib/clapper-gtk/po/cs.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# Czech translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: cs\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/de.po
Normal file
66
src/lib/clapper-gtk/po/de.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# German translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/es.po
Normal file
66
src/lib/clapper-gtk/po/es.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# Spanish translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
65
src/lib/clapper-gtk/po/eu.po
Normal file
65
src/lib/clapper-gtk/po/eu.po
Normal file
@@ -0,0 +1,65 @@
|
||||
# Basque translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: eu\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
65
src/lib/clapper-gtk/po/fa.po
Normal file
65
src/lib/clapper-gtk/po/fa.po
Normal file
@@ -0,0 +1,65 @@
|
||||
# Persian translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: fa\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/fi.po
Normal file
66
src/lib/clapper-gtk/po/fi.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# Finnish translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: fi\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/fr.po
Normal file
66
src/lib/clapper-gtk/po/fr.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# French translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/he.po
Normal file
66
src/lib/clapper-gtk/po/he.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# Hebrew translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: he\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
67
src/lib/clapper-gtk/po/hr.po
Normal file
67
src/lib/clapper-gtk/po/hr.po
Normal file
@@ -0,0 +1,67 @@
|
||||
# Croatian translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: hr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/hu.po
Normal file
66
src/lib/clapper-gtk/po/hu.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# Hungarian translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: hu\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/it.po
Normal file
66
src/lib/clapper-gtk/po/it.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# Italian translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/ja.po
Normal file
66
src/lib/clapper-gtk/po/ja.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# Japanese translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: ja\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
67
src/lib/clapper-gtk/po/lt.po
Normal file
67
src/lib/clapper-gtk/po/lt.po
Normal file
@@ -0,0 +1,67 @@
|
||||
# Lithuanian translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: lt\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"(n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
1
src/lib/clapper-gtk/po/meson.build
Normal file
1
src/lib/clapper-gtk/po/meson.build
Normal file
@@ -0,0 +1 @@
|
||||
i18n.gettext(meson.project_name() + '-gtk', preset: 'glib')
|
66
src/lib/clapper-gtk/po/nl.po
Normal file
66
src/lib/clapper-gtk/po/nl.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# Dutch translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: nl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
67
src/lib/clapper-gtk/po/pl.po
Normal file
67
src/lib/clapper-gtk/po/pl.po
Normal file
@@ -0,0 +1,67 @@
|
||||
# Polish translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
||||
"|| n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/pt.po
Normal file
66
src/lib/clapper-gtk/po/pt.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# Portuguese translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: pt\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
67
src/lib/clapper-gtk/po/pt_BR.po
Normal file
67
src/lib/clapper-gtk/po/pt_BR.po
Normal file
@@ -0,0 +1,67 @@
|
||||
# Portuguese translations for clapper-gtk package
|
||||
# Tradu<64><75>es em portugu<67>s brasileiro para o pacote clapper-gtk.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: pt_BR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
67
src/lib/clapper-gtk/po/ru.po
Normal file
67
src/lib/clapper-gtk/po/ru.po
Normal file
@@ -0,0 +1,67 @@
|
||||
# Russian translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/sk.po
Normal file
66
src/lib/clapper-gtk/po/sk.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# Slovak translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: sk\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/sv.po
Normal file
66
src/lib/clapper-gtk/po/sv.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# Swedish translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: sv\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/tr.po
Normal file
66
src/lib/clapper-gtk/po/tr.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# Turkish translations for clapper-gtk package.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: tr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
66
src/lib/clapper-gtk/po/zh_CN.po
Normal file
66
src/lib/clapper-gtk/po/zh_CN.po
Normal file
@@ -0,0 +1,66 @@
|
||||
# Chinese translations for clapper-gtk package
|
||||
# clapper-gtk <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>.
|
||||
# Copyright (C) 2024 THE clapper-gtk'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the clapper-gtk package.
|
||||
# Automatically generated, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper-gtk\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-05 20:50+0200\n"
|
||||
"PO-Revision-Date: 2024-03-07 20:49+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: zh_CN\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:9
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:227
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:17
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:228
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:25
|
||||
#: src/lib/clapper-gtk/clapper-gtk-extra-menu-button.c:229
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:28
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:32
|
||||
msgid "Open…"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:75
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui:119
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:126
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-stream-check-button.c:82
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:91
|
||||
msgid "No media"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/clapper-gtk/clapper-gtk-title-label.c:103
|
||||
msgid "Unknown title"
|
||||
msgstr ""
|
161
src/lib/clapper-gtk/ui/clapper-gtk-billboard.ui
Normal file
161
src/lib/clapper-gtk/ui/clapper-gtk-billboard.ui
Normal file
@@ -0,0 +1,161 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="clapper-gtk">
|
||||
<template class="ClapperGtkBillboard" parent="ClapperGtkContainer">
|
||||
<property name="halign">fill</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="height-target">422</property>
|
||||
<property name="adaptive-height">420</property>
|
||||
<property name="visible">false</property>
|
||||
<signal name="adapt" handler="adapt_cb"/>
|
||||
<child>
|
||||
<object class="GtkCenterBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="halign">fill</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">true</property>
|
||||
<child type="start">
|
||||
<object class="GtkRevealer" id="side_revealer">
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="transition-type">crossfade</property>
|
||||
<property name="transition-duration">500</property>
|
||||
<property name="visible">false</property>
|
||||
<signal name="notify::child-revealed" handler="revealer_revealed_cb"/>
|
||||
<child>
|
||||
<object class="ClapperGtkLeadContainer">
|
||||
<property name="blocked-actions">toggle-play</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="halign">start</property>
|
||||
<style>
|
||||
<class name="osd"/>
|
||||
<class name="sidebox"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkRevealer" id="progress_revealer">
|
||||
<property name="halign">fill</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="transition-type">slide-up</property>
|
||||
<property name="transition-duration">200</property>
|
||||
<property name="reveal-child">true</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="progress_box">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">fill</property>
|
||||
<property name="spacing">4</property>
|
||||
<style>
|
||||
<class name="progressbox"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkProgressBar" id="top_progress">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">fill</property>
|
||||
<property name="vexpand">true</property>
|
||||
<property name="inverted">true</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkProgressBar" id="bottom_progress">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">fill</property>
|
||||
<property name="vexpand">true</property>
|
||||
<property name="inverted">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="progress_image">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRevealer">
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">fill</property>
|
||||
<property name="transition-type">slide-right</property>
|
||||
<property name="transition-duration" bind-source="progress_revealer" bind-property="transition-duration" bind-flags="sync-create"/>
|
||||
<property name="reveal-child" bind-source="progress_revealer" bind-property="reveal-child" bind-flags="invert-boolean">false</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="progress_label">
|
||||
<property name="valign">center</property>
|
||||
<property name="label">100%</property>
|
||||
<style>
|
||||
<class name="numeric"/>
|
||||
<class name="progresslabel"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="center">
|
||||
<object class="GtkRevealer" id="message_revealer">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="transition-type">crossfade</property>
|
||||
<property name="transition-duration">500</property>
|
||||
<signal name="notify::child-revealed" handler="revealer_revealed_cb"/>
|
||||
<child>
|
||||
<object class="ClapperGtkContainer">
|
||||
<property name="width-target">280</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="spacing">8</property>
|
||||
<style>
|
||||
<class name="osd"/>
|
||||
<class name="rounded"/>
|
||||
<class name="messagebox"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkImage" id="message_image">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="message_label">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="justify">center</property>
|
||||
<property name="wrap">true</property>
|
||||
<property name="wrap-mode">word-char</property>
|
||||
<property name="natural-wrap-mode">word</property>
|
||||
<style>
|
||||
<class name="heading"/>
|
||||
<class name="numeric"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
254
src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui
Normal file
254
src/lib/clapper-gtk/ui/clapper-gtk-extra-menu-button.ui
Normal file
@@ -0,0 +1,254 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="clapper-gtk">
|
||||
<menu id="extra-menu">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="custom">top-box</attribute>
|
||||
</item>
|
||||
<submenu>
|
||||
<attribute name="label" translatable="yes">Video</attribute>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="custom">video-streams</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</submenu>
|
||||
<submenu>
|
||||
<attribute name="label" translatable="yes">Audio</attribute>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="custom">audio-streams</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</submenu>
|
||||
<submenu>
|
||||
<attribute name="label" translatable="yes">Subtitles</attribute>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Enabled</attribute>
|
||||
<attribute name="action">clappergtk.subtitle-stream-enabled</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Open…</attribute>
|
||||
<attribute name="action">clappergtk.open-subtitle-stream</attribute>
|
||||
<attribute name="hidden-when">action-disabled</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="custom">subtitle-streams</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</submenu>
|
||||
</section>
|
||||
</menu>
|
||||
<template class="ClapperGtkExtraMenuButton" parent="GtkWidget">
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="menu_button">
|
||||
<property name="direction">up</property>
|
||||
<property name="icon-name">view-more-symbolic</property>
|
||||
<property name="popover">
|
||||
<object class="GtkPopoverMenu">
|
||||
<property name="menu-model">extra-menu</property>
|
||||
<signal name="map" handler="popover_map_cb"/>
|
||||
<signal name="unmap" handler="popover_unmap_cb"/>
|
||||
<signal name="notify::visible-submenu" handler="visible_submenu_changed_cb"/>
|
||||
<child type="top-box">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="volume_box">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="halign">fill</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="volume_button">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="icon-name">audio-volume-high-symbolic</property>
|
||||
<property name="action-name">video.toggle-mute</property>
|
||||
<property name="tooltip-text" translatable="yes">Mute</property>
|
||||
<style>
|
||||
<class name="circular"/>
|
||||
<class name="flat"/>
|
||||
<class name="spinsidebutton"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="volume_spin">
|
||||
<property name="halign">fill</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="width-chars">5</property>
|
||||
<property name="adjustment">
|
||||
<object class="GtkAdjustment">
|
||||
<property name="lower">0.0</property>
|
||||
<property name="upper">2.0</property>
|
||||
<property name="value">1.0</property>
|
||||
<property name="page-increment">0</property>
|
||||
<property name="step-increment">0.02</property>
|
||||
</object>
|
||||
</property>
|
||||
<signal name="input" handler="volume_spin_input_cb"/>
|
||||
<signal name="output" handler="volume_spin_output_cb"/>
|
||||
<signal name="value-changed" handler="volume_spin_changed_cb"/>
|
||||
<style>
|
||||
<class name="numeric"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="speed_box">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="halign">fill</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="speed_button">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="icon-name">power-profile-balanced-symbolic</property>
|
||||
<property name="action-name">video.set-speed</property>
|
||||
<property name="action-target">1.0</property>
|
||||
<property name="tooltip-text" translatable="yes">Reset</property>
|
||||
<style>
|
||||
<class name="circular"/>
|
||||
<class name="flat"/>
|
||||
<class name="spinsidebutton"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="speed_spin">
|
||||
<property name="halign">fill</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="width-chars">5</property>
|
||||
<property name="adjustment">
|
||||
<object class="GtkAdjustment">
|
||||
<property name="lower">0.05</property>
|
||||
<property name="upper">2.0</property>
|
||||
<property name="value">1.0</property>
|
||||
<property name="page-increment">0</property>
|
||||
<property name="step-increment">0.05</property>
|
||||
</object>
|
||||
</property>
|
||||
<signal name="input" handler="speed_spin_input_cb"/>
|
||||
<signal name="output" handler="speed_spin_output_cb"/>
|
||||
<signal name="value-changed" handler="speed_spin_changed_cb"/>
|
||||
<style>
|
||||
<class name="numeric"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator" id="top_separator">
|
||||
<property name="orientation">horizontal</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="video-streams">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="orientation">horizontal</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="video_sw">
|
||||
<property name="css-name">clapper-gtk-menu-scrolled-window</property>
|
||||
<property name="hscrollbar-policy">automatic</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<property name="propagate-natural-width">false</property>
|
||||
<property name="propagate-natural-height">true</property>
|
||||
<property name="max-content-width">320</property>
|
||||
<property name="max-content-height">192</property>
|
||||
<child>
|
||||
<object class="GtkListView" id="video_list_view">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="enable-rubberband">false</property>
|
||||
<property name="single-click-activate">false</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="resource">/com/github/rafostar/Clapper/clapper-gtk/ui/clapper-gtk-stream-list-item.ui</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="audio-streams">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="orientation">horizontal</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="audio_sw">
|
||||
<property name="css-name">clapper-gtk-menu-scrolled-window</property>
|
||||
<property name="hscrollbar-policy">automatic</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<property name="propagate-natural-width">false</property>
|
||||
<property name="propagate-natural-height">true</property>
|
||||
<property name="max-content-width">320</property>
|
||||
<property name="max-content-height">192</property>
|
||||
<child>
|
||||
<object class="GtkListView" id="audio_list_view">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="enable-rubberband">false</property>
|
||||
<property name="single-click-activate">false</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="resource">/com/github/rafostar/Clapper/clapper-gtk/ui/clapper-gtk-stream-list-item.ui</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="subtitle-streams">
|
||||
<object class="GtkScrolledWindow" id="subtitle_sw">
|
||||
<property name="css-name">clapper-gtk-menu-scrolled-window</property>
|
||||
<property name="hscrollbar-policy">automatic</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<property name="propagate-natural-width">false</property>
|
||||
<property name="propagate-natural-height">true</property>
|
||||
<property name="max-content-width">320</property>
|
||||
<property name="max-content-height">192</property>
|
||||
<child>
|
||||
<object class="GtkListView" id="subtitle_list_view">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="enable-rubberband">false</property>
|
||||
<property name="single-click-activate">false</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="resource">/com/github/rafostar/Clapper/clapper-gtk/ui/clapper-gtk-stream-list-item.ui</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
83
src/lib/clapper-gtk/ui/clapper-gtk-seek-bar.ui
Normal file
83
src/lib/clapper-gtk/ui/clapper-gtk-seek-bar.ui
Normal file
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="clapper-gtk">
|
||||
<template class="ClapperGtkSeekBar" parent="GtkWidget">
|
||||
<property name="hexpand">true</property>
|
||||
<child>
|
||||
<object class="GtkRevealer" id="position_revealer">
|
||||
<property name="halign">end</property>
|
||||
<property name="transition-type">slide-left</property>
|
||||
<property name="transition-duration">800</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="position_label">
|
||||
<property name="valign">center</property>
|
||||
<property name="label">00:00</property>
|
||||
<style>
|
||||
<class name="numeric"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScale" id="scale">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="halign">fill</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="focusable">false</property>
|
||||
<property name="draw-value">false</property>
|
||||
<property name="adjustment">position_adjustment</property>
|
||||
<signal name="value-changed" handler="scale_value_changed_cb"/>
|
||||
<signal name="notify::css-classes" handler="scale_css_classes_changed_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPopover" id="popover">
|
||||
<property name="position">top</property>
|
||||
<property name="autohide">false</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="popover_label">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRevealer" id="duration_revealer">
|
||||
<property name="halign">start</property>
|
||||
<property name="transition-type">slide-right</property>
|
||||
<property name="transition-duration">800</property>
|
||||
<property name="reveal-child" bind-source="position_revealer" bind-property="reveal-child" bind-flags="sync-create"/>
|
||||
<child>
|
||||
<object class="GtkLabel" id="duration_label">
|
||||
<property name="valign">center</property>
|
||||
<property name="label">00:00</property>
|
||||
<style>
|
||||
<class name="numeric"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventControllerMotion">
|
||||
<signal name="motion" handler="motion_cb"/>
|
||||
<signal name="leave" handler="motion_leave_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGestureClick">
|
||||
<property name="propagation-phase">capture</property>
|
||||
<property name="touch-only">true</property>
|
||||
<signal name="released" handler="touch_released_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
<object class="GtkAdjustment" id="position_adjustment">
|
||||
<property name="lower">0</property>
|
||||
<property name="upper">0</property>
|
||||
<property name="value">0</property>
|
||||
<property name="page-increment">0</property>
|
||||
<property name="step-increment">8</property>
|
||||
</object>
|
||||
</interface>
|
137
src/lib/clapper-gtk/ui/clapper-gtk-simple-controls.ui
Normal file
137
src/lib/clapper-gtk/ui/clapper-gtk-simple-controls.ui
Normal file
@@ -0,0 +1,137 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="clapper-gtk">
|
||||
<template class="ClapperGtkSimpleControls" parent="ClapperGtkContainer">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="adaptive-width">560</property>
|
||||
<signal name="adapt" handler="initial_adapt_cb"/>
|
||||
<child>
|
||||
<object class="ClapperGtkContainer">
|
||||
<property name="adaptive-width">400</property>
|
||||
<signal name="adapt" handler="full_adapt_cb"/>
|
||||
<child>
|
||||
<object class="GtkCenterBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">end</property>
|
||||
<style>
|
||||
<class name="centerbox"/>
|
||||
</style>
|
||||
<child type="center">
|
||||
<object class="ClapperGtkContainer">
|
||||
<property name="width-target">944</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="halign">fill</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkRevealer" id="fullscreen_top_revealer">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="transition-type">crossfade</property>
|
||||
<property name="transition-duration">200</property>
|
||||
<property name="reveal-child" bind-source="controls_slide_revealer" bind-property="child-revealed" bind-flags="invert-boolean">false</property>
|
||||
<property name="visible" bind-source="controls_slide_revealer" bind-property="reveal-child" bind-flags="invert-boolean">false</property>
|
||||
<child>
|
||||
<object class="ClapperGtkToggleFullscreenButton">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="visible" bind-source="ClapperGtkSimpleControls" bind-property="fullscreenable" bind-flags="sync-create"/>
|
||||
<style>
|
||||
<class name="osd"/>
|
||||
<class name="flat"/>
|
||||
<class name="circular"/>
|
||||
<class name="fullscreenbutton"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="ClapperGtkLeadContainer">
|
||||
<property name="blocked-actions">toggle-play|seek-request</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="halign">fill</property>
|
||||
<property name="valign">center</property>
|
||||
<style>
|
||||
<class name="osd"/>
|
||||
<class name="rounded"/>
|
||||
<class name="mainbox"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="ClapperGtkTogglePlayButton">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<style>
|
||||
<class name="flat"/>
|
||||
<class name="circular"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="ClapperGtkSeekBar" id="seek_bar">
|
||||
<property name="halign">fill</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="seek-method" bind-source="ClapperGtkSimpleControls" bind-property="seek-method" bind-flags="bidirectional"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="ClapperGtkExtraMenuButton" id="extra_menu_button">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<style>
|
||||
<class name="flat"/>
|
||||
<class name="circular"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkRevealer" id="controls_slide_revealer">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="transition-type">slide-left</property>
|
||||
<property name="transition-duration">400</property>
|
||||
<property name="reveal-child" bind-source="fullscreen_top_revealer" bind-property="child-revealed" bind-flags="invert-boolean">true</property>
|
||||
<property name="reveal-child" bind-source="fullscreen_bottom_revealer" bind-property="child-revealed" bind-flags="default"/>
|
||||
<signal name="notify::child-revealed" handler="controls_revealed_cb"/>
|
||||
<child>
|
||||
<object class="GtkRevealer" id="fullscreen_bottom_revealer">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="transition-type">crossfade</property>
|
||||
<property name="transition-duration">200</property>
|
||||
<property name="reveal-child" bind-source="controls_slide_revealer" bind-property="child-revealed" bind-flags="default">true</property>
|
||||
<child>
|
||||
<object class="ClapperGtkToggleFullscreenButton">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="visible" bind-source="ClapperGtkSimpleControls" bind-property="fullscreenable" bind-flags="sync-create"/>
|
||||
<style>
|
||||
<class name="osd"/>
|
||||
<class name="flat"/>
|
||||
<class name="circular"/>
|
||||
<class name="fullscreenbutton"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
45
src/lib/clapper-gtk/ui/clapper-gtk-status.ui
Normal file
45
src/lib/clapper-gtk/ui/clapper-gtk-status.ui
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="clapper-gtk">
|
||||
<template class="ClapperGtkStatus" parent="ClapperGtkContainer">
|
||||
<property name="width-target">562</property>
|
||||
<property name="height-target">402</property>
|
||||
<property name="adaptive-width">560</property>
|
||||
<property name="adaptive-height">400</property>
|
||||
<signal name="adapt" handler="adapt_cb"/>
|
||||
<child>
|
||||
<object class="GtkBox" id="status_box">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="title_label">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="justify">center</property>
|
||||
<property name="wrap">true</property>
|
||||
<style>
|
||||
<class name="title-1"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="description_label">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="justify">center</property>
|
||||
<property name="wrap">true</property>
|
||||
<style>
|
||||
<class name="body"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
15
src/lib/clapper-gtk/ui/clapper-gtk-stream-list-item.ui
Normal file
15
src/lib/clapper-gtk/ui/clapper-gtk-stream-list-item.ui
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="clapper-gtk">
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="ClapperGtkStreamCheckButton">
|
||||
<binding name="stream">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</binding>
|
||||
<binding name="active">
|
||||
<lookup name="selected">GtkListItem</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
22
src/lib/clapper-gtk/ui/clapper-gtk-title-header.ui
Normal file
22
src/lib/clapper-gtk/ui/clapper-gtk-title-header.ui
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="clapper-gtk">
|
||||
<template class="ClapperGtkTitleHeader" parent="ClapperGtkLeadContainer">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="blocked-actions">toggle-play|seek-request</property>
|
||||
<property name="width-target">640</property>
|
||||
<style>
|
||||
<class name="osd"/>
|
||||
<class name="rounded"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="ClapperGtkTitleLabel" id="label">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<style>
|
||||
<class name="heading"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
48
src/lib/clapper-gtk/ui/clapper-gtk-video.ui
Normal file
48
src/lib/clapper-gtk/ui/clapper-gtk-video.ui
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="clapper-gtk">
|
||||
<template class="ClapperGtkVideo" parent="GtkWidget">
|
||||
<child type="overlay">
|
||||
<object class="ClapperGtkStatus" id="status">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="visible">false</property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="overlay">
|
||||
<object class="ClapperGtkBufferingAnimation" id="buffering_animation">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="visible">false</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGestureClick" id="touch_gesture">
|
||||
<property name="propagation-phase">capture</property>
|
||||
<property name="touch-only">true</property>
|
||||
<signal name="pressed" handler="touch_pressed_cb"/>
|
||||
<signal name="released" handler="touch_released_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGestureClick" id="click_gesture">
|
||||
<property name="button">1</property>
|
||||
<signal name="pressed" handler="left_click_pressed_cb"/>
|
||||
<signal name="released" handler="left_click_released_cb"/>
|
||||
<signal name="stopped" handler="left_click_stopped_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventControllerMotion">
|
||||
<signal name="enter" handler="motion_enter_cb"/>
|
||||
<signal name="motion" handler="motion_cb"/>
|
||||
<signal name="leave" handler="motion_leave_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropControllerMotion">
|
||||
<signal name="motion" handler="drop_motion_cb"/>
|
||||
<signal name="leave" handler="drop_motion_leave_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
@@ -12,3 +12,4 @@ gir_init_section = '--add-init-section=extern void gst_init(gint*,gchar**);' + \
|
||||
|
||||
subdir('gst')
|
||||
subdir('clapper')
|
||||
subdir('clapper-gtk')
|
||||
|
Reference in New Issue
Block a user