00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <QtCore/qdebug.h>
00024 #include <QtCore/qcoreapplication.h>
00025
00026 #include "qdbusconnection.h"
00027 #include "qdbusconnection_p.h"
00028
00029 QT_STATIC_CONST_IMPL char *QDBusConnection::default_connection_name = "qt_dbus_default_connection";
00030
00031 class QDBusConnectionManager
00032 {
00033 public:
00034 QDBusConnectionManager(): default_connection(0) {}
00035 ~QDBusConnectionManager();
00036 void bindToApplication();
00037 QDBusConnectionPrivate *connection(const QString &name) const;
00038 void removeConnection(const QString &name);
00039 void setConnection(const QString &name, QDBusConnectionPrivate *c);
00040
00041 private:
00042 QDBusConnectionPrivate *default_connection;
00043 QHash<QString, QDBusConnectionPrivate *> connectionHash;
00044 };
00045
00046 Q_GLOBAL_STATIC(QDBusConnectionManager, manager);
00047
00048 QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const
00049 {
00050 return name == QLatin1String(QDBusConnection::default_connection_name) ?
00051 default_connection : connectionHash.value(name, 0);
00052 }
00053
00054 void QDBusConnectionManager::removeConnection(const QString &name)
00055 {
00056 QDBusConnectionPrivate *d = 0;
00057 if (name == QLatin1String(QDBusConnection::default_connection_name)) {
00058 d = default_connection;
00059 default_connection = 0;
00060 } else {
00061 d = connectionHash.take(name);
00062 }
00063 if (!d->ref.deref())
00064 delete d;
00065 }
00066
00067 QDBusConnectionManager::~QDBusConnectionManager()
00068 {
00069 if (default_connection) {
00070 delete default_connection;
00071 default_connection = 0;
00072 }
00073 for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
00074 it != connectionHash.constEnd(); ++it) {
00075 delete it.value();
00076 }
00077 connectionHash.clear();
00078 }
00079
00080 void QDBusConnectionManager::bindToApplication()
00081 {
00082 if (default_connection) {
00083 default_connection->bindToApplication();
00084 }
00085 for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
00086 it != connectionHash.constEnd(); ++it) {
00087 (*it)->bindToApplication();
00088 }
00089 }
00090
00091 void qDBusBindToApplication()
00092 {
00093 manager()->bindToApplication();
00094 }
00095
00096 void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionPrivate *c)
00097 {
00098 if (name == QLatin1String(QDBusConnection::default_connection_name))
00099 default_connection = c;
00100 else
00101 connectionHash[name] = c;
00102 }
00103
00104
00105 QDBusConnection::QDBusConnection(const QString &name)
00106 {
00107 d = manager()->connection(name);
00108 if (d)
00109 d->ref.ref();
00110 }
00111
00112 QDBusConnection::QDBusConnection(const QDBusConnection &other)
00113 {
00114 d = other.d;
00115 if (d)
00116 d->ref.ref();
00117 }
00118
00119 QDBusConnection::~QDBusConnection()
00120 {
00121 if (d && !d->ref.deref())
00122 delete d;
00123 }
00124
00125 QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
00126 {
00127 if (other.d)
00128 other.d->ref.ref();
00129 QDBusConnectionPrivate *old = static_cast<QDBusConnectionPrivate *>(
00130 q_atomic_set_ptr(&d, other.d));
00131 if (old && !old->ref.deref())
00132 delete old;
00133
00134 return *this;
00135 }
00136
00137 QDBusConnection QDBusConnection::addConnection(BusType type, const QString &name)
00138 {
00139
00140
00141
00142 QDBusConnectionPrivate *d = manager()->connection(name);
00143 if (d)
00144 return QDBusConnection(name);
00145
00146 d = new QDBusConnectionPrivate;
00147 DBusConnection *c = 0;
00148 switch (type) {
00149 case SystemBus:
00150 c = dbus_bus_get(DBUS_BUS_SYSTEM, &d->error);
00151 break;
00152 case SessionBus:
00153 c = dbus_bus_get(DBUS_BUS_SESSION, &d->error);
00154 break;
00155 case ActivationBus:
00156 c = dbus_bus_get(DBUS_BUS_STARTER, &d->error);
00157 break;
00158 }
00159 d->setConnection(c);
00160
00161 manager()->setConnection(name, d);
00162
00163 return QDBusConnection(name);
00164 }
00165
00166 QDBusConnection QDBusConnection::addConnection(const QString &address,
00167 const QString &name)
00168 {
00169
00170
00171
00172 QDBusConnectionPrivate *d = manager()->connection(name);
00173 if (d)
00174 return QDBusConnection(name);
00175
00176 d = new QDBusConnectionPrivate;
00177
00178 d->setConnection(dbus_connection_open(address.toUtf8().constData(), &d->error));
00179
00180 manager()->setConnection(name, d);
00181
00182 return QDBusConnection(name);
00183 }
00184
00185 void QDBusConnection::closeConnection(const QString &name)
00186 {
00187 manager()->removeConnection(name);
00188 }
00189
00190 void QDBusConnectionPrivate::timerEvent(QTimerEvent *e)
00191 {
00192 DBusTimeout *timeout = timeouts.value(e->timerId(), 0);
00193 dbus_timeout_handle(timeout);
00194 }
00195
00196 bool QDBusConnection::send(const QDBusMessage &message) const
00197 {
00198 if (!d || !d->connection)
00199 return false;
00200
00201 DBusMessage *msg = message.toDBusMessage();
00202 if (!msg)
00203 return false;
00204
00205 bool isOk = dbus_connection_send(d->connection, msg, 0);
00206 dbus_message_unref(msg);
00207 return isOk;
00208 }
00209
00210 int QDBusConnection::sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
00211 const char *method) const
00212 {
00213 if (!d || !d->connection)
00214 return 0;
00215
00216 return d->sendWithReplyAsync(message, receiver, method);
00217 }
00218
00219 QDBusMessage QDBusConnection::sendWithReply(const QDBusMessage &message) const
00220 {
00221 if (!d || !d->connection)
00222 return QDBusMessage::fromDBusMessage(0);
00223
00224 DBusMessage *msg = message.toDBusMessage();
00225 if (!msg)
00226 return QDBusMessage::fromDBusMessage(0);
00227 DBusMessage *reply = dbus_connection_send_with_reply_and_block(d->connection, msg,
00228 -1, &d->error);
00229 d->handleError();
00230 dbus_message_unref(msg);
00231
00232 return QDBusMessage::fromDBusMessage(reply);
00233 }
00234
00235 bool QDBusConnection::connect(const QString &path, const QString &interface,
00236 const QString &name, QObject *receiver, const char *slot)
00237 {
00238 if (!receiver || !slot || !d || !d->connection)
00239 return false;
00240
00241 QDBusConnectionPrivate::SignalHook hook;
00242
00243 hook.interface = interface;
00244 hook.name = name;
00245 hook.obj = QPointer<QObject>(receiver);
00246 if (!hook.setSlot(slot + 1))
00247 return false;
00248
00249 d->signalHooks.insertMulti(path, hook);
00250 d->connect(receiver, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)));
00251
00252 return true;
00253 }
00254
00255 bool QDBusConnection::registerObject(const QString &path, const QString &interface,
00256 QObject *object)
00257 {
00258 if (!d || !d->connection || !object || path.isEmpty() || interface.isEmpty())
00259 return false;
00260
00261 QDBusConnectionPrivate::ObjectHook hook;
00262 hook.interface = interface;
00263 hook.obj = object;
00264
00265 QDBusConnectionPrivate::ObjectHookHash::iterator it = d->objectHooks.find(path);
00266 while (it != d->objectHooks.end() && it.key() == path) {
00267 if (it.value().interface == interface) {
00268 d->objectHooks.erase(it);
00269 break;
00270 }
00271 ++it;
00272 }
00273
00274 d->objectHooks.insert(path, hook);
00275
00276 d->connect(object, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)));
00277 qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData());
00278
00279 return true;
00280 }
00281
00282 void QDBusConnection::unregisterObject(const QString &path)
00283 {
00284 if (!d || !d->connection)
00285 return;
00286
00287
00288 d->objectHooks.remove(path);
00289 }
00290
00291 bool QDBusConnection::isConnected( ) const
00292 {
00293 return d && d->connection && dbus_connection_get_is_connected(d->connection);
00294 }
00295
00296 QDBusError QDBusConnection::lastError() const
00297 {
00298 return d ? d->lastError : QDBusError();
00299 }
00300
00301 QString QDBusConnection::baseService() const
00302 {
00303 return d && d->connection ?
00304 QString::fromUtf8(dbus_bus_get_unique_name(d->connection))
00305 : QString();
00306 }
00307
00308 bool QDBusConnection::requestName(const QString &name, NameRequestMode mode)
00309 {
00310
00311 static const int DBusModes[] = { 0, DBUS_NAME_FLAG_ALLOW_REPLACEMENT,
00312 DBUS_NAME_FLAG_REPLACE_EXISTING };
00313 Q_ASSERT(mode == 0 || mode == AllowReplace ||
00314 mode == ReplaceExisting );
00315
00316 DBusError error;
00317 dbus_error_init (&error);
00318 dbus_bus_request_name(d->connection, name.toUtf8(), DBusModes[mode], &error);
00319 if (dbus_error_is_set (&error)) {
00320 qDebug("Error %s\n", error.message);
00321 dbus_error_free (&error);
00322 return false;
00323 }
00324 return true;
00325 }
00326
00327 #include "qdbusconnection.moc"