2 * PCB, an interactive printed circuit board editor
4 * Copyright (C) 2006 University of Cambridge
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 2 of the License, or
9 * (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * D-Bus code originally derrived from example-service.c in the dbus-glib bindings
25 #define DBUS_API_SUBJECT_TO_CHANGE
26 #include <dbus/dbus.h>
30 #include "dbus-pcbmain.h"
31 #include "dbus-introspect.h"
36 #include "lrealpath.h"
39 #define PCB_DBUS_CANONICAL_NAME "org.seul.geda.pcb"
40 #define PCB_DBUS_OBJECT_PATH "/org/seul/geda/pcb"
41 #define PCB_DBUS_INTERFACE "org.seul.geda.pcb"
42 #define PCB_DBUS_ACTIONS_INTERFACE "org.seul.geda.pcb.actions"
44 static DBusConnection
*pcb_dbus_conn
;
47 static DBusHandlerResult
48 handle_get_filename (DBusConnection
* connection
, DBusMessage
* message
,
53 DBusHandlerResult result
;
56 result
= DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
58 // TODO: Should check the message signature matches what we expect?
60 reply
= dbus_message_new_method_return (message
);
63 fprintf (stderr
, "pcb_dbus: Couldn't create reply message\n");
66 dbus_message_iter_init_append (reply
, &iter
);
69 filename
= lrealpath (PCB
->Filename
);
77 "pcb_dbus: DEBUG: Couldn't get working filename, assuming none\n");
79 filename
= strdup ("");
83 "pcb_dbus: Couldn't strdup( \"\" ) for the filename\n");
87 if (!dbus_message_iter_append_basic (&iter
, DBUS_TYPE_STRING
, &filename
))
90 "pcb_dbus: Couldn't append return filename string to message reply, Out Of Memory!\n");
95 if (!dbus_connection_send (connection
, reply
, NULL
))
97 fprintf (stderr
, "pcb_dbus: Couldn't send message, Out Of Memory!\n");
100 result
= DBUS_HANDLER_RESULT_HANDLED
;
103 dbus_message_unref (reply
);
108 static DBusHandlerResult
109 handle_exec_action (DBusConnection
* connection
, DBusMessage
* message
,
113 DBusMessageIter iter
;
114 DBusHandlerResult result
;
116 dbus_uint32_t retval
;
124 result
= DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
126 // TODO: Should check the message signature matches what we expect?
128 // initialise the error struct
129 dbus_error_init (&err
);
131 /* DON'T FREE action_name, as it belongs to DBUS,
132 * DO FREE argv, using dbus_free_string_array()
135 if (!dbus_message_get_args (message
,
137 DBUS_TYPE_STRING
, &action_name
,
138 DBUS_TYPE_ARRAY
, DBUS_TYPE_STRING
, &argv
, &argc
,
141 fprintf (stderr
, "Failed to read method arguments\n");
143 dbus_free_string_array (argv
);
148 fprintf (stderr
, "pcb_dbus: DEBUG: Executing action: %s(", action_name
);
150 fprintf (stderr
, " \"%s\"", argv
[0]);
151 for (i
= 1; i
< argc
; i
++)
152 fprintf (stderr
, ", \"%s\"", argv
[i
]);
153 fprintf (stderr
, " )\n");
156 // TODO: Proper return value from actions
157 hid_actionv (action_name
, argc
, argv
);
160 dbus_free_string_array (argv
);
162 reply
= dbus_message_new_method_return (message
);
165 fprintf (stderr
, "pcb_dbus: Couldn't create reply message\n");
168 dbus_message_iter_init_append (reply
, &iter
);
169 if (!dbus_message_iter_append_basic (&iter
, DBUS_TYPE_UINT32
, &retval
))
171 fprintf (stderr
, "pcb_dbus: Couldn't sent message, Out Of Memory!\n");
175 if (!dbus_connection_send (connection
, reply
, NULL
))
177 fprintf (stderr
, "pcb_dbus: Couldn't send message, Out Of Memory!\n");
181 result
= DBUS_HANDLER_RESULT_HANDLED
;
183 dbus_message_unref (reply
);
188 static DBusHandlerResult
189 handle_introspect (DBusConnection
* connection
, DBusMessage
* message
,
193 DBusMessageIter iter
;
194 DBusHandlerResult result
;
196 result
= DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
197 reply
= dbus_message_new_method_return (message
);
200 fprintf (stderr
, "pcb_dbus: Couldn't create reply message\n");
203 dbus_message_iter_init_append (reply
, &iter
);
204 if (!dbus_message_iter_append_basic
205 (&iter
, DBUS_TYPE_STRING
, &pcb_dbus_introspect_xml
))
208 "pcb_dbus: Couldn't add introspect XML to message return\n");
211 if (!dbus_connection_send (pcb_dbus_conn
, reply
, NULL
))
214 "pcb_dbus: Couldn't queue reply message for sending\n");
217 result
= DBUS_HANDLER_RESULT_HANDLED
;
219 dbus_message_unref (reply
);
224 unregister_dbus_handler (DBusConnection
* connection
, void *data
)
229 static DBusHandlerResult
230 handle_dbus_message (DBusConnection
* connection
, DBusMessage
* message
,
234 msg_type
= dbus_message_get_type (message
);
238 case DBUS_MESSAGE_TYPE_METHOD_CALL
:
240 const char *method_name
;
241 const char *interface_name
;
243 method_name
= dbus_message_get_member (message
);
244 if (method_name
== NULL
)
246 fprintf (stderr
, "pcb_dbus: Method had no name specified\n");
250 interface_name
= dbus_message_get_interface (message
);
251 if (interface_name
== NULL
)
253 fprintf (stderr
, "pcb_dbus: Method had no interface specified\n");
257 if (strcmp (interface_name
, PCB_DBUS_INTERFACE
) == 0)
259 if (strcmp (method_name
, "GetFilename") == 0)
261 return handle_get_filename (connection
, message
, data
);
263 fprintf (stderr
, "pcb_dbus: Interface '%s' has no method '%s'\n",
264 interface_name
, method_name
);
267 else if (strcmp (interface_name
, PCB_DBUS_ACTIONS_INTERFACE
) == 0)
269 if (strcmp (method_name
, "ExecAction") == 0)
271 return handle_exec_action (connection
, message
, data
);
273 fprintf (stderr
, "pcb_dbus: Interface '%s' has no method '%s'\n",
274 interface_name
, method_name
);
277 else if (strcmp (interface_name
, DBUS_INTERFACE_INTROSPECTABLE
) == 0)
279 if (strcmp (method_name
, "Introspect") == 0)
281 return handle_introspect (connection
, message
, data
);
283 fprintf (stderr
, "pcb_dbus: Interface '%s' has no method '%s'\n",
284 interface_name
, method_name
);
289 fprintf (stderr
, "pcb_dbus: Interface '%s' was not recognised\n",
296 case DBUS_MESSAGE_TYPE_METHOD_RETURN
:
297 fprintf (stderr
, "pcb_dbus: DBUG: Method return message\n");
298 // WON'T ACTUALLY BE ANY UNLESS WE MAKE AN ASYNCRONOUS CALL?
301 case DBUS_MESSAGE_TYPE_ERROR
:
302 fprintf (stderr
, "pcb_dbus: DEBUG: Error message\n");
306 case DBUS_MESSAGE_TYPE_SIGNAL
:
307 fprintf (stderr
, "pcb_dbus: DEBUG: Signal message\n");
313 "pcb_dbus: DEBUG: Message type wasn't one we know about!\n");
314 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
317 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
322 pcb_dbus_setup (void)
326 const DBusObjectPathVTable object_vtable
= {
327 unregister_dbus_handler
,
329 NULL
, NULL
, NULL
, NULL
332 // Initialise the error variable
333 dbus_error_init (&err
);
335 // Connect to the bus
336 pcb_dbus_conn
= dbus_bus_get_private (DBUS_BUS_SESSION
, &err
);
337 if (dbus_error_is_set (&err
))
339 fprintf (stderr
, "pcb_dbus: DBus connection Error (%s)\n", err
.message
);
340 dbus_error_free (&err
);
342 if (pcb_dbus_conn
== NULL
)
345 // Request the canonical name for PCB on the bus
346 ret
= dbus_bus_request_name (pcb_dbus_conn
, PCB_DBUS_CANONICAL_NAME
,
347 DBUS_NAME_FLAG_REPLACE_EXISTING
, &err
);
348 if (dbus_error_is_set (&err
))
350 fprintf (stderr
, "pcb_dbus: DBus name error (%s)\n", err
.message
);
351 dbus_error_free (&err
);
353 if (ret
!= DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
354 && ret
!= DBUS_REQUEST_NAME_REPLY_IN_QUEUE
)
357 "pcb_dbus: Couldn't gain ownership or queued ownership of the canonical DBus name\n");
361 if (!dbus_connection_register_object_path (pcb_dbus_conn
, PCB_DBUS_OBJECT_PATH
, &object_vtable
, NULL
// void * user_data
364 fprintf (stderr
, "pcb_dbus: Couldn't register DBUS handler for %s\n",
365 PCB_DBUS_OBJECT_PATH
);
369 // Setup intergration with the pcb mainloop
370 pcb_dbus_connection_setup_with_mainloop (pcb_dbus_conn
);
372 // dbus_error_free(&err);
378 pcb_dbus_finish (void)
382 // Initialise the error variable
383 dbus_error_init (&err
);
385 // TODO: Could emit a "goodbye" signal here?
387 dbus_connection_flush (pcb_dbus_conn
);
389 dbus_connection_unregister_object_path (pcb_dbus_conn
,
390 PCB_DBUS_OBJECT_PATH
);
392 dbus_bus_release_name (pcb_dbus_conn
, PCB_DBUS_CANONICAL_NAME
, &err
);
394 dbus_error_free (&err
);
396 pcb_dbus_connection_finish_with_mainloop (pcb_dbus_conn
);
398 dbus_connection_close (pcb_dbus_conn
);
399 dbus_connection_unref (pcb_dbus_conn
);
401 // Call DBus shutdown. This doesn't work with shared connections,
402 // only private ones (like we took out earlier).
403 // If any future module / plugin to PCB wants to use DBus too,
404 // we must remove this call. DBus will get shut-down when the app exits.