Net-DBus
view release on metacpan or search on metacpan
lib/Net/DBus/Tutorial/ExportingObjects.pod view on Meta::CPAN
sub register_backend {
my $self = shift;
my $name = shift;
my $module = shift;
.. snipped rest of method body ...
}
And, thus:
dbus_method("find_backend", ["string"], ["string"])
sub find_backend {
my $self = shift;
my $extension = shift;
... snip method body...
}
=head1 DEFINING A SERVICE
Now that the objects have been written, it is time to define
a service. A service is nothing more than a well known name
for a given API contract. A contract can be thought of as a
definition of a list of object paths, and the corresponding
interfaces they provide. So, someone else could come along a
provide an alternate music player implementation using the
Python or QT bindings for DBus, and if they provided the same
set of object paths & interfaces, they could justifiably register
the same service on the bus.
The L<Net::DBus::Service> module provides the means to register
a service. Its constructor expects a reference to the bus object
(an instance of L<Net::DBus>), along with the name of the service.
As with interface names, the first component of a service name is
usually derived from a domain name, and then suffixed with the
name of the application, in our example forming C<org.cpan.Music.Player>.
While some objects will be created on the fly during execution
of the application, others are created upon initial startup. The
music player manager object created earlier in this tutorial is
an example of the latter. It is typical to instantiate and register
these objects in the constructor for the service. Thus a service
object for the music player application would look like:
package Music::Player;
use base qw(Net::DBus::Service);
sub new {
my $class = shift;
my $bus = shift;
my $self = $class->SUPER::new($bus, "org.cpan.music.player");
bless $self, $class;
$self->{manager} = Music::Player::Manager->new($self);
return $self;
}
The L<Net::DBus::Service> automatically provides one special
object to all services, under the path C</org/freedesktop/DBus/Exporter>.
This object implements the C<org.freedesktop.DBus.Exporter> interface
which has a method C<ListObject>. This enables clients to determine
a list of all objects exported within a service. While not functionally
necessary for most applications, it is none-the-less a useful tool for
developers debugging applications, or wondering what a service provides.
=head1 CONNECTING TO THE BUS
The final step in getting our service up and running is to connect it
to the bus. This brings up an interesting conundrum, does one export
the service on the system bus (shared by all users & processes on the
machine), or the session bus (one per user logged into a machine). In
some cases the answer, with only one of the two buses conceptually making
sense. In other cases, however, both the session & system bus are valid.
In the former one would use the C<session> or <system> methods on L<Net::DBus>
to get a handle to the desired bus, while in the latter case, the C<find>
method would be used. This applies a heuristic to determine the correct
bus based on execution environment. In the case of the music player, either
bus is relevant, so the code to connect the service to the bus would look
like:
use Net::DBus;
my $bus = Net::DBus->find;
my $player = Music::Player->new($bus);
With the service attached to the bus, it is merely necessary to run
the main event processing loop to listen out for & handle incoming
DBus messages. So the above code is modified to start a simple reactor:
use Net::DBus;
use Net::DBus::Reactor;
my $bus = Net::DBus->find;
my $player = Music::Player->new($bus);
Net::DBus::Reactor->main->run;
exit 0;
Saving this code into a script C</usr/bin/music-player.pl>, coding
is complete and the service ready for use by clients on the bus.
=head1 SERVICE ACTIVATION
One might now wonder how best to start the service, particularly
if it is a service capable of running on
both the system and session buses. DBus has the answer in the
concept of C<activation>. What happens is that when a client
on the bus attempts to call a method, or register a signal
handler against, a service not currently running, it will first
try and start the service. Service's which wish to participate
in this process merely need stick a simple service definition
file into the directory C</usr/share/dbus-1/services>. The file
should be named to match the service name, with the file extension
C<.service> appended. eg, C</usr/share/dbus-1/services/org.cpan.music.player.service>
The file contains two keys, first the name of the service, and
second the name of the executable used to run the service, or in
this case the Perl script. So, for our simple service the data
file would contain:
( run in 0.664 second using v1.01-cache-2.11-cpan-39bf76dae61 )