Added QtCamPropertySetter
authorMohammed Sameer <msameer@foolab.org>
Sat, 22 Dec 2012 15:59:49 +0000 (17:59 +0200)
committerMohammed Sameer <msameer@foolab.org>
Sat, 22 Dec 2012 15:59:49 +0000 (17:59 +0200)
This class will catch added elements to a bin and set properties specified
in a configuration file.

lib/lib.pro
lib/qtcamdevice.cpp
lib/qtcamdevice_p.h
lib/qtcampropertysetter.cpp [new file with mode: 0644]
lib/qtcampropertysetter.h [new file with mode: 0644]

index ad3f7bb..38c797c 100644 (file)
@@ -19,7 +19,7 @@ HEADERS += qtcamconfig.h qtcamera.h qtcamscanner.h qtcamdevice.h qtcamviewfinder
            qtcamwhitebalance.h qtcamcolortone.h qtcamflickerreduction.h \
            qtcamnoisereduction.h qtcamiso.h qtcamaperture.h qtcamexposure.h \
            qtcamvideomute.h qtcamnotifications.h qtcamfocus.h qtcamautofocus.h \
            qtcamwhitebalance.h qtcamcolortone.h qtcamflickerreduction.h \
            qtcamnoisereduction.h qtcamiso.h qtcamaperture.h qtcamexposure.h \
            qtcamvideomute.h qtcamnotifications.h qtcamfocus.h qtcamautofocus.h \
-           qtcamanalysisbin.h
+           qtcamanalysisbin.h qtcampropertysetter.h
 
 SOURCES += qtcamconfig.cpp qtcamera.cpp qtcamscanner.cpp qtcamdevice.cpp qtcamviewfinder.cpp \
            qtcammode.cpp qtcamgstreamermessagehandler.cpp qtcamgstreamermessagelistener.cpp \
 
 SOURCES += qtcamconfig.cpp qtcamera.cpp qtcamscanner.cpp qtcamdevice.cpp qtcamviewfinder.cpp \
            qtcammode.cpp qtcamgstreamermessagehandler.cpp qtcamgstreamermessagelistener.cpp \
@@ -30,7 +30,7 @@ SOURCES += qtcamconfig.cpp qtcamera.cpp qtcamscanner.cpp qtcamdevice.cpp qtcamvi
            qtcamwhitebalance.cpp qtcamcolortone.cpp qtcamflickerreduction.cpp \
            qtcamnoisereduction.cpp qtcamiso.cpp qtcamaperture.cpp qtcamexposure.cpp \
            qtcamvideomute.cpp qtcamnotifications.cpp qtcamfocus.cpp qtcamautofocus.cpp \
            qtcamwhitebalance.cpp qtcamcolortone.cpp qtcamflickerreduction.cpp \
            qtcamnoisereduction.cpp qtcamiso.cpp qtcamaperture.cpp qtcamexposure.cpp \
            qtcamvideomute.cpp qtcamnotifications.cpp qtcamfocus.cpp qtcamautofocus.cpp \
-           qtcamanalysisbin.cpp
+           qtcamanalysisbin.cpp qtcampropertysetter.cpp
 
 HEADERS += qtcammode_p.h qtcamdevice_p.h qtcamcapability_p.h qtcamautofocus_p.h \
            qtcamnotifications_p.h qtcamflash_p.h
 
 HEADERS += qtcammode_p.h qtcamdevice_p.h qtcamcapability_p.h qtcamautofocus_p.h \
            qtcamnotifications_p.h qtcamflash_p.h
index bb5becc..a8430dc 100644 (file)
@@ -30,6 +30,7 @@
 #include "qtcamvideomode.h"
 #include "qtcamnotifications.h"
 #include "gst/gstcopy.h"
 #include "qtcamvideomode.h"
 #include "qtcamnotifications.h"
 #include "gst/gstcopy.h"
+#include "qtcampropertysetter.h"
 
 QtCamDevice::QtCamDevice(QtCamConfig *config, const QString& name,
                         const QVariant& id, QObject *parent) :
 
 QtCamDevice::QtCamDevice(QtCamConfig *config, const QString& name,
                         const QVariant& id, QObject *parent) :
@@ -52,6 +53,8 @@ QtCamDevice::QtCamDevice(QtCamConfig *config, const QString& name,
     return;
   }
 
     return;
   }
 
+  d_ptr->propertySetter = new QtCamPropertySetter(d_ptr);
+
   d_ptr->createAndAddElement(d_ptr->conf->audioSource(), "audio-source", "QtCameraAudioSrc");
   d_ptr->createAndAddVideoSource();
 
   d_ptr->createAndAddElement(d_ptr->conf->audioSource(), "audio-source", "QtCameraAudioSrc");
   d_ptr->createAndAddVideoSource();
 
@@ -66,10 +69,6 @@ QtCamDevice::QtCamDevice(QtCamConfig *config, const QString& name,
   d_ptr->setAudioCaptureCaps();
   d_ptr->addViewfinderFilters();
 
   d_ptr->setAudioCaptureCaps();
   d_ptr->addViewfinderFilters();
 
-  // TODO: audio bitrate
-  // TODO: video bitrate
-
-  // TODO: custom properties for jifmux, mp4mux, audio encoder, video encoder, sink & video source
   d_ptr->listener = new QtCamGStreamerMessageListener(gst_element_get_bus(d_ptr->cameraBin),
                                                      d_ptr, this);
 
   d_ptr->listener = new QtCamGStreamerMessageListener(gst_element_get_bus(d_ptr->cameraBin),
                                                      d_ptr, this);
 
@@ -100,6 +99,8 @@ QtCamDevice::~QtCamDevice() {
   delete d_ptr->image; d_ptr->image = 0;
   delete d_ptr->video; d_ptr->video = 0;
 
   delete d_ptr->image; d_ptr->image = 0;
   delete d_ptr->video; d_ptr->video = 0;
 
+  delete d_ptr->propertySetter;
+
   if (d_ptr->cameraBin) {
     gst_object_unref(d_ptr->cameraBin);
   }
   if (d_ptr->cameraBin) {
     gst_object_unref(d_ptr->cameraBin);
   }
index 2e72654..818c843 100644 (file)
@@ -35,6 +35,7 @@ class QtCamGStreamerMessageListener;
 class QtCamMode;
 class QtCamImageMode;
 class QtCamVideoMode;
 class QtCamMode;
 class QtCamImageMode;
 class QtCamVideoMode;
+class QtCamPropertySetter;
 
 class QtCamDevicePrivate {
 public:
 
 class QtCamDevicePrivate {
 public:
@@ -270,6 +271,7 @@ public:
   QtCamGStreamerMessageListener *listener;
   bool error;
   QtCamNotifications *notifications;
   QtCamGStreamerMessageListener *listener;
   bool error;
   QtCamNotifications *notifications;
+  QtCamPropertySetter *propertySetter;
 };
 
 #endif /* QT_CAM_DEVICE_P_H */
 };
 
 #endif /* QT_CAM_DEVICE_P_H */
diff --git a/lib/qtcampropertysetter.cpp b/lib/qtcampropertysetter.cpp
new file mode 100644 (file)
index 0000000..7d21e69
--- /dev/null
@@ -0,0 +1,245 @@
+/*!
+ * This file is part of CameraPlus.
+ *
+ * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "qtcampropertysetter.h"
+#include "qtcamdevice_p.h"
+#include <QSettings>
+#include <QDebug>
+
+#define PROPERTIES_FILE                       "/etc/qtcamera/properties.ini"
+
+class QtCamPropertySetterPrivate {
+public:
+  void binAdded(GstElement *bin) {
+    g_signal_connect(bin, "element-added",
+                    G_CALLBACK(QtCamPropertySetterPrivate::element_added), this);
+
+    setProperties(bin);
+
+    // Let's traverse its children:
+    GstIterator *iter = gst_bin_iterate_elements(GST_BIN(bin));
+    if (!iter) {
+      return;
+    }
+
+    bool done = false;
+    GstElement *elem = 0;
+
+    while (!done) {
+      switch (gst_iterator_next(iter, (gpointer *)&elem)) {
+      case GST_ITERATOR_OK:
+       if (GST_IS_BIN(elem)) {
+         binAdded(elem);
+       }
+       else {
+         setProperties(elem);
+       }
+
+       gst_object_unref(elem);
+       break;
+      case GST_ITERATOR_RESYNC:
+       gst_iterator_resync(iter);
+       break;
+      case GST_ITERATOR_ERROR:
+       done = TRUE;
+       break;
+      case GST_ITERATOR_DONE:
+       done = TRUE;
+       break;
+      }
+    }
+  }
+
+  void setProperties(GstElement *element) {
+    QLatin1String name = elementName(element);
+    if (!name.latin1()) {
+      return;
+    }
+
+    QVariantMap map = properties(name);
+    if (map.isEmpty()) {
+      return;
+    }
+
+    QStringList keys = map.keys();
+    foreach (const QString& key, keys) {
+      QVariant value = map[key];
+      GParamSpec *pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(element),
+                                                      key.toUtf8().constData());
+      if (!pspec) {
+       qWarning() << "Property" << key << "not available for" << name;
+       continue;
+      }
+
+      GType type = getType(pspec->value_type);
+
+      switch (type) {
+      case G_TYPE_INT:
+      case G_TYPE_ENUM:
+       setInt(element, key, value);
+       break;
+      case G_TYPE_UINT:
+       setUnsignedInt(element, key, value);
+       break;
+      case G_TYPE_STRING:
+       setString(element, key, value);
+       break;
+      case G_TYPE_BOOLEAN:
+       setBoolean(element, key, value);
+       break;
+      default:
+       if (type == gstFraction) {
+         setFraction(element, key, value);
+         break;
+       }
+
+       qWarning() << "Unsupported property type"
+                  << g_type_name(pspec->value_type) << "of parent" << g_type_name(type)
+                  << "for" << key << "of element" << name;
+       break;
+      }
+    }
+  }
+
+  QVariantMap properties(const QLatin1String& name) {
+    QVariantMap map;
+
+    conf->beginGroup(name);
+
+    QStringList keys = conf->allKeys();
+    foreach (const QString& key, keys) {
+      map[key] = conf->value(key);
+    }
+
+    conf->endGroup();
+    return map;
+  }
+
+  QLatin1String elementName(GstElement *elem) {
+    GstElementFactory *factory = gst_element_get_factory(elem);
+    if (!factory) {
+      return QLatin1String(0);
+    }
+
+    const char *n = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));
+    if (!n) {
+      return QLatin1String(0);
+    }
+
+    QLatin1String name(n);
+
+    return name;
+  }
+
+  void setInt(GstElement *elem, const QString& key, const QVariant& value) {
+    if (!value.canConvert(QVariant::Int)) {
+      qWarning() << "Cannot convert" << value << "to int";
+      return;
+    }
+
+    g_object_set(elem, key.toUtf8().constData(), value.toInt(), NULL);
+  }
+
+  void setUnsignedInt(GstElement *elem, const QString& key, const QVariant& value) {
+    if (!value.canConvert(QVariant::UInt)) {
+      qWarning() << "Cannot convert" << value << "to unsigned int";
+      return;
+    }
+
+    g_object_set(elem, key.toUtf8().constData(), value.toUInt(), NULL);
+  }
+
+  void setString(GstElement *elem, const QString& key, const QVariant& value) {
+    if (!value.canConvert(QVariant::String)) {
+      qWarning() << "Cannot convert" << value << "to string";
+      return;
+    }
+
+    g_object_set(elem, key.toUtf8().constData(), value.toString().toUtf8().constData(), NULL);
+  }
+
+  void setBoolean(GstElement *elem, const QString& key, const QVariant& value) {
+    if (!value.canConvert(QVariant::Bool)) {
+      qWarning() << "Cannot convert" << value << "to bool";
+      return;
+    }
+
+    g_object_set(elem, key.toUtf8().constData(), value.toBool() ? TRUE : FALSE, NULL);
+  }
+
+  void setFraction(GstElement *elem, const QString& key, const QVariant& value) {
+    if (!value.canConvert(QVariant::List)) {
+      qWarning() << "Cannot convert" << value << "to list";
+      return;
+    }
+
+    QList<QVariant> list = value.toList();
+    if (list.size() != 2) {
+      qWarning() << "fraction list must contain 2 items";
+      return;
+    }
+
+    if (!list[0].canConvert(QVariant::Int) || !list[1].canConvert(QVariant::Int)) {
+      qWarning() << "list items cannot be converted to int";
+      return;
+    }
+
+    int val1 = list[0].toInt();
+    int val2 = list[1].toInt();
+
+    g_object_set(elem, key.toUtf8().constData(), val1, val2, NULL);
+  }
+
+  GType getType(GType parent) {
+    if (G_TYPE_IS_FUNDAMENTAL(parent)) {
+      return parent;
+    }
+
+    return getType(g_type_parent(parent));
+  }
+
+  static void element_added(GstBin *bin, GstElement *child, gpointer user_data) {
+    Q_UNUSED(bin);
+
+    QtCamPropertySetterPrivate *d = static_cast<QtCamPropertySetterPrivate *>(user_data);
+
+    if (GST_IS_BIN(child)) {
+      d->binAdded(child);
+    }
+    else {
+      d->setProperties(child);
+    }
+  }
+
+  QSettings *conf;
+  GType gstFraction;
+};
+
+QtCamPropertySetter::QtCamPropertySetter(QtCamDevicePrivate *pvt) :
+  d_ptr(new QtCamPropertySetterPrivate) {
+  d_ptr->conf = new QSettings(PROPERTIES_FILE, QSettings::IniFormat);
+  d_ptr->gstFraction = GST_TYPE_FRACTION;
+  d_ptr->binAdded(pvt->cameraBin);
+}
+
+QtCamPropertySetter::~QtCamPropertySetter() {
+  delete d_ptr->conf; d_ptr->conf = 0;
+  delete d_ptr; d_ptr = 0;
+}
diff --git a/lib/qtcampropertysetter.h b/lib/qtcampropertysetter.h
new file mode 100644 (file)
index 0000000..b373eab
--- /dev/null
@@ -0,0 +1,38 @@
+// -*- c++ -*-
+
+/*!
+ * This file is part of CameraPlus.
+ *
+ * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef QT_CAM_PROPERTY_SETTER_H
+#define QT_CAM_PROPERTY_SETTER_H
+
+class QtCamDevicePrivate;
+class QtCamPropertySetterPrivate;
+
+class QtCamPropertySetter {
+public:
+  QtCamPropertySetter(QtCamDevicePrivate *pvt);
+  ~QtCamPropertySetter();
+
+private:
+  QtCamPropertySetterPrivate *d_ptr;
+};
+
+#endif /* QT_CAM_PROPERTY_SETTER_H */