# Using Ekiga through DBUS

# Forewords

This DBUS interface to ekiga is there to make it possible to control ekiga through freedesktop.org's DBUS messaging system. The idea behind the development of this software component was to make at least parts of ekiga available nicely to other programs (be they desktop applications or scripts). The ekiga team is well aware that this interface is not complete, and plans on improving it in future releases. We still hope it will be of some use in its current form though.

# Generalities

There are a few important things which should be kept in mind :

- when ekiga gives some information through DBUS, this information may already be obsolete when it has gone through
- when ekiga is ordered to do something through DBUS, there is no guarantee that it will be able to handle the task
- ekiga receives orders through its main user interface and possibly through several DBUS programs: you're not alone!

Let us see how ekiga would work to deal with a list of objects ('foo'), each having an integer property (bar), and a state (state). (Notice: the reader familiar with the way rosters are managed in XMPP/jabber will certainly feel at home with that organisation)

All such objects will have a unique string identifier/token/hash. Ekiga will tell us about those objects with two signals:

- FooState, which comes with the token and the associated state
- FooBar, which comes with the token and the associated bar property

One of the state will be 'invalid', and will be emitted by ekiga to tell us one object was removed from the list. We will know an object was added to the list when we receive either FooState or FooBar about it.

This already allows a program watching for the signals to display the list and objects, and update it when it changes, with one caveat : if we launch the watcher after ekiga, we will not know the initial list!

This is the reason why ekiga will provide us the exceptional GetFooList method. It is exceptional because it returns something, namely the list of current valid identifiers. Beware that our example watcher should first start to watch the signals, and only then use GetFooList: remember that the list may be obsolete when we get it!

Once we have the list of identifiers, we can use the ResignalFooInfo method to ask ekiga to emit signals about the given identifier (this method doesn't return anything in itself). If the identifier is invalid (or has become since we got it!), ekiga will emit the FooState signal with the invalid state.

This part of the programming interface is enough to allow a watcher to display the list properly, and update it whenever it changes. Now what if don't want to just look at the list, but also act on it?

Ekiga may give us a DeleteFoo signal to remove an object from the list. This method won't return anything, but ekiga will emit the FooState signal in 'invalid' state if it worked.

Similarly, we may perhaps be allowed to add an object with a CreateFoo method, which would receive the value to give to the bar property. The method could either return the identifier of the new object, or nothing depending on the situation. Ekiga will emit the signals if the creation happened.

Finally, changing the value of the bar property, if possible, would be done with a SetFooBar method, which would receive the identifier and the new value. If things go well, ekiga will then emit the FooBar signal to tell us about the new value.

This little example interface is representative of how the other ekiga interfaces work, and hopefully the presentation makes it clear how to use it.

You can read directly in this file the current(cvs) list of interfaces available in ekiga, with their list of methods and signals. The rest of this document is a complement to this file and will try to make things more explicit.

# The net.ekiga.accounts interface

Ekiga doesn't allow to do and know much about the available accounts. The interface is pretty straightforward ; the only thing needing more discussion is the semantics of the state integer.

The state can take three values:

- 0: invalid
- 1: unregistered
- 2: registered

# The net.ekiga.calls interface

This interface allows to control the calls in which ekiga takes part. This is currently a little stupid since ekiga can only handle one, but we left room for future improvements.

Let us begin this tour by documenting the semantics of the call states:

- 0: invalid
- 1: standby
- 2: calling (we called the other end, it is ringing, we wait for an answer)
- 3: connected (the call is running normally)
- 4: called (someone is trying to call us, ekiga rings, waiting for us to answer)

Ekiga allows to add and remove calls from the list, using the Connect and Disconnect methods, whose meaning should be pretty clear. Notice that Connect returns the call token, so if we decide to call someone we can track what happened.

Here are the various informations we can have about a call (not all of them may be available!):

- StateChanged: gives the state of the call, as documented
- NameInfo: the name of the remote party
- ClientInfo: the name and version of the remote program
- UrlInfo: the address of the remote party
- ProtocolInfo: which protocol does the call use (SIP, H.323, ...)
- OnHoldInfo: is the call put on hold?

The PlayPause method is used to put the call on hold, or release it from the hold. The Transfer method is when you want to send the remote party to talk to someone else.

# The net.ekiga.self interface

This interface allows to get more information about ekiga's running instance.

It has simple methods like GetName, GetLocation and GetComment which allows to get what the user said in the preferences. The Shutdown command allows to quit ekiga.

And it has an interesting GetLocalAddress method, which allows to know which address to use to contact the user. You have to give it the protocol in which the address should be given (beware that it's reliable mostly for SIP). The goal of that method is to allow other programs, for example XMPP/jabber clients, to make us available for calls.

# The helper

Since launching ekiga to have only basic informations would be bad (it is a rather big program), it comes with a helper program, which can take requests on its behalf for easy questions.

Of course, this helper is short-lived and exits automatically quite fast, so it is always in sync with the available ekiga.

The current helper knows only two methods:

- GetVersion, which returns the version of the DBUS component available (pair of integers: major and minor)
- GetSupportedProtocols, which returns a string list of the supported protocols (needed for example by jabber/XMPP clients which would like to know what type of URI can be negociated)

To be completed(FIXME)

# Example C code

To be completed(FIXME)

# Example Perl code

The following program waits on D-Bus and runs a command when the call is made (either outgoing or incoming), and another one when the call is finished. It can be used for example for temporarily suspending the PulseAudio server, when ekiga is configured to use the ALSA device directly (i.e. `hw:0,0`).

    #!/usr/bin/perl -w
    #
    # A sample program for demonstrating the ekiga D-Bus interface.
    # This program suspends the PulseAudio server during ekiga calls.
    # Usable for example when ekiga is configured to use the hardware
    # ALSA devices (e.g. hw:0,0), i.e. at least until the following bugs
    # are fixed on your system:
    # http://www.pulseaudio.org/ticket/23 and
    # https://bugtrack.alsa-project.org/alsa-bug/view.php?id=2601
    #
    # This program is written by Jan "Yenya" Kasprzak, http://www.fi.muni.cz/~kas/
    # and it is distributable under the same terms as the Perl itself.
    #
    use strict;
    use Net::DBus;
    use Net::DBus::Reactor;

    my $bus = Net::DBus->session
    	or die "Can't connect to the session D-Bus";

    my $service = $bus->get_service("net.ekiga.instance")
    	or die "Can't find the Ekiga instance on the D-Bus\n"
    		. "(is ekiga running and has D-Bus support compiled in?)";

    my $object = Net::DBus::RemoteObject->new($service, '/net/ekiga/instance',
    	'net.ekiga.calls') or die "Can't get the ekiga instance";

    $object->connect_to_signal('StateChanged', sub {
    	my ($callid, $state) = @_;
    	open my $fh, '|-', 'pacmd >/dev/null 2>&1';
    	if (!defined $state || $state == 0 || $state == 1) {
    		print $fh "suspend 0\n";
    		print STDERR "Ekiga call finished, enabling PulseAudio\n"
    			if -t STDERR;
    		system 'notify-send', 'PulseAudio enabled',
    			'PulseAudio sound server enabled again.';
    	} elsif ($state == 2 || $state ==4) {
    		print $fh "suspend 1\n";
    		print STDERR "Ekiga call, suspending PulseAudio\n"
    			if -t STDERR;
    		system 'notify-send', 'PulseAudio suspended',
    			'PulseAudio sound server suspended during the VoIP call.';
    	}
    	close $fh;
    });

    my $reactor = Net::DBus::Reactor->main
    	or die "Can't get Net::DBus::Reactor";
    print STDERR "Waiting on D-Bus ...\n" if -t STDERR;
    $reactor->run();

# Example python code

The goal isn't to show off everything, but see how things work on some examples

First of all, you need to do the following to access DBUS:

`import dbus
bus = dbus.SessionBus ()`

## Which version of the DBUS component is available?

For this question, we need to have a proxy to the helper:

`obj = bus.get_object ('net.ekiga.helper', '/net/ekiga/helper')
helper = dbus.Interface(obj, 'net.ekiga.helper')`

once obtained, we just have to:

`helper.GetVersion ()
[0,0]`

Of course the actual result will depend on your version ;-)

## Watching for the UrlInfo signal of the net.ekiga.calls interface

To be completed(FIXME)

# Example pseudo-code

## Accepting a call from DBUS

Suppose that when ekiga rings we find it more convenient to click on a bluetooth headset's button to accept the call. We would like to know how a program which runs when that happens can accept the call.

- watch for the StateChanged and UrlInfo signals
- ask ekiga the list of calls
- for each call in that list, ask ekiga to ResignalCallInfo

This will allow you to find the call token in state called, with its url. Now just ask ekiga to Connect to that url, and you're done!

To be completed(FIXME)