Re: gstreamermm element wrapper-code generator



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]