diff options
author | George Kiagiadakis <kiagiadakis.george@gmail.com> | 2010-04-14 12:17:46 +0300 |
---|---|---|
committer | George Kiagiadakis <kiagiadakis.george@gmail.com> | 2010-04-14 12:17:46 +0300 |
commit | 246328aff0e81a62bb8e1e9e76237ed085508040 (patch) | |
tree | bf2d8fb32bba61ce604a6d98686e9401fe06e8cf /README | |
parent | 321bc745d792fda87b5ab77d14f69993559a91ec (diff) |
Add a README file with various information, mostly targeted to people that want to contribute.
Diffstat (limited to 'README')
-rw-r--r-- | README | 227 |
1 files changed, 227 insertions, 0 deletions
@@ -0,0 +1,227 @@ +1. About +-------- + +- What is QtGstreamer? + +QtGstreamer aims to become a library providing C++ bindings for Gstreamer [1] +with a Qt-style API plus some helper classes for integrating Gstreamer better +in Qt [2] applications. + +[1]. http://gstreamer.freedesktop.org/ +[2]. http://qt.nokia.com/ + +- What is QtGstreamer’s development state at the moment? + +QtGstreamer is still in early development state and is not suitable for use. + +- What are the differences between the C++ bindings of QtGstreamer and Gstreamermm? + + * QtGstreamer provides bindings that completely hide the Gstreamer ABI, + so your application doesn’t need to link to Gstreamer itself. + * QtGstreamer uses QtCore helper classes (QString, QList, etc..) where it can, + to ease integration with Qt. + * QtGstreamer provides support for connecting arbitrary GObject signals to + slots, while in Gstreamermm every signal needs to be defined in the bindings, + or else you need to use the C API for connecting it. This is especially useful + for connecting signals from element plugins, where their interface is unknown + at compile time. + + +2. Building +----------- + +QtGstreamer requires the following software to be installed in order to build: + * CMake <http://www.cmake.org/> + * Gstreamer <http://gstreamer.freedesktop.org/> + With its dependencies: + - Glib / GObject <http://www.gtk.org/> + - libxml2 <http://xmlsoft.org/> + * Qt 4 <http://qt.nokia.com/> + * Automoc <svn://anonsvn.kde.org/home/kde/trunk/kdesupport/automoc/> + * Boost (static_assert, type_traits, function, bind) <http://www.boost.org/> + * Flex <http://flex.sourceforge.net/> + * Bison <http://www.gnu.org/software/bison/> + +Also, for the moment, the GNU C++ compiler (g++) version 4.4 or later is required +in order to build the GObject signals wrapper, which is based on C++0x variadic +templates. In the future I plan to provide a non-variadic template version too, +with some limitation on the number of signal arguments. + +To build, the procedure is simple: + +$ mkdir build && cd build +$ cmake .. -DCMAKE_INSTALL_PREFIX=/path/to/installation/prefix +$ make +$ make install + + +3. Coding style +--------------- + +QtGstreamer follows the kdelibs coding style: +http://techbase.kde.org/Policies/Kdelibs_Coding_Style + + +4. Naming policies +------------------ + +4.1 The namespaces +------------------ + +The "G" namespace (GObject, GValue, etc...) is referred to as "QGlib". +The "Gst" namespace (GstObject, GstElement, etc...) is referred to as "QGst". +I didn't like them much when I chose them, better names could be discussed... + +4.2 The class names +------------------- + +Class names should be the same as their G* equivalents, with the namespace +prefix removed. For example, "GstObject" becomes "QGst::Object", "GParamSpec" +becomes "QGlib::ParamSpec", etc... + +4.3 The method names +-------------------- + +In general the method names should be the same as the gstreamer ones, +with the g[st]_<class> prefix removed and converted to camel case. + +For example, + gboolean gst_caps_is_empty(const GstCaps *caps); +becomes: + bool isEmpty() const; +(and member of the QGst::Caps class) + +There are cases where this may not be followed: + +1) Properties. Most property getters have a "get" prefix, for example, +gst_object_get_name(). In QtGstreamer the "get" prefix is omitted, so this +becomes just name(). + +2) Overloaded members. In C there is no possibility to have two methods with +the same name, so overloaded members usually have some extra suffix, like "_full". +For example, g_object_set_data and g_object_set_data_full. In C++ we just add +a method with the same name, or put optional parameters in the existing method. + +3) Other cases where the glib/gstreamer method name doesn't make much sense... +For example, gst_element_is_locked_state(). That doesn't make sense in english, +as "state" is the subject and should go before the verb "is". +So, it becomes stateIsLocked(). + + +5. Refcounted wrappers policy +----------------------------- + +All reference counted classes must: +1) Inherit from QGlib::RefCountedObject and implement its virtual ref() and + unref() methods. +2) Include the QGLIB_WRAPPER (or QGST_WRAPPER) macro in their class declaration. + This is used like this: QGST_WRAPPER(ClassName). +3) Be used with QGlib::RefPointer<T> and provide a + typedef QGlib::RefPointer<ClassName> ClassNamePtr; + +No constructor/destructor/copy constructor/assignment operator is allowed for +these classes and they are all defined as private in the QGLIB_WRAPPER/QGST_WRAPPER +macros. + +RefPointer always creates a new instance of the wrapper class every time it is +copied, but it keeps the m_object protected variable of RefCountedObject pointing +to the same underlying glib/gstreamer object, using ref()/unref() to keep its +reference count correct. + + +6. About codegen +---------------- + +Codegen is a simple code generator that does two basic jobs: + + 1) It generates all the implementations of the QGlib::GetType<T> specializations. +GetType<T>() is used to get the GType of a type at runtime. Since we don't want +the target application to include any glib/gstreamer headers and/or link to +glib/gstreamer directly, this is the only way to be able to find the GType of +a class in a template class or method, such as RefPointer::dynamicCast(), +Value::init(), etc... + +The header declaration of all these specializations is added on the header of each +class, with the QGLIB_REGISTER_TYPE() macro. This defines the declaration of the +specialization and also acts as a keyword for codegen, which then generates the +implementation. + +The usage is simple. For example: QGLIB_REGISTER_TYPE(QGst::Element) +With this declaration, codegen will generate an implementation that returns +GST_TYPE_ELEMENT. + +If a class name doesn't exactly reflect its GType getter macro, then one can +tell codegen which is the real GType macro with a special "codegen instruction" +comment after the QGLIB_REGISTER_TYPE keyword that goes like this: + + //codegen: GType=GST_TYPE_FOO + +For example, QGLIB_REGISTER_TYPE(QGlib::ParamSpec) would generate an implementation +that returns G_TYPE_PARAM_SPEC. However, that macro doesn't really exist, the +correct one is G_TYPE_PARAM. So, we define it like this: + + QGLIB_REGISTER_TYPE(QGst::ParamSpec) //codegen: GType=G_TYPE_PARAM + + + 2) It generates static assertions for all the enums to make sure that their +value is exactly the same as their glib/gstreamer equivalent. This is just used +as a safety test for developers and doesn't have any impact on the library. + +Since, according to the coding style, all enums should be camel case, starting +with a capital and glib's coding style says all enums should be capitals with +underscores for separators, codegen does a style conversion to find out the +glib/gstreamer equivalent of the enum. An enum that is defined as: FooBar +in the namespace QGst will become GST_FOO_BAR. If an enum is defined in such a way +that the conversion is not accurate, then one can use a "codegen instruction" +after the opening brace of the enum definition that goes like this: + + //codegen: EnumToBeConverted=ENUM_HOW_IT_SHOULD_BE_CONVERTED, SecondEnum=SECONDENUM , ... + +This will assume that "EnumToBeConverted" is "GST_ENUM_HOW_IT_SHOULD_BE_CONVERTED" +(assuming that the namespace is QGst), and similar for "SecondEnum" -> GST_SECONDENUM + +A real world example: + +---- snip ---- +namespace QGst { + enum PadLinkReturn { + //codegen: PadLinkNoFormat=PAD_LINK_NOFORMAT, PadLinkNoSched=PAD_LINK_NOSCHED + PadLinkOk = 0, + PadLinkWrongHierarchy = -1, + PadLinkWasLinked = -2, + PadLinkWrongDirection = -3, + PadLinkNoFormat = -4, + PadLinkNoSched = -5, + PadLinkRefused = -6 + }; +} +QGLIB_REGISTER_TYPE(QGst::PadLinkReturn) +---- endsnip ---- + +For this snippet, codegen will generate: + +---- snip ---- +QGLIB_REGISTER_TYPE_IMPLEMENTATION(QGst::PadLinkReturn,GST_TYPE_PAD_LINK_RETURN) + +namespace QGst { + BOOST_STATIC_ASSERT(static_cast<int>(PadLinkOk) == static_cast<int>(GST_PAD_LINK_OK)); + BOOST_STATIC_ASSERT(static_cast<int>(PadLinkWrongHierarchy) == static_cast<int>(GST_PAD_LINK_WRONG_HIERARCHY)); + BOOST_STATIC_ASSERT(static_cast<int>(PadLinkWasLinked) == static_cast<int>(GST_PAD_LINK_WAS_LINKED)); + BOOST_STATIC_ASSERT(static_cast<int>(PadLinkWrongDirection) == static_cast<int>(GST_PAD_LINK_WRONG_DIRECTION)); + BOOST_STATIC_ASSERT(static_cast<int>(PadLinkNoFormat) == static_cast<int>(GST_PAD_LINK_NOFORMAT)); + BOOST_STATIC_ASSERT(static_cast<int>(PadLinkNoSched) == static_cast<int>(GST_PAD_LINK_NOSCHED)); + BOOST_STATIC_ASSERT(static_cast<int>(PadLinkRefused) == static_cast<int>(GST_PAD_LINK_REFUSED)); +} +---- endsnip ---- + + +7. How to contribute +-------------------- + +Simply clone the repository on gitorious, develop the feature that you want there +and when it's ready, send me a merge request. + + +-- +George Kiagiadakis <kiagiadakis.george@gmail.com> +14 April 2010 |