Introduce POLYGONHOLE_MODE for creating holes in polygons
[geda-pcb/gde.git] / src / dbus.c
blobb3bb0076d295ed516b6574bf2f1b3cb7f7b831db
1 /*
2 * PCB, an interactive printed circuit board editor
3 * D-Bus IPC logic
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>
27 #include <string.h>
29 #include "dbus.h"
30 #include "dbus-pcbmain.h"
31 #include "dbus-introspect.h"
32 #include "global.h"
33 #include "data.h"
35 /* For lrealpath */
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,
49 void *data)
51 DBusMessage *reply;
52 DBusMessageIter iter;
53 DBusHandlerResult result;
54 char *filename;
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);
61 if (reply == NULL)
63 fprintf (stderr, "pcb_dbus: Couldn't create reply message\n");
64 return result;
66 dbus_message_iter_init_append (reply, &iter);
68 if (PCB->Filename)
69 filename = lrealpath (PCB->Filename);
70 else
71 filename = NULL;
73 if (filename == NULL)
75 #ifdef DEBUG
76 fprintf (stderr,
77 "pcb_dbus: DEBUG: Couldn't get working filename, assuming none\n");
78 #endif
79 filename = strdup ("");
80 if (filename == NULL)
82 fprintf (stderr,
83 "pcb_dbus: Couldn't strdup( \"\" ) for the filename\n");
84 goto out;
87 if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &filename))
89 fprintf (stderr,
90 "pcb_dbus: Couldn't append return filename string to message reply, Out Of Memory!\n");
91 free (filename);
92 goto out;
94 free (filename);
95 if (!dbus_connection_send (connection, reply, NULL))
97 fprintf (stderr, "pcb_dbus: Couldn't send message, Out Of Memory!\n");
98 goto out;
100 result = DBUS_HANDLER_RESULT_HANDLED;
102 out:
103 dbus_message_unref (reply);
104 return result;
108 static DBusHandlerResult
109 handle_exec_action (DBusConnection * connection, DBusMessage * message,
110 void *data)
112 DBusMessage *reply;
113 DBusMessageIter iter;
114 DBusHandlerResult result;
115 DBusError err;
116 dbus_uint32_t retval;
117 char *action_name;
118 char **argv;
119 int argc;
120 #ifdef DEBUG
121 int i;
122 #endif
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()
134 argv = NULL;
135 if (!dbus_message_get_args (message,
136 &err,
137 DBUS_TYPE_STRING, &action_name,
138 DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &argv, &argc,
139 DBUS_TYPE_INVALID))
141 fprintf (stderr, "Failed to read method arguments\n");
142 if (argv)
143 dbus_free_string_array (argv);
144 return result;
147 #ifdef DEBUG
148 fprintf (stderr, "pcb_dbus: DEBUG: Executing action: %s(", action_name);
149 if (argc > 0)
150 fprintf (stderr, " \"%s\"", argv[0]);
151 for (i = 1; i < argc; i++)
152 fprintf (stderr, ", \"%s\"", argv[i]);
153 fprintf (stderr, " )\n");
154 #endif
156 // TODO: Proper return value from actions
157 hid_actionv (action_name, argc, argv);
158 retval = 0;
160 dbus_free_string_array (argv);
162 reply = dbus_message_new_method_return (message);
163 if (reply == NULL)
165 fprintf (stderr, "pcb_dbus: Couldn't create reply message\n");
166 return result;
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");
172 goto out;
175 if (!dbus_connection_send (connection, reply, NULL))
177 fprintf (stderr, "pcb_dbus: Couldn't send message, Out Of Memory!\n");
178 goto out;
181 result = DBUS_HANDLER_RESULT_HANDLED;
182 out:
183 dbus_message_unref (reply);
184 return result;
188 static DBusHandlerResult
189 handle_introspect (DBusConnection * connection, DBusMessage * message,
190 void *data)
192 DBusMessage *reply;
193 DBusMessageIter iter;
194 DBusHandlerResult result;
196 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
197 reply = dbus_message_new_method_return (message);
198 if (reply == NULL)
200 fprintf (stderr, "pcb_dbus: Couldn't create reply message\n");
201 return result;
203 dbus_message_iter_init_append (reply, &iter);
204 if (!dbus_message_iter_append_basic
205 (&iter, DBUS_TYPE_STRING, &pcb_dbus_introspect_xml))
207 fprintf (stderr,
208 "pcb_dbus: Couldn't add introspect XML to message return\n");
209 goto out;
211 if (!dbus_connection_send (pcb_dbus_conn, reply, NULL))
213 fprintf (stderr,
214 "pcb_dbus: Couldn't queue reply message for sending\n");
215 goto out;
217 result = DBUS_HANDLER_RESULT_HANDLED;
218 out:
219 dbus_message_unref (reply);
220 return result;
223 static void
224 unregister_dbus_handler (DBusConnection * connection, void *data)
229 static DBusHandlerResult
230 handle_dbus_message (DBusConnection * connection, DBusMessage * message,
231 void *data)
233 int msg_type;
234 msg_type = dbus_message_get_type (message);
236 switch (msg_type)
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");
247 break;
250 interface_name = dbus_message_get_interface (message);
251 if (interface_name == NULL)
253 fprintf (stderr, "pcb_dbus: Method had no interface specified\n");
254 break;
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);
265 break;
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);
275 break;
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);
285 break;
287 else
289 fprintf (stderr, "pcb_dbus: Interface '%s' was not recognised\n",
290 interface_name);
291 break;
294 break;
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?
299 break;
301 case DBUS_MESSAGE_TYPE_ERROR:
302 fprintf (stderr, "pcb_dbus: DEBUG: Error message\n");
303 // HOPE NOT!
304 break;
306 case DBUS_MESSAGE_TYPE_SIGNAL:
307 fprintf (stderr, "pcb_dbus: DEBUG: Signal message\n");
308 // NONE AT PRESENT
309 break;
311 default:
312 fprintf (stderr,
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;
321 void
322 pcb_dbus_setup (void)
324 DBusError err;
325 int ret;
326 const DBusObjectPathVTable object_vtable = {
327 unregister_dbus_handler,
328 handle_dbus_message,
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)
343 return;
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)
356 fprintf (stderr,
357 "pcb_dbus: Couldn't gain ownership or queued ownership of the canonical DBus name\n");
358 return;
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);
366 return;
369 // Setup intergration with the pcb mainloop
370 pcb_dbus_connection_setup_with_mainloop (pcb_dbus_conn);
372 // dbus_error_free(&err);
373 return;
377 void
378 pcb_dbus_finish (void)
380 DBusError err;
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.
405 dbus_shutdown ();