Open ju1ius opened 3 years ago
From what I can see in the GIR file, GstElementClass is a gtype struct that isn't normally meant to be exposed in bindings (IIUC). We're currently filtering those out here:
g_struct_info_is_gtype_struct ()
gboolean
g_struct_info_is_gtype_struct (GIStructInfo *info);
Return true if this structure represents the "class structure" for some GObject or GInterface. This function is mainly useful to hide this kind of structure from generated public APIs.
Can you give an example use-case that you have for them? I'd prefer not to expose them, but if it's absolutely necessary so be it.
Can you give an example use-case that you have for them?
For example gst_element_class_add_pad_template
is required to implement custom Gstreamer bins with dynamic proxy pads... More generally I believe these kinds of methods are required to implement custom Gstreamer plugins in the host language.
Theses methods are available in the python bindings. In particular, gst_element_class_add_pad_template
is made available both as an instance method:
from gi.repository import Gst
class MyBin(Gst.Bin):
def __init__(self):
super().__init__(self)
self._element = Gst.ElementFactory.make('someelement')
self.add(self._element)
tpl = Gst.PadTemplate.new(
'audio_%u',
Gst.PadDirection.SRC,
Gst.PadPresence.REQUEST,
Gst.Caps.from_string('audio/x-raw'),
)
self.add_pad_template(tpl)
def do_request_new_pad(self, tpl: Gst.PadTemplate, name: str, caps: Gst.Caps):
target = self._element.get_request_pad('src_%u')
ghost_pad: Gst.GhostPad = Gst.GhostPad.new_from_template(name, target, tpl)
self.add_pad(ghost_pad)
return ghost_pad
and through the __gsttemplates__
class field mecanism:
from gi.repository import Gst
class MyBin(Gst.Bin):
__gsttemplates__ = (
Gst.PadTemplate.new(
'audio_%u',
Gst.PadDirection.SRC,
Gst.PadPresence.REQUEST,
Gst.Caps.from_string('audio/x-raw'),
),
)
def __init__(self):
super().__init__(self)
self._element = Gst.ElementFactory.make('someelement')
self.add(self._element)
def do_request_new_pad(self, tpl: Gst.PadTemplate, name: str, caps: Gst.Caps):
target = self._element.get_request_pad('src_%u')
ghost_pad: Gst.GhostPad = Gst.GhostPad.new_from_template(name, target, tpl)
self.add_pad(ghost_pad)
return ghost_pad
Oh ok, pygobject approach seems to be more involved than I would like it to be, they probably have some custom code just for GST :/
Do you happen to have a minimal example in C showing what you're trying to do? I can work from that and add the missing parts. Maybe just removing the if-guard will work but I'm not sure.
Oh ok, pygobject approach seems to be more involved than I would like it to be, they probably have some custom code just for GST :/
No, the Gst.Element.add_pad_template()
method is exposed automatically by pygobject, and it seems to be the standard behavior since it is also exposed by Vala...
The __gsttemplates__
mechanism is an override added by the gst-python package (reference).
So, I just wrote script to inspect the class struct methods, and it appears they are all exposed in vala. Here's the output for the Gtk 3.0 module:
method: find_cell_property
symbol: gtk_cell_area_class_find_cell_property
exposed by node-gtk: no
method: install_cell_property
symbol: gtk_cell_area_class_install_cell_property
exposed by node-gtk: no
method: list_cell_properties
symbol: gtk_cell_area_class_list_cell_properties
exposed by node-gtk: no
method: set_accessible_type
symbol: gtk_cell_renderer_class_set_accessible_type
exposed by node-gtk: no
method: find_child_property
symbol: gtk_container_class_find_child_property
exposed by node-gtk: no
method: handle_border_width
symbol: gtk_container_class_handle_border_width
exposed by node-gtk: no
method: install_child_properties
symbol: gtk_container_class_install_child_properties
exposed by node-gtk: no
method: install_child_property
symbol: gtk_container_class_install_child_property
exposed by node-gtk: no
method: list_child_properties
symbol: gtk_container_class_list_child_properties
exposed by node-gtk: no
method: bind_template_callback_full
symbol: gtk_widget_class_bind_template_callback_full
exposed by node-gtk: no
method: bind_template_child_full
symbol: gtk_widget_class_bind_template_child_full
exposed by node-gtk: no
method: find_style_property
symbol: gtk_widget_class_find_style_property
exposed by node-gtk: no
method: get_css_name
symbol: gtk_widget_class_get_css_name
exposed by node-gtk: no
method: install_style_property
symbol: gtk_widget_class_install_style_property
exposed by node-gtk: no
method: list_style_properties
symbol: gtk_widget_class_list_style_properties
exposed by node-gtk: no
method: set_accessible_role
symbol: gtk_widget_class_set_accessible_role
exposed by node-gtk: no
method: set_accessible_type
symbol: gtk_widget_class_set_accessible_type
exposed by node-gtk: no
method: set_connect_func
symbol: gtk_widget_class_set_connect_func
exposed by node-gtk: no
method: set_css_name
symbol: gtk_widget_class_set_css_name
exposed by node-gtk: no
method: set_template
symbol: gtk_widget_class_set_template
exposed by node-gtk: no
method: set_template_from_resource
symbol: gtk_widget_class_set_template_from_resource
exposed by node-gtk: no
And here's the output for the Gst-1.0 module:
method: add_metadata
symbol: gst_device_provider_class_add_metadata
exposed by node-gtk: no
method: add_static_metadata
symbol: gst_device_provider_class_add_static_metadata
exposed by node-gtk: no
method: get_metadata
symbol: gst_device_provider_class_get_metadata
exposed by node-gtk: no
method: set_metadata
symbol: gst_device_provider_class_set_metadata
exposed by node-gtk: no
method: set_static_metadata
symbol: gst_device_provider_class_set_static_metadata
exposed by node-gtk: no
method: add_metadata
symbol: gst_element_class_add_metadata
exposed by node-gtk: no
method: add_pad_template
symbol: gst_element_class_add_pad_template
exposed by node-gtk: no
method: add_static_metadata
symbol: gst_element_class_add_static_metadata
exposed by node-gtk: no
method: add_static_pad_template
symbol: gst_element_class_add_static_pad_template
exposed by node-gtk: no
method: add_static_pad_template_with_gtype
symbol: gst_element_class_add_static_pad_template_with_gtype
exposed by node-gtk: no
method: get_metadata
symbol: gst_element_class_get_metadata
exposed by node-gtk: no
method: get_pad_template
symbol: gst_element_class_get_pad_template
exposed by node-gtk: no
method: get_pad_template_list
symbol: gst_element_class_get_pad_template_list
exposed by node-gtk: no
method: set_metadata
symbol: gst_element_class_set_metadata
exposed by node-gtk: no
method: set_static_metadata
symbol: gst_element_class_set_static_metadata
exposed by node-gtk: no
Output for the GObject 2.0 module:
method: find_property
symbol: g_object_class_find_property
exposed by node-gtk: no
method: install_properties
symbol: g_object_class_install_properties
exposed by node-gtk: no
method: install_property
symbol: g_object_class_install_property
exposed by node-gtk: no
method: list_properties
symbol: g_object_class_list_properties
exposed by node-gtk: no
method: override_property
symbol: g_object_class_override_property
exposed by node-gtk: no
Using PyGObject:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
btn = Gtk.Button()
print(btn.list_properties())
[<GParamString 'action-name'>,
<GParamVariant 'action-target'>,
<GParamObject 'related-action'>,
<GParamBoolean 'use-action-appearance'>,
<GParamString 'name'>,
<GParamObject 'parent'>,
<GParamInt 'width-request'>,
<GParamInt 'height-request'>,
<GParamBoolean 'visible'>,
<GParamBoolean 'sensitive'>,
<GParamBoolean 'app-paintable'>,
<GParamBoolean 'can-focus'>,
<GParamBoolean 'has-focus'>,
<GParamBoolean 'is-focus'>,
<GParamBoolean 'focus-on-click'>,
<GParamBoolean 'can-default'>,
<GParamBoolean 'has-default'>,
<GParamBoolean 'receives-default'>,
<GParamBoolean 'composite-child'>,
<GParamObject 'style'>,
<GParamFlags 'events'>,
<GParamBoolean 'no-show-all'>,
<GParamBoolean 'has-tooltip'>,
<GParamString 'tooltip-markup'>,
<GParamString 'tooltip-text'>,
<GParamObject 'window'>,
<GParamDouble 'opacity'>,
<GParamBoolean 'double-buffered'>,
<GParamEnum 'halign'>,
<GParamEnum 'valign'>,
<GParamInt 'margin-left'>,
<GParamInt 'margin-right'>,
<GParamInt 'margin-start'>,
<GParamInt 'margin-end'>,
<GParamInt 'margin-top'>,
<GParamInt 'margin-bottom'>,
<GParamInt 'margin'>,
<GParamBoolean 'hexpand'>,
<GParamBoolean 'vexpand'>,
<GParamBoolean 'hexpand-set'>,
<GParamBoolean 'vexpand-set'>,
<GParamBoolean 'expand'>,
<GParamInt 'scale-factor'>,
<GParamUInt 'border-width'>,
<GParamEnum 'resize-mode'>,
<GParamObject 'child'>,
<GParamString 'label'>,
<GParamObject 'image'>,
<GParamEnum 'relief'>,
<GParamBoolean 'use-underline'>,
<GParamBoolean 'use-stock'>,
<GParamFloat 'xalign'>,
<GParamFloat 'yalign'>,
<GParamEnum 'image-position'>,
<GParamBoolean 'always-show-image'>]
Using GJS:
imports.gi.versions.GObject = '2.0'
imports.gi.versions.Gtk = '3.0'
const GObject = imports.gi.GObject
const Gtk = imports.gi.Gtk
const btn = new Gtk.Button()
const propNames = GObject.Object.list_properties.call(btn).map(prop => prop.name)
print(propNames)
action-name,action-target,related-action,use-action-appearance,name,parent,width-request,height-request,visible,sensitive,app-paintable,can-focus,has-focus,is-focus,focus-on-click,can-default,has-default,receives-default,composite-child,style,events,no-show-all,has-tooltip,tooltip-markup,tooltip-text,window,opacity,double-buffered,halign,valign,margin-left,margin-right,margin-start,margin-end,margin-top,margin-bottom,margin,hexpand,vexpand,hexpand-set,vexpand-set,expand,scale-factor,border-width,resize-mode,child,label,image,relief,use-underline,use-stock,xalign,yalign,image-position,always-show-image
Using node-gtk:
const gi = require('node-gtk')
const Gtk = gi.require('Gtk', '3.0')
Gtk.init()
const btn = new Gtk.Button()
console.log(GObject.Object.listProperties.call(btn)) // Uncaught TypeError: GObject.Object.listProperties is not a function
console.log(btn.listProperties()) // Uncaught TypeError: btn.listProperties is not a function
a gtype struct that isn't normally meant to be exposed in bindings
In the light of the previous comments, I think you might want to reassess this statement (and thus maybe reopen https://github.com/romgrk/node-gtk/issues/100 ?). It seems to me that, even if the class structs themselves are not publicly exposed, at least their methods should be made available on the corresponding class constructor or prototype. For the class struct fields, I don't know but it might be worth to investigate.
I'd be very interested in access to g_object_class_list_properties
as well. My use-case is like gst-inspect (see this line): I'm working with gstreamer and need to check which properties a specific gst element has. In different versions of gstreamer, these elements expose different properties. So in order to avoid an exception when trying to build a gstreamer pipeline with that element that uses a property that doesn't exist, I want to first check. I can probably work around it for now by using getProperty(NAME) !== undefined
but that's kludgy and makes discovery very awkward.
I found GObject.Object.interfaceListProperties
but g_object_class_list_properties
doesn't seem to be bound, not sure why. We might be missing a type of functions to add, it's listed under "class methods" in the docs, unlike g_object_interface_list_properties
which is listed under "functions". I tried looking into it a bit but I don't have enough time at the moment, I might need to add a note that the repository doesn't receive regular maintenance.
I don't think it would be very hard to fix, the entry point to setup GIR entries is here if someone wants to have a go at it.
Hi,
It seems the gst_elementclass* methods are missing (i.e. gst_element_class_add_pad_template):
Btw, congrats for this ambitious project ! 👍🏻