QtGStreamer 1.2.0
Loading...
Searching...
No Matches
signal.cpp
1/*
2 Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
3 Copyright (C) 2010 Collabora Ltd.
4 @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
5
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include "qglib_signal.h"
20#include "quark.h"
21#include <glib-object.h>
22#include <QtCore/QStringList>
23#include <QtCore/QDebug>
24
25//proper initializer for GValue structs on the stack
26#define QGLIB_G_VALUE_INITIALIZER {0, {{0}, {0}}}
27
28namespace QGlib {
29
30//BEGIN ******** Signal ********
31
32#ifndef DOXYGEN_RUN
33
34struct QTGLIB_NO_EXPORT Signal::Private : public QSharedData
35{
36 Private(uint i) : id(i), m_queryInitialized(false) {}
37
38 uint id;
39 GSignalQuery *query() const;
40
41private:
42 mutable GSignalQuery m_query;
43 mutable bool m_queryInitialized;
44};
45
46GSignalQuery *Signal::Private::query() const
47{
48 if (!m_queryInitialized) {
49 g_signal_query(id, &m_query);
50 m_queryInitialized = true;
51 }
52 return &m_query;
53}
54
55#endif //DOXYGEN_RUN
56
57Signal::Signal(uint id)
58 : d(new Private(id))
59{
60}
61
62Signal::Signal(const Signal & other)
63 : d(other.d)
64{
65}
66
67Signal & Signal::operator=(const Signal & other)
68{
69 d = other.d;
70 return *this;
71}
72
73Signal::~Signal()
74{
75}
76
77bool Signal::isValid() const
78{
79 return d->id != 0;
80}
81
82uint Signal::id() const
83{
84 return d->id;
85}
86
87QString Signal::name() const
88{
89 return QString::fromUtf8(d->query()->signal_name);
90}
91
92Signal::SignalFlags Signal::flags() const
93{
94 return QFlag(d->query()->signal_flags);
95}
96
97Type Signal::instanceType() const
98{
99 return d->query()->itype;
100}
101
102Type Signal::returnType() const
103{
104 return d->query()->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
105}
106
107QList<Type> Signal::paramTypes() const
108{
109 QList<Type> result;
110 for(uint i=0; i<d->query()->n_params; ++i) {
111 result.append(d->query()->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE);
112 }
113 return result;
114}
115
116//static
117Signal Signal::lookup(const char *name, Type type)
118{
119 return Signal(g_signal_lookup(name, type));
120}
121
122//static
123QList<Signal> Signal::listSignals(Type type)
124{
125 QList<Signal> result;
126 uint n_ids;
127 uint *ids = g_signal_list_ids(type, &n_ids);
128 for(uint i=0; i<n_ids; ++i) {
129 result.append(Signal(ids[i]));
130 }
131 g_free(ids);
132 return result;
133}
134
135//END ******** Signal ********
136
137namespace Private {
138
139//BEGIN ******** emit ********
140
141Value emit(void *instance, const char *detailedSignal, Quark detail, const QList<Value> & args)
142{
143 Value result;
144 Type itype = Type::fromInstance(instance);
145 QStringList signalParts = QString::fromUtf8(detailedSignal).split(QLatin1String("::"));
146 if (!detail && signalParts.size() > 1) {
147 detail = Quark::fromString(signalParts[1]);
148 }
149
150 //initialize arguments array
151 GValue *values = new GValue[args.size() + 1];
152 memset(values, 0, sizeof(GValue) * (args.size() + 1));
153
154 //set instance
155 g_value_init(&values[0], itype);
156 g_value_set_instance(&values[0], instance);
157
158 try {
159 //find the signal and perform sanity checks
160 Signal signal = Signal::lookup(signalParts[0].toUtf8(), itype);
161 if (!signal.isValid()) {
162 throw QString(QLatin1String("Could not find any signal named %1 "
163 "on this instance type")).arg(signalParts[0]);
164 }
165
166 QList<Type> paramTypes = signal.paramTypes();
167 if (paramTypes.size() != args.size()) {
168 throw QString(QLatin1String("The number of arguments that the signal accepts differ "
169 "from the number of arguments provided to emit"));
170 }
171
172 //set arguments
173 for(int i=0; i<args.size(); i++) {
174 if (!args[i].type().isA(paramTypes[i])) {
175 throw QString(QLatin1String("Argument %1 provided to emit is not of the "
176 "type that the signal expects")).arg(i);
177 } else {
178 g_value_init(&values[i+1], args[i].type());
179 g_value_copy(args[i], &values[i+1]);
180 }
181 }
182
183 //initialize return value
184 GValue returnValue = QGLIB_G_VALUE_INITIALIZER;
185 if (signal.returnType() != Type::None) {
186 g_value_init(&returnValue, signal.returnType());
187 }
188
189 //emit the signal
190 g_signal_emitv(values, signal.id(), detail, &returnValue);
191
192 if (G_IS_VALUE(&returnValue)) {
193 result = Value(&returnValue);
194 g_value_unset(&returnValue);
195 }
196 } catch (const QString & msg) {
197 QString instanceName = Value(&values[0]).toString();
198
199 qCritical() << "Error during emission of signal" << detailedSignal
200 << "on object"<< instanceName << ":" << msg;
201 }
202
203 //cleanup
204 for(int i=0; i<args.size() + 1; i++) {
205 g_value_unset(&values[i]);
206 }
207 delete[] values;
208
209 return result;
210}
211
212//END ******** emit ********
213
214} //namespace Private
215} //namespace QGlib
Wrapper class for GQuark.
Definition quark.h:43
Helper class providing introspection of GObject signals.
Wrapper class for GType.
Definition type.h:64
Wrapper class for GValue.
Definition value.h:77
Wrappers for Glib and GObject classes.