GNOME Bugzilla – Bug 686572
metadata is not set for inherited elements in python using pygi
Last modified: 2013-12-24 15:42:21 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.
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.
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?
There's also bug #685218
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.
Moving to gst-python then. Could you retitle the bug to say what's needed exactly?
__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'))