39 Commits

Author SHA1 Message Date
Rafał Dzięgiel
08216528cf flatpak: GTK4 and libadwaita downgrade test 2023-01-08 16:14:42 +01:00
Rafał Dzięgiel
44db8c0d3b flatpak: Sync with Flathub 2023-01-07 18:55:01 +01:00
Rafał Dzięgiel
6c5753db53 Merge pull request #317 from Rafostar/gnome43
flatpak: Update to GNOME 43
2022-10-14 08:13:17 +02:00
Rafał Dzięgiel
a25bfa5418 flatpak: Update to GNOME 43
Update git actions builds to GNOME 43 runtime. #315
2022-10-13 20:54:26 +02:00
Rafał Dzięgiel
aaa3f6c4da Merge pull request #316 from Rafostar/nights
Update nightly Flatpak builds
2022-10-10 22:45:48 +02:00
Rafał Dzięgiel
845de1db8b flatpak-nightly: Only build GStreamer Rust plugins on x64
We are no longer able to build them on aarch64, as CI either runs out of memory or time limit
2022-10-10 18:06:32 +02:00
Rafał Dzięgiel
301e1f2ade flatpak-nightly: Skip compiling libadwaita
Nightly has now newer version, so we do not need to build it ourselves anymore
2022-10-09 20:17:56 +02:00
Rafał Dzięgiel
ff5091e7d3 flatpak-nightly: Update to llvm14 2022-10-09 15:00:22 +02:00
Rafał Dzięgiel
0d74fbb3e6 workflow: Update Flatpak nightly to 22.08 2022-10-09 14:22:19 +02:00
Rafał Dzięgiel
9d6ec43b0a Merge pull request #312 from jakedane/jakedane-patch-1
plugin: sink: Replace deprecated method
2022-09-28 22:10:40 +02:00
Jake Dane
cbc3061714 plugin: sink: Replace deprecated method
The method gtk_picture_set_keep_aspect_ratio is deprecated. As per the
warnings given when compiling clapper, it is replaced with
gtk_picture_set_content_fit with the same behavior as before.
2022-09-27 20:50:16 +02:00
Rafał Dzięgiel
d8b02824f3 Update gitattributes
The contents of extras and lib/plugin folders should not be marked as linguist-vendored since they include only my own code made for Clapper. Lets include them in git stats.
2022-09-07 13:15:34 +02:00
Rafał Dzięgiel
dd255dd337 New translations com.github.rafostar.Clapper.pot (Persian) (#305) 2022-09-03 20:40:35 +02:00
Rafał Dzięgiel
447c6f30d0 meson: Validate appstream file with "--nonet" arg
We do not need network connection to validate our appstream file.
Make it easier to run tests in containers that do not have network access.

Closes #307
2022-07-31 19:12:42 +02:00
Rafał Dzięgiel
afa06d4579 Merge pull request #299 from Rafostar/web-fix
api: Do not set default user-agent string
2022-07-25 10:23:27 +02:00
Rafał Dzięgiel
b04bf11c42 api: Do not set default user-agent string
Similarly as with other properties, we should aim to make this into user config option.
For the time being remove, as our outdated default user-agent seems to be breaking
few HLS streaming services.
2022-07-24 19:39:11 +02:00
Rafał Dzięgiel
939f75763d Merge pull request #302 from Rafostar/crowdin_sync
New Crowdin updates
2022-07-21 18:07:18 +02:00
Rafał Dzięgiel
d4c44049ca New translations com.github.rafostar.Clapper.pot (Chinese Simplified) 2022-07-18 10:48:44 +02:00
Rafał Dzięgiel
11c27eccaa Merge pull request #279 from Rafostar/fix-gl-caps
Make GL caps negotiation check what HW supports
2022-07-04 18:51:45 +02:00
Rafał Dzięgiel
823cb0a894 Update LINGUAS file 2022-07-04 18:20:40 +02:00
Rafał Dzięgiel
b27db1ac22 New Crowdin updates (#283)
* New translations com.github.rafostar.Clapper.pot (Persian)

* New translations com.github.rafostar.Clapper.pot (Turkish)

* New translations com.github.rafostar.Clapper.pot (Asturian)
2022-07-04 18:16:55 +02:00
Rafał Dzięgiel
564c6e7299 flatpak: Sync with Flathub 2022-07-04 12:30:27 +02:00
Rafał Dzięgiel
6f4632d940 New translations com.github.rafostar.Clapper.pot (German) (#282) 2022-06-24 20:23:50 +02:00
Rafał Dzięgiel
23bb253ca2 0.5.2 2022-06-24 10:05:02 +02:00
Rafał Dzięgiel
8ebf4e3b2f plugin: gluploader: Check for formats actually supported
Do not assume that HW can do every format that GLUpload/GLColorConvert can.
Check what video formats GL context actually supports and advertise that,
so a format that HW cannot do will never be picked up.
2022-06-16 15:41:44 +02:00
Rafał Dzięgiel
04a028d689 plugin: Rework code to use new GL context handler
Create a GL context handler subclass of recently added context handler base class and
rework code to use it. This simplifies a lot of things, like: switching of importers
at runtime, handling context queries, sharing data between importers, etc.
2022-06-16 15:41:30 +02:00
Rafał Dzięgiel
0920914b89 plugin: Add context handler base class
In order to bridge work with GL between GTK and GStreamer reliably, we need to create and
check context capabilities ahead of time. We also need to be able to query context at any
time during playback. Also we should avoid changing importers on context queries, this can
lead to all sort of problems.

To be able to achieve all of above, introduce new context handler base class that works
separately of importers.
2022-06-12 13:58:51 +02:00
Rafał Dzięgiel
2343e84a41 plugin: Use set_static_metadata in class init
Use static version of this function, so our static strings will not be copied
2022-06-06 21:04:17 +02:00
Rafał Dzięgiel
c288223321 Merge pull request #278 from Rafostar/flatpak-gvfs
flatpak: Add missing GVFS access permissions
2022-06-06 20:48:53 +02:00
Rafał Dzięgiel
2ba6645462 flatpak-nightly: Add missing GVFS access permissions
Needed to make GVFS mounted filesystems work with GVFS 1.48+.
See: https://docs.flatpak.org/en/latest/sandbox-permissions.html#gvfs-access
2022-06-06 09:32:12 +02:00
Rafał Dzięgiel
adcbb5d827 flatpak: Add missing GVFS access permissions
Needed to make GVFS mounted filesystems work with GVFS 1.48+.
See: https://docs.flatpak.org/en/latest/sandbox-permissions.html#gvfs-access
2022-06-06 09:31:55 +02:00
Rafał Dzięgiel
9885a2f424 Merge pull request #275 from Rafostar/smart-colon
Use U+003A colon character on RTL languages
2022-06-03 16:17:27 +02:00
Rafał Dzięgiel
66b2d8c7de plugin: Also use min GL version when auto selecting context
When we prefer GLES, make sure its no lower then 3.1 version, so it can color convert 10bit videos,
otherwise core GL 3.2 that GTK4 normally defaults to takes precedence.

With auto behavior we should select the best one, both performance and support wise.
Otherwise user can request one or another with GST_GL_API env that works best
with his specific HW.
2022-06-03 14:36:34 +02:00
Rafał Dzięgiel
2c5d65d0b3 flatpak: Sync with Flathub 2022-06-02 14:08:17 +02:00
Rafał Dzięgiel
e37f2a0a30 Use U+003A colon character on RTL languages
Unfortunately U+2236 seems to break time labels on RTL languages. Check text direction at startup and select best one that works.
2022-06-01 17:09:39 +02:00
Rafał Dzięgiel
387bc7a2f3 Update LINGUAS file 2022-06-01 16:44:05 +02:00
Rafał Dzięgiel
495a59a07a New Crowdin updates (#274)
* New translations com.github.rafostar.Clapper.pot (Hebrew)
2022-06-01 16:41:59 +02:00
Rafał Dzięgiel
e5723cd25a 0.5.1 2022-05-29 14:17:25 +02:00
Rafostar
e7808df7cc plugin: paintable: Fix widget size calculations on non-100% display scaling
Unlike legacy sink that used GLArea, GdkPaintable snapshots without pre-multiplying
sizes with scale factor. Remove scaling multiply of our widget dimensions,
so both video and widget width/height will be calculated correctly.

This fixes both image and black borders displaying issues on displays with
non-100% scaling applied.
2022-05-29 10:19:48 +02:00
48 changed files with 2262 additions and 1148 deletions

4
.gitattributes vendored
View File

@@ -1,5 +1,3 @@
extras/**/* linguist-vendored
lib/**/* linguist-vendored
lib/**/**/* linguist-vendored
lib/gst/clapper/* linguist-vendored
lib/gst/clapper/gstclapper-mpris* linguist-vendored=false
lib/gst/clapper/gtk4/* linguist-vendored=false

View File

@@ -29,8 +29,8 @@ jobs:
platforms: arm64
- name: Prepare Runtime
run: |
flatpak --system install -y --noninteractive flathub org.freedesktop.Sdk.Extension.rust-nightly/${{ matrix.arch }}/21.08
flatpak --system install -y --noninteractive flathub org.freedesktop.Sdk.Extension.llvm13/${{ matrix.arch }}/21.08
flatpak --system install -y --noninteractive flathub org.freedesktop.Sdk.Extension.rust-nightly/${{ matrix.arch }}/22.08
flatpak --system install -y --noninteractive flathub org.freedesktop.Sdk.Extension.llvm14/${{ matrix.arch }}/22.08
- uses: bilelmoussaoui/flatpak-github-actions/flatpak-builder@v4
name: Build
with:

View File

@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 600
container:
image: bilelmoussaoui/flatpak-github-actions:gnome-42
image: bilelmoussaoui/flatpak-github-actions:gnome-43
options: --privileged
strategy:
matrix:

View File

@@ -48,6 +48,27 @@
</screenshot>
</screenshots>
<releases>
<release version="0.5.2" date="2022-06-24">
<description>
<p>Fixes:</p>
<ul>
<li>Fix time labels display on RTL languages</li>
<li>Improved GL/GLES context automatic selection</li>
</ul>
<p>New translations:</p>
<ul>
<li>Hebrew</li>
</ul>
</description>
</release>
<release version="0.5.1" date="2022-05-29">
<description>
<p>
A quick hotfix release. Fixes problems with new video sink on displays with non-100% scaling applied.
See 0.5.0 version release notes for full recent changelog.
</p>
</description>
</release>
<release version="0.5.0" date="2022-05-28">
<description>
<p>Changes:</p>

View File

@@ -3,7 +3,7 @@ iconsdir = join_paths(datadir, 'icons', 'hicolor')
appstream_util = find_program('appstream-util', required: false)
if appstream_util.found()
test('Validate appstream file', appstream_util, args: [
'validate-relax',
'validate-relax', '--nonet',
join_paths(meson.current_source_dir(), 'com.github.rafostar.Clapper.metainfo.xml')
])
endif

View File

@@ -3166,26 +3166,16 @@ static void
element_setup_cb (GstElement * playbin, GstElement * element, GstClapper * self)
{
GstElementFactory *factory;
GParamSpec *prop;
factory = gst_element_get_factory (element);
if (factory) {
if ((factory = gst_element_get_factory (element))) {
gchar *plugin_name = gst_object_get_name (GST_OBJECT_CAST (factory));
if (plugin_name) {
GST_INFO_OBJECT (self, "Plugin setup: %s", plugin_name);
/* TODO: Set plugin props */
g_free (plugin_name);
}
g_free (plugin_name);
}
prop = g_object_class_find_property (G_OBJECT_GET_CLASS (element), "user-agent");
if (prop && prop->value_type == G_TYPE_STRING) {
const gchar *user_agent =
"Mozilla/5.0 (X11; Linux x86_64; rv:86.0) Gecko/20100101 Firefox/86.0";
GST_INFO_OBJECT (self, "Setting element user-agent: %s", user_agent);
g_object_set (element, "user-agent", user_agent, NULL);
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2022 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 Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gstclappercontexthandler.h"
#define parent_class gst_clapper_context_handler_parent_class
G_DEFINE_TYPE (GstClapperContextHandler, gst_clapper_context_handler, GST_TYPE_OBJECT);
static gboolean
_default_handle_context_query (GstClapperContextHandler *self,
GstBaseSink *bsink, GstQuery *query)
{
GST_FIXME_OBJECT (self, "Need to handle context query");
return FALSE;
}
static void
gst_clapper_context_handler_init (GstClapperContextHandler *self)
{
}
static void
gst_clapper_context_handler_finalize (GObject *object)
{
GstClapperContextHandler *self = GST_CLAPPER_CONTEXT_HANDLER_CAST (object);
GST_TRACE_OBJECT (self, "Finalize");
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
}
static void
gst_clapper_context_handler_class_init (GstClapperContextHandlerClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GstClapperContextHandlerClass *handler_class = (GstClapperContextHandlerClass *) klass;
gobject_class->finalize = gst_clapper_context_handler_finalize;
handler_class->handle_context_query = _default_handle_context_query;
}
gboolean
gst_clapper_context_handler_handle_context_query (GstClapperContextHandler *self,
GstBaseSink *bsink, GstQuery *query)
{
GstClapperContextHandlerClass *handler_class = GST_CLAPPER_CONTEXT_HANDLER_GET_CLASS (self);
return handler_class->handle_context_query (self, bsink, query);
}
GstClapperContextHandler *
gst_clapper_context_handler_obtain_with_type (GPtrArray *context_handlers, GType type)
{
guint i;
for (i = 0; i < context_handlers->len; i++) {
GstClapperContextHandler *handler = g_ptr_array_index (context_handlers, i);
if (G_TYPE_CHECK_INSTANCE_TYPE (handler, type))
return gst_object_ref (handler);
}
return NULL;
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2022 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 Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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 <gst/gst.h>
#include <gst/base/gstbasesink.h>
G_BEGIN_DECLS
#define GST_TYPE_CLAPPER_CONTEXT_HANDLER (gst_clapper_context_handler_get_type())
#define GST_IS_CLAPPER_CONTEXT_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CLAPPER_CONTEXT_HANDLER))
#define GST_IS_CLAPPER_CONTEXT_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CLAPPER_CONTEXT_HANDLER))
#define GST_CLAPPER_CONTEXT_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CLAPPER_CONTEXT_HANDLER, GstClapperContextHandlerClass))
#define GST_CLAPPER_CONTEXT_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CLAPPER_CONTEXT_HANDLER, GstClapperContextHandler))
#define GST_CLAPPER_CONTEXT_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CLAPPER_CONTEXT_HANDLER, GstClapperContextHandlerClass))
#define GST_CLAPPER_CONTEXT_HANDLER_CAST(obj) ((GstClapperContextHandler *)(obj))
typedef struct _GstClapperContextHandler GstClapperContextHandler;
typedef struct _GstClapperContextHandlerClass GstClapperContextHandlerClass;
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstClapperContextHandler, gst_object_unref)
#endif
struct _GstClapperContextHandler
{
GstObject parent;
};
struct _GstClapperContextHandlerClass
{
GstObjectClass parent_class;
gboolean (* handle_context_query) (GstClapperContextHandler *handler,
GstBaseSink *bsink,
GstQuery *query);
};
GType gst_clapper_context_handler_get_type (void);
gboolean gst_clapper_context_handler_handle_context_query (GstClapperContextHandler *handler, GstBaseSink *bsink, GstQuery *query);
GstClapperContextHandler * gst_clapper_context_handler_obtain_with_type (GPtrArray *context_handlers, GType type);
G_END_DECLS

View File

@@ -89,6 +89,14 @@ _default_create_pool (GstClapperImporter *self, GstStructure **config)
return NULL;
}
static void
_default_add_allocation_metas (GstClapperImporter *importer, GstQuery *query)
{
/* Importer base class handles GstVideoOverlayCompositionMeta */
gst_query_add_allocation_meta (query, GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL);
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
}
static GdkTexture *
_default_generate_texture (GstClapperImporter *self,
GstBuffer *buffer, GstVideoInfo *v_info)
@@ -144,6 +152,7 @@ gst_clapper_importer_class_init (GstClapperImporterClass *klass)
gobject_class->finalize = gst_clapper_importer_finalize;
importer_class->create_pool = _default_create_pool;
importer_class->add_allocation_metas = _default_add_allocation_metas;
importer_class->generate_texture = _default_generate_texture;
}
@@ -295,30 +304,6 @@ gst_clapper_importer_prepare_overlays_locked (GstClapperImporter *self)
GST_LOG_OBJECT (self, "Prepared overlays: %u", self->pending_overlays->len);
}
gboolean
gst_clapper_importer_prepare (GstClapperImporter *self)
{
GstClapperImporterClass *importer_class = GST_CLAPPER_IMPORTER_GET_CLASS (self);
if (importer_class->prepare) {
if (!importer_class->prepare (self))
return FALSE;
}
GST_DEBUG_OBJECT (self, "Importer prepared");
return TRUE;
}
void
gst_clapper_importer_share_data (GstClapperImporter *self, GstClapperImporter *dest)
{
GstClapperImporterClass *importer_class = GST_CLAPPER_IMPORTER_GET_CLASS (self);
if (importer_class->share_data)
importer_class->share_data (self, dest);
}
void
gst_clapper_importer_set_caps (GstClapperImporter *self, GstCaps *caps)
{
@@ -362,20 +347,7 @@ gst_clapper_importer_add_allocation_metas (GstClapperImporter *self, GstQuery *q
{
GstClapperImporterClass *importer_class = GST_CLAPPER_IMPORTER_GET_CLASS (self);
if (importer_class->add_allocation_metas)
importer_class->add_allocation_metas (self, query);
}
gboolean
gst_clapper_importer_handle_context_query (GstClapperImporter *self,
GstBaseSink *bsink, GstQuery *query)
{
GstClapperImporterClass *importer_class = GST_CLAPPER_IMPORTER_GET_CLASS (self);
if (!importer_class->handle_context_query)
return FALSE;
return importer_class->handle_context_query (self, bsink, query);
importer_class->add_allocation_metas (self, query);
}
void

View File

@@ -33,11 +33,11 @@ G_BEGIN_DECLS
#define GST_CLAPPER_IMPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CLAPPER_IMPORTER, GstClapperImporterClass))
#define GST_CLAPPER_IMPORTER_CAST(obj) ((GstClapperImporter *)(obj))
#define GST_CLAPPER_IMPORTER_DEFINE(camel,lower,type) \
G_DEFINE_TYPE (camel, lower, type) \
G_MODULE_EXPORT GstClapperImporter *make_importer (void); \
G_MODULE_EXPORT GstCaps *make_caps (gboolean is_template, \
GstRank *rank, GStrv *context_types);
#define GST_CLAPPER_IMPORTER_DEFINE(camel,lower,type) \
G_DEFINE_TYPE (camel, lower, type) \
G_MODULE_EXPORT GstClapperImporter *make_importer (GPtrArray *context_handlers); \
G_MODULE_EXPORT GstCaps *make_caps (gboolean is_template, \
GstRank *rank, GPtrArray *context_handlers);
typedef struct _GstClapperImporter GstClapperImporter;
typedef struct _GstClapperImporterClass GstClapperImporterClass;
@@ -65,18 +65,9 @@ struct _GstClapperImporterClass
{
GstObjectClass parent_class;
gboolean (* prepare) (GstClapperImporter *importer);
void (* share_data) (GstClapperImporter *src,
GstClapperImporter *dest);
void (* set_caps) (GstClapperImporter *importer,
GstCaps *caps);
gboolean (* handle_context_query) (GstClapperImporter *importer,
GstBaseSink *bsink,
GstQuery *query);
GstBufferPool * (* create_pool) (GstClapperImporter *importer,
GstStructure **config);
@@ -90,9 +81,6 @@ struct _GstClapperImporterClass
GType gst_clapper_importer_get_type (void);
gboolean gst_clapper_importer_prepare (GstClapperImporter *importer);
void gst_clapper_importer_share_data (GstClapperImporter *importer, GstClapperImporter *dest);
gboolean gst_clapper_importer_handle_context_query (GstClapperImporter *importer, GstBaseSink *bsink, GstQuery *query);
GstBufferPool * gst_clapper_importer_create_pool (GstClapperImporter *importer, GstStructure **config);
void gst_clapper_importer_add_allocation_metas (GstClapperImporter *importer, GstQuery *query);

View File

@@ -25,6 +25,7 @@
#include "gstclapperimporterloader.h"
#include "gstclapperimporter.h"
#include "gstclappercontexthandler.h"
#define GST_CAT_DEFAULT gst_clapper_importer_loader_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
@@ -32,15 +33,14 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define parent_class gst_clapper_importer_loader_parent_class
G_DEFINE_TYPE (GstClapperImporterLoader, gst_clapper_importer_loader, GST_TYPE_OBJECT);
typedef GstClapperImporter* (* MakeImporter) (void);
typedef GstCaps* (* MakeCaps) (gboolean is_template, GstRank *rank, GStrv *context_types);
typedef GstClapperImporter* (* MakeImporter) (GPtrArray *context_handlers);
typedef GstCaps* (* MakeCaps) (gboolean is_template, GstRank *rank, GPtrArray *context_handlers);
typedef struct
{
GModule *module;
GstCaps *caps;
GstRank rank;
GStrv context_types;
} GstClapperImporterData;
static void
@@ -49,16 +49,17 @@ gst_clapper_importer_data_free (GstClapperImporterData *data)
GST_TRACE ("Freeing importer data: %" GST_PTR_FORMAT, data);
gst_clear_caps (&data->caps);
g_strfreev (data->context_types);
g_free (data);
}
static GstClapperImporterData *
_obtain_importer_data (GModule *module, gboolean is_template)
_obtain_importer_data (GModule *module, gboolean is_template, GPtrArray *context_handlers)
{
MakeCaps make_caps;
GstClapperImporterData *data;
GST_DEBUG ("Found importer: %s", g_module_name (module));
if (!g_module_symbol (module, "make_caps", (gpointer *) &make_caps)
|| make_caps == NULL) {
GST_WARNING ("Make caps function missing in importer");
@@ -67,26 +68,30 @@ _obtain_importer_data (GModule *module, gboolean is_template)
data = g_new0 (GstClapperImporterData, 1);
data->module = module;
data->caps = make_caps (is_template, &data->rank, &data->context_types);
data->caps = make_caps (is_template, &data->rank, context_handlers);
GST_TRACE ("Created importer data: %" GST_PTR_FORMAT, data);
if (G_UNLIKELY (!data->caps)) {
GST_ERROR ("Invalid importer without caps: %s",
g_module_name (data->module));
if (!is_template) {
GST_ERROR ("Invalid importer without caps: %s",
g_module_name (data->module));
} else {
/* When importer cannot be actually used, due to e.g. unsupported HW */
GST_DEBUG ("No actual caps returned from importer");
}
gst_clapper_importer_data_free (data);
return NULL;
}
GST_DEBUG ("Found importer: %s, caps: %" GST_PTR_FORMAT,
g_module_name (data->module), data->caps);
GST_DEBUG ("Importer caps: %" GST_PTR_FORMAT, data->caps);
return data;
}
static GstClapperImporter *
_obtain_importer_internal (GModule *module)
_obtain_importer_internal (GModule *module, GPtrArray *context_handlers)
{
MakeImporter make_importer;
GstClapperImporter *importer;
@@ -97,7 +102,7 @@ _obtain_importer_internal (GModule *module)
return NULL;
}
importer = make_importer ();
importer = make_importer (context_handlers);
GST_TRACE ("Created importer: %" GST_PTR_FORMAT, importer);
return importer;
@@ -183,13 +188,14 @@ _sort_importers_cb (gconstpointer a, gconstpointer b)
}
static GPtrArray *
_obtain_available_importers (gboolean is_template)
_obtain_importers (gboolean is_template, GPtrArray *context_handlers)
{
const GPtrArray *modules;
GPtrArray *importers;
guint i;
GST_DEBUG ("Checking available importers");
GST_DEBUG ("Checking %s importers",
(is_template) ? "available" : "usable");
modules = gst_clapper_importer_loader_get_available_modules ();
importers = g_ptr_array_new_with_free_func (
@@ -199,13 +205,14 @@ _obtain_available_importers (gboolean is_template)
GModule *module = g_ptr_array_index (modules, i);
GstClapperImporterData *data;
if ((data = _obtain_importer_data (module, is_template)))
if ((data = _obtain_importer_data (module, is_template, context_handlers)))
g_ptr_array_add (importers, data);
}
g_ptr_array_sort (importers, (GCompareFunc) _sort_importers_cb);
GST_DEBUG ("Found %i available importers", importers->len);
GST_DEBUG ("Found %i %s importers", importers->len,
(is_template) ? "available" : "usable");
return importers;
}
@@ -244,7 +251,7 @@ gst_clapper_importer_loader_make_sink_pad_template (void)
GST_DEBUG ("Making sink pad template");
importers = _obtain_available_importers (TRUE);
importers = _obtain_importers (TRUE, NULL);
caps = _make_caps_for_importers (importers);
g_ptr_array_unref (importers);
@@ -265,6 +272,22 @@ gst_clapper_importer_loader_make_actual_caps (GstClapperImporterLoader *self)
return _make_caps_for_importers (self->importers);
}
gboolean
gst_clapper_importer_loader_handle_context_query (GstClapperImporterLoader *self,
GstBaseSink *bsink, GstQuery *query)
{
guint i;
for (i = 0; i < self->context_handlers->len; i++) {
GstClapperContextHandler *handler = g_ptr_array_index (self->context_handlers, i);
if (gst_clapper_context_handler_handle_context_query (handler, bsink, query))
return TRUE;
}
return FALSE;
}
static const GstClapperImporterData *
_get_importer_data_for_caps (const GPtrArray *importers, const GstCaps *caps)
{
@@ -282,89 +305,41 @@ _get_importer_data_for_caps (const GPtrArray *importers, const GstCaps *caps)
return NULL;
}
static const GstClapperImporterData *
_get_importer_data_for_context_type (const GPtrArray *importers, const gchar *context_type)
{
guint i;
for (i = 0; i < importers->len; i++) {
GstClapperImporterData *data = g_ptr_array_index (importers, i);
guint j;
if (!data->context_types)
continue;
for (j = 0; data->context_types[j]; j++) {
if (strcmp (context_type, data->context_types[j]))
continue;
return data;
}
}
return NULL;
}
static gboolean
_find_importer_internal (GstClapperImporterLoader *self,
GstCaps *caps, GstQuery *query, GstClapperImporter **importer)
gboolean
gst_clapper_importer_loader_find_importer_for_caps (GstClapperImporterLoader *self,
GstCaps *caps, GstClapperImporter **importer)
{
const GstClapperImporterData *data = NULL;
GstClapperImporter *found_importer = NULL;
GST_OBJECT_LOCK (self);
if (caps) {
GST_DEBUG_OBJECT (self, "Requested importer for caps: %" GST_PTR_FORMAT, caps);
data = _get_importer_data_for_caps (self->importers, caps);
} else if (query) {
const gchar *context_type;
gst_query_parse_context_type (query, &context_type);
GST_DEBUG_OBJECT (self, "Requested importer for context: %s", context_type);
data = _get_importer_data_for_context_type (self->importers, context_type);
}
GST_DEBUG_OBJECT (self, "Requested importer for caps: %" GST_PTR_FORMAT, caps);
data = _get_importer_data_for_caps (self->importers, caps);
GST_LOG_OBJECT (self, "Old importer path: %s, new path: %s",
(self->last_module) ? g_module_name (self->last_module) : NULL,
(data) ? g_module_name (data->module) : NULL);
if (!data) {
/* In case of missing importer for context query, leave the old one.
* We should allow some queries to go through unresponded */
if (query)
GST_DEBUG_OBJECT (self, "No importer for query, leaving old one");
else
gst_clear_object (importer);
if (G_UNLIKELY (!data)) {
gst_clear_object (importer);
goto finish;
}
if (*importer && (self->last_module == data->module)) {
GST_DEBUG_OBJECT (self, "No importer change");
if (caps)
gst_clapper_importer_set_caps (*importer, caps);
gst_clapper_importer_set_caps (*importer, caps);
goto finish;
}
found_importer = _obtain_importer_internal (data->module);
if (*importer && found_importer)
gst_clapper_importer_share_data (*importer, found_importer);
found_importer = _obtain_importer_internal (data->module, self->context_handlers);
gst_clear_object (importer);
if (!found_importer || !gst_clapper_importer_prepare (found_importer)) {
gst_clear_object (&found_importer);
if (!found_importer)
goto finish;
}
if (caps)
gst_clapper_importer_set_caps (found_importer, caps);
gst_clapper_importer_set_caps (found_importer, caps);
*importer = found_importer;
@@ -378,33 +353,12 @@ finish:
return (*importer != NULL);
}
gboolean
gst_clapper_importer_loader_find_importer_for_caps (GstClapperImporterLoader *self,
GstCaps *caps, GstClapperImporter **importer)
{
return _find_importer_internal (self, caps, NULL, importer);
}
gboolean
gst_clapper_importer_loader_find_importer_for_context_query (GstClapperImporterLoader *self,
GstQuery *query, GstClapperImporter **importer)
{
return _find_importer_internal (self, NULL, query, importer);
}
static void
gst_clapper_importer_loader_init (GstClapperImporterLoader *self)
{
}
static void
gst_clapper_importer_loader_constructed (GObject *object)
{
GstClapperImporterLoader *self = GST_CLAPPER_IMPORTER_LOADER_CAST (object);
self->importers = _obtain_available_importers (FALSE);
GST_CALL_PARENT (G_OBJECT_CLASS, constructed, (object));
self->context_handlers = g_ptr_array_new_with_free_func (
(GDestroyNotify) gst_object_unref);
self->importers = _obtain_importers (FALSE, self->context_handlers);
}
static void
@@ -414,7 +368,10 @@ gst_clapper_importer_loader_finalize (GObject *object)
GST_TRACE ("Finalize");
g_ptr_array_unref (self->importers);
if (self->importers)
g_ptr_array_unref (self->importers);
g_ptr_array_unref (self->context_handlers);
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
}
@@ -424,6 +381,5 @@ gst_clapper_importer_loader_class_init (GstClapperImporterLoaderClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
gobject_class->constructed = gst_clapper_importer_loader_constructed;
gobject_class->finalize = gst_clapper_importer_loader_finalize;
}

View File

@@ -20,6 +20,7 @@
#pragma once
#include <gst/gst.h>
#include <gst/base/gstbasesink.h>
#include "gstclapperimporter.h"
@@ -35,7 +36,9 @@ struct _GstClapperImporterLoader
GstObject parent;
GModule *last_module;
GPtrArray *importers;
GPtrArray *context_handlers;
};
GstClapperImporterLoader * gst_clapper_importer_loader_new (void);
@@ -44,8 +47,8 @@ GstPadTemplate * gst_clapper_importer_loader_make_sink_pad_template
GstCaps * gst_clapper_importer_loader_make_actual_caps (GstClapperImporterLoader *loader);
gboolean gst_clapper_importer_loader_handle_context_query (GstClapperImporterLoader *loader, GstBaseSink *bsink, GstQuery *query);
gboolean gst_clapper_importer_loader_find_importer_for_caps (GstClapperImporterLoader *loader, GstCaps *caps, GstClapperImporter **importer);
gboolean gst_clapper_importer_loader_find_importer_for_context_query (GstClapperImporterLoader *loader, GstQuery *query, GstClapperImporter **importer);
G_END_DECLS

View File

@@ -376,11 +376,8 @@ gst_clapper_paintable_snapshot (GdkPaintable *paintable,
gint widget_width = 0, widget_height = 0;
if ((widget = g_weak_ref_get (&self->widget))) {
gint scale_factor;
scale_factor = gtk_widget_get_scale_factor (widget);
widget_width = gtk_widget_get_width (widget) * scale_factor;
widget_height = gtk_widget_get_height (widget) * scale_factor;
widget_width = gtk_widget_get_width (widget);
widget_height = gtk_widget_get_height (widget);
g_object_unref (widget);
}

View File

@@ -279,8 +279,15 @@ gst_clapper_sink_get_widget (GstClapperSink *self)
gst_clapper_paintable_set_widget (self->paintable, self->widget);
/* Set earlier remembered property */
#if GTK_CHECK_VERSION(4,8,0)
if (self->force_aspect_ratio)
gtk_picture_set_content_fit (GTK_PICTURE (self->widget), GTK_CONTENT_FIT_CONTAIN);
else
gtk_picture_set_content_fit (GTK_PICTURE (self->widget), GTK_CONTENT_FIT_FILL);
#else
gtk_picture_set_keep_aspect_ratio (GTK_PICTURE (self->widget),
self->force_aspect_ratio);
#endif
gtk_picture_set_paintable (GTK_PICTURE (self->widget), GDK_PAINTABLE (self->paintable));
@@ -358,8 +365,15 @@ gst_clapper_sink_set_property (GObject *object, guint prop_id,
self->force_aspect_ratio = g_value_get_boolean (value);
if (self->widget) {
#if GTK_CHECK_VERSION(4,8,0)
if (self->force_aspect_ratio)
gtk_picture_set_content_fit (GTK_PICTURE (self->widget), GTK_CONTENT_FIT_CONTAIN);
else
gtk_picture_set_content_fit (GTK_PICTURE (self->widget), GTK_CONTENT_FIT_FILL);
#else
gtk_picture_set_keep_aspect_ratio (GTK_PICTURE (self->widget),
self->force_aspect_ratio);
#endif
}
break;
case PROP_PIXEL_ASPECT_RATIO:
@@ -480,25 +494,12 @@ gst_clapper_sink_query (GstBaseSink *bsink, GstQuery *query)
GstClapperSink *self = GST_CLAPPER_SINK_CAST (bsink);
gboolean res = FALSE;
GST_CLAPPER_SINK_LOCK (self);
if (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT) {
gboolean is_inactive;
GST_OBJECT_LOCK (self);
is_inactive = (GST_STATE (self) < GST_STATE_PAUSED);
GST_OBJECT_UNLOCK (self);
/* Some random context query in the middle of playback
* should not trigger importer replacement */
if (is_inactive)
gst_clapper_importer_loader_find_importer_for_context_query (self->loader, query, &self->importer);
if (self->importer)
res = gst_clapper_importer_handle_context_query (self->importer, bsink, query);
GST_CLAPPER_SINK_LOCK (self);
res = gst_clapper_importer_loader_handle_context_query (self->loader, bsink, query);
GST_CLAPPER_SINK_UNLOCK (self);
}
GST_CLAPPER_SINK_UNLOCK (self);
if (res)
return TRUE;
@@ -890,7 +891,7 @@ gst_clapper_sink_class_init (GstClapperSinkClass *klass)
gstvideosink_class->set_info = gst_clapper_sink_set_info;
gstvideosink_class->show_frame = gst_clapper_sink_show_frame;
gst_element_class_set_metadata (gstelement_class,
gst_element_class_set_static_metadata (gstelement_class,
"Clapper video sink",
"Sink/Video", "A GTK4 video sink used by Clapper media player",
"Rafał Dzięgiel <rafostar.github@gmail.com>");

View File

@@ -21,43 +21,41 @@
#include "config.h"
#endif
#include "gstclapperglbaseimporter.h"
#include "gstclapperglcontexthandler.h"
#include "gst/plugin/gstgdkformats.h"
#include "gst/plugin/gstgtkutils.h"
#include <gst/gl/gstglfuncs.h>
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WAYLAND
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WAYLAND
#include <gdk/wayland/gdkwayland.h>
#include <gst/gl/wayland/gstgldisplay_wayland.h>
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11
#include <gdk/x11/gdkx.h>
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_GLX
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_GLX
#include <gst/gl/x11/gstgldisplay_x11.h>
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_EGL || GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_EGL
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_EGL || GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_EGL
#include <gst/gl/egl/gstgldisplay_egl.h>
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32
#include <gdk/win32/gdkwin32.h>
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_MACOS
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_MACOS
#include <gdk/macos/gdkmacos.h>
#endif
#define GST_CAT_DEFAULT gst_clapper_gl_base_importer_debug
#define GST_CAT_DEFAULT gst_clapper_gl_context_handler_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define parent_class gst_clapper_gl_base_importer_parent_class
G_DEFINE_TYPE (GstClapperGLBaseImporter, gst_clapper_gl_base_importer, GST_TYPE_CLAPPER_IMPORTER);
#define parent_class gst_clapper_gl_context_handler_parent_class
G_DEFINE_TYPE (GstClapperGLContextHandler, gst_clapper_gl_context_handler, GST_TYPE_OBJECT);
static GstGLContext *
wrap_current_gl (GstGLDisplay *display, GdkGLAPI gdk_gl_api, GstGLPlatform platform)
_wrap_current_gl (GstGLDisplay *display, GdkGLAPI gdk_gl_api, GstGLPlatform platform)
{
GstGLAPI gst_gl_api = GST_GL_API_NONE;
@@ -86,380 +84,19 @@ wrap_current_gl (GstGLDisplay *display, GdkGLAPI gdk_gl_api, GstGLPlatform platf
}
static gboolean
retrieve_gl_context_on_main (GstClapperGLBaseImporter *self)
{
GstClapperGLBaseImporterClass *gl_bi_class = GST_CLAPPER_GL_BASE_IMPORTER_GET_CLASS (self);
GdkDisplay *gdk_display;
GdkGLContext *gdk_context;
GError *error = NULL;
GdkGLAPI gdk_gl_api;
GstGLPlatform platform = GST_GL_PLATFORM_NONE;
gint gl_major = 0, gl_minor = 0;
if (!gtk_init_check ()) {
GST_ERROR_OBJECT (self, "Could not ensure GTK initialization");
return FALSE;
}
/* Make sure we are clean here, otherwise data sharing
* between GL-based importers may lead to leaks */
gst_clear_object (&self->wrapped_context);
g_clear_object (&self->gdk_context);
gst_clear_object (&self->gst_display);
gdk_display = gdk_display_get_default ();
if (G_UNLIKELY (!gdk_display)) {
GST_ERROR_OBJECT (self, "Could not retrieve Gdk display");
return FALSE;
}
if (!(gdk_context = gdk_display_create_gl_context (gdk_display, &error))) {
GST_ERROR_OBJECT (self, "Error creating Gdk GL context: %s",
error ? error->message : "No error set by Gdk");
g_clear_error (&error);
return FALSE;
}
if (!gl_bi_class->gdk_context_realize (self, gdk_context)) {
GST_ERROR_OBJECT (self, "Could not realize Gdk context: %" GST_PTR_FORMAT,
gdk_context);
g_object_unref (gdk_context);
return FALSE;
}
gdk_gl_api = gdk_gl_context_get_api (gdk_context);
GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self);
self->gdk_context = gdk_context;
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WAYLAND
if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) {
struct wl_display *wayland_display =
gdk_wayland_display_get_wl_display (gdk_display);
self->gst_display = (GstGLDisplay *)
gst_gl_display_wayland_new_with_display (wayland_display);
}
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11
if (GDK_IS_X11_DISPLAY (gdk_display)) {
gpointer display_ptr;
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_EGL
display_ptr = gdk_x11_display_get_egl_display (gdk_display);
if (display_ptr) {
self->gst_display = (GstGLDisplay *)
gst_gl_display_egl_new_with_egl_display (display_ptr);
}
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_GLX
if (!self->gst_display) {
display_ptr = gdk_x11_display_get_xdisplay (gdk_display);
self->gst_display = (GstGLDisplay *)
gst_gl_display_x11_new_with_display (display_ptr);
}
}
#endif
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32
if (GDK_IS_WIN32_DISPLAY (gdk_display)) {
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_EGL
gpointer display_ptr = gdk_win32_display_get_egl_display (gdk_display);
if (display_ptr) {
self->gst_display = (GstGLDisplay *)
gst_gl_display_egl_new_with_egl_display (display_ptr);
}
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_WGL
if (!self->gst_display) {
self->gst_display =
gst_gl_display_new_with_type (GST_GL_DISPLAY_TYPE_WIN32);
}
}
#endif
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_MACOS
if (GDK_IS_MACOS_DISPLAY (gdk_display)) {
self->gst_display =
gst_gl_display_new_with_type (GST_GL_DISPLAY_TYPE_COCOA);
}
#endif
/* Fallback to generic display */
if (G_UNLIKELY (!self->gst_display)) {
GST_WARNING_OBJECT (self, "Unknown Gdk display!");
self->gst_display = gst_gl_display_new ();
}
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WAYLAND
if (GST_IS_GL_DISPLAY_WAYLAND (self->gst_display)) {
platform = GST_GL_PLATFORM_EGL;
GST_INFO_OBJECT (self, "Using EGL on Wayland");
goto have_display;
}
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_EGL
if (GST_IS_GL_DISPLAY_EGL (self->gst_display)
&& GDK_IS_X11_DISPLAY (gdk_display)) {
platform = GST_GL_PLATFORM_EGL;
GST_INFO_OBJECT (self, "Using EGL on x11");
goto have_display;
}
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_GLX
if (GST_IS_GL_DISPLAY_X11 (self->gst_display)) {
platform = GST_GL_PLATFORM_GLX;
GST_INFO_OBJECT (self, "Using GLX on x11");
goto have_display;
}
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_EGL
if (GST_IS_GL_DISPLAY_EGL (self->gst_display)
&& GDK_IS_WIN32_DISPLAY (gdk_display)) {
platform = GST_GL_PLATFORM_EGL;
GST_INFO_OBJECT (self, "Using EGL on Win32");
goto have_display;
}
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_WGL
if (gst_gl_display_get_handle_type (self->gst_display) == GST_GL_DISPLAY_TYPE_WIN32) {
platform = GST_GL_PLATFORM_WGL;
GST_INFO_OBJECT (self, "Using WGL on Win32");
goto have_display;
}
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_MACOS
if (gst_gl_display_get_handle_type (self->gst_display) == GST_GL_DISPLAY_TYPE_COCOA) {
platform = GST_GL_PLATFORM_CGL;
GST_INFO_OBJECT (self, "Using CGL on macOS");
goto have_display;
}
#endif
g_clear_object (&self->gdk_context);
gst_clear_object (&self->gst_display);
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
GST_ERROR_OBJECT (self, "Unsupported GL platform");
return FALSE;
have_display:
gdk_gl_context_make_current (self->gdk_context);
self->wrapped_context = wrap_current_gl (self->gst_display, gdk_gl_api, platform);
if (!self->wrapped_context) {
GST_ERROR ("Could not retrieve Gdk OpenGL context");
gdk_gl_context_clear_current ();
g_clear_object (&self->gdk_context);
gst_clear_object (&self->gst_display);
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
return FALSE;
}
GST_INFO ("Retrieved Gdk OpenGL context %" GST_PTR_FORMAT, self->wrapped_context);
gst_gl_context_activate (self->wrapped_context, TRUE);
if (!gst_gl_context_fill_info (self->wrapped_context, &error)) {
GST_ERROR ("Failed to fill Gdk context info: %s", error->message);
g_clear_error (&error);
gst_gl_context_activate (self->wrapped_context, FALSE);
gst_clear_object (&self->wrapped_context);
g_clear_object (&self->gdk_context);
gst_clear_object (&self->gst_display);
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
return FALSE;
}
gst_gl_context_get_gl_version (self->wrapped_context, &gl_major, &gl_minor);
GST_INFO ("Using OpenGL%s %i.%i", (gdk_gl_api == GDK_GL_API_GLES) ? " ES" : "",
gl_major, gl_minor);
/* Deactivate in both places */
gst_gl_context_activate (self->wrapped_context, FALSE);
gdk_gl_context_clear_current ();
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
return TRUE;
}
static gboolean
retrieve_gst_context (GstClapperGLBaseImporter *self)
{
GstGLDisplay *gst_display = NULL;
GstGLContext *gst_context = NULL;
GError *error = NULL;
GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self);
gst_display = gst_object_ref (self->gst_display);
/* GstGLDisplay operations require display object lock to be held */
GST_OBJECT_LOCK (gst_display);
if (!self->gst_context) {
GST_TRACE_OBJECT (self, "Creating new GstGLContext");
if (!gst_gl_display_create_context (gst_display, self->wrapped_context,
&self->gst_context, &error)) {
GST_WARNING ("Could not create OpenGL context: %s",
error ? error->message : "Unknown");
g_clear_error (&error);
GST_OBJECT_UNLOCK (gst_display);
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
return FALSE;
}
}
gst_context = gst_object_ref (self->gst_context);
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
gst_gl_display_add_context (gst_display, gst_context);
GST_OBJECT_UNLOCK (gst_display);
gst_object_unref (gst_display);
gst_object_unref (gst_context);
return TRUE;
}
static gboolean
gst_clapper_gl_base_importer_prepare (GstClapperImporter *importer)
{
GstClapperGLBaseImporter *self = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer);
gboolean need_invoke;
GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self);
need_invoke = (!self->gdk_context || !self->gst_display || !self->wrapped_context);
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
if (need_invoke) {
if (!(! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback)
retrieve_gl_context_on_main, self)))
return FALSE;
}
if (!retrieve_gst_context (self))
return FALSE;
if (!GST_CLAPPER_IMPORTER_CLASS (parent_class)->prepare)
return TRUE;
return GST_CLAPPER_IMPORTER_CLASS (parent_class)->prepare (importer);
}
static void
gst_clapper_gl_base_importer_share_data (GstClapperImporter *importer, GstClapperImporter *dest_importer)
{
GstClapperGLBaseImporter *self = GST_CLAPPER_GL_BASE_IMPORTER (importer);
if (GST_IS_CLAPPER_GL_BASE_IMPORTER (dest_importer)) {
GstClapperGLBaseImporter *dest = GST_CLAPPER_GL_BASE_IMPORTER (dest_importer);
GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self);
GST_CLAPPER_GL_BASE_IMPORTER_LOCK (dest);
/* Successfully prepared GL importer should have all three */
if (self->gdk_context && self->gst_display && self->wrapped_context) {
g_clear_object (&dest->gdk_context);
dest->gdk_context = g_object_ref (self->gdk_context);
gst_clear_object (&dest->gst_display);
dest->gst_display = gst_object_ref (self->gst_display);
gst_clear_object (&dest->wrapped_context);
dest->wrapped_context = gst_object_ref (self->wrapped_context);
}
/* This context is not required, we can create it ourselves
* using gst_display and wrapped_context */
if (self->gst_context) {
gst_clear_object (&dest->gst_context);
dest->gst_context = gst_object_ref (self->gst_context);
}
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (dest);
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
}
if (GST_CLAPPER_IMPORTER_CLASS (parent_class)->share_data)
GST_CLAPPER_IMPORTER_CLASS (parent_class)->share_data (importer, dest_importer);
}
static gboolean
gst_clapper_gl_base_importer_handle_context_query (GstClapperImporter *importer,
GstBaseSink *bsink, GstQuery *query)
{
GstClapperGLBaseImporter *self = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer);
gboolean res;
GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self);
res = gst_gl_handle_context_query (GST_ELEMENT_CAST (bsink), query,
self->gst_display, self->gst_context, self->wrapped_context);
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
return res;
}
static GstBufferPool *
gst_clapper_gl_base_importer_create_pool (GstClapperImporter *importer, GstStructure **config)
{
GstClapperGLBaseImporter *self = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer);
GstBufferPool *pool;
GST_DEBUG_OBJECT (self, "Creating new GL buffer pool");
GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self);
pool = gst_gl_buffer_pool_new (self->gst_context);
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
*config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_add_option (*config, GST_BUFFER_POOL_OPTION_VIDEO_META);
gst_buffer_pool_config_add_option (*config, GST_BUFFER_POOL_OPTION_GL_SYNC_META);
return pool;
}
static void
gst_clapper_gl_base_importer_add_allocation_metas (GstClapperImporter *importer, GstQuery *query)
{
GstClapperGLBaseImporter *self = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer);
gst_query_add_allocation_meta (query, GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL);
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self);
if (self->gst_context->gl_vtable->FenceSync)
gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, NULL);
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
}
static gboolean
_realize_gdk_context_with_api (GdkGLContext *gdk_context, GdkGLAPI api)
_realize_gdk_context_with_api (GdkGLContext *gdk_context, GdkGLAPI api, gint maj, gint min)
{
GError *error = NULL;
gboolean success;
gdk_gl_context_set_allowed_apis (gdk_context, api);
gdk_gl_context_set_required_version (gdk_context, maj, min);
GST_DEBUG ("Trying to realize %s context, min ver: %i.%i",
(api & GDK_GL_API_GL) ? "GL" : "GLES", maj, min);
if (!(success = gdk_gl_context_realize (gdk_context, &error))) {
GST_WARNING ("Could not realize Gdk context with %s: %s",
GST_DEBUG ("Could not realize Gdk context with %s: %s",
(api & GDK_GL_API_GL) ? "GL" : "GLES", error->message);
g_clear_error (&error);
}
@@ -468,7 +105,7 @@ _realize_gdk_context_with_api (GdkGLContext *gdk_context, GdkGLAPI api)
}
static gboolean
gst_clapper_gl_base_importer_gdk_context_realize (GstClapperGLBaseImporter *self, GdkGLContext *gdk_context)
_gl_context_handler_context_realize (GstClapperGLContextHandler *self, GdkGLContext *gdk_context)
{
GdkGLAPI preferred_api = GDK_GL_API_GL;
GdkDisplay *gdk_display;
@@ -486,7 +123,7 @@ gst_clapper_gl_base_importer_gdk_context_realize (GstClapperGLBaseImporter *self
: GDK_GL_API_GL | GDK_GL_API_GLES;
/* With requested by user API, we either use it or give up */
return _realize_gdk_context_with_api (gdk_context, preferred_api);
return _realize_gdk_context_with_api (gdk_context, preferred_api, 0, 0);
}
gdk_display = gdk_gl_context_get_display (gdk_context);
@@ -496,15 +133,15 @@ gst_clapper_gl_base_importer_gdk_context_realize (GstClapperGLBaseImporter *self
/* Apple decoder uses rectangle texture-target, which GLES does not support.
* For Linux we prefer EGL + GLES in order to get direct HW colorspace conversion.
* Windows will try EGL + GLES setup first and auto fallback to WGL. */
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WAYLAND
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WAYLAND
if (GDK_IS_WAYLAND_DISPLAY (gdk_display))
preferred_api = GDK_GL_API_GLES;
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_EGL
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_EGL
if (GDK_IS_X11_DISPLAY (gdk_display) && gdk_x11_display_get_egl_display (gdk_display))
preferred_api = GDK_GL_API_GLES;
#endif
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_EGL
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_EGL
if (GDK_IS_WIN32_DISPLAY (gdk_display) && gdk_win32_display_get_egl_display (gdk_display))
preferred_api = GDK_GL_API_GLES;
#endif
@@ -513,34 +150,318 @@ gst_clapper_gl_base_importer_gdk_context_realize (GstClapperGLBaseImporter *self
* "scrambled" image on Linux with Intel GPUs that are mostly used together with
* x86 CPUs at the expense of using slightly slower non-direct DMABuf import.
* See: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1236 */
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WAYLAND || GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_EGL
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WAYLAND || GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_EGL
#if !defined(HAVE_GST_PATCHES) && (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64))
preferred_api = GDK_GL_API_GL;
#endif
#endif
if (!(success = _realize_gdk_context_with_api (gdk_context, preferred_api))) {
/* Continue with GLES only if it should have "GL_EXT_texture_norm16"
* extension, as we need it to handle P010_10LE, etc. */
if ((preferred_api == GDK_GL_API_GLES)
&& _realize_gdk_context_with_api (gdk_context, GDK_GL_API_GLES, 3, 1))
return TRUE;
/* If not using GLES 3.1, try with core GL 3.2 that GTK4 defaults to */
if (_realize_gdk_context_with_api (gdk_context, GDK_GL_API_GL, 3, 2))
return TRUE;
/* Try with what we normally prefer first, otherwise use fallback */
if (!(success = _realize_gdk_context_with_api (gdk_context, preferred_api, 0, 0))) {
GdkGLAPI fallback_api;
fallback_api = (GDK_GL_API_GL | GDK_GL_API_GLES);
fallback_api &= ~preferred_api;
success = _realize_gdk_context_with_api (gdk_context, fallback_api);
success = _realize_gdk_context_with_api (gdk_context, fallback_api, 0, 0);
}
return success;
}
static void
gst_clapper_gl_base_importer_init (GstClapperGLBaseImporter *self)
static gboolean
_retrieve_gl_context_on_main (GstClapperGLContextHandler *self)
{
g_mutex_init (&self->lock);
GdkDisplay *gdk_display;
GdkGLContext *gdk_context;
GError *error = NULL;
GdkGLAPI gdk_gl_api;
GstGLPlatform platform = GST_GL_PLATFORM_NONE;
gint gl_major = 0, gl_minor = 0;
if (!gtk_init_check ()) {
GST_ERROR_OBJECT (self, "Could not ensure GTK initialization");
return FALSE;
}
gdk_display = gdk_display_get_default ();
if (G_UNLIKELY (!gdk_display)) {
GST_ERROR_OBJECT (self, "Could not retrieve Gdk display");
return FALSE;
}
if (!(gdk_context = gdk_display_create_gl_context (gdk_display, &error))) {
GST_ERROR_OBJECT (self, "Error creating Gdk GL context: %s",
error ? error->message : "No error set by Gdk");
g_clear_error (&error);
return FALSE;
}
if (!_gl_context_handler_context_realize (self, gdk_context)) {
GST_ERROR_OBJECT (self, "Could not realize Gdk context: %" GST_PTR_FORMAT,
gdk_context);
g_object_unref (gdk_context);
return FALSE;
}
gdk_gl_api = gdk_gl_context_get_api (gdk_context);
GST_OBJECT_LOCK (self);
self->gdk_context = gdk_context;
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WAYLAND
if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) {
struct wl_display *wayland_display =
gdk_wayland_display_get_wl_display (gdk_display);
self->gst_display = (GstGLDisplay *)
gst_gl_display_wayland_new_with_display (wayland_display);
}
#endif
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11
if (GDK_IS_X11_DISPLAY (gdk_display)) {
gpointer display_ptr;
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_EGL
display_ptr = gdk_x11_display_get_egl_display (gdk_display);
if (display_ptr) {
self->gst_display = (GstGLDisplay *)
gst_gl_display_egl_new_with_egl_display (display_ptr);
}
#endif
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_GLX
if (!self->gst_display) {
display_ptr = gdk_x11_display_get_xdisplay (gdk_display);
self->gst_display = (GstGLDisplay *)
gst_gl_display_x11_new_with_display (display_ptr);
}
}
#endif
#endif
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32
if (GDK_IS_WIN32_DISPLAY (gdk_display)) {
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_EGL
gpointer display_ptr = gdk_win32_display_get_egl_display (gdk_display);
if (display_ptr) {
self->gst_display = (GstGLDisplay *)
gst_gl_display_egl_new_with_egl_display (display_ptr);
}
#endif
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_WGL
if (!self->gst_display) {
self->gst_display =
gst_gl_display_new_with_type (GST_GL_DISPLAY_TYPE_WIN32);
}
}
#endif
#endif
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_MACOS
if (GDK_IS_MACOS_DISPLAY (gdk_display)) {
self->gst_display =
gst_gl_display_new_with_type (GST_GL_DISPLAY_TYPE_COCOA);
}
#endif
/* Fallback to generic display */
if (G_UNLIKELY (!self->gst_display)) {
GST_WARNING_OBJECT (self, "Unknown Gdk display!");
self->gst_display = gst_gl_display_new ();
}
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WAYLAND
if (GST_IS_GL_DISPLAY_WAYLAND (self->gst_display)) {
platform = GST_GL_PLATFORM_EGL;
GST_INFO_OBJECT (self, "Using EGL on Wayland");
goto have_display;
}
#endif
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_EGL
if (GST_IS_GL_DISPLAY_EGL (self->gst_display)
&& GDK_IS_X11_DISPLAY (gdk_display)) {
platform = GST_GL_PLATFORM_EGL;
GST_INFO_OBJECT (self, "Using EGL on x11");
goto have_display;
}
#endif
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_GLX
if (GST_IS_GL_DISPLAY_X11 (self->gst_display)) {
platform = GST_GL_PLATFORM_GLX;
GST_INFO_OBJECT (self, "Using GLX on x11");
goto have_display;
}
#endif
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_EGL
if (GST_IS_GL_DISPLAY_EGL (self->gst_display)
&& GDK_IS_WIN32_DISPLAY (gdk_display)) {
platform = GST_GL_PLATFORM_EGL;
GST_INFO_OBJECT (self, "Using EGL on Win32");
goto have_display;
}
#endif
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_WGL
if (gst_gl_display_get_handle_type (self->gst_display) == GST_GL_DISPLAY_TYPE_WIN32) {
platform = GST_GL_PLATFORM_WGL;
GST_INFO_OBJECT (self, "Using WGL on Win32");
goto have_display;
}
#endif
#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_MACOS
if (gst_gl_display_get_handle_type (self->gst_display) == GST_GL_DISPLAY_TYPE_COCOA) {
platform = GST_GL_PLATFORM_CGL;
GST_INFO_OBJECT (self, "Using CGL on macOS");
goto have_display;
}
#endif
g_clear_object (&self->gdk_context);
gst_clear_object (&self->gst_display);
GST_OBJECT_UNLOCK (self);
GST_ERROR_OBJECT (self, "Unsupported GL platform");
return FALSE;
have_display:
gdk_gl_context_make_current (self->gdk_context);
self->wrapped_context = _wrap_current_gl (self->gst_display, gdk_gl_api, platform);
if (!self->wrapped_context) {
GST_ERROR ("Could not retrieve Gdk OpenGL context");
gdk_gl_context_clear_current ();
g_clear_object (&self->gdk_context);
gst_clear_object (&self->gst_display);
GST_OBJECT_UNLOCK (self);
return FALSE;
}
GST_INFO ("Retrieved Gdk OpenGL context %" GST_PTR_FORMAT, self->wrapped_context);
gst_gl_context_activate (self->wrapped_context, TRUE);
if (!gst_gl_context_fill_info (self->wrapped_context, &error)) {
GST_ERROR ("Failed to fill Gdk context info: %s", error->message);
g_clear_error (&error);
gst_gl_context_activate (self->wrapped_context, FALSE);
gst_clear_object (&self->wrapped_context);
g_clear_object (&self->gdk_context);
gst_clear_object (&self->gst_display);
GST_OBJECT_UNLOCK (self);
return FALSE;
}
gst_gl_context_get_gl_version (self->wrapped_context, &gl_major, &gl_minor);
GST_INFO ("Using OpenGL%s %i.%i", (gdk_gl_api == GDK_GL_API_GLES) ? " ES" : "",
gl_major, gl_minor);
/* Deactivate in both places */
gst_gl_context_activate (self->wrapped_context, FALSE);
gdk_gl_context_clear_current ();
GST_OBJECT_UNLOCK (self);
return TRUE;
}
static gboolean
_retrieve_gst_context (GstClapperGLContextHandler *self)
{
GstGLDisplay *gst_display = NULL;
GstGLContext *gst_context = NULL;
GError *error = NULL;
GST_OBJECT_LOCK (self);
gst_display = gst_object_ref (self->gst_display);
GST_TRACE_OBJECT (self, "Creating new GstGLContext");
/* GstGLDisplay operations require display object lock to be held */
GST_OBJECT_LOCK (gst_display);
if (!gst_gl_display_create_context (gst_display, self->wrapped_context,
&self->gst_context, &error)) {
GST_WARNING ("Could not create OpenGL context: %s",
error ? error->message : "Unknown");
g_clear_error (&error);
GST_OBJECT_UNLOCK (gst_display);
GST_OBJECT_UNLOCK (self);
return FALSE;
}
gst_context = gst_object_ref (self->gst_context);
GST_OBJECT_UNLOCK (self);
gst_gl_display_add_context (gst_display, gst_context);
GST_OBJECT_UNLOCK (gst_display);
gst_object_unref (gst_display);
gst_object_unref (gst_context);
return TRUE;
}
static gboolean
gst_clapper_gl_context_handler_handle_context_query (GstClapperContextHandler *handler,
GstBaseSink *bsink, GstQuery *query)
{
GstClapperGLContextHandler *self = GST_CLAPPER_GL_CONTEXT_HANDLER_CAST (handler);
gboolean res;
GST_OBJECT_LOCK (self);
res = gst_gl_handle_context_query (GST_ELEMENT_CAST (bsink), query,
self->gst_display, self->gst_context, self->wrapped_context);
GST_OBJECT_UNLOCK (self);
return res;
}
static void
gst_clapper_gl_base_importer_finalize (GObject *object)
gst_clapper_gl_context_handler_init (GstClapperGLContextHandler *self)
{
GstClapperGLBaseImporter *self = GST_CLAPPER_GL_BASE_IMPORTER_CAST (object);
}
static void
gst_clapper_gl_context_handler_constructed (GObject *object)
{
GstClapperGLContextHandler *self = GST_CLAPPER_GL_CONTEXT_HANDLER_CAST (object);
if (! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback)
_retrieve_gl_context_on_main, self)) {
_retrieve_gst_context (self);
}
GST_CALL_PARENT (G_OBJECT_CLASS, constructed, (object));
}
static void
gst_clapper_gl_context_handler_finalize (GObject *object)
{
GstClapperGLContextHandler *self = GST_CLAPPER_GL_CONTEXT_HANDLER_CAST (object);
GST_TRACE ("Finalize");
g_clear_object (&self->gdk_context);
@@ -548,70 +469,74 @@ gst_clapper_gl_base_importer_finalize (GObject *object)
gst_clear_object (&self->wrapped_context);
gst_clear_object (&self->gst_context);
g_mutex_clear (&self->lock);
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
}
static void
gst_clapper_gl_base_importer_class_init (GstClapperGLBaseImporterClass *klass)
gst_clapper_gl_context_handler_class_init (GstClapperGLContextHandlerClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GstClapperImporterClass *importer_class = (GstClapperImporterClass *) klass;
GstClapperGLBaseImporterClass *gl_bi_class = (GstClapperGLBaseImporterClass *) klass;
GstClapperContextHandlerClass *handler_class = (GstClapperContextHandlerClass *) klass;
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperglbaseimporter", 0,
"Clapper GL Base Importer");
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperglcontexthandler", 0,
"Clapper GL Context Handler");
gobject_class->finalize = gst_clapper_gl_base_importer_finalize;
gobject_class->constructed = gst_clapper_gl_context_handler_constructed;
gobject_class->finalize = gst_clapper_gl_context_handler_finalize;
importer_class->prepare = gst_clapper_gl_base_importer_prepare;
importer_class->share_data = gst_clapper_gl_base_importer_share_data;
importer_class->handle_context_query = gst_clapper_gl_base_importer_handle_context_query;
importer_class->create_pool = gst_clapper_gl_base_importer_create_pool;
importer_class->add_allocation_metas = gst_clapper_gl_base_importer_add_allocation_metas;
handler_class->handle_context_query = gst_clapper_gl_context_handler_handle_context_query;
}
gl_bi_class->gdk_context_realize = gst_clapper_gl_base_importer_gdk_context_realize;
void
gst_clapper_gl_context_handler_add_handler (GPtrArray *context_handlers)
{
guint i;
gboolean found = FALSE;
for (i = 0; i < context_handlers->len; i++) {
GstClapperContextHandler *handler = g_ptr_array_index (context_handlers, i);
if ((found = GST_IS_CLAPPER_GL_CONTEXT_HANDLER (handler)))
break;
}
if (!found) {
GstClapperGLContextHandler *handler = g_object_new (
GST_TYPE_CLAPPER_GL_CONTEXT_HANDLER, NULL);
g_ptr_array_add (context_handlers, handler);
GST_DEBUG ("Added GL context handler to handlers array");
}
}
GstCaps *
gst_clapper_gl_base_importer_make_supported_gdk_gl_caps (void)
gst_clapper_gl_context_handler_make_gdk_gl_caps (const gchar *features, gboolean only_2d)
{
GstCaps *caps, *tmp;
tmp = gst_caps_from_string (
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_GL_MEMORY,
"{ " GST_GDK_GL_TEXTURE_FORMATS " }") ", "
"texture-target = (string) { " GST_GL_TEXTURE_TARGET_2D_STR " }");
if (only_2d) {
tmp = gst_caps_from_string (GST_VIDEO_CAPS_MAKE (
"{ " GST_GDK_GL_TEXTURE_FORMATS " }") ", "
"texture-target = (string) { " GST_GL_TEXTURE_TARGET_2D_STR " }");
} else {
tmp = gst_caps_from_string (GST_VIDEO_CAPS_MAKE (
"{ " GST_GDK_GL_TEXTURE_FORMATS " }"));
}
caps = gst_caps_copy (tmp);
gst_caps_set_features_simple (tmp, gst_caps_features_new (
features, NULL));
gst_caps_set_features_simple (caps, gst_caps_features_new (
GST_CAPS_FEATURE_MEMORY_GL_MEMORY,
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, NULL));
features, GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, NULL));
gst_caps_append (caps, tmp);
return caps;
}
GStrv
gst_clapper_gl_base_importer_make_gl_context_types (void)
{
GStrv context_types;
GStrvBuilder *builder = g_strv_builder_new ();
g_strv_builder_add (builder, GST_GL_DISPLAY_CONTEXT_TYPE);
g_strv_builder_add (builder, "gst.gl.app_context");
g_strv_builder_add (builder, "gst.gl.local_context");
context_types = g_strv_builder_end (builder);
g_strv_builder_unref (builder);
return context_types;
}
GdkTexture *
gst_clapper_gl_base_importer_make_gl_texture (GstClapperGLBaseImporter *self,
gst_clapper_gl_context_handler_make_gl_texture (GstClapperGLContextHandler *self,
GstBuffer *buffer, GstVideoInfo *v_info)
{
GdkTexture *texture;
@@ -623,7 +548,7 @@ gst_clapper_gl_base_importer_make_gl_texture (GstClapperGLBaseImporter *self,
return NULL;
}
GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self);
GST_OBJECT_LOCK (self);
/* Must have context active here for both sync meta
* and Gdk texture format auto-detection to work */
@@ -650,7 +575,7 @@ gst_clapper_gl_base_importer_make_gl_texture (GstClapperGLBaseImporter *self,
gst_gl_context_activate (self->wrapped_context, FALSE);
gdk_gl_context_clear_current ();
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
GST_OBJECT_UNLOCK (self);
gst_video_frame_unmap (&frame);

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2022 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 Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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 <gst/gst.h>
#include <gst/video/video.h>
#include <gst/gl/gl.h>
#include <gst/gl/gstglfuncs.h>
#include <gtk/gtk.h>
#include "gst/plugin/gstclappercontexthandler.h"
G_BEGIN_DECLS
#define GST_TYPE_CLAPPER_GL_CONTEXT_HANDLER (gst_clapper_gl_context_handler_get_type())
G_DECLARE_FINAL_TYPE (GstClapperGLContextHandler, gst_clapper_gl_context_handler, GST, CLAPPER_GL_CONTEXT_HANDLER, GstClapperContextHandler)
#define GST_CLAPPER_GL_CONTEXT_HANDLER_CAST(obj) ((GstClapperGLContextHandler *)(obj))
#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WAYLAND (GST_GL_HAVE_WINDOW_WAYLAND && defined (GDK_WINDOWING_WAYLAND))
#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11 (GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11))
#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_GLX (GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11 && GST_GL_HAVE_PLATFORM_GLX)
#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_EGL (GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11 && GST_GL_HAVE_PLATFORM_EGL)
#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32 (GST_GL_HAVE_WINDOW_WIN32 && defined (GDK_WINDOWING_WIN32))
#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_WGL (GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32 && GST_GL_HAVE_PLATFORM_WGL)
#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_EGL (GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32 && GST_GL_HAVE_PLATFORM_EGL)
#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_MACOS (GST_GL_HAVE_WINDOW_COCOA && defined (GDK_WINDOWING_MACOS) && GST_GL_HAVE_PLATFORM_CGL)
struct _GstClapperGLContextHandler
{
GstClapperContextHandler parent;
GdkGLContext *gdk_context;
GstGLDisplay *gst_display;
GstGLContext *wrapped_context;
GstGLContext *gst_context;
};
void gst_clapper_gl_context_handler_add_handler (GPtrArray *context_handlers);
GstCaps * gst_clapper_gl_context_handler_make_gdk_gl_caps (const gchar *features, gboolean only_2d);
GdkTexture * gst_clapper_gl_context_handler_make_gl_texture (GstClapperGLContextHandler *handler, GstBuffer *buffer, GstVideoInfo *v_info);
G_END_DECLS

View File

@@ -0,0 +1,83 @@
gst_clapper_gl_ch_dep = dependency('', required: false)
build_gl_ch = (
not get_option('glimporter').disabled()
or not get_option('gluploader').disabled()
)
gl_support_required = (
get_option('glimporter').enabled()
or get_option('gluploader').enabled()
)
gst_plugin_gl_ch_deps = [gst_clapper_sink_dep, gstgl_dep, gstglproto_dep]
have_gtk_gl_windowing = false
if gst_gl_have_window_x11 and (gst_gl_have_platform_egl or gst_gl_have_platform_glx)
gtk_x11_dep = dependency('gtk4-x11', required: false)
if gtk_x11_dep.found()
gst_plugin_gl_ch_deps += gtk_x11_dep
if gst_gl_have_platform_glx
gst_plugin_gl_ch_deps += gstglx11_dep
endif
have_gtk_gl_windowing = true
endif
endif
if gst_gl_have_window_wayland and gst_gl_have_platform_egl
gtk_wayland_dep = dependency('gtk4-wayland', required: false)
if gtk_wayland_dep.found()
gst_plugin_gl_ch_deps += [gtk_wayland_dep, gstglwayland_dep]
have_gtk_gl_windowing = true
endif
endif
if gst_gl_have_window_win32 and (gst_gl_have_platform_egl or gst_gl_have_platform_wgl)
gtk_win32_dep = dependency('gtk4-win32', required: false)
if gtk_win32_dep.found()
gst_plugin_gl_ch_deps += gtk_win32_dep
have_gtk_gl_windowing = true
endif
endif
if gst_gl_have_window_cocoa and gst_gl_have_platform_cgl
gtk_macos_dep = dependency('gtk4-macos', required: false)
if gtk_macos_dep.found()
gst_plugin_gl_ch_deps += gtk_macos_dep
have_gtk_gl_windowing = true
endif
endif
if not have_gtk_gl_windowing
if gl_support_required
error('GL-based importer was enabled, but support for current GL windowing is missing')
endif
build_gl_ch = false
endif
if gst_gl_have_platform_egl
gst_plugin_gl_ch_deps += gstglegl_dep
endif
foreach dep : gst_plugin_gl_ch_deps
if not dep.found()
if gl_support_required
error('GL-based importer was enabled, but required dependencies were not found')
endif
build_gl_ch = false
endif
endforeach
if build_gl_ch
gst_clapper_gl_ch_dep = declare_dependency(
link_with: library('gstclapperglcontexthandler',
'gstclapperglcontexthandler.c',
c_args: gst_clapper_plugin_args,
include_directories: configinc,
dependencies: gst_plugin_gl_ch_deps,
version: libversion,
install: true,
),
include_directories: configinc,
dependencies: gst_plugin_gl_ch_deps,
)
endif

View File

@@ -0,0 +1 @@
subdir('gl')

View File

@@ -1,85 +0,0 @@
/*
* Copyright (C) 2022 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 Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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 <gst/gl/gl.h>
#include "gst/plugin/gstclapperimporter.h"
G_BEGIN_DECLS
#define GST_TYPE_CLAPPER_GL_BASE_IMPORTER (gst_clapper_gl_base_importer_get_type())
#define GST_IS_CLAPPER_GL_BASE_IMPORTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CLAPPER_GL_BASE_IMPORTER))
#define GST_IS_CLAPPER_GL_BASE_IMPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CLAPPER_GL_BASE_IMPORTER))
#define GST_CLAPPER_GL_BASE_IMPORTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CLAPPER_GL_BASE_IMPORTER, GstClapperGLBaseImporterClass))
#define GST_CLAPPER_GL_BASE_IMPORTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CLAPPER_GL_BASE_IMPORTER, GstClapperGLBaseImporter))
#define GST_CLAPPER_GL_BASE_IMPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CLAPPER_GL_BASE_IMPORTER, GstClapperGLBaseImporterClass))
#define GST_CLAPPER_GL_BASE_IMPORTER_CAST(obj) ((GstClapperGLBaseImporter *)(obj))
#define GST_CLAPPER_GL_BASE_IMPORTER_GET_LOCK(obj) (&GST_CLAPPER_GL_BASE_IMPORTER_CAST(obj)->lock)
#define GST_CLAPPER_GL_BASE_IMPORTER_LOCK(obj) g_mutex_lock (GST_CLAPPER_GL_BASE_IMPORTER_GET_LOCK(obj))
#define GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK(obj) g_mutex_unlock (GST_CLAPPER_GL_BASE_IMPORTER_GET_LOCK(obj))
#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WAYLAND (GST_GL_HAVE_WINDOW_WAYLAND && defined (GDK_WINDOWING_WAYLAND))
#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11 (GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11))
#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_GLX (GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11 && GST_GL_HAVE_PLATFORM_GLX)
#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_EGL (GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11 && GST_GL_HAVE_PLATFORM_EGL)
#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32 (GST_GL_HAVE_WINDOW_WIN32 && defined (GDK_WINDOWING_WIN32))
#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_WGL (GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32 && GST_GL_HAVE_PLATFORM_WGL)
#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_EGL (GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32 && GST_GL_HAVE_PLATFORM_EGL)
#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_MACOS (GST_GL_HAVE_WINDOW_COCOA && defined (GDK_WINDOWING_MACOS) && GST_GL_HAVE_PLATFORM_CGL)
typedef struct _GstClapperGLBaseImporter GstClapperGLBaseImporter;
typedef struct _GstClapperGLBaseImporterClass GstClapperGLBaseImporterClass;
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstClapperGLBaseImporter, gst_object_unref)
#endif
struct _GstClapperGLBaseImporter
{
GstClapperImporter parent;
GMutex lock;
GdkGLContext *gdk_context;
GstGLDisplay *gst_display;
GstGLContext *wrapped_context;
GstGLContext *gst_context;
};
struct _GstClapperGLBaseImporterClass
{
GstClapperImporterClass parent_class;
gboolean (* gdk_context_realize) (GstClapperGLBaseImporter *gl_bi,
GdkGLContext *gdk_context);
};
GType gst_clapper_gl_base_importer_get_type (void);
GstCaps * gst_clapper_gl_base_importer_make_supported_gdk_gl_caps (void);
GStrv gst_clapper_gl_base_importer_make_gl_context_types (void);
GdkTexture * gst_clapper_gl_base_importer_make_gl_texture (GstClapperGLBaseImporter *self, GstBuffer *buffer, GstVideoInfo *v_info);
G_END_DECLS

View File

@@ -27,15 +27,45 @@
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define parent_class gst_clapper_gl_importer_parent_class
GST_CLAPPER_IMPORTER_DEFINE (GstClapperGLImporter, gst_clapper_gl_importer, GST_TYPE_CLAPPER_GL_BASE_IMPORTER);
GST_CLAPPER_IMPORTER_DEFINE (GstClapperGLImporter, gst_clapper_gl_importer, GST_TYPE_CLAPPER_IMPORTER);
static GstBufferPool *
gst_clapper_gl_importer_create_pool (GstClapperImporter *importer, GstStructure **config)
{
GstClapperGLImporter *self = GST_CLAPPER_GL_IMPORTER_CAST (importer);
GstBufferPool *pool;
GST_DEBUG_OBJECT (self, "Creating new GL buffer pool");
pool = gst_gl_buffer_pool_new (self->gl_handler->gst_context);
*config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_add_option (*config, GST_BUFFER_POOL_OPTION_VIDEO_META);
gst_buffer_pool_config_add_option (*config, GST_BUFFER_POOL_OPTION_GL_SYNC_META);
return pool;
}
static void
gst_clapper_gl_importer_add_allocation_metas (GstClapperImporter *importer, GstQuery *query)
{
GstClapperGLImporter *self = GST_CLAPPER_GL_IMPORTER_CAST (importer);
/* We can support GL sync meta */
if (self->gl_handler->gst_context->gl_vtable->FenceSync)
gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, NULL);
/* Also add base importer class supported meta */
GST_CLAPPER_IMPORTER_CLASS (parent_class)->add_allocation_metas (importer, query);
}
static GdkTexture *
gst_clapper_gl_importer_generate_texture (GstClapperImporter *importer,
GstBuffer *buffer, GstVideoInfo *v_info)
{
GstClapperGLBaseImporter *gl_bi = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer);
GstClapperGLImporter *self = GST_CLAPPER_GL_IMPORTER_CAST (importer);
return gst_clapper_gl_base_importer_make_gl_texture (gl_bi, buffer, v_info);
return gst_clapper_gl_context_handler_make_gl_texture (self->gl_handler, buffer, v_info);
}
static void
@@ -43,28 +73,58 @@ gst_clapper_gl_importer_init (GstClapperGLImporter *self)
{
}
static void
gst_clapper_gl_importer_finalize (GObject *object)
{
GstClapperGLImporter *self = GST_CLAPPER_GL_IMPORTER_CAST (object);
gst_clear_object (&self->gl_handler);
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
}
static void
gst_clapper_gl_importer_class_init (GstClapperGLImporterClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GstClapperImporterClass *importer_class = (GstClapperImporterClass *) klass;
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperglimporter", 0,
"Clapper GL Importer");
gobject_class->finalize = gst_clapper_gl_importer_finalize;
importer_class->create_pool = gst_clapper_gl_importer_create_pool;
importer_class->add_allocation_metas = gst_clapper_gl_importer_add_allocation_metas;
importer_class->generate_texture = gst_clapper_gl_importer_generate_texture;
}
GstClapperImporter *
make_importer (void)
make_importer (GPtrArray *context_handlers)
{
return g_object_new (GST_TYPE_CLAPPER_GL_IMPORTER, NULL);
GstClapperGLImporter *self;
GstClapperContextHandler *handler;
handler = gst_clapper_context_handler_obtain_with_type (context_handlers,
GST_TYPE_CLAPPER_GL_CONTEXT_HANDLER);
if (G_UNLIKELY (!handler))
return NULL;
self = g_object_new (GST_TYPE_CLAPPER_GL_IMPORTER, NULL);
self->gl_handler = GST_CLAPPER_GL_CONTEXT_HANDLER_CAST (handler);
return GST_CLAPPER_IMPORTER_CAST (self);
}
GstCaps *
make_caps (gboolean is_template, GstRank *rank, GStrv *context_types)
make_caps (gboolean is_template, GstRank *rank, GPtrArray *context_handlers)
{
*rank = GST_RANK_SECONDARY;
*context_types = gst_clapper_gl_base_importer_make_gl_context_types ();
return gst_clapper_gl_base_importer_make_supported_gdk_gl_caps ();
if (!is_template && context_handlers)
gst_clapper_gl_context_handler_add_handler (context_handlers);
return gst_clapper_gl_context_handler_make_gdk_gl_caps (
GST_CAPS_FEATURE_MEMORY_GL_MEMORY, TRUE);
}

View File

@@ -19,18 +19,21 @@
#pragma once
#include "gstclapperglbaseimporter.h"
#include "gst/plugin/gstclapperimporter.h"
#include "gst/plugin/handlers/gl/gstclapperglcontexthandler.h"
G_BEGIN_DECLS
#define GST_TYPE_CLAPPER_GL_IMPORTER (gst_clapper_gl_importer_get_type())
G_DECLARE_FINAL_TYPE (GstClapperGLImporter, gst_clapper_gl_importer, GST, CLAPPER_GL_IMPORTER, GstClapperGLBaseImporter)
G_DECLARE_FINAL_TYPE (GstClapperGLImporter, gst_clapper_gl_importer, GST, CLAPPER_GL_IMPORTER, GstClapperImporter)
#define GST_CLAPPER_GL_IMPORTER_CAST(obj) ((GstClapperGLImporter *)(obj))
struct _GstClapperGLImporter
{
GstClapperGLBaseImporter parent;
GstClapperImporter parent;
GstClapperGLContextHandler *gl_handler;
};
G_END_DECLS

View File

@@ -22,40 +22,38 @@
#endif
#include "gstclappergluploader.h"
#include "gst/plugin/gstgtkutils.h"
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11
#include <gdk/x11/gdkx.h>
#endif
#define GST_CAT_DEFAULT gst_clapper_gl_uploader_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define parent_class gst_clapper_gl_uploader_parent_class
GST_CLAPPER_IMPORTER_DEFINE (GstClapperGLUploader, gst_clapper_gl_uploader, GST_TYPE_CLAPPER_GL_BASE_IMPORTER);
GST_CLAPPER_IMPORTER_DEFINE (GstClapperGLUploader, gst_clapper_gl_uploader, GST_TYPE_CLAPPER_IMPORTER);
static void
_update_elements_caps_locked (GstClapperGLUploader *self, GstCaps *upload_sink_caps)
{
GstClapperGLBaseImporter *gl_bi = GST_CLAPPER_GL_BASE_IMPORTER_CAST (self);
GstGLContext *gst_context;
GstCaps *upload_src_caps, *color_sink_caps, *color_src_caps, *gdk_sink_caps;
gst_context = self->gl_handler->gst_context;
GST_INFO_OBJECT (self, "Input caps: %" GST_PTR_FORMAT, upload_sink_caps);
upload_src_caps = gst_gl_upload_transform_caps (self->upload, gl_bi->gst_context,
upload_src_caps = gst_gl_upload_transform_caps (self->upload, gst_context,
GST_PAD_SINK, upload_sink_caps, NULL);
upload_src_caps = gst_caps_fixate (upload_src_caps);
GST_INFO_OBJECT (self, "GLUpload caps: %" GST_PTR_FORMAT, upload_src_caps);
gst_gl_upload_set_caps (self->upload, upload_sink_caps, upload_src_caps);
gdk_sink_caps = gst_clapper_gl_base_importer_make_supported_gdk_gl_caps ();
color_sink_caps = gst_gl_color_convert_transform_caps (gl_bi->gst_context,
gdk_sink_caps = gst_clapper_gl_context_handler_make_gdk_gl_caps (
GST_CAPS_FEATURE_MEMORY_GL_MEMORY, TRUE);
color_sink_caps = gst_gl_color_convert_transform_caps (gst_context,
GST_PAD_SRC, upload_src_caps, gdk_sink_caps);
gst_caps_unref (gdk_sink_caps);
/* Second caps arg is transfer-full */
color_src_caps = gst_gl_color_convert_fixate_caps (gl_bi->gst_context,
color_src_caps = gst_gl_color_convert_fixate_caps (gst_context,
GST_PAD_SINK, upload_src_caps, color_sink_caps);
GST_INFO_OBJECT (self, "GLColorConvert caps: %" GST_PTR_FORMAT, color_src_caps);
@@ -72,9 +70,9 @@ gst_clapper_gl_uploader_set_caps (GstClapperImporter *importer, GstCaps *caps)
{
GstClapperGLUploader *self = GST_CLAPPER_GL_UPLOADER_CAST (importer);
GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self);
GST_CLAPPER_GL_UPLOADER_LOCK (self);
_update_elements_caps_locked (self, caps);
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
GST_CLAPPER_GL_UPLOADER_UNLOCK (self);
}
static void
@@ -92,28 +90,6 @@ _uploader_reconfigure_locked (GstClapperGLUploader *self)
}
}
static gboolean
gst_clapper_gl_uploader_prepare (GstClapperImporter *importer)
{
gboolean res = GST_CLAPPER_IMPORTER_CLASS (parent_class)->prepare (importer);
if (res) {
GstClapperGLUploader *self = GST_CLAPPER_GL_UPLOADER_CAST (importer);
GstClapperGLBaseImporter *gl_bi = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer);
GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self);
if (!self->upload)
self->upload = gst_gl_upload_new (gl_bi->gst_context);
if (!self->color_convert)
self->color_convert = gst_gl_color_convert_new (gl_bi->gst_context);
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
}
return res;
}
static GstBuffer *
_upload_perform_locked (GstClapperGLUploader *self, GstBuffer *buffer)
{
@@ -152,13 +128,19 @@ gst_clapper_gl_uploader_add_allocation_metas (GstClapperImporter *importer, GstQ
GstClapperGLUploader *self = GST_CLAPPER_GL_UPLOADER_CAST (importer);
GstGLUpload *upload;
GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self);
GST_CLAPPER_GL_UPLOADER_LOCK (self);
upload = gst_object_ref (self->upload);
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
GST_CLAPPER_GL_UPLOADER_UNLOCK (self);
/* Add glupload supported meta */
gst_gl_upload_propose_allocation (upload, NULL, query);
gst_object_unref (upload);
/* We can support GL sync meta */
if (self->gl_handler->gst_context->gl_vtable->FenceSync)
gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, NULL);
/* Also add base importer class supported meta */
GST_CLAPPER_IMPORTER_CLASS (parent_class)->add_allocation_metas (importer, query);
}
@@ -167,7 +149,6 @@ gst_clapper_gl_uploader_generate_texture (GstClapperImporter *importer,
GstBuffer *buffer, GstVideoInfo *v_info)
{
GstClapperGLUploader *self = GST_CLAPPER_GL_UPLOADER_CAST (importer);
GstClapperGLBaseImporter *gl_bi = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer);
GstBuffer *upload_buf, *color_buf;
GdkTexture *texture;
@@ -177,13 +158,13 @@ gst_clapper_gl_uploader_generate_texture (GstClapperImporter *importer,
GST_LOG_OBJECT (self, "Uploading %" GST_PTR_FORMAT, buffer);
GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self);
GST_CLAPPER_GL_UPLOADER_LOCK (self);
upload_buf = _upload_perform_locked (self, buffer);
if (G_UNLIKELY (!upload_buf)) {
GST_ERROR_OBJECT (self, "Could not perform upload on input buffer");
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
GST_CLAPPER_GL_UPLOADER_UNLOCK (self);
return NULL;
}
@@ -198,7 +179,7 @@ gst_clapper_gl_uploader_generate_texture (GstClapperImporter *importer,
self->has_pending_v_info = FALSE;
}
GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self);
GST_CLAPPER_GL_UPLOADER_UNLOCK (self);
if (G_UNLIKELY (!color_buf)) {
GST_ERROR_OBJECT (self, "Could not perform color conversion on input buffer");
@@ -206,7 +187,7 @@ gst_clapper_gl_uploader_generate_texture (GstClapperImporter *importer,
}
GST_LOG_OBJECT (self, "Color converted into %" GST_PTR_FORMAT, color_buf);
texture = gst_clapper_gl_base_importer_make_gl_texture (gl_bi, color_buf, &self->v_info);
texture = gst_clapper_gl_context_handler_make_gl_texture (self->gl_handler, color_buf, &self->v_info);
gst_buffer_unref (color_buf);
return texture;
@@ -215,6 +196,8 @@ gst_clapper_gl_uploader_generate_texture (GstClapperImporter *importer,
static void
gst_clapper_gl_uploader_init (GstClapperGLUploader *self)
{
g_mutex_init (&self->lock);
gst_video_info_init (&self->pending_v_info);
gst_video_info_init (&self->v_info);
}
@@ -227,6 +210,10 @@ gst_clapper_gl_uploader_finalize (GObject *object)
gst_clear_object (&self->upload);
gst_clear_object (&self->color_convert);
gst_clear_object (&self->gl_handler);
g_mutex_clear (&self->lock);
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
}
@@ -241,7 +228,6 @@ gst_clapper_gl_uploader_class_init (GstClapperGLUploaderClass *klass)
gobject_class->finalize = gst_clapper_gl_uploader_finalize;
importer_class->prepare = gst_clapper_gl_uploader_prepare;
importer_class->set_caps = gst_clapper_gl_uploader_set_caps;
importer_class->create_pool = gst_clapper_gl_uploader_create_pool;
importer_class->add_allocation_metas = gst_clapper_gl_uploader_add_allocation_metas;
@@ -249,64 +235,94 @@ gst_clapper_gl_uploader_class_init (GstClapperGLUploaderClass *klass)
}
GstClapperImporter *
make_importer (void)
make_importer (GPtrArray *context_handlers)
{
return g_object_new (GST_TYPE_CLAPPER_GL_UPLOADER, NULL);
GstClapperGLUploader *self;
GstClapperContextHandler *handler;
handler = gst_clapper_context_handler_obtain_with_type (context_handlers,
GST_TYPE_CLAPPER_GL_CONTEXT_HANDLER);
if (G_UNLIKELY (!handler))
return NULL;
self = g_object_new (GST_TYPE_CLAPPER_GL_UPLOADER, NULL);
self->gl_handler = GST_CLAPPER_GL_CONTEXT_HANDLER_CAST (handler);
self->upload = gst_gl_upload_new (self->gl_handler->gst_context);
self->color_convert = gst_gl_color_convert_new (self->gl_handler->gst_context);
return GST_CLAPPER_IMPORTER_CAST (self);
}
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_GLX
static gboolean
_filter_glx_caps_cb (GstCapsFeatures *features,
GstStructure *structure, gpointer user_data)
static GstCaps *
_make_actual_caps (GstClapperGLContextHandler *gl_handler)
{
return !gst_caps_features_contains (features, "memory:DMABuf");
GstGLUpload *upload;
GstCaps *gdk_sink_caps, *color_sink_caps, *upload_sink_caps, *actual;
guint i;
/* Having "gst_context" means we also have all other contexts and
* display as they are used to create it, so no need to check */
if (!gl_handler->gst_context)
return NULL;
gdk_sink_caps = gst_clapper_gl_context_handler_make_gdk_gl_caps (
GST_CAPS_FEATURE_MEMORY_GL_MEMORY, TRUE);
color_sink_caps = gst_gl_color_convert_transform_caps (gl_handler->gst_context,
GST_PAD_SRC, gdk_sink_caps, NULL);
gst_caps_unref (gdk_sink_caps);
upload = gst_gl_upload_new (NULL);
upload_sink_caps = gst_gl_upload_transform_caps (upload, gl_handler->gst_context,
GST_PAD_SRC, color_sink_caps, NULL);
gst_caps_unref (color_sink_caps);
gst_object_unref (upload);
/* Check for existence and remove duplicated structures,
* they may contain unsupported by our GL context formats */
actual = gst_caps_new_empty ();
for (i = 0; i < gst_caps_get_size (upload_sink_caps); i++) {
GstCaps *tmp = gst_caps_copy_nth (upload_sink_caps, i);
if (!gst_caps_can_intersect (actual, tmp))
gst_caps_append (actual, tmp);
else
gst_caps_unref (tmp);
}
gst_caps_unref (upload_sink_caps);
if (G_UNLIKELY (gst_caps_is_empty (actual)))
gst_clear_caps (&actual);
return actual;
}
static gboolean
_update_glx_caps_on_main (GstCaps *caps)
GstCaps *
make_caps (gboolean is_template, GstRank *rank, GPtrArray *context_handlers)
{
GdkDisplay *gdk_display;
GstCaps *caps = NULL;
if (!gtk_init_check ())
return FALSE;
if (is_template) {
caps = gst_gl_upload_get_input_template_caps ();
} else if (context_handlers) {
GstClapperGLContextHandler *gl_handler;
gdk_display = gdk_display_get_default ();
if (G_UNLIKELY (!gdk_display))
return FALSE;
/* Add GL context handler if not already present */
gst_clapper_gl_context_handler_add_handler (context_handlers);
if (GDK_IS_X11_DISPLAY (gdk_display)) {
gboolean using_glx = TRUE;
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_EGL
using_glx = (gdk_x11_display_get_egl_display (gdk_display) == NULL);
#endif
if (using_glx) {
gst_caps_filter_and_map_in_place (caps,
(GstCapsFilterMapFunc) _filter_glx_caps_cb, NULL);
if ((gl_handler = GST_CLAPPER_GL_CONTEXT_HANDLER_CAST (
gst_clapper_context_handler_obtain_with_type (context_handlers,
GST_TYPE_CLAPPER_GL_CONTEXT_HANDLER)))) {
caps = _make_actual_caps (gl_handler);
gst_object_unref (gl_handler);
}
}
return TRUE;
}
#endif
GstCaps *
make_caps (gboolean is_template, GstRank *rank, GStrv *context_types)
{
GstCaps *caps = gst_gl_upload_get_input_template_caps ();
#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_GLX
if (!is_template && !(! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback)
_update_glx_caps_on_main, caps)))
gst_clear_caps (&caps);
#endif
if (G_UNLIKELY (!caps))
return NULL;
*rank = GST_RANK_MARGINAL + 1;
*context_types = gst_clapper_gl_base_importer_make_gl_context_types ();
if (caps)
*rank = GST_RANK_MARGINAL + 1;
return caps;
}

View File

@@ -19,18 +19,27 @@
#pragma once
#include "gstclapperglbaseimporter.h"
#include "gst/plugin/gstclapperimporter.h"
#include "gst/plugin/handlers/gl/gstclapperglcontexthandler.h"
G_BEGIN_DECLS
#define GST_TYPE_CLAPPER_GL_UPLOADER (gst_clapper_gl_uploader_get_type())
G_DECLARE_FINAL_TYPE (GstClapperGLUploader, gst_clapper_gl_uploader, GST, CLAPPER_GL_UPLOADER, GstClapperGLBaseImporter)
G_DECLARE_FINAL_TYPE (GstClapperGLUploader, gst_clapper_gl_uploader, GST, CLAPPER_GL_UPLOADER, GstClapperImporter)
#define GST_CLAPPER_GL_UPLOADER_CAST(obj) ((GstClapperGLUploader *)(obj))
#define GST_CLAPPER_GL_UPLOADER_GET_LOCK(obj) (&GST_CLAPPER_GL_UPLOADER_CAST(obj)->lock)
#define GST_CLAPPER_GL_UPLOADER_LOCK(obj) g_mutex_lock (GST_CLAPPER_GL_UPLOADER_GET_LOCK(obj))
#define GST_CLAPPER_GL_UPLOADER_UNLOCK(obj) g_mutex_unlock (GST_CLAPPER_GL_UPLOADER_GET_LOCK(obj))
struct _GstClapperGLUploader
{
GstClapperGLBaseImporter parent;
GstClapperImporter parent;
GMutex lock;
GstClapperGLContextHandler *gl_handler;
GstGLUpload *upload;
GstGLColorConvert *color_convert;

View File

@@ -47,13 +47,6 @@ gst_clapper_raw_importer_create_pool (GstClapperImporter *importer, GstStructure
return pool;
}
static void
gst_clapper_raw_importer_add_allocation_metas (GstClapperImporter *importer, GstQuery *query)
{
gst_query_add_allocation_meta (query, GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL);
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
}
static GdkTexture *
gst_clapper_raw_importer_generate_texture (GstClapperImporter *importer,
GstBuffer *buffer, GstVideoInfo *v_info)
@@ -86,18 +79,17 @@ gst_clapper_raw_importer_class_init (GstClapperRawImporterClass *klass)
"Clapper RAW Importer");
importer_class->create_pool = gst_clapper_raw_importer_create_pool;
importer_class->add_allocation_metas = gst_clapper_raw_importer_add_allocation_metas;
importer_class->generate_texture = gst_clapper_raw_importer_generate_texture;
}
GstClapperImporter *
make_importer (void)
make_importer (GPtrArray *context_handlers)
{
return g_object_new (GST_TYPE_CLAPPER_RAW_IMPORTER, NULL);
}
GstCaps *
make_caps (gboolean is_template, GstRank *rank, GStrv *context_types)
make_caps (gboolean is_template, GstRank *rank, GPtrArray *context_handlers)
{
*rank = GST_RANK_MARGINAL;

View File

@@ -1,20 +1,9 @@
gst_clapper_gl_base_importer_dep = dependency('', required: false)
all_importers = [
'glimporter',
'gluploader',
'rawimporter',
]
build_glbase = (
not get_option('glimporter').disabled()
or not get_option('gluploader').disabled()
)
gl_support_required = (
get_option('glimporter').enabled()
or get_option('gluploader').enabled()
)
# We cannot build any importers without sink that they depend on
if not gst_clapper_sink_dep.found()
foreach imp : all_importers
@@ -24,89 +13,16 @@ if not gst_clapper_sink_dep.found()
endforeach
endif
gst_plugin_gl_base_deps = [gst_clapper_sink_dep, gstgl_dep, gstglproto_dep]
have_gtk_gl_windowing = false
if gst_gl_have_window_x11 and (gst_gl_have_platform_egl or gst_gl_have_platform_glx)
gtk_x11_dep = dependency('gtk4-x11', required: false)
if gtk_x11_dep.found()
gst_plugin_gl_base_deps += gtk_x11_dep
if gst_gl_have_platform_glx
gst_plugin_gl_base_deps += gstglx11_dep
endif
have_gtk_gl_windowing = true
endif
endif
if gst_gl_have_window_wayland and gst_gl_have_platform_egl
gtk_wayland_dep = dependency('gtk4-wayland', required: false)
if gtk_wayland_dep.found()
gst_plugin_gl_base_deps += [gtk_wayland_dep, gstglwayland_dep]
have_gtk_gl_windowing = true
endif
endif
if gst_gl_have_window_win32 and (gst_gl_have_platform_egl or gst_gl_have_platform_wgl)
gtk_win32_dep = dependency('gtk4-win32', required: false)
if gtk_win32_dep.found()
gst_plugin_gl_base_deps += gtk_win32_dep
have_gtk_gl_windowing = true
endif
endif
if gst_gl_have_window_cocoa and gst_gl_have_platform_cgl
gtk_macos_dep = dependency('gtk4-macos', required: false)
if gtk_macos_dep.found()
gst_plugin_gl_base_deps += gtk_macos_dep
have_gtk_gl_windowing = true
endif
endif
if not have_gtk_gl_windowing
if gl_support_required
error('GL-based importer was enabled, but support for current GL windowing is missing')
endif
build_glbase = false
endif
if gst_gl_have_platform_egl
gst_plugin_gl_base_deps += gstglegl_dep
endif
foreach dep : gst_plugin_gl_base_deps
if not dep.found()
if gl_support_required
error('GL-based importer was enabled, but required dependencies were not found')
endif
build_glbase = false
endif
endforeach
if build_glbase
gst_clapper_gl_base_importer_dep = declare_dependency(
link_with: library('gstclapperglbaseimporter',
'gstclapperglbaseimporter.c',
c_args: gst_clapper_plugin_args,
include_directories: configinc,
dependencies: gst_plugin_gl_base_deps,
version: libversion,
install: true,
),
include_directories: configinc,
dependencies: gst_plugin_gl_base_deps,
)
endif
build_glimporter = (
not get_option('glimporter').disabled()
and gst_clapper_gl_base_importer_dep.found()
and gst_clapper_gl_ch_dep.found()
)
if build_glimporter
library(
'gstclapperglimporter',
'gstclapperglimporter.c',
dependencies: gst_clapper_gl_base_importer_dep,
dependencies: gst_clapper_gl_ch_dep,
include_directories: configinc,
c_args: gst_clapper_plugin_args,
install: true,
@@ -116,14 +32,14 @@ endif
build_gluploader = (
not get_option('gluploader').disabled()
and gst_clapper_gl_base_importer_dep.found()
and gst_clapper_gl_ch_dep.found()
)
if build_gluploader
library(
'gstclappergluploader',
'gstclappergluploader.c',
dependencies: gst_clapper_gl_base_importer_dep,
dependencies: gst_clapper_gl_ch_dep,
include_directories: configinc,
c_args: gst_clapper_plugin_args,
install: true,

View File

@@ -41,6 +41,7 @@ gst_clapper_plugin_sources = [
'gstclapperpaintable.c',
'gstgtkutils.c',
'gstplugin.c',
'gstclappercontexthandler.c',
'gstclapperimporter.c',
'gstclapperimporterloader.c',
]
@@ -60,4 +61,5 @@ if build_gst_plugin
)
endif
subdir('handlers')
subdir('importers')

View File

@@ -1,5 +1,5 @@
project('com.github.rafostar.Clapper', 'c', 'cpp',
version: '0.5.0',
version: '0.5.2',
meson_version: '>= 0.50.0',
license: 'GPL-3.0-or-later',
default_options: [

View File

@@ -5,7 +5,7 @@
"sdk": "org.gnome.Sdk",
"sdk-extensions": [
"org.freedesktop.Sdk.Extension.rust-nightly",
"org.freedesktop.Sdk.Extension.llvm13"
"org.freedesktop.Sdk.Extension.llvm14"
],
"command": "com.github.rafostar.Clapper",
"finish-args": [
@@ -18,20 +18,18 @@
"--device=all",
"--filesystem=xdg-run/pipewire-0:ro",
"--filesystem=xdg-videos",
"--filesystem=xdg-run/gvfsd",
"--own-name=org.mpris.MediaPlayer2.Clapper",
"--talk-name=org.gtk.vfs.*",
"--talk-name=org.gnome.Shell",
"--env=GST_PLUGIN_SYSTEM_PATH=/app/lib/gstreamer-1.0",
"--env=GST_VAAPI_ALL_DRIVERS=1"
"--env=GST_PLUGIN_SYSTEM_PATH=/app/lib/gstreamer-1.0"
],
"build-options": {
"append-path": "/usr/lib/sdk/rust-nightly/bin:/usr/lib/sdk/llvm13/bin",
"prepend-ld-library-path": "/usr/lib/sdk/llvm13/lib"
"append-path": "/usr/lib/sdk/rust-nightly/bin:/usr/lib/sdk/llvm14/bin",
"prepend-ld-library-path": "/usr/lib/sdk/llvm14/lib"
},
"modules": [
"flathub/shared-modules/gudev/gudev.json",
"flathub/lib/libsass.json",
"flathub/lib/sassc.json",
"flathub/lib/libadwaita.json",
"flathub/lib/liba52.json",
"flathub/lib/libmpeg2.json",
"flathub/lib/libdv.json",

View File

@@ -1,7 +1,7 @@
{
"app-id": "com.github.rafostar.Clapper",
"runtime": "org.gnome.Platform",
"runtime-version": "42",
"runtime-version": "43",
"sdk": "org.gnome.Sdk",
"command": "com.github.rafostar.Clapper",
"finish-args": [
@@ -14,10 +14,11 @@
"--device=all",
"--filesystem=xdg-run/pipewire-0:ro",
"--filesystem=xdg-videos",
"--filesystem=xdg-run/gvfsd",
"--own-name=org.mpris.MediaPlayer2.Clapper",
"--talk-name=org.gtk.vfs.*",
"--talk-name=org.gnome.Shell",
"--env=GST_PLUGIN_SYSTEM_PATH=/app/lib/gstreamer-1.0",
"--env=GST_VAAPI_ALL_DRIVERS=1"
"--env=GST_PLUGIN_SYSTEM_PATH=/app/lib/gstreamer-1.0"
],
"modules": [
"flathub/shared-modules/gudev/gudev.json",
@@ -39,6 +40,9 @@
{
"name": "clapper",
"buildsystem": "meson",
"config-opts": [
"-Dc_args=\"-DHAVE_GST_PATCHES=1\""
],
"sources": [
{
"type": "dir",

View File

@@ -1,6 +1,9 @@
{
"name": "gst-plugins-rs",
"buildsystem": "simple",
"only-arches": [
"x86_64"
],
"build-options": {
"build-args": [
"--share=network"

View File

@@ -0,0 +1,13 @@
diff --git a/meson.build b/meson.build
index 38d23ed61c..68dea864a0 100644
--- a/meson.build
+++ b/meson.build
@@ -799,7 +799,7 @@ subdir('docs/tools')
subdir('docs/reference')
if not meson.is_cross_build()
- if meson.version().version_compare('>=0.57.0')
+ if false
gnome.post_install(
glib_compile_schemas: true,
gio_querymodules: gio_module_dirs,

View File

@@ -0,0 +1,114 @@
From 4dcd02e85315f487310e2e01fe9412706a77dc35 Mon Sep 17 00:00:00 2001
From: Emmanuele Bassi <ebassi@gnome.org>
Date: Tue, 19 Apr 2022 15:33:21 +0100
Subject: [PATCH] Quench the anger of GCC
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Direct access of the fields of the union trips compiler warnings with
GCC 12, such as:
../gtk/gtkimagedefinition.c:135:13: error: array subscript
GtkImageDefinition {aka union _GtkImageDefinition}[0] is partly
outside array bounds of GtkImageDefinitionEmpty[1] {aka
struct _GtkImageDefinitionEmpty[1]} [-Werror=array-bounds]
---
gtk/gtkimagedefinition.c | 38 ++++++++++++++++++++++++++++----------
1 file changed, 28 insertions(+), 10 deletions(-)
diff --git a/gtk/gtkimagedefinition.c b/gtk/gtkimagedefinition.c
index 1b7c9e51d9..3cf785b01c 100644
--- a/gtk/gtkimagedefinition.c
+++ b/gtk/gtkimagedefinition.c
@@ -132,7 +132,9 @@ gtk_image_definition_new_paintable (GdkPaintable *paintable)
GtkImageDefinition *
gtk_image_definition_ref (GtkImageDefinition *def)
{
- def->empty.ref_count++;
+ GtkImageDefinitionEmpty *empty = (GtkImageDefinitionEmpty *) def;
+
+ empty->ref_count++;
return def;
}
@@ -140,9 +142,11 @@ gtk_image_definition_ref (GtkImageDefinition *def)
void
gtk_image_definition_unref (GtkImageDefinition *def)
{
- def->empty.ref_count--;
+ GtkImageDefinitionEmpty *empty = (GtkImageDefinitionEmpty *) def;
+
+ empty->ref_count--;
- if (def->empty.ref_count > 0)
+ if (empty->ref_count > 0)
return;
switch (def->type)
@@ -152,13 +156,22 @@ gtk_image_definition_unref (GtkImageDefinition *def)
g_assert_not_reached ();
break;
case GTK_IMAGE_PAINTABLE:
- g_object_unref (def->paintable.paintable);
+ {
+ GtkImageDefinitionPaintable *paintable = (GtkImageDefinitionPaintable *) def;
+ g_object_unref (paintable->paintable);
+ }
break;
case GTK_IMAGE_ICON_NAME:
- g_free (def->icon_name.icon_name);
+ {
+ GtkImageDefinitionIconName *icon_name = (GtkImageDefinitionIconName *) def;
+ g_free (icon_name->icon_name);
+ }
break;
case GTK_IMAGE_GICON:
- g_object_unref (def->gicon.gicon);
+ {
+ GtkImageDefinitionGIcon *gicon = (GtkImageDefinitionGIcon *) def;
+ g_object_unref (gicon->gicon);
+ }
break;
}
@@ -189,27 +202,32 @@ gtk_image_definition_get_scale (const GtkImageDefinition *def)
const char *
gtk_image_definition_get_icon_name (const GtkImageDefinition *def)
{
+ const GtkImageDefinitionIconName *icon_name = (const GtkImageDefinitionIconName *) def;
+
if (def->type != GTK_IMAGE_ICON_NAME)
return NULL;
- return def->icon_name.icon_name;
+ return icon_name->icon_name;
}
GIcon *
gtk_image_definition_get_gicon (const GtkImageDefinition *def)
{
+ const GtkImageDefinitionGIcon *gicon = (const GtkImageDefinitionGIcon *) def;
+
if (def->type != GTK_IMAGE_GICON)
return NULL;
- return def->gicon.gicon;
+ return gicon->gicon;
}
GdkPaintable *
gtk_image_definition_get_paintable (const GtkImageDefinition *def)
{
+ const GtkImageDefinitionPaintable *paintable = (const GtkImageDefinitionPaintable *) def;
+
if (def->type != GTK_IMAGE_PAINTABLE)
return NULL;
- return def->paintable.paintable;
+ return paintable->paintable;
}
-
--
GitLab

View File

@@ -0,0 +1,31 @@
From b413ee2c7d458c7005d3d3d1da8822cd86893ac0 Mon Sep 17 00:00:00 2001
From: Rafostar <40623528+Rafostar@users.noreply.github.com>
Date: Fri, 4 Dec 2020 19:25:34 +0100
Subject: [PATCH] popover: Call unrealize on hide
When popover is shown "realize" method is called which creates a new
surface for popup. Unfortunately this causes performance drop on Wayland until that
surface is destroyed what happens inside "unrealize" method during popover destruction.
This commit changes default behavior in a way that surface will be destroyed
when popover is closed and app will ragain the performance it lost when
popover was shown.
---
gtk/gtkpopover.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c
index 504dcd6cc1..a7a764d483 100644
--- a/gtk/gtkpopover.c
+++ b/gtk/gtkpopover.c
@@ -951,6 +951,7 @@ gtk_popover_hide (GtkWidget *widget)
gtk_popover_set_mnemonics_visible (GTK_POPOVER (widget), FALSE);
_gtk_widget_set_visible_flag (widget, FALSE);
+ gtk_widget_unrealize (widget);
gtk_widget_unmap (widget);
g_signal_emit (widget, signals[CLOSED], 0);
}
--
GitLab

View File

@@ -1,14 +1,11 @@
{
"name": "gtk",
"buildsystem": "meson",
"build-options": {
"build-args": [
"--share=network"
]
},
"config-opts": [
"--buildtype=release",
"--wrap-mode=nodownload",
"-Dbroadway-backend=true",
"-Dwin32-backend=false",
"-Dmacos-backend=false",
"-Dmedia-ffmpeg=disabled",
@@ -26,8 +23,19 @@
{
"type": "git",
"url": "https://gitlab.gnome.org/GNOME/gtk.git",
"tag": "4.6.4",
"commit": "1e6bad6c4f412dc0eb7b2f508cb4465929a04303"
"branch": "gtk-4-4"
},
{
"type": "patch",
"path": "gtk4-popover-unrealize.patch"
},
{
"type": "patch",
"path": "gtk4-disable-meson-gnome-post-install.patch"
},
{
"type": "patch",
"path": "gtk4-latest-gcc-fix.patch"
}
]
}

View File

@@ -14,8 +14,8 @@
{
"type": "git",
"url": "https://gitlab.gnome.org/GNOME/libadwaita.git",
"tag": "1.1.1",
"commit": "5ec9f624b23bf78b29dd708e77ccdfcee0a9867a"
"tag": "1.0.0.alpha.4",
"commit": "6b447fde8f270001a0dc29ef59d3e9bf6d32dae9"
}
]
}

View File

@@ -1 +1 @@
ar ca cs de es eu fr hu it ja nl pl pt pt_BR ru sv tr zh_CN
ar ast ca cs de es eu fa fr he hu it ja nl pl pt pt_BR ru sv tr zh_CN

438
po/ast.po Normal file
View File

@@ -0,0 +1,438 @@
msgid ""
msgstr ""
"Project-Id-Version: clapper\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-05-26 18:41+0200\n"
"PO-Revision-Date: 2022-06-26 22:43\n"
"Last-Translator: \n"
"Language-Team: Asturian\n"
"Language: ast_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"
"X-Crowdin-Project: clapper\n"
"X-Crowdin-Project-ID: 473374\n"
"X-Crowdin-Language: ast\n"
"X-Crowdin-File: /master/po/com.github.rafostar.Clapper.pot\n"
"X-Crowdin-File-ID: 31\n"
#: ui/clapper.ui:6
msgid "Open Files…"
msgstr "Abrir ficheros…"
#: ui/clapper.ui:10
msgid "Open URI…"
msgstr "Abrir un URI…"
#: ui/clapper.ui:16 ui/preferences-window.ui:4
msgid "Preferences"
msgstr "Preferencies"
#: ui/clapper.ui:20
msgid "Shortcuts"
msgstr "Atayos"
#: ui/clapper.ui:26
msgid "About Clapper"
msgstr "Tocante a Clapper"
#: ui/elapsed-time-button.ui:27
msgid "Speed"
msgstr "Velocidá"
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:82
msgid "Normal"
msgstr "Normal"
#: ui/help-overlay.ui:10 ui/preferences-window.ui:11
msgid "General"
msgstr "Xenerales"
#: ui/help-overlay.ui:13
msgid "Show shortcuts"
msgstr "Amosar los atayos"
#: ui/help-overlay.ui:19
msgid "Toggle fullscreen"
msgstr ""
#: ui/help-overlay.ui:20
msgid "Double tap | Double click"
msgstr ""
#: ui/help-overlay.ui:26
msgid "Leave fullscreen"
msgstr ""
#: ui/help-overlay.ui:32
msgid "Reveal OSD (fullscreen only)"
msgstr ""
#: ui/help-overlay.ui:33
msgid "Tap"
msgstr ""
#: ui/help-overlay.ui:39
msgid "Quit"
msgstr "Colar"
#: ui/help-overlay.ui:47
msgid "Media"
msgstr ""
#: ui/help-overlay.ui:50
msgid "Open files"
msgstr ""
#: ui/help-overlay.ui:56 src/dialogs.js:137
msgid "Open URI"
msgstr ""
#: ui/help-overlay.ui:64
msgid "Playlist"
msgstr "Llista de reproducción"
#: ui/help-overlay.ui:67
msgid "Next item"
msgstr ""
#: ui/help-overlay.ui:68
msgid "Double tap (right side)"
msgstr ""
#: ui/help-overlay.ui:74
msgid "Previous item"
msgstr ""
#: ui/help-overlay.ui:75
msgid "Double tap (left side)"
msgstr ""
#: ui/help-overlay.ui:81
msgid "Change repeat mode"
msgstr ""
#: ui/help-overlay.ui:87
msgid "Export to file"
msgstr ""
#: ui/help-overlay.ui:95 ui/preferences-window.ui:118
msgid "Playback"
msgstr ""
#: ui/help-overlay.ui:98
msgid "Toggle play"
msgstr ""
#: ui/help-overlay.ui:99
msgid "Long press | Right click"
msgstr ""
#: ui/help-overlay.ui:105
msgid "Seek forward"
msgstr ""
#: ui/help-overlay.ui:106
msgid "Swipe right | Scroll right"
msgstr ""
#: ui/help-overlay.ui:112
msgid "Seek backward"
msgstr ""
#: ui/help-overlay.ui:113
msgid "Swipe left | Scroll left"
msgstr ""
#: ui/help-overlay.ui:119
msgid "Volume up"
msgstr ""
#: ui/help-overlay.ui:120
msgid "Swipe up | Scroll up"
msgstr ""
#: ui/help-overlay.ui:126
msgid "Volume down"
msgstr ""
#: ui/help-overlay.ui:127
msgid "Swipe down | Scroll down"
msgstr ""
#: ui/help-overlay.ui:133
msgid "Toggle mute"
msgstr ""
#: ui/help-overlay.ui:139
msgid "Next chapter"
msgstr ""
#: ui/help-overlay.ui:145
msgid "Previous chapter"
msgstr ""
#: ui/preferences-plugin-ranking-subpage.ui:11
msgid "Decoders"
msgstr ""
#: ui/preferences-plugin-ranking-subpage.ui:18
msgid "Return to the preferences"
msgstr ""
#: ui/preferences-window.ui:15
msgid "Behavior"
msgstr ""
#: ui/preferences-window.ui:18
msgid "Auto fullscreen"
msgstr ""
#: ui/preferences-window.ui:19
msgid "Enter fullscreen when playlist is replaced except floating mode"
msgstr ""
#: ui/preferences-window.ui:25
msgid "Ask to resume recent media"
msgstr ""
#: ui/preferences-window.ui:31
msgid "Float on all workspaces"
msgstr ""
#: ui/preferences-window.ui:32
msgid "This option only works on GNOME"
msgstr "Esta opción namái funciona en GNOME"
#: ui/preferences-window.ui:38
msgid "After playback"
msgstr ""
#: ui/preferences-window.ui:43
msgid "Do nothing"
msgstr ""
#: ui/preferences-window.ui:44
msgid "Freeze last frame"
msgstr ""
#: ui/preferences-window.ui:45
msgid "Close the app"
msgstr "Zarrar laplicación"
#: ui/preferences-window.ui:55
msgid "Volume"
msgstr "Volume"
#: ui/preferences-window.ui:58
msgid "Custom initial value"
msgstr ""
#: ui/preferences-window.ui:59
msgid "Set custom volume at startup instead of restoring it"
msgstr ""
#: ui/preferences-window.ui:63
msgid "Volume percentage"
msgstr "Porcentaxe de volume"
#: ui/preferences-window.ui:74
msgid "Seeking"
msgstr ""
#: ui/preferences-window.ui:77
msgid "Mode"
msgstr "Mou"
#: ui/preferences-window.ui:83
msgid "Accurate"
msgstr ""
#: ui/preferences-window.ui:84
msgid "Fast"
msgstr ""
#: ui/preferences-window.ui:92
msgid "Unit"
msgstr ""
#: ui/preferences-window.ui:97
msgid "Second"
msgstr "Segundu"
#: ui/preferences-window.ui:98
msgid "Minute"
msgstr "Minutu"
#: ui/preferences-window.ui:99
msgid "Percentage"
msgstr "Porcentaxe"
#: ui/preferences-window.ui:107
msgid "Value"
msgstr ""
#: ui/preferences-window.ui:122
msgid "Audio"
msgstr "Audio"
#: ui/preferences-window.ui:125
msgid "Offset in milliseconds"
msgstr ""
#: ui/preferences-window.ui:132
msgid "Only native audio formats"
msgstr ""
#: ui/preferences-window.ui:140
msgid "Subtitles"
msgstr "Sotítulos"
#: ui/preferences-window.ui:143
msgid "Default font"
msgstr ""
#: ui/preferences-window.ui:153
msgid "Network"
msgstr "Rede"
#: ui/preferences-window.ui:157
msgid "Client"
msgstr "Veceru"
#: ui/preferences-window.ui:160
msgid "Progressive download buffering"
msgstr ""
#: ui/preferences-window.ui:168
msgid "Server"
msgstr "Sirvidor"
#: ui/preferences-window.ui:171
msgid "Control player remotely"
msgstr ""
#: ui/preferences-window.ui:175
msgid "Listening port"
msgstr ""
#: ui/preferences-window.ui:188
msgid "Tweaks"
msgstr ""
#: ui/preferences-window.ui:192
msgid "Appearance"
msgstr ""
#: ui/preferences-window.ui:195
msgid "Dark theme"
msgstr "Tema escuru"
#: ui/preferences-window.ui:201
msgid "Render window shadows"
msgstr ""
#: ui/preferences-window.ui:202
msgid "Disable to increase performance when windowed"
msgstr ""
#: ui/preferences-window.ui:213
msgid "Plugin ranking"
msgstr ""
#: ui/preferences-window.ui:214
msgid "Alter default ranks of GStreamer plugins"
msgstr ""
#: ui/preferences-window.ui:219
msgid "Use playbin3"
msgstr ""
#: ui/preferences-window.ui:220 ui/preferences-window.ui:229
msgid "Requires player restart"
msgstr ""
#: ui/preferences-window.ui:222 ui/preferences-window.ui:231
msgid "Experimental"
msgstr ""
#: ui/preferences-window.ui:228
msgid "Use PipeWire for audio output"
msgstr ""
#: src/buttons.js:201
#, javascript-format
msgid "Decoder: %s"
msgstr ""
#: src/dialogs.js:152
msgid "Enter or drop URI here"
msgstr ""
#: src/dialogs.js:157
msgid "Cancel"
msgstr "Encaboxar"
#: src/dialogs.js:158
msgid "Open"
msgstr "Abrir"
#: src/dialogs.js:226
msgid "Title"
msgstr "Títulu"
#: src/dialogs.js:227
msgid "Completed"
msgstr "Completáu al"
#: src/dialogs.js:235
msgid "Resume playback?"
msgstr "¿Quies siguir cola reproducción?"
#: src/dialogs.js:289
#, javascript-format
msgid "GTK version: %s"
msgstr "Versión de GTK: %s"
#: src/dialogs.js:290
#, javascript-format
msgid "Adwaita version: %s"
msgstr "Versión dAdwaita: %s"
#: src/dialogs.js:291
#, javascript-format
msgid "GStreamer version: %s"
msgstr "Versión de GStreamer: %s"
#: src/dialogs.js:292
#, javascript-format
msgid "GJS version: %s"
msgstr "Versión de GJS: %s"
#: src/dialogs.js:300
msgid "A GNOME media player powered by GStreamer"
msgstr ""
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
#: src/dialogs.js:305
msgid "translator-credits"
msgstr "Adolfo Jayme Barrientos <fitojb@ubuntu.com>, 2022"
#: src/revealers.js:170
#, javascript-format
msgid "Ends at: %s"
msgstr ""
#: src/widget.js:226 src/widget.js:235 src/widget.js:241 src/widget.js:247
msgid "Undetermined"
msgstr ""
#: src/widget.js:242
msgid "Channels"
msgstr ""
#: src/widget.js:260
msgid "Disabled"
msgstr ""

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: clapper\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-05-26 18:41+0200\n"
"PO-Revision-Date: 2022-05-27 16:27\n"
"PO-Revision-Date: 2022-06-24 17:27\n"
"Last-Translator: \n"
"Language-Team: German\n"
"Language: de_DE\n"
@@ -163,7 +163,7 @@ msgstr "Nach unten wischen bzw. scrollen"
#: ui/help-overlay.ui:133
msgid "Toggle mute"
msgstr "In Vollbildmodus wechseln"
msgstr "Stummschaltung umschalten"
#: ui/help-overlay.ui:139
msgid "Next chapter"

438
po/fa.po Normal file
View File

@@ -0,0 +1,438 @@
msgid ""
msgstr ""
"Project-Id-Version: clapper\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-05-26 18:41+0200\n"
"PO-Revision-Date: 2022-07-23 14:14\n"
"Last-Translator: \n"
"Language-Team: Persian\n"
"Language: fa_IR\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"
"X-Crowdin-Project: clapper\n"
"X-Crowdin-Project-ID: 473374\n"
"X-Crowdin-Language: fa\n"
"X-Crowdin-File: /master/po/com.github.rafostar.Clapper.pot\n"
"X-Crowdin-File-ID: 31\n"
#: ui/clapper.ui:6
msgid "Open Files…"
msgstr "گشودن پرونده‌ها…"
#: ui/clapper.ui:10
msgid "Open URI…"
msgstr "گشودن نشانی…"
#: ui/clapper.ui:16 ui/preferences-window.ui:4
msgid "Preferences"
msgstr "ترجیحات"
#: ui/clapper.ui:20
msgid "Shortcuts"
msgstr "میان‌برها"
#: ui/clapper.ui:26
msgid "About Clapper"
msgstr "دربارهٔ کلَپِر"
#: ui/elapsed-time-button.ui:27
msgid "Speed"
msgstr "سرعت"
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:82
msgid "Normal"
msgstr "معمولی"
#: ui/help-overlay.ui:10 ui/preferences-window.ui:11
msgid "General"
msgstr "عمومی"
#: ui/help-overlay.ui:13
msgid "Show shortcuts"
msgstr "نمایش میان‌برها"
#: ui/help-overlay.ui:19
msgid "Toggle fullscreen"
msgstr "تغییر حالت تمام‌صفحه"
#: ui/help-overlay.ui:20
msgid "Double tap | Double click"
msgstr "دو بار ضربه | دو بار کلیک"
#: ui/help-overlay.ui:26
msgid "Leave fullscreen"
msgstr "خروج از تمام‌صفحه"
#: ui/help-overlay.ui:32
msgid "Reveal OSD (fullscreen only)"
msgstr "نمایش OSD (فقط تمام‌صفحه)"
#: ui/help-overlay.ui:33
msgid "Tap"
msgstr "ضربه"
#: ui/help-overlay.ui:39
msgid "Quit"
msgstr "خروج"
#: ui/help-overlay.ui:47
msgid "Media"
msgstr "رسانه"
#: ui/help-overlay.ui:50
msgid "Open files"
msgstr "گشودن پرونده‌ها"
#: ui/help-overlay.ui:56 src/dialogs.js:137
msgid "Open URI"
msgstr "گشودن نشانی"
#: ui/help-overlay.ui:64
msgid "Playlist"
msgstr "سیاههٔ پخش"
#: ui/help-overlay.ui:67
msgid "Next item"
msgstr "مورد بعدی"
#: ui/help-overlay.ui:68
msgid "Double tap (right side)"
msgstr "ضربه دوتایی (سمت راست)"
#: ui/help-overlay.ui:74
msgid "Previous item"
msgstr "مورد قبل"
#: ui/help-overlay.ui:75
msgid "Double tap (left side)"
msgstr "ضربه دوتایی (سمت چپ)"
#: ui/help-overlay.ui:81
msgid "Change repeat mode"
msgstr "تغییر حالت تکرار"
#: ui/help-overlay.ui:87
msgid "Export to file"
msgstr "خروجی گرفتن در فایل"
#: ui/help-overlay.ui:95 ui/preferences-window.ui:118
msgid "Playback"
msgstr "بازپخش"
#: ui/help-overlay.ui:98
msgid "Toggle play"
msgstr "تغییر پخش"
#: ui/help-overlay.ui:99
msgid "Long press | Right click"
msgstr "فشار طولانی | کلیک راست"
#: ui/help-overlay.ui:105
msgid "Seek forward"
msgstr "پیمایش به جلو"
#: ui/help-overlay.ui:106
msgid "Swipe right | Scroll right"
msgstr "کشیدن به راست | اسکرول به راست"
#: ui/help-overlay.ui:112
msgid "Seek backward"
msgstr "پیمایش به عقب"
#: ui/help-overlay.ui:113
msgid "Swipe left | Scroll left"
msgstr "کشیدن به چپ | اسکرول به چپ"
#: ui/help-overlay.ui:119
msgid "Volume up"
msgstr "افزایش صدا"
#: ui/help-overlay.ui:120
msgid "Swipe up | Scroll up"
msgstr "کشیدن به بالا | اسکرول به بالا"
#: ui/help-overlay.ui:126
msgid "Volume down"
msgstr "کاهش صدا"
#: ui/help-overlay.ui:127
msgid "Swipe down | Scroll down"
msgstr "کشیدن به پایین | اسکرول به پایین"
#: ui/help-overlay.ui:133
msgid "Toggle mute"
msgstr "تغییر وضعیت بیصدا"
#: ui/help-overlay.ui:139
msgid "Next chapter"
msgstr "فصل بعدی"
#: ui/help-overlay.ui:145
msgid "Previous chapter"
msgstr "بخش قبلی"
#: ui/preferences-plugin-ranking-subpage.ui:11
msgid "Decoders"
msgstr "کد گشاها"
#: ui/preferences-plugin-ranking-subpage.ui:18
msgid "Return to the preferences"
msgstr "بازگشت به تنظیمات"
#: ui/preferences-window.ui:15
msgid "Behavior"
msgstr "رفتار"
#: ui/preferences-window.ui:18
msgid "Auto fullscreen"
msgstr "تمام صفحه خودکار"
#: ui/preferences-window.ui:19
msgid "Enter fullscreen when playlist is replaced except floating mode"
msgstr "ورود به تمام صفحه وقتی لیست پخش جایگزین شود به جز حالت شناور"
#: ui/preferences-window.ui:25
msgid "Ask to resume recent media"
msgstr "پرسش برای ادامه پخش مدیا"
#: ui/preferences-window.ui:31
msgid "Float on all workspaces"
msgstr "حالت شناور روی همه‌ی صفحات‌کاری"
#: ui/preferences-window.ui:32
msgid "This option only works on GNOME"
msgstr "این مورد تنها بر روی GNOME کار می‌کند"
#: ui/preferences-window.ui:38
msgid "After playback"
msgstr "پس از بازپخش"
#: ui/preferences-window.ui:43
msgid "Do nothing"
msgstr "کاری انجام نشود"
#: ui/preferences-window.ui:44
msgid "Freeze last frame"
msgstr "بی‌حرکت کردن ةخرین قاب"
#: ui/preferences-window.ui:45
msgid "Close the app"
msgstr "بستن برنامه"
#: ui/preferences-window.ui:55
msgid "Volume"
msgstr "درجه صدا"
#: ui/preferences-window.ui:58
msgid "Custom initial value"
msgstr "مقدار اولیه سفارشی"
#: ui/preferences-window.ui:59
msgid "Set custom volume at startup instead of restoring it"
msgstr "تنظیم صدای سفارشی در هنگام راه اندازی به جای بازیابی آن"
#: ui/preferences-window.ui:63
msgid "Volume percentage"
msgstr "درصد صدا"
#: ui/preferences-window.ui:74
msgid "Seeking"
msgstr "پوییدن"
#: ui/preferences-window.ui:77
msgid "Mode"
msgstr "حالت"
#: ui/preferences-window.ui:83
msgid "Accurate"
msgstr "دقت"
#: ui/preferences-window.ui:84
msgid "Fast"
msgstr "تند"
#: ui/preferences-window.ui:92
msgid "Unit"
msgstr "واحد"
#: ui/preferences-window.ui:97
msgid "Second"
msgstr "ثانیه"
#: ui/preferences-window.ui:98
msgid "Minute"
msgstr "دقیقه"
#: ui/preferences-window.ui:99
msgid "Percentage"
msgstr "درصد"
#: ui/preferences-window.ui:107
msgid "Value"
msgstr "مقدار"
#: ui/preferences-window.ui:122
msgid "Audio"
msgstr "صوتی"
#: ui/preferences-window.ui:125
msgid "Offset in milliseconds"
msgstr "جابجایی بر اساس میلی‌ثانیه"
#: ui/preferences-window.ui:132
msgid "Only native audio formats"
msgstr "فقط فرمت‌های صوتی بومی"
#: ui/preferences-window.ui:140
msgid "Subtitles"
msgstr "زیرنویس‌ها"
#: ui/preferences-window.ui:143
msgid "Default font"
msgstr "قلم پیش فرض"
#: ui/preferences-window.ui:153
msgid "Network"
msgstr "شبکه"
#: ui/preferences-window.ui:157
msgid "Client"
msgstr "مشتری"
#: ui/preferences-window.ui:160
msgid "Progressive download buffering"
msgstr "بافرینگ دانلود مترقی"
#: ui/preferences-window.ui:168
msgid "Server"
msgstr "سرور"
#: ui/preferences-window.ui:171
msgid "Control player remotely"
msgstr "کنترل پخش‌کننده از راه دور"
#: ui/preferences-window.ui:175
msgid "Listening port"
msgstr "شنود پورت"
#: ui/preferences-window.ui:188
msgid "Tweaks"
msgstr "دستكاري"
#: ui/preferences-window.ui:192
msgid "Appearance"
msgstr "ظاهر"
#: ui/preferences-window.ui:195
msgid "Dark theme"
msgstr "پوسته تیره"
#: ui/preferences-window.ui:201
msgid "Render window shadows"
msgstr "رندر سایه‌ پنجره‌ها"
#: ui/preferences-window.ui:202
msgid "Disable to increase performance when windowed"
msgstr "غیر فعال سازی برای افزایش کارایی در حالت پنجره ای"
#: ui/preferences-window.ui:213
msgid "Plugin ranking"
msgstr "پیکربندی پلاگین"
#: ui/preferences-window.ui:214
msgid "Alter default ranks of GStreamer plugins"
msgstr "تغییر پیکربندی پیش فرض پلاگین های GStreamer"
#: ui/preferences-window.ui:219
msgid "Use playbin3"
msgstr "استفاده از playbin3"
#: ui/preferences-window.ui:220 ui/preferences-window.ui:229
msgid "Requires player restart"
msgstr "نیازمند به بازشروع برنامه"
#: ui/preferences-window.ui:222 ui/preferences-window.ui:231
msgid "Experimental"
msgstr "آزمایشی"
#: ui/preferences-window.ui:228
msgid "Use PipeWire for audio output"
msgstr "استفاده از PipeWire برای خروجی صدا"
#: src/buttons.js:201
#, javascript-format
msgid "Decoder: %s"
msgstr "کدگشا: %s"
#: src/dialogs.js:152
msgid "Enter or drop URI here"
msgstr "رها کردن یا واردکردن URI"
#: src/dialogs.js:157
msgid "Cancel"
msgstr "لغو"
#: src/dialogs.js:158
msgid "Open"
msgstr "گشودن"
#: src/dialogs.js:226
msgid "Title"
msgstr "عنوان"
#: src/dialogs.js:227
msgid "Completed"
msgstr "کامل شده"
#: src/dialogs.js:235
msgid "Resume playback?"
msgstr "ادامه بازپخش?"
#: src/dialogs.js:289
#, javascript-format
msgid "GTK version: %s"
msgstr "نسخه GTK: %s"
#: src/dialogs.js:290
#, javascript-format
msgid "Adwaita version: %s"
msgstr "نسخه Adwita: %s"
#: src/dialogs.js:291
#, javascript-format
msgid "GStreamer version: %s"
msgstr "نسخه GStreamer: %s"
#: src/dialogs.js:292
#, javascript-format
msgid "GJS version: %s"
msgstr "نسخه GJS: %s"
#: src/dialogs.js:300
msgid "A GNOME media player powered by GStreamer"
msgstr "یک پخش‌کننده رسانه GNOME قدرت گرفته از GStreamer"
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
#: src/dialogs.js:305
msgid "translator-credits"
msgstr "سجاد موسوی نژاد <ssmns@outlook.com>"
#: src/revealers.js:170
#, javascript-format
msgid "Ends at: %s"
msgstr "پایان در: %s"
#: src/widget.js:226 src/widget.js:235 src/widget.js:241 src/widget.js:247
msgid "Undetermined"
msgstr "نامشخص"
#: src/widget.js:242
msgid "Channels"
msgstr "کانال‌ها"
#: src/widget.js:260
msgid "Disabled"
msgstr "غیرفعال"

208
po/he.po
View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: clapper\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-05-26 18:41+0200\n"
"PO-Revision-Date: 2022-05-26 16:50\n"
"PO-Revision-Date: 2022-06-01 08:42\n"
"Last-Translator: \n"
"Language-Team: Hebrew\n"
"Language: he_IL\n"
@@ -19,420 +19,420 @@ msgstr ""
#: ui/clapper.ui:6
msgid "Open Files…"
msgstr ""
msgstr "פתיחת קבצים…"
#: ui/clapper.ui:10
msgid "Open URI…"
msgstr ""
msgstr "פתיחת כתובת…"
#: ui/clapper.ui:16 ui/preferences-window.ui:4
msgid "Preferences"
msgstr ""
msgstr "העדפות"
#: ui/clapper.ui:20
msgid "Shortcuts"
msgstr ""
msgstr "צירופי מקשים"
#: ui/clapper.ui:26
msgid "About Clapper"
msgstr ""
msgstr "על אודות Clapper"
#: ui/elapsed-time-button.ui:27
msgid "Speed"
msgstr ""
msgstr "מהירות"
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:82
msgid "Normal"
msgstr ""
msgstr "רגילה"
#: ui/help-overlay.ui:10 ui/preferences-window.ui:11
msgid "General"
msgstr ""
msgstr "כללי"
#: ui/help-overlay.ui:13
msgid "Show shortcuts"
msgstr ""
msgstr "הצגת צירופי מקשים"
#: ui/help-overlay.ui:19
msgid "Toggle fullscreen"
msgstr ""
msgstr "שינוי מצב מסך מלא"
#: ui/help-overlay.ui:20
msgid "Double tap | Double click"
msgstr ""
msgstr "נגיעה כפולה | לחיצה כפולה"
#: ui/help-overlay.ui:26
msgid "Leave fullscreen"
msgstr ""
msgstr "יציאה ממסך מלא"
#: ui/help-overlay.ui:32
msgid "Reveal OSD (fullscreen only)"
msgstr ""
msgstr "הצגת מידע וכפתורים (מסך מלא בלבד)"
#: ui/help-overlay.ui:33
msgid "Tap"
msgstr ""
msgstr "נגיעה"
#: ui/help-overlay.ui:39
msgid "Quit"
msgstr ""
msgstr "יציאה"
#: ui/help-overlay.ui:47
msgid "Media"
msgstr ""
msgstr "מדיה"
#: ui/help-overlay.ui:50
msgid "Open files"
msgstr ""
msgstr "פתיחת קבצים"
#: ui/help-overlay.ui:56 src/dialogs.js:137
msgid "Open URI"
msgstr ""
msgstr "פתיחת כתובת"
#: ui/help-overlay.ui:64
msgid "Playlist"
msgstr ""
msgstr "רשימת השמעה"
#: ui/help-overlay.ui:67
msgid "Next item"
msgstr ""
msgstr "פריט הבא"
#: ui/help-overlay.ui:68
msgid "Double tap (right side)"
msgstr ""
msgstr "נגיעה כפולה (צד ימין)"
#: ui/help-overlay.ui:74
msgid "Previous item"
msgstr ""
msgstr "פריט קודם"
#: ui/help-overlay.ui:75
msgid "Double tap (left side)"
msgstr ""
msgstr "נגיעה כפולה (צד שמאל)"
#: ui/help-overlay.ui:81
msgid "Change repeat mode"
msgstr ""
msgstr "שינוי מצב חזרה"
#: ui/help-overlay.ui:87
msgid "Export to file"
msgstr ""
msgstr "ייצוא לקובץ"
#: ui/help-overlay.ui:95 ui/preferences-window.ui:118
msgid "Playback"
msgstr ""
msgstr "השמעה"
#: ui/help-overlay.ui:98
msgid "Toggle play"
msgstr ""
msgstr "הפעלה/השהיה"
#: ui/help-overlay.ui:99
msgid "Long press | Right click"
msgstr ""
msgstr "לחיצה ארוכה | לחצן ימני"
#: ui/help-overlay.ui:105
msgid "Seek forward"
msgstr ""
msgstr "דילוג קדימה"
#: ui/help-overlay.ui:106
msgid "Swipe right | Scroll right"
msgstr ""
msgstr "החלקה ימינה | גלילה ימינה"
#: ui/help-overlay.ui:112
msgid "Seek backward"
msgstr ""
msgstr "דילוג לאחור"
#: ui/help-overlay.ui:113
msgid "Swipe left | Scroll left"
msgstr ""
msgstr "החלקה שמאלה | גלילה שמאלה"
#: ui/help-overlay.ui:119
msgid "Volume up"
msgstr ""
msgstr "הגברת עצמת השמע"
#: ui/help-overlay.ui:120
msgid "Swipe up | Scroll up"
msgstr ""
msgstr "החלקה למעלה | גלילה למעלה"
#: ui/help-overlay.ui:126
msgid "Volume down"
msgstr ""
msgstr "הנמכת עצמת השמע"
#: ui/help-overlay.ui:127
msgid "Swipe down | Scroll down"
msgstr ""
msgstr "החלקה למעלה | גלילה למעלה"
#: ui/help-overlay.ui:133
msgid "Toggle mute"
msgstr ""
msgstr "השתקה/ביטול השתקה"
#: ui/help-overlay.ui:139
msgid "Next chapter"
msgstr ""
msgstr "פרק הבא"
#: ui/help-overlay.ui:145
msgid "Previous chapter"
msgstr ""
msgstr "פרק קודם"
#: ui/preferences-plugin-ranking-subpage.ui:11
msgid "Decoders"
msgstr ""
msgstr "מפענחים"
#: ui/preferences-plugin-ranking-subpage.ui:18
msgid "Return to the preferences"
msgstr ""
msgstr "חזרה להגדרות"
#: ui/preferences-window.ui:15
msgid "Behavior"
msgstr ""
msgstr "התנהגות"
#: ui/preferences-window.ui:18
msgid "Auto fullscreen"
msgstr ""
msgstr "מסך מלא אוטומטי"
#: ui/preferences-window.ui:19
msgid "Enter fullscreen when playlist is replaced except floating mode"
msgstr ""
msgstr "כניסה למצב מסך מלא עם החלפת רשימת השמעה מלבד במצב ציפה"
#: ui/preferences-window.ui:25
msgid "Ask to resume recent media"
msgstr ""
msgstr "לשאול אם להפעיל מחדש את המדיה האחרונה"
#: ui/preferences-window.ui:31
msgid "Float on all workspaces"
msgstr ""
msgstr "ציפה בכל מרחבי העבודה"
#: ui/preferences-window.ui:32
msgid "This option only works on GNOME"
msgstr ""
msgstr "אפשרות זו פועלת רק ב־GNOME"
#: ui/preferences-window.ui:38
msgid "After playback"
msgstr ""
msgstr "בסיום צפייה"
#: ui/preferences-window.ui:43
msgid "Do nothing"
msgstr ""
msgstr "לא לעשות דבר"
#: ui/preferences-window.ui:44
msgid "Freeze last frame"
msgstr ""
msgstr "הקפאת התמונה האחרונה"
#: ui/preferences-window.ui:45
msgid "Close the app"
msgstr ""
msgstr "סגירת היישום"
#: ui/preferences-window.ui:55
msgid "Volume"
msgstr ""
msgstr "עצמת שמע"
#: ui/preferences-window.ui:58
msgid "Custom initial value"
msgstr ""
msgstr "התאמת ערך התחלתי"
#: ui/preferences-window.ui:59
msgid "Set custom volume at startup instead of restoring it"
msgstr ""
msgstr "הגדרת עצמת השמע עם ההפעלה במקום שחזור"
#: ui/preferences-window.ui:63
msgid "Volume percentage"
msgstr ""
msgstr "עצמת שמע באחוזים"
#: ui/preferences-window.ui:74
msgid "Seeking"
msgstr ""
msgstr "דילוג"
#: ui/preferences-window.ui:77
msgid "Mode"
msgstr ""
msgstr "מצב"
#: ui/preferences-window.ui:83
msgid "Accurate"
msgstr ""
msgstr "מדויק"
#: ui/preferences-window.ui:84
msgid "Fast"
msgstr ""
msgstr "מהיר"
#: ui/preferences-window.ui:92
msgid "Unit"
msgstr ""
msgstr "יחידה"
#: ui/preferences-window.ui:97
msgid "Second"
msgstr ""
msgstr "שניה"
#: ui/preferences-window.ui:98
msgid "Minute"
msgstr ""
msgstr "דקה"
#: ui/preferences-window.ui:99
msgid "Percentage"
msgstr ""
msgstr "אחוז"
#: ui/preferences-window.ui:107
msgid "Value"
msgstr ""
msgstr "ערך"
#: ui/preferences-window.ui:122
msgid "Audio"
msgstr ""
msgstr "שמע"
#: ui/preferences-window.ui:125
msgid "Offset in milliseconds"
msgstr ""
msgstr "היסט במילי־שניות"
#: ui/preferences-window.ui:132
msgid "Only native audio formats"
msgstr ""
msgstr "תבניות שמע רגילות בלבד"
#: ui/preferences-window.ui:140
msgid "Subtitles"
msgstr ""
msgstr "כתוביות"
#: ui/preferences-window.ui:143
msgid "Default font"
msgstr ""
msgstr "גופן ברירת מחדל"
#: ui/preferences-window.ui:153
msgid "Network"
msgstr ""
msgstr "רשת"
#: ui/preferences-window.ui:157
msgid "Client"
msgstr ""
msgstr "לקוח"
#: ui/preferences-window.ui:160
msgid "Progressive download buffering"
msgstr ""
msgstr "שימוש בחוצץ הורדה"
#: ui/preferences-window.ui:168
msgid "Server"
msgstr ""
msgstr "שרת"
#: ui/preferences-window.ui:171
msgid "Control player remotely"
msgstr ""
msgstr "שליטה בנגן מרחוק"
#: ui/preferences-window.ui:175
msgid "Listening port"
msgstr ""
msgstr "פתחת האזנה"
#: ui/preferences-window.ui:188
msgid "Tweaks"
msgstr ""
msgstr "התאמות"
#: ui/preferences-window.ui:192
msgid "Appearance"
msgstr ""
msgstr "מראה"
#: ui/preferences-window.ui:195
msgid "Dark theme"
msgstr ""
msgstr "מראה כהה"
#: ui/preferences-window.ui:201
msgid "Render window shadows"
msgstr ""
msgstr "עיבוד צל לחלון"
#: ui/preferences-window.ui:202
msgid "Disable to increase performance when windowed"
msgstr ""
msgstr "השבתה לצמצום צריכת החלונות"
#: ui/preferences-window.ui:213
msgid "Plugin ranking"
msgstr ""
msgstr "דרגות תוספים"
#: ui/preferences-window.ui:214
msgid "Alter default ranks of GStreamer plugins"
msgstr ""
msgstr "שינוי דירוג ברירת המחדל של תוספי GStreamer"
#: ui/preferences-window.ui:219
msgid "Use playbin3"
msgstr ""
msgstr "שימוש ב־playbin3"
#: ui/preferences-window.ui:220 ui/preferences-window.ui:229
msgid "Requires player restart"
msgstr ""
msgstr "דורש הפעלה מחדש של הנגן"
#: ui/preferences-window.ui:222 ui/preferences-window.ui:231
msgid "Experimental"
msgstr ""
msgstr "ניסיוני"
#: ui/preferences-window.ui:228
msgid "Use PipeWire for audio output"
msgstr ""
msgstr "שימוש ב־PipeWire לפלט השמע"
#: src/buttons.js:201
#, javascript-format
msgid "Decoder: %s"
msgstr ""
msgstr "מפענח: %s"
#: src/dialogs.js:152
msgid "Enter or drop URI here"
msgstr ""
msgstr "יש להזין או להשליך כתובת לכאן"
#: src/dialogs.js:157
msgid "Cancel"
msgstr ""
msgstr "ביטול"
#: src/dialogs.js:158
msgid "Open"
msgstr ""
msgstr "פתיחה"
#: src/dialogs.js:226
msgid "Title"
msgstr ""
msgstr "כותרת"
#: src/dialogs.js:227
msgid "Completed"
msgstr ""
msgstr "הושלם"
#: src/dialogs.js:235
msgid "Resume playback?"
msgstr ""
msgstr "להמשיך בצפייה?"
#: src/dialogs.js:289
#, javascript-format
msgid "GTK version: %s"
msgstr ""
msgstr "גרסת GTK: %s"
#: src/dialogs.js:290
#, javascript-format
msgid "Adwaita version: %s"
msgstr ""
msgstr "גרסת Adwaita: %s"
#: src/dialogs.js:291
#, javascript-format
msgid "GStreamer version: %s"
msgstr ""
msgstr "גרסת GStreamer: %s"
#: src/dialogs.js:292
#, javascript-format
msgid "GJS version: %s"
msgstr ""
msgstr "גרסת GJS: %s"
#: src/dialogs.js:300
msgid "A GNOME media player powered by GStreamer"
msgstr ""
msgstr "נגן מדיה עבור GNOME המופעל על ידי GStreamer"
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
#: src/dialogs.js:305
msgid "translator-credits"
msgstr ""
msgstr "יוסף אור בוצ׳קו <yoseforb@gnome.org>"
#: src/revealers.js:170
#, javascript-format
msgid "Ends at: %s"
msgstr ""
msgstr "שעת סיום: %s"
#: src/widget.js:226 src/widget.js:235 src/widget.js:241 src/widget.js:247
msgid "Undetermined"
msgstr ""
msgstr "לא מוגדר"
#: src/widget.js:242
msgid "Channels"
msgstr ""
msgstr "ערוצים"
#: src/widget.js:260
msgid "Disabled"
msgstr ""
msgstr "מושבת"

136
po/tr.po
View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: clapper\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-05-26 18:41+0200\n"
"PO-Revision-Date: 2022-05-26 16:50\n"
"PO-Revision-Date: 2022-06-25 12:42\n"
"Last-Translator: \n"
"Language-Team: Turkish\n"
"Language: tr_TR\n"
@@ -19,7 +19,7 @@ msgstr ""
#: ui/clapper.ui:6
msgid "Open Files…"
msgstr "Dosya Aç…"
msgstr "Dosyaları Aç…"
#: ui/clapper.ui:10
msgid "Open URI…"
@@ -55,7 +55,7 @@ msgstr "Kısayolları göster"
#: ui/help-overlay.ui:19
msgid "Toggle fullscreen"
msgstr "Tam ekran"
msgstr "Tam ekranı aç/kapat"
#: ui/help-overlay.ui:20
msgid "Double tap | Double click"
@@ -83,7 +83,7 @@ msgstr "Ortam"
#: ui/help-overlay.ui:50
msgid "Open files"
msgstr "Dosyaları Aç"
msgstr "Dosyaları aç"
#: ui/help-overlay.ui:56 src/dialogs.js:137
msgid "Open URI"
@@ -111,11 +111,11 @@ msgstr "Çift tıkla (sol tarafa)"
#: ui/help-overlay.ui:81
msgid "Change repeat mode"
msgstr "Tekrarlı oynatma modunu değiştir"
msgstr "Yineleme kipini değiştir"
#: ui/help-overlay.ui:87
msgid "Export to file"
msgstr "Dosyaya aktar"
msgstr "Dosyaya dışa aktar"
#: ui/help-overlay.ui:95 ui/preferences-window.ui:118
msgid "Playback"
@@ -123,7 +123,7 @@ msgstr "Oynatma"
#: ui/help-overlay.ui:98
msgid "Toggle play"
msgstr "Oynatmayı başlat"
msgstr "Oynatmayı başlat/durdur"
#: ui/help-overlay.ui:99
msgid "Long press | Right click"
@@ -163,7 +163,7 @@ msgstr "Aşağı sürükle | Aşağı kaydır"
#: ui/help-overlay.ui:133
msgid "Toggle mute"
msgstr "Sesi kapat"
msgstr "Sesi kapat/aç"
#: ui/help-overlay.ui:139
msgid "Next chapter"
@@ -191,248 +191,248 @@ msgstr "Otomatik tam ekran"
#: ui/preferences-window.ui:19
msgid "Enter fullscreen when playlist is replaced except floating mode"
msgstr ""
msgstr "Yüzen kip dışında oynatma listesi değiştirildiğinde tam ekrana geç"
#: ui/preferences-window.ui:25
msgid "Ask to resume recent media"
msgstr ""
msgstr "Son ortamı devam ettirmeyi sor"
#: ui/preferences-window.ui:31
msgid "Float on all workspaces"
msgstr ""
msgstr "Tüm çalışma alanlarının üstünde yüz"
#: ui/preferences-window.ui:32
msgid "This option only works on GNOME"
msgstr ""
msgstr "Bu seçenek sadece GNOME'da çalışır"
#: ui/preferences-window.ui:38
msgid "After playback"
msgstr ""
msgstr "Oynatma sonrası"
#: ui/preferences-window.ui:43
msgid "Do nothing"
msgstr ""
msgstr "Hiçbir şey yapma"
#: ui/preferences-window.ui:44
msgid "Freeze last frame"
msgstr ""
msgstr "Son kareyi dondur"
#: ui/preferences-window.ui:45
msgid "Close the app"
msgstr ""
msgstr "Uygulamayı kapat"
#: ui/preferences-window.ui:55
msgid "Volume"
msgstr ""
msgstr "Ses"
#: ui/preferences-window.ui:58
msgid "Custom initial value"
msgstr ""
msgstr "Özel başlangıç değeri"
#: ui/preferences-window.ui:59
msgid "Set custom volume at startup instead of restoring it"
msgstr ""
msgstr "Başlangıçta sesi geri yüklemek yerine özel ses ayarla"
#: ui/preferences-window.ui:63
msgid "Volume percentage"
msgstr ""
msgstr "Ses yüzdesi"
#: ui/preferences-window.ui:74
msgid "Seeking"
msgstr ""
msgstr "Sarma"
#: ui/preferences-window.ui:77
msgid "Mode"
msgstr ""
msgstr "Kip"
#: ui/preferences-window.ui:83
msgid "Accurate"
msgstr ""
msgstr "Hatasız"
#: ui/preferences-window.ui:84
msgid "Fast"
msgstr ""
msgstr "Hızlı"
#: ui/preferences-window.ui:92
msgid "Unit"
msgstr ""
msgstr "Birim"
#: ui/preferences-window.ui:97
msgid "Second"
msgstr ""
msgstr "Saniye"
#: ui/preferences-window.ui:98
msgid "Minute"
msgstr ""
msgstr "Dakika"
#: ui/preferences-window.ui:99
msgid "Percentage"
msgstr ""
msgstr "Yüzde"
#: ui/preferences-window.ui:107
msgid "Value"
msgstr ""
msgstr "Değer"
#: ui/preferences-window.ui:122
msgid "Audio"
msgstr ""
msgstr "Ses"
#: ui/preferences-window.ui:125
msgid "Offset in milliseconds"
msgstr ""
msgstr "Milisaniye cinsinden solma süresi"
#: ui/preferences-window.ui:132
msgid "Only native audio formats"
msgstr ""
msgstr "Yalnızca yerel ses biçimleri"
#: ui/preferences-window.ui:140
msgid "Subtitles"
msgstr ""
msgstr "Altyazılar"
#: ui/preferences-window.ui:143
msgid "Default font"
msgstr ""
msgstr "Öntanımlı yazı tipi"
#: ui/preferences-window.ui:153
msgid "Network"
msgstr ""
msgstr ""
#: ui/preferences-window.ui:157
msgid "Client"
msgstr ""
msgstr "İstemci"
#: ui/preferences-window.ui:160
msgid "Progressive download buffering"
msgstr ""
msgstr "Aşamalı indirme arabelleğe alma"
#: ui/preferences-window.ui:168
msgid "Server"
msgstr ""
msgstr "Sunucu"
#: ui/preferences-window.ui:171
msgid "Control player remotely"
msgstr ""
msgstr "Oynatıcıyı uzaktan denetle"
#: ui/preferences-window.ui:175
msgid "Listening port"
msgstr ""
msgstr "Dinleme portu"
#: ui/preferences-window.ui:188
msgid "Tweaks"
msgstr ""
msgstr "İnce Ayarlar"
#: ui/preferences-window.ui:192
msgid "Appearance"
msgstr ""
msgstr "Görünüm"
#: ui/preferences-window.ui:195
msgid "Dark theme"
msgstr ""
msgstr "Koyu tema"
#: ui/preferences-window.ui:201
msgid "Render window shadows"
msgstr ""
msgstr "Pencere gölgelerini işle"
#: ui/preferences-window.ui:202
msgid "Disable to increase performance when windowed"
msgstr ""
msgstr "Pencere açıldığında performansı artırmak için devre dışı bırak"
#: ui/preferences-window.ui:213
msgid "Plugin ranking"
msgstr ""
msgstr "Eklenti puanı"
#: ui/preferences-window.ui:214
msgid "Alter default ranks of GStreamer plugins"
msgstr ""
msgstr "GStreamer eklentilerinin öntanımlı sıralarını değiştir"
#: ui/preferences-window.ui:219
msgid "Use playbin3"
msgstr ""
msgstr "Playbin3 kullan"
#: ui/preferences-window.ui:220 ui/preferences-window.ui:229
msgid "Requires player restart"
msgstr ""
msgstr "Çalıcının yeniden başlatılmasını gerektirir"
#: ui/preferences-window.ui:222 ui/preferences-window.ui:231
msgid "Experimental"
msgstr ""
msgstr "Deneysel"
#: ui/preferences-window.ui:228
msgid "Use PipeWire for audio output"
msgstr ""
msgstr "Ses çıktısı için PipeWire kullan"
#: src/buttons.js:201
#, javascript-format
msgid "Decoder: %s"
msgstr ""
msgstr "Çözücü: %s"
#: src/dialogs.js:152
msgid "Enter or drop URI here"
msgstr ""
msgstr "Bağlantıyı buraya gir veya sürükle"
#: src/dialogs.js:157
msgid "Cancel"
msgstr ""
msgstr "İptal Et"
#: src/dialogs.js:158
msgid "Open"
msgstr ""
msgstr ""
#: src/dialogs.js:226
msgid "Title"
msgstr ""
msgstr "Başlık"
#: src/dialogs.js:227
msgid "Completed"
msgstr ""
msgstr "Tamamlandı"
#: src/dialogs.js:235
msgid "Resume playback?"
msgstr ""
msgstr "Oynatmaya devam edilsin mi?"
#: src/dialogs.js:289
#, javascript-format
msgid "GTK version: %s"
msgstr ""
msgstr "GTK sürümü: %s"
#: src/dialogs.js:290
#, javascript-format
msgid "Adwaita version: %s"
msgstr ""
msgstr "Adwaita sürümü: %s"
#: src/dialogs.js:291
#, javascript-format
msgid "GStreamer version: %s"
msgstr ""
msgstr "GStreamer sürümü: %s"
#: src/dialogs.js:292
#, javascript-format
msgid "GJS version: %s"
msgstr ""
msgstr "GJS sürümü: %s"
#: src/dialogs.js:300
msgid "A GNOME media player powered by GStreamer"
msgstr ""
msgstr "GStreamer'dan gücünü alan bir GNOME ortam oynatıcısı"
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
#: src/dialogs.js:305
msgid "translator-credits"
msgstr ""
msgstr "Clapper Çevirilerine Katkıda Bulunan Herkese Çok Teşekkür Ederiz"
#: src/revealers.js:170
#, javascript-format
msgid "Ends at: %s"
msgstr ""
msgstr "Bitiş: %s"
#: src/widget.js:226 src/widget.js:235 src/widget.js:241 src/widget.js:247
msgid "Undetermined"
msgstr ""
msgstr "Belirsiz"
#: src/widget.js:242
msgid "Channels"
msgstr ""
msgstr "Kanallar"
#: src/widget.js:260
msgid "Disabled"
msgstr ""
msgstr "Devre dışı"

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: clapper\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-05-26 18:41+0200\n"
"PO-Revision-Date: 2022-05-26 16:50\n"
"PO-Revision-Date: 2022-07-18 08:48\n"
"Last-Translator: \n"
"Language-Team: Chinese Simplified\n"
"Language: zh_CN\n"
@@ -27,7 +27,7 @@ msgstr "打开 URI…"
#: ui/clapper.ui:16 ui/preferences-window.ui:4
msgid "Preferences"
msgstr "选项"
msgstr "选项"
#: ui/clapper.ui:20
msgid "Shortcuts"
@@ -59,7 +59,7 @@ msgstr "切换全屏"
#: ui/help-overlay.ui:20
msgid "Double tap | Double click"
msgstr ""
msgstr "轻击两次 | 双击"
#: ui/help-overlay.ui:26
msgid "Leave fullscreen"
@@ -71,7 +71,7 @@ msgstr "显示 OSD仅全屏"
#: ui/help-overlay.ui:33
msgid "Tap"
msgstr ""
msgstr "轻击"
#: ui/help-overlay.ui:39
msgid "Quit"
@@ -99,7 +99,7 @@ msgstr "下一项"
#: ui/help-overlay.ui:68
msgid "Double tap (right side)"
msgstr ""
msgstr "双击(右侧)"
#: ui/help-overlay.ui:74
msgid "Previous item"
@@ -107,7 +107,7 @@ msgstr "上一项"
#: ui/help-overlay.ui:75
msgid "Double tap (left side)"
msgstr ""
msgstr "双击(左侧)"
#: ui/help-overlay.ui:81
msgid "Change repeat mode"
@@ -123,7 +123,7 @@ msgstr "播放"
#: ui/help-overlay.ui:98
msgid "Toggle play"
msgstr ""
msgstr "切换播放"
#: ui/help-overlay.ui:99
msgid "Long press | Right click"
@@ -135,7 +135,7 @@ msgstr "快进"
#: ui/help-overlay.ui:106
msgid "Swipe right | Scroll right"
msgstr ""
msgstr "向右滑动 | 向右滚动"
#: ui/help-overlay.ui:112
msgid "Seek backward"
@@ -143,7 +143,7 @@ msgstr "快退"
#: ui/help-overlay.ui:113
msgid "Swipe left | Scroll left"
msgstr ""
msgstr "向左滑动 | 向左滚动"
#: ui/help-overlay.ui:119
msgid "Volume up"
@@ -167,11 +167,11 @@ msgstr "切换静音"
#: ui/help-overlay.ui:139
msgid "Next chapter"
msgstr ""
msgstr "下一章节"
#: ui/help-overlay.ui:145
msgid "Previous chapter"
msgstr ""
msgstr "上一章节"
#: ui/preferences-plugin-ranking-subpage.ui:11
msgid "Decoders"
@@ -191,15 +191,15 @@ msgstr "自动全屏"
#: ui/preferences-window.ui:19
msgid "Enter fullscreen when playlist is replaced except floating mode"
msgstr ""
msgstr "在播放列表被替换时进入全屏模式,除非悬浮模式"
#: ui/preferences-window.ui:25
msgid "Ask to resume recent media"
msgstr ""
msgstr "询问恢复播放最近的媒体"
#: ui/preferences-window.ui:31
msgid "Float on all workspaces"
msgstr ""
msgstr "悬浮于所有工作区"
#: ui/preferences-window.ui:32
msgid "This option only works on GNOME"
@@ -231,7 +231,7 @@ msgstr "自定义初始值"
#: ui/preferences-window.ui:59
msgid "Set custom volume at startup instead of restoring it"
msgstr ""
msgstr "设置启动时的自定义音量而非恢复先前"
#: ui/preferences-window.ui:63
msgid "Volume percentage"
@@ -279,11 +279,11 @@ msgstr "音频"
#: ui/preferences-window.ui:125
msgid "Offset in milliseconds"
msgstr ""
msgstr "以毫秒为单位的偏移"
#: ui/preferences-window.ui:132
msgid "Only native audio formats"
msgstr ""
msgstr "仅原生音频格式"
#: ui/preferences-window.ui:140
msgid "Subtitles"
@@ -303,7 +303,7 @@ msgstr "客户端"
#: ui/preferences-window.ui:160
msgid "Progressive download buffering"
msgstr ""
msgstr "渐进式下载缓存"
#: ui/preferences-window.ui:168
msgid "Server"
@@ -335,15 +335,15 @@ msgstr "渲染窗口阴影"
#: ui/preferences-window.ui:202
msgid "Disable to increase performance when windowed"
msgstr ""
msgstr "禁用以提升窗口模式时的性能"
#: ui/preferences-window.ui:213
msgid "Plugin ranking"
msgstr ""
msgstr "插件等级"
#: ui/preferences-window.ui:214
msgid "Alter default ranks of GStreamer plugins"
msgstr ""
msgstr "更改 GStreamer 插件的默认等级"
#: ui/preferences-window.ui:219
msgid "Use playbin3"
@@ -368,7 +368,7 @@ msgstr "解码器:%s"
#: src/dialogs.js:152
msgid "Enter or drop URI here"
msgstr ""
msgstr "输入或拖放 URI 到这里"
#: src/dialogs.js:157
msgid "Cancel"
@@ -412,12 +412,13 @@ msgstr "GJS 版本:%s"
#: src/dialogs.js:300
msgid "A GNOME media player powered by GStreamer"
msgstr ""
msgstr "一款基于 GStreamer 的 GNOME 媒体播放器"
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
#: src/dialogs.js:305
msgid "translator-credits"
msgstr "刘韬"
msgstr "刘韬\n"
"Tommy He"
#: src/revealers.js:170
#, javascript-format
@@ -426,7 +427,7 @@ msgstr "结束于:%s"
#: src/widget.js:226 src/widget.js:235 src/widget.js:241 src/widget.js:247
msgid "Undetermined"
msgstr ""
msgstr "未确定"
#: src/widget.js:242
msgid "Channels"

View File

@@ -165,7 +165,7 @@ class ClapperElapsedTimeButton extends PopoverButtonBase
setInitialState()
{
this.label = '00000000';
this.label = `00${Misc.timeColon}0000${Misc.timeColon}00`;
}
setFullscreenMode(isFullscreen, isMobileMonitor)

2
src/controls.js vendored
View File

@@ -27,7 +27,7 @@ class ClapperControls extends Gtk.Box
this.isMobile = false;
this.showHours = false;
this.durationFormatted = '0000';
this.durationFormatted = `00${Misc.timeColon}00`;
this.revealersArr = [];
this.chapters = null;

View File

@@ -10,6 +10,7 @@ Debug.debug('imports');
const { GstClapper, Gtk, Adw } = imports.gi;
const { App } = imports.src.app;
const Misc = imports.src.misc;
function main(argv)
{
@@ -19,6 +20,10 @@ function main(argv)
Gtk.init();
Adw.init();
/* U+2236 seems to break RTL languages, use U+003A instead */
if(Gtk.Widget.get_default_direction() === Gtk.TextDirection.RTL)
Misc.timeColon = ':';
Debug.debug('initialized');
new App().run(argv);

View File

@@ -9,6 +9,7 @@ var subsMimes = [
'application/x-subrip',
'text/x-ssa',
];
var timeColon = '';
var settings = new Gio.Settings({
schema_id: appId,
@@ -161,8 +162,8 @@ function getFormattedTime(time, showHours)
time -= minutes * 60;
const seconds = ('0' + Math.floor(time)).slice(-2);
const parsed = (hours) ? `${hours}` : '';
return parsed + `${minutes}${seconds}`;
const parsed = (hours) ? `${hours}${timeColon}` : '';
return parsed + `${minutes}${timeColon}${seconds}`;
}
function parsePlaylistFiles(filesArray)

View File

@@ -59,8 +59,8 @@ class ClapperRevealerTop extends CustomRevealer
const initTime = GLib.DateTime.new_now_local().format('%X');
this.timeFormat = (initTime.length > 8)
? '%I%M %p'
: '%H%M';
? `%I${Misc.timeColon}%M %p`
: `%H${Misc.timeColon}%M`;
this.mediaTitle = new Gtk.Label({
ellipsize: Pango.EllipsizeMode.END,