示例#1
0
文件: BLEThread.cpp 项目: appl/RASP
guint bluez_create_watcher(GDBusConnection* conn, BLEThread* thread)
{
    /* We are lazy here - we don't want to manually provide
    * the introspection data structures - so we just build
    * them from XML.
    */
    introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
    g_assert(introspection_data != NULL);

    guint registration_id;

    gchar path[255];
    g_snprintf(path, 255, "/test/bluez/%d", getpid());

    registration_id = g_dbus_connection_register_object(conn,
                                                       path,
                                                       introspection_data->interfaces[0],
                                                       &interface_vtable,
                                                       thread,  /* user_data */
                                                       NULL,  /* user_data_free_func */
                                                       NULL); /* GError** */
    g_assert(registration_id > 0);

    return g_bus_own_name_on_connection(conn,
                                     "org.test.bluez",
                                     G_BUS_NAME_OWNER_FLAGS_NONE,
                                     on_name_acquired,
                                     on_name_lost,
                                     NULL,
                                     NULL);
}
示例#2
0
static guint
start_service (GDBusConnection *bus,
               NMConnectionList *list,
               guint *out_registration_id)
{
	static const gchar introspection_xml[] =
		"<node>"
		"  <interface name='org.gnome.nm_connection_editor'>"
		"    <method name='Start'>"
		"      <arg type='a{sv}' name='args' direction='in'/>"
		"    </method>"
		"  </interface>"
		"</node>";

	introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
	g_assert (introspection_data != NULL);

	*out_registration_id = g_dbus_connection_register_object (bus,
	                                                          "/",
	                                                          introspection_data->interfaces[0],
	                                                          &interface_vtable,
	                                                          list,  /* user_data */
	                                                          NULL,  /* user_data_free_func */
	                                                          NULL); /* GError** */

	return g_bus_own_name_on_connection (bus,
	                                     NM_CE_DBUS_SERVICE,
	                                     G_BUS_NAME_OWNER_FLAGS_NONE,
	                                     NULL,
	                                     NULL,
	                                     NULL,
	                                     NULL);
}
示例#3
0
int main(void)
{
    int r;

    GError *error = NULL;

    r = co2mon_init();
    if (r < 0)
    {
        return r;
    }

    introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
    g_assert(introspection_data != NULL);

    connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
    if (connection == NULL)
    {
        g_assert(error != NULL);
        fprintf(stderr, "Unable to connect to D-Bus: %s\n", error->message);
        g_error_free(error);
        return 1;
    }

    on_bus_acquired();

    GMainLoop *main_loop = g_main_loop_new(NULL, FALSE);

    guint owner_id = g_bus_own_name_on_connection(
        connection,
        service,
        G_BUS_NAME_OWNER_FLAGS_NONE,
        on_name_acquired,
        on_name_lost,
        main_loop, /* user_data */
        NULL
    );

    g_main_loop_run(main_loop);

    g_bus_unown_name(owner_id);
    g_main_loop_unref(main_loop);
    g_object_unref(connection);

    co2mon_exit();
    return 1;
}
/**
 * g_bus_own_name_on_connection_with_closures:
 * @connection: A #GDBusConnection.
 * @name: The well-known name to own.
 * @flags: A set of flags from the #GBusNameOwnerFlags enumeration.
 * @name_acquired_closure: (allow-none): #GClosure to invoke when @name is
 * acquired or %NULL.
 * @name_lost_closure: (allow-none): #GClosure to invoke when @name is lost or
 * %NULL.
 *
 * Version of g_bus_own_name_on_connection() using closures instead of callbacks for
 * easier binding in other languages.
 *
 * Returns: An identifier (never 0) that an be used with
 * g_bus_unown_name() to stop owning the name.
 *
 * Rename to: g_bus_own_name_on_connection
 *
 * Since: 2.26
 */
guint
g_bus_own_name_on_connection_with_closures (GDBusConnection          *connection,
                                            const gchar              *name,
                                            GBusNameOwnerFlags        flags,
                                            GClosure                 *name_acquired_closure,
                                            GClosure                 *name_lost_closure)
{
  return g_bus_own_name_on_connection (connection,
          name,
          flags,
          name_acquired_closure != NULL ? own_with_closures_on_name_acquired : NULL,
          name_lost_closure != NULL ? own_with_closures_on_name_lost : NULL,
          own_name_data_new (NULL,
                             name_acquired_closure,
                             name_lost_closure),
          bus_own_name_free_func);
}
示例#5
0
static void
on_manager_ready (GObject *source,
                  GAsyncResult *res,
                  gpointer user_data)
{
  StorageDaemon *self = user_data;

  self->manager = storage_manager_new_finish (source, res);
  storage_daemon_publish (self, "/org/freedesktop/UDisks2/Manager", FALSE, self->manager);

  self->name_owner_id = g_bus_own_name_on_connection (self->connection,
                                                      "com.redhat.storaged",
                                                      self->name_flags,
                                                      on_name_acquired,
                                                      on_name_lost,
                                                      self,
                                                      NULL);
}
示例#6
0
/*****************************************************************************
 * neardal_agent_acquire_dbus_name: acquire dbus name for management of neard
 *  agent feature
 ****************************************************************************/
errorCode_t neardal_agent_acquire_dbus_name(void)
{
	errorCode_t			err = NEARDAL_SUCCESS;

	NEARDAL_TRACEIN();
	if (neardalMgr.conn == NULL)
		return NEARDAL_ERROR_DBUS;

	neardalMgr.OwnerId = g_bus_own_name_on_connection(neardalMgr.conn
				, NEARDAL_DBUS_WELLKNOWN_NAME
				, G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
				  G_BUS_NAME_OWNER_FLAGS_REPLACE
				, on_name_acquired	/* on_name_acquired */
				, on_name_lost		/* on_name_lost */
				, NULL			/* user data */
				, NULL);	/* freeing user_data func */

	if (neardalMgr.OwnerId == 0) {
		err = NEARDAL_ERROR_DBUS;
		goto exit;
	}

	/* Create a new org.neardal.ObjectManager rooted at /neardal */
	neardalMgr.agentMgr = g_dbus_object_manager_server_new(AGENT_PREFIX);
	if (neardalMgr.agentMgr == NULL) {
		err = NEARDAL_ERROR_DBUS;
		goto exit;
	}

	/* Export all objects */
	g_dbus_object_manager_server_set_connection (neardalMgr.agentMgr
						     , neardalMgr.conn);


exit:
	if (err != NEARDAL_SUCCESS)
		NEARDAL_TRACE_ERR("(%d:%s)\n", err
				  , neardal_error_get_text(err));

	return err;
}
示例#7
0
static gboolean
on_claim_other_name (TestFrobber *frobber,
                     GDBusMethodInvocation *invocation,
                     const gchar *name,
                     gpointer user_data)
{
  ClaimNameData *claim_data;
  MockData *mock_data = user_data;
  guint id;

  g_return_val_if_fail (g_hash_table_lookup (mock_data->other_names, name) == NULL, FALSE);

  claim_data = g_new0 (ClaimNameData, 1);
  claim_data->invocation = g_object_ref (invocation);
  id = g_bus_own_name_on_connection (mock_data->connection, name,
                                     G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | G_BUS_NAME_OWNER_FLAGS_NONE,
                                     on_other_name_acquired,
                                     on_other_name_lost,
                                     claim_data, claim_name_data_free);

  g_hash_table_replace (mock_data->other_names, g_strdup (name), GUINT_TO_POINTER (id));
  return TRUE;
}
示例#8
0
guint
evd_dbus_agent_own_name (GObject             *object,
                         guint                connection_id,
                         const gchar         *name,
                         GBusNameOwnerFlags   flags,
                         GError             **error)
{
  GDBusConnection *conn;
  ObjectData *obj_data;
  NameOwnerData *owner_data;

  conn = evd_dbus_agent_get_connection (object, connection_id, error);
  if (conn == NULL)
    return 0;

  obj_data = evd_dbus_agent_get_object_data (object);

  owner_data = g_slice_new (NameOwnerData);
  owner_data->obj_data = obj_data;
  owner_data->conn_id = connection_id;
  owner_data->dbus_conn = conn;

  owner_data->owner_id = g_bus_own_name_on_connection (conn,
                                           name,
                                           flags,
                                           evd_dbus_agent_name_acquired,
                                           evd_dbus_agent_name_lost,
                                           owner_data,
                                           NULL);

  g_hash_table_insert (obj_data->owned_names,
                       &owner_data->owner_id,
                       owner_data);

  return owner_data->owner_id;
}
示例#9
0
static gboolean
tracker_controller_dbus_start (TrackerController   *controller,
                               GError             **error)
{
	TrackerControllerPrivate *priv;
	GError *err = NULL;
	GDBusInterfaceVTable interface_vtable = {
		handle_method_call,
		NULL, NULL
	};

	priv = controller->priv;

	priv->connection = tracker_sparql_connection_get (NULL, &err);

	if (!priv->connection) {
		g_propagate_error (error, err);
		return FALSE;
	}

	priv->d_connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, &err);

	if (!priv->d_connection) {
		g_propagate_error (error, err);
		return FALSE;
	}

	priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, &err);
	if (!priv->introspection_data) {
		g_propagate_error (error, err);
		return FALSE;
	}

	g_message ("Registering D-Bus object...");
	g_message ("  Path:'" TRACKER_WRITEBACK_PATH "'");
	g_message ("  Object Type:'%s'", G_OBJECT_TYPE_NAME (controller));

	priv->registration_id =
		g_dbus_connection_register_object (priv->d_connection,
		                                   TRACKER_WRITEBACK_PATH,
		                                   priv->introspection_data->interfaces[0],
		                                   &interface_vtable,
		                                   controller,
		                                   NULL,
		                                   &err);

	if (err) {
		g_critical ("Could not register the D-Bus object "TRACKER_WRITEBACK_PATH", %s",
		            err ? err->message : "no error given.");
		g_propagate_error (error, err);
		return FALSE;
	}

	priv->bus_name_id =
		g_bus_own_name_on_connection (priv->d_connection,
		                              TRACKER_WRITEBACK_SERVICE,
		                              G_BUS_NAME_OWNER_FLAGS_NONE,
		                              bus_name_acquired_cb,
		                              bus_name_vanished_cb,
		                              controller, NULL);

	if (err) {
		g_critical ("Could not own the D-Bus name "TRACKER_WRITEBACK_SERVICE", %s",
		            err ? err->message : "no error given.");
		g_propagate_error (error, err);
		return FALSE;
	}

	return TRUE;
}
示例#10
0
文件: meta-daemon.c 项目: gicmo/gvfs
int
main (int argc, char *argv[])
{
  GMainLoop *loop;
  GDBusConnection *conn;
  gboolean replace;
  gboolean show_version;
  GError *error;
  guint name_owner_id;
  GBusNameOwnerFlags flags;
  GOptionContext *context;
  const GOptionEntry options[] = {
    { "replace", 'r', 0, G_OPTION_ARG_NONE, &replace,  N_("Replace old daemon."), NULL },
    { "version", 0, 0, G_OPTION_ARG_NONE, &show_version, N_("Show program version."), NULL},
    { NULL }
  };

  setlocale (LC_ALL, "");

  bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR);
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
  textdomain (GETTEXT_PACKAGE);

  g_set_application_name (_("GVFS Metadata Daemon"));
  context = g_option_context_new ("");

  g_option_context_set_summary (context, _("Metadata daemon for GVFS"));

  g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);

  replace = FALSE;
  show_version = FALSE;
  name_owner_id = 0;

  error = NULL;
  if (!g_option_context_parse (context, &argc, &argv, &error))
    {
      /* Translators: the first %s is the application name, */
      /* the second %s is the error message                 */
      g_printerr (_("%s: %s"), g_get_application_name(), error->message);
      g_printerr ("\n");
      g_printerr (_("Try \"%s --help\" for more information."),
		  g_get_prgname ());
      g_printerr ("\n");
      g_error_free (error);
      g_option_context_free (context);
      return 1;
    }

  g_option_context_free (context);

  if (show_version)
    {
      g_print(PACKAGE_STRING "\n");
      return 0;
    }

  error = NULL;
  conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
  if (!conn)
    {
      g_printerr ("Failed to connect to the D-BUS daemon: %s (%s, %d)\n",
                  error->message, g_quark_to_string (error->domain), error->code);
      g_error_free (error);
      return 1;
    }

  tree_infos = g_hash_table_new_full (g_str_hash,
				      g_str_equal,
				      NULL,
				      (GDestroyNotify)tree_info_free);

  loop = g_main_loop_new (NULL, FALSE);
  g_dbus_connection_set_exit_on_close (conn, FALSE);
  g_signal_connect (conn, "closed", G_CALLBACK (on_connection_closed), loop);

  flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT;
  if (replace)
    flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE;

  skeleton = gvfs_metadata_skeleton_new ();

  g_signal_connect (skeleton, "handle-set", G_CALLBACK (handle_set), skeleton);
  g_signal_connect (skeleton, "handle-remove", G_CALLBACK (handle_remove), skeleton);
  g_signal_connect (skeleton, "handle-move", G_CALLBACK (handle_move), skeleton);
  g_signal_connect (skeleton, "handle-get-tree-from-device", G_CALLBACK (handle_get_tree_from_device), skeleton);

  error = NULL;
  if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton), conn,
                                         G_VFS_DBUS_METADATA_PATH, &error))
    {
      g_printerr ("Error exporting metadata daemon: %s (%s, %d)\n",
                  error->message, g_quark_to_string (error->domain), error->code);
      g_error_free (error);
      g_object_unref (conn);
      g_main_loop_unref (loop);
      return 1;
    }

  name_owner_id = g_bus_own_name_on_connection (conn,
                                                G_VFS_DBUS_METADATA_NAME,
                                                flags,
                                                NULL,
                                                on_name_lost,
                                                loop,
                                                NULL);
  
  g_main_loop_run (loop);
  
  if (skeleton)
    g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (skeleton));
  if (name_owner_id != 0)
    g_bus_unown_name (name_owner_id);
  if (conn)
    g_object_unref (conn);
  if (loop != NULL)
    g_main_loop_unref (loop);

  return 0;
}
示例#11
0
static void CAPeripheralStartEventLoop(void * data)
{
    CALEContext * const context = data;

    assert(context != NULL);

    // Create the event loop.
    GMainContext * const loop_context = g_main_context_new();
    GMainLoop * const event_loop = g_main_loop_new(loop_context, FALSE);

    g_main_context_push_thread_default(loop_context);

    // Acquire the bus name after exporting our D-Bus objects.
    guint const owner_id =
        g_bus_own_name_on_connection(context->connection,
                                     CA_DBUS_GATT_SERVICE_NAME,
                                     G_BUS_NAME_OWNER_FLAGS_NONE,
                                     CAPeripheralOnNameAcquired,
                                     CAPeripheralOnNameLost,
                                     NULL, // user_data,
                                     NULL);

    /**
     * Create proxies to the @c org.bluez.LEAdvertisingManager1 D-Bus
     * objects that will later be used to register the OIC LE
     * advertisement data.
     *
     * @todo Failure to retrieve the LE advertising managers is
     *       currently ignored.  We should propagate the failure to
     *       the thread that spawned this one.
     *
     * @note Retrieval of the @c org.bluez.LEAdvertisingManager1
     *       proxies must be done in a thread separate from the one
     *       that makes calls through those proxies since the
     *       underlying GDBusObjectManagerClient sets up signal
     *       subscriptions that are used when dispatching D-Bus method
     *       handling calls (e.g. property retrieval, etc).
     *       Otherwise, a distributed deadlock situation could occur
     *       if a synchronous D-Bus proxy call is made that causes the
     *       recipient (like BlueZ) to call back in to the thread that
     *       handles signals.  For example, registration of our LE
     *       advertisment with BlueZ causes BlueZ itself to make a
     *       call to our own @c org.bluez.LEAdvertisement1 object.
     *       However, the thread that initiated the advertisement
     *       registration is blocked waiting for BlueZ to respond, but
     *       BlueZ is blocked waiting for that same thread to respond
     *       to its own advertisement property retrieval call.
     */
    GList * advertising_managers = NULL;
    if (!CAGetBlueZManagedObjectProxies(
            &advertising_managers,
            BLUEZ_ADVERTISING_MANAGER_INTERFACE,
            context,
            NULL))
    {
        OIC_LOG(ERROR,
                TAG,
                "Failed to retrieve BlueZ LE advertising "
                "manager interface.");
    }

    ca_mutex_lock(g_context.lock);

    assert(g_context.event_loop == NULL);
    g_context.event_loop = event_loop;

    g_context.base = context;

    g_context.owner_id = owner_id;

    /**
     * Initialize all GATT services.
     *
     * @todo Failure to initialize the OIC GATT services is currently
     *       ignored.  We should propagate the failure to the thread
     *       that spawned this one.
     *
     * @note See the @c org.bluez.LEAdvertisingManager1 note above to
     *       understand why the GATT services must be initialized in
     *       a thread seperate from the one that initiates GATT
     *       service registration.
     */
    g_context.gatt_services = CAPeripheralInitializeGattServices(context);

    CALEAdvertisementInitialize(&g_context.advertisement,
                                context->connection,
                                advertising_managers);

    ca_mutex_unlock(g_context.lock);

    ca_cond_signal(g_context.condition);

    g_main_loop_run(event_loop);  // Blocks until loop is quit.

    /*
      Clean up in the same thread to avoid having to explicitly bump
      the ref count to retain ownership.
    */
    g_main_context_unref(loop_context);
    g_main_loop_unref(event_loop);
}
示例#12
0
文件: testgmenu.c 项目: 3v1n0/gtk
int
main (int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *box;
  GtkWidget *button;
  GtkWidget *tv;
  GtkWidget *buttons;
  MenuHolder *holder;
  GMenuModel *model;
  GActionGroup *group;
  GDBusConnection *bus;
  GError *error = NULL;
  gboolean do_export = FALSE;
  gboolean do_import = FALSE;
  GOptionEntry entries[] = {
    { "export", 0, 0, G_OPTION_ARG_NONE, &do_export, "Export actions and menus over D-Bus", NULL },
    { "import", 0, 0, G_OPTION_ARG_NONE, &do_import, "Use exported actions and menus", NULL },
    { NULL, }
  };

  gtk_init_with_args (&argc, &argv, NULL, entries, NULL, NULL);

  if (do_export && do_import)
    {
       g_error ("can't have it both ways\n");
       exit (1);
    }

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  g_signal_connect (window, "delete-event", G_CALLBACK(on_delete_event), NULL);
  box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
  gtk_container_add (GTK_CONTAINER (window), box);

  bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);

  if (do_import)
    {
      g_print ("Getting menus from the bus...\n");
      model = (GMenuModel*)g_dbus_menu_model_get (bus, BUS_NAME, OBJ_PATH);
      g_print ("Getting actions from the bus...\n");
      group = (GActionGroup*)g_dbus_action_group_get (bus, BUS_NAME, OBJ_PATH);
    }
  else
    {
      group = get_group ();
      model = get_model ();

      tv = create_action_treeview (group);
      gtk_container_add (GTK_CONTAINER (box), tv);
      buttons = create_add_remove_buttons (group, model, tv);
      gtk_container_add (GTK_CONTAINER (box), buttons);
    }

  if (do_export)
    {
      g_print ("Exporting menus on the bus...\n");
      if (!g_dbus_connection_export_menu_model (bus, OBJ_PATH, model, &error))
        {
          g_warning ("Menu export failed: %s", error->message);
          exit (1);
        }
      g_print ("Exporting actions on the bus...\n");
      if (!g_dbus_connection_export_action_group (bus, OBJ_PATH, group, &error))
        {
          g_warning ("Action export failed: %s", error->message);
          exit (1);
        }
      g_bus_own_name_on_connection (bus, BUS_NAME, 0, NULL, NULL, NULL, NULL);
    }
  else
    {
      holder = menu_holder_new (model, group);
      button = gtk_button_new_with_label ("Click here");
      g_signal_connect (button, "clicked",
                        G_CALLBACK (button_clicked), holder);
      gtk_container_add (GTK_CONTAINER (box), button);
    }

  gtk_widget_show_all (window);

  gtk_main ();

  return 0;
}
示例#13
0
gpointer dbusSvc_instanceThread(gpointer data)
{
   (void) data;
   /*
    * This is thread in which a GLIB "main" loop will run. The GLIB callback functionality is handled
    * and registered in this context.
    */

   GError *error=NULL;
   GMainLoop *loop;
   GDBusConnection *connection;
   guint id;

   // Add watches for needed DBUS interfaces here

   // Create a new GLIB context which will attach to this thread
   loop = g_main_loop_new(NULL, FALSE);

   if(dbusRemoteIP == NULL)
   {
      // We are using the local DBUS SYSTEM bus

      g_print("[dbusSvc_instanceThread] Local DBUS connection on SYSTEM bus\n");

      id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
                          DBUS_NAME,
                          G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | G_BUS_NAME_OWNER_FLAGS_REPLACE,
                          onBusAcquired,
                          onNameAcquired,
                          onNameLost,
                          loop,
                          NULL);
   }
   else
   {
      // We are using a remote connection to a target DBUS daemon
      gchar *remoteAddress;

      remoteAddress = g_strdup_printf("tcp:host=%s,port=%s",dbusRemoteIP,dbusRemotePort);

      g_print("[dbusSvc_instanceThread] Remote DBUS connection on: %s\n",remoteAddress);

      connection = g_dbus_connection_new_for_address_sync(remoteAddress,
                                                          G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION | G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
                                                          NULL,
                                                          NULL,
                                                          &error);

      g_free(remoteAddress);

      if (error != NULL)
      {
         /*
          * Critical error remote bus was not obtainable
          */
         g_print("[dbusSvc_instanceThread] Failed to get remote bus. DBUS services disabled\n");
         g_error_free(error);
      }
      else
      {

      onBusAcquired(connection,"Remote DBUS over TCP",NULL);

      id = g_bus_own_name_on_connection (connection,
                                    DBUS_NAME,
                                    G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | G_BUS_NAME_OWNER_FLAGS_REPLACE,
                                    onNameAcquired,
                                    onNameLost,
                                    loop,
                                    NULL);
      }

   }

   // Fire off the GLIB main loop. This will not return until the process is terminated.
   g_main_loop_run(loop);

   // Remove additional client watches here.


   // Release the DBUS name
   g_bus_unown_name(id);

   // Remove the DBUs watcher as we lost the connection anyways.
   dbusMesaInterface_removeDbusNameWatch();

   // Free the main loop object
   g_main_loop_unref(loop);
}
示例#14
0
bool_t mpris2_init (void)
{
    GError * error = NULL;
    bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, & error);

    if (! bus)
    {
        fprintf (stderr, "mpris2: %s\n", error->message);
        g_error_free (error);
        return FALSE;
    }

    g_bus_own_name_on_connection (bus, "org.mpris.MediaPlayer2.audacious", 0,
     NULL, NULL, NULL, NULL);

    object_core = (GObject *) mpris_media_player2_skeleton_new ();

    g_object_set (object_core,
     "can-quit", TRUE,
     "can-raise", TRUE,
     "desktop-entry", "audacious",
     "identity", "Audacious",
     NULL);

    g_signal_connect (object_core, "handle-quit", (GCallback) quit_cb, NULL);
    g_signal_connect (object_core, "handle-raise", (GCallback) raise_cb, NULL);

    object_player = (GObject *) mpris_media_player2_player_skeleton_new ();

    g_object_set (object_player,
     "can-control", TRUE,
     "can-go-next", TRUE,
     "can-go-previous", TRUE,
     "can-pause", TRUE,
     "can-play", TRUE,
     "can-seek", TRUE,
     NULL);

    update_timer = g_timeout_add (250, (GSourceFunc) update, object_player);
    update_playback_status (NULL, object_player);

    if (aud_drct_get_playing () && aud_drct_get_ready ())
        emit_seek (NULL, object_player);

    hook_associate ("playback begin", (HookFunction) update_playback_status, object_player);
    hook_associate ("playback pause", (HookFunction) update_playback_status, object_player);
    hook_associate ("playback stop", (HookFunction) update_playback_status, object_player);
    hook_associate ("playback unpause", (HookFunction) update_playback_status, object_player);

    hook_associate ("playlist set playing", (HookFunction) update_metadata, object_player);
    hook_associate ("playlist position", (HookFunction) update_metadata, object_player);
    hook_associate ("playlist update", (HookFunction) update_metadata, object_player);

    hook_associate ("playback ready", (HookFunction) emit_seek, object_player);
    hook_associate ("playback seek", (HookFunction) emit_seek, object_player);

    g_signal_connect (object_player, "handle-next", (GCallback) next_cb, NULL);
    g_signal_connect (object_player, "handle-pause", (GCallback) pause_cb, NULL);
    g_signal_connect (object_player, "handle-play", (GCallback) play_cb, NULL);
    g_signal_connect (object_player, "handle-play-pause", (GCallback) play_pause_cb, NULL);
    g_signal_connect (object_player, "handle-previous", (GCallback) previous_cb, NULL);
    g_signal_connect (object_player, "handle-seek", (GCallback) seek_cb, NULL);
    g_signal_connect (object_player, "handle-set-position", (GCallback) set_position_cb, NULL);
    g_signal_connect (object_player, "handle-stop", (GCallback) stop_cb, NULL);

    g_signal_connect (object_player, "notify::volume", (GCallback) volume_changed, NULL);

    if (! g_dbus_interface_skeleton_export ((GDBusInterfaceSkeleton *)
     object_core, bus, "/org/mpris/MediaPlayer2", & error) ||
     ! g_dbus_interface_skeleton_export ((GDBusInterfaceSkeleton *)
     object_player, bus, "/org/mpris/MediaPlayer2", & error))
    {
        mpris2_cleanup ();
        fprintf (stderr, "mpris2: %s\n", error->message);
        g_error_free (error);
        return FALSE;
    }

    return TRUE;
}