pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 00028 #define DBUS_API_SUBJECT_TO_CHANGE 00029 #include <dbus/dbus.h> 00030 #include <string.h> 00031 00032 #include "dbus.h" 00033 #include "dbus-pcbmain.h" 00034 #include "dbus-introspect.h" 00035 #include "global.h" 00036 #include "data.h" 00037 00038 /* For lrealpath */ 00039 #include "lrealpath.h" 00040 00041 00042 #define PCB_DBUS_CANONICAL_NAME "org.seul.geda.pcb" 00043 #define PCB_DBUS_OBJECT_PATH "/org/seul/geda/pcb" 00044 #define PCB_DBUS_INTERFACE "org.seul.geda.pcb" 00045 #define PCB_DBUS_ACTIONS_INTERFACE "org.seul.geda.pcb.actions" 00046 00047 static DBusConnection *pcb_dbus_conn; 00048 00049 00050 static DBusHandlerResult 00051 handle_get_filename (DBusConnection * connection, DBusMessage * message, 00052 void *data) 00053 { 00054 DBusMessage *reply; 00055 DBusMessageIter iter; 00056 DBusHandlerResult result; 00057 char *filename; 00058 00059 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00060 00061 // TODO: Should check the message signature matches what we expect? 00062 00063 reply = dbus_message_new_method_return (message); 00064 if (reply == NULL) 00065 { 00066 fprintf (stderr, "pcb_dbus: Couldn't create reply message\n"); 00067 return result; 00068 } 00069 dbus_message_iter_init_append (reply, &iter); 00070 00071 if (PCB->Filename) 00072 filename = lrealpath (PCB->Filename); 00073 else 00074 filename = NULL; 00075 00076 if (filename == NULL) 00077 { 00078 #ifdef DEBUG 00079 fprintf (stderr, 00080 "pcb_dbus: DEBUG: Couldn't get working filename, assuming none\n"); 00081 #endif 00082 filename = strdup (""); 00083 if (filename == NULL) 00084 { 00085 fprintf (stderr, 00086 "pcb_dbus: Couldn't strdup( \"\" ) for the filename\n"); 00087 goto out; 00088 } 00089 } 00090 if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &filename)) 00091 { 00092 fprintf (stderr, 00093 "pcb_dbus: Couldn't append return filename string to message reply, Out Of Memory!\n"); 00094 free (filename); 00095 goto out; 00096 } 00097 free (filename); 00098 if (!dbus_connection_send (connection, reply, NULL)) 00099 { 00100 fprintf (stderr, "pcb_dbus: Couldn't send message, Out Of Memory!\n"); 00101 goto out; 00102 } 00103 result = DBUS_HANDLER_RESULT_HANDLED; 00104 00105 out: 00106 dbus_message_unref (reply); 00107 return result; 00108 } 00109 00110 00111 static DBusHandlerResult 00112 handle_exec_action (DBusConnection * connection, DBusMessage * message, 00113 void *data) 00114 { 00115 DBusMessage *reply; 00116 DBusMessageIter iter; 00117 DBusHandlerResult result; 00118 DBusError err; 00119 dbus_uint32_t retval; 00120 char *action_name; 00121 char **argv; 00122 int argc; 00123 #ifdef DEBUG 00124 int i; 00125 #endif 00126 00127 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00128 00129 // TODO: Should check the message signature matches what we expect? 00130 00131 // initialise the error struct 00132 dbus_error_init (&err); 00133 00134 /* DON'T FREE action_name, as it belongs to DBUS, 00135 * DO FREE argv, using dbus_free_string_array() 00136 */ 00137 argv = NULL; 00138 if (!dbus_message_get_args (message, 00139 &err, 00140 DBUS_TYPE_STRING, &action_name, 00141 DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &argv, &argc, 00142 DBUS_TYPE_INVALID)) 00143 { 00144 fprintf (stderr, "Failed to read method arguments\n"); 00145 if (argv) 00146 dbus_free_string_array (argv); 00147 return result; 00148 } 00149 00150 #ifdef DEBUG 00151 fprintf (stderr, "pcb_dbus: DEBUG: Executing action: %s(", action_name); 00152 if (argc > 0) 00153 fprintf (stderr, " \"%s\"", argv[0]); 00154 for (i = 1; i < argc; i++) 00155 fprintf (stderr, ", \"%s\"", argv[i]); 00156 fprintf (stderr, " )\n"); 00157 #endif 00158 00159 // TODO: Proper return value from actions 00160 hid_actionv (action_name, argc, argv); 00161 retval = 0; 00162 00163 dbus_free_string_array (argv); 00164 00165 reply = dbus_message_new_method_return (message); 00166 if (reply == NULL) 00167 { 00168 fprintf (stderr, "pcb_dbus: Couldn't create reply message\n"); 00169 return result; 00170 } 00171 dbus_message_iter_init_append (reply, &iter); 00172 if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &retval)) 00173 { 00174 fprintf (stderr, "pcb_dbus: Couldn't sent message, Out Of Memory!\n"); 00175 goto out; 00176 } 00177 00178 if (!dbus_connection_send (connection, reply, NULL)) 00179 { 00180 fprintf (stderr, "pcb_dbus: Couldn't send message, Out Of Memory!\n"); 00181 goto out; 00182 } 00183 00184 result = DBUS_HANDLER_RESULT_HANDLED; 00185 out: 00186 dbus_message_unref (reply); 00187 return result; 00188 } 00189 00190 00191 static DBusHandlerResult 00192 handle_introspect (DBusConnection * connection, DBusMessage * message, 00193 void *data) 00194 { 00195 DBusMessage *reply; 00196 DBusMessageIter iter; 00197 DBusHandlerResult result; 00198 00199 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00200 reply = dbus_message_new_method_return (message); 00201 if (reply == NULL) 00202 { 00203 fprintf (stderr, "pcb_dbus: Couldn't create reply message\n"); 00204 return result; 00205 } 00206 dbus_message_iter_init_append (reply, &iter); 00207 if (!dbus_message_iter_append_basic 00208 (&iter, DBUS_TYPE_STRING, &pcb_dbus_introspect_xml)) 00209 { 00210 fprintf (stderr, 00211 "pcb_dbus: Couldn't add introspect XML to message return\n"); 00212 goto out; 00213 } 00214 if (!dbus_connection_send (pcb_dbus_conn, reply, NULL)) 00215 { 00216 fprintf (stderr, 00217 "pcb_dbus: Couldn't queue reply message for sending\n"); 00218 goto out; 00219 } 00220 result = DBUS_HANDLER_RESULT_HANDLED; 00221 out: 00222 dbus_message_unref (reply); 00223 return result; 00224 } 00225 00226 static void 00227 unregister_dbus_handler (DBusConnection * connection, void *data) 00228 { 00229 } 00230 00231 00232 static DBusHandlerResult 00233 handle_dbus_message (DBusConnection * connection, DBusMessage * message, 00234 void *data) 00235 { 00236 int msg_type; 00237 msg_type = dbus_message_get_type (message); 00238 00239 switch (msg_type) 00240 { 00241 case DBUS_MESSAGE_TYPE_METHOD_CALL: 00242 { 00243 const char *method_name; 00244 const char *interface_name; 00245 00246 method_name = dbus_message_get_member (message); 00247 if (method_name == NULL) 00248 { 00249 fprintf (stderr, "pcb_dbus: Method had no name specified\n"); 00250 break; 00251 } 00252 00253 interface_name = dbus_message_get_interface (message); 00254 if (interface_name == NULL) 00255 { 00256 fprintf (stderr, "pcb_dbus: Method had no interface specified\n"); 00257 break; 00258 } 00259 00260 if (strcmp (interface_name, PCB_DBUS_INTERFACE) == 0) 00261 { 00262 if (strcmp (method_name, "GetFilename") == 0) 00263 { 00264 return handle_get_filename (connection, message, data); 00265 } 00266 fprintf (stderr, "pcb_dbus: Interface '%s' has no method '%s'\n", 00267 interface_name, method_name); 00268 break; 00269 } 00270 else if (strcmp (interface_name, PCB_DBUS_ACTIONS_INTERFACE) == 0) 00271 { 00272 if (strcmp (method_name, "ExecAction") == 0) 00273 { 00274 return handle_exec_action (connection, message, data); 00275 } 00276 fprintf (stderr, "pcb_dbus: Interface '%s' has no method '%s'\n", 00277 interface_name, method_name); 00278 break; 00279 } 00280 else if (strcmp (interface_name, DBUS_INTERFACE_INTROSPECTABLE) == 0) 00281 { 00282 if (strcmp (method_name, "Introspect") == 0) 00283 { 00284 return handle_introspect (connection, message, data); 00285 } 00286 fprintf (stderr, "pcb_dbus: Interface '%s' has no method '%s'\n", 00287 interface_name, method_name); 00288 break; 00289 } 00290 else 00291 { 00292 fprintf (stderr, "pcb_dbus: Interface '%s' was not recognised\n", 00293 interface_name); 00294 break; 00295 } 00296 } 00297 break; 00298 00299 case DBUS_MESSAGE_TYPE_METHOD_RETURN: 00300 fprintf (stderr, "pcb_dbus: DBUG: Method return message\n"); 00301 // WON'T ACTUALLY BE ANY UNLESS WE MAKE AN ASYNCRONOUS CALL? 00302 break; 00303 00304 case DBUS_MESSAGE_TYPE_ERROR: 00305 fprintf (stderr, "pcb_dbus: DEBUG: Error message\n"); 00306 // HOPE NOT! 00307 break; 00308 00309 case DBUS_MESSAGE_TYPE_SIGNAL: 00310 fprintf (stderr, "pcb_dbus: DEBUG: Signal message\n"); 00311 // NONE AT PRESENT 00312 break; 00313 00314 default: 00315 fprintf (stderr, 00316 "pcb_dbus: DEBUG: Message type wasn't one we know about!\n"); 00317 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00318 } 00319 00320 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00321 } 00322 00323 00328 void 00329 pcb_dbus_setup (void) 00330 { 00331 DBusError err; 00332 int ret; 00333 const DBusObjectPathVTable object_vtable = { 00334 unregister_dbus_handler, 00335 handle_dbus_message, 00336 NULL, NULL, NULL, NULL 00337 }; 00338 00339 // Initialise the error variable 00340 dbus_error_init (&err); 00341 00342 // Connect to the bus 00343 pcb_dbus_conn = dbus_bus_get_private (DBUS_BUS_SESSION, &err); 00344 if (dbus_error_is_set (&err)) 00345 { 00346 fprintf (stderr, "pcb_dbus: DBus connection Error (%s)\n", err.message); 00347 dbus_error_free (&err); 00348 } 00349 if (pcb_dbus_conn == NULL) 00350 return; 00351 00352 // Request the canonical name for PCB on the bus 00353 ret = dbus_bus_request_name (pcb_dbus_conn, PCB_DBUS_CANONICAL_NAME, 00354 DBUS_NAME_FLAG_REPLACE_EXISTING, &err); 00355 if (dbus_error_is_set (&err)) 00356 { 00357 fprintf (stderr, "pcb_dbus: DBus name error (%s)\n", err.message); 00358 dbus_error_free (&err); 00359 } 00360 if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 00361 && ret != DBUS_REQUEST_NAME_REPLY_IN_QUEUE) 00362 { 00363 fprintf (stderr, 00364 "pcb_dbus: Couldn't gain ownership or queued ownership of the canonical DBus name\n"); 00365 return; 00366 } 00367 00368 if (!dbus_connection_register_object_path (pcb_dbus_conn, PCB_DBUS_OBJECT_PATH, &object_vtable, NULL // void * user_data 00369 )) 00370 { 00371 fprintf (stderr, "pcb_dbus: Couldn't register DBUS handler for %s\n", 00372 PCB_DBUS_OBJECT_PATH); 00373 return; 00374 } 00375 00376 // Setup intergration with the pcb mainloop 00377 pcb_dbus_connection_setup_with_mainloop (pcb_dbus_conn); 00378 00379 // dbus_error_free(&err); 00380 return; 00381 } 00382 00383 00384 00388 void 00389 pcb_dbus_finish (void) 00390 { 00391 DBusError err; 00392 00393 // Initialise the error variable 00394 dbus_error_init (&err); 00395 00396 // TODO: Could emit a "goodbye" signal here? 00397 00398 dbus_connection_flush (pcb_dbus_conn); 00399 00400 dbus_connection_unregister_object_path (pcb_dbus_conn, 00401 PCB_DBUS_OBJECT_PATH); 00402 00403 dbus_bus_release_name (pcb_dbus_conn, PCB_DBUS_CANONICAL_NAME, &err); 00404 00405 dbus_error_free (&err); 00406 00407 pcb_dbus_connection_finish_with_mainloop (pcb_dbus_conn); 00408 00409 dbus_connection_close (pcb_dbus_conn); 00410 dbus_connection_unref (pcb_dbus_conn); 00411 00412 // Call DBus shutdown. This doesn't work with shared connections, 00413 // only private ones (like we took out earlier). 00414 // If any future module / plugin to PCB wants to use DBus too, 00415 // we must remove this call. DBus will get shut-down when the app exits. 00416 dbus_shutdown (); 00417 }