Add GInterface

Original commit message from CVS:
Add GInterface
This commit is contained in:
Ronald S. Bultje 2003-09-04 21:03:12 +00:00
parent b79680d0b2
commit 8ff69a6cc8

View file

@ -47,7 +47,7 @@ Obviously, a pipeline can be a fallback for an interface. Imagine
that we're looking for an audio sink that exposes a mixer, but our that we're looking for an audio sink that exposes a mixer, but our
fakesink audio output doesn't ("I wonder why"). We could then create fakesink audio output doesn't ("I wonder why"). We could then create
a pipeline with the volume element in it to "fake" a mixer. Ideally, a pipeline with the volume element in it to "fake" a mixer. Ideally,
the volume element would implement a mixer itself. the volume element would implement a mixer interface itself.
How are we going to do that in programmatic way? We currently use How are we going to do that in programmatic way? We currently use
properties. Their huge advantage is that we do not need to care properties. Their huge advantage is that we do not need to care
@ -65,16 +65,12 @@ the idea of embedding interfaces (dynamically, of course) in the
GstElement object. Think of an object being able to register an GstElement object. Think of an object being able to register an
indefinate number of interfaces per object instance, and a client indefinate number of interfaces per object instance, and a client
application could then enumerate interfaces and instantiate one. application could then enumerate interfaces and instantiate one.
The API would then look like this: Glib gives us GInterface for this purpose. The disadvantage of
this is that it's on a per-class basis, not a per-instance basis.
void gst_element_register_interface (GstElement *element, This is a problem in case of elements where it depends on several
const gchar *name, properties whether it supports an interface or not. This can be
GstInterfaceFunc func); solved by simply making one generic virtual function "supported ()"
in a generic derived object of GInterface (GstInterface?).
const GList *gst_element_list_interfaces (GstElement *element);
GstInterface *gst_element_get_interface (GstElement *element,
const gchar *name);
GstInterface is then a generic thing that is inherited by specific GstInterface is then a generic thing that is inherited by specific
interfaces (see examples). Obviously, the client will need to know interfaces (see examples). Obviously, the client will need to know
@ -89,19 +85,12 @@ useful currently, so this'd make them a lot more interesting).
These interfaces inherit from GstInterface. The functions that These interfaces inherit from GstInterface. The functions that
are needed, can be provided through a class object. The element is are needed, can be provided through a class object. The element is
then responsible for storing variables and so on. gstvideo/audio then responsible for storing variables and so on. gstvideo/audio
provides wrapper functions for the class functions. provides wrapper functions for the class functions. That's also how
glib suggest us to use GInterfaces.
For the plugin, it's then as simple as can be. The class_init Plugin and application then handle and retrieve interfaces as
function sets the virtual functions in the interface class object, documented in the glib documentation, which is available at:
and the instance_init function registers the object per created http://www.gnome.org/~mathieu/gobject/main.html
element. The get_interface() handler refs this interface and
returns it. The application unrefs it when it's done. The
appropriate functions will be called by the application when it
thinks it needs to. Perfectly simple!
For applictions, it's even simpler. Request an interface and use
it as documented. When you're done, unref it. It's just like
elements: simple!
So the most important part left is to document the interfaces So the most important part left is to document the interfaces
and make sure all elements exporting them work equally. For this, and make sure all elements exporting them work equally. For this,
@ -111,13 +100,41 @@ I'll give two examples.
=========== ===========
typedef struct _GstInterface { typedef struct _GstInterface {
GObject object; /* dummy */
} GstInterface; } GstInterface;
typedef struct _GstInterfaceClass { typedef struct _GstInterfaceClass {
GObjectClass klass; GTypeInterface parent;
gboolean (* supported) (GstInterface *iface);
} GstInterfaceClass; } GstInterfaceClass;
There would probably be a convenience function that checks
a specific interface's implementation (glib allows for this)
and checks for ->supported () to be set and to return TRUE:
gboolean
gst_element_implements_interface (GstElement *element,
GType iface_type)
{
if (G_TYPE_CHECK_INSTANCE_TYPE (G_OBJECT (element),
type)) {
GstInterface *iface;
GstInterfaceClass *ifclass;
iface = G_TYPE_CHECK_INSTANCE_CAST (G_OBJECT (element),
type, GstInterface)
ifclass = GST_INTERFACE_GET_CLASS (iface);
if (ifclass->supported != NULL &&
ifclass->supported (iface) == TRUE) {
return TRUE;
}
}
return FALSE;
}
4a) mixer 4a) mixer
--------- ---------
A mixer is a way of controlling volume and input/output channels. A mixer is a way of controlling volume and input/output channels.
@ -186,50 +203,20 @@ typedef struct _GstOssMixerClass {
[..] [..]
static void
gst_ossmixer_class_init (GstOssMixerClass *klass)
{
GstMixerClass *mix_klass = (GstMixerClass *) klass;
[.. set virtual functions to their oss/mixer counterparts here ..]
}
[..]
static void static void
gst_osssrc_init (GstOssSrc *osssrc) gst_osssrc_init (GstOssSrc *osssrc)
{ {
GstOssMixer *mixer = GST_OSS_MIXER (osssrc);
[..] [..]
gst_element_register_interface (GST_ELEMENT (osssrc), mixer->element = GST_ELEMENT (osssrc);
"mixer",
gst_osssrc_get_interface);
[..] [..]
} }
static GstInterface * The rest is done automatically, as described in the already-
gst_osssrc_get_interface (GstElement *element, mentioned glib documentation for GInterface.
const gchar *name)
{
GstOssMixer *mixer;
g_assert (strcmp (name, "mixer") == 0); We could add a pointer to the file descriptor in the
osssrc/osssink, too, and we'd have full access to the device.
mixer = g_object_new (GST_TYPE_OSS_MIXER, NULL);
mixer->element = element;
[..]
return (GstInterface *) mixer;
}
And yes, that's quite a piece of code, but you didn't expect
that we could make a mixer in five lines of code, did you?
However, applications now *can*!
There might be some refcounting issues here: get_interface ()
should ref () the element, and we should set a mixer dispose
handler to unref () it again. Then, too, we could add a pointer
to the file descriptor in the osssrc/osssink, too, and we'd
have full access to the device.
However, that's implementation. Let's first worry about general However, that's implementation. Let's first worry about general
design. design.