|
DBus-1-TQt
1.0
|
00001 /* qdbusintegrator.cpp TQT_DBusConnection private implementation 00002 * 00003 * Copyright (C) 2005 Harald Fernengel <harry@kdevelop.org> 00004 * Copyright (C) 2005 Kevin Krammer <kevin.krammer@gmx.at> 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 00021 * USA. 00022 * 00023 */ 00024 00025 #include <tqapplication.h> 00026 #include <tqevent.h> 00027 #include <tqmetaobject.h> 00028 #include <tqsocketnotifier.h> 00029 #include <tqtimer.h> 00030 00031 #include "tqdbusconnection_p.h" 00032 #include "tqdbusmessage.h" 00033 00034 Atomic::Atomic(int value) : m_value(value) 00035 { 00036 } 00037 00038 void Atomic::ref() 00039 { 00040 m_value++; 00041 } 00042 00043 bool Atomic::deref() 00044 { 00045 m_value--; 00046 return m_value > 0; 00047 } 00048 00049 int TQT_DBusConnectionPrivate::messageMetaType = 0; 00050 00051 static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data) 00052 { 00053 Q_ASSERT(timeout); 00054 Q_ASSERT(data); 00055 00056 // tqDebug("addTimeout %d", dbus_timeout_get_interval(timeout)); 00057 00058 TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data); 00059 00060 if (!dbus_timeout_get_enabled(timeout)) 00061 return true; 00062 00063 if (!tqApp) { 00064 d->pendingTimeouts.append(timeout); 00065 return true; 00066 } 00067 int timerId = d->startTimer(dbus_timeout_get_interval(timeout)); 00068 if (!timerId) 00069 return false; 00070 00071 d->timeouts[timerId] = timeout; 00072 return true; 00073 } 00074 00075 static void qDBusRemoveTimeout(DBusTimeout *timeout, void *data) 00076 { 00077 Q_ASSERT(timeout); 00078 Q_ASSERT(data); 00079 00080 // tqDebug("removeTimeout"); 00081 00082 TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data); 00083 for (TQValueList<DBusTimeout*>::iterator it = d->pendingTimeouts.begin(); 00084 it != d->pendingTimeouts.end();) { 00085 if ((*it) == timeout) { 00086 it = d->pendingTimeouts.erase(it); 00087 } 00088 else 00089 ++it; 00090 } 00091 00092 TQT_DBusConnectionPrivate::TimeoutHash::iterator it = d->timeouts.begin(); 00093 while (it != d->timeouts.end()) { 00094 if (it.data() == timeout) { 00095 d->killTimer(it.key()); 00096 TQT_DBusConnectionPrivate::TimeoutHash::iterator copyIt = it; 00097 ++it; 00098 d->timeouts.erase(copyIt); 00099 } else { 00100 ++it; 00101 } 00102 } 00103 } 00104 00105 static void qDBusToggleTimeout(DBusTimeout *timeout, void *data) 00106 { 00107 Q_ASSERT(timeout); 00108 Q_ASSERT(data); 00109 00110 //tqDebug("ToggleTimeout"); 00111 00112 qDBusRemoveTimeout(timeout, data); 00113 qDBusAddTimeout(timeout, data); 00114 } 00115 00116 static dbus_bool_t qDBusAddWatch(DBusWatch *watch, void *data) 00117 { 00118 Q_ASSERT(watch); 00119 Q_ASSERT(data); 00120 00121 TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data); 00122 00123 int flags = dbus_watch_get_flags(watch); 00124 int fd = dbus_watch_get_unix_fd(watch); 00125 00126 TQT_DBusConnectionPrivate::Watcher watcher; 00127 if (flags & DBUS_WATCH_READABLE) { 00128 bool enabled = dbus_watch_get_enabled(watch); 00129 //tqDebug("addReadWatch %d %s", fd, (enabled ? "enabled" : "disabled")); 00130 watcher.watch = watch; 00131 if (tqApp) { 00132 watcher.read = new TQSocketNotifier(fd, TQSocketNotifier::Read, d); 00133 if (!enabled) watcher.read->setEnabled(false); 00134 d->connect(watcher.read, TQT_SIGNAL(activated(int)), TQT_SLOT(socketRead(int))); 00135 } 00136 } 00137 if (flags & DBUS_WATCH_WRITABLE) { 00138 bool enabled = dbus_watch_get_enabled(watch); 00139 //tqDebug("addWriteWatch %d %s", fd, (enabled ? "enabled" : "disabled")); 00140 watcher.watch = watch; 00141 if (tqApp) { 00142 watcher.write = new TQSocketNotifier(fd, TQSocketNotifier::Write, d); 00143 if (!enabled) watcher.write->setEnabled(false); 00144 d->connect(watcher.write, TQT_SIGNAL(activated(int)), TQT_SLOT(socketWrite(int))); 00145 } 00146 } 00147 // FIXME-QT4 d->watchers.insertMulti(fd, watcher); 00148 TQT_DBusConnectionPrivate::WatcherHash::iterator it = d->watchers.find(fd); 00149 if (it == d->watchers.end()) 00150 { 00151 it = d->watchers.insert(fd, TQT_DBusConnectionPrivate::WatcherList()); 00152 } 00153 it.data().append(watcher); 00154 00155 return true; 00156 } 00157 00158 static void qDBusRemoveWatch(DBusWatch *watch, void *data) 00159 { 00160 Q_ASSERT(watch); 00161 Q_ASSERT(data); 00162 00163 //tqDebug("remove watch"); 00164 00165 TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data); 00166 int fd = dbus_watch_get_unix_fd(watch); 00167 00168 TQT_DBusConnectionPrivate::WatcherHash::iterator it = d->watchers.find(fd); 00169 if (it != d->watchers.end()) 00170 { 00171 TQT_DBusConnectionPrivate::WatcherList& list = *it; 00172 for (TQT_DBusConnectionPrivate::WatcherList::iterator wit = list.begin(); 00173 wit != list.end(); ++wit) 00174 { 00175 if ((*wit).watch == watch) 00176 { 00177 // migth be called from a function triggered by a socket listener 00178 // so just disconnect them and schedule their delayed deletion. 00179 00180 d->removedWatches.append(*wit); 00181 if ((*wit).read) 00182 { 00183 (*wit).read->disconnect(d); 00184 (*wit).read = 0; 00185 } 00186 if ((*wit).write) 00187 { 00188 (*wit).write->disconnect(d); 00189 (*wit).write = 0; 00190 } 00191 (*wit).watch = 0; 00192 } 00193 } 00194 } 00195 00196 if (d->removedWatches.count() > 0) 00197 TQTimer::singleShot(0, d, TQT_SLOT(purgeRemovedWatches())); 00198 } 00199 00200 static void qDBusToggleWatch(DBusWatch *watch, void *data) 00201 { 00202 Q_ASSERT(watch); 00203 Q_ASSERT(data); 00204 00205 //tqDebug("toggle watch"); 00206 00207 TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data); 00208 int fd = dbus_watch_get_unix_fd(watch); 00209 00210 TQT_DBusConnectionPrivate::WatcherHash::iterator it = d->watchers.find(fd); 00211 if (it != d->watchers.end()) { 00212 TQT_DBusConnectionPrivate::WatcherList& list = *it; 00213 for (TQT_DBusConnectionPrivate::WatcherList::iterator wit = list.begin(); wit != list.end(); 00214 ++wit) 00215 { 00216 if ((*wit).watch == watch) { 00217 bool enabled = dbus_watch_get_enabled(watch); 00218 int flags = dbus_watch_get_flags(watch); 00219 00220 // tqDebug("toggle watch %d to %d (write: %d, read: %d)", 00221 // dbus_watch_get_unix_fd(watch), enabled, 00222 // flags & DBUS_WATCH_WRITABLE, flags & DBUS_WATCH_READABLE); 00223 00224 if (flags & DBUS_WATCH_READABLE && (*wit).read) 00225 (*wit).read->setEnabled(enabled); 00226 if (flags & DBUS_WATCH_WRITABLE && (*wit).write) 00227 (*wit).write->setEnabled(enabled); 00228 return; 00229 } 00230 } 00231 } 00232 } 00233 00234 static void qDBusNewConnection(DBusServer *server, DBusConnection *c, void *data) 00235 { 00236 Q_ASSERT(data); Q_ASSERT(server); Q_ASSERT(c); 00237 00238 tqDebug("SERVER: GOT A NEW CONNECTION"); // TODO 00239 } 00240 00241 static DBusHandlerResult qDBusSignalFilter(DBusConnection *connection, 00242 DBusMessage *message, void *data) 00243 { 00244 Q_ASSERT(data); 00245 Q_UNUSED(connection); 00246 00247 TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data); 00248 if (d->mode == TQT_DBusConnectionPrivate::InvalidMode) 00249 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00250 00251 int msgType = dbus_message_get_type(message); 00252 bool handled = false; 00253 00254 //TQT_DBusMessage amsg = TQT_DBusMessage::fromDBusMessage(message); 00255 //tqDebug() << "got message: " << dbus_message_get_type(message) << amsg; 00256 00257 if (msgType == DBUS_MESSAGE_TYPE_SIGNAL) { 00258 handled = d->handleSignal(message); 00259 } else if (msgType == DBUS_MESSAGE_TYPE_METHOD_CALL) { 00260 handled = d->handleObjectCall(message); 00261 } 00262 00263 return handled ? DBUS_HANDLER_RESULT_HANDLED : 00264 DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00265 } 00266 00267 int TQT_DBusConnectionPrivate::registerMessageMetaType() 00268 { 00269 // FIXME-QT4 int tp = messageMetaType = qRegisterMetaType<TQT_DBusMessage>("TQT_DBusMessage"); 00270 int tp = 0; 00271 return tp; 00272 } 00273 00274 TQT_DBusConnectionPrivate::TQT_DBusConnectionPrivate(TQObject *parent) 00275 : TQObject(parent), ref(1), mode(InvalidMode), connection(0), server(0), 00276 dispatcher(0), inDispatch(false) 00277 { 00278 static const int msgType = registerMessageMetaType(); 00279 Q_UNUSED(msgType); 00280 00281 dbus_error_init(&error); 00282 00283 dispatcher = new TQTimer(this); 00284 TQObject::connect(dispatcher, TQT_SIGNAL(timeout()), this, TQT_SLOT(dispatch())); 00285 00286 m_resultEmissionQueueTimer = new TQTimer(this); 00287 TQObject::connect(m_resultEmissionQueueTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(transmitResultEmissionQueue())); 00288 m_messageEmissionQueueTimer = new TQTimer(this); 00289 TQObject::connect(m_messageEmissionQueueTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(transmitMessageEmissionQueue())); 00290 } 00291 00292 TQT_DBusConnectionPrivate::~TQT_DBusConnectionPrivate() 00293 { 00294 for (PendingCallMap::iterator it = pendingCalls.begin(); it != pendingCalls.end();) 00295 { 00296 PendingCallMap::iterator copyIt = it; 00297 ++it; 00298 dbus_pending_call_cancel(copyIt.key()); 00299 dbus_pending_call_unref(copyIt.key()); 00300 delete copyIt.data(); 00301 pendingCalls.erase(copyIt); 00302 } 00303 00304 if (dbus_error_is_set(&error)) 00305 dbus_error_free(&error); 00306 00307 closeConnection(); 00308 } 00309 00310 void TQT_DBusConnectionPrivate::closeConnection() 00311 { 00312 ConnectionMode oldMode = mode; 00313 mode = InvalidMode; // prevent reentrancy 00314 if (oldMode == ServerMode) { 00315 if (server) { 00316 dbus_server_disconnect(server); 00317 dbus_server_unref(server); 00318 server = 0; 00319 } 00320 } else if (oldMode == ClientMode) { 00321 if (connection) { 00322 // closing shared connections is forbidden 00323 #if 0 00324 dbus_connection_close(connection); 00325 // send the "close" message 00326 while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS); 00327 #endif 00328 dbus_connection_unref(connection); 00329 connection = 0; 00330 } 00331 } 00332 } 00333 00334 bool TQT_DBusConnectionPrivate::handleError() 00335 { 00336 lastError = TQT_DBusError(&error); 00337 if (dbus_error_is_set(&error)) 00338 dbus_error_free(&error); 00339 return lastError.isValid(); 00340 } 00341 00342 void TQT_DBusConnectionPrivate::emitPendingCallReply(const TQT_DBusMessage& message) 00343 { 00344 emit dbusPendingCallReply(message); 00345 } 00346 00347 void TQT_DBusConnectionPrivate::bindToApplication() 00348 { 00349 // Yay, now that we have an application we are in business 00350 // Re-add all watchers 00351 WatcherHash oldWatchers = watchers; 00352 watchers.clear(); 00353 // FIXME-QT4 TQHashIterator<int, TQT_DBusConnectionPrivate::Watcher> it(oldWatchers); 00354 for (WatcherHash::const_iterator it = oldWatchers.begin(); it != oldWatchers.end(); ++it) 00355 { 00356 const WatcherList& list = *it; 00357 for (WatcherList::const_iterator wit = list.begin(); wit != list.end(); ++wit) 00358 { 00359 if (!(*wit).read && !(*wit).write) { 00360 qDBusAddWatch((*wit).watch, this); 00361 } 00362 } 00363 } 00364 00365 // Re-add all timeouts 00366 while (!pendingTimeouts.isEmpty()) { 00367 qDBusAddTimeout(pendingTimeouts.first(), this); 00368 pendingTimeouts.pop_front(); 00369 } 00370 } 00371 00372 void TQT_DBusConnectionPrivate::socketRead(int fd) 00373 { 00374 // FIXME-QT4 TQHashIterator<int, TQT_DBusConnectionPrivate::Watcher> it(watchers); 00375 WatcherHash::const_iterator it = watchers.find(fd); 00376 if (it != watchers.end()) { 00377 const WatcherList& list = *it; 00378 for (WatcherList::const_iterator wit = list.begin(); wit != list.end(); ++wit) { 00379 if ((*wit).read && (*wit).read->isEnabled()) { 00380 if (!dbus_watch_handle((*wit).watch, DBUS_WATCH_READABLE)) 00381 tqDebug("OUT OF MEM"); 00382 } 00383 } 00384 } 00385 if (mode == ClientMode) 00386 scheduleDispatch(); 00387 } 00388 00389 void TQT_DBusConnectionPrivate::socketWrite(int fd) 00390 { 00391 // FIXME-QT4 TQHashIterator<int, TQT_DBusConnectionPrivate::Watcher> it(watchers); 00392 WatcherHash::const_iterator it = watchers.find(fd); 00393 if (it != watchers.end()) { 00394 const WatcherList& list = *it; 00395 for (WatcherList::const_iterator wit = list.begin(); wit != list.end(); ++wit) { 00396 if ((*wit).write && (*wit).write->isEnabled()) { 00397 if (!dbus_watch_handle((*wit).watch, DBUS_WATCH_WRITABLE)) 00398 tqDebug("OUT OF MEM"); 00399 } 00400 } 00401 } 00402 } 00403 00404 void TQT_DBusConnectionPrivate::objectDestroyed(TQObject* object) 00405 { 00406 //tqDebug("Object destroyed"); 00407 for (PendingCallMap::iterator it = pendingCalls.begin(); it != pendingCalls.end();) 00408 { 00409 TQObject* receiver = (TQObject*) it.data()->receiver; 00410 if (receiver == object || receiver == 0) 00411 { 00412 PendingCallMap::iterator copyIt = it; 00413 ++it; 00414 00415 dbus_pending_call_cancel(copyIt.key()); 00416 dbus_pending_call_unref(copyIt.key()); 00417 delete copyIt.data(); 00418 pendingCalls.erase(copyIt); 00419 } 00420 else 00421 ++it; 00422 } 00423 } 00424 00425 void TQT_DBusConnectionPrivate::purgeRemovedWatches() 00426 { 00427 if (removedWatches.isEmpty()) return; 00428 00429 WatcherList::iterator listIt = removedWatches.begin(); 00430 for (; listIt != removedWatches.end(); ++listIt) 00431 { 00432 delete (*listIt).read; 00433 delete (*listIt).write; 00434 } 00435 removedWatches.clear(); 00436 00437 uint count = 0; 00438 WatcherHash::iterator it = watchers.begin(); 00439 while (it != watchers.end()) 00440 { 00441 WatcherList& list = *it; 00442 listIt = list.begin(); 00443 while (listIt != list.end()) 00444 { 00445 if (!((*listIt).read) && !((*listIt).write)) 00446 { 00447 listIt = list.erase(listIt); 00448 ++count; 00449 } 00450 } 00451 00452 if (list.isEmpty()) 00453 { 00454 WatcherHash::iterator copyIt = it; 00455 ++it; 00456 watchers.erase(copyIt); 00457 } 00458 else 00459 ++it; 00460 } 00461 } 00462 00463 void TQT_DBusConnectionPrivate::scheduleDispatch() 00464 { 00465 dispatcher->start(0); 00466 } 00467 00468 void TQT_DBusConnectionPrivate::dispatch() 00469 { 00470 // dbus_connection_dispatch will hang if called recursively 00471 if (inDispatch) { 00472 printf("[dbus-1-tqt] WARNING: Attempt to call dispatch() recursively was silently ignored to prevent lockup!\n\r"); fflush(stdout); 00473 return; 00474 } 00475 inDispatch = true; 00476 00477 if (mode == ClientMode) 00478 { 00479 if (dbus_connection_dispatch(connection) != DBUS_DISPATCH_DATA_REMAINS) 00480 { 00481 // stop dispatch timer 00482 dispatcher->stop(); 00483 } 00484 } 00485 00486 inDispatch = false; 00487 } 00488 00489 void TQT_DBusConnectionPrivate::transmitMessageEmissionQueue() 00490 { 00491 TQT_DBusConnectionPrivate::PendingMessagesForEmit::iterator pmfe; 00492 pmfe = pendingMessages.begin(); 00493 while (pmfe != pendingMessages.end()) { 00494 TQT_DBusMessage msg = *pmfe; 00495 pmfe = pendingMessages.remove(pmfe); 00496 dbusSignal(msg); 00497 } 00498 } 00499 00500 bool TQT_DBusConnectionPrivate::handleObjectCall(DBusMessage *message) 00501 { 00502 TQT_DBusMessage msg = TQT_DBusMessage::fromDBusMessage(message); 00503 00504 ObjectMap::iterator it = registeredObjects.find(msg.path()); 00505 if (it == registeredObjects.end()) 00506 return false; 00507 00508 return it.data()->handleMethodCall(msg); 00509 } 00510 00511 bool TQT_DBusConnectionPrivate::handleSignal(DBusMessage *message) 00512 { 00513 TQT_DBusMessage msg = TQT_DBusMessage::fromDBusMessage(message); 00514 00515 // yes, it is a single "|" below... 00516 // FIXME-QT4 00517 //return handleSignal(TQString(), msg) | handleSignal(msg.path(), msg); 00518 00519 // If dbusSignal(msg) were called here, it could easily cause a lockup as it would enter the TQt3 event loop, 00520 // which could result in arbitrary methods being called while still inside dbus_connection_dispatch. 00521 // Instead, I enqueue the messages here for TQt3 event loop transmission after dbus_connection_dispatch is finished. 00522 pendingMessages.append(msg); 00523 if (!m_messageEmissionQueueTimer->isActive()) m_messageEmissionQueueTimer->start(0, TRUE); 00524 00525 return true; 00526 } 00527 00528 static dbus_int32_t server_slot = -1; 00529 00530 void TQT_DBusConnectionPrivate::setServer(DBusServer *s) 00531 { 00532 if (!server) { 00533 handleError(); 00534 return; 00535 } 00536 00537 server = s; 00538 mode = ServerMode; 00539 00540 dbus_server_allocate_data_slot(&server_slot); 00541 if (server_slot < 0) 00542 return; 00543 00544 dbus_server_set_watch_functions(server, qDBusAddWatch, qDBusRemoveWatch, 00545 qDBusToggleWatch, this, 0); // ### check return type? 00546 dbus_server_set_timeout_functions(server, qDBusAddTimeout, qDBusRemoveTimeout, 00547 qDBusToggleTimeout, this, 0); 00548 dbus_server_set_new_connection_function(server, qDBusNewConnection, this, 0); 00549 00550 dbus_server_set_data(server, server_slot, this, 0); 00551 } 00552 00553 void TQT_DBusConnectionPrivate::setConnection(DBusConnection *dbc) 00554 { 00555 if (!dbc) { 00556 handleError(); 00557 return; 00558 } 00559 00560 connection = dbc; 00561 mode = ClientMode; 00562 00563 dbus_connection_set_exit_on_disconnect(connection, false); 00564 dbus_connection_set_watch_functions(connection, qDBusAddWatch, qDBusRemoveWatch, 00565 qDBusToggleWatch, this, 0); 00566 dbus_connection_set_timeout_functions(connection, qDBusAddTimeout, qDBusRemoveTimeout, 00567 qDBusToggleTimeout, this, 0); 00568 // dbus_bus_add_match(connection, "type='signal',interface='com.trolltech.dbus.Signal'", &error); 00569 // dbus_bus_add_match(connection, "type='signal'", &error); 00570 00571 dbus_bus_add_match(connection, "type='signal'", &error); 00572 if (handleError()) { 00573 closeConnection(); 00574 return; 00575 } 00576 00577 const char *service = dbus_bus_get_unique_name(connection); 00578 if (service) { 00579 TQCString filter; 00580 filter += "destination='"; 00581 filter += service; 00582 filter += "\'"; 00583 00584 dbus_bus_add_match(connection, filter.data(), &error); 00585 if (handleError()) { 00586 closeConnection(); 00587 return; 00588 } 00589 } else { 00590 tqWarning("TQT_DBusConnectionPrivate::SetConnection: Unable to get unique name"); 00591 } 00592 00593 dbus_connection_add_filter(connection, qDBusSignalFilter, this, 0); 00594 00595 //tqDebug("unique name: %s", service); 00596 } 00597 00598 static void qDBusResultReceived(DBusPendingCall *pending, void *user_data) 00599 { 00600 //tqDebug("Pending Call Result received"); 00601 TQT_DBusConnectionPrivate* d = reinterpret_cast<TQT_DBusConnectionPrivate*>(user_data); 00602 TQT_DBusConnectionPrivate::PendingCallMap::iterator it = d->pendingCalls.find(pending); 00603 00604 DBusMessage *dbusReply = dbus_pending_call_steal_reply(pending); 00605 00606 dbus_set_error_from_message(&d->error, dbusReply); 00607 d->handleError(); 00608 00609 if (it != d->pendingCalls.end()) 00610 { 00611 TQT_DBusMessage reply = TQT_DBusMessage::fromDBusMessage(dbusReply); 00612 00613 TQT_DBusResultInfo dbusResult; 00614 dbusResult.message = reply; 00615 dbusResult.receiver = it.data()->receiver; 00616 dbusResult.method = it.data()->method.data(); 00617 d->m_resultEmissionQueue.append(dbusResult); 00618 d->newMethodInResultEmissionQueue(); 00619 } 00620 00621 dbus_message_unref(dbusReply); 00622 dbus_pending_call_unref(pending); 00623 delete it.data(); 00624 00625 d->pendingCalls.erase(it); 00626 } 00627 00628 int TQT_DBusConnectionPrivate::sendWithReplyAsync(const TQT_DBusMessage &message, TQObject *receiver, 00629 const char *method) 00630 { 00631 if (!receiver || !method) 00632 return 0; 00633 00634 if (!TQObject::connect(receiver, TQT_SIGNAL(destroyed(TQObject*)), 00635 this, TQT_SLOT(objectDestroyed(TQObject*)))) 00636 return false; 00637 00638 DBusMessage *msg = message.toDBusMessage(); 00639 if (!msg) 00640 return 0; 00641 00642 int msg_serial = 0; 00643 DBusPendingCall *pending = 0; 00644 if (dbus_connection_send_with_reply(connection, msg, &pending, message.timeout())) { 00645 TQT_DBusPendingCall *pcall = new TQT_DBusPendingCall; 00646 pcall->receiver = receiver; 00647 pcall->method = method; 00648 pcall->pending = pending; 00649 pendingCalls.insert(pcall->pending, pcall); 00650 00651 dbus_pending_call_set_notify(pending, qDBusResultReceived, this, 0); 00652 00653 msg_serial = dbus_message_get_serial(msg); 00654 } 00655 00656 dbus_message_unref(msg); 00657 return msg_serial; 00658 } 00659 00660 void TQT_DBusConnectionPrivate::flush() 00661 { 00662 if (!connection) return; 00663 00664 dbus_connection_flush(connection); 00665 } 00666 00667 void TQT_DBusConnectionPrivate::newMethodInResultEmissionQueue() 00668 { 00669 if (!m_resultEmissionQueueTimer->isActive()) m_resultEmissionQueueTimer->start(0, TRUE); 00670 } 00671 00672 void TQT_DBusConnectionPrivate::transmitResultEmissionQueue() 00673 { 00674 if (!m_resultEmissionQueue.isEmpty()) { 00675 TQT_DBusResultInfoList::Iterator it; 00676 it = m_resultEmissionQueue.begin(); 00677 while (it != m_resultEmissionQueue.end()) { 00678 TQT_DBusResultInfo dbusResult = (*it); 00679 m_resultEmissionQueue.remove(it); 00680 it = m_resultEmissionQueue.begin(); 00681 00682 TQObject::connect(this, TQT_SIGNAL(dbusPendingCallReply(const TQT_DBusMessage&)), dbusResult.receiver, dbusResult.method.data()); 00683 emitPendingCallReply(dbusResult.message); 00684 TQObject::disconnect(this, TQT_SIGNAL(dbusPendingCallReply(const TQT_DBusMessage&)), dbusResult.receiver, dbusResult.method.data()); 00685 } 00686 } 00687 } 00688 00689 #include "tqdbusconnection_p.moc"