summaryrefslogtreecommitdiff
path: root/dev-python/gst-python
diff options
context:
space:
mode:
Diffstat (limited to 'dev-python/gst-python')
-rw-r--r--dev-python/gst-python/Manifest2
-rw-r--r--dev-python/gst-python/files/gst-python-1.26.11-pygobject-3.52.patch176
-rw-r--r--dev-python/gst-python/files/gst-python-1.26.11-skip-test.patch30
-rw-r--r--dev-python/gst-python/gst-python-1.26.11.ebuild76
4 files changed, 284 insertions, 0 deletions
diff --git a/dev-python/gst-python/Manifest b/dev-python/gst-python/Manifest
index 6f5866c81ec9..c2600ad3f736 100644
--- a/dev-python/gst-python/Manifest
+++ b/dev-python/gst-python/Manifest
@@ -1 +1,3 @@
DIST gst-python-1.24.13.tar.xz 128500 BLAKE2B bb33b95d5e062da85ec559fd149377b1ddd5deb0560181f53bde616900fd5281189373dc70f6abe39eb0961a3a1e9bfdf347a1291efcb269ef0a7c41abdb5eb5 SHA512 aa92d6c9c5e81a0230e8d8d7d9f63a3c73c0e4ca5bb377be7cbe8dfc1b1edf74377b35b3f79f6f9df04261a96b89716a19423c0ece1ad250841d661677d7ba9e
+DIST gst-python-1.26.11.tar.xz 141240 BLAKE2B bf7becda7794024480ce19f41819fcdccc5d01cf58134df8a6a595777c3c5dcdba73f6f6a435d72d0a6373f4eab6f3dd160a9c7a2bf3f2bf98f74c5d073ce25a SHA512 8a618750f1616ba11e55501c7b2d05dfd0fe06569faef173703ae0d7301ff82249cf3a73e91b1e78362e967638f6c40771781269597db90c3640f8156f34143d
+DIST gst-python-1.26.11.tar.xz.asc 833 BLAKE2B 3a98ae6d88303634ddfec9629161c46d75c54c4a1bfd59a59a7c5c37059fa4d853dddbee0e0b02fb42428080c022f10966abd56b637ac375a07f318da4fd2e53 SHA512 718b6ea53d6cd6ed795d446b13d3726d5db673af9555a8eb6294fc2e887cafe18f76e63aaa1bbd627add564b1d5c760e70b96d71d0cf5b8b27c1dcbeb579d36e
diff --git a/dev-python/gst-python/files/gst-python-1.26.11-pygobject-3.52.patch b/dev-python/gst-python/files/gst-python-1.26.11-pygobject-3.52.patch
new file mode 100644
index 000000000000..a24465cb99ba
--- /dev/null
+++ b/dev-python/gst-python/files/gst-python-1.26.11-pygobject-3.52.patch
@@ -0,0 +1,176 @@
+https://bugs.gentoo.org/957940
+https://gitlab.freedesktop.org/gstreamer/gstreamer/-/commit/47874799e328f2b4f081b623efe9d0ae059d0fd8
+
+From 47874799e328f2b4f081b623efe9d0ae059d0fd8 Mon Sep 17 00:00:00 2001
+From: Thibault Saunier <tsaunier@igalia.com>
+Date: Sun, 28 Sep 2025 09:48:05 -0300
+Subject: [PATCH] ges: Move OTIO formatter to a separate Python plugin
+
+The GES OpenTimelineIO formatter was previously embedded directly in
+libges using GLib resources, this was all a bit complex for not much
+benefit, moreover it started to crash recently.
+
+Move the formatter to a standalone Python plugin that will be loaded
+through the standard GStreamer Python plugin infrastructure making
+it all more simple.
+
+The formatter is now located in subprojects/gst-python/plugins/ges/
+and will only be loaded when the Python plugin is available and
+opentimelineio is installed.
+
+Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4676
+
+Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9759>
+--- a/meson.build
++++ b/meson.build
+@@ -128,7 +128,8 @@ configinc = include_directories('.')
+ meson.add_dist_script('scripts/gen-changelog.py', meson.project_name(), '1.26.0', meson.project_version())
+
+ pkgconfig = import('pkgconfig')
+-plugins_install_dir = join_paths(libdir, 'gstreamer-1.0')
++plugins_install_dir = join_paths(get_option('libdir'), 'gstreamer-1.0')
++python_plugin_install_dir = join_paths(plugins_install_dir, 'python')
+ plugins_pkgconfig_install_dir = join_paths(plugins_install_dir, 'pkgconfig')
+ if get_option('default_library') == 'shared'
+ # If we don't build static plugins there is no need to generate pc files
+@@ -139,6 +140,7 @@ subdir('gi')
+ if not get_option('plugin').disabled()
+ if get_option('default_library') != 'static'
+ subdir('plugin')
++ subdir('plugins')
+ else
+ warning('Python plugin not supported with `static` builds yet.')
+ endif
+--- a/plugin/meson.build
++++ b/plugin/meson.build
+@@ -3,7 +3,7 @@ gstpython = library('gstpython',
+ include_directories : [configinc],
+ dependencies : [gst_dep, pygobject_dep, gstbase_dep, python_embed_dep, gmodule_dep, libdl],
+ install : true,
+- install_dir : '@0@/gstreamer-1.0'.format(get_option('libdir')),
++ install_dir : plugins_install_dir,
+ )
+ plugins = [gstpython]
+ # XXX: Generate a pc file for this plugin? Can gstpython be statically linked?
+--- /dev/null
++++ b/plugins/ges/meson.build
+@@ -0,0 +1,4 @@
++install_data(
++ 'python/gesotioformatter.py',
++ install_dir: python_plugin_install_dir
++)
+--- /dev/null
++++ b/plugins/ges/python/gesotioformatter.py
+@@ -0,0 +1,105 @@
++#!/usr/bin/env python
++# -*- Mode: Python -*-
++# vi:si:et:sw=4:sts=4:ts=4
++#
++# Copyright (C) 2019 Igalia S.L
++# Authors:
++# Thibault Saunier <tsaunier@igalia.com>
++#
++
++import sys
++
++import gi
++import tempfile
++
++try:
++ gi.require_version("GES", "1.0")
++ gi.require_version("Gst", "1.0")
++
++ from gi.repository import GObject
++ from gi.repository import Gst
++ Gst.init(None)
++ from gi.repository import GES
++ from gi.repository import GLib
++ from collections import OrderedDict
++
++ import opentimelineio as otio
++ otio.adapters.from_name('xges')
++
++ class GESOtioFormatter(GES.Formatter):
++ def do_save_to_uri(self, timeline, uri, overwrite):
++ if not Gst.uri_is_valid(uri) or Gst.uri_get_protocol(uri) != "file":
++ Gst.error("Protocol not supported for file: %s" % uri)
++ return False
++
++ with tempfile.NamedTemporaryFile(suffix=".xges") as tmpxges:
++ timeline.get_asset().save(timeline, "file://" + tmpxges.name, None, overwrite)
++
++ linker = otio.media_linker.MediaLinkingPolicy.ForceDefaultLinker
++ otio_timeline = otio.adapters.read_from_file(tmpxges.name, "xges", media_linker_name=linker)
++ location = Gst.uri_get_location(uri)
++ out_adapter = otio.adapters.from_filepath(location)
++ otio.adapters.write_to_file(otio_timeline, Gst.uri_get_location(uri), out_adapter.name)
++
++ return True
++
++ def do_can_load_uri(self, uri):
++ try:
++ if not Gst.uri_is_valid(uri) or Gst.uri_get_protocol(uri) != "file":
++ return False
++ except GLib.Error as e:
++ Gst.error(str(e))
++ return False
++
++ if uri.endswith(".xges"):
++ return False
++
++ try:
++ return otio.adapters.from_filepath(Gst.uri_get_location(uri)) is not None
++ except Exception as e:
++ Gst.info("Could not load %s -> %s" % (uri, e))
++ return False
++
++ def do_load_from_uri(self, timeline, uri):
++ location = Gst.uri_get_location(uri)
++ in_adapter = otio.adapters.from_filepath(location)
++ assert (in_adapter) # can_load_uri should have ensured it is loadable
++
++ linker = otio.media_linker.MediaLinkingPolicy.ForceDefaultLinker
++ otio_timeline = otio.adapters.read_from_file(
++ location,
++ in_adapter.name,
++ media_linker_name=linker
++ )
++
++ with tempfile.NamedTemporaryFile(suffix=".xges") as tmpxges:
++ otio.adapters.write_to_file(otio_timeline, tmpxges.name, "xges")
++ formatter = GES.Formatter.get_default().extract()
++ timeline.get_asset().add_formatter(formatter)
++ return formatter.load_from_uri(timeline, "file://" + tmpxges.name)
++
++ GObject.type_register(GESOtioFormatter)
++ known_extensions_mimetype_map = [
++ ("otio", "xml", "fcpxml"),
++ ("application/vnd.pixar.opentimelineio+json", "application/vnd.apple-xmeml+xml", "application/vnd.apple-fcp+xml")
++ ]
++
++ extensions = []
++ for adapter in otio.plugins.ActiveManifest().adapters:
++ if adapter.name != 'xges':
++ extensions.extend(adapter.suffixes)
++
++ extensions_mimetype_map = [[], []]
++ for i, ext in enumerate(known_extensions_mimetype_map[0]):
++ if ext in extensions:
++ extensions_mimetype_map[0].append(ext)
++ extensions_mimetype_map[1].append(known_extensions_mimetype_map[1][i])
++ extensions.remove(ext)
++ extensions_mimetype_map[0].extend(extensions)
++
++ GES.FormatterClass.register_metas(GESOtioFormatter, "otioformatter",
++ "GES Formatter using OpenTimelineIO",
++ ','.join(extensions_mimetype_map[0]),
++ ';'.join(extensions_mimetype_map[1]), 0.1, Gst.Rank.SECONDARY)
++except (ImportError, TypeError) as e:
++ Gst.warning(f"opentimelineio module not found, GES OTIO formatter will not be available: {e}")
+--- /dev/null
++++ b/subprojects/gst-python/plugins/meson.build
+@@ -0,0 +1 @@
++subdir('ges')
+--
+GitLab
+
diff --git a/dev-python/gst-python/files/gst-python-1.26.11-skip-test.patch b/dev-python/gst-python/files/gst-python-1.26.11-skip-test.patch
new file mode 100644
index 000000000000..00928d30d64f
--- /dev/null
+++ b/dev-python/gst-python/files/gst-python-1.26.11-skip-test.patch
@@ -0,0 +1,30 @@
+https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4772#note_3291563
+
+Description: disable tests that are broken since pygobject 3.54
+ Since pygobject 3.54, the tests are broken. With 1.28.0 on the horizon,
+ the choice is to disable the broken tests to get the version release
+ synchronised again.
+Author: Marc Leeman <marc.leeman@gmail.com>
+Forwarded: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4772
+Last-Update: 2026-01-16
+
+Index: gst-python1.0/testsuite/test_gst_init.py
+===================================================================
+--- gst-python1.0.orig/testsuite/test_gst_init.py
++++ gst-python1.0/testsuite/test_gst_init.py
+@@ -30,6 +30,7 @@ overrides_hack
+
+
+ class TestNotInitialized(TestCase):
++ @unittest.skip("Broken since pygobject 3.54")
+ def testNotInitialized(self):
+ if sys.version_info >= (3, 0):
+ assert_type = Gst.NotInitialized
+@@ -45,6 +46,7 @@ class TestNotInitialized(TestCase):
+ with self.assertRaises(assert_type):
+ Gst.ElementFactory.make("identity", None)
+
++ @unittest.skip("Broken since pygobject 3.54")
+ def testNotDeinitialized(self):
+ Gst.init(None)
+
diff --git a/dev-python/gst-python/gst-python-1.26.11.ebuild b/dev-python/gst-python/gst-python-1.26.11.ebuild
new file mode 100644
index 000000000000..51aaeb874adb
--- /dev/null
+++ b/dev-python/gst-python/gst-python-1.26.11.ebuild
@@ -0,0 +1,76 @@
+# Copyright 1999-2026 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+
+PYTHON_COMPAT=( python3_{10..14} )
+
+inherit meson python-r1 verify-sig xdg-utils
+
+DESCRIPTION="A Python Interface to GStreamer"
+HOMEPAGE="https://gstreamer.freedesktop.org/"
+SRC_URI="
+ https://gstreamer.freedesktop.org/src/${PN}/${P}.tar.xz
+ verify-sig? ( https://gstreamer.freedesktop.org/src/${PN}/${P}.tar.xz.asc )
+"
+
+LICENSE="LGPL-2+"
+SLOT="1.0"
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~loong ~ppc ~ppc64 ~riscv ~sparc ~x86"
+REQUIRED_USE="${PYTHON_REQUIRED_USE}"
+
+RDEPEND="${PYTHON_DEPS}
+ >=media-libs/gstreamer-${PV}:1.0[introspection]
+ >=media-libs/gst-plugins-bad-${PV}:1.0[introspection]
+ >=media-libs/gst-plugins-base-${PV}:1.0[introspection]
+ >=dev-python/pygobject-3.8:3[${PYTHON_USEDEP}]
+"
+DEPEND="${RDEPEND}"
+BDEPEND="
+ virtual/pkgconfig
+ verify-sig? ( sec-keys/openpgp-keys-tpm )
+"
+
+VERIFY_SIG_OPENPGP_KEY_PATH=/usr/share/openpgp-keys/tpm.asc
+
+PATCHES=(
+ "${FILESDIR}"/gst-python-1.26.11-pygobject-3.52.patch
+ "${FILESDIR}"/gst-python-1.26.11-skip-test.patch
+)
+
+src_prepare() {
+ default
+
+ # Avoid building & testing plugin - it must NOT be multi-python as gst-inspect will map in all libpython.so versions
+ # and crash or behave mysteriously.
+ # Python plugin support is of limited use (GIL gets in the way). If it's ever requested or needed, it should be a
+ # separate python-single-r1 media-plugins/gst-plugins-python package that only builds the plugin directory.
+ sed -e '/subdir.*plugin/d' -i meson.build || die
+ sed -e '/test_plugin.py/d' -i testsuite/meson.build || die
+
+ xdg_environment_reset
+}
+
+src_configure() {
+ configuring() {
+ meson_src_configure \
+ -Dpython="${EPYTHON}"
+ }
+ python_foreach_impl configuring
+}
+
+src_compile() {
+ python_foreach_impl meson_src_compile
+}
+
+src_test() {
+ python_foreach_impl meson_src_test
+}
+
+src_install() {
+ installing() {
+ meson_src_install
+ python_optimize
+ }
+ python_foreach_impl installing
+}