Default STEP export to board only
[geda-pcb/pcjc2/v2.git] / src / dbus-pcbmain.c
blob649e377004d5bb5e38e78950f8249686ea55bfc6
1 /* -*- mode: C; c-file-style: "gnu" -*- */
3 /*!
4 * \file src/dbus-pcbmain.c
6 * \brief PCB HID main loop integration.
8 * Adapted from dbus-gmain.c from dbus-glib bindings:
10 * Copyright (C) 2002, 2003 CodeFactory AB
12 * Copyright (C) 2005 Red Hat, Inc.
14 * Licensed under the Academic Free License version 2.1
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
36 #define DBUS_API_SUBJECT_TO_CHANGE
37 #include <dbus/dbus.h>
38 #include <stdio.h>
40 #include "global.h"
41 #include "dbus-pcbmain.h"
43 typedef struct _IOWatchHandler IOWatchHandler;
44 typedef struct _TimeoutHandler TimeoutHandler;
46 struct _IOWatchHandler
48 DBusWatch *dbus_watch;
49 hidval pcb_watch;
52 struct _TimeoutHandler
54 DBusTimeout *dbus_timeout;
55 hidval pcb_timer;
56 int interval;
60 static void
61 block_hook_cb (hidval data)
63 DBusConnection *connection = (DBusConnection *) data.ptr;
64 if (dbus_connection_get_dispatch_status (connection) !=
65 DBUS_DISPATCH_DATA_REMAINS)
66 return;
68 // TODO: IS THIS NEEDED?
69 // dbus_connection_ref (connection);
71 /* Only dispatch once - we don't want to starve other mainloop users */
72 dbus_connection_dispatch (connection);
74 // dbus_connection_unref (connection);
75 return;
78 static void
79 io_watch_handler_dbus_freed (void *data)
81 IOWatchHandler *handler;
82 handler = (IOWatchHandler *)data;
84 // Remove the watch registered with the HID
85 gui->unwatch_file (handler->pcb_watch);
86 free (handler);
90 void
91 io_watch_handler_cb (hidval pcb_watch,
92 int fd, unsigned int condition, hidval data)
94 IOWatchHandler *handler;
95 unsigned int dbus_condition = 0;
97 handler = (IOWatchHandler *) data.ptr;
99 // TODO: IS THIS NEEDED?
100 //if (connection)
101 // dbus_connection_ref (connection);
103 if (condition & PCB_WATCH_READABLE)
104 dbus_condition |= DBUS_WATCH_READABLE;
105 if (condition & PCB_WATCH_WRITABLE)
106 dbus_condition |= DBUS_WATCH_WRITABLE;
107 if (condition & PCB_WATCH_ERROR)
108 dbus_condition |= DBUS_WATCH_ERROR;
109 if (condition & PCB_WATCH_HANGUP)
110 dbus_condition |= DBUS_WATCH_HANGUP;
112 /* We don't touch the handler after this, because DBus
113 * may have disabled the watch and thus killed the handler
115 dbus_watch_handle (handler->dbus_watch, dbus_condition);
116 handler = NULL;
118 //if (connection)
119 // dbus_connection_unref (connection);
121 return;
125 static void
126 timeout_handler_dbus_freed (void *data)
128 TimeoutHandler *handler;
129 handler = (TimeoutHandler *)data;
131 // Remove the timeout registered with the HID
132 gui->stop_timer (handler->pcb_timer);
133 free (handler);
137 void
138 timeout_handler_cb (hidval data)
140 TimeoutHandler *handler;
141 handler = (TimeoutHandler *)data.ptr;
143 // Re-add the timeout, as PCB will remove the current one
144 // Do this before calling to dbus, incase DBus removes the timeout.
145 // We can't touch handler after libdbus has been run for this reason.
146 handler->pcb_timer =
147 gui->add_timer (timeout_handler_cb, handler->interval, data);
149 dbus_timeout_handle (handler->dbus_timeout);
153 static dbus_bool_t
154 watch_add (DBusWatch * dbus_watch, void *data)
156 IOWatchHandler *handler;
157 int fd;
158 unsigned int pcb_condition;
159 unsigned int dbus_flags;
160 hidval temp;
162 // We won't create a watch until it becomes enabled.
163 if (!dbus_watch_get_enabled (dbus_watch))
164 return TRUE;
166 dbus_flags = dbus_watch_get_flags (dbus_watch);
168 pcb_condition = PCB_WATCH_ERROR | PCB_WATCH_HANGUP;
169 if (dbus_flags & DBUS_WATCH_READABLE)
170 pcb_condition |= PCB_WATCH_READABLE;
171 if (dbus_flags & DBUS_WATCH_WRITABLE)
172 pcb_condition |= PCB_WATCH_READABLE;
174 #if HAVE_DBUS_WATCH_GET_UNIX_FD
175 fd = dbus_watch_get_unix_fd (dbus_watch);
176 #else
177 fd = dbus_watch_get_fd (dbus_watch);
178 #endif
180 handler = (IOWatchHandler *)malloc (sizeof (IOWatchHandler));
181 temp.ptr = (void *)handler;
182 handler->dbus_watch = dbus_watch;
183 handler->pcb_watch =
184 gui->watch_file (fd, pcb_condition, io_watch_handler_cb, temp);
186 dbus_watch_set_data (dbus_watch, handler, io_watch_handler_dbus_freed);
187 return TRUE;
190 static void
191 watch_remove (DBusWatch * dbus_watch, void *data)
193 // Free the associated data. Its destroy callback removes the watch
194 dbus_watch_set_data (dbus_watch, NULL, NULL);
197 static void
198 watch_toggled (DBusWatch * dbus_watch, void *data)
200 /* Simply add/remove the watch completely */
201 if (dbus_watch_get_enabled (dbus_watch))
202 watch_add (dbus_watch, data);
203 else
204 watch_remove (dbus_watch, data);
208 static dbus_bool_t
209 timeout_add (DBusTimeout * timeout, void *data)
211 TimeoutHandler *handler;
212 hidval temp;
214 // We won't create a timeout until it becomes enabled.
215 if (!dbus_timeout_get_enabled (timeout))
216 return TRUE;
218 //FIXME: Need to store the interval, as PCB requires us
219 // to manually re-add the timer each time it expires.
220 // This is non-ideal, and hopefully can be changed?
222 handler = (TimeoutHandler *)malloc (sizeof (TimeoutHandler));
223 temp.ptr = (void *)handler;
224 handler->dbus_timeout = timeout;
225 handler->interval = dbus_timeout_get_interval (timeout);
226 handler->pcb_timer =
227 gui->add_timer (timeout_handler_cb, handler->interval, temp);
229 dbus_timeout_set_data (timeout, handler, timeout_handler_dbus_freed);
230 return TRUE;
233 static void
234 timeout_remove (DBusTimeout * timeout, void *data)
236 // Free the associated data. Its destroy callback removes the timer
237 dbus_timeout_set_data (timeout, NULL, NULL);
240 static void
241 timeout_toggled (DBusTimeout * timeout, void *data)
243 /* Simply add/remove the timeout completely */
244 if (dbus_timeout_get_enabled (timeout))
245 timeout_add (timeout, data);
246 else
247 timeout_remove (timeout, data);
250 void
251 dispatch_status_changed (DBusConnection * conn, DBusDispatchStatus new_status,
252 void *data)
254 // TODO: Can use this eventually to add one-shot idle work-functions to dispatch
255 // remaining IO. It could possibly replace the block_hook polling mechanism.
256 // (We could use a one-shot block_book to dispatch the work though.)
258 // *** NO DISPATCHING TO BE DONE INSIDE THIS FUNCTION ***
261 // END INTERNALS
265 * Sets the watch and timeout functions of a #DBusConnection
266 * to integrate the connection with the GUI HID's main loop.
268 * @param connection the connection
270 void
271 pcb_dbus_connection_setup_with_mainloop (DBusConnection * connection)
273 //ConnectionSetup *cs;
274 hidval temp;
276 /* FIXME we never free the slot, so its refcount just keeps growing,
277 * which is kind of broken.
279 //dbus_connection_allocate_data_slot (&connection_slot);
280 //if (connection_slot < 0)
281 // goto nomem;
283 #if 0
284 cs = connection_setup_new (connection);
286 if (!dbus_connection_set_data (connection, connection_slot, cs,
287 (DBusFreeFunction) connection_setup_free))
288 goto nomem;
289 #endif
291 if (!dbus_connection_set_watch_functions (connection,
292 watch_add,
293 watch_remove,
294 watch_toggled, NULL, NULL))
295 // cs, NULL))
296 goto nomem;
298 if (!dbus_connection_set_timeout_functions (connection,
299 timeout_add,
300 timeout_remove,
301 timeout_toggled, NULL, NULL))
302 // cs, NULL))
303 goto nomem;
305 dbus_connection_set_dispatch_status_function (connection,
306 dispatch_status_changed,
307 NULL, NULL);
308 // cs, NULL);
310 /* Register a new mainloop hook to mop up any unfinished IO. */
311 temp.ptr = (void *)connection;
312 gui->add_block_hook (block_hook_cb, temp);
314 return;
315 nomem:
316 fprintf (stderr,
317 "Not enough memory to set up DBusConnection for use with PCB\n");
320 void
321 pcb_dbus_connection_finish_with_mainloop (DBusConnection * connection)
323 //ConnectionSetup *cs;
325 //cs = dbus_connection_get_data (connection, connection_slot );
327 // Replace the stored data with NULL, thus freeing the old data
328 // DBus will call the function connection_setup_free() which we registered earlier
329 //dbus_connection_set_data (connection, connection_slot, NULL, NULL );
331 //dbus_connection_free_data_slot( &connection_slot );
333 if (!dbus_connection_set_watch_functions (connection,
334 NULL, NULL, NULL, NULL, NULL))
335 goto nomem;
337 if (!dbus_connection_set_timeout_functions (connection,
338 NULL, NULL, NULL, NULL, NULL))
339 goto nomem;
341 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
342 return;
343 nomem:
344 fprintf (stderr,
345 "Not enough memory when cleaning up DBusConnection mainloop integration\n");