After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 626759 - Offer D-Bus API for gnome-shell to use
Offer D-Bus API for gnome-shell to use
Status: RESOLVED FIXED
Product: gnome-bluetooth
Classification: Core
Component: applet
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gnome-bluetooth-general-maint@gnome.bugs
gnome-bluetooth-general-maint@gnome.bugs
Depends on:
Blocks: 618312
 
 
Reported: 2010-08-12 17:55 UTC by Bastien Nocera
Modified: 2010-10-27 20:04 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Refactor bluetooth-applet as a library (45.22 KB, patch)
2010-09-10 15:48 UTC, Giovanni Campagna
none Details | Review
Refactor bluetooth-applet as a library (46.96 KB, patch)
2010-09-17 16:27 UTC, Giovanni Campagna
needs-work Details | Review
Fix introspection (13.52 KB, patch)
2010-09-29 19:48 UTC, Giovanni Campagna
none Details | Review
Refactor bluetooth-applet as a library (36.23 KB, patch)
2010-09-29 19:49 UTC, Giovanni Campagna
needs-work Details | Review
More fixes to introspection (2.98 KB, patch)
2010-10-05 15:08 UTC, Giovanni Campagna
committed Details | Review
Refactor bluetooth-applet as a library (35.57 KB, patch)
2010-10-05 18:43 UTC, Giovanni Campagna
committed Details | Review
Port bluetooth-applet to the new applet library (47.80 KB, patch)
2010-10-05 18:43 UTC, Giovanni Campagna
committed Details | Review

Description Bastien Nocera 2010-08-12 17:55:20 UTC
See http://live.gnome.org/GnomeShell/Design/Guidelines/SystemStatus/Bluetooth for details.

This is the current API being discussed:

Node: org.gnome.Bluetooth
 - node /org/gnome/Bluetooth
 - interface: org.gnome.Bluetooth

Methods:
    GetDevices () -> a{s(su)} - returns a dictionary of devices, keys are opaque identifiers, values are tuple with user facing name and a bit mask of capabilities (0x1: send file, 0x3: browse files, possibly others)
    InvokeAction (s device, u action) - invoke the action specified (it is the single capability bit) on the device - if device is empty, ask the user for one

Properties:
    Active: b - whether bluetooth is active or not
    Visible: b - whether this computer is visible
    GlobalCapabilities: u - capabilities globally supported by the adapter (should be shown in main menu)

Signals:
    DeviceListChanged () - reread device list
    PropertiesChanged (a{sv} property_new_values)
Comment 1 Bastien Nocera 2010-08-12 18:12:33 UTC
(In reply to comment #0)
> See http://live.gnome.org/GnomeShell/Design/Guidelines/SystemStatus/Bluetooth
> for details.
> 
> This is the current API being discussed:
> 
> Node: org.gnome.Bluetooth
>  - node /org/gnome/Bluetooth
>  - interface: org.gnome.Bluetooth
> 
> Methods:
>     GetDevices () -> a{s(su)} - returns a dictionary of devices, keys are
> opaque identifiers, values are tuple with user facing name and a bit mask of
> capabilities (0x1: send file, 0x3: browse files, possibly others)

You also need to have something mentioning whether the device is connected, connecting, or disconnecting, and show a menu item to connect or disconnect if it's relevant to that device (eg. it's relevant for mice and keyboards, but not for phones).

You can see a file list in applet/main.c:update_device_list(), look for the "if (action == NULL) {" condition. There are currently 5 additional menu items, not including the connection status, and "connect/disconnect" entries.

>     InvokeAction (s device, u action) - invoke the action specified (it is the
> single capability bit) on the device - if device is empty, ask the user for one

Add a mention that "device" is the Bluetooth address (bdaddr) of the device.

> Properties:
>     Active: b - whether bluetooth is active or not

This isn't good enough. See the various combinations possible in killswitch_state_changed() in the applet. You need to show when Bluetooth isn't available because of killswitches.

>     Visible: b - whether this computer is visible

Read-write property.

>     GlobalCapabilities: u - capabilities globally supported by the adapter
> (should be shown in main menu)

This would correspond to whether or not the "adapter-action-group" is shown, see applet/popup-menu.ui.

> Signals:
>     DeviceListChanged () - reread device list
>     PropertiesChanged (a{sv} property_new_values)

You're missing API to handle the pairing agent registration. This could potentially be implemented directly in gnome-shell, but I'd rather only the interaction be done in gnome-shell, to avoid leaking too much of Bluetooth implementation details into the shell itself.

There are 6 separate "pairing" requests that need to be handled (in UI) by the shell, before the answers are passed back to the applet.
Comment 2 Giovanni Campagna 2010-08-13 10:20:54 UTC
From discussion on that wiki page, I thought that you wanted to avoid a DBus API, since the applet is just presentation code.
In fact, with the right amount of introspection, rewriting the indicator in JS is straightforward, and could be cleaner and faster than using DBus (for one, you have one daemon less in every session).

Actually, it may be that the solution is to rewrite the indicator in JS, but keep it in the gnome-bluetooth tree, and sort of "dinamically load" it at startup.
(Just need to install it under $(datadir)/gnome-shell/js/ui/status)
Comment 3 Bastien Nocera 2010-08-13 10:34:23 UTC
(In reply to comment #2)
> From discussion on that wiki page, I thought that you wanted to avoid a DBus
> API, since the applet is just presentation code.

The applet isn't just presentation code, which is the problem. Most of it is presentation, the rest of it is tricky, and somewhat fragile working around the kernel and bluetoothd behaviours.

FWIW, we had the discussion with Owen on IRC yesterday.

> In fact, with the right amount of introspection, rewriting the indicator in JS
> is straightforward, and could be cleaner and faster than using DBus (for one,
> you have one daemon less in every session).

Except that you'd want me to make public things that I don't want public.

> Actually, it may be that the solution is to rewrite the indicator in JS, but
> keep it in the gnome-bluetooth tree, and sort of "dinamically load" it at
> startup.

If you want to rewrite it, don't expect me to help, writing it once, and then maintaining it is more than enough.

> (Just need to install it under $(datadir)/gnome-shell/js/ui/status)

Turns out I changed my mind. The whole point of the exercise is to avoid reimplementing all the work-arounds, and tricks that are in the applet. The D-Bus API would be minimal impact, and probably more straight forward to test without needing the shell (which means I'd be able to test it on more platforms as well).

If you're still interested in working on this, could you please make corrections to the D-Bus API?
Comment 4 Giovanni Campagna 2010-08-13 10:57:32 UTC
I see your points, and partly agree (it maybe that I haven't read the code enough)... so the DBus API needs to be:

Methods:

GetDevices() -> a{s(suu)}
returns dictionary from bdaddr to tuple with name, connected status (enumeration: 0 = disconnected, 1 = connected, 2 = connecting) and capability bit mask, whose values are
0x1: connect/disconnect
0x2: send to
0x4: browse file
0x8: open sound prefs
0x16: open keyboard prefs
0x32: open mouse prefs
(as you see, the API is designed around avoiding to expose the type of device)

InvokeAction(s bdaddr, u cap_bit)
as above

AuthResponse(s bdaddr, b success)
ConfirmResponse(s bdaddr, b success)
invoked after signal AuthRequest (resp. ConfirmRequest), to report the user selection

PinResponse(s bdaddr, s pin)
invoked after signal PinRequest, to give the PIN

Properties:

Visible: b - read/write
KillswitchStatus: u (enum with 0 = hard blocked, 1 = soft blocked, 2 = unblocked) - read/write (if not hard blocked)
GlobalCapabilities: u
I see that in current bluetooth applet it is all-or-nothing (and only obex), but it may be more future-proof to leave this as a bitmask

Signals:

DeviceListChanged()
PropertiesChanged(a{sv} new_values)

AuthRequest(s bdaddr, s name, s long_name)
ConfirmRequest(s bdaddr, s name, s long_name, s pin)
PinRequest(s bdaddr, s name, s long_name)
these expose the corresponding agent UI

AgentRequestCancelled(s bdaddr)
Comment 5 Giovanni Campagna 2010-08-13 10:59:58 UTC
Actually, I thought on this later... if gnome-bluetooth is running as a session daemon, it could implement the agents directly (they would use Gtk dialogs anyway), leaving only the status area indicator in the shell, and making the API cleaner and smaller.
Comment 6 Bastien Nocera 2010-08-13 11:05:04 UTC
(In reply to comment #5)
> Actually, I thought on this later... if gnome-bluetooth is running as a session
> daemon, it could implement the agents directly (they would use Gtk dialogs
> anyway), leaving only the status area indicator in the shell, and making the
> API cleaner and smaller.

That'd be the way until those are actually implemented in gnome-shell, as we want a different UI for system (non-application) dialogues (like the logout dialogue). See:
http://live.gnome.org/GnomeShell/Design/Whiteboards/SystemDialogs
Comment 7 Giovanni Campagna 2010-08-13 11:07:06 UTC
Good. In that case, it is better to implement the agents in the Shell from the start (and use stolen GtkBuilder files if we have nothing better)
Comment 8 Bastien Nocera 2010-08-13 11:11:23 UTC
(In reply to comment #7)
> Good. In that case, it is better to implement the agents in the Shell from the
> start (and use stolen GtkBuilder files if we have nothing better)

I think it would be better if the applet kept the smarts about that. There are a bunch of requests that we should handle internally without nagging the user. Just ignore that whole part for now, and I'll try to come up with something better in the future.

Just an example of the things we want to do in the agent:
- Handle keyboards and mice in a special way
- Provide better integration with PulseAudio for devices asking to play music back on the computer
- Disallow any access to a few services that we think should require pairing (eg. try accessing the computer's address book without being paired).
Comment 9 Giovanni Campagna 2010-08-20 10:02:22 UTC
Something I was thinking recently: another DBus server introduces a lot of overhead, placing itself between the shell and the BlueZ stack. And most of time, it would just propagate calls to the GnomeBluetooth library.
So, what about a GnomeBluetoothApplet private introspected library, exposing an API even more high-level than the proposed DBus?
Then both legacy bluetooth-applet and gnome-shell indicator could use the library to expose the bluetooth UI.
Comment 10 Bastien Nocera 2010-08-20 10:22:34 UTC
(In reply to comment #9)
> Something I was thinking recently: another DBus server introduces a lot of
> overhead, placing itself between the shell and the BlueZ stack. And most of
> time, it would just propagate calls to the GnomeBluetooth library.
> So, what about a GnomeBluetoothApplet private introspected library, exposing an
> API even more high-level than the proposed DBus?
> Then both legacy bluetooth-applet and gnome-shell indicator could use the
> library to expose the bluetooth UI.

I really don't see how you could implement that cleanly enough, but feel free to write the code and try it out for yourself. I still don't like the idea of exposing internals to the world, but I can I can make do with it.
Comment 11 Giovanni Campagna 2010-08-20 10:28:15 UTC
What world? The library would be private and privately introspected (like libmutterprivate or libshell, for example).
I'll try reorganizing bluetooth-applet, to see what I end up with.
Comment 12 Giovanni Campagna 2010-09-10 13:14:30 UTC
While reimplementing the agent for libgnome-bluetooth BluetoothApplet, I discovered that org.bluez.Agent.CancelRequest is inusable, since the method does not specify which device cancelled its request, thus the agent can't tell which request to cancel.

Also, the implementation is buggy, as it relies on the adapter path to be the key inside the input list, but adapter used is always the default one at method invocation time, not the default when making the request.
Consider the following:

1) device asks for pairing to Adapter One, which is the default
2) org.bluez.Agent.AuthRequest is called
3) input_data->path is set to "/org/bluez/<pid>/hci0", dialog is shown
4) mainloop in bluetooth-applet runs
5) default adapter changes, now is Adapter Two
6) default_adapter_changed() is called, changes BluetoothAgent->cancel_data to be the DBusGProxy for the new adapter
7) pairing request is cancelled
8) cancel_request() is called, with the DBusGProxy for Adapter Two
9) path is /org/bluez/<pid>/hci1, cannot be found in input_list
10) correct reply to org.bluez.Agent.AuthRequest is not given, memory is leaked
Comment 13 Giovanni Campagna 2010-09-10 13:15:50 UTC
I forgot to add, that for now I will just cancel any pending request upon org.bluez.Agent.CancelRequest(), and so should do the front end using the library.
Comment 14 Giovanni Campagna 2010-09-10 15:48:57 UTC
Created attachment 169962 [details] [review]
Refactor bluetooth-applet as a library

Turn all non UI components into an introspected BluetoothApplet class
in libgnome-bluetooth.la so that GNOME Shell can use it for the native
indicator.
Also, includes some modifications to make it work with latest gobject-
introspection (which is stricter wrt annotations and will (skip)
anything it is unsure about).
Comment 15 Giovanni Campagna 2010-09-17 16:27:35 UTC
Created attachment 170506 [details] [review]
Refactor bluetooth-applet as a library

Some bugs fixed, as I have now tested it with a the corresponding Shell part.
Comment 16 Bastien Nocera 2010-09-20 16:29:25 UTC
Review of attachment 170506 [details] [review]:

I don't want to see the applet's code exported in the main library for 3rd-party apps developers.

I'll review the applet code separately, but starting with using C-style comments, and not C++ style would be good.

The generic introspection fixes should also be separated from the main patch.

::: configure.ac
@@ +190,3 @@
 AC_SUBST(GLIB_GENMARSHAL)
 
+GOBJECT_INTROSPECTION_CHECK([0.9.5])

Is 0.9.3 not enough?

::: lib/Makefile.am
@@ +64,3 @@
 	bluetooth-enums.h				\
+	bluetooth-plugin.h				\
+	applet/bluetooth-applet.h

I'd rather the applet code was either separate. It would statically link against libgnome-bluetooth.la, as is currently done, so that private functions are only accessed from within the applet library's code.

::: lib/bluetooth-chooser-button.h
@@ +32,3 @@
 typedef struct _BluetoothChooserButton BluetoothChooserButton;
 
+typedef struct _BluetoothChooserButtonClass BluetoothChooserButtonClass;

Could you please make those changes separately?

::: lib/bluetooth-client.h
@@ +81,3 @@
+					      const char *device,
+					      BluetoothClientConnectFunc func,
+					      gpointer data);

Why is all of this necessary? We try hard not to leak implementation details to application writers.

::: lib/marshal.list
@@ +6,3 @@
 VOID:STRING,STRING,STRING
+
+#for the applet

As I mentioned, I'd rather the applet library be separate.
Comment 17 Giovanni Campagna 2010-09-29 19:48:45 UTC
Created attachment 171357 [details] [review]
Fix introspection

Fix generation of .gir files to work with latest gobject-introspection,
including annotations where necessary.
Comment 18 Giovanni Campagna 2010-09-29 19:49:08 UTC
Created attachment 171358 [details] [review]
Refactor bluetooth-applet as a library

Take out non UI parts of bluetooth-applet and put them in a private
library, which will be used by gnome-shell (and therefore is installed
in gnome-shell private prefix).
Comment 19 Bastien Nocera 2010-10-04 11:01:21 UTC
(In reply to comment #17)
> Created an attachment (id=171357) [details] [review]
> Fix introspection

Some of those fixes were already in bug 630024, which I just merged.
Comment 20 Bastien Nocera 2010-10-04 11:08:34 UTC
Fixed up and committed, let me know if I made any mistakes in the merge.

commit fd89195dc3173b37e35299b07e673b3ec0253647
Author: Giovanni Campagna <scampa.giovanni@gmail.com>
Date:   Sun Sep 26 17:47:13 2010 +0200

    Fix introspection
    
    Fix generation of .gir files to work with latest gobject-introspection,
    including annotations where necessary.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=626759

Could you make another patch to avoid trying to create bindings for the plugin system. It only supports C language plugins.

bluetooth-plugin.h:16: Warning: GnomeBluetooth: symbol='GbtPluginInfo': Skipping foreign identifier 'GbtPluginInfo' from namespace GObject
bluetooth-plugin.h:17: Warning: GnomeBluetooth: symbol='GbtPlugin': Skipping foreign identifier 'GbtPlugin' from namespace GObject
<unknown>:: Warning: GnomeBluetooth: Skipping foreign identifier 'GbtPluginInfo' from namespace GObject
<unknown>:: Warning: GnomeBluetooth: Skipping foreign identifier 'GbtPlugin' from namespace GObject
Comment 21 Bastien Nocera 2010-10-04 11:12:54 UTC
Review of attachment 171358 [details] [review]:

I'd rather the library lived in applet/ along with the applet.

Any reasons the applet itself isn't using the new applet library code?

::: .gitignore
@@ +51,1 @@
 applet/test-agentdialog

Why remove applet/bluetooth-applet.desktop.in from the .gitignore?

::: lib/Makefile.am
@@ -40,3 @@
 	gnome-bluetooth-enum-types.h	\
 	bluetooth-chooser-private.h
-EXTRA_DIST += $(libgnome_bluetooth_private_headers)

Should this be made as a separate patch, along with the rest of the introspection fixes?
Comment 22 Giovanni Campagna 2010-10-05 15:08:07 UTC
Created attachment 171774 [details] [review]
More fixes to introspection
Comment 23 Bastien Nocera 2010-10-05 15:22:04 UTC
Comment on attachment 171774 [details] [review]
More fixes to introspection

Committed after fixing the white space problems.
Comment 24 Giovanni Campagna 2010-10-05 18:43:14 UTC
Created attachment 171783 [details] [review]
Refactor bluetooth-applet as a library

Minor fixes
Comment 25 Giovanni Campagna 2010-10-05 18:43:42 UTC
Created attachment 171784 [details] [review]
Port bluetooth-applet to the new applet library

Refactor the existing standalone bluetooth-applet to use the applet
library just introduced, to reduce duplicated code and make it easier
to test and fix the library itself.
Comment 26 Bastien Nocera 2010-10-08 16:15:08 UTC
The patches are unreviewable as-is. You pretty much rewrote the applet, but the flow of original code isn't so visible.

I'll take me a little while to unpick the changes you made, and see whether they work as expected.
Comment 27 Bastien Nocera 2010-10-27 20:04:13 UTC
I found quite a few bugs on top of the existing code. Take a look at the commits in gnome-bluetooth master.

I expect to find similar niggles elsewhere, and I'll probably change a few APIs as I get more time to review the code (especially the agents dialogue, as discussed on IRC).

Thanks for working on this though, much appreciated.

Attachment 171783 [details] pushed as 1838f07 - Refactor bluetooth-applet as a library
Attachment 171784 [details] pushed as c7b48a3 - Port bluetooth-applet to the new applet library