summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>2003-08-28 20:48:54 +0000
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>2003-08-28 20:48:54 +0000
commitae97ea085fe9d62fbaa4812f7070ddb751f30ae9 (patch)
treec5a28c8ec553dbd63b8294ba731dfa7b9c3bb184
parent7e6ea67d56bfe26494806c28c84312f5ad5fa277 (diff)
downloadgstreamer-ae97ea085fe9d62fbaa4812f7070ddb751f30ae9.tar.gz
A generic interface proposal
Original commit message from CVS: A generic interface proposal
-rw-r--r--docs/random/interfaces240
1 files changed, 240 insertions, 0 deletions
diff --git a/docs/random/interfaces b/docs/random/interfaces
new file mode 100644
index 0000000000..0fc80094cb
--- /dev/null
+++ b/docs/random/interfaces
@@ -0,0 +1,240 @@
+INTERFACES & ELEMENTS
+---------------------
+
+1) Introduction
+===============
+Interfaces are descriptions on how to handle an object, without actually
+implementing the object. This allows for multiple objects to be instantiated
+based on this interface. Each of them can then be handled equally by an
+application.
+Glib, apparently (unchecked), has a way of creating interfaces, probably
+by means of a class struct without actually defining the object. The object,
+then, does not define a class and these two add up. Benjamin knows more
+about interfaces, I didn't study interfaces & glib too deeply, yet. I know
+them just from Java.
+Interfaces are cool! It allows for some sort of random element creation
+without needing to link to the implementation. This is similar to how
+GStreamer currently handles media plugins. GStreamer itself could be seen
+as an interface too, in that respect.
+
+2) So why do we need interfaces?
+================================
+Because GStreamer doesn't handle it all. GStreamer in itself is a media
+framework for streams of data from one element to the next. There's lots
+of things that's media-related, but not handled in this description.
+Several examples will probably clarify this: think of the Xvideo output
+plugin. We can create an overlay here (Xv-based), and we currently control
+this X-connection using glib properties. However, what property name is
+associated with what control? And does it work the same as v4lsrc's
+overlay image control?
+The same goes for a mixer, for image control, audio control, and probably
+a lot more. The general idea is simple: *this needs to be documented*.
+But properties aren't all - they simply cannot do this all. Some things
+cannot be described in a simple one-argument property thing. Of course,
+we could give a pointer to a struct as argument, but that's merely a hack
+and requires both plugin and app to know the ABI of the struct. This
+kills the whole idea of making the plugin independent of the app.
+In short: we want interfaces for this.
+
+3) How to integrate an interface in GStreamer
+=============================================
+Let us start with some starting point: an interface is associated
+with an element. It is a feature exported by that specific element,
+not by a pipeline or anything more complex. Pipelines are already
+handled just fine by GStreamer (or you wouldn't be reading all
+this).
+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
+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,
+the volume element would implement a mixer itself.
+
+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
+about adding new functions or whatever. Their disadvantage is that
+they're limited to one argument. Anything more complex requires
+app/plugin knowledge about the shared data, and that defeats the
+point of them: to have no dependency on each other. This could be
+solved partially by using action signals, but that makes the whole
+picture quite complex (since you use multiple methods for doing one
+simple thing). Also, they are quite slow compared to functions
+because of the table lookups. In short: it'd work, but I'm not in
+facour of it...
+OK, so an element exposes interfaces. This allows us to think of
+the idea of embedding interfaces (dynamically, of course) in the
+GstElement object. Think of an object being able to register an
+indefinate number of interfaces per object instance, and a client
+application could then enumerate interfaces and instantiate one.
+The API would then look like this:
+
+void gst_element_register_interface (GstElement *element,
+ const gchar *name,
+ GstInterfaceFunc func);
+
+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
+interfaces (see examples). Obviously, the client will need to know
+about the ABI/API of this struct, but that'll happen either way.
+Surely, there needs to binary linkage, but I don't consider that a
+bad thing. It does improve performance compared to action signals!
+
+So an element contains interfaces. But where are these interfaces
+described? And who creates them? I suggest that we do that just as
+we handle gstvideo and gstaudio right now (these libs do *nothing*
+useful currently, so this'd make them a lot more interesting).
+These interfaces inherit from GstInterface. The functions that
+are needed, can be provided through a class object. The element is
+then responsible for storing variables and so on. gstvideo/audio
+provides wrapper functions for the class functions.
+
+For the plugin, it's then as simple as can be. The class_init
+function sets the virtual functions in the interface class object,
+and the instance_init function registers the object per created
+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
+and make sure all elements exporting them work equally. For this,
+I'll give two examples.
+
+4) Examples
+===========
+
+typedef struct _GstInterface {
+ GObject object;
+} GstInterface;
+
+typedef struct _GstInterfaceClass {
+ GObjectClass klass;
+} GstInterfaceClass;
+
+4a) mixer
+---------
+A mixer is a way of controlling volume and input/output channels.
+This doesn't mean that you control which channel is the subwoofer,
+all that is supposed to be done automatically. It is really meant
+as a way of representing system-level volumes and such. It could
+also be used to turn on/off certain outputs or inputs.
+As you've noticed, I'm not only talking about output, but also
+input. Indeed, I want both osssrc *and* osssink to export the
+same mixer interface! Or at least a very similar one. Volume
+control works the same for both. You could say that osssrc should
+enumerate the input channels (such as microphone, line-in). Of
+course, osssink should not. Or maybe it should, not sure...
+And alsasink would surely implement the same interface.
+
+/* This is confusing naming... (i.e. FIXME)
+ * A channel is referred to both as the number of simultaneous
+ * sounds the input can handle as well as the in-/output itself
+ */
+
+typedef struct _GstMixerChannel {
+ gchar *label;
+ gint current_num_channels,
+ max_num_channels;
+} GstMixerChannel;
+
+typedef struct _GstMixer {
+ GstInterface interface;
+} GstMixer;
+
+typedef struct _GstMixerClass {
+ GstInterfaceClass klass;
+
+ /* virtual functions */
+ GList * (* list_channels) (GstMixer *mixer);
+ void (* set_volume) (GstMixer *mixer,
+ GstMixerChannel *channel,
+ gint *volumes);
+ void (* get_volume) (GstMixer *mixer,
+ GstMixerChannel *channel,
+ gint *volumes);
+ void (* set_mute) (GstMixer *mixer,
+ GstMixerChannel *channel,
+ gboolean mute);
+ gboolean (* get_mute) (GstMixer *mixer,
+ GstMixerChannel *channel);
+} GstMixerClass;
+
+Name for in the element list: "mixer". Gstaudio provides wrapper
+functions for each of the class' virtual functions. Possibly also
+some macros for GST_MIXER_CHANNEL_HAS_FLAG () or _get_channel ().
+
+4b) overlay
+-----------
+Overlay is used in both in- and output, too. Think of v4lsrc,
+v4l2src, v4lmjpegsrc, xvideosink - all overlays. But where do
+we position the overlay window? Control of this can be done at
+various levels: locational control (over the server, asynchronous)
+or XID control (but that makes you depend on X and limits the
+ability to broaden it over to non-X elements such as fbsink).
+
+However, simplicity *is* an issue here. Do we really care about
+overlay? In the end, users will have to link against either FB
+or X anyway, so we might want to create separate interfaces for
+both. On the other hand, we want to be general too... This is a
+decision that we need to make as early as possible in this process.
+
+Let's assume that we take X as a basis. Then, overlay becomes as
+simple as one function. Possible extendible by providing inputs
+(like in the mixer) and norms, although that only applies to
+input-to-analog, not to-digital... Discussion needed here!
+
+typedef struct _GstOverlayChannel {
+ gchar *label;
+} GstOverlayChannel;
+
+typedef struct _GstOverlayNorm {
+ gchar *label;
+} GstOverlayNorm;
+
+typedef struct _GstOverlay {
+ GstInterface interface;
+} GstOverlay;
+
+typedef struct _GstOverlayClass {
+ GstInterfaceClass klass;
+
+ /* virtual functions */
+ GList * (* list_channels) (GstOverlay *overlay);
+ void (* set_channel) (GstOverlay *overlay,
+ GstOverlayChannel *channel);
+ const gchar * (* get_channel) (GstOverlay *overlay);
+ GList * (* list_norms) (GstOverlay *overlay);
+ void (* set_norm) (GstOverlay *overlay,
+ GstOverlayNorm *norm);
+ const gchar * (* get_norm) (GstOverlay *overlay);
+ void (* set_xwindowid) (GstOverlay *overlay,
+ XWindowID xid);
+} GstOverlayClass;
+
+4c) user input
+--------------
+And yes, user input could be an interface too. Even better, it
+should definately be. And wasn't this one of our key issues for
+0.8.0?
+
+No code here. Go implement it, lazy ass!
+
+5) Status of this document
+==========================
+This is a proposal, nothing more. Nothing is implemented. Target
+release is 0.8.0 or any 0.7.x version.
+
+6) Copyright and blabla
+=======================
+(c) Ronald Bultje, 2003 <rbultje@ronald.bitfreak.net> under the
+terms of the GNU Free Documentation License. See http://www.gnu.org/
+for details.
+
+And no, I'm not for hire. ;).