QtGStreamer 0.10.1
|
00001 /* 00002 Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com> 00003 Copyright (C) 2010 Collabora Ltd. 00004 @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk> 00005 00006 This library is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU Lesser General Public License as published 00008 by the Free Software Foundation; either version 2.1 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU Lesser General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 #include "signal.h" 00020 #include "quark.h" 00021 #include <glib-object.h> 00022 #include <QtCore/QStringList> 00023 #include <QtCore/QDebug> 00024 00025 //proper initializer for GValue structs on the stack 00026 #define QGLIB_G_VALUE_INITIALIZER {0, {{0}, {0}}} 00027 00028 namespace QGlib { 00029 00030 //BEGIN ******** Signal ******** 00031 00032 #ifndef DOXYGEN_RUN 00033 00034 struct QTGLIB_NO_EXPORT Signal::Private : public QSharedData 00035 { 00036 Private(uint i) : id(i), m_queryInitialized(false) {} 00037 00038 uint id; 00039 GSignalQuery *query() const; 00040 00041 private: 00042 mutable GSignalQuery m_query; 00043 mutable bool m_queryInitialized; 00044 }; 00045 00046 GSignalQuery *Signal::Private::query() const 00047 { 00048 if (!m_queryInitialized) { 00049 g_signal_query(id, &m_query); 00050 m_queryInitialized = true; 00051 } 00052 return &m_query; 00053 } 00054 00055 #endif //DOXYGEN_RUN 00056 00057 Signal::Signal(uint id) 00058 : d(new Private(id)) 00059 { 00060 } 00061 00062 Signal::Signal(const Signal & other) 00063 : d(other.d) 00064 { 00065 } 00066 00067 Signal & Signal::operator=(const Signal & other) 00068 { 00069 d = other.d; 00070 return *this; 00071 } 00072 00073 Signal::~Signal() 00074 { 00075 } 00076 00077 bool Signal::isValid() const 00078 { 00079 return d->id != 0; 00080 } 00081 00082 uint Signal::id() const 00083 { 00084 return d->id; 00085 } 00086 00087 QString Signal::name() const 00088 { 00089 return QString::fromUtf8(d->query()->signal_name); 00090 } 00091 00092 Signal::SignalFlags Signal::flags() const 00093 { 00094 return QFlag(d->query()->signal_flags); 00095 } 00096 00097 Type Signal::instanceType() const 00098 { 00099 return d->query()->itype; 00100 } 00101 00102 Type Signal::returnType() const 00103 { 00104 return d->query()->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE; 00105 } 00106 00107 QList<Type> Signal::paramTypes() const 00108 { 00109 QList<Type> result; 00110 for(uint i=0; i<d->query()->n_params; ++i) { 00111 result.append(d->query()->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE); 00112 } 00113 return result; 00114 } 00115 00116 //static 00117 Signal Signal::lookup(const char *name, Type type) 00118 { 00119 return Signal(g_signal_lookup(name, type)); 00120 } 00121 00122 //static 00123 QList<Signal> Signal::listSignals(Type type) 00124 { 00125 QList<Signal> result; 00126 uint n_ids; 00127 uint *ids = g_signal_list_ids(type, &n_ids); 00128 for(uint i=0; i<n_ids; ++i) { 00129 result.append(Signal(ids[i])); 00130 } 00131 g_free(ids); 00132 return result; 00133 } 00134 00135 //END ******** Signal ******** 00136 00137 namespace Private { 00138 00139 //BEGIN ******** emit ******** 00140 00141 Value emit(void *instance, const char *detailedSignal, Quark detail, const QList<Value> & args) 00142 { 00143 Value result; 00144 Type itype = Type::fromInstance(instance); 00145 QStringList signalParts = QString::fromUtf8(detailedSignal).split(QLatin1String("::")); 00146 if (!detail && signalParts.size() > 1) { 00147 detail = Quark::fromString(signalParts[1]); 00148 } 00149 00150 //initialize arguments array 00151 GValue *values = new GValue[args.size() + 1]; 00152 memset(values, 0, sizeof(GValue) * (args.size() + 1)); 00153 00154 //set instance 00155 g_value_init(&values[0], itype); 00156 g_value_set_instance(&values[0], instance); 00157 00158 try { 00159 //find the signal and perform sanity checks 00160 Signal signal = Signal::lookup(signalParts[0].toUtf8(), itype); 00161 if (!signal.isValid()) { 00162 throw QString(QLatin1String("Could not find any signal named %1 " 00163 "on this instance type")).arg(signalParts[0]); 00164 } 00165 00166 QList<Type> paramTypes = signal.paramTypes(); 00167 if (paramTypes.size() != args.size()) { 00168 throw QString(QLatin1String("The number of arguments that the signal accepts differ " 00169 "from the number of arguments provided to emit")); 00170 } 00171 00172 //set arguments 00173 for(int i=0; i<args.size(); i++) { 00174 if (!args[i].type().isA(paramTypes[i])) { 00175 throw QString(QLatin1String("Argument %1 provided to emit is not of the " 00176 "type that the signal expects")).arg(i); 00177 } else { 00178 g_value_init(&values[i+1], args[i].type()); 00179 g_value_copy(args[i], &values[i+1]); 00180 } 00181 } 00182 00183 //initialize return value 00184 GValue returnValue = QGLIB_G_VALUE_INITIALIZER; 00185 if (signal.returnType() != Type::None) { 00186 g_value_init(&returnValue, signal.returnType()); 00187 } 00188 00189 //emit the signal 00190 g_signal_emitv(values, signal.id(), detail, &returnValue); 00191 00192 if (G_IS_VALUE(&returnValue)) { 00193 result = Value(&returnValue); 00194 g_value_unset(&returnValue); 00195 } 00196 } catch (const QString & msg) { 00197 QString instanceName = Value(&values[0]).toString(); 00198 00199 qCritical() << "Error during emission of signal" << detailedSignal 00200 << "on object"<< instanceName << ":" << msg; 00201 } 00202 00203 //cleanup 00204 for(int i=0; i<args.size() + 1; i++) { 00205 g_value_unset(&values[i]); 00206 } 00207 delete[] values; 00208 00209 return result; 00210 } 00211 00212 //END ******** emit ******** 00213 00214 } //namespace Private 00215 } //namespace QGlib