[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

gEDA-dev: PCB DBus support code - 2



Attached are the new dbus support files, which I didn't include in the
previous email.

The two .c files still need work still before it could be considered for
release. I don't personally see harm in applying to CVS, as the code
isn't built unless specifically configured.

Would it be possible to set up CVS write access for me, such that I can
work on this code in a branch off HEAD?

Regards,

-- 
Peter Clifton

Electrical Engineering Division,
Engineering Department,
University of Cambridge,
9, JJ Thomson Avenue,
Cambridge
CB3 0FA

Tel: +44 (0)7729 980173 - (No signal in the lab!)
/*
 * PCB, an interactive printed circuit board editor
 * D-Bus IPC logic
 * Copyright (C) 2006 University of Cambridge
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 *  D-Bus code originally derrived from example-service.c in the dbus-glib bindings
 */

// For canonicalize_file_name
#define _GNU_SOURCE
#include <stdlib.h>

#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>

#include "dbus.h"
#include "dbus-introspect.h"
#include "data.h"

#define PCB_DBUS_CANONICAL_NAME    "org.seul.geda.pcb"
#define PCB_DBUS_OBJECT_PATH       "/org/seul/geda/pcb"
#define PCB_DBUS_INTERFACE         "org.seul.geda.pcb"
#define PCB_DBUS_ACTIONS_INTERFACE "org.seul.geda.pcb.actions"

static DBusConnection* pcb_dbus_conn;


static void
unregister_dbus_handler (DBusConnection *connection, void *data)
{
}


static DBusHandlerResult
handle_get_filename( DBusConnection *connection, DBusMessage *message, void *data)
{
  DBusMessage *reply;
  DBusMessageIter iter;
  DBusHandlerResult result;
  char *filename;
  
  result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  
  // TODO: Should check the message signature matches what we expect 
  
  reply = dbus_message_new_method_return(message);
  if (reply == NULL)
    {
      fprintf( stderr, "pcb_dbus: DEBUG: Couldn't create reply message\n" );
      return result;
    }
  dbus_message_iter_init_append(reply, &iter);

  // TODO: Use libiberty lrealname
//  filename = canonicalize_file_name( PCB->Filename );
  filename = canonicalize_file_name( "/home/pcjc2/xgsch2pcb_test/mytest.pcb" );

  if (filename == NULL)
    {
      fprintf(stderr, "pcb_dbus: DEBUG: Couldn't get working filename, assuming none\n");
      filename = strdup( "" );
      if (filename == NULL)
        {
          fprintf(stderr, "pcb_dbus: DEBUG: Couldn't strdup( \"\" ) for the filename\n");
          goto out;
        }
    }
  if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &filename))
    {
      fprintf(stderr, "pcb_dbus: DEBUG: Couldn't append return filename string to message reply, Out Of Memory!\n");
      free( filename );
      goto out;
    }
  free( filename );
  if (!dbus_connection_send(connection, reply, NULL))
    {
      fprintf(stderr, "pcb_dbus: DEBUG: Couldn't send message, Out Of Memory!\n");
      goto out;
    }
  result = DBUS_HANDLER_RESULT_HANDLED;

out:
  dbus_message_unref( reply );
  return result;
}


static DBusHandlerResult
handle_exec_action( DBusConnection *connection, DBusMessage *message, void *data)
{
  DBusMessage *reply;
  DBusMessageIter iter;
  DBusHandlerResult result;
  DBusError err;
  dbus_uint32_t retval;
  char *action_name;
  char **argv;
  int argc;
  int i;
  
  result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  
  // TODO: Should check the message signature matches what we expect 
  
  // initialise the error struct
  dbus_error_init(&err);

  /* DON'T FREE action_name, as it belongs to DBUS,
   * DO    FREE argv, using dbus_free_string_array()
   */ 
  if (!dbus_message_get_args( message,
                              &err, 
                              DBUS_TYPE_STRING, &action_name,
                              DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &argv, &argc,
                              DBUS_TYPE_INVALID
                            ) )
    {
      fprintf(stderr, "Failed to read method arguments\n");
      // TODO: Check my assumption that if error, argv wasn't allocated?
      //       Perhaps we ougt to NULL it before the call, and check here?
      return result;
    }

  // TODO: Proper return value from actions
  fprintf( stderr, "pcb_dbus: DEBUG: Executing action: %s(", action_name );
  if ( argc > 0 )
    fprintf( stderr, " \"%s\"", argv[0] );
  for ( i = 1; i < argc; i++ )
    fprintf( stderr, ", \"%s\"", argv[i] );
  fprintf( stderr, " )\n" );
  hid_actionv( action_name, argc, argv ); 
  retval = 0;

  dbus_free_string_array( argv );

  reply = dbus_message_new_method_return(message);
  if (reply == NULL)
    {
      fprintf( stderr, "pcb_dbus: DEBUG: Couldn't create reply message\n" );
      return result;
    }
  dbus_message_iter_init_append(reply, &iter);
  if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &retval))
    {
     fprintf(stderr, "pcb_dbus: DEBUG: Couldn't sent message, Out Of Memory!\n");
     goto out;
    }

  if (!dbus_connection_send(connection, reply, NULL))
    {
     fprintf(stderr, "pcb_dbus: DEBUG: Couldn't send message, Out Of Memory!\n");
     goto out;
    }

  result = DBUS_HANDLER_RESULT_HANDLED;
out:
  dbus_message_unref( reply );
  return result;
}


static DBusHandlerResult
handle_introspect( DBusConnection *connection, DBusMessage *message, void *data)
{
  DBusMessage *reply;
  DBusMessageIter iter;
  DBusHandlerResult result;
  
  result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  reply = dbus_message_new_method_return (message);
  if (reply == NULL)
    {
      fprintf( stderr, "pcb_dbus: DEBUG: Couldn't create reply message\n" );
      return result;
    }
  dbus_message_iter_init_append (reply, &iter);
  if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &pcb_dbus_introspect_xml))
    {
      fprintf( stderr, "pcb_dbus: DEBUG: Couldn't add introspect XML to message return\n" );
      goto out;
    }
  if (! dbus_connection_send (pcb_dbus_conn, reply, NULL))
    {
      fprintf( stderr, "pcb_dbus: DEBUG: Couldn't queue reply message for sending\n" );
      goto out;
    }
  result = DBUS_HANDLER_RESULT_HANDLED;
out:
  dbus_message_unref( reply );
  return result;
}


static DBusHandlerResult
handle_dbus_message (DBusConnection *connection, DBusMessage *message, void *data)
{
  int msg_type;
  msg_type = dbus_message_get_type( message );
  
  switch( msg_type )
    {
  case DBUS_MESSAGE_TYPE_METHOD_CALL:
      {
        const char *method_name;
        const char *interface_name;

        method_name = dbus_message_get_member( message );
        if ( method_name == NULL )
          {
            fprintf( stderr, "pcb_dbus: DEBUG: Method had no name specified\n");
            break;
          }

        interface_name = dbus_message_get_interface( message );
        if ( interface_name == NULL )
          {
            fprintf( stderr, "pcb_dbus: DEBUG: Method had no interface specified\n");
            break;
          }
        
        if ( interface_name && strcmp( interface_name, PCB_DBUS_INTERFACE ) == 0 )
          {
            if ( strcmp( method_name, "GetFilename" ) == 0 )
              {
                return handle_get_filename( connection, message, data );
              }
            fprintf( stderr, "pcb_dbus: DEBUG: Interface '%s' has no method '%s'\n", interface_name, method_name );
            break;
          }
        else if ( interface_name && strcmp( interface_name, PCB_DBUS_ACTIONS_INTERFACE ) == 0 )
          {
            if ( strcmp( method_name, "ExecAction" ) == 0 )
              {
                return handle_exec_action( connection, message, data );
              }
            fprintf( stderr, "pcb_dbus: DEBUG: Interface '%s' has no method '%s'\n", interface_name, method_name );
            break;
          }
        else if ( interface_name && strcmp( interface_name, DBUS_INTERFACE_INTROSPECTABLE ) == 0 )
          {
            if ( strcmp( method_name, "Introspect" ) == 0 )
              {
                return handle_introspect( connection, message, data );
              }
            fprintf( stderr, "pcb_dbus: DEBUG: Interface '%s' has no method '%s'\n", interface_name, method_name );
            break;
          }
        else if ( interface_name )
          {
            fprintf( stderr, "pcb_dbus: DEBUG: Interface '%s' was not recognised\n", interface_name );
            break;
          }
        else
          {
            fprintf( stderr, "pcb_dbus: DEBUG: No interface was specified\n" );
            break;
          }
      }
      break;
  
  case DBUS_MESSAGE_TYPE_METHOD_RETURN:
      fprintf( stderr, "pcb_dbus: DEBUG: Method return message\n" );
      // WON'T ACTUALLY BE ANY UNLESS WE MAKE AN ASYNCRONOUS CALL?
      break;

  case DBUS_MESSAGE_TYPE_ERROR:
      fprintf( stderr, "pcb_dbus: DEBUG: Error message\n" );
      // HOPE NOT!
      break;

  case DBUS_MESSAGE_TYPE_SIGNAL:
      fprintf( stderr, "pcb_dbus: DEBUG: Signal message\n" );
      // NONE AT PRESENT
      break;
 
  default:
      fprintf( stderr, "pcb_dbus: DEBUG: Message type wasn't one we know about!\n" );
      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    }

#if 0
  //if (dbus_message_is_method_call (message, "org.seul.geda.pcb", "GetFilename")) {
  //if (dbus_message_is_method_call (message, "org.seul.geda.pcb.actions", "ExecAction")) {
    DBusMessageIter iter;
    guint32 current_time;

    if (!dbus_message_iter_init (message, &iter))
      return DBUS_HANDLER_RESULT_NEED_MEMORY;

    if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

    dbus_message_iter_get_basic (&iter, &current_time);

    rb_shell_present (shell, current_time, NULL);
    return DBUS_HANDLER_RESULT_HANDLED;
  } else {
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  }
#endif
  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}


void
pcb_dbus_setup ( void )
{
  DBusError err;
  int ret;
  const DBusObjectPathVTable object_vtable = {
    unregister_dbus_handler,
    handle_dbus_message,
    NULL, NULL, NULL, NULL
  };

  // initialise the errors
  dbus_error_init(&err);

  // connect to the bus
  pcb_dbus_conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
  if (dbus_error_is_set(&err))
    {
     fprintf(stderr, "Connection Error (%s)\n", err.message);
     dbus_error_free(&err);
    }
  if (pcb_dbus_conn == NULL)
    return;

  // request a name on the bus
  ret = dbus_bus_request_name(pcb_dbus_conn, PCB_DBUS_CANONICAL_NAME,
        DBUS_NAME_FLAG_REPLACE_EXISTING
        , &err);
  if (dbus_error_is_set(&err))
    {
     fprintf(stderr, "Name Error (%s)\n", err.message);
     dbus_error_free(&err);
    }
  if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER && ret != DBUS_REQUEST_NAME_REPLY_IN_QUEUE)
    return;

  if ( ! dbus_connection_register_object_path(
                                               pcb_dbus_conn,
                                               PCB_DBUS_OBJECT_PATH,
                                               &object_vtable,
                                               NULL // void * user_data
                                               ) )
    {
      fprintf(stderr, "Couldn't register DBUS handler for /org/geda/seul/pcb\n");
      return;
    }

  dbus_connection_setup_with_pcb_main( pcb_dbus_conn );

//  // BEGIN TESTING
//  while (dbus_connection_read_write_dispatch (pcb_dbus_conn, -1)); 
//  // END TESTING

  return;
}


void
pcb_dbus_finish( void )
{
  // TODO: Could emit a "goodbye" signal here?
  
  // TODO: Do we need to undo dbus_connection_setup_With_pcb_main() ?

  // Don't close the connection, as the SESSION_BUS is shared
  // dbus_connection_close(pcb_dbus_conn);
}
/*
 * PCB, an interactive printed circuit board editor
 * D-Bus IPC logic
 * Copyright (C) 2006 University of Cambridge
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#ifndef _DBUS_H_
#define _DBUS_H_

/* Carry out all actions to setup the D-Bus and register appropriate callbacks */
void pcb_dbus_setup();

/* Carry out all actions to finalise the D-Bus connection */
void pcb_dbus_finish();


#endif /* !_DBUS_H */

dbus.xml

/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-pcbmain.c PCB HID main loop integration
 *
 * Adapted from dbus-gmain.c from dbus-glib bindings:
 * Copyright (C) 2002, 2003 CodeFactory AB
 * Copyright (C) 2005 Red Hat, Inc.
 *
 * Licensed under the Academic Free License version 2.1
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "global.h"
#include "dbus-pcbmain.h"

#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>
#include <stdio.h>

#warning Change asserts to more verbose error tests
#include <assert.h>

/* Set timeout to -1 for unlimited, or max number of milliseconds to block before looping again
 * Return FALSE if we have nothing to dispatch later, otherwise TRUE
 */
static void
message_queue_block_hook_cb (hidval data)
{
  DBusConnection *connection = (DBusConnection*)data.ptr;
  if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_DATA_REMAINS)
    return;
 
  fprintf( stderr, "message_queue_block_hook_cb(): Dispatching a message\n" ); 
  dbus_connection_ref (connection);
  /* Only dispatch once - we don't want to starve other mainloop users */
#warning **** DO WE INFACT _NEED_ TO DISPATCH ALL WE CAN? ****
  dbus_connection_dispatch (connection);
  dbus_connection_unref (connection);
  return;
}

void message_queue_setup_with_pcb_mainloop( DBusConnection *conn )
{
  gui->add_block_hook( message_queue_block_hook_cb, (hidval)(void*)conn );
}

typedef struct _ConnectionSetup ConnectionSetup;
typedef struct _IOHandler IOHandler; 
typedef struct _TimeoutHandler TimeoutHandler; 

struct _ConnectionSetup
{
  //GSList *ios;                /**< all IOHandler */
  IOHandler **ios;                /**< all IOHandler */
  //GSList *timeouts;           /**< all TimeoutHandler */
  TimeoutHandler **timeouts;           /**< all TimeoutHandler */
  DBusConnection *dbus_conn;  /**< DBUS Connection */
};

struct _IOHandler
{
  ConnectionSetup *cs;
  DBusWatch *dbus_watch;
  hidval pcb_watch;
};

struct _TimeoutHandler
{
  ConnectionSetup *cs;
  DBusTimeout *timeout;
  int interval;
};

static dbus_int32_t connection_slot = -1;

static ConnectionSetup*
connection_setup_new(DBusConnection *connection)
{
  ConnectionSetup *cs;
  cs = malloc(sizeof (ConnectionSetup));
#warning Fixme!!
  cs->ios = NULL;
#warning Fixme!!
  cs->timeouts = NULL;
  cs->dbus_conn = connection;
  
#warning Thought required
  /* At this point, the glib binding defines a new mainloop source to mop up
     any unfinished IO. We don't, so we need to make sure that doesn't block
  */
  return cs;
}

#if 0
static void
io_handler_source_finalized (void *data)
{
  IOHandler *handler;
  handler = data;
  if (handler->dbus_watch)
    dbus_watch_set_data (handler->dbus_watch, NULL, NULL);
  free (handler);
}
#endif

static void
io_handler_destroy_source (void *data)
{
//  IOHandler *handler;
//  handler = data;
//  if (handler->source)
//    {
//      GSource *source = handler->source;
//      handler->source = NULL;
//      handler->cs->ios = g_slist_remove (handler->cs->ios, handler);
//      g_source_destroy (source);
//      g_source_unref (source);
//    }
}

static void
io_handler_watch_freed (void *data)
{
  IOHandler *handler;
  handler = data;
  handler->dbus_watch = NULL;
  io_handler_destroy_source (handler);
}

void
io_handler_dispatch (hidval pcb_watch, // We need some way to identify which watch this is
                     int fd, // We could of course, find this using the data callback
                     unsigned int condition, // Reason we were called
                     hidval data)
{
  IOHandler *handler;
  unsigned int dbus_condition = 0;
  DBusConnection *connection;

  handler = (IOHandler *)data.ptr;

  connection = handler->cs->dbus_conn;
  
  if (connection)
    dbus_connection_ref (connection);
 
  if (condition & PCB_WATCH_READABLE)
    dbus_condition |= DBUS_WATCH_READABLE;
  if (condition & PCB_WATCH_WRITABLE)
    dbus_condition |= DBUS_WATCH_WRITABLE;
  if (condition & PCB_WATCH_ERROR)
    dbus_condition |= DBUS_WATCH_ERROR;
  if (condition & PCB_WATCH_HANGUP)
    dbus_condition |= DBUS_WATCH_HANGUP;

  /* Note that we don't touch the handler after this, because
   * dbus may have disabled the watch and thus killed the
   * handler.
   */
  dbus_watch_handle (handler->dbus_watch, dbus_condition);
  handler = NULL;

  if (connection)
    dbus_connection_unref (connection);
  
  //return TRUE; // Run this callback again
  return;
}

#if 0
static void
timeout_handler_source_finalized (void *data)
{
  TimeoutHandler *handler;

  handler = data;

  if (handler->timeout)
    dbus_timeout_set_data (handler->timeout, NULL, NULL);
  
  free (handler);
}
#endif

static void
timeout_handler_destroy_source (void *data)
{
//  TimeoutHandler *handler;
//  handler = data;
//  if (handler->source)
//    {
//      GSource *source = handler->source;
//      handler->source = NULL;
//      handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler);
//      g_source_destroy (source);
//      g_source_unref (source);
//    }
}

static void
timeout_handler_timeout_freed (void *data)
{
  TimeoutHandler *handler;
  handler = data;
  handler->timeout = NULL;
  timeout_handler_destroy_source (handler);
}

void
timeout_handler_dispatch (hidval data)
{
  TimeoutHandler *handler;
  handler = data.ptr;
  dbus_timeout_handle (handler->timeout);
  // TODO: See if we can get PCB's behaviour changed
  gui->add_timer( timeout_handler_dispatch, handler->interval, data);
}

static void
connection_setup_add_timeout (ConnectionSetup *cs,
                              DBusTimeout     *timeout)
{
  TimeoutHandler *handler;
  
  fprintf( stderr, "dbus-pcbmain: connection_setup_add_timeout()\n" );
  if (!dbus_timeout_get_enabled (timeout))
    return;
  
  assert (dbus_timeout_get_data (timeout) == NULL);

  handler = malloc( sizeof(TimeoutHandler ) );
  handler->cs = cs;
  handler->timeout = timeout;
  handler->interval = dbus_timeout_get_interval( timeout );

  //FIXME: Need to store the interval, as PCB requires us
  //       to manually re-add the timer each time it expires.
  //       This is non-ideal, and hopefully can be changed?

  gui->add_timer( timeout_handler_dispatch, handler->interval, (hidval)(void *)handler);

#warning Thought required
  // TODO: Work out the implications of not getting a finalize handler  

#warning Fixme
  // TODO: Add the timeout to our list
  //cs->timeouts = g_slist_prepend (cs->timeouts, handler);

  dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed);
}

static void
connection_setup_remove_timeout (ConnectionSetup *cs,
                                 DBusTimeout       *timeout)
{
  TimeoutHandler *handler;
  handler = dbus_timeout_get_data (timeout);
  if (handler == NULL)
    return;
  timeout_handler_destroy_source (handler);
}

// Called when dbus has had enough of us.
static void
connection_setup_free (ConnectionSetup *cs)
{
//  while (cs->ios)
//    io_handler_destroy_source (cs->ios->data);

//  while (cs->timeouts)
//    timeout_handler_destroy_source (cs->timeouts->data);

//  if (cs->message_queue_source)
//    {
//      GSource *source;
//      source = cs->message_queue_source;
//      cs->message_queue_source = NULL;
//      g_source_destroy (source);
//      g_source_unref (source);
//    }
  
  free (cs);
}

static dbus_bool_t
add_watch (DBusWatch *dbus_watch,
	   void *data)
{
  IOHandler *handler;
  int fd;
  unsigned int pcb_condition;
  unsigned int dbus_flags;
  
  fprintf( stderr, "dbus-pcbmain: add_watch()\n" );
  ConnectionSetup *cs;
  cs = data;
  
  if (!dbus_watch_get_enabled (dbus_watch))
    return TRUE;
  
  assert (dbus_watch_get_data (dbus_watch) == NULL);

  dbus_flags = dbus_watch_get_flags( dbus_watch );  
  
  pcb_condition = PCB_WATCH_ERROR | PCB_WATCH_HANGUP;
  if (dbus_flags & DBUS_WATCH_READABLE)
    pcb_condition |= PCB_WATCH_READABLE;
  if (dbus_flags & DBUS_WATCH_WRITABLE)
    pcb_condition |= PCB_WATCH_READABLE;
  
  fd = dbus_watch_get_fd (dbus_watch);

  handler = malloc( sizeof( IOHandler ));
  handler->cs = cs;
  handler->dbus_watch = dbus_watch;
  handler->pcb_watch = gui->watch_file(fd, pcb_condition, io_handler_dispatch, (hidval)(void *)handler);

  // TODO: Add this watch to our list
  //cs->ios = g_slist_prepend (cs->ios, handler);

  dbus_watch_set_data (dbus_watch, handler, io_handler_watch_freed);
  return TRUE;
}

static void
remove_watch (DBusWatch *dbus_watch,
	      void      *data)
{
  IOHandler *handler;

  handler = dbus_watch_get_data (dbus_watch);

  if (handler == NULL)
    return;
  
  io_handler_destroy_source (handler);
}

static void
watch_toggled (DBusWatch *dbus_watch,
               void      *data)
{
  /* Because we just exit on OOM, enable/disable is
   * no different from add/remove
   */
  if (dbus_watch_get_enabled (dbus_watch))
    add_watch (dbus_watch, data);
  else
    remove_watch (dbus_watch, data);
}

static dbus_bool_t
add_timeout (DBusTimeout *timeout,
	     void        *data)
{
  ConnectionSetup *cs;
  cs = data;
  
  fprintf( stderr, "dbus-pcbmain: add_timeout()\n" );
  
  if (!dbus_timeout_get_enabled (timeout))
    return TRUE;
  
  connection_setup_add_timeout (cs, timeout);
  return TRUE;
}

static void
remove_timeout (DBusTimeout *timeout,
		void        *data)
{
  ConnectionSetup *cs;
  cs = data;
  connection_setup_remove_timeout (cs, timeout);
}

static void
timeout_toggled (DBusTimeout *timeout,
                 void        *data)
{
  /* Because we just exit on OOM, enable/disable is
   * no different from add/remove
   */
  if (dbus_timeout_get_enabled (timeout))
    add_timeout (timeout, data);
  else
    remove_timeout (timeout, data);
}

//static void
//wakeup_main (void *data)
//{
////  g_main_context_wakeup (cs->context);
//  fprintf(stderr, "dbus-pcbmain: wakeup_main() called, but we don't know what to do\n");
//}


// END INTERNALS


/**
 * Sets the watch and timeout functions of a #DBusConnection
 * to integrate the connection with the GUI HID's main loop.
 *
 * @param connection the connection
 */
void
dbus_connection_setup_with_pcb_main (DBusConnection *connection)
{
  ConnectionSetup *cs;
  
  /* FIXME we never free the slot, so its refcount just keeps growing,
   * which is kind of broken.
   */
  dbus_connection_allocate_data_slot (&connection_slot);
  if (connection_slot < 0)
    goto nomem;

  cs = connection_setup_new (connection);

  if (!dbus_connection_set_data (connection, connection_slot, cs,
                                 (DBusFreeFunction)connection_setup_free))
    goto nomem;
  
  if (!dbus_connection_set_watch_functions (connection,
                                            add_watch,
                                            remove_watch,
                                            watch_toggled,
                                            cs, NULL))
    goto nomem;

  if (!dbus_connection_set_timeout_functions (connection,
                                              add_timeout,
                                              remove_timeout,
                                              timeout_toggled,
                                              cs, NULL))
    goto nomem;
    
  //dbus_connection_set_wakeup_main_function (connection,
//					    wakeup_main,
//					    cs, NULL);
  
  message_queue_setup_with_pcb_mainloop( connection );
  return;

 nomem:
  fprintf(stderr, "Not enough memory to set up DBusConnection for use with PCB");
}

/*
 * PCB, an interactive printed circuit board editor
 * D-Bus IPC logic
 * Copyright (C) 2006 University of Cambridge
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#ifndef _DBUS_PCBMAIN_H_
#define _DBUS_PCBMAIN_H_

#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>

void dbus_connection_setup_with_pcb_main (DBusConnection *connection);

#endif /* !_DBUS_PCBMAIN_H */


_______________________________________________
geda-dev mailing list
geda-dev@moria.seul.org
http://www.seul.org/cgi-bin/mailman/listinfo/geda-dev