tmus

TUI Music Player
git clone https://git.sinitax.com/sinitax/tmus
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

mpris.c (3383B)


      1#include "log.h"
      2#include "mpris.h"
      3#include "player.h"
      4#include "util.h"
      5
      6#include <stdbool.h>
      7
      8static void dbus_handle_getall(DBusMessage *msg);
      9
     10int dbus_active;
     11DBusConnection *dbus_conn;
     12
     13static const char *const dbus_mpris_caps[] = {
     14	"CanPlay",
     15	"CanPause",
     16	"CanGoPrevious",
     17	"CanGoNext",
     18	"CanControl"
     19};
     20
     21void
     22dbus_handle_getall(DBusMessage *msg)
     23{
     24	DBusMessage *reply;
     25	DBusError err;
     26	DBusMessageIter iter, aiter, eiter, viter;
     27	const char *interface;
     28	dbus_bool_t can;
     29	int i, ok;
     30
     31	dbus_error_init(&err);
     32
     33	ok = dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &interface);
     34	if (ok && strcmp(interface, "org.mpris.MediaPlayer2.Player")) {
     35		dbus_error_free(&err);
     36		return;
     37	}
     38
     39	reply = dbus_message_new_method_return(msg);
     40
     41	/* TODO: change to more sane api like gio and gdbus (?) */
     42
     43	/* connect argument iter to message */
     44	dbus_message_iter_init_append(reply, &iter);
     45
     46	/* add array of dict entries { string : variant } */
     47	ASSERT(dbus_message_iter_open_container(&iter, 'a', "{sv}", &aiter));
     48
     49	for (i = 0; i < ARRLEN(dbus_mpris_caps); i++) {
     50		/* add dict entry */
     51		ASSERT(dbus_message_iter_open_container(&aiter,
     52			'e', NULL, &eiter));
     53
     54		/* string key */
     55		ASSERT(dbus_message_iter_append_basic(&eiter,
     56			's', &dbus_mpris_caps[i]));
     57
     58		/* variant container */
     59		ASSERT(dbus_message_iter_open_container(&eiter,
     60			'v', "b", &viter));
     61
     62		can = true; /* bool value */
     63		ASSERT(dbus_message_iter_append_basic(&viter, 'b', &can));
     64
     65		dbus_message_iter_close_container(&eiter, &viter);
     66		dbus_message_iter_close_container(&aiter, &eiter);
     67	}
     68
     69	dbus_message_iter_close_container(&iter, &aiter);
     70
     71	dbus_connection_send(dbus_conn, reply, NULL);
     72
     73	dbus_message_unref(reply);
     74
     75	dbus_error_free(&err);
     76}
     77
     78void
     79dbus_init(void)
     80{
     81	DBusError err;
     82	int ret;
     83
     84	dbus_active = 0;
     85
     86	dbus_error_init(&err);
     87
     88	/* dont fail if dbus not available, not everyone has
     89	 * it or needs it to play music */
     90	dbus_conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
     91	if (dbus_error_is_set(&err) || !dbus_conn) {
     92		dbus_error_free(&err);
     93		return;
     94	}
     95
     96	/* register as MPRIS compliant player for events */
     97	ret = dbus_bus_request_name(dbus_conn, "org.mpris.MediaPlayer2.tmus",
     98		DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
     99	if (dbus_error_is_set(&err))
    100		ERRORX(SYSTEM, "mpris register failed");
    101
    102	log_info("DBus active!\n");
    103
    104	dbus_active = 1;
    105
    106	dbus_error_free(&err);
    107}
    108
    109void
    110dbus_deinit(void)
    111{
    112	if (!dbus_active) return;
    113
    114	dbus_connection_unref(dbus_conn);
    115}
    116
    117void
    118dbus_update(void)
    119{
    120	DBusMessage *msg;
    121	const char *interface;
    122	const char *method;
    123
    124	if (!dbus_active) return;
    125
    126	dbus_connection_read_write(dbus_conn, 0);
    127	msg = dbus_connection_pop_message(dbus_conn);
    128	if (msg == NULL) return;
    129
    130	method = dbus_message_get_member(msg);
    131	interface = dbus_message_get_interface(msg);
    132	if (!strcmp(interface, "org.freedesktop.DBus.Properties")) {
    133		log_info("DBus: Properties requested\n");
    134		if (!strcmp(method, "GetAll"))
    135			dbus_handle_getall(msg);
    136	} else if (!strcmp(interface, "org.mpris.MediaPlayer2.Player")) {
    137		log_info("MPRIS: Method %s\n", method);
    138		if (!strcmp(method, "PlayPause")) {
    139			player_toggle_pause();
    140		} else if (!strcmp(method, "Pause")) {
    141			player_pause();
    142		} else if (!strcmp(method, "Play")) {
    143			player_play();
    144		} else if (!strcmp(method, "Next")) {
    145			player_next();
    146		} else if (!strcmp(method, "Previous")) {
    147			player_prev();
    148		}
    149	}
    150
    151	dbus_message_unref(msg);
    152}
    153