1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** All rights reserved.
|
---|
5 | ** Contact: Nokia Corporation (qt-info@nokia.com)
|
---|
6 | **
|
---|
7 | ** This file is part of the plugins of the Qt Toolkit.
|
---|
8 | **
|
---|
9 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
10 | ** Commercial Usage
|
---|
11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
14 | ** a written agreement between you and Nokia.
|
---|
15 | **
|
---|
16 | ** GNU Lesser General Public License Usage
|
---|
17 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
18 | ** General Public License version 2.1 as published by the Free Software
|
---|
19 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
20 | ** packaging of this file. Please review the following information to
|
---|
21 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
23 | **
|
---|
24 | ** In addition, as a special exception, Nokia gives you certain additional
|
---|
25 | ** rights. These rights are described in the Nokia Qt LGPL Exception
|
---|
26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
---|
27 | **
|
---|
28 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you have questions regarding the use of this file, please contact
|
---|
37 | ** Nokia at qt-info@nokia.com.
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 |
|
---|
43 | #include <QDebug>
|
---|
44 | #include <QtCore>
|
---|
45 | #include <poll.h>
|
---|
46 | #include <dbus/dbus.h>
|
---|
47 | #include <dbus/dbus-glib-lowlevel.h>
|
---|
48 | #include <glib.h>
|
---|
49 | #include "dbusdispatcher.h"
|
---|
50 |
|
---|
51 | namespace Maemo {
|
---|
52 |
|
---|
53 | /*!
|
---|
54 | \class DBusDispatcher
|
---|
55 |
|
---|
56 | \brief DBusDispatcher is a class, which is able to send DBUS method call
|
---|
57 | messages and receive unicast signals from DBUS object.
|
---|
58 | */
|
---|
59 |
|
---|
60 | class DBusDispatcherPrivate
|
---|
61 | {
|
---|
62 | public:
|
---|
63 | DBusDispatcherPrivate(const QString& service,
|
---|
64 | const QString& path,
|
---|
65 | const QString& interface,
|
---|
66 | const QString& signalPath)
|
---|
67 | : service(service), path(path), interface(interface),
|
---|
68 | signalPath(signalPath), connection(0)
|
---|
69 | {
|
---|
70 | memset(&signal_vtable, 0, sizeof(signal_vtable));
|
---|
71 | }
|
---|
72 |
|
---|
73 | ~DBusDispatcherPrivate()
|
---|
74 | {
|
---|
75 | foreach(DBusPendingCall *call, pending_calls) {
|
---|
76 | dbus_pending_call_cancel(call);
|
---|
77 | dbus_pending_call_unref(call);
|
---|
78 | }
|
---|
79 | }
|
---|
80 |
|
---|
81 | QString service;
|
---|
82 | QString path;
|
---|
83 | QString interface;
|
---|
84 | QString signalPath;
|
---|
85 | struct DBusConnection *connection;
|
---|
86 | QList<DBusPendingCall *> pending_calls;
|
---|
87 | struct DBusObjectPathVTable signal_vtable;
|
---|
88 | };
|
---|
89 |
|
---|
90 | static bool constantVariantList(const QVariantList& variantList) {
|
---|
91 | // Special case, empty list == empty struct
|
---|
92 | if (variantList.isEmpty()) {
|
---|
93 | return false;
|
---|
94 | } else {
|
---|
95 | QVariant::Type type = variantList[0].type();
|
---|
96 | // Iterate items in the list and check if they are same type
|
---|
97 | foreach(QVariant variant, variantList) {
|
---|
98 | if (variant.type() != type) {
|
---|
99 | return false;
|
---|
100 | }
|
---|
101 | }
|
---|
102 | }
|
---|
103 | return true;
|
---|
104 | }
|
---|
105 |
|
---|
106 | static QString variantToSignature(const QVariant& argument,
|
---|
107 | bool constantList = true) {
|
---|
108 | switch (argument.type()) {
|
---|
109 | case QVariant::Bool:
|
---|
110 | return "b";
|
---|
111 | case QVariant::ByteArray:
|
---|
112 | return "ay";
|
---|
113 | case QVariant::Char:
|
---|
114 | return "y";
|
---|
115 | case QVariant::Int:
|
---|
116 | return "i";
|
---|
117 | case QVariant::UInt:
|
---|
118 | return "u";
|
---|
119 | case QVariant::StringList:
|
---|
120 | return "as";
|
---|
121 | case QVariant::String:
|
---|
122 | return "s";
|
---|
123 | case QVariant::LongLong:
|
---|
124 | return "x";
|
---|
125 | case QVariant::ULongLong:
|
---|
126 | return "t";
|
---|
127 | case QVariant::List:
|
---|
128 | {
|
---|
129 | QString signature;
|
---|
130 | QVariantList variantList = argument.toList();
|
---|
131 | if (!constantList) {
|
---|
132 | signature += DBUS_STRUCT_BEGIN_CHAR_AS_STRING;
|
---|
133 | foreach(QVariant listItem, variantList) {
|
---|
134 | signature += variantToSignature(listItem);
|
---|
135 | }
|
---|
136 | signature += DBUS_STRUCT_END_CHAR_AS_STRING;
|
---|
137 | } else {
|
---|
138 | if (variantList.isEmpty())
|
---|
139 | return "";
|
---|
140 | signature = "a" + variantToSignature(variantList[0]);
|
---|
141 | }
|
---|
142 |
|
---|
143 | return signature;
|
---|
144 | }
|
---|
145 | default:
|
---|
146 | qDebug() << "Unsupported variant type: " << argument.type();
|
---|
147 | break;
|
---|
148 | }
|
---|
149 |
|
---|
150 | return "";
|
---|
151 | }
|
---|
152 |
|
---|
153 | static bool appendVariantToDBusMessage(const QVariant& argument,
|
---|
154 | DBusMessageIter *dbus_iter) {
|
---|
155 | int idx = 0;
|
---|
156 | DBusMessageIter array_iter;
|
---|
157 | QStringList str_list;
|
---|
158 | dbus_bool_t bool_data;
|
---|
159 | dbus_int32_t int32_data;
|
---|
160 | dbus_uint32_t uint32_data;
|
---|
161 | dbus_int64_t int64_data;
|
---|
162 | dbus_uint64_t uint64_data;
|
---|
163 | char *str_data;
|
---|
164 | char char_data;
|
---|
165 |
|
---|
166 | switch (argument.type()) {
|
---|
167 |
|
---|
168 | case QVariant::Bool:
|
---|
169 | bool_data = argument.toBool();
|
---|
170 | dbus_message_iter_append_basic(dbus_iter, DBUS_TYPE_BOOLEAN,
|
---|
171 | &bool_data);
|
---|
172 | break;
|
---|
173 |
|
---|
174 | case QVariant::ByteArray:
|
---|
175 | str_data = argument.toByteArray().data();
|
---|
176 | dbus_message_iter_open_container(dbus_iter, DBUS_TYPE_ARRAY,
|
---|
177 | DBUS_TYPE_BYTE_AS_STRING, &array_iter);
|
---|
178 | dbus_message_iter_append_fixed_array(&array_iter,
|
---|
179 | DBUS_TYPE_BYTE,
|
---|
180 | &str_data,
|
---|
181 | argument.toByteArray().size());
|
---|
182 | dbus_message_iter_close_container(dbus_iter, &array_iter);
|
---|
183 | break;
|
---|
184 |
|
---|
185 | case QVariant::Char:
|
---|
186 | char_data = argument.toChar().toAscii();
|
---|
187 | dbus_message_iter_append_basic(dbus_iter, DBUS_TYPE_BYTE,
|
---|
188 | &char_data);
|
---|
189 | break;
|
---|
190 |
|
---|
191 | case QVariant::Int:
|
---|
192 | int32_data = argument.toInt();
|
---|
193 | dbus_message_iter_append_basic(dbus_iter, DBUS_TYPE_INT32,
|
---|
194 | &int32_data);
|
---|
195 | break;
|
---|
196 |
|
---|
197 | case QVariant::String:
|
---|
198 | str_data = argument.toString().toLatin1().data();
|
---|
199 | dbus_message_iter_append_basic(dbus_iter, DBUS_TYPE_STRING,
|
---|
200 | &str_data);
|
---|
201 | break;
|
---|
202 |
|
---|
203 | case QVariant::StringList:
|
---|
204 | str_list = argument.toStringList();
|
---|
205 | dbus_message_iter_open_container(dbus_iter, DBUS_TYPE_ARRAY,
|
---|
206 | "s", &array_iter);
|
---|
207 | for (idx = 0; idx < str_list.size(); idx++) {
|
---|
208 | str_data = str_list.at(idx).toLatin1().data();
|
---|
209 | dbus_message_iter_append_basic(&array_iter,
|
---|
210 | DBUS_TYPE_STRING,
|
---|
211 | &str_data);
|
---|
212 | }
|
---|
213 | dbus_message_iter_close_container(dbus_iter, &array_iter);
|
---|
214 | break;
|
---|
215 |
|
---|
216 | case QVariant::UInt:
|
---|
217 | uint32_data = argument.toUInt();
|
---|
218 | dbus_message_iter_append_basic(dbus_iter, DBUS_TYPE_UINT32,
|
---|
219 | &uint32_data);
|
---|
220 | break;
|
---|
221 |
|
---|
222 | case QVariant::ULongLong:
|
---|
223 | uint64_data = argument.toULongLong();
|
---|
224 | dbus_message_iter_append_basic(dbus_iter, DBUS_TYPE_UINT64,
|
---|
225 | &uint64_data);
|
---|
226 | break;
|
---|
227 |
|
---|
228 | case QVariant::LongLong:
|
---|
229 | int64_data = argument.toLongLong();
|
---|
230 | dbus_message_iter_append_basic(dbus_iter, DBUS_TYPE_INT64,
|
---|
231 | &int64_data);
|
---|
232 | break;
|
---|
233 |
|
---|
234 | case QVariant::List:
|
---|
235 | {
|
---|
236 | QVariantList variantList = argument.toList();
|
---|
237 | bool constantList = constantVariantList(variantList);
|
---|
238 | DBusMessageIter array_iter;
|
---|
239 |
|
---|
240 | // List is mapped either as an DBUS array (all items same type)
|
---|
241 | // DBUS struct (variable types) depending on constantList
|
---|
242 | if (constantList) {
|
---|
243 | // Resolve the signature for the first item
|
---|
244 | QString signature = "";
|
---|
245 | if (!variantList.isEmpty()) {
|
---|
246 | signature = variantToSignature(
|
---|
247 | variantList[0],
|
---|
248 | constantVariantList(variantList[0].toList()));
|
---|
249 | }
|
---|
250 |
|
---|
251 | // Mapped as DBUS array
|
---|
252 | dbus_message_iter_open_container(dbus_iter, DBUS_TYPE_ARRAY,
|
---|
253 | signature.toAscii(),
|
---|
254 | &array_iter);
|
---|
255 |
|
---|
256 | foreach(QVariant listItem, variantList) {
|
---|
257 | appendVariantToDBusMessage(listItem, &array_iter);
|
---|
258 | }
|
---|
259 |
|
---|
260 | dbus_message_iter_close_container(dbus_iter, &array_iter);
|
---|
261 | } else {
|
---|
262 | // Mapped as DBUS struct
|
---|
263 | dbus_message_iter_open_container(dbus_iter, DBUS_TYPE_STRUCT,
|
---|
264 | NULL,
|
---|
265 | &array_iter);
|
---|
266 |
|
---|
267 | foreach(QVariant listItem, variantList) {
|
---|
268 | appendVariantToDBusMessage(listItem, &array_iter);
|
---|
269 | }
|
---|
270 |
|
---|
271 | dbus_message_iter_close_container(dbus_iter, &array_iter);
|
---|
272 | }
|
---|
273 |
|
---|
274 | break;
|
---|
275 | }
|
---|
276 | default:
|
---|
277 | qDebug() << "Unsupported variant type: " << argument.type();
|
---|
278 | break;
|
---|
279 | }
|
---|
280 |
|
---|
281 | return true;
|
---|
282 | }
|
---|
283 |
|
---|
284 | static QVariant getVariantFromDBusMessage(DBusMessageIter *iter) {
|
---|
285 | dbus_bool_t bool_data;
|
---|
286 | dbus_int32_t int32_data;
|
---|
287 | dbus_uint32_t uint32_data;
|
---|
288 | dbus_int64_t int64_data;
|
---|
289 | dbus_uint64_t uint64_data;
|
---|
290 | char *str_data;
|
---|
291 | char char_data;
|
---|
292 | int argtype = dbus_message_iter_get_arg_type(iter);
|
---|
293 |
|
---|
294 | switch (argtype) {
|
---|
295 |
|
---|
296 | case DBUS_TYPE_BOOLEAN:
|
---|
297 | {
|
---|
298 | dbus_message_iter_get_basic(iter, &bool_data);
|
---|
299 | QVariant variant((bool)bool_data);
|
---|
300 | return variant;
|
---|
301 | }
|
---|
302 |
|
---|
303 | case DBUS_TYPE_ARRAY:
|
---|
304 | {
|
---|
305 | // Handle all arrays here
|
---|
306 | int elem_type = dbus_message_iter_get_element_type(iter);
|
---|
307 | DBusMessageIter array_iter;
|
---|
308 |
|
---|
309 | dbus_message_iter_recurse(iter, &array_iter);
|
---|
310 |
|
---|
311 | if (elem_type == DBUS_TYPE_BYTE) {
|
---|
312 | QByteArray byte_array;
|
---|
313 | do {
|
---|
314 | dbus_message_iter_get_basic(&array_iter, &char_data);
|
---|
315 | byte_array.append(char_data);
|
---|
316 | } while (dbus_message_iter_next(&array_iter));
|
---|
317 | QVariant variant(byte_array);
|
---|
318 | return variant;
|
---|
319 | } else if (elem_type == DBUS_TYPE_STRING) {
|
---|
320 | QStringList str_list;
|
---|
321 | do {
|
---|
322 | dbus_message_iter_get_basic(&array_iter, &str_data);
|
---|
323 | str_list.append(str_data);
|
---|
324 | } while (dbus_message_iter_next(&array_iter));
|
---|
325 | QVariant variant(str_list);
|
---|
326 | return variant;
|
---|
327 | } else {
|
---|
328 | QVariantList variantList;
|
---|
329 | do {
|
---|
330 | variantList << getVariantFromDBusMessage(&array_iter);
|
---|
331 | } while (dbus_message_iter_next(&array_iter));
|
---|
332 | QVariant variant(variantList);
|
---|
333 | return variant;
|
---|
334 | }
|
---|
335 | break;
|
---|
336 | }
|
---|
337 |
|
---|
338 | case DBUS_TYPE_BYTE:
|
---|
339 | {
|
---|
340 | dbus_message_iter_get_basic(iter, &char_data);
|
---|
341 | QChar ch(char_data);
|
---|
342 | QVariant variant(ch);
|
---|
343 | return variant;
|
---|
344 | }
|
---|
345 |
|
---|
346 | case DBUS_TYPE_INT32:
|
---|
347 | {
|
---|
348 | dbus_message_iter_get_basic(iter, &int32_data);
|
---|
349 | QVariant variant((int)int32_data);
|
---|
350 | return variant;
|
---|
351 | }
|
---|
352 |
|
---|
353 | case DBUS_TYPE_UINT32:
|
---|
354 | {
|
---|
355 | dbus_message_iter_get_basic(iter, &uint32_data);
|
---|
356 | QVariant variant((uint)uint32_data);
|
---|
357 | return variant;
|
---|
358 | }
|
---|
359 |
|
---|
360 | case DBUS_TYPE_STRING:
|
---|
361 | {
|
---|
362 | dbus_message_iter_get_basic(iter, &str_data);
|
---|
363 | QString str(str_data);
|
---|
364 | QVariant variant(str);
|
---|
365 | return variant;
|
---|
366 | }
|
---|
367 |
|
---|
368 | case DBUS_TYPE_INT64:
|
---|
369 | {
|
---|
370 | dbus_message_iter_get_basic(iter, &int64_data);
|
---|
371 | QVariant variant((qlonglong)int64_data);
|
---|
372 | return variant;
|
---|
373 | }
|
---|
374 |
|
---|
375 | case DBUS_TYPE_UINT64:
|
---|
376 | {
|
---|
377 | dbus_message_iter_get_basic(iter, &uint64_data);
|
---|
378 | QVariant variant((qulonglong)uint64_data);
|
---|
379 | return variant;
|
---|
380 | }
|
---|
381 |
|
---|
382 | case DBUS_TYPE_STRUCT:
|
---|
383 | {
|
---|
384 | // Handle all structs here
|
---|
385 | DBusMessageIter struct_iter;
|
---|
386 | dbus_message_iter_recurse(iter, &struct_iter);
|
---|
387 |
|
---|
388 | QVariantList variantList;
|
---|
389 | do {
|
---|
390 | variantList << getVariantFromDBusMessage(&struct_iter);
|
---|
391 | } while (dbus_message_iter_next(&struct_iter));
|
---|
392 | QVariant variant(variantList);
|
---|
393 | return variant;
|
---|
394 | }
|
---|
395 |
|
---|
396 | default:
|
---|
397 | qDebug() << "Unsupported DBUS type: " << argtype;
|
---|
398 | }
|
---|
399 |
|
---|
400 | return QVariant();
|
---|
401 | }
|
---|
402 |
|
---|
403 | static DBusHandlerResult signalHandler (DBusConnection *connection,
|
---|
404 | DBusMessage *message,
|
---|
405 | void *object_ref) {
|
---|
406 | (void)connection;
|
---|
407 | QString interface;
|
---|
408 | QString signal;
|
---|
409 | DBusDispatcher *dispatcher = (DBusDispatcher *)object_ref;
|
---|
410 |
|
---|
411 | if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL) {
|
---|
412 | interface = dbus_message_get_interface(message);
|
---|
413 | signal = dbus_message_get_member(message);
|
---|
414 |
|
---|
415 | QList<QVariant> arglist;
|
---|
416 | DBusMessageIter dbus_iter;
|
---|
417 |
|
---|
418 | if (dbus_message_iter_init(message, &dbus_iter)) {
|
---|
419 | // Read return arguments
|
---|
420 | while (dbus_message_iter_get_arg_type (&dbus_iter) != DBUS_TYPE_INVALID) {
|
---|
421 | arglist << getVariantFromDBusMessage(&dbus_iter);
|
---|
422 | dbus_message_iter_next(&dbus_iter);
|
---|
423 | }
|
---|
424 | }
|
---|
425 |
|
---|
426 | dispatcher->emitSignalReceived(interface, signal, arglist);
|
---|
427 | return DBUS_HANDLER_RESULT_HANDLED;
|
---|
428 | }
|
---|
429 | (void)message;
|
---|
430 | return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
---|
431 | }
|
---|
432 |
|
---|
433 | DBusDispatcher::DBusDispatcher(const QString& service,
|
---|
434 | const QString& path,
|
---|
435 | const QString& interface,
|
---|
436 | QObject *parent)
|
---|
437 | : QObject(parent),
|
---|
438 | d_ptr(new DBusDispatcherPrivate(service, path, interface, path)) {
|
---|
439 | setupDBus();
|
---|
440 | }
|
---|
441 |
|
---|
442 | DBusDispatcher::DBusDispatcher(const QString& service,
|
---|
443 | const QString& path,
|
---|
444 | const QString& interface,
|
---|
445 | const QString& signalPath,
|
---|
446 | QObject *parent)
|
---|
447 | : QObject(parent),
|
---|
448 | d_ptr(new DBusDispatcherPrivate(service, path, interface, signalPath)) {
|
---|
449 | setupDBus();
|
---|
450 | }
|
---|
451 |
|
---|
452 | DBusDispatcher::~DBusDispatcher()
|
---|
453 | {
|
---|
454 | if (d_ptr->connection) {
|
---|
455 | dbus_connection_close(d_ptr->connection);
|
---|
456 | dbus_connection_unref(d_ptr->connection);
|
---|
457 | }
|
---|
458 | delete d_ptr;
|
---|
459 | }
|
---|
460 |
|
---|
461 | void DBusDispatcher::setupDBus()
|
---|
462 | {
|
---|
463 | d_ptr->connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, NULL);
|
---|
464 |
|
---|
465 | if (d_ptr->connection == NULL)
|
---|
466 | qDebug() << "Unable to get DBUS connection!";
|
---|
467 | else {
|
---|
468 | d_ptr->signal_vtable.message_function = signalHandler;
|
---|
469 |
|
---|
470 | dbus_connection_set_exit_on_disconnect(d_ptr->connection, FALSE);
|
---|
471 | dbus_connection_setup_with_g_main(d_ptr->connection, NULL);
|
---|
472 | dbus_connection_register_object_path(d_ptr->connection,
|
---|
473 | d_ptr->signalPath.toLatin1(),
|
---|
474 | &d_ptr->signal_vtable,
|
---|
475 | this);
|
---|
476 | }
|
---|
477 | }
|
---|
478 |
|
---|
479 | static DBusMessage *prepareDBusCall(const QString& service,
|
---|
480 | const QString& path,
|
---|
481 | const QString& interface,
|
---|
482 | const QString& method,
|
---|
483 | const QVariant& arg1 = QVariant(),
|
---|
484 | const QVariant& arg2 = QVariant(),
|
---|
485 | const QVariant& arg3 = QVariant(),
|
---|
486 | const QVariant& arg4 = QVariant(),
|
---|
487 | const QVariant& arg5 = QVariant(),
|
---|
488 | const QVariant& arg6 = QVariant(),
|
---|
489 | const QVariant& arg7 = QVariant(),
|
---|
490 | const QVariant& arg8 = QVariant())
|
---|
491 | {
|
---|
492 | DBusMessage *message = dbus_message_new_method_call(service.toLatin1(),
|
---|
493 | path.toLatin1(),
|
---|
494 | interface.toLatin1(),
|
---|
495 | method.toLatin1());
|
---|
496 | DBusMessageIter dbus_iter;
|
---|
497 |
|
---|
498 | // Append variants to DBUS message
|
---|
499 | QList<QVariant> arglist;
|
---|
500 | if (arg1.isValid()) arglist << arg1;
|
---|
501 | if (arg2.isValid()) arglist << arg2;
|
---|
502 | if (arg3.isValid()) arglist << arg3;
|
---|
503 | if (arg4.isValid()) arglist << arg4;
|
---|
504 | if (arg5.isValid()) arglist << arg5;
|
---|
505 | if (arg6.isValid()) arglist << arg6;
|
---|
506 | if (arg7.isValid()) arglist << arg7;
|
---|
507 | if (arg8.isValid()) arglist << arg8;
|
---|
508 |
|
---|
509 | dbus_message_iter_init_append (message, &dbus_iter);
|
---|
510 |
|
---|
511 | while (!arglist.isEmpty()) {
|
---|
512 | QVariant argument = arglist.takeFirst();
|
---|
513 | appendVariantToDBusMessage(argument, &dbus_iter);
|
---|
514 | }
|
---|
515 |
|
---|
516 | return message;
|
---|
517 | }
|
---|
518 |
|
---|
519 | QList<QVariant> DBusDispatcher::call(const QString& method,
|
---|
520 | const QVariant& arg1,
|
---|
521 | const QVariant& arg2,
|
---|
522 | const QVariant& arg3,
|
---|
523 | const QVariant& arg4,
|
---|
524 | const QVariant& arg5,
|
---|
525 | const QVariant& arg6,
|
---|
526 | const QVariant& arg7,
|
---|
527 | const QVariant& arg8) {
|
---|
528 | DBusMessageIter dbus_iter;
|
---|
529 | DBusMessage *message = prepareDBusCall(d_ptr->service, d_ptr->path,
|
---|
530 | d_ptr->interface, method,
|
---|
531 | arg1, arg2, arg3, arg4, arg5,
|
---|
532 | arg6, arg7, arg8);
|
---|
533 | DBusMessage *reply = dbus_connection_send_with_reply_and_block(
|
---|
534 | d_ptr->connection,
|
---|
535 | message, -1, NULL);
|
---|
536 | dbus_message_unref(message);
|
---|
537 |
|
---|
538 | QList<QVariant> replylist;
|
---|
539 | if (reply != NULL && dbus_message_iter_init(reply, &dbus_iter)) {
|
---|
540 | // Read return arguments
|
---|
541 | while (dbus_message_iter_get_arg_type (&dbus_iter) != DBUS_TYPE_INVALID) {
|
---|
542 | replylist << getVariantFromDBusMessage(&dbus_iter);
|
---|
543 | dbus_message_iter_next(&dbus_iter);
|
---|
544 | }
|
---|
545 | }
|
---|
546 | if (reply != NULL) dbus_message_unref(reply);
|
---|
547 | return replylist;
|
---|
548 | }
|
---|
549 |
|
---|
550 | class PendingCallInfo {
|
---|
551 | public:
|
---|
552 | QString method;
|
---|
553 | DBusDispatcher *dispatcher;
|
---|
554 | DBusDispatcherPrivate *priv;
|
---|
555 | };
|
---|
556 |
|
---|
557 | static void freePendingCallInfo(void *memory) {
|
---|
558 | PendingCallInfo *info = (PendingCallInfo *)memory;
|
---|
559 | delete info;
|
---|
560 | }
|
---|
561 |
|
---|
562 | static void pendingCallFunction (DBusPendingCall *pending,
|
---|
563 | void *memory) {
|
---|
564 | PendingCallInfo *info = (PendingCallInfo *)memory;
|
---|
565 | QString errorStr;
|
---|
566 | QList<QVariant> replyList;
|
---|
567 | DBusMessage *reply = dbus_pending_call_steal_reply (pending);
|
---|
568 |
|
---|
569 | Q_ASSERT(reply != NULL);
|
---|
570 |
|
---|
571 | if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
|
---|
572 | errorStr = dbus_message_get_error_name (reply);
|
---|
573 | } else {
|
---|
574 | DBusMessageIter dbus_iter;
|
---|
575 | dbus_message_iter_init(reply, &dbus_iter);
|
---|
576 | // Read return arguments
|
---|
577 | while (dbus_message_iter_get_arg_type (&dbus_iter) != DBUS_TYPE_INVALID) {
|
---|
578 | replyList << getVariantFromDBusMessage(&dbus_iter);
|
---|
579 | dbus_message_iter_next(&dbus_iter);
|
---|
580 | }
|
---|
581 | }
|
---|
582 |
|
---|
583 | info->priv->pending_calls.removeOne(pending);
|
---|
584 | info->dispatcher->emitCallReply(info->method, replyList, errorStr);
|
---|
585 | dbus_message_unref(reply);
|
---|
586 | dbus_pending_call_unref(pending);
|
---|
587 | }
|
---|
588 |
|
---|
589 | bool DBusDispatcher::callAsynchronous(const QString& method,
|
---|
590 | const QVariant& arg1,
|
---|
591 | const QVariant& arg2,
|
---|
592 | const QVariant& arg3,
|
---|
593 | const QVariant& arg4,
|
---|
594 | const QVariant& arg5,
|
---|
595 | const QVariant& arg6,
|
---|
596 | const QVariant& arg7,
|
---|
597 | const QVariant& arg8) {
|
---|
598 | DBusMessage *message = prepareDBusCall(d_ptr->service, d_ptr->path,
|
---|
599 | d_ptr->interface, method,
|
---|
600 | arg1, arg2, arg3, arg4, arg5,
|
---|
601 | arg6, arg7, arg8);
|
---|
602 | DBusPendingCall *call = NULL;
|
---|
603 | dbus_bool_t ret = dbus_connection_send_with_reply(d_ptr->connection,
|
---|
604 | message, &call, -1);
|
---|
605 | PendingCallInfo *info = new PendingCallInfo;
|
---|
606 | info->method = method;
|
---|
607 | info->dispatcher = this;
|
---|
608 | info->priv = d_ptr;
|
---|
609 |
|
---|
610 | dbus_pending_call_set_notify(call, pendingCallFunction, info, freePendingCallInfo);
|
---|
611 | d_ptr->pending_calls.append(call);
|
---|
612 | return (bool)ret;
|
---|
613 | }
|
---|
614 |
|
---|
615 | void DBusDispatcher::emitSignalReceived(const QString& interface,
|
---|
616 | const QString& signal,
|
---|
617 | const QList<QVariant>& args) {
|
---|
618 | emit signalReceived(interface, signal, args); }
|
---|
619 |
|
---|
620 | void DBusDispatcher::emitCallReply(const QString& method,
|
---|
621 | const QList<QVariant>& args,
|
---|
622 | const QString& error) {
|
---|
623 | emit callReply(method, args, error); }
|
---|
624 |
|
---|
625 | void DBusDispatcher::synchronousDispatch(int timeout_ms)
|
---|
626 | {
|
---|
627 | dbus_connection_read_write_dispatch(d_ptr->connection, timeout_ms);
|
---|
628 | }
|
---|
629 |
|
---|
630 | } // Maemo namespace
|
---|
631 |
|
---|