1 /********************************************************************************
2 *                                                                               *
3 *                        F O X  D B U S  S U P P O R T                          *
4 *                                                                               *
5 *********************************************************************************
6 * Copyright (C) 2007-2021 by Sander Jansen. All Rights Reserved.                *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or                 *
9 * modify it under the terms of the GNU Lesser General Public                    *
10 * License as published by the Free Software Foundation; either                  *
11 * version 2.1 of the License, or (at your option) any later version.            *
12 *                                                                               *
13 * This library is distributed in the hope that it will be useful,               *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU             *
16 * Lesser General Public License for more details.                               *
17 *                                                                               *
18 * You should have received a copy of the GNU Lesser General Public              *
19 * License along with this library; if not, write to the Free Software           *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.    *
21 ********************************************************************************/
22 #ifndef GMDBUS_H
23 #define GMDBUS_H
24 
25 #ifndef DBUS_BUS_H
26 #include <dbus/dbus.h>
27 #endif
28 
29 /**
30 * GMDBus is a thin wrapper of DBusConnection with the purpose of integrating it
31 * into the FOX event loop (1.6), so that activity on DBus will be properly handled.
32 * DBusConnections may only be managed by one GMDBus. The APIs are strictly enforcing this
33 * by keeping a global (threadsafe) map of GMDBus/DBusConnection references.
34 **
35 * In the future I hope to support the new FXReactor framework in FOX.
36 *
37 */
38 
39 class GMDBusManager;
40 
41 class GMDBus : public FXObject {
42 FXDECLARE(GMDBus)
43 private:
44   DBusConnection * dc = nullptr;
45 private:
46   GMDBus(const GMDBus &);
47   GMDBus &operator=(const GMDBus&);
48 public:
49   enum {
50     ID_HANDLE = 1,
51     ID_DISPATCH,
52     ID_LAST,
53     };
54 public:
55   long onHandleRead(FXObject*,FXSelector,void*);
56   long onHandleWrite(FXObject*,FXSelector,void*);
57   long onHandleExcept(FXObject*,FXSelector,void*);
58   long onDispatch(FXObject*,FXSelector,void*);
59 public:
60   /**
61   *  Construct non active Dbus Connection Hook
62   */
63   GMDBus();
64 
65   /**
66   *  Open Standard Bus
67   *  return false if already managed by other FXDBusConnection
68   */
69   FXbool open(DBusBusType bustype=DBUS_BUS_SESSION);
70 
71   /**
72   * Return FXDBusConnection for given DBusConnection. Return nullptr if not found.
73   */
74   static GMDBus * find(DBusConnection * dc);
75 
76   /**
77   * Init the event loop for all connections
78   */
79   static void initEventLoop();
80 
81  /**
82   * Return DBUS version
83   */
84   static FXString dbusversion();
85 
86   /**
87   * Setup Callback Hooks
88   */
89   virtual void setup_event_loop();
90 
91   /**
92   * Return DBusConnection
93   */
connection()94   DBusConnection * connection() const { return dc; }
95 
96   /**
97   * Returns whether we're connected or not
98   */
99   FXbool connected() const;
100 
101   /**
102   * Returns whether we're  authenticated
103   */
104   FXbool authenticated() const;
105 
106 
107   /**
108   * Flush
109   */
110   void flush();
111 
112   /**
113   * Send with Reply
114   */
115   FXbool sendWithReply(DBusMessage * msg,FXint timeout,FXObject*,FXSelector);
116 
117   /**
118   * Send
119   */
120   void send(DBusMessage * msg,FXuint & serial);
121   void send(DBusMessage * msg);
122 
123   /**
124   * Destructor. Existing DBusConnection will be unreffed.
125   */
126   virtual ~GMDBus();
127   };
128 
129 
130 /* A Remote Object */
131 class GMDBusProxy : public FXObject {
132 FXDECLARE(GMDBusProxy)
133 protected:
134   GMDBus           * bus        = nullptr;  /// Bus
135   FXString           name;                  /// Name
136   FXString           path;                  /// Path
137   FXString           interface;             /// Interface
138 protected:
139   FXbool             associated = false;    /// Are we associated
140   FXObject         * target     = nullptr;  /// Target object
141   FXSelector         message    = 0;        /// Message ID
142 protected:
143   FXHash             serial;
144 protected:
145   GMDBusProxy();
146 private:
147   GMDBusProxy(const GMDBusProxy&);
148   GMDBusProxy& operator=(const GMDBusProxy&);
149 public:
150   long onCreate(FXObject*,FXSelector,void*);
151   long onDestroy(FXObject*,FXSelector,void*);
152   long onReplaced(FXObject*,FXSelector,void*);
153   long onMethod(FXObject*,FXSelector,void*);
154   long onSignal(FXObject*,FXSelector,void*);
155 public:
156   GMDBusProxy(GMDBus*,const FXchar * name,const FXchar * path,const FXchar * interface);
157 
getPath()158   FXString getPath() const { return path; }
159 
getName()160   FXString getName() const { return name; }
161 
getInterface()162   FXString getInterface() const { return interface; }
163 
164   FXbool matchSerial(DBusMessage * msg);
165 
166   DBusMessage * method(const FXchar * method);
167 
168   DBusMessage * signal(const FXchar * name);
169 
170   void send(DBusMessage*,FXObject*,FXSelector);
171 
172   virtual ~GMDBusProxy();
173   };
174 
175 
176 
177 #define DEBUG_DBUS_MESSAGE(msg) { \
178     FXTRACE((80,"-----%s-------\n",__func__)); \
179     FXTRACE((80,"type: %s\n",dbus_message_type_to_string(dbus_message_get_type(msg))));\
180     FXTRACE((80,"path: %s\n",dbus_message_get_path(msg))); \
181     FXTRACE((80,"member: \"%s\"\n",dbus_message_get_member(msg))); \
182     FXTRACE((80,"interface: %s\n",dbus_message_get_interface(msg))); \
183     FXTRACE((80,"sender: %s\n",dbus_message_get_sender(msg))); \
184     FXTRACE((80,"signature: %s\n",dbus_message_get_signature(msg))); }
185 
186 /* Some Helper Functions */
187 extern void gm_dbus_variant_append_basic(DBusMessageIter * iter,const FXchar * element_string,FXint element,const void * value);
188 extern void gm_dbus_variant_append_string(DBusMessageIter * iter,const FXchar * value);
189 extern void gm_dbus_variant_append_path(DBusMessageIter * iter,const FXchar * value);
190 extern void gm_dbus_variant_append_int32(DBusMessageIter * iter,const FXint value);
191 extern void gm_dbus_variant_append_uint32(DBusMessageIter * iter,const FXuint value);
192 extern void gm_dbus_variant_append_bool(DBusMessageIter * iter,const dbus_bool_t value);
193 extern void gm_dbus_variant_append_double(DBusMessageIter * iter,const FXdouble value);
194 extern void gm_dbus_variant_append_long(DBusMessageIter * iter,const FXlong value);
195 extern void gm_dbus_variant_append_string_list(DBusMessageIter * iter,const FXchar * data[]);
196 extern void gm_dbus_variant_append_string_list(DBusMessageIter * iter,const FXStringList&);
197 
198 extern void gm_dbus_append_string(DBusMessageIter *iter,const FXString & value);
199 extern void gm_dbus_append_string_pair(DBusMessageIter *iter,const FXchar * key,const FXchar * value);
200 
201 extern void gm_dbus_dict_append_int32(DBusMessageIter * dict,const FXchar * key,const FXint value);
202 extern void gm_dbus_dict_append_uint32(DBusMessageIter * dict,const FXchar * key,const FXuint value);
203 extern void gm_dbus_dict_append_string(DBusMessageIter * dict,const FXchar * key,const FXchar * value);
204 extern void gm_dbus_dict_append_string(DBusMessageIter * dict,const FXchar * key,const FXString & value);
205 extern void gm_dbus_dict_append_double(DBusMessageIter * dict,const FXchar * key,const FXdouble & value);
206 extern void gm_dbus_dict_append_long(DBusMessageIter * dict,const FXchar * key,const FXlong & value);
207 extern void gm_dbus_dict_append_path(DBusMessageIter * dict,const FXchar * key,const FXchar * value);
208 extern void gm_dbus_dict_append_bool(DBusMessageIter * dict,const FXchar * key,const dbus_bool_t value);
209 extern void gm_dbus_dict_append_string_list(DBusMessageIter * dict,const FXchar * key,const FXchar * data[]);
210 extern void gm_dbus_dict_append_string_list(DBusMessageIter * dict,const FXchar * key,const FXStringList &);
211 
212 
213 extern DBusHandlerResult gm_dbus_property_string(DBusConnection*,DBusMessage*,const FXchar * xml);
214 extern DBusHandlerResult gm_dbus_property_string_list(DBusConnection*,DBusMessage *,const FXchar * data[]);
215 extern DBusHandlerResult gm_dbus_property_bool(DBusConnection*,DBusMessage*,const dbus_bool_t);
216 extern DBusHandlerResult gm_dbus_property_double(DBusConnection*,DBusMessage*,const FXdouble);
217 extern DBusHandlerResult gm_dbus_property_long(DBusConnection*,DBusMessage*,const FXlong);
218 
219 
220 extern DBusHandlerResult gm_dbus_reply_string(DBusConnection * connection,DBusMessage * msg,const FXchar * xml);
221 extern DBusHandlerResult gm_dbus_reply_uint_string(DBusConnection * connection,DBusMessage * msg,const FXuint val,const FXchar * xml);
222 extern DBusHandlerResult gm_dbus_reply_int(DBusConnection * connection,DBusMessage * msg,const FXint value);
223 extern DBusHandlerResult gm_dbus_reply_double(DBusConnection * connection,DBusMessage * msg,const FXdouble value);
224 extern DBusHandlerResult gm_dbus_reply_unsigned_int(DBusConnection * connection,DBusMessage * msg,const FXuint value);
225 extern DBusHandlerResult gm_dbus_reply_long(DBusConnection * connection,DBusMessage * msg,const FXlong value);
226 extern DBusHandlerResult gm_dbus_reply_if_needed(DBusConnection * connection,DBusMessage * msg);
227 extern DBusHandlerResult gm_dbus_reply_bool(DBusConnection*connection,DBusMessage*msg,const dbus_bool_t);
228 extern DBusHandlerResult gm_dbus_reply_string_list(DBusConnection * connection,DBusMessage * msg,const FXchar * data[]);
229 
230 extern void gm_dbus_match_signal(DBusConnection*,const FXchar * path,const FXchar * interface,const FXchar * member);
231 
232 #endif
233 
234 
235 
236