README.md

A native erlang implementation of D-Bus
==============================================

D-Bus is now largely used in a lot of applications for
language-independant, object-oriented RPC system.

The erlang platform needs an erlang native implementation.

[![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=jeanparpaillon&url=https://github.com/lizenn/erlang-dbus.git&title=erlang-dbus&language=erlang&tags=github&category=software)
[![Build Status](https://travis-ci.org/lizenn/erlang-dbus.svg?branch=master)](https://travis-ci.org/lizenn/erlang-dbus)
[![Hex.pm](https://img.shields.io/hexpm/v/dbus.svg)](https://hex.pm/packages/dbus)
[![Hex.pm](https://img.shields.io/hexpm/dt/dbus.svg)](https://hex.pm/packages/dbus)
[![Project Stats](https://www.openhub.net/p/erlang-dbus2/widgets/project_thin_badge.gif)](https://www.openhub.net/p/erlang-dbus2)

## Usage as Client

This example is making a dbus call to the `org.freedesktop.DBus` system service (under linux) and a list of registered services.

```erlang
  {ok, Bus} = dbus_bus_reg:get_bus(session),
  {ok, Service} = dbus_bus:get_service(Bus, 'org.freedesktop.DBus'),
  {ok, RemoteObject} = dbus_remote_service:get_object(Service, '/org/freedesktop/DBus'),
  {ok, Iface} = dbus_proxy:interface(RemoteObject, 'org.freedesktop.DBus'),
  {ok, Names} = dbus_proxy:call(Iface, 'ListNames', []),
  io:format("ListNames: ~p~n", [lists:sort(Reply1)]),
  ok = dbus_remote_service:release_object(Service, RemoteObject),
  ok = dbus_bus:release_service(Bus, Service),
```

## Usage as Service

In the demo folder there is a bigger example, but is a minimal service callback module:

```erlang
-module(my_service).
-include_lib("dbus/include/dbus.hrl").
-behaviour(gen_dbus).

-export([
%% api
  start_link/2,
  handle_info/2,

%% dbus object callbacks
  'HelloWorld'/1,
  'HelloWorld'/3,

%% gen_dbus callbacks
  init/1
]).

-record(state, {}).

start_link() ->
  gen_dbus:start_link({local, ?MODULE}, ?MODULE, [], []).

init([Service, Path]) ->
  State = #state{},
  Methods = ['HelloWorld'],
  {ok, {"com.example.MyService", '/SomeObject', [
    {interface, 'com.example.MyInterface'},
    {methods, Methods},
    {signals, []}
    ]}, State}.

'HelloWorld'(dbus_info) ->
  [{interface, 'com.example.MyInterface'},
    {signature, [string], [{array, string}]}].

'HelloWorld'([HelloMessage], From, State) ->
  {reply, ["Hello from Erlang"], State}.

handle_info(Info, State) ->
  error_logger:warning_msg("Unhandled info: ~p~n", [Info]),
  {noreply, State}.

```

When the `dbus` application is running you can start this service with `my_module:start_link().` or add it to your supervision tree.

*Caveat* at the moment the service creation does not open a dbus connection and as a result the service will not be visible until you create the first dbus connection e.g. via `dbus_bus_reg:get_bus(session).`

## Documentation

* [API documentation](doc/README.md)
* [Manual](https://github.com/lizenn/erlang-dbus/wiki)

## Current status

The status: 
* Consuming D-Bus services: ok
* Providing D-Bus services: ok
* Tests for both are working!
* Connect through TCP and UNIX socket: ok

### TODO
* Figure out why `make ct` tests don't run on github actions
* Fix signal emission from services
* Make dializer happy
* Some authentication mechanisms are not implemented, but architectures allows for easy extension (see https://github.com/lizenn/erlang-dbus/blob/master/src/dbus_auth_cookie_sha1.erl, https://github.com/lizenn/erlang-dbus/blob/master/src/dbus_auth_external.erl and https://github.com/lizenn/erlang-dbus/blob/master/src/dbus_auth_anonymous.erl)
* Create new gen_dbus.erl that uses `handle_dbus_call(Name, Args)` form instead of current.
* Cleanup Supervisor & gen_server hierarchy
  * Remove superfluos gen_servers (proxy / peer / dbus)
  * Make service registration more explicit when using multiple busses
* Fix indentation
* More docs & examples
* More tests: unit tests regarding (un)marshaling would be really great, even if the above mentioned xample has rather complex interfaces which works both with Python and Java implementations
* Provide facilities for standard interfaces: Properties, ObjectManager, etc.