3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2006-2007 Nokia Corporation
6 * Copyright (C) 2004-2009 Marcel Holtmann <marcel@holtmann.org>
7 * Copyright (C) 2011 BMW Car IT GmbH. All rights reserved.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32 #include <bluetooth/uuid.h>
37 #include "../src/adapter.h"
38 #include "../src/dbus-common.h"
40 #include "glib-helper.h"
46 #include "transport.h"
53 #define MEDIA_INTERFACE "org.bluez.Media"
54 #define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint"
55 #define MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer"
57 #define REQUEST_TIMEOUT (3 * 1000) /* 3 seconds */
59 struct media_adapter {
60 bdaddr_t src; /* Adapter address */
61 char *path; /* Adapter path */
62 DBusConnection *conn; /* Adapter connection */
63 GSList *endpoints; /* Endpoints list */
64 GSList *players; /* Players list */
67 struct endpoint_request {
68 struct media_endpoint *endpoint;
70 DBusPendingCall *call;
71 media_endpoint_cb_t cb;
72 GDestroyNotify destroy;
76 struct media_endpoint {
78 char *sender; /* Endpoint DBus bus id */
79 char *path; /* Endpoint object path */
80 char *uuid; /* Endpoint property UUID */
81 uint8_t codec; /* Endpoint codec */
82 uint8_t *capabilities; /* Endpoint property capabilities */
83 size_t size; /* Endpoint capabilities size */
88 struct media_adapter *adapter;
93 struct media_adapter *adapter;
94 struct avrcp_player *player;
95 char *sender; /* Player DBus bus id */
96 char *path; /* Player object path */
97 GHashTable *settings; /* Player settings */
98 GHashTable *track; /* Player current track */
100 guint property_watch;
108 struct metadata_value {
116 static GSList *adapters = NULL;
118 static void endpoint_request_free(struct endpoint_request *request)
121 dbus_pending_call_unref(request->call);
123 if (request->destroy)
124 request->destroy(request->user_data);
126 dbus_message_unref(request->msg);
130 static void media_endpoint_cancel(struct endpoint_request *request)
132 struct media_endpoint *endpoint = request->endpoint;
135 dbus_pending_call_cancel(request->call);
137 endpoint->requests = g_slist_remove(endpoint->requests, request);
139 endpoint_request_free(request);
142 static void media_endpoint_cancel_all(struct media_endpoint *endpoint)
144 while (endpoint->requests != NULL)
145 media_endpoint_cancel(endpoint->requests->data);
148 static void media_endpoint_destroy(struct media_endpoint *endpoint)
150 struct media_adapter *adapter = endpoint->adapter;
152 DBG("sender=%s path=%s", endpoint->sender, endpoint->path);
154 if (endpoint->hs_watch)
155 headset_remove_state_cb(endpoint->hs_watch);
157 if (endpoint->ag_watch)
158 gateway_remove_state_cb(endpoint->ag_watch);
160 media_endpoint_cancel_all(endpoint);
162 g_slist_free_full(endpoint->transports,
163 (GDestroyNotify) media_transport_destroy);
165 g_dbus_remove_watch(adapter->conn, endpoint->watch);
166 g_free(endpoint->capabilities);
167 g_free(endpoint->sender);
168 g_free(endpoint->path);
169 g_free(endpoint->uuid);
173 static void media_endpoint_remove(struct media_endpoint *endpoint)
175 struct media_adapter *adapter = endpoint->adapter;
178 a2dp_remove_sep(endpoint->sep);
182 info("Endpoint unregistered: sender=%s path=%s", endpoint->sender,
185 adapter->endpoints = g_slist_remove(adapter->endpoints, endpoint);
187 media_endpoint_destroy(endpoint);
190 static void media_endpoint_exit(DBusConnection *connection, void *user_data)
192 struct media_endpoint *endpoint = user_data;
195 media_endpoint_remove(endpoint);
198 static void headset_setconf_cb(struct media_endpoint *endpoint, void *ret,
199 int size, void *user_data)
201 struct audio_device *dev = user_data;
206 headset_shutdown(dev);
209 static void clear_configuration(struct media_endpoint *endpoint,
210 struct media_transport *transport)
212 DBusConnection *conn;
216 conn = endpoint->adapter->conn;
218 msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
219 MEDIA_ENDPOINT_INTERFACE,
220 "ClearConfiguration");
222 error("Couldn't allocate D-Bus message");
226 path = media_transport_get_path(transport);
227 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &path,
229 g_dbus_send_message(conn, msg);
231 endpoint->transports = g_slist_remove(endpoint->transports, transport);
232 media_transport_destroy(transport);
235 static void clear_endpoint(struct media_endpoint *endpoint)
237 media_endpoint_cancel_all(endpoint);
239 while (endpoint->transports != NULL)
240 clear_configuration(endpoint, endpoint->transports->data);
243 static void endpoint_reply(DBusPendingCall *call, void *user_data)
245 struct endpoint_request *request = user_data;
246 struct media_endpoint *endpoint = request->endpoint;
253 /* steal_reply will always return non-NULL since the callback
254 * is only called after a reply has been received */
255 reply = dbus_pending_call_steal_reply(call);
257 dbus_error_init(&err);
258 if (dbus_set_error_from_message(&err, reply)) {
259 error("Endpoint replied with an error: %s",
262 /* Clear endpoint configuration in case of NO_REPLY error */
263 if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY)) {
265 request->cb(endpoint, NULL, size,
267 clear_endpoint(endpoint);
268 dbus_message_unref(reply);
269 dbus_error_free(&err);
273 dbus_error_free(&err);
277 if (dbus_message_is_method_call(request->msg, MEDIA_ENDPOINT_INTERFACE,
278 "SelectConfiguration")) {
279 DBusMessageIter args, array;
280 uint8_t *configuration;
282 dbus_message_iter_init(reply, &args);
284 dbus_message_iter_recurse(&args, &array);
286 dbus_message_iter_get_fixed_array(&array, &configuration, &size);
290 } else if (!dbus_message_get_args(reply, &err, DBUS_TYPE_INVALID)) {
291 error("Wrong reply signature: %s", err.message);
292 dbus_error_free(&err);
301 dbus_message_unref(reply);
304 request->cb(endpoint, ret, size, request->user_data);
306 endpoint->requests = g_slist_remove(endpoint->requests, request);
307 endpoint_request_free(request);
310 static gboolean media_endpoint_async_call(DBusConnection *conn,
312 struct media_endpoint *endpoint,
313 media_endpoint_cb_t cb,
315 GDestroyNotify destroy)
317 struct endpoint_request *request;
319 request = g_new0(struct endpoint_request, 1);
321 /* Timeout should be less than avdtp request timeout (4 seconds) */
322 if (dbus_connection_send_with_reply(conn, msg, &request->call,
323 REQUEST_TIMEOUT) == FALSE) {
324 error("D-Bus send failed");
329 dbus_pending_call_set_notify(request->call, endpoint_reply, request,
332 request->endpoint = endpoint;
335 request->destroy = destroy;
336 request->user_data = user_data;
338 endpoint->requests = g_slist_append(endpoint->requests, request);
340 DBG("Calling %s: name = %s path = %s", dbus_message_get_member(msg),
341 dbus_message_get_destination(msg),
342 dbus_message_get_path(msg));
347 static gboolean select_configuration(struct media_endpoint *endpoint,
348 uint8_t *capabilities,
350 media_endpoint_cb_t cb,
352 GDestroyNotify destroy)
354 DBusConnection *conn;
357 conn = endpoint->adapter->conn;
359 msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
360 MEDIA_ENDPOINT_INTERFACE,
361 "SelectConfiguration");
363 error("Couldn't allocate D-Bus message");
367 dbus_message_append_args(msg, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
368 &capabilities, length,
371 return media_endpoint_async_call(conn, msg, endpoint, cb, user_data,
375 static gint transport_device_cmp(gconstpointer data, gconstpointer user_data)
377 struct media_transport *transport = (struct media_transport *) data;
378 const struct audio_device *device = user_data;
380 if (device == media_transport_get_dev(transport))
386 static struct media_transport *find_device_transport(
387 struct media_endpoint *endpoint,
388 struct audio_device *device)
392 match = g_slist_find_custom(endpoint->transports, device,
393 transport_device_cmp);
400 static gboolean set_configuration(struct media_endpoint *endpoint,
401 struct audio_device *device,
402 uint8_t *configuration, size_t size,
403 media_endpoint_cb_t cb,
405 GDestroyNotify destroy)
407 DBusConnection *conn;
410 DBusMessageIter iter;
411 struct media_transport *transport;
413 transport = find_device_transport(endpoint, device);
415 if (transport != NULL)
418 conn = endpoint->adapter->conn;
420 transport = media_transport_create(conn, endpoint, device,
421 configuration, size);
422 if (transport == NULL)
425 msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
426 MEDIA_ENDPOINT_INTERFACE,
429 error("Couldn't allocate D-Bus message");
430 media_transport_destroy(transport);
434 endpoint->transports = g_slist_append(endpoint->transports, transport);
436 dbus_message_iter_init_append(msg, &iter);
438 path = media_transport_get_path(transport);
439 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
441 transport_get_properties(transport, &iter);
443 return media_endpoint_async_call(conn, msg, endpoint, cb, user_data,
447 static void release_endpoint(struct media_endpoint *endpoint)
451 DBG("sender=%s path=%s", endpoint->sender, endpoint->path);
454 if (endpoint->watch == 0)
457 msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
458 MEDIA_ENDPOINT_INTERFACE,
461 error("Couldn't allocate D-Bus message");
465 g_dbus_send_message(endpoint->adapter->conn, msg);
468 media_endpoint_remove(endpoint);
471 static void headset_state_changed(struct audio_device *dev,
472 headset_state_t old_state,
473 headset_state_t new_state,
476 struct media_endpoint *endpoint = user_data;
477 struct media_transport *transport;
481 if (bacmp(&endpoint->adapter->src, &dev->src) != 0)
485 case HEADSET_STATE_DISCONNECTED:
486 transport = find_device_transport(endpoint, dev);
488 if (transport != NULL) {
489 DBG("Clear endpoint %p", endpoint);
490 clear_configuration(endpoint, transport);
493 case HEADSET_STATE_CONNECTING:
494 set_configuration(endpoint, dev, NULL, 0, headset_setconf_cb,
497 case HEADSET_STATE_CONNECTED:
499 case HEADSET_STATE_PLAY_IN_PROGRESS:
501 case HEADSET_STATE_PLAYING:
506 static const char *get_name(struct a2dp_sep *sep, void *user_data)
508 struct media_endpoint *endpoint = user_data;
510 return endpoint->sender;
513 static size_t get_capabilities(struct a2dp_sep *sep, uint8_t **capabilities,
516 struct media_endpoint *endpoint = user_data;
518 *capabilities = endpoint->capabilities;
519 return endpoint->size;
522 struct a2dp_config_data {
523 struct a2dp_setup *setup;
524 a2dp_endpoint_config_t cb;
527 struct a2dp_select_data {
528 struct a2dp_setup *setup;
529 a2dp_endpoint_select_t cb;
532 static void select_cb(struct media_endpoint *endpoint, void *ret, int size,
535 struct a2dp_select_data *data = user_data;
537 data->cb(data->setup, ret, size);
540 static int select_config(struct a2dp_sep *sep, uint8_t *capabilities,
541 size_t length, struct a2dp_setup *setup,
542 a2dp_endpoint_select_t cb, void *user_data)
544 struct media_endpoint *endpoint = user_data;
545 struct a2dp_select_data *data;
547 data = g_new0(struct a2dp_select_data, 1);
551 if (select_configuration(endpoint, capabilities, length,
552 select_cb, data, g_free) == TRUE)
559 static void config_cb(struct media_endpoint *endpoint, void *ret, int size,
562 struct a2dp_config_data *data = user_data;
564 data->cb(data->setup, ret ? TRUE : FALSE);
567 static int set_config(struct a2dp_sep *sep, struct audio_device *dev,
568 uint8_t *configuration, size_t length,
569 struct a2dp_setup *setup,
570 a2dp_endpoint_config_t cb,
573 struct media_endpoint *endpoint = user_data;
574 struct a2dp_config_data *data;
576 data = g_new0(struct a2dp_config_data, 1);
580 if (set_configuration(endpoint, dev, configuration, length,
581 config_cb, data, g_free) == TRUE)
588 static void clear_config(struct a2dp_sep *sep, void *user_data)
590 struct media_endpoint *endpoint = user_data;
592 clear_endpoint(endpoint);
595 static void set_delay(struct a2dp_sep *sep, uint16_t delay, void *user_data)
597 struct media_endpoint *endpoint = user_data;
599 if (endpoint->transports == NULL)
602 media_transport_update_delay(endpoint->transports->data, delay);
605 static struct a2dp_endpoint a2dp_endpoint = {
606 .get_name = get_name,
607 .get_capabilities = get_capabilities,
608 .select_configuration = select_config,
609 .set_configuration = set_config,
610 .clear_configuration = clear_config,
611 .set_delay = set_delay
614 static void a2dp_destroy_endpoint(void *user_data)
616 struct media_endpoint *endpoint = user_data;
618 clear_endpoint(endpoint);
620 endpoint->sep = NULL;
621 release_endpoint(endpoint);
624 static void gateway_setconf_cb(struct media_endpoint *endpoint, void *ret,
625 int size, void *user_data)
627 struct audio_device *dev = user_data;
632 gateway_set_state(dev, GATEWAY_STATE_DISCONNECTED);
635 static void gateway_state_changed(struct audio_device *dev,
636 gateway_state_t old_state,
637 gateway_state_t new_state,
640 struct media_endpoint *endpoint = user_data;
641 struct media_transport *transport;
645 if (bacmp(&endpoint->adapter->src, &dev->src) != 0)
649 case GATEWAY_STATE_DISCONNECTED:
650 transport = find_device_transport(endpoint, dev);
651 if (transport != NULL) {
652 DBG("Clear endpoint %p", endpoint);
653 clear_configuration(endpoint, transport);
656 case GATEWAY_STATE_CONNECTING:
657 set_configuration(endpoint, dev, NULL, 0,
658 gateway_setconf_cb, dev, NULL);
660 case GATEWAY_STATE_CONNECTED:
662 case GATEWAY_STATE_PLAYING:
667 static gboolean endpoint_init_a2dp_source(struct media_endpoint *endpoint,
668 gboolean delay_reporting,
671 endpoint->sep = a2dp_add_sep(&endpoint->adapter->src,
672 AVDTP_SEP_TYPE_SOURCE, endpoint->codec,
673 delay_reporting, &a2dp_endpoint,
674 endpoint, a2dp_destroy_endpoint, err);
675 if (endpoint->sep == NULL)
681 static gboolean endpoint_init_a2dp_sink(struct media_endpoint *endpoint,
682 gboolean delay_reporting,
685 endpoint->sep = a2dp_add_sep(&endpoint->adapter->src,
686 AVDTP_SEP_TYPE_SINK, endpoint->codec,
687 delay_reporting, &a2dp_endpoint,
688 endpoint, a2dp_destroy_endpoint, err);
689 if (endpoint->sep == NULL)
695 static gboolean endpoint_init_ag(struct media_endpoint *endpoint, int *err)
700 endpoint->hs_watch = headset_add_state_cb(headset_state_changed,
702 list = manager_find_devices(NULL, &endpoint->adapter->src, BDADDR_ANY,
703 AUDIO_HEADSET_INTERFACE, TRUE);
705 for (l = list; l != NULL; l = l->next) {
706 struct audio_device *dev = l->data;
708 set_configuration(endpoint, dev, NULL, 0,
709 headset_setconf_cb, dev, NULL);
717 static gboolean endpoint_init_hs(struct media_endpoint *endpoint, int *err)
722 endpoint->ag_watch = gateway_add_state_cb(gateway_state_changed,
724 list = manager_find_devices(NULL, &endpoint->adapter->src, BDADDR_ANY,
725 AUDIO_GATEWAY_INTERFACE, TRUE);
727 for (l = list; l != NULL; l = l->next) {
728 struct audio_device *dev = l->data;
730 set_configuration(endpoint, dev, NULL, 0,
731 gateway_setconf_cb, dev, NULL);
739 static struct media_endpoint *media_endpoint_create(struct media_adapter *adapter,
743 gboolean delay_reporting,
745 uint8_t *capabilities,
749 struct media_endpoint *endpoint;
752 endpoint = g_new0(struct media_endpoint, 1);
753 endpoint->sender = g_strdup(sender);
754 endpoint->path = g_strdup(path);
755 endpoint->uuid = g_strdup(uuid);
756 endpoint->codec = codec;
759 endpoint->capabilities = g_new(uint8_t, size);
760 memcpy(endpoint->capabilities, capabilities, size);
761 endpoint->size = size;
764 endpoint->adapter = adapter;
766 if (strcasecmp(uuid, A2DP_SOURCE_UUID) == 0)
767 succeeded = endpoint_init_a2dp_source(endpoint,
768 delay_reporting, err);
769 else if (strcasecmp(uuid, A2DP_SINK_UUID) == 0)
770 succeeded = endpoint_init_a2dp_sink(endpoint,
771 delay_reporting, err);
772 else if (strcasecmp(uuid, HFP_AG_UUID) == 0 ||
773 strcasecmp(uuid, HSP_AG_UUID) == 0)
774 succeeded = endpoint_init_ag(endpoint, err);
775 else if (strcasecmp(uuid, HFP_HS_UUID) == 0 ||
776 strcasecmp(uuid, HSP_HS_UUID) == 0)
777 succeeded = endpoint_init_hs(endpoint, err);
790 endpoint->watch = g_dbus_add_disconnect_watch(adapter->conn, sender,
791 media_endpoint_exit, endpoint,
794 adapter->endpoints = g_slist_append(adapter->endpoints, endpoint);
795 info("Endpoint registered: sender=%s path=%s", sender, path);
802 static struct media_endpoint *media_adapter_find_endpoint(
803 struct media_adapter *adapter,
810 for (l = adapter->endpoints; l; l = l->next) {
811 struct media_endpoint *endpoint = l->data;
813 if (sender && g_strcmp0(endpoint->sender, sender) != 0)
816 if (path && g_strcmp0(endpoint->path, path) != 0)
819 if (uuid && g_strcmp0(endpoint->uuid, uuid) != 0)
828 static int parse_properties(DBusMessageIter *props, const char **uuid,
829 gboolean *delay_reporting, uint8_t *codec,
830 uint8_t **capabilities, int *size)
832 gboolean has_uuid = FALSE;
833 gboolean has_codec = FALSE;
835 while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
837 DBusMessageIter value, entry;
840 dbus_message_iter_recurse(props, &entry);
841 dbus_message_iter_get_basic(&entry, &key);
843 dbus_message_iter_next(&entry);
844 dbus_message_iter_recurse(&entry, &value);
846 var = dbus_message_iter_get_arg_type(&value);
847 if (strcasecmp(key, "UUID") == 0) {
848 if (var != DBUS_TYPE_STRING)
850 dbus_message_iter_get_basic(&value, uuid);
852 } else if (strcasecmp(key, "Codec") == 0) {
853 if (var != DBUS_TYPE_BYTE)
855 dbus_message_iter_get_basic(&value, codec);
857 } else if (strcasecmp(key, "DelayReporting") == 0) {
858 if (var != DBUS_TYPE_BOOLEAN)
860 dbus_message_iter_get_basic(&value, delay_reporting);
861 } else if (strcasecmp(key, "Capabilities") == 0) {
862 DBusMessageIter array;
864 if (var != DBUS_TYPE_ARRAY)
867 dbus_message_iter_recurse(&value, &array);
868 dbus_message_iter_get_fixed_array(&array, capabilities,
872 dbus_message_iter_next(props);
875 return (has_uuid && has_codec) ? 0 : -EINVAL;
878 static DBusMessage *register_endpoint(DBusConnection *conn, DBusMessage *msg,
881 struct media_adapter *adapter = data;
882 DBusMessageIter args, props;
883 const char *sender, *path, *uuid;
884 gboolean delay_reporting = FALSE;
886 uint8_t *capabilities;
890 sender = dbus_message_get_sender(msg);
892 dbus_message_iter_init(msg, &args);
894 dbus_message_iter_get_basic(&args, &path);
895 dbus_message_iter_next(&args);
897 if (media_adapter_find_endpoint(adapter, sender, path, NULL) != NULL)
898 return btd_error_already_exists(msg);
900 dbus_message_iter_recurse(&args, &props);
901 if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY)
902 return btd_error_invalid_args(msg);
904 if (parse_properties(&props, &uuid, &delay_reporting, &codec,
905 &capabilities, &size) < 0)
906 return btd_error_invalid_args(msg);
908 if (media_endpoint_create(adapter, sender, path, uuid, delay_reporting,
909 codec, capabilities, size, &err) == NULL) {
910 if (err == -EPROTONOSUPPORT)
911 return btd_error_not_supported(msg);
913 return btd_error_invalid_args(msg);
916 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
919 static DBusMessage *unregister_endpoint(DBusConnection *conn, DBusMessage *msg,
922 struct media_adapter *adapter = data;
923 struct media_endpoint *endpoint;
924 const char *sender, *path;
926 if (!dbus_message_get_args(msg, NULL,
927 DBUS_TYPE_OBJECT_PATH, &path,
931 sender = dbus_message_get_sender(msg);
933 endpoint = media_adapter_find_endpoint(adapter, sender, path, NULL);
934 if (endpoint == NULL)
935 return btd_error_does_not_exist(msg);
937 media_endpoint_remove(endpoint);
939 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
942 static struct media_player *media_adapter_find_player(
943 struct media_adapter *adapter,
949 for (l = adapter->players; l; l = l->next) {
950 struct media_player *mp = l->data;
952 if (sender && g_strcmp0(mp->sender, sender) != 0)
955 if (path && g_strcmp0(mp->path, path) != 0)
964 static void release_player(struct media_player *mp)
968 DBG("sender=%s path=%s", mp->sender, mp->path);
970 msg = dbus_message_new_method_call(mp->sender, mp->path,
971 MEDIA_PLAYER_INTERFACE,
974 error("Couldn't allocate D-Bus message");
978 g_dbus_send_message(mp->adapter->conn, msg);
981 static void media_player_free(gpointer data)
983 struct media_player *mp = data;
984 struct media_adapter *adapter = mp->adapter;
987 adapter->players = g_slist_remove(adapter->players, mp);
991 g_dbus_remove_watch(adapter->conn, mp->watch);
992 g_dbus_remove_watch(adapter->conn, mp->property_watch);
993 g_dbus_remove_watch(adapter->conn, mp->track_watch);
996 g_hash_table_unref(mp->track);
999 g_hash_table_unref(mp->settings);
1001 g_timer_destroy(mp->timer);
1007 static void media_player_destroy(struct media_player *mp)
1009 struct media_adapter *adapter = mp->adapter;
1011 DBG("sender=%s path=%s", mp->sender, mp->path);
1014 struct avrcp_player *player = mp->player;
1016 adapter->players = g_slist_remove(adapter->players, mp);
1017 avrcp_unregister_player(player);
1021 media_player_free(mp);
1024 static void media_player_remove(struct media_player *mp)
1026 info("Player unregistered: sender=%s path=%s", mp->sender, mp->path);
1028 media_player_destroy(mp);
1031 static const char *attrval_to_str(uint8_t attr, uint8_t value)
1034 case AVRCP_ATTRIBUTE_EQUALIZER:
1036 case AVRCP_EQUALIZER_ON:
1038 case AVRCP_EQUALIZER_OFF:
1043 case AVRCP_ATTRIBUTE_REPEAT_MODE:
1045 case AVRCP_REPEAT_MODE_OFF:
1047 case AVRCP_REPEAT_MODE_SINGLE:
1048 return "singletrack";
1049 case AVRCP_REPEAT_MODE_ALL:
1051 case AVRCP_REPEAT_MODE_GROUP:
1056 /* Shuffle and scan have the same values */
1057 case AVRCP_ATTRIBUTE_SHUFFLE:
1058 case AVRCP_ATTRIBUTE_SCAN:
1060 case AVRCP_SCAN_OFF:
1062 case AVRCP_SCAN_ALL:
1064 case AVRCP_SCAN_GROUP:
1074 static int attrval_to_val(uint8_t attr, const char *value)
1079 case AVRCP_ATTRIBUTE_EQUALIZER:
1080 if (!strcmp(value, "off"))
1081 ret = AVRCP_EQUALIZER_OFF;
1082 else if (!strcmp(value, "on"))
1083 ret = AVRCP_EQUALIZER_ON;
1088 case AVRCP_ATTRIBUTE_REPEAT_MODE:
1089 if (!strcmp(value, "off"))
1090 ret = AVRCP_REPEAT_MODE_OFF;
1091 else if (!strcmp(value, "singletrack"))
1092 ret = AVRCP_REPEAT_MODE_SINGLE;
1093 else if (!strcmp(value, "alltracks"))
1094 ret = AVRCP_REPEAT_MODE_ALL;
1095 else if (!strcmp(value, "group"))
1096 ret = AVRCP_REPEAT_MODE_GROUP;
1101 case AVRCP_ATTRIBUTE_SHUFFLE:
1102 if (!strcmp(value, "off"))
1103 ret = AVRCP_SHUFFLE_OFF;
1104 else if (!strcmp(value, "alltracks"))
1105 ret = AVRCP_SHUFFLE_ALL;
1106 else if (!strcmp(value, "group"))
1107 ret = AVRCP_SHUFFLE_GROUP;
1112 case AVRCP_ATTRIBUTE_SCAN:
1113 if (!strcmp(value, "off"))
1114 ret = AVRCP_SCAN_OFF;
1115 else if (!strcmp(value, "alltracks"))
1116 ret = AVRCP_SCAN_ALL;
1117 else if (!strcmp(value, "group"))
1118 ret = AVRCP_SCAN_GROUP;
1128 static const char *attr_to_str(uint8_t attr)
1131 case AVRCP_ATTRIBUTE_EQUALIZER:
1133 case AVRCP_ATTRIBUTE_REPEAT_MODE:
1135 case AVRCP_ATTRIBUTE_SHUFFLE:
1137 case AVRCP_ATTRIBUTE_SCAN:
1144 static int attr_to_val(const char *str)
1146 if (!strcasecmp(str, "Equalizer"))
1147 return AVRCP_ATTRIBUTE_EQUALIZER;
1148 else if (!strcasecmp(str, "Repeat"))
1149 return AVRCP_ATTRIBUTE_REPEAT_MODE;
1150 else if (!strcasecmp(str, "Shuffle"))
1151 return AVRCP_ATTRIBUTE_SHUFFLE;
1152 else if (!strcasecmp(str, "Scan"))
1153 return AVRCP_ATTRIBUTE_SCAN;
1158 static int play_status_to_val(const char *status)
1160 if (!strcasecmp(status, "stopped"))
1161 return AVRCP_PLAY_STATUS_STOPPED;
1162 else if (!strcasecmp(status, "playing"))
1163 return AVRCP_PLAY_STATUS_PLAYING;
1164 else if (!strcasecmp(status, "paused"))
1165 return AVRCP_PLAY_STATUS_PAUSED;
1166 else if (!strcasecmp(status, "forward-seek"))
1167 return AVRCP_PLAY_STATUS_FWD_SEEK;
1168 else if (!strcasecmp(status, "reverse-seek"))
1169 return AVRCP_PLAY_STATUS_REV_SEEK;
1170 else if (!strcasecmp(status, "error"))
1171 return AVRCP_PLAY_STATUS_ERROR;
1176 static int metadata_to_val(const char *str)
1178 if (!strcasecmp(str, "Title"))
1179 return AVRCP_MEDIA_ATTRIBUTE_TITLE;
1180 else if (!strcasecmp(str, "Artist"))
1181 return AVRCP_MEDIA_ATTRIBUTE_ARTIST;
1182 else if (!strcasecmp(str, "Album"))
1183 return AVRCP_MEDIA_ATTRIBUTE_ALBUM;
1184 else if (!strcasecmp(str, "Genre"))
1185 return AVRCP_MEDIA_ATTRIBUTE_GENRE;
1186 else if (!strcasecmp(str, "NumberOfTracks"))
1187 return AVRCP_MEDIA_ATTRIBUTE_N_TRACKS;
1188 else if (!strcasecmp(str, "Number"))
1189 return AVRCP_MEDIA_ATTRIBUTE_TRACK;
1190 else if (!strcasecmp(str, "Duration"))
1191 return AVRCP_MEDIA_ATTRIBUTE_DURATION;
1196 static const char *metadata_to_str(uint32_t id)
1199 case AVRCP_MEDIA_ATTRIBUTE_TITLE:
1201 case AVRCP_MEDIA_ATTRIBUTE_ARTIST:
1203 case AVRCP_MEDIA_ATTRIBUTE_ALBUM:
1205 case AVRCP_MEDIA_ATTRIBUTE_GENRE:
1207 case AVRCP_MEDIA_ATTRIBUTE_TRACK:
1209 case AVRCP_MEDIA_ATTRIBUTE_N_TRACKS:
1210 return "NumberOfTracks";
1211 case AVRCP_MEDIA_ATTRIBUTE_DURATION:
1218 static int get_setting(uint8_t attr, void *user_data)
1220 struct media_player *mp = user_data;
1221 guint attr_uint = attr;
1224 DBG("%s", attr_to_str(attr));
1226 value = g_hash_table_lookup(mp->settings, GUINT_TO_POINTER(attr_uint));
1230 return GPOINTER_TO_UINT(value);
1233 static int set_setting(uint8_t attr, uint8_t val, void *user_data)
1235 struct media_player *mp = user_data;
1236 struct media_adapter *adapter = mp->adapter;
1237 const char *property, *value;
1238 guint attr_uint = attr;
1240 DBusMessageIter iter, var;
1242 property = attr_to_str(attr);
1243 value = attrval_to_str(attr, val);
1245 DBG("%s = %s", property, value);
1247 if (property == NULL || value == NULL)
1250 if (!g_hash_table_lookup(mp->settings, GUINT_TO_POINTER(attr_uint)))
1253 msg = dbus_message_new_method_call(mp->sender, mp->path,
1254 MEDIA_PLAYER_INTERFACE,
1257 error("Couldn't allocate D-Bus message");
1261 dbus_message_iter_init_append(msg, &iter);
1262 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
1264 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1265 DBUS_TYPE_STRING_AS_STRING,
1267 dbus_message_iter_append_basic(&var, DBUS_TYPE_STRING, &value);
1268 dbus_message_iter_close_container(&iter, &var);
1270 g_dbus_send_message(adapter->conn, msg);
1275 static GList *list_metadata(void *user_data)
1277 struct media_player *mp = user_data;
1281 if (mp->track == NULL)
1284 return g_hash_table_get_keys(mp->track);
1287 static uint64_t get_uid(void *user_data)
1289 struct media_player *mp = user_data;
1291 DBG("%p", mp->track);
1293 if (mp->track == NULL)
1299 static void *get_metadata(uint32_t id, void *user_data)
1301 struct media_player *mp = user_data;
1302 struct metadata_value *value;
1304 DBG("%s", metadata_to_str(id));
1306 if (mp->track == NULL)
1309 value = g_hash_table_lookup(mp->track, GUINT_TO_POINTER(id));
1313 switch (value->type) {
1314 case DBUS_TYPE_STRING:
1315 return value->value.str;
1316 case DBUS_TYPE_UINT32:
1317 return GUINT_TO_POINTER(value->value.num);
1323 static uint8_t get_status(void *user_data)
1325 struct media_player *mp = user_data;
1330 static uint32_t get_position(void *user_data)
1332 struct media_player *mp = user_data;
1336 if (mp->status != AVRCP_PLAY_STATUS_PLAYING)
1337 return mp->position;
1339 timedelta = g_timer_elapsed(mp->timer, NULL);
1341 sec = (uint32_t) timedelta;
1342 msec = (uint32_t) ((timedelta - sec) * 1000);
1344 return mp->position + sec * 1000 + msec;
1347 static void set_volume(uint8_t volume, struct audio_device *dev, void *user_data)
1349 struct media_player *mp = user_data;
1352 if (mp->volume == volume)
1355 mp->volume = volume;
1357 for (l = mp->adapter->endpoints; l; l = l->next) {
1358 struct media_endpoint *endpoint = l->data;
1359 struct media_transport *transport;
1361 /* Volume is A2DP only */
1362 if (endpoint->sep == NULL)
1365 transport = find_device_transport(endpoint, dev);
1366 if (transport == NULL)
1369 media_transport_update_volume(transport, volume);
1373 static struct avrcp_player_cb player_cb = {
1374 .get_setting = get_setting,
1375 .set_setting = set_setting,
1376 .list_metadata = list_metadata,
1378 .get_metadata = get_metadata,
1379 .get_position = get_position,
1380 .get_status = get_status,
1381 .set_volume = set_volume
1384 static void media_player_exit(DBusConnection *connection, void *user_data)
1386 struct media_player *mp = user_data;
1389 media_player_remove(mp);
1392 static gboolean set_status(struct media_player *mp, DBusMessageIter *iter)
1397 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
1400 dbus_message_iter_get_basic(iter, &value);
1401 DBG("Status=%s", value);
1403 val = play_status_to_val(value);
1405 error("Invalid status");
1409 if (mp->status == val)
1412 mp->position = get_position(mp);
1413 g_timer_start(mp->timer);
1417 avrcp_player_event(mp->player, AVRCP_EVENT_STATUS_CHANGED, &val);
1422 static gboolean set_position(struct media_player *mp, DBusMessageIter *iter)
1425 struct metadata_value *duration;
1427 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT32)
1430 dbus_message_iter_get_basic(iter, &value);
1431 DBG("Position=%u", value);
1433 mp->position = value;
1434 g_timer_start(mp->timer);
1436 if (!mp->position) {
1437 avrcp_player_event(mp->player,
1438 AVRCP_EVENT_TRACK_REACHED_START, NULL);
1442 duration = g_hash_table_lookup(mp->track, GUINT_TO_POINTER(
1443 AVRCP_MEDIA_ATTRIBUTE_DURATION));
1446 * If position is the maximum value allowed or greater than track's
1447 * duration, we send a track-reached-end event.
1449 if (mp->position == UINT32_MAX ||
1450 (duration && mp->position >= duration->value.num))
1451 avrcp_player_event(mp->player, AVRCP_EVENT_TRACK_REACHED_END,
1457 static gboolean set_property(struct media_player *mp, const char *key,
1458 DBusMessageIter *entry)
1460 DBusMessageIter var;
1464 if (dbus_message_iter_get_arg_type(entry) != DBUS_TYPE_VARIANT)
1467 dbus_message_iter_recurse(entry, &var);
1469 if (strcasecmp(key, "Status") == 0)
1470 return set_status(mp, &var);
1472 if (strcasecmp(key, "Position") == 0)
1473 return set_position(mp, &var);
1475 attr = attr_to_val(key);
1479 if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
1482 dbus_message_iter_get_basic(&var, &value);
1484 val = attrval_to_val(attr, value);
1488 DBG("%s=%s", key, value);
1490 g_hash_table_replace(mp->settings, GUINT_TO_POINTER(attr),
1491 GUINT_TO_POINTER(val));
1496 static gboolean property_changed(DBusConnection *connection, DBusMessage *msg,
1499 struct media_player *mp = user_data;
1500 DBusMessageIter iter;
1501 const char *property;
1503 DBG("sender=%s path=%s", mp->sender, mp->path);
1505 dbus_message_iter_init(msg, &iter);
1507 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
1508 error("Unexpected signature in %s.%s signal",
1509 dbus_message_get_interface(msg),
1510 dbus_message_get_member(msg));
1514 dbus_message_iter_get_basic(&iter, &property);
1516 dbus_message_iter_next(&iter);
1518 set_property(mp, property, &iter);
1523 static void metadata_value_free(gpointer data)
1525 struct metadata_value *value = data;
1527 switch (value->type) {
1528 case DBUS_TYPE_STRING:
1529 g_free(value->value.str);
1536 static gboolean parse_player_metadata(struct media_player *mp,
1537 DBusMessageIter *iter)
1539 DBusMessageIter dict;
1540 DBusMessageIter var;
1543 gboolean title = FALSE;
1546 ctype = dbus_message_iter_get_arg_type(iter);
1547 if (ctype != DBUS_TYPE_ARRAY)
1550 dbus_message_iter_recurse(iter, &dict);
1552 track = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
1553 metadata_value_free);
1555 while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
1556 DBUS_TYPE_INVALID) {
1557 DBusMessageIter entry;
1559 struct metadata_value *value;
1562 if (ctype != DBUS_TYPE_DICT_ENTRY)
1565 dbus_message_iter_recurse(&dict, &entry);
1566 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1569 dbus_message_iter_get_basic(&entry, &key);
1570 dbus_message_iter_next(&entry);
1572 id = metadata_to_val(key);
1576 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1579 dbus_message_iter_recurse(&entry, &var);
1581 value = g_new0(struct metadata_value, 1);
1582 value->type = dbus_message_iter_get_arg_type(&var);
1585 case AVRCP_MEDIA_ATTRIBUTE_TITLE:
1587 case AVRCP_MEDIA_ATTRIBUTE_ARTIST:
1588 case AVRCP_MEDIA_ATTRIBUTE_ALBUM:
1589 case AVRCP_MEDIA_ATTRIBUTE_GENRE:
1590 if (value->type != DBUS_TYPE_STRING) {
1595 dbus_message_iter_get_basic(&var, &value->value.str);
1597 case AVRCP_MEDIA_ATTRIBUTE_TRACK:
1598 case AVRCP_MEDIA_ATTRIBUTE_N_TRACKS:
1599 case AVRCP_MEDIA_ATTRIBUTE_DURATION:
1600 if (value->type != DBUS_TYPE_UINT32) {
1605 dbus_message_iter_get_basic(&var, &value->value.num);
1611 switch (value->type) {
1612 case DBUS_TYPE_STRING:
1613 value->value.str = g_strdup(value->value.str);
1614 DBG("%s=%s", key, value->value.str);
1617 DBG("%s=%u", key, value->value.num);
1620 g_hash_table_replace(track, GUINT_TO_POINTER(id), value);
1621 dbus_message_iter_next(&dict);
1624 if (g_hash_table_size(track) == 0) {
1625 g_hash_table_unref(track);
1627 } else if (title == FALSE) {
1628 struct metadata_value *value = g_new(struct metadata_value, 1);
1629 uint32_t id = AVRCP_MEDIA_ATTRIBUTE_TITLE;
1631 value->type = DBUS_TYPE_STRING;
1632 value->value.str = g_strdup("");
1633 g_hash_table_insert(track, GUINT_TO_POINTER(id), value);
1636 if (mp->track != NULL)
1637 g_hash_table_unref(mp->track);
1641 g_timer_start(mp->timer);
1644 avrcp_player_event(mp->player, AVRCP_EVENT_TRACK_CHANGED, &uid);
1645 avrcp_player_event(mp->player, AVRCP_EVENT_TRACK_REACHED_START,
1652 g_hash_table_unref(track);
1657 static gboolean track_changed(DBusConnection *connection, DBusMessage *msg,
1660 struct media_player *mp = user_data;
1661 DBusMessageIter iter;
1663 DBG("sender=%s path=%s", mp->sender, mp->path);
1665 dbus_message_iter_init(msg, &iter);
1667 if (parse_player_metadata(mp, &iter) == FALSE) {
1668 error("Unexpected signature in %s.%s signal",
1669 dbus_message_get_interface(msg),
1670 dbus_message_get_member(msg));
1676 static struct media_player *media_player_create(struct media_adapter *adapter,
1681 struct media_player *mp;
1683 mp = g_new0(struct media_player, 1);
1684 mp->adapter = adapter;
1685 mp->sender = g_strdup(sender);
1686 mp->path = g_strdup(path);
1687 mp->timer = g_timer_new();
1689 mp->watch = g_dbus_add_disconnect_watch(adapter->conn, sender,
1690 media_player_exit, mp,
1692 mp->property_watch = g_dbus_add_signal_watch(adapter->conn, sender,
1693 path, MEDIA_PLAYER_INTERFACE,
1697 mp->track_watch = g_dbus_add_signal_watch(adapter->conn, sender,
1698 path, MEDIA_PLAYER_INTERFACE,
1702 mp->player = avrcp_register_player(&adapter->src, &player_cb, mp,
1706 *err = -EPROTONOSUPPORT;
1707 media_player_destroy(mp);
1711 mp->settings = g_hash_table_new(g_direct_hash, g_direct_equal);
1713 adapter->players = g_slist_append(adapter->players, mp);
1715 info("Player registered: sender=%s path=%s", sender, path);
1723 static gboolean parse_player_properties(struct media_player *mp,
1724 DBusMessageIter *iter)
1726 DBusMessageIter dict;
1729 ctype = dbus_message_iter_get_arg_type(iter);
1730 if (ctype != DBUS_TYPE_ARRAY)
1733 dbus_message_iter_recurse(iter, &dict);
1735 while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
1736 DBUS_TYPE_INVALID) {
1737 DBusMessageIter entry;
1740 if (ctype != DBUS_TYPE_DICT_ENTRY)
1743 dbus_message_iter_recurse(&dict, &entry);
1744 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1747 dbus_message_iter_get_basic(&entry, &key);
1748 dbus_message_iter_next(&entry);
1750 if (set_property(mp, key, &entry) == FALSE)
1753 dbus_message_iter_next(&dict);
1759 static DBusMessage *register_player(DBusConnection *conn, DBusMessage *msg,
1762 struct media_adapter *adapter = data;
1763 struct media_player *mp;
1764 DBusMessageIter args;
1765 const char *sender, *path;
1768 sender = dbus_message_get_sender(msg);
1770 dbus_message_iter_init(msg, &args);
1772 dbus_message_iter_get_basic(&args, &path);
1773 dbus_message_iter_next(&args);
1775 if (media_adapter_find_player(adapter, sender, path) != NULL)
1776 return btd_error_already_exists(msg);
1778 mp = media_player_create(adapter, sender, path, &err);
1780 if (err == -EPROTONOSUPPORT)
1781 return btd_error_not_supported(msg);
1783 return btd_error_invalid_args(msg);
1786 if (parse_player_properties(mp, &args) == FALSE) {
1787 media_player_destroy(mp);
1788 return btd_error_invalid_args(msg);
1791 dbus_message_iter_next(&args);
1793 if (parse_player_metadata(mp, &args) == FALSE) {
1794 media_player_destroy(mp);
1795 return btd_error_invalid_args(msg);
1798 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1801 static DBusMessage *unregister_player(DBusConnection *conn, DBusMessage *msg,
1804 struct media_adapter *adapter = data;
1805 struct media_player *player;
1806 const char *sender, *path;
1808 if (!dbus_message_get_args(msg, NULL,
1809 DBUS_TYPE_OBJECT_PATH, &path,
1813 sender = dbus_message_get_sender(msg);
1815 player = media_adapter_find_player(adapter, sender, path);
1817 return btd_error_does_not_exist(msg);
1819 media_player_remove(player);
1821 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1824 static const GDBusMethodTable media_methods[] = {
1825 { GDBUS_METHOD("RegisterEndpoint",
1826 GDBUS_ARGS({ "endpoint", "o" }, { "properties", "a{sv}" }),
1827 NULL, register_endpoint) },
1828 { GDBUS_METHOD("UnregisterEndpoint",
1829 GDBUS_ARGS({ "endpoint", "o" }), NULL, unregister_endpoint) },
1830 { GDBUS_METHOD("RegisterPlayer",
1831 GDBUS_ARGS({ "player", "o" }, { "properties", "a{sv}" },
1832 { "metadata", "a{sv}" }),
1833 NULL, register_player) },
1834 { GDBUS_METHOD("UnregisterPlayer",
1835 GDBUS_ARGS({ "player", "o" }), NULL, unregister_player) },
1839 static void path_free(void *data)
1841 struct media_adapter *adapter = data;
1843 while (adapter->endpoints)
1844 release_endpoint(adapter->endpoints->data);
1846 dbus_connection_unref(adapter->conn);
1848 adapters = g_slist_remove(adapters, adapter);
1850 g_free(adapter->path);
1854 int media_register(DBusConnection *conn, const char *path, const bdaddr_t *src)
1856 struct media_adapter *adapter;
1858 adapter = g_new0(struct media_adapter, 1);
1859 adapter->conn = dbus_connection_ref(conn);
1860 bacpy(&adapter->src, src);
1861 adapter->path = g_strdup(path);
1863 if (!g_dbus_register_interface(conn, path, MEDIA_INTERFACE,
1864 media_methods, NULL, NULL,
1865 adapter, path_free)) {
1866 error("D-Bus failed to register %s path", path);
1871 adapters = g_slist_append(adapters, adapter);
1876 void media_unregister(const char *path)
1880 for (l = adapters; l; l = l->next) {
1881 struct media_adapter *adapter = l->data;
1883 if (g_strcmp0(path, adapter->path) == 0) {
1884 g_dbus_unregister_interface(adapter->conn, path,
1891 struct a2dp_sep *media_endpoint_get_sep(struct media_endpoint *endpoint)
1893 return endpoint->sep;
1896 const char *media_endpoint_get_uuid(struct media_endpoint *endpoint)
1898 return endpoint->uuid;
1901 uint8_t media_endpoint_get_codec(struct media_endpoint *endpoint)
1903 return endpoint->codec;