QtGStreamer  1.2.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
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 
28 namespace QGlib {
29 
30 //BEGIN ******** Signal ********
31 
32 #ifndef DOXYGEN_RUN
33 
34 struct 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 
41 private:
42  mutable GSignalQuery m_query;
43  mutable bool m_queryInitialized;
44 };
45 
46 GSignalQuery *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 
57 Signal::Signal(uint id)
58  : d(new Private(id))
59 {
60 }
61 
62 Signal::Signal(const Signal & other)
63  : d(other.d)
64 {
65 }
66 
67 Signal & Signal::operator=(const Signal & other)
68 {
69  d = other.d;
70  return *this;
71 }
72 
73 Signal::~Signal()
74 {
75 }
76 
77 bool Signal::isValid() const
78 {
79  return d->id != 0;
80 }
81 
82 uint Signal::id() const
83 {
84  return d->id;
85 }
86 
87 QString Signal::name() const
88 {
89  return QString::fromUtf8(d->query()->signal_name);
90 }
91 
92 Signal::SignalFlags Signal::flags() const
93 {
94  return QFlag(d->query()->signal_flags);
95 }
96 
98 {
99  return d->query()->itype;
100 }
101 
103 {
104  return d->query()->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
105 }
106 
107 QList<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
117 Signal Signal::lookup(const char *name, Type type)
118 {
119  return Signal(g_signal_lookup(name, type));
120 }
121 
122 //static
123 QList<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 
137 namespace Private {
138 
139 //BEGIN ******** emit ********
140 
141 Value 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
static Quark fromString(const char *str)
Definition: quark.cpp:25
QString name() const
Returns the signal's name.
Definition: signal.cpp:87
Wrapper class for GValue.
Definition: value.h:74
QList< Type > paramTypes() const
Returns the types of the signal parameters.
Definition: signal.cpp:107
Type returnType() const
Returns the return Type of the signal.
Definition: signal.cpp:102
static QList< Signal > listSignals(Type type)
Definition: signal.cpp:123
bool isValid() const
Definition: signal.cpp:77
R emit(void *instance, const char *detailedSignal, const Args &...args)
Definition: emitimpl.h:111
uint id() const
Returns the signal's id.
Definition: signal.cpp:82
Type instanceType() const
Definition: signal.cpp:97
Helper class providing introspection of GObject signals.
Definition: qglib_signal.h:62
static Signal lookup(const char *name, Type type)
Definition: signal.cpp:117
Wrapper class for GQuark.
Definition: quark.h:42
Wrapper class for GType.
Definition: type.h:63
SignalFlags flags() const
Returns the signal's flags.
Definition: signal.cpp:92