Apr 282013
 

I’ve been tinkering with GStreamer lately, specifically QtGStreamer, since Qt is my preferred UI toolkit.

One thing I wanted to be able to do, is to programatically generate a list of all plug-ins and elements accessible to the application. My end goal was to allow a user to select audio devices for input/output.

Now, I could just try the suck-it-and-see approach, attempting to guess the names of elements. This could work, but suppose someone wanted to use an element other than the ones blessed enough to be included in your list?

Most of the audio source and sink elements have similar parameters, and the parameters can be discovered at run-time anyway. The bulk of them seem to accept a “device” parameter, which can be probed to generate a list of possible devices.

This gives us an elegant way of letting the user specify what they want. Known elements can be configured with specialised UI forms, but anything else, there’s a way to at least present the options to the user and allow them to configure it.

/*!
 * @file gstinfo.h
 */
#ifndef _GSTINFO_H
#define _GSTINFO_H

#include <QList>
#include <QString>

/*!
 * Get a list of all GStreamer plug-ins installed
 * @param       list    A list that will be populated with the names
 *                      of installed plug-ins.
 */
void GstGetPlugins(QList<QString>& list);

/*!
 * Get a list of all elements provided by the given GStreamer plug-in.
 * @param       plugin  The plug-in to query
 * @param       list    A list that will be populated with the names
 *                      of elements provided by this plug-in.
 */
void GstGetElements(const QString& plugin, QList<QString>& list);

#endif

/*!
 * @file gstinfo.cpp
 */
#include "gstinfo.h"
#include <gst/controller/gstcontroller.h>

/*!
 * Get a list of all GStreamer plug-ins installed
 * @param       list    A list that will be populated with the names
 *                      of installed plug-ins.
 */
void GstGetPlugins(QList<QString>& list) {
        /*
         * This code is partially based on code observed in gst-inspect.c
         * from GStreamer release 0.10.36.
         *
         * Original copyright:
         * GStreamer
         * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
         *               2000 Wim Taymans <wtay@chello.be>
         *               2004 Thomas Vander Stichele <thomas@apestaart.org>
         */
        GList* plugins; /* The head of the plug-in list */
        GList* pnode;   /* The currently viewed node */

        /* Empty the list out here */
        list.clear();

        plugins = pnode = gst_default_registry_get_plugin_list();
        while(pnode) {
                /* plugin: the plug-in info object pointed to by pnode */
                GstPlugin* plugin = (GstPlugin*)pnode->data;
                list << QString(plugin->desc.name);
                pnode = g_list_next(pnode);
        }

        /* Clean-up */
        gst_plugin_list_free (plugins);
}

/*!
 * Get a list of all elements provided by the given GStreamer plug-in.
 * @param       plugin  The plug-in to query
 * @param       list    A list that will be populated with the names
 *                      of elements provided by this plug-in.
 */
void GstGetElements(const QString& plugin, QList<QString>& list) {
        /*
         * This code is partially based on code observed in gst-inspect.c
         * from GStreamer release 0.10.36.
         *
         * Original copyright:
         * GStreamer
         * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
         *               2000 Wim Taymans <wtay@chello.be>
         *               2004 Thomas Vander Stichele <thomas@apestaart.org>
         */
        GList* features;        /* The list of plug-in features */
        GList* fnode;           /* The currently viewed node */

        /* Empty the list out here */
        list.clear();

        features = fnode = gst_registry_get_feature_list_by_plugin(
                        gst_registry_get_default(),
                        plugin.toUtf8().data());
        while(fnode) {
                if (fnode->data) {
                        /* Currently pointed-to feature */
                        GstPluginFeature* feature
                                = GST_PLUGIN_FEATURE(fnode->data);

                        if (GST_IS_ELEMENT_FACTORY (feature)) {
                                GstElementFactory* factory
                                        = GST_ELEMENT_FACTORY(gst_plugin_feature_load(feature));
                                list << QString(GST_PLUGIN_FEATURE_NAME(factory));
                        }
                }
                fnode = g_list_next(fnode);
        }
        gst_plugin_feature_list_free(features);
}

How does one use this?

	QList<QString> plugins;
	QList<QString>::iterator p_it;

	GstGetPlugins(plugins);
	for (p_it = plugins.begin(); p_it != plugins.end(); p_it++) {
		QList<QString> elements;
		QList<QString>::iterator e_it;
		GstGetElements(*p_it, elements);
		for (e_it = elements.begin(); e_it != elements.end(); e_it++) {
			std::cout	<< "Plug-in "
					<< p_it->toStdString()
					<< " Element "
					<< e_it->toStdString()
					<< std::endl;
		}
	}