From 2e338b621c8e6cc9250814f95a1ab6910330d8db Mon Sep 17 00:00:00 2001 From: Mohammed Sameer Date: Sat, 22 Dec 2012 17:59:49 +0200 Subject: [PATCH] Added QtCamPropertySetter This class will catch added elements to a bin and set properties specified in a configuration file. --- lib/lib.pro | 4 +- lib/qtcamdevice.cpp | 9 +- lib/qtcamdevice_p.h | 2 + lib/qtcampropertysetter.cpp | 245 ++++++++++++++++++++++++++++++++++++ lib/qtcampropertysetter.h | 38 ++++++ 5 files changed, 292 insertions(+), 6 deletions(-) create mode 100644 lib/qtcampropertysetter.cpp create mode 100644 lib/qtcampropertysetter.h diff --git a/lib/lib.pro b/lib/lib.pro index ad3f7bb..38c797c 100644 --- a/lib/lib.pro +++ b/lib/lib.pro @@ -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 \ - qtcamanalysisbin.h + qtcamanalysisbin.h qtcampropertysetter.h 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 \ - 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 diff --git a/lib/qtcamdevice.cpp b/lib/qtcamdevice.cpp index bb5becc..a8430dc 100644 --- a/lib/qtcamdevice.cpp +++ b/lib/qtcamdevice.cpp @@ -30,6 +30,7 @@ #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) : @@ -52,6 +53,8 @@ QtCamDevice::QtCamDevice(QtCamConfig *config, const QString& name, return; } + d_ptr->propertySetter = new QtCamPropertySetter(d_ptr); + 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(); - // 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); @@ -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->propertySetter; + if (d_ptr->cameraBin) { gst_object_unref(d_ptr->cameraBin); } diff --git a/lib/qtcamdevice_p.h b/lib/qtcamdevice_p.h index 2e72654..818c843 100644 --- a/lib/qtcamdevice_p.h +++ b/lib/qtcamdevice_p.h @@ -35,6 +35,7 @@ class QtCamGStreamerMessageListener; class QtCamMode; class QtCamImageMode; class QtCamVideoMode; +class QtCamPropertySetter; class QtCamDevicePrivate { public: @@ -270,6 +271,7 @@ public: QtCamGStreamerMessageListener *listener; bool error; QtCamNotifications *notifications; + QtCamPropertySetter *propertySetter; }; #endif /* QT_CAM_DEVICE_P_H */ diff --git a/lib/qtcampropertysetter.cpp b/lib/qtcampropertysetter.cpp new file mode 100644 index 0000000..7d21e69 --- /dev/null +++ b/lib/qtcampropertysetter.cpp @@ -0,0 +1,245 @@ +/*! + * This file is part of CameraPlus. + * + * Copyright (C) 2012 Mohammed Sameer + * + * 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 +#include + +#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 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(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 index 0000000..b373eab --- /dev/null +++ b/lib/qtcampropertysetter.h @@ -0,0 +1,38 @@ +// -*- c++ -*- + +/*! + * This file is part of CameraPlus. + * + * Copyright (C) 2012 Mohammed Sameer + * + * 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 */ -- 2.25.1