00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "wvdbusmsg.h"
00012 #include "wvdbusconn.h"
00013 #include "wvstrutils.h"
00014 #undef interface // windows
00015 #include <dbus/dbus.h>
00016
00017
00018 class WvDBusReplyMsg : public WvDBusMsg
00019 {
00020 public:
00027 WvDBusReplyMsg(DBusMessage *_msg);
00028
00029 virtual ~WvDBusReplyMsg() {}
00030 };
00031
00032
00033
00034 WvDBusMsg::Iter::Iter(const WvDBusMsg &_msg)
00035 : first(new DBusMessageIter), it(new DBusMessageIter)
00036 {
00037 dbus_message_iter_init(_msg, first);
00038 rewind();
00039 }
00040
00041
00042 WvDBusMsg::Iter::Iter(const WvDBusMsg::Iter &_it)
00043 : first(new DBusMessageIter), it(new DBusMessageIter)
00044 {
00045 *first = *_it.first;
00046 rewind();
00047 }
00048
00049
00050 WvDBusMsg::Iter::Iter(const DBusMessageIter &_first)
00051 : first(new DBusMessageIter), it(new DBusMessageIter)
00052 {
00053 *first = _first;
00054 rewind();
00055 }
00056
00057
00058 WvDBusMsg::Iter::~Iter()
00059 {
00060 delete first;
00061 delete it;
00062 }
00063
00064
00065 void WvDBusMsg::Iter::rewind()
00066 {
00067 rewound = true;
00068 }
00069
00070
00071 bool WvDBusMsg::Iter::next()
00072 {
00073 if (rewound)
00074 *it = *first;
00075 else if (type() != DBUS_TYPE_INVALID)
00076 dbus_message_iter_next(it);
00077 rewound = false;
00078 return type() != DBUS_TYPE_INVALID;
00079 }
00080
00081
00082 int WvDBusMsg::Iter::type() const
00083 {
00084 return dbus_message_iter_get_arg_type(it);
00085 }
00086
00087
00088 WvDBusMsg::Iter WvDBusMsg::Iter::open() const
00089 {
00090 DBusMessageIter sub;
00091 dbus_message_iter_recurse(it, &sub);
00092 return Iter(sub);
00093 }
00094
00095
00096 bool WvDBusMsg::Iter::cur() const
00097 {
00098 return !rewound && type() != DBUS_TYPE_INVALID;
00099 }
00100
00101
00102 void WvDBusMsg::Iter::get_all(WvStringList &list)
00103 {
00104 int items = 0;
00105 for (rewind(); next() && items < 20; items++)
00106 list.append(get_str());
00107 if (items == 20)
00108 list.append("...");
00109 }
00110
00111
00112 WvString WvDBusMsg::Iter::get_all()
00113 {
00114 WvStringList list;
00115 get_all(list);
00116 return list.join(",");
00117 }
00118
00119
00120 WvString WvDBusMsg::Iter::get_str() const
00121 {
00122 char *s;
00123 double d;
00124
00125 switch (type())
00126 {
00127 case DBUS_TYPE_BYTE:
00128
00129
00130
00131 case DBUS_TYPE_BOOLEAN:
00132
00133 case DBUS_TYPE_INT16:
00134 case DBUS_TYPE_INT32:
00135 case DBUS_TYPE_INT64:
00136 return get_int();
00137 case DBUS_TYPE_UINT16:
00138 case DBUS_TYPE_UINT32:
00139 case DBUS_TYPE_UINT64:
00140 return get_uint();
00141 case DBUS_TYPE_DOUBLE:
00142 dbus_message_iter_get_basic(it, &d);
00143 return d;
00144 case DBUS_TYPE_STRING:
00145 dbus_message_iter_get_basic(it, &s);
00146 return s;
00147 case DBUS_TYPE_VARIANT:
00148 return WvString("{%s}", open().getnext().get_str());
00149 case DBUS_TYPE_STRUCT:
00150 case DBUS_TYPE_ARRAY:
00151 return WvString("[%s]", open().get_all());
00152 case DBUS_TYPE_INVALID:
00153 return WvString();
00154 default:
00155 return WvString("UNKNOWN_TYPE(%c)", type());
00156 }
00157 }
00158
00159
00160 int64_t WvDBusMsg::Iter::get_int() const
00161 {
00162 dbus_bool_t b;
00163 unsigned char c;
00164 dbus_int16_t s;
00165 dbus_int32_t i;
00166 dbus_int64_t l;
00167 char *str;
00168
00169 switch (type())
00170 {
00171 case DBUS_TYPE_BYTE:
00172 dbus_message_iter_get_basic(it, &c);
00173 return c;
00174
00175 case DBUS_TYPE_BOOLEAN:
00176 dbus_message_iter_get_basic(it, &b);
00177 return b;
00178
00179 case DBUS_TYPE_INT16:
00180 case DBUS_TYPE_UINT16:
00181 dbus_message_iter_get_basic(it, &s);
00182 return s;
00183
00184 case DBUS_TYPE_INT32:
00185 case DBUS_TYPE_UINT32:
00186 dbus_message_iter_get_basic(it, &i);
00187 return i;
00188
00189 case DBUS_TYPE_INT64:
00190 case DBUS_TYPE_UINT64:
00191 dbus_message_iter_get_basic(it, &l);
00192 return l;
00193
00194 case DBUS_TYPE_STRING:
00195 dbus_message_iter_get_basic(it, &str);
00196 return WvString(str).num();
00197
00198 case DBUS_TYPE_VARIANT:
00199 return open().getnext().get_int();
00200
00201 default:
00202 return 0;
00203 }
00204 }
00205
00206
00207 uint64_t WvDBusMsg::Iter::get_uint() const
00208 {
00209 dbus_bool_t b;
00210 unsigned char c;
00211 dbus_uint16_t s;
00212 dbus_uint32_t i;
00213 dbus_uint64_t l;
00214 char *str;
00215
00216 switch (type())
00217 {
00218 case DBUS_TYPE_BYTE:
00219 dbus_message_iter_get_basic(it, &c);
00220 return c;
00221
00222 case DBUS_TYPE_BOOLEAN:
00223 dbus_message_iter_get_basic(it, &b);
00224 return b;
00225
00226 case DBUS_TYPE_INT16:
00227 case DBUS_TYPE_UINT16:
00228 dbus_message_iter_get_basic(it, &s);
00229 return s;
00230
00231 case DBUS_TYPE_INT32:
00232 case DBUS_TYPE_UINT32:
00233 dbus_message_iter_get_basic(it, &i);
00234 return i;
00235
00236 case DBUS_TYPE_INT64:
00237 case DBUS_TYPE_UINT64:
00238 dbus_message_iter_get_basic(it, &l);
00239 return l;
00240
00241 case DBUS_TYPE_STRING:
00242 dbus_message_iter_get_basic(it, &str);
00243 return WvString(str).num();
00244
00245 case DBUS_TYPE_VARIANT:
00246 return open().getnext().get_uint();
00247
00248 default:
00249 return 0;
00250 }
00251 }
00252
00253
00254 double WvDBusMsg::Iter::get_double() const
00255 {
00256 dbus_bool_t b;
00257 unsigned char c;
00258 dbus_uint16_t s;
00259 dbus_uint32_t i;
00260 dbus_uint64_t l;
00261 char *str;
00262 double d;
00263
00264 switch (type())
00265 {
00266 case DBUS_TYPE_DOUBLE:
00267 dbus_message_iter_get_basic(it, &d);
00268 return d;
00269
00270 case DBUS_TYPE_BYTE:
00271 dbus_message_iter_get_basic(it, &c);
00272 return c;
00273
00274 case DBUS_TYPE_BOOLEAN:
00275 dbus_message_iter_get_basic(it, &b);
00276 return b;
00277
00278 case DBUS_TYPE_INT16:
00279 case DBUS_TYPE_UINT16:
00280 dbus_message_iter_get_basic(it, &s);
00281 return s;
00282
00283 case DBUS_TYPE_INT32:
00284 case DBUS_TYPE_UINT32:
00285 dbus_message_iter_get_basic(it, &i);
00286 return i;
00287
00288 case DBUS_TYPE_INT64:
00289 case DBUS_TYPE_UINT64:
00290 dbus_message_iter_get_basic(it, &l);
00291 return l;
00292
00293 case DBUS_TYPE_STRING:
00294 dbus_message_iter_get_basic(it, &str);
00295 return atof(str);
00296
00297 case DBUS_TYPE_VARIANT:
00298 return open().getnext().get_double();
00299
00300 default:
00301 return 0;
00302 }
00303 }
00304
00305
00306 WvString *WvDBusMsg::Iter::ptr() const
00307 {
00308 s = get_str();
00309 return &s;
00310 }
00311
00312
00313
00314
00315 static DBusMessageIter *new_append_iter(WvDBusMsg &msg)
00316 {
00317 DBusMessageIter *it = new DBusMessageIter;
00318 dbus_message_iter_init_append(msg, it);
00319 return it;
00320 }
00321
00322
00323 WvDBusMsg::WvDBusMsg(WvStringParm busname, WvStringParm objectname,
00324 WvStringParm interface, WvStringParm method)
00325 {
00326 msg = dbus_message_new_method_call(busname, objectname, interface, method);
00327 itlist.prepend(new_append_iter(*this), true);
00328 }
00329
00330
00331 WvDBusMsg::WvDBusMsg(WvDBusMsg &_msg)
00332 {
00333 msg = _msg.msg;
00334 dbus_message_ref(msg);
00335 itlist.prepend(new_append_iter(*this), true);
00336 }
00337
00338
00339 WvDBusMsg::WvDBusMsg(DBusMessage *_msg)
00340 {
00341 msg = _msg;
00342 dbus_message_ref(msg);
00343 itlist.prepend(new_append_iter(*this), true);
00344 }
00345
00346
00347 WvDBusMsg::~WvDBusMsg()
00348 {
00349 dbus_message_unref(msg);
00350 }
00351
00352
00353 WvDBusMsg::operator DBusMessage* () const
00354 {
00355 return msg;
00356 }
00357
00358
00359 WvString WvDBusMsg::get_sender() const
00360 {
00361 return dbus_message_get_sender(msg);
00362 }
00363
00364
00365 WvString WvDBusMsg::get_dest() const
00366 {
00367 return dbus_message_get_destination(msg);
00368 }
00369
00370
00371 WvString WvDBusMsg::get_path() const
00372 {
00373 return dbus_message_get_path(msg);
00374 }
00375
00376
00377 WvString WvDBusMsg::get_interface() const
00378 {
00379 return dbus_message_get_interface(msg);
00380 }
00381
00382
00383 WvString WvDBusMsg::get_member() const
00384 {
00385 return dbus_message_get_member(msg);
00386 }
00387
00388
00389 WvString WvDBusMsg::get_error() const
00390 {
00391 if (iserror())
00392 return dbus_message_get_error_name(msg);
00393
00394 return WvString::null;
00395 }
00396
00397 bool WvDBusMsg::is_reply() const
00398 {
00399
00400
00401
00402 return get_replyserial() != 0;
00403 }
00404
00405
00406 uint32_t WvDBusMsg::get_serial() const
00407 {
00408 return dbus_message_get_serial(msg);
00409 }
00410
00411
00412 uint32_t WvDBusMsg::get_replyserial() const
00413 {
00414 return dbus_message_get_reply_serial(msg);
00415 }
00416
00417
00418 void WvDBusMsg::get_arglist(WvStringList &list) const
00419 {
00420 Iter(*this).get_all(list);
00421 }
00422
00423
00424 WvString WvDBusMsg::get_argstr() const
00425 {
00426 return Iter(*this).get_all();
00427 }
00428
00429
00430 WvDBusMsg::operator WvString() const
00431 {
00432 WvString dest(get_dest());
00433 if (!dest)
00434 dest = "";
00435 else
00436 dest = WvString("%s:", dest);
00437 if (is_reply())
00438 {
00439 if (iserror())
00440 return WvString("ERR#%s->%s#%s(%s)",
00441 get_serial(), dest, get_replyserial(),
00442 get_argstr());
00443 else
00444 return WvString("REPLY#%s->%s#%s(%s)",
00445 get_serial(), dest, get_replyserial(),
00446 get_argstr());
00447 }
00448 else
00449 {
00450 WvString s("%s%s/%s.%s(%s)#%s",
00451 dest,
00452 get_path(), get_interface(), get_member(),
00453 get_argstr(), get_serial());
00454 s = strreplace(s, "org.freedesktop.DBus", "o.f.D");
00455 s = strreplace(s, "org/freedesktop/DBus", "o/f/D");
00456 return s;
00457 }
00458 }
00459
00460
00461 WvDBusMsg &WvDBusMsg::append(const char *s)
00462 {
00463 assert(msg);
00464 assert(s);
00465 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_STRING, &s);
00466 return *this;
00467 }
00468
00469
00470 WvDBusMsg &WvDBusMsg::append(bool b)
00471 {
00472 assert(msg);
00473 dbus_bool_t bb = b;
00474 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_BOOLEAN, &bb);
00475 return *this;
00476 }
00477
00478
00479 WvDBusMsg &WvDBusMsg::append(signed char c)
00480 {
00481 assert(msg);
00482 dbus_unichar_t cc = c;
00483 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_BYTE, &cc);
00484 return *this;
00485 }
00486
00487
00488 WvDBusMsg &WvDBusMsg::append(unsigned char c)
00489 {
00490 assert(msg);
00491 dbus_unichar_t cc = c;
00492 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_BYTE, &cc);
00493 return *this;
00494 }
00495
00496
00497 WvDBusMsg &WvDBusMsg::append(int16_t i)
00498 {
00499 assert(msg);
00500 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_INT16, &i);
00501 return *this;
00502 }
00503
00504
00505 WvDBusMsg &WvDBusMsg::append(uint16_t i)
00506 {
00507 assert(msg);
00508 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_UINT16, &i);
00509 return *this;
00510 }
00511
00512
00513 WvDBusMsg &WvDBusMsg::append(int32_t i)
00514 {
00515 assert(msg);
00516 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_INT32, &i);
00517 return *this;
00518 }
00519
00520
00521 WvDBusMsg &WvDBusMsg::append(uint32_t i)
00522 {
00523 assert(msg);
00524 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_UINT32, &i);
00525 return *this;
00526 }
00527
00528
00529 WvDBusMsg &WvDBusMsg::append(int64_t i)
00530 {
00531 assert(msg);
00532 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_INT64, &i);
00533 return *this;
00534 }
00535
00536
00537 WvDBusMsg &WvDBusMsg::append(uint64_t i)
00538 {
00539 assert(msg);
00540 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_UINT64, &i);
00541 return *this;
00542 }
00543
00544
00545 WvDBusMsg &WvDBusMsg::append(double d)
00546 {
00547 assert(msg);
00548 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_DOUBLE, &d);
00549 return *this;
00550 }
00551
00552
00553 WvDBusMsg &WvDBusMsg::variant_start(WvStringParm element_type)
00554 {
00555 DBusMessageIter *parent = itlist.first();
00556 DBusMessageIter *sub = new DBusMessageIter;
00557 dbus_message_iter_open_container(parent,
00558 DBUS_TYPE_VARIANT, element_type, sub);
00559 itlist.prepend(sub, true);
00560 return *this;
00561 }
00562
00563
00564 WvDBusMsg &WvDBusMsg::variant_end()
00565 {
00566 assert(itlist.count() >= 2);
00567
00568 WvList<DBusMessageIter>::Iter i(itlist);
00569 i.rewind(); i.next();
00570 DBusMessageIter *sub = i.ptr();
00571 i.next();
00572 DBusMessageIter *parent = i.ptr();
00573
00574 dbus_message_iter_close_container(parent, sub);
00575 itlist.unlink_first();
00576 return *this;
00577 }
00578
00579
00580 WvDBusMsg &WvDBusMsg::struct_start(WvStringParm element_type)
00581 {
00582 DBusMessageIter *parent = itlist.first();
00583 DBusMessageIter *sub = new DBusMessageIter;
00584 dbus_message_iter_open_container(parent,
00585 DBUS_TYPE_STRUCT, 0, sub);
00586 itlist.prepend(sub, true);
00587 return *this;
00588 }
00589
00590
00591 WvDBusMsg &WvDBusMsg::struct_end()
00592 {
00593 return array_end();
00594 }
00595
00596
00597 WvDBusMsg &WvDBusMsg::array_start(WvStringParm element_type)
00598 {
00599 DBusMessageIter *parent = itlist.first();
00600 DBusMessageIter *sub = new DBusMessageIter;
00601 dbus_message_iter_open_container(parent,
00602 DBUS_TYPE_ARRAY, element_type, sub);
00603 itlist.prepend(sub, true);
00604 return *this;
00605 }
00606
00607
00608 WvDBusMsg &WvDBusMsg::array_end()
00609 {
00610 return variant_end();
00611 }
00612
00613
00614 WvDBusMsg &WvDBusMsg::varray_start(WvStringParm element_type)
00615 {
00616 variant_start(WvString("a%s", element_type));
00617 return array_start(element_type);
00618 }
00619
00620
00621 WvDBusMsg &WvDBusMsg::varray_end()
00622 {
00623 assert(itlist.count() >= 3);
00624 array_end();
00625 return variant_end();
00626 }
00627
00628
00629 WvDBusMsg WvDBusMsg::reply()
00630 {
00631 return WvDBusReplyMsg(*this);
00632 }
00633
00634
00635 bool WvDBusMsg::iserror() const
00636 {
00637 return dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_ERROR;
00638 }
00639
00640
00641 void WvDBusMsg::send(WvDBusConn &conn)
00642 {
00643 conn.send(*this);
00644 }
00645
00646
00647 WvDBusReplyMsg::WvDBusReplyMsg(DBusMessage *_msg)
00648 : WvDBusMsg(dbus_message_new_method_return(_msg))
00649 {
00650 dbus_message_unref(msg);
00651 }
00652
00653
00654 WvDBusSignal::WvDBusSignal(WvStringParm objectname, WvStringParm interface,
00655 WvStringParm name)
00656 : WvDBusMsg(dbus_message_new_signal(objectname, interface, name))
00657 {
00658 dbus_message_unref(msg);
00659 }
00660
00661
00662 DBusMessage *WvDBusError::setup1(WvDBusMsg &in_reply_to,
00663 WvStringParm errname, WvStringParm message)
00664 {
00665 return dbus_message_new_error(in_reply_to, errname, message);
00666 }
00667
00668 void WvDBusError::setup2()
00669 {
00670 dbus_message_unref(msg);
00671 }