mvidner-ruby-dbus 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/NEWS ADDED
@@ -0,0 +1,55 @@
1
+ = Ruby D-Bus NEWS
2
+
3
+ == Ruby D-Bus 0.2.10 - 2009-09-10
4
+
5
+ Bug fixes:
6
+
7
+ * DBus::Service.exists? fixed (Murat Demirten).
8
+ * Ruby 1.9 fixes (Jedediah Smith).
9
+ * Fixed an endless sleep in DBus::Main.run (bnc#537401).
10
+ * Added details to PacketMarshaller exceptions (bnc#538050).
11
+
12
+ (bnc#FOO refers to https://bugzilla.novell.com/show_bug.cgi?id=FOO )
13
+
14
+ == Ruby D-Bus "I'm not dead" 0.2.9 - 2009-08-26
15
+
16
+ Thank you to Paul and Arnaud for starting the project. I, Martin
17
+ Vidner, am continuing with it on GitHub.
18
+
19
+ * Fixed passing an array through a variant (no ticket).
20
+ * Fixed marshalling "av" (Ticket #30).
21
+ * Fixed variant alignment (Ticket #27).
22
+ * Added DBus::Main.quit.
23
+ * Mention the DBus interface in a NameError for an unknown method.
24
+ * Fixed ruby-1.9 "warning: default `to_a' will be obsolete".
25
+ * Added Rakefile and gemspec.
26
+
27
+ == Ruby D-Bus "Thanks for all the fish" 0.2.1 - 2007-12-29
28
+
29
+ More bugfixes, mostly supplied by users supplying us with patches. Thanks!
30
+
31
+ * Support for new types added:
32
+ - dict (courtesy of Drake Wilson);
33
+ - double (courtesy of Patrick Sissons);
34
+ - variant.
35
+ * Improved exception raise support (courtesy of Sjoerd Simons,
36
+ Patrick Sissons).
37
+ * Some polish (removed debug output, solved unnecessary warnings).
38
+ * Documentation updates, example fixes and updates.
39
+
40
+ == Ruby D-Bus "Almost live from DebConf 7" 0.2.0 - 2007-06-02
41
+
42
+ Again a bugfix release, also meant to be the public release
43
+ for exploratory purposes. New in 0.2.0:
44
+
45
+ * Complete tutorial revamp.
46
+ * Relicensed to the LGPL.
47
+
48
+ == Ruby D-Bus "Release Often" 0.1.1 - 2007-04-23
49
+
50
+ Bugfix release. Fixes hardcoded string for requesting bus names,
51
+ found by Rudi Cilibrasi.
52
+
53
+ == Ruby D-Bus "Happy Birthday Paul" 0.1.0 - 2007-04-17
54
+
55
+ First release. Supports most of D-Bus' features.
data/README ADDED
@@ -0,0 +1,53 @@
1
+ = Ruby D-Bus README
2
+
3
+ Ruby D-Bus provides an implementation of the D-Bus protocol such that the
4
+ D-Bus system can be used in the Ruby programming language.
5
+
6
+ == Requirements
7
+
8
+ * Ruby 1.8 (>= 1.8.6?)
9
+
10
+ Optionally, for generating the tutorial:
11
+ * Webgen (>= 0.4)
12
+
13
+ == Installation
14
+
15
+ 1. Decompress the Ruby D-Bus tarball (ruby-dbus-<version>.tar.gz).
16
+ 2. Move to top-level directory and type:
17
+
18
+ $ ruby setup.rb config
19
+ $ ruby setup.rb setup
20
+ ($ su)
21
+ # ruby setup.rb install
22
+
23
+ You can also install files in your favorite directory by
24
+ supplying setup.rb some options. Try "ruby setup.rb --help".
25
+
26
+ == Feature
27
+
28
+ Ruby D-Bus currently supports the following features:
29
+
30
+ * Connecting to local buses.
31
+ * Accessing remote services, objects and interfaces.
32
+ * Invoking methods on remote objects synchronously and asynchronously.
33
+ * Catch signals on remote objects and handle them via callbacks.
34
+ * Remote object introspection.
35
+ * Walking object trees.
36
+ * Creating services and registering them on the bus.
37
+ * Exporting objects with interfaces on a bus for remote use.
38
+ * Rubyish D-Bus object and interface syntax support that automatically
39
+ allows for introspection.
40
+ * Emitting signals on exported objects.
41
+
42
+ == Usage
43
+
44
+ See some of the examples in the examples/ subdirectory of the tarball.
45
+ Also, check out the included tutorial (in Webgen format) in doc/tutorial/
46
+ or view it online on http://trac.luon.net/data/ruby-dbus/tutorial/.
47
+
48
+ == License
49
+
50
+ Ruby D-Bus is free software; you can redistribute it and/or modify it
51
+ under the terms of the GNU Lesser General Public License as published by the
52
+ Free Software Foundation; either version 2.1 of the License, or (at
53
+ your option) any later version.
@@ -0,0 +1,12 @@
1
+ ---
2
+ title: Welcome
3
+ inMenu: true
4
+ directoryName: Start
5
+ ---
6
+
7
+ h2. Welcome!
8
+
9
+ This is the Ruby D-Bus tutorial. It aims to show you the features of Ruby
10
+ D-Bus and as you read through the tutorial also how to use them.
11
+
12
+ Please proceed to the "Introduction":intro.html.
@@ -0,0 +1,127 @@
1
+ ---
2
+ title: Introduction
3
+ inMenu: true
4
+ ---
5
+
6
+ This is a tutorial for Ruby D-Bus, a library to access D-Bus facilities of your
7
+ system. This chapter has the following sections:
8
+
9
+ # "What is D-Bus?":#what-is
10
+ # "Definitions":#def
11
+ ## "Client":#def-client
12
+ ## "Service":#def-service
13
+ ## "Object path":#def-obj-path
14
+ ## "Interface":#def-iface
15
+ ## "Method":#def-method
16
+ ## "Signal":#def-signal
17
+ ## "Message":#def-message
18
+ ## "Signature":#def-sig
19
+
20
+ h2(#what-is). What is D-Bus?
21
+
22
+ D-Bus is an RPC(Remote Procedure Call) protocol. A common setup can have
23
+ multiple D-Bus daemons running that route procedure calls and signals in
24
+ the form of messages. Each of these daemons supports a bus. A bus that
25
+ is often used by modern desktop environments, and is available per session, is
26
+ called the _session bus_. Another bus that can be available, but in a
27
+ system-wide manner, is called the _system bus_. It is used for example by
28
+ the "Hardware Abstraction Layer":http://hal.freedesktop.org/ daemon. Note
29
+ that theoretically the D-Bus RPC protocol can be used without a system or
30
+ session bus. I never came across any actual use of this though.
31
+
32
+ At the desktop level, D-Bus allows some components to interact. Typically
33
+ if you are writing an application or a personal script that wants to
34
+ interact with your web browser, your music player, or that simply wants to
35
+ pop-up a desktop notification, D-Bus comes into play.
36
+
37
+ At the system level, the Hardware Abstraction Layer is a privileged daemon
38
+ that notifies other software of hardware activities. Typically, if you
39
+ want to be notified if a CD-ROM has been loaded in, of if you want to
40
+ explore hardware, the system daemon comes into play.
41
+
42
+ The D-Bus RPC system is as we will see _object oriented_.
43
+
44
+ Buses provide access to _services_ provided in turn by running or ready to
45
+ run processes. Let me introduce some D-Bus terminology before we discuss
46
+ the API of Ruby D-Bus.
47
+
48
+ h2(#def). Definitions
49
+
50
+ h3(#def-client). Client
51
+
52
+ A D-Bus client is a process that connects to a D-Bus. They issue method
53
+ calls and register to the bus for signals and events.
54
+
55
+ h3(#def-service). Service
56
+
57
+ A connected client can export some of its objects and let other clients
58
+ call some of its methods. Such clients typically register a special name
59
+ like @org.freedesktop.Notifications@, the service name.
60
+
61
+ There is slightly different type of service. They are provided by
62
+ processes that can be launched by a D-Bus daemon on demand. Once they are
63
+ started by D-Bus they register a service name and behave like another
64
+ client.
65
+
66
+ Note that the buses themselves provide the @org.freedesktop.DBus@ service,
67
+ and provide some features through it.
68
+
69
+ h3(#def-obj-path). Object path
70
+
71
+ An object path is the D-Bus way to specify an object _instance_ address. A
72
+ service can provide different object instances to the outside world, so
73
+ that external processes can call methods on each of them. An object path
74
+ is an address of an instance in a very similar way that the path is an
75
+ address of a file on a file system. For example:
76
+ @/org/freedesktop/Notification@ is an object path of an object provided by
77
+ the @org.freedesktop.Notification@ service
78
+
79
+ *Beware*: service names and object paths can, but do _not_ have to be
80
+ related! You'll probably encounter a lot of cases though, where the
81
+ object path is a slashed version of the dotted service name.
82
+
83
+ h3(#def-iface). Interface
84
+
85
+ Classically in an object model, classes can implement interfaces. That is,
86
+ some method definitions grouped in an interface. This is exactly what a
87
+ D-Bus interface is as well. In D-Bus interfaces have names. These names must be
88
+ specified on method calls.
89
+
90
+ The @org.freedesktop.Notification@ service provides an object instance
91
+ called @/org/freedesktop/Notification@. This instance object implements an
92
+ interface called @org.freedesktop.Notifications@. It also provides two
93
+ special D-Bus specific interfaces: @org.freedesktop.DBus.Introspect@ and
94
+ @org.freedesktop.DBus.Properties@. Again, object paths, service names,
95
+ and interface names can be related but do not have to be.
96
+
97
+ Basically the @org.freedesktop.DBus.Introspect@ has an @Introspect@ method,
98
+ that returns XML data describing the @/org/freedesktop/Notification@ object
99
+ interfaces. This is used heavily internally by Ruby D-Bus.
100
+
101
+ h3(#def-method). Method
102
+
103
+ A method is, well, a method in the classical meaning. It's a function that
104
+ is called in the context of an object instance. Methods have typed
105
+ parameters and return typed return values.
106
+
107
+ h3(#def-signal). Signal
108
+
109
+ Signals are simplified method calls that do not have a return value. They
110
+ do have typed parameters though.
111
+
112
+ h3(#def-message). Message
113
+
114
+ Method calls, method returns, signals, errors: all are encoded as D-Bus
115
+ messages sent over a bus. They are made of a packet header with source and
116
+ destination address, a type (method call, method reply, signal) and the
117
+ body containing the parameters (for signals and method calls) or the return
118
+ values (for a method return message).
119
+
120
+ h3(#def-sig). Signature
121
+
122
+ Because D-Bus is typed and dynamic, each message comes with a signature that
123
+ describes the types of the data that is contained within the message. The
124
+ signature is a string with an extremely basic language that only describes
125
+ a data type. You will need to have some knowledge of what a signature
126
+ looks like if you are setting up a service. If you are just programming a
127
+ D-Bus client, you can live without knowing about them.
@@ -0,0 +1,174 @@
1
+ ---
2
+ title: Client Usage
3
+ inMenu: true
4
+ ---
5
+
6
+ This chapter discusses basic client usage and has the following topics:
7
+
8
+ # "Using the library":#loading
9
+ # "Connecting to a bus":#connecting
10
+ # "Performing method calls":#method-call
11
+ ## "Introspection":#method-call--introspection
12
+ # "Calling a method asynchronously":#method-call-async
13
+ # "Waiting for a signal":#signal-wait
14
+ # "More about introspection":#introspection
15
+ ## "Walking the object tree":#introspection--tree
16
+
17
+ h2(#loading). Using the library
18
+
19
+ If you want to use the library, you have to make Ruby load it by issuing:
20
+
21
+ require 'dbus'
22
+
23
+ That's all! Now we can move on to really using it...
24
+
25
+ h2(#connecting). Connecting to a bus
26
+
27
+ On a typical system, two buses are running, the system bus and the session
28
+ bus. The system bus can be accessed by:
29
+
30
+ bus = DBus::SystemBus.instance
31
+
32
+ Probably you already have guessed how to access the session bus. This
33
+ can be done by:
34
+
35
+ bus = DBus::SessionBus.instance
36
+
37
+ h2(#method-call). Performing method calls
38
+
39
+ Let me continue this example using the session bus. Let's say that I want
40
+ to access an object of some client on the session bus. This particular
41
+ D-Bus client provides a service called @org.gnome.Rhythmbox@. Let me
42
+ access this service:
43
+
44
+ rb_service = bus.service("org.gnome.Rhythmbox")
45
+
46
+ In this example I access the @org.gnome.Rhythmbox@ service, which is
47
+ provided by the application
48
+ "Rhythmbox":http://www.gnome.org/projects/rhythmbox/.
49
+ OK, I have a service handle now, and I know that it exports the object
50
+ "/org/gnome/Rhythmbox/Player". I will trivially access this remote object
51
+ using:
52
+
53
+ rb_player = rb_service.object("/org/gnome/Rhythmbox/Player")
54
+
55
+ h3(#method-call--introspection). Introspection
56
+
57
+ Well, that was easy. Let's say that I know that this particular object is
58
+ introspectable. In real life most of them are. The @rb_object@ object we
59
+ have here is just a handle of a remote object, in general they are called
60
+ _proxy objects_, because they are the local handle of a remote object. It
61
+ would be nice to be able to make it have methods, and that its methods send
62
+ a D-Bus call to remotely execute the actual method in another process.
63
+ Well, instating these methods for a _introspectable_ object is trivial:
64
+
65
+ rb_player.introspect
66
+
67
+ And there you go. Note that not all services or objects can be
68
+ introspected, therefore you have to do this manually! Let me remind you
69
+ that objects in D-Bus have interfaces and interfaces have methods. Let's
70
+ now access these methods:
71
+
72
+ rb_player_iface = rb_player["org.gnome.Rhythmbox.Player"]
73
+ puts rb_player_iface.getPlayingUri
74
+
75
+ As you can see, when you want to call a method on an instance object, you have
76
+ to get the correct interface. It is a bit tedious, so we have the following
77
+ shortcut that does the same thing as before:
78
+
79
+ rb_player.default_iface = "org.gnome.Rhythmbox.Player"
80
+ puts rb_player.getPlayingUri
81
+
82
+ The @default_iface=@ call specifies the default interface that should be
83
+ used when non existing methods are called directly on a proxy object, and
84
+ not on one of its interfaces.
85
+
86
+ Note that the bus itself has a corresponding introspectable object. You can
87
+ access it with @bus.proxy@ method. For example, you can retrieve an array of
88
+ exported service names of a bus like this:
89
+
90
+ bus.proxy.ListNames[0]
91
+
92
+ h2(#method-call-async). Calling a method asynchronously
93
+
94
+ D-Bus is _asynchronous_. This means that you do not have to wait for a
95
+ reply when you send a message. When you call a remote method that takes a
96
+ lot of time to process remotely, you don't want your application to hang,
97
+ right? Well the asychronousness exists for this reason. What if you dont'
98
+ want to wait for the return value of a method, but still you want to take
99
+ some action when you receive it?
100
+
101
+ There is a classical method to program this event-driven mechanism. You do
102
+ some computation, perform some method call, and at the same time you setup
103
+ a callback that will be triggered once you receive a reply. Then you run a
104
+ main loop that is responsible to call the callbacks properly. Here is how
105
+ you do it:
106
+
107
+ rb_player.getPlayingUri do |resp|
108
+ puts "The playing URI is #{resp}"
109
+ end
110
+ puts "See, I'm not waiting!"
111
+ loop = DBus::Main.new
112
+ loop << bus
113
+ loop.run
114
+
115
+ This code will print the following:
116
+
117
+ See, I'm not waiting!
118
+ The playing URI is file:///music/papapingoin.mp3
119
+
120
+ h2(#signal-wait). Waiting for a signal
121
+
122
+ Signals are calls from the remote object to your program. As a client, you
123
+ set yourself up to receive a signal and handle it with a callback. Then running
124
+ the main loop triggers the callback. You can register a callback handler
125
+ as allows:
126
+
127
+ rb_player.on_signal("elapsedChanged") do |u|
128
+ puts u
129
+ end
130
+
131
+ h2(#introspection). More about introspection
132
+
133
+ There are various ways to inspect a remote service. You can simply call
134
+ @Introspect()@ and read the XML output. However, in this tutorial I assume
135
+ that you want to do it using the Ruby D-Bus API.
136
+
137
+ Notice that you can introspect a service, and not only objects:
138
+
139
+ rb_service = bus.service("org.gnome.Rhythmbox")
140
+ rb_service.introspect
141
+ p rb_service.root
142
+
143
+ This dumps a tree-like structure that represents multiple object paths. In
144
+ this particular case the output is:
145
+
146
+ </: {org => {gnome => {Rhythmbox => {Player => ..fdbe625de {},Shell => ..fdbe6852e {},PlaylistManager => ..fdbe4e340 {}}></code></pre>
147
+
148
+ Read this left to right: the root node is "/", it has one child node "org",
149
+ "org" has one child node "gnome", and "gnome" has one child node "Rhythmbox".
150
+ Rhythmbox has Tree child nodes "Player", "Shell" and "PlaylistManager".
151
+ These three last child nodes have a weird digit that means it has an object
152
+ instance. Such object instances are already introspected.
153
+
154
+ If the prose wasn't clear, maybe the following ASCII art will help you:
155
+
156
+ /
157
+ org
158
+ gnome
159
+ Rhythmbox
160
+ Shell (with object)
161
+ Player (with object)
162
+ PlaylistManager (with object)
163
+
164
+ h3(#introspection--tree). Walking the object tree
165
+
166
+ You can have an object on any node, i.e. it is not limited to leaves.
167
+ You can access a specific node like this:
168
+
169
+ rb_player = rb_service.root["org"]["gnome"]["Rhythmbox"]["Player"]
170
+ rb_player = rb_service.object("/org/gnome/Rhythmbox/Player")
171
+
172
+ The difference between the two is that for the first one, @rb_service@
173
+ needs to have been introspected. Also the obtained @rb_player@ is already
174
+ introspected whereas the second @rb_player@ isn't yet.
@@ -0,0 +1,121 @@
1
+ ---
2
+ title: Creating a Service
3
+ inMenu: true
4
+ ---
5
+
6
+ This chapter deals with the opposite side of the basic client usage, namely
7
+ the creation of a D-Bus service. It contains the following sections:
8
+
9
+ # "Registering a service":#service-reg
10
+ # "Exporting an object":#obj-export
11
+ ## "Using the exported object":#obj-export-use
12
+ # "Emitting a signal":#signal-emit
13
+
14
+ h2(#service-reg). Registering a service
15
+
16
+ Now that you know how to perform D-Bus calls, and how to wait for and
17
+ handle signals, you might want to learn how to publish some object and
18
+ interface to provide them to the D-Bus world. Here is how you do that.
19
+
20
+ As you should already know, D-Bus clients that provide some object to be
21
+ called remotely are services. Here is how to allocate a name on a bus:
22
+
23
+ bus = DBus.session_bus
24
+ service = bus.request_service("org.ruby.service")
25
+
26
+ Now this client is know to the outside world as @org.ruby.service@.
27
+ Note that this is a request and it _can_ be denied! When it
28
+ is denied, an exception (@DBus::NameRequestError@) is thrown.
29
+
30
+ h2(#obj-export). Exporting an object
31
+
32
+ Now, let's define a class that we want to export:
33
+
34
+ class Test < DBus::Object
35
+ # Create an interface.
36
+ dbus_interface "org.ruby.SampleInterface" do
37
+ # Create a hello method in that interface.
38
+ dbus_method :hello, "in name:s, in name2:s" do |name, name2|
39
+ puts "hello(#{name}, #{name2})"
40
+ end
41
+ end
42
+ end
43
+
44
+ As you can see, we define a @Test@ class in which we define a
45
+ @org.ruby.SampleInterface@ interface. In this interface, we define a
46
+ method. The given code block is the method's implementation. This will be
47
+ executed when remote programs performs a D-Bus call. Now the annoying part:
48
+ the actual method definition. As you can guess the call
49
+
50
+ dbus_method :hello, "in name:s, in name2:s" do ...
51
+
52
+ creates a @hello@ method that takes two parameters both of type string.
53
+ The _:s_ means "of type string". Let's have a look at some other common
54
+ parameter types:
55
+
56
+ * _u_ means unsigned integer
57
+ * _i_ means integer
58
+ * _y_ means byte
59
+ * _(ui)_ means a structure having a unsigned integer and a signed one.
60
+ * _a_ means array, so that "ai" means array of integers
61
+ ** _as_ means array of string
62
+ ** _a(is)_ means array of structures, each having an integer and a string.
63
+
64
+ For a full description of the available D-Bus types, please refer to the
65
+ "D-Bus specification":http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-signatures.
66
+
67
+ Now that the class has been defined, we can instantiate an object
68
+ and export it as follows:
69
+
70
+ exported_obj = Test.new("/org/ruby/MyInstance")
71
+ service.export(exported_obj)
72
+
73
+ This piece of code above instantiates a @Test@ object with a D-Bus object
74
+ path. This object is reachable from the outside world after
75
+ @service.export(exported_obj)@ is called.
76
+
77
+ h3(#obj-export-use). Using the exported object
78
+
79
+ Now, let's consider another program that will access our newly created service:
80
+
81
+ ruby_service = bus.service("org.ruby.service")
82
+ obj = ruby_service.object("/org/ruby/MyInstance")
83
+ obj.introspect
84
+ obj.default_iface = "org.ruby.SampleInterface"
85
+ obj.hello("giligiligiligili", "haaaaaaa")
86
+
87
+ As you can see, the object we defined earlier is automatically introspectable.
88
+ See also "Basic Client Usage":basic_client.html.
89
+
90
+ h2(#signal-emit). Emitting a signal
91
+
92
+ Let's add some example method so you can see how to return a value to the
93
+ caller and let's also define another example interface that has a signal.
94
+
95
+ class Test2 < DBus::Object
96
+ # Create an interface
97
+ dbus_interface "org.ruby.SampleInterface" do
98
+ # Create a hello method in the interface:
99
+ dbus_method :hello, "in name:s, in name2:s" do |name, name2|
100
+ puts "hello(#{name}, #{name2})"
101
+ end
102
+ # Define a signal in the interface:
103
+ dbus_signal :SomethingJustHappened, "toto:s, tutu:u"
104
+ end
105
+
106
+ dbus_interface "org.ruby.AnotherInterface" do
107
+ dbus_method :ThatsALongMethodNameIThink, "in name:s, out ret:s" do |name|
108
+ ["So your name is #{name}"]
109
+ end
110
+ end
111
+ end
112
+
113
+ Triggering the signal is a easy as calling a method, but then this time on
114
+ a local (exported) object and not on a remote/proxy object:
115
+
116
+ exported_obj.SomethingJustHappened("blah", 1)
117
+
118
+ Note that the @ThatsALongMethodNameIThink@ method is returning a single
119
+ value to the caller. Notice that you always have to return an array. If
120
+ you want to return multiple values, just have an array with multiple
121
+ values.