App Developer Week -- Take control of your desktop easily with DBus -- alecu -- Wed, Apr 13th, 2011
1 [18:56] <alecu> hello all 2 [18:56] <ClassBot> There are 5 minutes remaining in the current session. 3 [18:56] <alecu> let's wait a couple more minutes and then we'll start 4 [18:58] <ClassBot> chadadavis asked: What's the best way to stay up to date on the API documentation status? 5 [18:58] <aquarius> chadadavis, watch the U1 blog where we'll announce that the developer site is available 6 [19:01] <alecu> hello all 7 === ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - https://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Questions in #ubuntu-classroom-chat || Event: Ubuntu App Developer Week - Current Session: Take control of your desktop easily with DBus - Instructors: alecu 8 [19:01] <alecu> My name is alecu, some people also call me "Alejandro J. Cura" 9 [19:01] <ClassBot> Logs for this session will be available at http://irclogs.ubuntu.com/2011/04/13/%23ubuntu-classroom.html following the conclusion of the session. 10 [19:02] <alecu> I'm a developer on the Ubuntu One team, currently working on the desktop side of Ubuntu One. 11 [19:03] <alecu> For the past year or so I've been using DBus a lot to do bits and pieces of my work, so I'd like to share a bit of that during this session. 12 [19:03] <alecu> As you all probably know, DBus is a way for applications to request services from other applications. 13 [19:04] <alecu> For instance, Ubuntu One asks the gnome-keyring daemon for passwords. 14 [19:04] <alecu> Or the sound menu asks the music players to start playing or to change tracks. 15 [19:04] <alecu> so, let's dive into an example... 16 [19:04] <alecu> for this we need to have d-feet installed 17 [19:05] <alecu> sudo apt-get install d-feet 18 [19:05] <alecu> so, everybody has d-feet installed by now? 19 [19:06] <alecu> open it, and let's browse the Dbus bus a bit 20 [19:06] <alecu> go to File -> Connect to Session 21 [19:06] <alecu> and we will be able to explore the Session Bus 22 [19:07] <alecu> on the left we have a list of Bus Names. It's common for each application that's providing a service to use one, but some apps export more than one Bus Name. 23 [19:07] <alecu> clicking on one of the Bus Names, we'll see a list of Object Paths on the right 24 [19:08] <alecu> it's very common for one application to export more than one Object Path 25 [19:09] <alecu> if you click on one Bus Name and no object paths appear, that means that the application is not providing introspection data, and that means that we'll need to ask the app developers for more info on how to use those services thru dbus. 26 [19:09] <alecu> but the common case is to have both introspection data and some dbus documentation... 27 [19:10] <alecu> let's look at one example 28 [19:10] <alecu> let's open banshee, or some rhythmbox 29 [19:11] <alecu> when we run banshee, we'll see on d-feet that a new "Bus Name" was published to provide services to other apps 30 [19:11] <alecu> try clicking on d-feet on it: org.bansheeproject.Banshee 31 [19:12] <alecu> on the right hand we'll see a few Object Paths 32 [19:12] <alecu> let's open /org/mpris/MediaPlayer2 33 [19:12] <alecu> and open the "org.mpris.MediaPlayer2.Player" interface 34 === kevin4896 is now known as kdemarest 35 [19:13] <alecu> Inside that interface we'll see a list of Methods, Properties and Signals 36 === tubadaz is now known as tubadaz_away 37 [19:13] <alecu> let's try one Method: play 38 [19:13] <alecu> sorry, Play() 39 [19:14] <alecu> double click on it, and a new small window opens "Execute D-Bus Method" 40 [19:14] <alecu> just click on Execute 41 [19:14] <alecu> banshee should start playing 42 [19:15] <alecu> (if it does not, try making it play some song by hand, then pausing it thru d-feet) 43 [19:17] <alecu> and then try playing with the other methods 44 [19:17] <alecu> for instance, Seek takes a parameter, try 30000000 45 [19:18] <alecu> or -30000000 46 [19:18] <ClassBot> chadadavis asked: there are a few 'play' methods under other object paths. Why are there so many? What's the difference, in the case of banshee here? 47 [19:18] <alecu> chadadavis, you mean Play and PlayPause? 48 [19:19] <alecu> I think Play always plays, but PlayPause is like a toggle. 49 [19:19] <alecu> chadadavis, the thing is that I don't know exactly how that works, and since it won't be documented in a DBus browser like d-feet we need to find some spec 50 [19:20] <alecu> and I was just pointing all of you to this example, because there's a lovely documentation for this interface, and it's common to many-many media players. 51 [19:21] <alecu> it's http://xmms2.org/wiki/MPRIS 52 [19:22] <alecu> and for the work I've been doing for the gnome-keyring and kwallet, I've been using the "Secrets Service API" http://people.collabora.co.uk/~stefw/secret-service/ 53 === tubadaz_away is now known as tubadaz 54 [19:23] <alecu> so you'll probably need some similar docs for the service you are trying to use 55 [19:23] <alecu> or just use an explorer like d-feet to experiment with the interface you want. 56 [19:24] <alecu> So, after finding some service that you want to use, and some docs on it, you'll want to use DBus from your own application. 57 [19:24] <alecu> I've mostly used python for this, but I understand that other bindings are similar. 58 [19:25] <alecu> Here's a few examples I've made, so we can go over: 59 [19:25] <alecu> bzr branch lp:~alecu/+junk/dbus-lessons 60 [19:26] <ClassBot> crazedpsyc asked: if credentials are transported through DBus, can't I, or anyone else see them by using something like dbus-monitor? 61 [19:27] <alecu> crazedpsyc, there is one instance of DBus running for the system, and an instance per user that's logged in. 62 [19:28] <alecu> crazedpsyc, DBus connections are always local, and are either in the context of your computer or your session. 63 [19:28] <alecu> crazedpsyc, there are security rules on the system DBus, so apps are limited on what they can listen to. 64 [19:29] <alecu> crazedpsyc, for the session DBus I haven't seen any security restrictions, so afaict any app can listen for all the Dbus traffic for every other app. 65 [19:30] <alecu> crazedpsyc, that includes listening for the same logged in user credentials, but any X window app can capture all keystrokes anyway, so there's no point in securing that. 66 [19:30] <alecu> crazedpsyc, makes sense? 67 [19:31] <alecu> crazedpsyc, we can discuss this on much detail later, since app sandboxing is an issue I find very interesting to work on. 68 [19:32] <alecu> anyway, let's go back to the samples 69 [19:32] <alecu> let's look at the first one: 01-call_method.py 70 [19:34] <alecu> DBus usually has to work together with the main loop of your application 71 [19:34] <alecu> usually it's the gtk or kde main loop, and DBus supports it. 72 [19:34] <alecu> But you can also use the twisted reactor as a main loop, and we'll be able to integrate that as well. 73 [19:35] <alecu> in this example I'm using the gobject main loop, as used by gtk. 74 [19:35] <alecu> this line joins dbus with the loop: "DBusGMainLoop(set_as_default=True)" 75 [19:36] <alecu> and on the following lines we get at the "Session Bus", get an object from it using a "Bus Name" and an "Object Path" 76 [19:36] <alecu> and we get an "Interface" from that object. 77 [19:36] <alecu> as you can see, it all matches what we are able to see on d-feet. 78 [19:37] <alecu> once we get an Interface, we can call on the Methods on it, and access its Properties 79 [19:38] <alecu> in this example I'm just changing the brightness of my laptop display, and depending on your hardware it might not work. 80 [19:38] <alecu> So I'll ask you all for homework to modify it so it changes the volume of the music player. 81 [19:39] <ClassBot> psusi asked: What is the use of naming the Interface of an object separtely from the name of the object itself? Can this be used to publish versioned interfaces to, for instance, add a new argument to a signal without breaking applications that depend on the interface without the argument? 82 [19:41] <alecu> psusi, exactly. We can add more than one interface for an object, to group interfaces per intent, so for instance the MPRIS spec separates the methods in the Player from the Playlist interfaces, and also as you very correctly point out to create a new interface and not break compatibility with older interfaces. 83 [19:42] <alecu> Ok, let's look a bit further into arguments for the Methods 84 === crazedpsyc is now known as crazedpsyc_away 85 [19:43] <alecu> since DBus is language agnostic, it defines a way to specify the types of the arguments and return values of DBus Methods 86 [19:44] <alecu> each language binding will try to match it to native types. For instance the python binding will usually transform DBus byte arrays into python strings 87 [19:44] <alecu> (python 2 strings, that is :-) ) 88 [19:45] <alecu> so Dbus has a way of specifying a small string that will act as the signature for the types in a DBus method call 89 === crazedpsyc_away is now known as crazedpsyc 90 [19:47] <alecu> for instance let's browse with d-feet the org.mpris.MediaPlayer2.Playlists interface 91 [19:47] <alecu> the GetPlaylists method has a very complicated signature 92 [19:47] <alecu> Uint32 index, Uint32 maxcount, String order, Boolean reverse_order 93 [19:48] <alecu> in dbus you'll usually see this as "uusb" 94 [19:49] <alecu> and the return value for that method is array of [struct of (object path, string, string)] 95 [19:49] <alecu> you'll see it defined as "a(oss)" 96 [19:50] <alecu> for a complete reference of this, and much more, try this tutorial: http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#data-types 97 [19:50] <alecu> we'll need to define strings similar to this when we export our own objects on DBus as services 98 [19:51] <alecu> so let's look at example 03-export_object.py 99 [19:51] <ClassBot> There are 10 minutes remaining in the current session. 100 [19:52] <alecu> in this example I'm exporting a DBus object on a given "Bus Name" and with a given "Object Path" 101 [19:52] <alecu> and when I run the example, I can use d-feet to call the example_method. Go ahead, try it. 102 [19:53] <alecu> In addition to the Method, I'm also exporting a "Signal" 103 [19:53] <alecu> Signals work backwards 104 [19:54] <alecu> Usually a dbus client calls a method. 105 [19:54] <alecu> But the clients subscribe to signals, and the dbus service calls them. 106 [19:54] <alecu> We can see how to subscribe to a signal in example 2 107 [19:55] <alecu> in 02-listen_signal.py we connect to the bus, and using a "Bus Name", an "Object Path" and an "Interface", we connect a function of our code to a DBus signal. 108 [19:56] <ClassBot> There are 5 minutes remaining in the current session. 109 [19:56] <alecu> in this example I also use the BackLight, but as homework as well you may change listen to media player signals as well. 110 [19:57] <alecu> ok, this was a brief overview of how to use DBus in your code. 111 [19:57] <alecu> I hope you follow the examples and start using DBus to take control of all the apps in your desktop. 112 [19:58] <alecu> Let's do a bit of Q/A if we have a bit more time. 113 [19:58] <alecu> And don't hesitate to ask me more questions by mail if you have any problems when working with DBus. 114 [20:00] <alecu> and please let me know what you ended up doing with DBus! :-) 115 [20:01] <ClassBot> chadadavis asked: so, when you setup a signal for others to subscribe to, you're responsible for sending them? Can you chain signals, with intermediate changes, to provide variations of existing signals from other services?