Re: gstreamermm element wrapper-code generator
- From: "Milosz Derezynski" <internalerror gmail com>
- To: gtkmm-list <gtkmm-list gnome org>
- Subject: Re: gstreamermm element wrapper-code generator
- Date: Thu, 3 Apr 2008 21:29:43 +0200
Yes of course i forgot the attach, sorry, here it is:
-- Milosz
2008/4/3, Milosz Derezynski <internalerror gmail com>:
Hey All,
So here is the first version of the promised element wrapper generator. It is directly based off gstreamer's CVS-as-of-today gst-inspect tool (http://linux.die.net/man/1/gst-inspect-0.10)
You can compile it with:
g++ -o wrapper wrapper.cc `pkg-config --libs --cflags gstreamermm-0.10 glibmm-2.4`
and run it similar to glib-genmarshal:
'wrapper --header <element name>' (e.g. "ximagesink") will output the header file and
'wrapper --body <element name>' the corresponding body file
What remains to be done (in both senses) is the include of the header into the body since the output
so far happens to stdout, just open the body file and add the include of the generated header file (to
generate header/body file as files just use the shell redirect).
What works:
- Creates a class named after the given element
- Wraps all properties of a given GstElement as Glib::Object C++ properties
What doesn't work (yet):
- Wrapping signals. This will be tough because there exists nothing in glibmm/gtkmm to semi-automatically wrap C signals like we can do with properties, hence we will need parts of gmmproc to do that for us; i have yet to figure out what a good way is, help very appreciated
What is bad:
- The way the wrapper class wraps the generic Gst::Element in question is probably very _bad_. I just don't really know how to do this, because Glib::wrap won't work: we would everytime pass just a simple plain GstObject* to wrap(), and wrap() wouldn't know how to differentiate then, so this is out of the question. Comments here very appreciated.
-- Milosz
/* gstreamermm
* Copyright (C) 2007, 2008 Milosz Derezynski, Jose Albuquerque,
* Murray Cumming
*
* gstmm-wrapper-gen: Based on:
*
* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega cse ogi edu>
* 2000 Wim Taymans <wtay chello be>
* 2004 Thomas Vander Stichele <thomas apestaart org>
*
* gst-inspect.c: tool to inspect the GStreamer registry
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <glibmm.h>
#include <glibmm/i18n.h>
#include <gst/gst.h>
#include <string>
#include <cstring>
#include <glib/gprintf.h>
#include <vector>
#include <stdexcept>
namespace
{
Glib::ustring
genPropName (Glib::ustring const& in)
{
Glib::ustring propName;
if(in.find("-") != Glib::ustring::npos)
{
char ** frags = g_strsplit (in.c_str(), "-", -1);
char * newname = g_strjoinv ("_", frags);
propName = newname;
g_strfreev(frags);
g_free (newname);
}
else
propName = in;
return propName.lowercase();
}
enum PropertyFlags
{
PROP_FLAGS_NONE = 0,
PROP_FLAGS_READABLE = 1 << 0,
PROP_FLAGS_WRITABLE = 1 << 1
};
inline PropertyFlags operator|(PropertyFlags lhs, PropertyFlags rhs)
{ return static_cast<PropertyFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs)); }
inline void operator|=(PropertyFlags & lhs, PropertyFlags rhs)
{ lhs = static_cast<PropertyFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs)); }
/*---------------------------------------------------------------------------*/
struct PropertyInfo
{
std::string m_PropName;
std::string m_PropComment;
std::string m_PropType;
PropertyFlags m_PropFlags;
PropertyInfo ();
};
PropertyInfo::PropertyInfo ()
: m_PropFlags(PROP_FLAGS_NONE)
{
}
typedef std::vector<PropertyInfo> PropertyV;
/*---------------------------------------------------------------------------*/
struct ElementInfo
{
std::string m_ClassName;
PropertyV m_Properties;
};
class ElementScanner
{
private:
ElementInfo & m_EInfo;
std::string m_FacName;
GstElement * m_Element;
void
scan_properties ();
public:
ElementScanner (std::string const& fac_name, ElementInfo & info);
~ElementScanner ();
void
scan ();
};
/*---------------------------------------------------------------------------*/
ElementScanner::ElementScanner (std::string const& fac_name, ElementInfo & info)
: m_EInfo(info)
, m_FacName(fac_name)
{
m_Element = gst_element_factory_make(fac_name.c_str(), NULL);
if(!m_Element)
exit(-1);
info.m_ClassName = Glib::ustring(std::string(1, fac_name[0])).uppercase() + Glib::ustring(fac_name).substr(1);
}
ElementScanner::~ElementScanner ()
{
gst_object_unref(m_Element);
}
void
ElementScanner::scan_properties ()
{
GParamSpec **property_specs;
guint num_properties, i;
property_specs = g_object_class_list_properties(G_OBJECT_GET_CLASS (m_Element), &num_properties);
for (i = 0; i < num_properties; i++)
{
GValue value = { 0, };
GParamSpec *param = property_specs[i];
g_value_init (&value, param->value_type);
PropertyInfo info;
info.m_PropName= g_param_spec_get_name (param);
info.m_PropComment = g_param_spec_get_blurb (param);
if (param->flags & G_PARAM_READABLE)
{
g_object_get_property (G_OBJECT (m_Element), param->name, &value);
info.m_PropFlags |= PROP_FLAGS_READABLE;
}
if (param->flags & G_PARAM_WRITABLE) {
info.m_PropFlags |= PROP_FLAGS_WRITABLE;
}
switch (G_VALUE_TYPE (&value))
{
case G_TYPE_STRING:
{
info.m_PropType = "std::string";
break;
}
case G_TYPE_BOOLEAN:
{
info.m_PropType = "bool";
break;
}
case G_TYPE_ULONG:
{
info.m_PropType = "gulong";
break;
}
case G_TYPE_LONG:
{
info.m_PropType = "glong";
break;
}
case G_TYPE_UINT:
{
info.m_PropType = "guint";
break;
}
case G_TYPE_INT:
{
info.m_PropType = "gint";
break;
}
case G_TYPE_UINT64:
{
info.m_PropType = "guint64";
break;
}
case G_TYPE_INT64:
{
info.m_PropType = "gint64";
break;
}
case G_TYPE_FLOAT:
{
info.m_PropType = "float";
break;
}
case G_TYPE_DOUBLE:
{
info.m_PropType = "double";
break;
}
default:
if (param->value_type == GST_TYPE_CAPS)
{
info.m_PropType = "Glib::RefPtr<Gst::Caps> ";
}
else if (G_IS_PARAM_SPEC_ENUM (param))
{
info.m_PropType = "int";
}
else if (G_IS_PARAM_SPEC_FLAGS (param))
{
info.m_PropType = "int";
}
else if (G_IS_PARAM_SPEC_OBJECT (param))
{
info.m_PropType = "GObject*";
} else if (G_IS_PARAM_SPEC_BOXED (param))
{
info.m_PropType = "GBoxed*";
}
else if (G_IS_PARAM_SPEC_POINTER (param))
{
info.m_PropType = "gpointer";
}
else if (param->value_type == G_TYPE_VALUE_ARRAY) {
info.m_PropType = "Glib::ArrayHandle<Glib::ValueBase> ";
}
else if (GST_IS_PARAM_SPEC_FRACTION (param))
{
info.m_PropType = "Glib::ValueBase";
} else if (GST_IS_PARAM_SPEC_MINI_OBJECT (param))
{
info.m_PropType = "Glib::RefPtr<Gst::MiniObject> ";
}
else
{
g_warning("Unknown type: %s",
g_type_name (param->value_type));
}
break;
}
m_EInfo.m_Properties.push_back(info);
g_value_reset (&value);
}
g_free (property_specs);
}
void
ElementScanner::scan ()
{
scan_properties ();
}
/*---------------------------------------------------------------------------*/
class ElementPrinter_Base
{
protected:
ElementInfo const& m_EInfo;
public:
ElementPrinter_Base (ElementInfo const& info);
virtual void
print_header ();
virtual void
print_body ();
};
ElementPrinter_Base::ElementPrinter_Base (ElementInfo const& info)
: m_EInfo(info)
{
}
void
ElementPrinter_Base::print_header ()
{
g_printf("Class: Gst::Element%s\n\n", m_EInfo.m_ClassName.c_str());
for(PropertyV::const_iterator i = m_EInfo.m_Properties.begin(); i != m_EInfo.m_Properties.end(); ++i)
{
g_printf ("Property Name: %s, Type: %s\n", i->m_PropName.c_str(), i->m_PropType.c_str());
}
}
void
ElementPrinter_Base::print_body ()
{
}
class ElementPrinter_CPPClass
: public ElementPrinter_Base
{
private:
void
print_classheader ();
void
print_classfooter ();
void
print_includes ();
void
print_properties_header ();
void
print_ctor_header ();
void
print_properties_body ();
void
print_ctor_body ();
public:
ElementPrinter_CPPClass (ElementInfo const& info);
virtual void
print_header ();
virtual void
print_body ();
};
ElementPrinter_CPPClass::ElementPrinter_CPPClass (ElementInfo const& info)
: ElementPrinter_Base(info)
{
}
void
ElementPrinter_CPPClass::print_properties_body ()
{
for(PropertyV::const_iterator i = m_EInfo.m_Properties.begin(); i != m_EInfo.m_Properties.end(); ++i)
{
PropertyInfo const& info (*i);
if((info.m_PropFlags & (PROP_FLAGS_READABLE | PROP_FLAGS_READABLE)))
{
g_printf("\tGlib::PropertyProxy<");
}
else if(((info.m_PropFlags & PROP_FLAGS_READABLE)))
{
g_printf("\tGlib::PropertyProxy_ReadOnly<");
}
else if(((info.m_PropFlags & PROP_FLAGS_WRITABLE)))
{
g_printf("\tGlib::PropertyProxy_WriteOnly<");
}
g_printf (info.m_PropType.c_str());
g_printf (">", info.m_PropName.c_str());
g_printf("\tElement%s::property_%s ()\n\t{\n", m_EInfo.m_ClassName.c_str(), genPropName(info.m_PropName).c_str());
if((info.m_PropFlags & (PROP_FLAGS_READABLE | PROP_FLAGS_READABLE)))
{
g_printf("\t\t return Glib::PropertyProxy<");
}
else if(((info.m_PropFlags & PROP_FLAGS_READABLE)))
{
g_printf("\t\t return Glib::PropertyProxy_ReadOnly<");
}
else if(((info.m_PropFlags & PROP_FLAGS_WRITABLE)))
{
g_printf("\t\t return Glib::PropertyProxy_WriteOnly<");
}
g_printf (info.m_PropType.c_str());
g_printf (">(this, \"%s\");", info.m_PropName.c_str());
g_printf("\n\t}\n\n");
}
}
void
ElementPrinter_CPPClass::print_properties_header ()
{
for(PropertyV::const_iterator i = m_EInfo.m_Properties.begin(); i != m_EInfo.m_Properties.end(); ++i)
{
PropertyInfo const& info (*i);
g_printf("\t\t/* %s */\n", info.m_PropComment.c_str());
if((info.m_PropFlags & (PROP_FLAGS_READABLE | PROP_FLAGS_READABLE)))
{
g_printf("\t\tGlib::PropertyProxy<");
}
else if(((info.m_PropFlags & PROP_FLAGS_READABLE)))
{
g_printf("\t\tGlib::PropertyProxy_ReadOnly<");
}
else if(((info.m_PropFlags & PROP_FLAGS_WRITABLE)))
{
g_printf("\t\tGlib::PropertyProxy_WriteOnly<");
}
g_printf (info.m_PropType.c_str());
g_printf ("> property_%s();\n\n", genPropName(info.m_PropName).c_str());
}
}
void
ElementPrinter_CPPClass::print_includes ()
{
g_printf("#include <glibmm.h>\n");
g_printf("#include <gstreamermm.h>\n");
g_printf("#include <string>\n\n");
}
void
ElementPrinter_CPPClass::print_classheader ()
{
g_printf("namespace Gst\n{\n\n");
g_printf("\tclass Element%s\n", m_EInfo.m_ClassName.c_str());
g_printf("\t : public Gst::Element\n\t{\n\n");
}
void
ElementPrinter_CPPClass::print_ctor_header ()
{
g_printf("\tprivate:\n\n");
g_printf("\t\tElement%s (const Glib::RefPtr<Gst::Element>&);\n\n", m_EInfo.m_ClassName.c_str());
g_printf("\tpublic:\n\n");
g_printf("\t\tstatic Glib::RefPtr<Gst::Element%s> wrap (const Glib::RefPtr<Gst::Element>&);\n\n", m_EInfo.m_ClassName.c_str());
}
void
ElementPrinter_CPPClass::print_ctor_body ()
{
g_printf("\tElement%s::Element%s (const Glib::RefPtr<Gst::Element>& element)\n\n",
m_EInfo.m_ClassName.c_str(),
m_EInfo.m_ClassName.c_str());
g_printf("\t{\n");
g_printf("\t\tgobject_ = (GObject*)(element->gobj());\n");
g_printf("\t\tg_object_ref(gobject_);\n");
g_printf("\t}\n\n");
g_printf("\tGlib::RefPtr<Gst::Element%s>\n\tElement%s::wrap (const Glib::RefPtr<Gst::Element>& element)\n",
m_EInfo.m_ClassName.c_str(),
m_EInfo.m_ClassName.c_str());
g_printf("\t{\n");
g_printf("\t\treturn Glib::RefPtr<Gst::Element%s>(new Gst::Element%s(element));",
m_EInfo.m_ClassName.c_str(),
m_EInfo.m_ClassName.c_str());
g_printf("\n\t}\n\n");
}
void
ElementPrinter_CPPClass::print_classfooter ()
{
g_printf("\n\t}; // class Element%s\n", m_EInfo.m_ClassName.c_str());
g_printf("} // namespace Gst\n\n");
}
void
ElementPrinter_CPPClass::print_header ()
{
print_includes ();
print_classheader ();
print_ctor_header ();
print_properties_header ();
print_classfooter ();
}
void
ElementPrinter_CPPClass::print_body ()
{
print_includes ();
g_printf("namespace Gst\n{\n\n");
print_ctor_body ();
print_properties_body ();
g_printf("\n}");
}
#if 0
char *_name = NULL;
int print_element_info (GstElementFactory * factory, gboolean print_names);
void
n_print (const char *format, ...)
{
va_list args;
gint retval;
if (_name)
g_print (_name);
va_start (args, format);
retval = g_vprintf (format, args);
va_end (args);
}
gboolean
print_field (GQuark field, const GValue * value, gpointer pfx)
{
gchar *str = gst_value_serialize (value);
n_print ("%s %15s: %s\n", (gchar *) pfx, g_quark_to_string (field), str);
g_free (str);
return TRUE;
}
void
print_caps (const GstCaps * caps, const gchar * pfx)
{
guint i;
g_return_if_fail (caps != NULL);
if (gst_caps_is_any (caps)) {
n_print ("%sANY\n", pfx);
return;
}
if (gst_caps_is_empty (caps)) {
n_print ("%sEMPTY\n", pfx);
return;
}
for (i = 0; i < gst_caps_get_size (caps); i++) {
GstStructure *structure = gst_caps_get_structure (caps, i);
n_print ("%s%s\n", pfx, gst_structure_get_name (structure));
gst_structure_foreach (structure, print_field, (gpointer) pfx);
}
}
#if 0
void
print_formats (const GstFormat * formats)
{
while (formats && *formats) {
const GstFormatDefinition *definition;
definition = gst_format_get_details (*formats);
if (definition)
n_print ("\t\t(%d):\t%s (%s)\n", *formats,
definition->nick, definition->description);
else
n_print ("\t\t(%d):\tUnknown format\n", *formats);
formats++;
}
}
#endif
void
print_query_types (const GstQueryType * types)
{
while (types && *types) {
const GstQueryTypeDefinition *definition;
definition = gst_query_type_get_details (*types);
if (definition)
n_print ("\t\t(%d):\t%s (%s)\n", *types,
definition->nick, definition->description);
else
n_print ("\t\t(%d):\tUnknown query format\n", *types);
types++;
}
}
#ifndef GST_DISABLE_ENUMTYPES
#if 0
void
print_event_masks (const GstEventMask * masks)
{
GType event_type;
GEnumClass *klass;
GType event_flags;
GFlagsClass *flags_class = NULL;
event_type = gst_event_type_get_type ();
klass = (GEnumClass *) g_type_class_ref (event_type);
while (masks && masks->type) {
GEnumValue *value;
gint flags = 0, index = 0;
switch (masks->type) {
case GST_EVENT_SEEK:
flags = masks->flags;
event_flags = gst_seek_type_get_type ();
flags_class = (GFlagsClass *) g_type_class_ref (event_flags);
break;
default:
break;
}
value = g_enum_get_value (klass, masks->type);
g_print ("\t\t%s ", value->value_nick);
while (flags) {
GFlagsValue *value;
if (flags & 1) {
value = g_flags_get_first_value (flags_class, 1 << index);
if (value)
g_print ("| %s ", value->value_nick);
else
g_print ("| ? ");
}
flags >>= 1;
index++;
}
g_print ("\n");
masks++;
}
}
#endif
#else
void
print_event_masks (const GstEventMask * masks)
{
}
#endif
void
print_element_properties_info (GstElement * element)
{
GParamSpec **property_specs;
guint num_properties, i;
gboolean readable;
gboolean first_flag;
property_specs = g_object_class_list_properties
(G_OBJECT_GET_CLASS (element), &num_properties);
n_print ("\n");
n_print ("Element Properties:\n");
for (i = 0; i < num_properties; i++) {
GValue value = { 0, };
GParamSpec *param = property_specs[i];
readable = FALSE;
g_value_init (&value, param->value_type);
n_print (" %-20s: %s\n", g_param_spec_get_name (param),
g_param_spec_get_blurb (param));
first_flag = TRUE;
n_print ("%-23.23s flags: ", "");
if (param->flags & G_PARAM_READABLE) {
g_object_get_property (G_OBJECT (element), param->name, &value);
readable = TRUE;
if (!first_flag)
g_print (", ");
else
first_flag = FALSE;
g_print (_("readable"));
}
if (param->flags & G_PARAM_WRITABLE) {
if (!first_flag)
g_print (", ");
else
first_flag = FALSE;
g_print (_("writable"));
}
if (param->flags & GST_PARAM_CONTROLLABLE) {
if (!first_flag)
g_print (", ");
else
first_flag = FALSE;
g_print (_("controllable"));
}
n_print ("\n");
switch (G_VALUE_TYPE (&value)) {
case G_TYPE_STRING:
{
GParamSpecString *pstring = G_PARAM_SPEC_STRING (param);
n_print ("%-23.23s String. ", "");
if (pstring->default_value == NULL)
g_print ("Default: null ");
else
g_print ("Default: \"%s\" ", pstring->default_value);
if (readable) {
const char *string_val = g_value_get_string (&value);
if (string_val == NULL)
g_print ("Current: null");
else
g_print ("Current: \"%s\"", string_val);
}
break;
}
case G_TYPE_BOOLEAN:
{
GParamSpecBoolean *pboolean = G_PARAM_SPEC_BOOLEAN (param);
n_print ("%-23.23s Boolean. ", "");
g_print ("Default: %s ", (pboolean->default_value ? "true" : "false"));
if (readable)
g_print ("Current: %s",
(g_value_get_boolean (&value) ? "true" : "false"));
break;
}
case G_TYPE_ULONG:
{
GParamSpecULong *pulong = G_PARAM_SPEC_ULONG (param);
n_print ("%-23.23s Unsigned Long. ", "");
g_print ("Range: %lu - %lu Default: %lu ",
pulong->minimum, pulong->maximum, pulong->default_value);
if (readable)
g_print ("Current: %lu", g_value_get_ulong (&value));
break;
}
case G_TYPE_LONG:
{
GParamSpecLong *plong = G_PARAM_SPEC_LONG (param);
n_print ("%-23.23s Long. ", "");
g_print ("Range: %ld - %ld Default: %ld ",
plong->minimum, plong->maximum, plong->default_value);
if (readable)
g_print ("Current: %ld", g_value_get_long (&value));
break;
}
case G_TYPE_UINT:
{
GParamSpecUInt *puint = G_PARAM_SPEC_UINT (param);
n_print ("%-23.23s Unsigned Integer. ", "");
g_print ("Range: %u - %u Default: %u ",
puint->minimum, puint->maximum, puint->default_value);
if (readable)
g_print ("Current: %u", g_value_get_uint (&value));
break;
}
case G_TYPE_INT:
{
GParamSpecInt *pint = G_PARAM_SPEC_INT (param);
n_print ("%-23.23s Integer. ", "");
g_print ("Range: %d - %d Default: %d ",
pint->minimum, pint->maximum, pint->default_value);
if (readable)
g_print ("Current: %d", g_value_get_int (&value));
break;
}
case G_TYPE_UINT64:
{
GParamSpecUInt64 *puint64 = G_PARAM_SPEC_UINT64 (param);
n_print ("%-23.23s Unsigned Integer64. ", "");
g_print ("Range: %" G_GUINT64_FORMAT " - %" G_GUINT64_FORMAT
" Default: %" G_GUINT64_FORMAT " ",
puint64->minimum, puint64->maximum, puint64->default_value);
if (readable)
g_print ("Current: %" G_GUINT64_FORMAT, g_value_get_uint64 (&value));
break;
}
case G_TYPE_INT64:
{
GParamSpecInt64 *pint64 = G_PARAM_SPEC_INT64 (param);
n_print ("%-23.23s Integer64. ", "");
g_print ("Range: %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT
" Default: %" G_GINT64_FORMAT " ",
pint64->minimum, pint64->maximum, pint64->default_value);
if (readable)
g_print ("Current: %" G_GINT64_FORMAT, g_value_get_int64 (&value));
break;
}
case G_TYPE_FLOAT:
{
GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT (param);
n_print ("%-23.23s Float. ", "");
g_print ("Range: %15.7g - %15.7g Default: %15.7g ",
pfloat->minimum, pfloat->maximum, pfloat->default_value);
if (readable)
g_print ("Current: %15.7g", g_value_get_float (&value));
break;
}
case G_TYPE_DOUBLE:
{
GParamSpecDouble *pdouble = G_PARAM_SPEC_DOUBLE (param);
n_print ("%-23.23s Double. ", "");
g_print ("Range: %15.7g - %15.7g Default: %15.7g ",
pdouble->minimum, pdouble->maximum, pdouble->default_value);
if (readable)
g_print ("Current: %15.7g", g_value_get_double (&value));
break;
}
default:
if (param->value_type == GST_TYPE_CAPS) {
const GstCaps *caps = gst_value_get_caps (&value);
if (!caps)
n_print ("%-23.23s Caps (NULL)", "");
else {
print_caps (caps, " ");
}
} else if (G_IS_PARAM_SPEC_ENUM (param)) {
GParamSpecEnum *penum = G_PARAM_SPEC_ENUM (param);
GEnumValue *values;
guint j = 0;
gint enum_value;
const gchar *def_val_nick = "", *cur_val_nick = "";
values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values;
enum_value = g_value_get_enum (&value);
while (values[j].value_name) {
if (values[j].value == enum_value)
cur_val_nick = values[j].value_nick;
if (values[j].value == penum->default_value)
def_val_nick = values[j].value_nick;
j++;
}
n_print
("%-23.23s Enum \"%s\" Default: %d, \"%s\" Current: %d, \"%s\"",
"", g_type_name (G_VALUE_TYPE (&value)), penum->default_value,
def_val_nick, enum_value, cur_val_nick);
j = 0;
while (values[j].value_name) {
g_print ("\n");
if (_name)
g_print (_name);
g_print ("%-23.23s (%d): %-16s - %s", "",
values[j].value, values[j].value_nick, values[j].value_name);
j++;
}
/* g_type_class_unref (ec); */
} else if (G_IS_PARAM_SPEC_FLAGS (param)) {
GParamSpecFlags *pflags = G_PARAM_SPEC_FLAGS (param);
GFlagsValue *values;
guint j = 0;
gint flags_value;
GString *cur_flags = NULL, *def_flags = NULL;
values = G_FLAGS_CLASS (g_type_class_ref (param->value_type))->values;
flags_value = g_value_get_flags (&value);
while (values[j].value_name) {
if (values[j].value & flags_value) {
if (cur_flags) {
g_string_append_printf (cur_flags, " | %s",
values[j].value_nick);
} else {
cur_flags = g_string_new (values[j].value_nick);
}
}
if (values[j].value & pflags->default_value) {
if (def_flags) {
g_string_append_printf (def_flags, " | %s",
values[j].value_nick);
} else {
def_flags = g_string_new (values[j].value_nick);
}
}
j++;
}
n_print
("%-23.23s Flags \"%s\" Default: 0x%08x, \"%s\" Current: 0x%08x, \"%s\"",
"", g_type_name (G_VALUE_TYPE (&value)), pflags->default_value,
(def_flags ? def_flags->str : "(none)"), flags_value,
(cur_flags ? cur_flags->str : "(none)"));
j = 0;
while (values[j].value_name) {
g_print ("\n");
if (_name)
g_print (_name);
g_print ("%-23.23s (0x%08x): %-16s - %s", "",
values[j].value, values[j].value_nick, values[j].value_name);
j++;
}
if (cur_flags)
g_string_free (cur_flags, TRUE);
if (def_flags)
g_string_free (def_flags, TRUE);
} else if (G_IS_PARAM_SPEC_OBJECT (param)) {
n_print ("%-23.23s Object of type \"%s\"", "",
g_type_name (param->value_type));
} else if (G_IS_PARAM_SPEC_BOXED (param)) {
n_print ("%-23.23s Boxed pointer of type \"%s\"", "",
g_type_name (param->value_type));
} else if (G_IS_PARAM_SPEC_POINTER (param)) {
if (param->value_type != G_TYPE_POINTER) {
n_print ("%-23.23s Pointer of type \"%s\".", "",
g_type_name (param->value_type));
} else {
n_print ("%-23.23s Pointer.", "");
}
} else if (param->value_type == G_TYPE_VALUE_ARRAY) {
n_print ("%-23.23s Array of GValues", "");
} else if (GST_IS_PARAM_SPEC_FRACTION (param)) {
GstParamSpecFraction *pfraction = GST_PARAM_SPEC_FRACTION (param);
n_print ("%-23.23s Fraction. ", "");
g_print ("Range: %d/%d - %d/%d Default: %d/%d ",
pfraction->min_num, pfraction->min_den,
pfraction->max_num, pfraction->max_den,
pfraction->def_num, pfraction->def_den);
if (readable)
g_print ("Current: %d/%d",
gst_value_get_fraction_numerator (&value),
gst_value_get_fraction_denominator (&value));
} else if (GST_IS_PARAM_SPEC_MINI_OBJECT (param)) {
n_print ("%-23.23s MiniObject of type \"%s\"", "",
g_type_name (param->value_type));
} else {
n_print ("%-23.23s Unknown type %ld \"%s\"", "", param->value_type,
g_type_name (param->value_type));
}
break;
}
if (!readable)
g_print (" Write only\n");
else
g_print ("\n");
g_value_reset (&value);
}
if (num_properties == 0)
n_print (" none\n");
g_free (property_specs);
}
void
print_signal_info (GstElement * element)
{
/* Signals/Actions Block */
guint *signals;
guint nsignals;
gint i = 0, j, k;
GSignalQuery *query = NULL;
GType type;
GSList *found_signals, *l;
for (k = 0; k < 2; k++) {
found_signals = NULL;
for (type = G_OBJECT_TYPE (element); type; type = g_type_parent (type)) {
if (type == GST_TYPE_ELEMENT || type == GST_TYPE_OBJECT)
break;
if (type == GST_TYPE_BIN && G_OBJECT_TYPE (element) != GST_TYPE_BIN)
continue;
signals = g_signal_list_ids (type, &nsignals);
for (i = 0; i < nsignals; i++) {
query = g_new0 (GSignalQuery, 1);
g_signal_query (signals[i], query);
if ((k == 0 && !(query->signal_flags & G_SIGNAL_ACTION)) ||
(k == 1 && (query->signal_flags & G_SIGNAL_ACTION)))
found_signals = g_slist_append (found_signals, query);
else
g_free (query);
}
g_free (signals);
signals = NULL;
}
if (found_signals) {
n_print ("\n");
if (k == 0)
n_print ("Element Signals:\n");
else
n_print ("Element Actions:\n");
} else {
continue;
}
for (l = found_signals; l; l = l->next) {
gchar *indent;
int indent_len;
query = (GSignalQuery *) l->data;
indent_len = strlen (query->signal_name) +
strlen (g_type_name (query->return_type)) + 24;
indent = g_new0 (gchar, indent_len + 1);
memset (indent, ' ', indent_len);
n_print (" \"%s\" : %s user_function (%s* object",
query->signal_name,
g_type_name (query->return_type), g_type_name (type));
for (j = 0; j < query->n_params; j++) {
if (_name)
g_print (_name);
if (G_TYPE_IS_FUNDAMENTAL (query->param_types[j])) {
g_print (",\n%s%s arg%d", indent,
g_type_name (query->param_types[j]), j);
} else if (G_TYPE_IS_ENUM (query->param_types[j])) {
g_print (",\n%s%s arg%d", indent,
g_type_name (query->param_types[j]), j);
} else {
g_print (",\n%s%s* arg%d", indent,
g_type_name (query->param_types[j]), j);
}
}
if (k == 0) {
if (_name)
g_print (_name);
g_print (",\n%sgpointer user_data);\n", indent);
} else
g_print (");\n");
g_free (indent);
}
if (found_signals) {
g_slist_foreach (found_signals, (GFunc) g_free, NULL);
g_slist_free (found_signals);
}
}
}
int
print_element_info (GstElementFactory * factory, gboolean print_names)
{
GstElement *element;
gint maxlevel = 0;
factory =
GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
(factory)));
if (!factory) {
g_print ("element plugin couldn't be loaded\n");
return -1;
}
element = gst_element_factory_create (factory, NULL);
if (!element) {
g_print ("couldn't construct element for some reason\n");
return -1;
}
if (print_names)
_name = g_strdup_printf ("%s: ", GST_PLUGIN_FEATURE (factory)->name);
else
_name = NULL;
#if 0
print_factory_details_info (factory);
if (GST_PLUGIN_FEATURE (factory)->plugin_name) {
GstPlugin *plugin;
plugin = gst_registry_find_plugin (gst_registry_get_default (),
GST_PLUGIN_FEATURE (factory)->plugin_name);
if (plugin) {
print_plugin_info (plugin);
}
}
#endif
print_element_properties_info (element);
print_signal_info (element);
gst_object_unref (element);
gst_object_unref (factory);
g_free (_name);
return 0;
}
#endif
}
int
main (int argc, char *argv[])
{
gboolean arg_header = FALSE;
gboolean arg_body = FALSE;
GOptionEntry options[] =
{
{"header", 'h', 0, G_OPTION_ARG_NONE, &arg_header, N_("generate C++ headers"), 0},
{"body", 'b', 0, G_OPTION_ARG_NONE, &arg_body, N_("generate C++ code"), 0}
};
if (!g_thread_supported ())
g_thread_init (NULL);
g_type_init ();
GOptionContext *oc = g_option_context_new ("<element>");
g_option_context_add_main_entries (oc, options, "gstmm-wrapper-gen");
g_option_context_add_group (oc, gst_init_get_option_group ());
Glib::OptionContext occc (oc, true);
occc.parse(argc, argv);
if(argc < 2)
{
g_print("Error: Please specify an element to generate code for!\n\n");
exit(0);
}
ElementInfo info;
ElementScanner scanner (argv[1], info);
scanner.scan ();
ElementPrinter_CPPClass printer (info);
if(arg_header)
printer.print_header ();
if (arg_body)
printer.print_body ();
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]