After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 686572 - metadata is not set for inherited elements in python using pygi
metadata is not set for inherited elements in python using pygi
Status: RESOLVED NOTABUG
Product: GStreamer
Classification: Platform
Component: gst-python
1.x
Other Linux
: Normal normal
: git master
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2012-10-21 12:34 UTC by Jan Schole
Modified: 2013-12-24 15:42 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Jan Schole 2012-10-21 12:34:25 UTC
I'm using the GObject introspection system to write a filter element in python3 for GStreamer 1.0.1. Apparantly using __gstdetails__ to set the metadata in the class does not work for PyGI anymore and I haven't found an alternative. The result is, that the element can not be registered, because it has an invalid 'long-name'.

The following code reproduces the error. It contains a passthrough element inherited from GstBase.BaseTransform. Here the registration fails.

#!/usr/bin/python3

import gi
gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gst

GObject.threads_init()
Gst.init(None)

from gi.repository import GstBase

class TestFilter(GstBase.BaseTransform):
    
    __gstdetails__ = (
        'Test Filter',
        'Generic',
        'Passthrough for all buffers',
        'jan'
    )

    __gsttemplates__ = (
        Gst.PadTemplate.new('src', Gst.PadDirection.SRC, Gst.PadPresence.ALWAYS, Gst.caps_from_string('ANY')),
        Gst.PadTemplate.new('sink', Gst.PadDirection.SINK, Gst.PadPresence.ALWAYS, Gst.caps_from_string('ANY'))
    )
    
    def __init__(self):
        GstBase.BaseTransform.__init__(self)
        self.set_passthrough(True)
    
    def transform_ip(self, buf):
        print('I am called!')
        return gst.FLOW_OK

def plugin_init(plugin, userarg):
    TestFilterType = GObject.type_register(TestFilter)
    res = Gst.Element.register(plugin, 'testfilter', 0, TestFilterType)
    print('Registered?', res)
    return True

version = Gst.version()
Gst.Plugin.register_static_full(
    version[0],
    version[1],
    'testfilter',
    'passthrough element',
    plugin_init,
    '1.0',
    'LGPL',
    'testfilter',
    'testfilter',
    'http://',
    None
)

output:
>./plugin-test.py

(python3:24992): GStreamer-WARNING **: Element factory metadata for 'testfilter' has no valid long-name field
Registered? False

In the second example the element is inherited from Gst.Bin. Here the registration works, but a look at the 'long-name' shows, that the metadata of the Gst.Bin has been used instead of the intended one, supplied in the code:

#!/usr/bin/python3

import gi
gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gst

GObject.threads_init()
Gst.init(None)

class TestFilter(Gst.Bin):
    
    __gstdetails__ = (
        'Test Filter',
        'Generic',
        'Passthrough for all buffers',
        'jan'
    )

    __gsttemplates__ = (
        Gst.PadTemplate.new('src', Gst.PadDirection.SRC, Gst.PadPresence.ALWAYS, Gst.caps_from_string('ANY')),
        Gst.PadTemplate.new('sink', Gst.PadDirection.SINK, Gst.PadPresence.ALWAYS, Gst.caps_from_string('ANY'))
    )
    
    def __init__(self):
        Gst.Bin.__init__(self)
    
def plugin_init(plugin, userarg):
    TestFilterType = GObject.type_register(TestFilter)
    res = Gst.Element.register(plugin, 'testfilter', 0, TestFilterType)
    print('Registered?', res)
    return True

version = Gst.version()
Gst.Plugin.register_static_full(
    version[0],
    version[1],
    'testfilter',
    'passthrough element',
    plugin_init,
    '1.0',
    'LGPL',
    'testfilter',
    'testfilter',
    'http://',
    None
)

print(Gst.ElementFactory.find('testfilter').get_metadata('long-name'))


output:
>./plugin-bin-test.py
Registered? True
Generic bin

Is there some new way to set the metadata or is it missing? All tutorials I've found are examples of the second kind, where simply the metadata of the Gst.Bin is used.
Comment 1 Jason Gerard DeRose 2012-12-20 12:53:08 UTC
I can confirm this. I have a Gst.Bin subclass that seemingly works:

http://bazaar.launchpad.net/~jderose/+junk/gst-examples/view/head:/plugin-1.0

(Although I didn't realize the long name wasn't properly being set.) But when I tried something similar with a GstBase.BaseTransform subclass, I get the same "has no valid long-name field" error.

I'd really like to see comprehensive Python tests for all the API that should be accessible though PyGI, both to make sure stuff continues to work, but also to provide at least one example of how to use the API from PyGI.
Comment 2 Tim-Philipp Müller 2013-03-03 20:31:19 UTC
I don't know if this is a bug in GStreamer, it seems like a py-gi issue to me.

Apparently this can be hacked around though (courtesy of Alessandro):

from gi.repository import GObject, Gst
Gst.init(None)

def get_element_class(klass):
    element_class = GObject.type_class_peek(klass.__gtype__)
    element_class.__class__ = Gst.ElementClass
    return element_class

class E(Gst.Element):
    pass

get_element_class(E).set_metadata('longname', 'classification', 'description', 'author')
E.register(None, 'foo', Gst.Rank.NONE, E.__gtype__)

print Gst.ElementFactory.make('foo')


Move as enhancement to gst-python or bug to py-gi/introspection?
Comment 3 Tim-Philipp Müller 2013-03-03 21:05:22 UTC
There's also bug #685218
Comment 4 Jan Schole 2013-03-11 16:28:45 UTC
It seems to me, that the overrides in the current GIT code of gst-python already solve the specific problem, that I reported. It would still be nice to have a method to access the element_class like Alessandros, though.
Comment 5 Tim-Philipp Müller 2013-11-24 18:55:46 UTC
Moving to gst-python then. Could you retitle the bug to say what's needed exactly?
Comment 6 Thibault Saunier 2013-12-24 15:41:58 UTC
__gstdetails__ does not exist anymore, it is now called __gstmetadata__.

Make sure that latest gst-python is present and properly set up.

The following code does work:

#!/usr/bin/python

from gi.repository import GObject, Gst

GObject.threads_init()
Gst.init(None)

class TestFilter(Gst.Bin):

    __gstmetadata__ = (
        'Test Filter',
        'Generic',
        'Passthrough for all buffers',
        'jan'
    )

    __gsttemplates__ = (
        Gst.PadTemplate.new('src', Gst.PadDirection.SRC,
        Gst.PadPresence.ALWAYS, Gst.caps_from_string('ANY')),
                Gst.PadTemplate.new('sink', Gst.PadDirection.SINK,
        Gst.PadPresence.ALWAYS, Gst.caps_from_string('ANY'))
    )

    def __init__(self):
        Gst.Bin.__init__(self)

def plugin_init(plugin, userarg):
    TestFilterType = GObject.type_register(TestFilter)
    res = Gst.Element.register(plugin, 'testfilter', 0, TestFilterType)
    print('Registered?', res)
    return True

version = Gst.version()
Gst.Plugin.register_static_full(
    version[0],
    version[1],
    'testfilter',
    'passthrough element',
    plugin_init,
    '1.0',
    'LGPL',
    'testfilter',
    'testfilter',
    'http://',
    None
)

print(Gst.ElementFactory.find('testfilter').get_metadata('long-name'))