1 /*******************************************************************************
2 * Goggles Music Manager *
3 ********************************************************************************
4 * Copyright (C) 2007-2021 by Sander Jansen. All Rights Reserved *
5 * --- *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 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 General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see http://www.gnu.org/licenses. *
18 ********************************************************************************/
19 #include "gmdefs.h"
20 #include "GMDBus.h"
21 #include "FXThread.h"
22
23 #ifndef DBUS_MAJOR_VERSION
24 #define DBUS_MAJOR_VERSION 1
25 #endif
26
27 #ifndef DBUS_MINOR_VERSION
28 #define DBUS_MINOR_VERSION 0
29 #endif
30
31 #ifndef DBUS_MICRO_VERSION
32 #define DBUS_MICRO_VERSION 0
33 #endif
34
35 #define DBUSVERSION ((DBUS_MICRO_VERSION) + (DBUS_MINOR_VERSION*1000) + (DBUS_MAJOR_VERSION*100000))
36 #define MKDBUSVERSION(major,minor,release) ((release)+(minor*1000)+(major*100000))
37
38
39 /*******************************************************************************************************/
40 /* GLOBAL INIT */
41 /*******************************************************************************************************/
42
43 class GMDBusTimeout;
44
45 class GMDBusGlobal {
46 private:
47 FXMutex mutex;
48 FXHash tm;
49 FXHash connections;
50 public:
GMDBusGlobal()51 GMDBusGlobal() {
52 dbus_threads_init_default();
53 }
54
find(DBusConnection * dc)55 GMDBus * find(DBusConnection* dc) {
56 FXScopedMutex lock(mutex);
57 return static_cast<GMDBus*>(connections.at(dc));
58 }
59
setuphooks()60 void setuphooks() {
61 for (FXint i=0;i<connections.no();i++) {
62 if (!connections.empty(i)) {
63 static_cast<GMDBus*>(connections.data(i))->setup_event_loop();
64 }
65 }
66 }
67
insert(DBusConnection * dc,GMDBus * fxdc)68 void insert(DBusConnection * dc,GMDBus * fxdc) {
69 FXScopedMutex lock(mutex);
70 connections.insert(dc,fxdc);
71 }
72
remove(DBusConnection * dc)73 void remove(DBusConnection * dc) {
74 FXScopedMutex lock(mutex);
75 connections.remove(dc);
76 }
77
find(DBusTimeout * t)78 GMDBusTimeout * find(DBusTimeout*t) {
79 return static_cast<GMDBusTimeout*>(tm.at(t));
80 }
81
insert(DBusTimeout * t,GMDBusTimeout * f)82 void insert(DBusTimeout*t,GMDBusTimeout*f) {
83 tm.insert(t,f);
84 }
85
remove(DBusTimeout * t)86 void remove(DBusTimeout*t) {
87 tm.remove(t);
88 }
89 };
90
91 static GMDBusGlobal fxdbus;
92
93 class GMDBusTimeout : public FXObject {
94 FXDECLARE(GMDBusTimeout);
95 protected:
96 DBusTimeout* timeout = nullptr;
97 FXuchar flags = 0;
98 protected:
GMDBusTimeout()99 GMDBusTimeout(){}
100 private:
101 GMDBusTimeout(const GMDBusTimeout*);
102 GMDBusTimeout& operator=(const GMDBusTimeout&);
103 protected:
104 enum {
105 FLAG_CALLBACK = 0x1,
106 FLAG_REMOVED = 0x2
107 };
108 public:
109 enum {
110 ID_TIMEOUT = 1
111 };
112 public:
113 long onTimeout(FXObject*,FXSelector,void*);
114 public:
115 GMDBusTimeout(DBusTimeout *t);
116 void add();
117 void remove();
118 ~GMDBusTimeout();
119 };
120
121 FXDEFMAP(GMDBusTimeout) GMDBusTimeoutMap[]={
122 FXMAPFUNC(SEL_TIMEOUT,GMDBusTimeout::ID_TIMEOUT,GMDBusTimeout::onTimeout),
123 };
124 FXIMPLEMENT(GMDBusTimeout,FXObject,GMDBusTimeoutMap,ARRAYNUMBER(GMDBusTimeoutMap));
125
126
127
GMDBusTimeout(DBusTimeout * t)128 GMDBusTimeout::GMDBusTimeout(DBusTimeout *t) : timeout(t){
129 fxdbus.insert(timeout,this);
130 }
131
~GMDBusTimeout()132 GMDBusTimeout::~GMDBusTimeout() {
133 fxdbus.remove(timeout);
134 }
135
add()136 void GMDBusTimeout::add() {
137 flags&=~FLAG_REMOVED;
138 FXApp::instance()->addTimeout(this,GMDBusTimeout::ID_TIMEOUT,TIME_MSEC(dbus_timeout_get_interval(timeout)));
139 }
140
remove()141 void GMDBusTimeout::remove() {
142 if (flags&FLAG_CALLBACK) {
143 flags|=FLAG_REMOVED;
144 return;
145 }
146 FXApp::instance()->removeTimeout(this,GMDBusTimeout::ID_TIMEOUT);
147 delete this;
148 }
149
150
fxdbus_addtimeout(DBusTimeout * timeout,void *)151 static dbus_bool_t fxdbus_addtimeout(DBusTimeout *timeout,void *) {
152 //fxmessage("fxdbus_addtimeout %p\n",timeout);
153 GMDBusTimeout * tm = fxdbus.find(timeout);
154 if (tm==nullptr)
155 tm = new GMDBusTimeout(timeout);
156
157 tm->add();
158 return true;
159 }
160
161
fxdbus_removetimeout(DBusTimeout * timeout,void *)162 static void fxdbus_removetimeout(DBusTimeout *timeout,void *) {
163 //fxmessage("fxdbus_removetimeout %p\n",timeout);
164 GMDBusTimeout * tm = fxdbus.find(timeout);
165 if (tm) tm->remove();
166 }
167
fxdbus_toggletimeout(DBusTimeout * timeout,void * data)168 static void fxdbus_toggletimeout(DBusTimeout *timeout,void*data) {
169 //fxmessage("fxdbus_toggletimeout %p\n",timeout);
170 if (dbus_timeout_get_enabled(timeout) && dbus_timeout_get_interval(timeout)>0)
171 fxdbus_addtimeout(timeout,data);
172 else
173 fxdbus_removetimeout(timeout,data);
174 }
175
onTimeout(FXObject *,FXSelector,void *)176 long GMDBusTimeout::onTimeout(FXObject*,FXSelector,void*){
177 //fxmessage("onTimeout() %p {\n",timeout);
178 flags|=FLAG_CALLBACK;
179 dbus_timeout_handle(timeout);
180 if (flags&FLAG_REMOVED) {
181 delete this;
182 //fxmessage("}\n");
183 return 1;
184 }
185 else {
186 if (dbus_timeout_get_enabled(timeout) && dbus_timeout_get_interval(timeout)>0 && !FXApp::instance()->hasTimeout(this,ID_TIMEOUT)){
187 FXApp::instance()->addTimeout(this,GMDBusTimeout::ID_TIMEOUT,TIME_MSEC(dbus_timeout_get_interval(timeout)));
188 }
189 }
190 flags&=~FLAG_CALLBACK;
191 //fxmessage("}\n");
192 return 1;
193 }
194
195
196
197
198
199
200
201
202
203
204
205 /*******************************************************************************************************/
206 /* Call Backs */
207 /*******************************************************************************************************/
208
fxdbus_addwatch(DBusWatch * watch,void * data)209 static dbus_bool_t fxdbus_addwatch(DBusWatch *watch,void * data) {
210 FXTRACE((35,"fxdbus_addwatch()\n"));
211 GMDBus * dc = static_cast<GMDBus*>(data);
212 FXuint mode = INPUT_EXCEPT;
213 FXuint flags = dbus_watch_get_flags(watch);
214
215 /// If it's not enabled, we're not going to add it
216 if (!dbus_watch_get_enabled(watch)) return true;
217
218 if (flags&DBUS_WATCH_READABLE)
219 mode|=INPUT_READ;
220 if (flags&DBUS_WATCH_WRITABLE)
221 mode|=INPUT_WRITE;
222
223 #if DBUSVERSION == MKDBUSVERSION(1,1,20) || DBUSVERSION >= MKDBUSVERSION(1,2,0)
224 return FXApp::instance()->addInput(dc,GMDBus::ID_HANDLE,(FXInputHandle)dbus_watch_get_unix_fd(watch),mode,watch);
225 #else
226 return FXApp::instance()->addInput(dc,GMDBus::ID_HANDLE,(FXInputHandle)dbus_watch_get_fd(watch),mode,watch);
227 #endif
228
229 }
230
fxdbus_removewatch(DBusWatch * watch,void *)231 static void fxdbus_removewatch(DBusWatch *watch,void *) {
232 FXTRACE((35,"fxdbus_removewatch()\n"));
233 /*
234 FXuint mode=INPUT_EXCEPT;
235 unsigned int flags = dbus_watch_get_flags(watch);
236 if (flags&DBUS_WATCH_READABLE)
237 mode|=INPUT_READ;
238 if (flags&DBUS_WATCH_WRITABLE) {
239 mode|=INPUT_WRITE;
240 return;
241 }
242 */
243 FXuint mode=INPUT_READ|INPUT_WRITE|INPUT_EXCEPT;
244 #if DBUSVERSION == MKDBUSVERSION(1,1,20) || DBUSVERSION >= MKDBUSVERSION(1,2,0)
245 FXApp::instance()->removeInput(dbus_watch_get_unix_fd(watch),mode);
246 #else
247 FXApp::instance()->removeInput(dbus_watch_get_fd(watch),mode);
248 #endif
249
250 }
251
fxdbus_togglewatch(DBusWatch * watch,void * data)252 static void fxdbus_togglewatch(DBusWatch *watch,void* data) {
253 FXTRACE((35,"fxdbus_togglewatch()\n"));
254 if (dbus_watch_get_enabled(watch))
255 fxdbus_addwatch(watch,data);
256 else
257 fxdbus_removewatch(watch,data);
258 }
259
fxdbus_wakeup(void *)260 static void fxdbus_wakeup(void *){
261 /// To Do
262 }
263
264
265
266 /*******************************************************************************************************/
267 /* PUBLIC API */
268 /*******************************************************************************************************/
269
270 FXDEFMAP(GMDBus) GMDBusMap[]={
271 FXMAPFUNC(SEL_IO_READ,GMDBus::ID_HANDLE,GMDBus::onHandleRead),
272 FXMAPFUNC(SEL_IO_WRITE,GMDBus::ID_HANDLE,GMDBus::onHandleWrite),
273 FXMAPFUNC(SEL_IO_EXCEPT,GMDBus::ID_HANDLE,GMDBus::onHandleExcept),
274 FXMAPFUNC(SEL_CHORE,GMDBus::ID_DISPATCH,GMDBus::onDispatch)
275 };
276
277 FXIMPLEMENT(GMDBus,FXObject,GMDBusMap,ARRAYNUMBER(GMDBusMap));
278
GMDBus()279 GMDBus::GMDBus() {
280 }
281
~GMDBus()282 GMDBus::~GMDBus(){
283 if (dc) {
284 fxdbus.remove(dc);
285 dbus_connection_unref(dc);
286 dc=nullptr;
287 FXApp::instance()->removeChore(this,ID_DISPATCH);
288 }
289 }
290
291
find(DBusConnection * dc)292 GMDBus * GMDBus::find(DBusConnection * dc) {
293 return fxdbus.find(dc);
294 }
295
initEventLoop()296 void GMDBus::initEventLoop() {
297 fxdbus.setuphooks();
298 }
299
300
open(DBusBusType bustype)301 FXbool GMDBus::open(DBusBusType bustype/*=DBUS_BUS_SESSION*/){
302 FXASSERT(dc==nullptr);
303 dc = dbus_bus_get(bustype,nullptr);
304 if (dc==nullptr) return false;
305 if (fxdbus.find(dc)) {
306 dbus_connection_unref(dc);
307 dc=nullptr;
308 return false;
309 }
310 fxdbus.insert(dc,this);
311 dbus_connection_set_exit_on_disconnect(dc,false);
312 return true;
313 }
314
315
connected() const316 FXbool GMDBus::connected() const {
317 if (dc)
318 return dbus_connection_get_is_connected(dc);
319 else
320 return false;
321 }
322
authenticated() const323 FXbool GMDBus::authenticated() const {
324 if (dc)
325 return dbus_connection_get_is_authenticated(dc);
326 else
327 return false;
328 }
329
flush()330 void GMDBus::flush() {
331 if (dc) dbus_connection_flush(dc);
332 }
333
334
dbusversion()335 FXString GMDBus::dbusversion() {
336 #if (DBUSVERSION == MKDBUSVERSION(1,1,20)) || DBUSVERSION >= MKDBUSVERSION(1,2,0)
337 int major,minor,micro;
338 dbus_get_version(&major,&minor,µ);
339 return FXString::value("%d.%d.%d",major,minor,micro);
340 #else
341 return FXString("1.0.x");
342 #endif
343 }
344
345 struct CallTarget{
346 FXObject * target;
347 FXSelector message;
348 };
349
fxdbus_pendingcallfree(void * memory)350 static void fxdbus_pendingcallfree(void *memory){
351 //fxmessage("fxdbuspendingcallfree\n");
352 if (memory){
353 CallTarget * call = static_cast<CallTarget*>(memory);
354 delete call;
355 }
356 }
357
fxdbus_pendingcallnotify(DBusPendingCall * pending,void * data)358 static void fxdbus_pendingcallnotify(DBusPendingCall*pending,void*data){
359 DBusMessage * msg = dbus_pending_call_steal_reply(pending);
360 if (msg) {
361 CallTarget * call = static_cast<CallTarget*>(data);
362 if (call && call->target && call->message) {
363 call->target->handle(nullptr,FXSEL(SEL_COMMAND,call->message),msg);
364 }
365 dbus_message_unref(msg);
366 }
367 }
368
369
sendWithReply(DBusMessage * msg,FXint timeout,FXObject * tgt,FXSelector sel)370 FXbool GMDBus::sendWithReply(DBusMessage * msg,FXint timeout,FXObject*tgt,FXSelector sel){
371 FXASSERT(msg);
372 DBusPendingCall * pending = nullptr;
373 if (dbus_connection_send_with_reply(dc,msg,&pending,timeout)) {
374 if (pending) {
375 CallTarget * call = new CallTarget;
376 call->target=tgt;
377 call->message=sel;
378 dbus_pending_call_set_notify(pending,fxdbus_pendingcallnotify,(void*)call,fxdbus_pendingcallfree);
379 dbus_pending_call_unref(pending);
380 }
381 dbus_message_unref(msg);
382 return true;
383 }
384 return false;
385 }
386
387
send(DBusMessage * msg)388 void GMDBus::send(DBusMessage * msg){
389 FXuint serial;
390 dbus_connection_send(dc,msg,&serial);
391 dbus_message_unref(msg);
392 }
393
send(DBusMessage * msg,FXuint & serial)394 void GMDBus::send(DBusMessage * msg,FXuint & serial){
395 dbus_connection_send(dc,msg,&serial);
396 dbus_message_unref(msg);
397 }
398
399
400
401 /*******************************************************************************************************/
402 /* MESSAGE HANDLERS */
403 /*******************************************************************************************************/
404
onHandleRead(FXObject *,FXSelector,void * ptr)405 long GMDBus::onHandleRead(FXObject*,FXSelector,void*ptr){
406 DBusWatch * watch = static_cast<DBusWatch*>(ptr);
407 dbus_watch_handle(watch,DBUS_WATCH_READABLE);
408 FXApp::instance()->addChore(this,ID_DISPATCH);
409 return 0;
410 }
411
onHandleWrite(FXObject *,FXSelector,void * ptr)412 long GMDBus::onHandleWrite(FXObject*,FXSelector,void*ptr){
413 DBusWatch * watch = static_cast<DBusWatch*>(ptr);
414 dbus_watch_handle(watch,DBUS_WATCH_WRITABLE);
415 return 0;
416 }
417
onHandleExcept(FXObject *,FXSelector,void * ptr)418 long GMDBus::onHandleExcept(FXObject*,FXSelector,void*ptr){
419 DBusWatch * watch = static_cast<DBusWatch*>(ptr);
420 dbus_watch_handle(watch,DBUS_WATCH_ERROR|DBUS_WATCH_HANGUP);
421 return 0;
422 }
423
onDispatch(FXObject *,FXSelector,void *)424 long GMDBus::onDispatch(FXObject*,FXSelector,void*){
425 if (dbus_connection_dispatch((DBusConnection*)dc)==DBUS_DISPATCH_DATA_REMAINS) {
426 FXApp::instance()->addChore(this,ID_DISPATCH);
427 }
428 return 0;
429 }
430
431
432 /*******************************************************************************************************/
433 /* PROTECTED API */
434 /*******************************************************************************************************/
435
setup_event_loop()436 void GMDBus::setup_event_loop() {
437 FXASSERT(dc);
438
439 dbus_connection_set_watch_functions(dc,
440 fxdbus_addwatch,
441 fxdbus_removewatch,
442 fxdbus_togglewatch,
443 this,nullptr);
444
445 dbus_connection_set_timeout_functions(dc,
446 fxdbus_addtimeout,
447 fxdbus_removetimeout,
448 fxdbus_toggletimeout,
449 this,nullptr);
450
451 dbus_connection_set_wakeup_main_function(dc,fxdbus_wakeup,nullptr,nullptr);
452 }
453
454
455
456
457
dbus_proxy_filter(DBusConnection *,DBusMessage * msg,void * ptr)458 static DBusHandlerResult dbus_proxy_filter(DBusConnection *,DBusMessage * msg,void * ptr){
459 GMDBusProxy * proxy = static_cast<GMDBusProxy*>(ptr);
460 FXASSERT(proxy);
461 FXuint type = dbus_message_get_type(msg);
462
463 if (type==DBUS_MESSAGE_TYPE_METHOD_CALL) {
464 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
465 }
466 else if (type==DBUS_MESSAGE_TYPE_METHOD_RETURN || type==DBUS_MESSAGE_TYPE_ERROR) {
467 if (proxy->matchSerial(msg))
468 return DBUS_HANDLER_RESULT_HANDLED;
469 else
470 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
471 }
472 else { /* SIGNALS */
473 DEBUG_DBUS_MESSAGE(msg);
474
475 if (dbus_message_has_path(msg,DBUS_PATH_DBUS)) {
476 if (dbus_message_is_signal(msg,DBUS_INTERFACE_DBUS,"NameOwnerChanged")) {
477 const FXchar * dbus_name=nullptr;
478 const FXchar * new_owner=nullptr;
479 const FXchar * old_owner=nullptr;
480 if (dbus_message_get_args(msg,nullptr,DBUS_TYPE_STRING,&dbus_name,DBUS_TYPE_STRING,&old_owner,DBUS_TYPE_STRING,&new_owner,DBUS_TYPE_INVALID)) {
481 if (compare(proxy->getName(),dbus_name)==0) {
482 if (new_owner==nullptr || compare(new_owner,"")==0) {
483 proxy->handle(proxy,FXSEL(SEL_DESTROY,0),nullptr);
484 }
485 else if (old_owner==nullptr || compare(old_owner,"")==0){
486 proxy->handle(proxy,FXSEL(SEL_CREATE,0),nullptr);
487 }
488 else {
489 proxy->handle(proxy,FXSEL(SEL_REPLACED,0),nullptr);
490 }
491 return DBUS_HANDLER_RESULT_HANDLED;
492 }
493 }
494 }
495 }
496 /// Make sure it is for us...
497 if (dbus_message_has_path(msg,proxy->getPath().text()) && dbus_message_has_interface(msg,proxy->getInterface().text())) {
498 return proxy->handle(proxy,FXSEL(SEL_SIGNAL,0),msg) ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
499 }
500 }
501 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
502 }
503
504
505
506 struct GMDBusProxyReply {
507 FXObject * target;
508 FXSelector message;
GMDBusProxyReplyGMDBusProxyReply509 GMDBusProxyReply(FXObject * t,FXSelector m) : target(t), message(m) {}
510 };
511
512
513 FXDEFMAP(GMDBusProxy) GMDBusProxyMap[]={
514 FXMAPFUNC(SEL_CREATE, 0,GMDBusProxy::onCreate),
515 FXMAPFUNC(SEL_DESTROY, 0,GMDBusProxy::onDestroy),
516 FXMAPFUNC(SEL_REPLACED, 0,GMDBusProxy::onReplaced),
517 FXMAPFUNC(SEL_SIGNAL, 0,GMDBusProxy::onSignal),
518 FXMAPFUNC(SEL_COMMAND, 0,GMDBusProxy::onMethod),
519 };
520
521 FXIMPLEMENT(GMDBusProxy,FXObject,GMDBusProxyMap,ARRAYNUMBER(GMDBusProxyMap));
522
523
GMDBusProxy()524 GMDBusProxy::GMDBusProxy() {
525 }
526
~GMDBusProxy()527 GMDBusProxy::~GMDBusProxy() {
528 FXString rule = "type='signal',sender='"+ name +"',path='" + path +"',interface='"+interface+"'";
529 dbus_bus_remove_match(bus->connection(),rule.text(),nullptr);
530 dbus_connection_remove_filter(bus->connection(),dbus_proxy_filter,this);
531
532 /// remove any pending proxy replies;
533 for (FXint i=0;i<serial.no();i++) {
534 if (!serial.empty(i)) {
535 GMDBusProxyReply * reply = static_cast<GMDBusProxyReply*>(serial.data(i));
536 delete reply;
537 }
538 }
539 serial.clear();
540 }
541
GMDBusProxy(GMDBus * c,const FXchar * n,const FXchar * p,const FXchar * i)542 GMDBusProxy::GMDBusProxy(GMDBus *c,const FXchar * n,const FXchar * p,const FXchar * i) : bus(c),name(n),path(p),interface(i),associated(true),target(nullptr) {
543 FXString rule = "type='signal',sender='"+ name +"',path='" + path +"',interface='"+interface+"'";
544 dbus_bus_add_match(bus->connection(),rule.text(),nullptr);
545 dbus_connection_add_filter(bus->connection(),dbus_proxy_filter,this,nullptr);
546 }
547
548
matchSerial(DBusMessage * msg)549 FXbool GMDBusProxy::matchSerial(DBusMessage * msg) {
550 void * ptr;
551 FXuint s=dbus_message_get_reply_serial(msg);
552 if (s && (ptr=serial.at((void*)(FXuval)s))!=nullptr) {
553 GMDBusProxyReply * reply = static_cast<GMDBusProxyReply*>(ptr);
554 if (reply->target) reply->target->handle(this,FXSEL(SEL_COMMAND,reply->message),msg);
555 serial.remove((void*)(FXuval)dbus_message_get_reply_serial(msg));
556 delete reply;
557 return true;
558 }
559 else {
560 return false;
561 }
562 }
563
send(DBusMessage * msg,FXObject * obj,FXSelector m)564 void GMDBusProxy::send(DBusMessage*msg,FXObject * obj,FXSelector m) {
565 FXuint s;
566 dbus_connection_send(bus->connection(),msg,&s);
567 dbus_message_unref(msg);
568 serial.insert((void*)(FXuval)s,new GMDBusProxyReply(obj,m));
569 }
570
571
572
method(const FXchar * methodcall)573 DBusMessage * GMDBusProxy::method(const FXchar * methodcall){
574 return dbus_message_new_method_call(name.text(),path.text(),interface.text(),methodcall);
575 }
576
signal(const FXchar * sname)577 DBusMessage * GMDBusProxy::signal(const FXchar * sname){
578 return dbus_message_new_signal(path.text(),interface.text(),sname);
579 }
580
581
onCreate(FXObject *,FXSelector,void * ptr)582 long GMDBusProxy::onCreate(FXObject*,FXSelector,void*ptr) {
583 associated=true;
584 return target && target->tryHandle(this,FXSEL(SEL_DESTROY,message),ptr);
585 }
onDestroy(FXObject *,FXSelector,void * ptr)586 long GMDBusProxy::onDestroy(FXObject*,FXSelector,void*ptr) {
587 associated=false;
588 return target && target->tryHandle(this,FXSEL(SEL_DESTROY,message),ptr);
589 }
onReplaced(FXObject *,FXSelector,void * ptr)590 long GMDBusProxy::onReplaced(FXObject*,FXSelector,void*ptr) {
591 return target && target->tryHandle(this,FXSEL(SEL_REPLACED,message),ptr);
592 }
onSignal(FXObject *,FXSelector,void * ptr)593 long GMDBusProxy::onSignal(FXObject*,FXSelector,void*ptr) {
594 return target && target->tryHandle(this,FXSEL(SEL_SIGNAL,message),ptr);
595 }
onMethod(FXObject *,FXSelector,void * ptr)596 long GMDBusProxy::onMethod(FXObject*,FXSelector,void*ptr) {
597 return target && target->tryHandle(this,FXSEL(SEL_COMMAND,message),ptr);
598 }
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620 /*******************************************************************************************************/
621 /* HELPER API */
622 /*******************************************************************************************************/
623
624
gm_dbus_variant_append_basic(DBusMessageIter * iter,const FXchar * element_type_string,FXint element_type,const void * value)625 void gm_dbus_variant_append_basic(DBusMessageIter * iter,const FXchar * element_type_string,FXint element_type,const void * value) {
626 DBusMessageIter container;
627 dbus_message_iter_open_container(iter,DBUS_TYPE_VARIANT,element_type_string,&container);
628 dbus_message_iter_append_basic(&container,element_type,value);
629 dbus_message_iter_close_container(iter,&container);
630 }
631
632
gm_dbus_variant_append_string(DBusMessageIter * iter,const FXchar * value)633 void gm_dbus_variant_append_string(DBusMessageIter * iter,const FXchar * value) {
634 gm_dbus_variant_append_basic(iter,DBUS_TYPE_STRING_AS_STRING,DBUS_TYPE_STRING,&value);
635 }
636
gm_dbus_variant_append_int32(DBusMessageIter * iter,const FXint value)637 void gm_dbus_variant_append_int32(DBusMessageIter * iter,const FXint value){
638 gm_dbus_variant_append_basic(iter,DBUS_TYPE_INT32_AS_STRING,DBUS_TYPE_INT32,&value);
639 }
640
gm_dbus_variant_append_uint32(DBusMessageIter * iter,const FXuint value)641 void gm_dbus_variant_append_uint32(DBusMessageIter * iter,const FXuint value){
642 gm_dbus_variant_append_basic(iter,DBUS_TYPE_UINT32_AS_STRING,DBUS_TYPE_UINT32,&value);
643 }
644
gm_dbus_variant_append_path(DBusMessageIter * iter,const FXchar * value)645 void gm_dbus_variant_append_path(DBusMessageIter * iter,const FXchar * value){
646 gm_dbus_variant_append_basic(iter,DBUS_TYPE_OBJECT_PATH_AS_STRING,DBUS_TYPE_OBJECT_PATH,&value);
647 }
648
gm_dbus_variant_append_bool(DBusMessageIter * iter,const dbus_bool_t value)649 void gm_dbus_variant_append_bool(DBusMessageIter * iter,const dbus_bool_t value){
650 gm_dbus_variant_append_basic(iter,DBUS_TYPE_BOOLEAN_AS_STRING,DBUS_TYPE_BOOLEAN,&value);
651 }
652
gm_dbus_variant_append_double(DBusMessageIter * iter,const FXdouble value)653 void gm_dbus_variant_append_double(DBusMessageIter * iter,const FXdouble value){
654 gm_dbus_variant_append_basic(iter,DBUS_TYPE_DOUBLE_AS_STRING,DBUS_TYPE_DOUBLE,&value);
655 }
656
gm_dbus_variant_append_long(DBusMessageIter * iter,const FXlong value)657 void gm_dbus_variant_append_long(DBusMessageIter * iter,const FXlong value){
658 gm_dbus_variant_append_basic(iter,DBUS_TYPE_INT64_AS_STRING,DBUS_TYPE_INT64,&value);
659 }
660
gm_dbus_variant_append_string_list(DBusMessageIter * iter,const FXchar * value[])661 void gm_dbus_variant_append_string_list(DBusMessageIter * iter,const FXchar * value[]){
662 DBusMessageIter container;
663 DBusMessageIter array;
664 dbus_message_iter_open_container(iter,DBUS_TYPE_VARIANT,DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,&container);
665 dbus_message_iter_open_container(&container,DBUS_TYPE_ARRAY,DBUS_TYPE_STRING_AS_STRING,&array);
666 for (FXint n=0;value[n];n++) {
667 dbus_message_iter_append_basic(&array,DBUS_TYPE_STRING,&value[n]);
668 }
669 dbus_message_iter_close_container(&container,&array);
670 dbus_message_iter_close_container(iter,&container);
671 }
672
gm_dbus_variant_append_string_list(DBusMessageIter * iter,const FXStringList & list)673 void gm_dbus_variant_append_string_list(DBusMessageIter * iter,const FXStringList & list){
674 DBusMessageIter container;
675 DBusMessageIter array;
676 dbus_message_iter_open_container(iter,DBUS_TYPE_VARIANT,DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,&container);
677 dbus_message_iter_open_container(&container,DBUS_TYPE_ARRAY,DBUS_TYPE_STRING_AS_STRING,&array);
678 for (FXint n=0;n<list.no();n++) {
679 gm_dbus_append_string(&array,list[n]);
680 }
681 dbus_message_iter_close_container(&container,&array);
682 dbus_message_iter_close_container(iter,&container);
683 }
684
gm_dbus_append_string(DBusMessageIter * iter,const FXString & value)685 void gm_dbus_append_string(DBusMessageIter *iter,const FXString & value){
686 const FXchar * v = value.text();
687 dbus_message_iter_append_basic(iter,DBUS_TYPE_STRING,&v);
688 }
689
690
gm_dbus_append_string_pair(DBusMessageIter * iter,const FXchar * key,const FXchar * value)691 void gm_dbus_append_string_pair(DBusMessageIter *iter,const FXchar * key,const FXchar * value){
692 dbus_message_iter_append_basic(iter,DBUS_TYPE_STRING,&key);
693 dbus_message_iter_append_basic(iter,DBUS_TYPE_STRING,&value);
694 }
695
696
gm_dbus_dict_append_int32(DBusMessageIter * iter,const FXchar * key,const FXint value)697 void gm_dbus_dict_append_int32(DBusMessageIter * iter,const FXchar * key,const FXint value){
698 DBusMessageIter container;
699 dbus_message_iter_open_container(iter,DBUS_TYPE_DICT_ENTRY,0,&container);
700 dbus_message_iter_append_basic(&container,DBUS_TYPE_STRING,&key);
701 gm_dbus_variant_append_int32(&container,value);
702 dbus_message_iter_close_container(iter,&container);
703 }
704
gm_dbus_dict_append_uint32(DBusMessageIter * iter,const FXchar * key,const FXuint value)705 void gm_dbus_dict_append_uint32(DBusMessageIter * iter,const FXchar * key,const FXuint value){
706 DBusMessageIter container;
707 dbus_message_iter_open_container(iter,DBUS_TYPE_DICT_ENTRY,0,&container);
708 dbus_message_iter_append_basic(&container,DBUS_TYPE_STRING,&key);
709 gm_dbus_variant_append_uint32(&container,value);
710 dbus_message_iter_close_container(iter,&container);
711 }
712
713
gm_dbus_dict_append_string(DBusMessageIter * iter,const FXchar * key,const FXchar * value)714 void gm_dbus_dict_append_string(DBusMessageIter * iter,const FXchar * key,const FXchar * value){
715 DBusMessageIter container;
716 dbus_message_iter_open_container(iter,DBUS_TYPE_DICT_ENTRY,0,&container);
717 dbus_message_iter_append_basic(&container,DBUS_TYPE_STRING,&key);
718 gm_dbus_variant_append_string(&container,value);
719 dbus_message_iter_close_container(iter,&container);
720 }
721
gm_dbus_dict_append_string(DBusMessageIter * iter,const FXchar * key,const FXString & value)722 void gm_dbus_dict_append_string(DBusMessageIter * iter,const FXchar * key,const FXString & value){
723 DBusMessageIter container;
724 dbus_message_iter_open_container(iter,DBUS_TYPE_DICT_ENTRY,0,&container);
725 dbus_message_iter_append_basic(&container,DBUS_TYPE_STRING,&key);
726 gm_dbus_variant_append_string(&container,value.text());
727 dbus_message_iter_close_container(iter,&container);
728 }
729
gm_dbus_dict_append_path(DBusMessageIter * iter,const FXchar * key,const FXchar * value)730 void gm_dbus_dict_append_path(DBusMessageIter * iter,const FXchar * key,const FXchar * value){
731 DBusMessageIter container;
732 dbus_message_iter_open_container(iter,DBUS_TYPE_DICT_ENTRY,0,&container);
733 dbus_message_iter_append_basic(&container,DBUS_TYPE_STRING,&key);
734 gm_dbus_variant_append_path(&container,value);
735 dbus_message_iter_close_container(iter,&container);
736 }
737
gm_dbus_dict_append_bool(DBusMessageIter * iter,const FXchar * key,const dbus_bool_t value)738 void gm_dbus_dict_append_bool(DBusMessageIter * iter,const FXchar * key,const dbus_bool_t value){
739 DBusMessageIter container;
740 dbus_message_iter_open_container(iter,DBUS_TYPE_DICT_ENTRY,0,&container);
741 dbus_message_iter_append_basic(&container,DBUS_TYPE_STRING,&key);
742 gm_dbus_variant_append_bool(&container,value);
743 dbus_message_iter_close_container(iter,&container);
744 }
745
746
gm_dbus_dict_append_double(DBusMessageIter * iter,const FXchar * key,const FXdouble & value)747 void gm_dbus_dict_append_double(DBusMessageIter * iter,const FXchar * key,const FXdouble & value){
748 DBusMessageIter container;
749 dbus_message_iter_open_container(iter,DBUS_TYPE_DICT_ENTRY,0,&container);
750 dbus_message_iter_append_basic(&container,DBUS_TYPE_STRING,&key);
751 gm_dbus_variant_append_double(&container,value);
752 dbus_message_iter_close_container(iter,&container);
753 }
754
gm_dbus_dict_append_long(DBusMessageIter * iter,const FXchar * key,const FXlong & value)755 void gm_dbus_dict_append_long(DBusMessageIter * iter,const FXchar * key,const FXlong & value){
756 DBusMessageIter container;
757 dbus_message_iter_open_container(iter,DBUS_TYPE_DICT_ENTRY,0,&container);
758 dbus_message_iter_append_basic(&container,DBUS_TYPE_STRING,&key);
759 gm_dbus_variant_append_long(&container,value);
760 dbus_message_iter_close_container(iter,&container);
761 }
762
763
gm_dbus_dict_append_string_list(DBusMessageIter * iter,const FXchar * key,const FXchar * value[])764 void gm_dbus_dict_append_string_list(DBusMessageIter * iter,const FXchar * key,const FXchar * value[]){
765 DBusMessageIter container;
766 dbus_message_iter_open_container(iter,DBUS_TYPE_DICT_ENTRY,0,&container);
767 dbus_message_iter_append_basic(&container,DBUS_TYPE_STRING,&key);
768 gm_dbus_variant_append_string_list(&container,value);
769 dbus_message_iter_close_container(iter,&container);
770 }
771
gm_dbus_dict_append_string_list(DBusMessageIter * iter,const FXchar * key,const FXStringList & value)772 void gm_dbus_dict_append_string_list(DBusMessageIter * iter,const FXchar * key,const FXStringList &value){
773 DBusMessageIter container;
774 dbus_message_iter_open_container(iter,DBUS_TYPE_DICT_ENTRY,0,&container);
775 dbus_message_iter_append_basic(&container,DBUS_TYPE_STRING,&key);
776 gm_dbus_variant_append_string_list(&container,value);
777 dbus_message_iter_close_container(iter,&container);
778 }
779
780
gm_dbus_property_string(DBusConnection * connection,DBusMessage * msg,const FXchar * data)781 DBusHandlerResult gm_dbus_property_string(DBusConnection * connection,DBusMessage * msg,const FXchar * data) {
782 FXuint serial;
783 DBusMessage * reply = dbus_message_new_method_return(msg);
784 if (reply) {
785 DBusMessageIter iter;
786 dbus_message_iter_init_append(reply,&iter);
787 gm_dbus_variant_append_string(&iter,data);
788 dbus_connection_send(connection,reply,&serial);
789 dbus_message_unref(reply);
790 }
791 return DBUS_HANDLER_RESULT_HANDLED;
792 }
793
gm_dbus_property_string_list(DBusConnection * connection,DBusMessage * msg,const FXchar * data[])794 DBusHandlerResult gm_dbus_property_string_list(DBusConnection * connection,DBusMessage * msg,const FXchar * data[]) {
795 FXuint serial;
796 DBusMessage * reply = dbus_message_new_method_return(msg);
797 if (reply) {
798 DBusMessageIter iter;
799 dbus_message_iter_init_append(reply,&iter);
800 gm_dbus_variant_append_string_list(&iter,data);
801 dbus_connection_send(connection,reply,&serial);
802 dbus_message_unref(reply);
803 }
804 return DBUS_HANDLER_RESULT_HANDLED;
805 }
806
807
gm_dbus_property_bool(DBusConnection * connection,DBusMessage * msg,const dbus_bool_t data)808 DBusHandlerResult gm_dbus_property_bool(DBusConnection * connection,DBusMessage * msg,const dbus_bool_t data) {
809 FXuint serial;
810 DBusMessage * reply = dbus_message_new_method_return(msg);
811 if (reply) {
812 DBusMessageIter iter;
813 dbus_message_iter_init_append(reply,&iter);
814 gm_dbus_variant_append_bool(&iter,data);
815 dbus_connection_send(connection,reply,&serial);
816 dbus_message_unref(reply);
817 }
818 return DBUS_HANDLER_RESULT_HANDLED;
819 }
820
gm_dbus_property_long(DBusConnection * connection,DBusMessage * msg,const FXlong data)821 DBusHandlerResult gm_dbus_property_long(DBusConnection * connection,DBusMessage * msg,const FXlong data) {
822 FXuint serial;
823 DBusMessage * reply = dbus_message_new_method_return(msg);
824 if (reply) {
825 DBusMessageIter iter;
826 dbus_message_iter_init_append(reply,&iter);
827 gm_dbus_variant_append_long(&iter,data);
828 dbus_connection_send(connection,reply,&serial);
829 dbus_message_unref(reply);
830 }
831 return DBUS_HANDLER_RESULT_HANDLED;
832 }
833
834
gm_dbus_property_double(DBusConnection * connection,DBusMessage * msg,const FXdouble data)835 DBusHandlerResult gm_dbus_property_double(DBusConnection * connection,DBusMessage * msg,const FXdouble data) {
836 FXuint serial;
837 DBusMessage * reply = dbus_message_new_method_return(msg);
838 if (reply) {
839 DBusMessageIter iter;
840 dbus_message_iter_init_append(reply,&iter);
841 gm_dbus_variant_append_double(&iter,data);
842 dbus_connection_send(connection,reply,&serial);
843 dbus_message_unref(reply);
844 }
845 return DBUS_HANDLER_RESULT_HANDLED;
846 }
847
848
849
gm_dbus_reply_string(DBusConnection * connection,DBusMessage * msg,const FXchar * data)850 DBusHandlerResult gm_dbus_reply_string(DBusConnection * connection,DBusMessage * msg,const FXchar * data) {
851 FXuint serial;
852 DBusMessage * reply = dbus_message_new_method_return(msg);
853 if (reply) {
854 dbus_message_append_args(reply,DBUS_TYPE_STRING,&data,DBUS_TYPE_INVALID);
855 dbus_connection_send(connection,reply,&serial);
856 dbus_message_unref(reply);
857 }
858 return DBUS_HANDLER_RESULT_HANDLED;
859 }
860
gm_dbus_reply_uint_string(DBusConnection * connection,DBusMessage * msg,const FXuint val,const FXchar * data)861 DBusHandlerResult gm_dbus_reply_uint_string(DBusConnection * connection,DBusMessage * msg,const FXuint val,const FXchar * data) {
862 FXuint serial;
863 DBusMessage * reply = dbus_message_new_method_return(msg);
864 if (reply) {
865 dbus_message_append_args(reply,DBUS_TYPE_UINT32,&val,DBUS_TYPE_STRING,&data,DBUS_TYPE_INVALID);
866 dbus_connection_send(connection,reply,&serial);
867 dbus_message_unref(reply);
868 }
869 return DBUS_HANDLER_RESULT_HANDLED;
870 }
871
gm_dbus_reply_int(DBusConnection * connection,DBusMessage * msg,const FXint data)872 DBusHandlerResult gm_dbus_reply_int(DBusConnection * connection,DBusMessage * msg,const FXint data) {
873 FXuint serial;
874 DBusMessage * reply = dbus_message_new_method_return(msg);
875 if (reply) {
876 dbus_message_append_args(reply,DBUS_TYPE_INT32,&data,DBUS_TYPE_INVALID);
877 dbus_connection_send(connection,reply,&serial);
878 dbus_message_unref(reply);
879 }
880 return DBUS_HANDLER_RESULT_HANDLED;
881 }
882
gm_dbus_reply_double(DBusConnection * connection,DBusMessage * msg,const FXdouble data)883 DBusHandlerResult gm_dbus_reply_double(DBusConnection * connection,DBusMessage * msg,const FXdouble data) {
884 FXuint serial;
885 DBusMessage * reply = dbus_message_new_method_return(msg);
886 if (reply) {
887 dbus_message_append_args(reply,DBUS_TYPE_DOUBLE,&data,DBUS_TYPE_INVALID);
888 dbus_connection_send(connection,reply,&serial);
889 dbus_message_unref(reply);
890 }
891 return DBUS_HANDLER_RESULT_HANDLED;
892 }
893
gm_dbus_reply_long(DBusConnection * connection,DBusMessage * msg,const FXlong data)894 DBusHandlerResult gm_dbus_reply_long(DBusConnection * connection,DBusMessage * msg,const FXlong data) {
895 FXuint serial;
896 DBusMessage * reply = dbus_message_new_method_return(msg);
897 if (reply) {
898 dbus_message_append_args(reply,DBUS_TYPE_INT64,&data,DBUS_TYPE_INVALID);
899 dbus_connection_send(connection,reply,&serial);
900 dbus_message_unref(reply);
901 }
902 return DBUS_HANDLER_RESULT_HANDLED;
903 }
904
gm_dbus_reply_unsigned_int(DBusConnection * connection,DBusMessage * msg,const FXuint data)905 DBusHandlerResult gm_dbus_reply_unsigned_int(DBusConnection * connection,DBusMessage * msg,const FXuint data) {
906 FXuint serial;
907 DBusMessage * reply = dbus_message_new_method_return(msg);
908 if (reply) {
909 dbus_message_append_args(reply,DBUS_TYPE_UINT32,&data,DBUS_TYPE_INVALID);
910 dbus_connection_send(connection,reply,&serial);
911 dbus_message_unref(reply);
912 }
913 return DBUS_HANDLER_RESULT_HANDLED;
914 }
915
gm_dbus_reply_bool(DBusConnection * connection,DBusMessage * msg,const dbus_bool_t data)916 DBusHandlerResult gm_dbus_reply_bool(DBusConnection * connection,DBusMessage * msg,const dbus_bool_t data) {
917 FXuint serial;
918 DBusMessage * reply = dbus_message_new_method_return(msg);
919 if (reply) {
920 dbus_message_append_args(reply,DBUS_TYPE_BOOLEAN,&data,DBUS_TYPE_INVALID);
921 dbus_connection_send(connection,reply,&serial);
922 dbus_message_unref(reply);
923 }
924 return DBUS_HANDLER_RESULT_HANDLED;
925 }
926
gm_dbus_reply_string_list(DBusConnection * connection,DBusMessage * msg,const FXchar * data[])927 DBusHandlerResult gm_dbus_reply_string_list(DBusConnection * connection,DBusMessage * msg,const FXchar * data[]) {
928 FXuint serial;
929 DBusMessage * reply = dbus_message_new_method_return(msg);
930 if (reply) {
931 DBusMessageIter iter;
932 DBusMessageIter array;
933 dbus_message_iter_init_append(reply,&iter);
934 dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,DBUS_TYPE_STRING_AS_STRING,&array);
935 for (FXint n=0;data[n];n++) {
936 dbus_message_iter_append_basic(&array,DBUS_TYPE_STRING,&data[n]);
937 }
938 dbus_message_iter_close_container(&iter,&array);
939 dbus_connection_send(connection,reply,&serial);
940 dbus_message_unref(reply);
941 }
942 return DBUS_HANDLER_RESULT_HANDLED;
943 }
944
945
946
947
gm_dbus_reply_if_needed(DBusConnection * connection,DBusMessage * msg)948 DBusHandlerResult gm_dbus_reply_if_needed(DBusConnection * connection,DBusMessage * msg) {
949 if (!dbus_message_get_no_reply(msg)) {
950 FXuint serial;
951 DBusMessage * reply = dbus_message_new_method_return(msg);
952 if (reply) {
953 dbus_connection_send(connection,reply,&serial);
954 dbus_message_unref(reply);
955 }
956 }
957 return DBUS_HANDLER_RESULT_HANDLED;
958 }
959
gm_dbus_match_signal(DBusConnection * connection,const FXchar * path,const FXchar * interface,const FXchar * member)960 void gm_dbus_match_signal(DBusConnection*connection,const FXchar * path,const FXchar * interface,const FXchar * member){
961 FXString rule = FXString::value("type='signal',path='%s',interface='%s',member='%s'",path,interface,member);
962 dbus_bus_add_match(connection,rule.text(),nullptr);
963 }
964