Tizen 2.0 Release
[profile/ivi/bluez.git] / audio / media.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
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.
8  *
9  *
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.
14  *
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.
19  *
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
23  *
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #include <errno.h>
31
32 #include <bluetooth/uuid.h>
33
34 #include <glib.h>
35 #include <gdbus.h>
36
37 #include "../src/adapter.h"
38 #include "../src/dbus-common.h"
39
40 #include "glib-helper.h"
41 #include "log.h"
42 #include "error.h"
43 #include "device.h"
44 #include "avdtp.h"
45 #include "media.h"
46 #include "transport.h"
47 #include "a2dp.h"
48 #include "avrcp.h"
49 #include "headset.h"
50 #include "gateway.h"
51 #include "manager.h"
52
53 #define MEDIA_INTERFACE "org.bluez.Media"
54 #define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint"
55 #define MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer"
56
57 #define REQUEST_TIMEOUT (3 * 1000)              /* 3 seconds */
58
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 */
65 };
66
67 struct endpoint_request {
68         struct media_endpoint   *endpoint;
69         DBusMessage             *msg;
70         DBusPendingCall         *call;
71         media_endpoint_cb_t     cb;
72         GDestroyNotify          destroy;
73         void                    *user_data;
74 };
75
76 struct media_endpoint {
77         struct a2dp_sep         *sep;
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 */
84         guint                   hs_watch;
85         guint                   ag_watch;
86         guint                   watch;
87         GSList                  *requests;
88         struct media_adapter    *adapter;
89         GSList                  *transports;
90 };
91
92 struct media_player {
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 */
99         guint                   watch;
100         guint                   property_watch;
101         guint                   track_watch;
102         uint8_t                 status;
103         uint32_t                position;
104         uint8_t                 volume;
105         GTimer                  *timer;
106 };
107
108 struct metadata_value {
109         int                     type;
110         union {
111                 char            *str;
112                 uint32_t        num;
113         } value;
114 };
115
116 static GSList *adapters = NULL;
117
118 static void endpoint_request_free(struct endpoint_request *request)
119 {
120         if (request->call)
121                 dbus_pending_call_unref(request->call);
122
123         if (request->destroy)
124                 request->destroy(request->user_data);
125
126         dbus_message_unref(request->msg);
127         g_free(request);
128 }
129
130 static void media_endpoint_cancel(struct endpoint_request *request)
131 {
132         struct media_endpoint *endpoint = request->endpoint;
133
134         if (request->call)
135                 dbus_pending_call_cancel(request->call);
136
137         endpoint->requests = g_slist_remove(endpoint->requests, request);
138
139         endpoint_request_free(request);
140 }
141
142 static void media_endpoint_cancel_all(struct media_endpoint *endpoint)
143 {
144         while (endpoint->requests != NULL)
145                 media_endpoint_cancel(endpoint->requests->data);
146 }
147
148 static void media_endpoint_destroy(struct media_endpoint *endpoint)
149 {
150         struct media_adapter *adapter = endpoint->adapter;
151
152         DBG("sender=%s path=%s", endpoint->sender, endpoint->path);
153
154         if (endpoint->hs_watch)
155                 headset_remove_state_cb(endpoint->hs_watch);
156
157         if (endpoint->ag_watch)
158                 gateway_remove_state_cb(endpoint->ag_watch);
159
160         media_endpoint_cancel_all(endpoint);
161
162         g_slist_free_full(endpoint->transports,
163                                 (GDestroyNotify) media_transport_destroy);
164
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);
170         g_free(endpoint);
171 }
172
173 static void media_endpoint_remove(struct media_endpoint *endpoint)
174 {
175         struct media_adapter *adapter = endpoint->adapter;
176
177         if (endpoint->sep) {
178                 a2dp_remove_sep(endpoint->sep);
179                 return;
180         }
181
182         info("Endpoint unregistered: sender=%s path=%s", endpoint->sender,
183                         endpoint->path);
184
185         adapter->endpoints = g_slist_remove(adapter->endpoints, endpoint);
186
187         media_endpoint_destroy(endpoint);
188 }
189
190 static void media_endpoint_exit(DBusConnection *connection, void *user_data)
191 {
192         struct media_endpoint *endpoint = user_data;
193
194         endpoint->watch = 0;
195         media_endpoint_remove(endpoint);
196 }
197
198 static void headset_setconf_cb(struct media_endpoint *endpoint, void *ret,
199                                                 int size, void *user_data)
200 {
201         struct audio_device *dev = user_data;
202
203         if (ret != NULL)
204                 return;
205
206         headset_shutdown(dev);
207 }
208
209 static void clear_configuration(struct media_endpoint *endpoint,
210                                         struct media_transport *transport)
211 {
212         DBusConnection *conn;
213         DBusMessage *msg;
214         const char *path;
215
216         conn = endpoint->adapter->conn;
217
218         msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
219                                                 MEDIA_ENDPOINT_INTERFACE,
220                                                 "ClearConfiguration");
221         if (msg == NULL) {
222                 error("Couldn't allocate D-Bus message");
223                 goto done;
224         }
225
226         path = media_transport_get_path(transport);
227         dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &path,
228                                                         DBUS_TYPE_INVALID);
229         g_dbus_send_message(conn, msg);
230 done:
231         endpoint->transports = g_slist_remove(endpoint->transports, transport);
232         media_transport_destroy(transport);
233 }
234
235 static void clear_endpoint(struct media_endpoint *endpoint)
236 {
237         media_endpoint_cancel_all(endpoint);
238
239         while (endpoint->transports != NULL)
240                 clear_configuration(endpoint, endpoint->transports->data);
241 }
242
243 static void endpoint_reply(DBusPendingCall *call, void *user_data)
244 {
245         struct endpoint_request *request = user_data;
246         struct media_endpoint *endpoint = request->endpoint;
247         DBusMessage *reply;
248         DBusError err;
249         gboolean value;
250         void *ret = NULL;
251         int size = -1;
252
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);
256
257         dbus_error_init(&err);
258         if (dbus_set_error_from_message(&err, reply)) {
259                 error("Endpoint replied with an error: %s",
260                                 err.name);
261
262                 /* Clear endpoint configuration in case of NO_REPLY error */
263                 if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY)) {
264                         if (request->cb)
265                                 request->cb(endpoint, NULL, size,
266                                                         request->user_data);
267                         clear_endpoint(endpoint);
268                         dbus_message_unref(reply);
269                         dbus_error_free(&err);
270                         return;
271                 }
272
273                 dbus_error_free(&err);
274                 goto done;
275         }
276
277         if (dbus_message_is_method_call(request->msg, MEDIA_ENDPOINT_INTERFACE,
278                                 "SelectConfiguration")) {
279                 DBusMessageIter args, array;
280                 uint8_t *configuration;
281
282                 dbus_message_iter_init(reply, &args);
283
284                 dbus_message_iter_recurse(&args, &array);
285
286                 dbus_message_iter_get_fixed_array(&array, &configuration, &size);
287
288                 ret = configuration;
289                 goto done;
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);
293                 goto done;
294         }
295
296         size = 1;
297         value = TRUE;
298         ret = &value;
299
300 done:
301         dbus_message_unref(reply);
302
303         if (request->cb)
304                 request->cb(endpoint, ret, size, request->user_data);
305
306         endpoint->requests = g_slist_remove(endpoint->requests, request);
307         endpoint_request_free(request);
308 }
309
310 static gboolean media_endpoint_async_call(DBusConnection *conn,
311                                         DBusMessage *msg,
312                                         struct media_endpoint *endpoint,
313                                         media_endpoint_cb_t cb,
314                                         void *user_data,
315                                         GDestroyNotify destroy)
316 {
317         struct endpoint_request *request;
318
319         request = g_new0(struct endpoint_request, 1);
320
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");
325                 g_free(request);
326                 return FALSE;
327         }
328
329         dbus_pending_call_set_notify(request->call, endpoint_reply, request,
330                                                                         NULL);
331
332         request->endpoint = endpoint;
333         request->msg = msg;
334         request->cb = cb;
335         request->destroy = destroy;
336         request->user_data = user_data;
337
338         endpoint->requests = g_slist_append(endpoint->requests, request);
339
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));
343
344         return TRUE;
345 }
346
347 static gboolean select_configuration(struct media_endpoint *endpoint,
348                                                 uint8_t *capabilities,
349                                                 size_t length,
350                                                 media_endpoint_cb_t cb,
351                                                 void *user_data,
352                                                 GDestroyNotify destroy)
353 {
354         DBusConnection *conn;
355         DBusMessage *msg;
356
357         conn = endpoint->adapter->conn;
358
359         msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
360                                                 MEDIA_ENDPOINT_INTERFACE,
361                                                 "SelectConfiguration");
362         if (msg == NULL) {
363                 error("Couldn't allocate D-Bus message");
364                 return FALSE;
365         }
366
367         dbus_message_append_args(msg, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
368                                         &capabilities, length,
369                                         DBUS_TYPE_INVALID);
370
371         return media_endpoint_async_call(conn, msg, endpoint, cb, user_data,
372                                                                 destroy);
373 }
374
375 static gint transport_device_cmp(gconstpointer data, gconstpointer user_data)
376 {
377         struct media_transport *transport = (struct media_transport *) data;
378         const struct audio_device *device = user_data;
379
380         if (device == media_transport_get_dev(transport))
381                 return 0;
382
383         return -1;
384 }
385
386 static struct media_transport *find_device_transport(
387                                         struct media_endpoint *endpoint,
388                                         struct audio_device *device)
389 {
390         GSList *match;
391
392         match = g_slist_find_custom(endpoint->transports, device,
393                                                         transport_device_cmp);
394         if (match == NULL)
395                 return NULL;
396
397         return match->data;
398 }
399
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,
404                                         void *user_data,
405                                         GDestroyNotify destroy)
406 {
407         DBusConnection *conn;
408         DBusMessage *msg;
409         const char *path;
410         DBusMessageIter iter;
411         struct media_transport *transport;
412
413         transport = find_device_transport(endpoint, device);
414
415         if (transport != NULL)
416                 return FALSE;
417
418         conn = endpoint->adapter->conn;
419
420         transport = media_transport_create(conn, endpoint, device,
421                                                 configuration, size);
422         if (transport == NULL)
423                 return FALSE;
424
425         msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
426                                                 MEDIA_ENDPOINT_INTERFACE,
427                                                 "SetConfiguration");
428         if (msg == NULL) {
429                 error("Couldn't allocate D-Bus message");
430                 media_transport_destroy(transport);
431                 return FALSE;
432         }
433
434         endpoint->transports = g_slist_append(endpoint->transports, transport);
435
436         dbus_message_iter_init_append(msg, &iter);
437
438         path = media_transport_get_path(transport);
439         dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
440
441         transport_get_properties(transport, &iter);
442
443         return media_endpoint_async_call(conn, msg, endpoint, cb, user_data,
444                                                                 destroy);
445 }
446
447 static void release_endpoint(struct media_endpoint *endpoint)
448 {
449         DBusMessage *msg;
450
451         DBG("sender=%s path=%s", endpoint->sender, endpoint->path);
452
453         /* already exit */
454         if (endpoint->watch == 0)
455                 goto done;
456
457         msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
458                                                 MEDIA_ENDPOINT_INTERFACE,
459                                                 "Release");
460         if (msg == NULL) {
461                 error("Couldn't allocate D-Bus message");
462                 return;
463         }
464
465         g_dbus_send_message(endpoint->adapter->conn, msg);
466
467 done:
468         media_endpoint_remove(endpoint);
469 }
470
471 static void headset_state_changed(struct audio_device *dev,
472                                         headset_state_t old_state,
473                                         headset_state_t new_state,
474                                         void *user_data)
475 {
476         struct media_endpoint *endpoint = user_data;
477         struct media_transport *transport;
478
479         DBG("");
480
481         if (bacmp(&endpoint->adapter->src, &dev->src) != 0)
482                 return;
483
484         switch (new_state) {
485         case HEADSET_STATE_DISCONNECTED:
486                 transport = find_device_transport(endpoint, dev);
487
488                 if (transport != NULL) {
489                         DBG("Clear endpoint %p", endpoint);
490                         clear_configuration(endpoint, transport);
491                 }
492                 break;
493         case HEADSET_STATE_CONNECTING:
494                 set_configuration(endpoint, dev, NULL, 0, headset_setconf_cb,
495                                                                 dev, NULL);
496                 break;
497         case HEADSET_STATE_CONNECTED:
498                 break;
499         case HEADSET_STATE_PLAY_IN_PROGRESS:
500                 break;
501         case HEADSET_STATE_PLAYING:
502                 break;
503         }
504 }
505
506 static const char *get_name(struct a2dp_sep *sep, void *user_data)
507 {
508         struct media_endpoint *endpoint = user_data;
509
510         return endpoint->sender;
511 }
512
513 static size_t get_capabilities(struct a2dp_sep *sep, uint8_t **capabilities,
514                                                         void *user_data)
515 {
516         struct media_endpoint *endpoint = user_data;
517
518         *capabilities = endpoint->capabilities;
519         return endpoint->size;
520 }
521
522 struct a2dp_config_data {
523         struct a2dp_setup *setup;
524         a2dp_endpoint_config_t cb;
525 };
526
527 struct a2dp_select_data {
528         struct a2dp_setup *setup;
529         a2dp_endpoint_select_t cb;
530 };
531
532 static void select_cb(struct media_endpoint *endpoint, void *ret, int size,
533                                                         void *user_data)
534 {
535         struct a2dp_select_data *data = user_data;
536
537         data->cb(data->setup, ret, size);
538 }
539
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)
543 {
544         struct media_endpoint *endpoint = user_data;
545         struct a2dp_select_data *data;
546
547         data = g_new0(struct a2dp_select_data, 1);
548         data->setup = setup;
549         data->cb = cb;
550
551         if (select_configuration(endpoint, capabilities, length,
552                                         select_cb, data, g_free) == TRUE)
553                 return 0;
554
555         g_free(data);
556         return -ENOMEM;
557 }
558
559 static void config_cb(struct media_endpoint *endpoint, void *ret, int size,
560                                                         void *user_data)
561 {
562         struct a2dp_config_data *data = user_data;
563
564         data->cb(data->setup, ret ? TRUE : FALSE);
565 }
566
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,
571                                 void *user_data)
572 {
573         struct media_endpoint *endpoint = user_data;
574         struct a2dp_config_data *data;
575
576         data = g_new0(struct a2dp_config_data, 1);
577         data->setup = setup;
578         data->cb = cb;
579
580         if (set_configuration(endpoint, dev, configuration, length,
581                                         config_cb, data, g_free) == TRUE)
582                 return 0;
583
584         g_free(data);
585         return -ENOMEM;
586 }
587
588 static void clear_config(struct a2dp_sep *sep, void *user_data)
589 {
590         struct media_endpoint *endpoint = user_data;
591
592         clear_endpoint(endpoint);
593 }
594
595 static void set_delay(struct a2dp_sep *sep, uint16_t delay, void *user_data)
596 {
597         struct media_endpoint *endpoint = user_data;
598
599         if (endpoint->transports == NULL)
600                 return;
601
602         media_transport_update_delay(endpoint->transports->data, delay);
603 }
604
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
612 };
613
614 static void a2dp_destroy_endpoint(void *user_data)
615 {
616         struct media_endpoint *endpoint = user_data;
617
618         clear_endpoint(endpoint);
619
620         endpoint->sep = NULL;
621         release_endpoint(endpoint);
622 }
623
624 static void gateway_setconf_cb(struct media_endpoint *endpoint, void *ret,
625                                                 int size, void *user_data)
626 {
627         struct audio_device *dev = user_data;
628
629         if (ret != NULL)
630                 return;
631
632         gateway_set_state(dev, GATEWAY_STATE_DISCONNECTED);
633 }
634
635 static void gateway_state_changed(struct audio_device *dev,
636                                         gateway_state_t old_state,
637                                         gateway_state_t new_state,
638                                         void *user_data)
639 {
640         struct media_endpoint *endpoint = user_data;
641         struct media_transport *transport;
642
643         DBG("");
644
645         if (bacmp(&endpoint->adapter->src, &dev->src) != 0)
646                 return;
647
648         switch (new_state) {
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);
654                 }
655                 break;
656         case GATEWAY_STATE_CONNECTING:
657                 set_configuration(endpoint, dev, NULL, 0,
658                                         gateway_setconf_cb, dev, NULL);
659                 break;
660         case GATEWAY_STATE_CONNECTED:
661                 break;
662         case GATEWAY_STATE_PLAYING:
663                 break;
664         }
665 }
666
667 static gboolean endpoint_init_a2dp_source(struct media_endpoint *endpoint,
668                                                 gboolean delay_reporting,
669                                                 int *err)
670 {
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)
676                 return FALSE;
677
678         return TRUE;
679 }
680
681 static gboolean endpoint_init_a2dp_sink(struct media_endpoint *endpoint,
682                                                 gboolean delay_reporting,
683                                                 int *err)
684 {
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)
690                 return FALSE;
691
692         return TRUE;
693 }
694
695 static gboolean endpoint_init_ag(struct media_endpoint *endpoint, int *err)
696 {
697         GSList *list;
698         GSList *l;
699
700         endpoint->hs_watch = headset_add_state_cb(headset_state_changed,
701                                                                 endpoint);
702         list = manager_find_devices(NULL, &endpoint->adapter->src, BDADDR_ANY,
703                                                 AUDIO_HEADSET_INTERFACE, TRUE);
704
705         for (l = list; l != NULL; l = l->next) {
706                 struct audio_device *dev = l->data;
707
708                 set_configuration(endpoint, dev, NULL, 0,
709                                                 headset_setconf_cb, dev, NULL);
710         }
711
712         g_slist_free(list);
713
714         return TRUE;
715 }
716
717 static gboolean endpoint_init_hs(struct media_endpoint *endpoint, int *err)
718 {
719         GSList *list;
720         GSList *l;
721
722         endpoint->ag_watch = gateway_add_state_cb(gateway_state_changed,
723                                                                 endpoint);
724         list = manager_find_devices(NULL, &endpoint->adapter->src, BDADDR_ANY,
725                                                 AUDIO_GATEWAY_INTERFACE, TRUE);
726
727         for (l = list; l != NULL; l = l->next) {
728                 struct audio_device *dev = l->data;
729
730                 set_configuration(endpoint, dev, NULL, 0,
731                                                 gateway_setconf_cb, dev, NULL);
732         }
733
734         g_slist_free(list);
735
736         return TRUE;
737 }
738
739 static struct media_endpoint *media_endpoint_create(struct media_adapter *adapter,
740                                                 const char *sender,
741                                                 const char *path,
742                                                 const char *uuid,
743                                                 gboolean delay_reporting,
744                                                 uint8_t codec,
745                                                 uint8_t *capabilities,
746                                                 int size,
747                                                 int *err)
748 {
749         struct media_endpoint *endpoint;
750         gboolean succeeded;
751
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;
757
758         if (size > 0) {
759                 endpoint->capabilities = g_new(uint8_t, size);
760                 memcpy(endpoint->capabilities, capabilities, size);
761                 endpoint->size = size;
762         }
763
764         endpoint->adapter = adapter;
765
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);
778         else {
779                 succeeded = FALSE;
780
781                 if (err)
782                         *err = -EINVAL;
783         }
784
785         if (!succeeded) {
786                 g_free(endpoint);
787                 return NULL;
788         }
789
790         endpoint->watch = g_dbus_add_disconnect_watch(adapter->conn, sender,
791                                                 media_endpoint_exit, endpoint,
792                                                 NULL);
793
794         adapter->endpoints = g_slist_append(adapter->endpoints, endpoint);
795         info("Endpoint registered: sender=%s path=%s", sender, path);
796
797         if (err)
798                 *err = 0;
799         return endpoint;
800 }
801
802 static struct media_endpoint *media_adapter_find_endpoint(
803                                                 struct media_adapter *adapter,
804                                                 const char *sender,
805                                                 const char *path,
806                                                 const char *uuid)
807 {
808         GSList *l;
809
810         for (l = adapter->endpoints; l; l = l->next) {
811                 struct media_endpoint *endpoint = l->data;
812
813                 if (sender && g_strcmp0(endpoint->sender, sender) != 0)
814                         continue;
815
816                 if (path && g_strcmp0(endpoint->path, path) != 0)
817                         continue;
818
819                 if (uuid && g_strcmp0(endpoint->uuid, uuid) != 0)
820                         continue;
821
822                 return endpoint;
823         }
824
825         return NULL;
826 }
827
828 static int parse_properties(DBusMessageIter *props, const char **uuid,
829                                 gboolean *delay_reporting, uint8_t *codec,
830                                 uint8_t **capabilities, int *size)
831 {
832         gboolean has_uuid = FALSE;
833         gboolean has_codec = FALSE;
834
835         while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
836                 const char *key;
837                 DBusMessageIter value, entry;
838                 int var;
839
840                 dbus_message_iter_recurse(props, &entry);
841                 dbus_message_iter_get_basic(&entry, &key);
842
843                 dbus_message_iter_next(&entry);
844                 dbus_message_iter_recurse(&entry, &value);
845
846                 var = dbus_message_iter_get_arg_type(&value);
847                 if (strcasecmp(key, "UUID") == 0) {
848                         if (var != DBUS_TYPE_STRING)
849                                 return -EINVAL;
850                         dbus_message_iter_get_basic(&value, uuid);
851                         has_uuid = TRUE;
852                 } else if (strcasecmp(key, "Codec") == 0) {
853                         if (var != DBUS_TYPE_BYTE)
854                                 return -EINVAL;
855                         dbus_message_iter_get_basic(&value, codec);
856                         has_codec = TRUE;
857                 } else if (strcasecmp(key, "DelayReporting") == 0) {
858                         if (var != DBUS_TYPE_BOOLEAN)
859                                 return -EINVAL;
860                         dbus_message_iter_get_basic(&value, delay_reporting);
861                 } else if (strcasecmp(key, "Capabilities") == 0) {
862                         DBusMessageIter array;
863
864                         if (var != DBUS_TYPE_ARRAY)
865                                 return -EINVAL;
866
867                         dbus_message_iter_recurse(&value, &array);
868                         dbus_message_iter_get_fixed_array(&array, capabilities,
869                                                         size);
870                 }
871
872                 dbus_message_iter_next(props);
873         }
874
875         return (has_uuid && has_codec) ? 0 : -EINVAL;
876 }
877
878 static DBusMessage *register_endpoint(DBusConnection *conn, DBusMessage *msg,
879                                         void *data)
880 {
881         struct media_adapter *adapter = data;
882         DBusMessageIter args, props;
883         const char *sender, *path, *uuid;
884         gboolean delay_reporting = FALSE;
885         uint8_t codec;
886         uint8_t *capabilities;
887         int size = 0;
888         int err;
889
890         sender = dbus_message_get_sender(msg);
891
892         dbus_message_iter_init(msg, &args);
893
894         dbus_message_iter_get_basic(&args, &path);
895         dbus_message_iter_next(&args);
896
897         if (media_adapter_find_endpoint(adapter, sender, path, NULL) != NULL)
898                 return btd_error_already_exists(msg);
899
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);
903
904         if (parse_properties(&props, &uuid, &delay_reporting, &codec,
905                                                 &capabilities, &size) < 0)
906                 return btd_error_invalid_args(msg);
907
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);
912                 else
913                         return btd_error_invalid_args(msg);
914         }
915
916         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
917 }
918
919 static DBusMessage *unregister_endpoint(DBusConnection *conn, DBusMessage *msg,
920                                         void *data)
921 {
922         struct media_adapter *adapter = data;
923         struct media_endpoint *endpoint;
924         const char *sender, *path;
925
926         if (!dbus_message_get_args(msg, NULL,
927                                 DBUS_TYPE_OBJECT_PATH, &path,
928                                 DBUS_TYPE_INVALID))
929                 return NULL;
930
931         sender = dbus_message_get_sender(msg);
932
933         endpoint = media_adapter_find_endpoint(adapter, sender, path, NULL);
934         if (endpoint == NULL)
935                 return btd_error_does_not_exist(msg);
936
937         media_endpoint_remove(endpoint);
938
939         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
940 }
941
942 static struct media_player *media_adapter_find_player(
943                                                 struct media_adapter *adapter,
944                                                 const char *sender,
945                                                 const char *path)
946 {
947         GSList *l;
948
949         for (l = adapter->players; l; l = l->next) {
950                 struct media_player *mp = l->data;
951
952                 if (sender && g_strcmp0(mp->sender, sender) != 0)
953                         continue;
954
955                 if (path && g_strcmp0(mp->path, path) != 0)
956                         continue;
957
958                 return mp;
959         }
960
961         return NULL;
962 }
963
964 static void release_player(struct media_player *mp)
965 {
966         DBusMessage *msg;
967
968         DBG("sender=%s path=%s", mp->sender, mp->path);
969
970         msg = dbus_message_new_method_call(mp->sender, mp->path,
971                                                 MEDIA_PLAYER_INTERFACE,
972                                                 "Release");
973         if (msg == NULL) {
974                 error("Couldn't allocate D-Bus message");
975                 return;
976         }
977
978         g_dbus_send_message(mp->adapter->conn, msg);
979 }
980
981 static void media_player_free(gpointer data)
982 {
983         struct media_player *mp = data;
984         struct media_adapter *adapter = mp->adapter;
985
986         if (mp->player) {
987                 adapter->players = g_slist_remove(adapter->players, mp);
988                 release_player(mp);
989         }
990
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);
994
995         if (mp->track)
996                 g_hash_table_unref(mp->track);
997
998         if (mp->settings)
999                 g_hash_table_unref(mp->settings);
1000
1001         g_timer_destroy(mp->timer);
1002         g_free(mp->sender);
1003         g_free(mp->path);
1004         g_free(mp);
1005 }
1006
1007 static void media_player_destroy(struct media_player *mp)
1008 {
1009         struct media_adapter *adapter = mp->adapter;
1010
1011         DBG("sender=%s path=%s", mp->sender, mp->path);
1012
1013         if (mp->player) {
1014                 struct avrcp_player *player = mp->player;
1015                 mp->player = NULL;
1016                 adapter->players = g_slist_remove(adapter->players, mp);
1017                 avrcp_unregister_player(player);
1018                 return;
1019         }
1020
1021         media_player_free(mp);
1022 }
1023
1024 static void media_player_remove(struct media_player *mp)
1025 {
1026         info("Player unregistered: sender=%s path=%s", mp->sender, mp->path);
1027
1028         media_player_destroy(mp);
1029 }
1030
1031 static const char *attrval_to_str(uint8_t attr, uint8_t value)
1032 {
1033         switch (attr) {
1034         case AVRCP_ATTRIBUTE_EQUALIZER:
1035                 switch (value) {
1036                 case AVRCP_EQUALIZER_ON:
1037                         return "on";
1038                 case AVRCP_EQUALIZER_OFF:
1039                         return "off";
1040                 }
1041
1042                 break;
1043         case AVRCP_ATTRIBUTE_REPEAT_MODE:
1044                 switch (value) {
1045                 case AVRCP_REPEAT_MODE_OFF:
1046                         return "off";
1047                 case AVRCP_REPEAT_MODE_SINGLE:
1048                         return "singletrack";
1049                 case AVRCP_REPEAT_MODE_ALL:
1050                         return "alltracks";
1051                 case AVRCP_REPEAT_MODE_GROUP:
1052                         return "group";
1053                 }
1054
1055                 break;
1056         /* Shuffle and scan have the same values */
1057         case AVRCP_ATTRIBUTE_SHUFFLE:
1058         case AVRCP_ATTRIBUTE_SCAN:
1059                 switch (value) {
1060                 case AVRCP_SCAN_OFF:
1061                         return "off";
1062                 case AVRCP_SCAN_ALL:
1063                         return "alltracks";
1064                 case AVRCP_SCAN_GROUP:
1065                         return "group";
1066                 }
1067
1068                 break;
1069         }
1070
1071         return NULL;
1072 }
1073
1074 static int attrval_to_val(uint8_t attr, const char *value)
1075 {
1076         int ret;
1077
1078         switch (attr) {
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;
1084                 else
1085                         ret = -EINVAL;
1086
1087                 return ret;
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;
1097                 else
1098                         ret = -EINVAL;
1099
1100                 return ret;
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;
1108                 else
1109                         ret = -EINVAL;
1110
1111                 return ret;
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;
1119                 else
1120                         ret = -EINVAL;
1121
1122                 return ret;
1123         }
1124
1125         return -EINVAL;
1126 }
1127
1128 static const char *attr_to_str(uint8_t attr)
1129 {
1130         switch (attr) {
1131         case AVRCP_ATTRIBUTE_EQUALIZER:
1132                 return "Equalizer";
1133         case AVRCP_ATTRIBUTE_REPEAT_MODE:
1134                 return "Repeat";
1135         case AVRCP_ATTRIBUTE_SHUFFLE:
1136                 return "Shuffle";
1137         case AVRCP_ATTRIBUTE_SCAN:
1138                 return "Scan";
1139         }
1140
1141         return NULL;
1142 }
1143
1144 static int attr_to_val(const char *str)
1145 {
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;
1154
1155         return -EINVAL;
1156 }
1157
1158 static int play_status_to_val(const char *status)
1159 {
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;
1172
1173         return -EINVAL;
1174 }
1175
1176 static int metadata_to_val(const char *str)
1177 {
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;
1192
1193         return -EINVAL;
1194 }
1195
1196 static const char *metadata_to_str(uint32_t id)
1197 {
1198         switch (id) {
1199         case AVRCP_MEDIA_ATTRIBUTE_TITLE:
1200                 return "Title";
1201         case AVRCP_MEDIA_ATTRIBUTE_ARTIST:
1202                 return "Artist";
1203         case AVRCP_MEDIA_ATTRIBUTE_ALBUM:
1204                 return "Album";
1205         case AVRCP_MEDIA_ATTRIBUTE_GENRE:
1206                 return "Genre";
1207         case AVRCP_MEDIA_ATTRIBUTE_TRACK:
1208                 return "Track";
1209         case AVRCP_MEDIA_ATTRIBUTE_N_TRACKS:
1210                 return "NumberOfTracks";
1211         case AVRCP_MEDIA_ATTRIBUTE_DURATION:
1212                 return "Duration";
1213         }
1214
1215         return NULL;
1216 }
1217
1218 static int get_setting(uint8_t attr, void *user_data)
1219 {
1220         struct media_player *mp = user_data;
1221         guint attr_uint = attr;
1222         void *value;
1223
1224         DBG("%s", attr_to_str(attr));
1225
1226         value = g_hash_table_lookup(mp->settings, GUINT_TO_POINTER(attr_uint));
1227         if (!value)
1228                 return -EINVAL;
1229
1230         return GPOINTER_TO_UINT(value);
1231 }
1232
1233 static int set_setting(uint8_t attr, uint8_t val, void *user_data)
1234 {
1235         struct media_player *mp = user_data;
1236         struct media_adapter *adapter = mp->adapter;
1237         const char *property, *value;
1238         guint attr_uint = attr;
1239         DBusMessage *msg;
1240         DBusMessageIter iter, var;
1241
1242         property = attr_to_str(attr);
1243         value = attrval_to_str(attr, val);
1244
1245         DBG("%s = %s", property, value);
1246
1247         if (property == NULL || value == NULL)
1248                 return -EINVAL;
1249
1250         if (!g_hash_table_lookup(mp->settings, GUINT_TO_POINTER(attr_uint)))
1251                 return -EINVAL;
1252
1253         msg = dbus_message_new_method_call(mp->sender, mp->path,
1254                                                 MEDIA_PLAYER_INTERFACE,
1255                                                 "SetProperty");
1256         if (msg == NULL) {
1257                 error("Couldn't allocate D-Bus message");
1258                 return -ENOMEM;
1259         }
1260
1261         dbus_message_iter_init_append(msg, &iter);
1262         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
1263
1264         dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1265                                                 DBUS_TYPE_STRING_AS_STRING,
1266                                                 &var);
1267         dbus_message_iter_append_basic(&var, DBUS_TYPE_STRING, &value);
1268         dbus_message_iter_close_container(&iter, &var);
1269
1270         g_dbus_send_message(adapter->conn, msg);
1271
1272         return 0;
1273 }
1274
1275 static GList *list_metadata(void *user_data)
1276 {
1277         struct media_player *mp = user_data;
1278
1279         DBG("");
1280
1281         if (mp->track == NULL)
1282                 return NULL;
1283
1284         return g_hash_table_get_keys(mp->track);
1285 }
1286
1287 static uint64_t get_uid(void *user_data)
1288 {
1289         struct media_player *mp = user_data;
1290
1291         DBG("%p", mp->track);
1292
1293         if (mp->track == NULL)
1294                 return UINT64_MAX;
1295
1296         return 0;
1297 }
1298
1299 static void *get_metadata(uint32_t id, void *user_data)
1300 {
1301         struct media_player *mp = user_data;
1302         struct metadata_value *value;
1303
1304         DBG("%s", metadata_to_str(id));
1305
1306         if (mp->track == NULL)
1307                 return NULL;
1308
1309         value = g_hash_table_lookup(mp->track, GUINT_TO_POINTER(id));
1310         if (!value)
1311                 return NULL;
1312
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);
1318         }
1319
1320         return NULL;
1321 }
1322
1323 static uint8_t get_status(void *user_data)
1324 {
1325         struct media_player *mp = user_data;
1326
1327         return mp->status;
1328 }
1329
1330 static uint32_t get_position(void *user_data)
1331 {
1332         struct media_player *mp = user_data;
1333         double timedelta;
1334         uint32_t sec, msec;
1335
1336         if (mp->status != AVRCP_PLAY_STATUS_PLAYING)
1337                 return mp->position;
1338
1339         timedelta = g_timer_elapsed(mp->timer, NULL);
1340
1341         sec = (uint32_t) timedelta;
1342         msec = (uint32_t) ((timedelta - sec) * 1000);
1343
1344         return mp->position + sec * 1000 + msec;
1345 }
1346
1347 static void set_volume(uint8_t volume, struct audio_device *dev, void *user_data)
1348 {
1349         struct media_player *mp = user_data;
1350         GSList *l;
1351
1352         if (mp->volume == volume)
1353                 return;
1354
1355         mp->volume = volume;
1356
1357         for (l = mp->adapter->endpoints; l; l = l->next) {
1358                 struct media_endpoint *endpoint = l->data;
1359                 struct media_transport *transport;
1360
1361                 /* Volume is A2DP only */
1362                 if (endpoint->sep == NULL)
1363                         continue;
1364
1365                 transport = find_device_transport(endpoint, dev);
1366                 if (transport == NULL)
1367                         continue;
1368
1369                 media_transport_update_volume(transport, volume);
1370         }
1371 }
1372
1373 static struct avrcp_player_cb player_cb = {
1374         .get_setting = get_setting,
1375         .set_setting = set_setting,
1376         .list_metadata = list_metadata,
1377         .get_uid = get_uid,
1378         .get_metadata = get_metadata,
1379         .get_position = get_position,
1380         .get_status = get_status,
1381         .set_volume = set_volume
1382 };
1383
1384 static void media_player_exit(DBusConnection *connection, void *user_data)
1385 {
1386         struct media_player *mp = user_data;
1387
1388         mp->watch = 0;
1389         media_player_remove(mp);
1390 }
1391
1392 static gboolean set_status(struct media_player *mp, DBusMessageIter *iter)
1393 {
1394         const char *value;
1395         int val;
1396
1397         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
1398                 return FALSE;
1399
1400         dbus_message_iter_get_basic(iter, &value);
1401         DBG("Status=%s", value);
1402
1403         val = play_status_to_val(value);
1404         if (val < 0) {
1405                 error("Invalid status");
1406                 return FALSE;
1407         }
1408
1409         if (mp->status == val)
1410                 return TRUE;
1411
1412         mp->position = get_position(mp);
1413         g_timer_start(mp->timer);
1414
1415         mp->status = val;
1416
1417         avrcp_player_event(mp->player, AVRCP_EVENT_STATUS_CHANGED, &val);
1418
1419         return TRUE;
1420 }
1421
1422 static gboolean set_position(struct media_player *mp, DBusMessageIter *iter)
1423 {
1424         uint32_t value;
1425         struct metadata_value *duration;
1426
1427         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT32)
1428                         return FALSE;
1429
1430         dbus_message_iter_get_basic(iter, &value);
1431         DBG("Position=%u", value);
1432
1433         mp->position = value;
1434         g_timer_start(mp->timer);
1435
1436         if (!mp->position) {
1437                 avrcp_player_event(mp->player,
1438                                         AVRCP_EVENT_TRACK_REACHED_START, NULL);
1439                 return TRUE;
1440         }
1441
1442         duration = g_hash_table_lookup(mp->track, GUINT_TO_POINTER(
1443                                         AVRCP_MEDIA_ATTRIBUTE_DURATION));
1444
1445         /*
1446          * If position is the maximum value allowed or greater than track's
1447          * duration, we send a track-reached-end event.
1448          */
1449         if (mp->position == UINT32_MAX ||
1450                         (duration && mp->position >= duration->value.num))
1451                 avrcp_player_event(mp->player, AVRCP_EVENT_TRACK_REACHED_END,
1452                                                                         NULL);
1453
1454         return TRUE;
1455 }
1456
1457 static gboolean set_property(struct media_player *mp, const char *key,
1458                                                         DBusMessageIter *entry)
1459 {
1460         DBusMessageIter var;
1461         const char *value;
1462         int attr, val;
1463
1464         if (dbus_message_iter_get_arg_type(entry) != DBUS_TYPE_VARIANT)
1465                 return FALSE;
1466
1467         dbus_message_iter_recurse(entry, &var);
1468
1469         if (strcasecmp(key, "Status") == 0)
1470                 return set_status(mp, &var);
1471
1472         if (strcasecmp(key, "Position") == 0)
1473                 return set_position(mp, &var);
1474
1475         attr = attr_to_val(key);
1476         if (attr < 0)
1477                 return FALSE;
1478
1479         if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
1480                 return FALSE;
1481
1482         dbus_message_iter_get_basic(&var, &value);
1483
1484         val = attrval_to_val(attr, value);
1485         if (val < 0)
1486                 return FALSE;
1487
1488         DBG("%s=%s", key, value);
1489
1490         g_hash_table_replace(mp->settings, GUINT_TO_POINTER(attr),
1491                                                 GUINT_TO_POINTER(val));
1492
1493         return TRUE;
1494 }
1495
1496 static gboolean property_changed(DBusConnection *connection, DBusMessage *msg,
1497                                                         void *user_data)
1498 {
1499         struct media_player *mp = user_data;
1500         DBusMessageIter iter;
1501         const char *property;
1502
1503         DBG("sender=%s path=%s", mp->sender, mp->path);
1504
1505         dbus_message_iter_init(msg, &iter);
1506
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));
1511                 return TRUE;
1512         }
1513
1514         dbus_message_iter_get_basic(&iter, &property);
1515
1516         dbus_message_iter_next(&iter);
1517
1518         set_property(mp, property, &iter);
1519
1520         return TRUE;
1521 }
1522
1523 static void metadata_value_free(gpointer data)
1524 {
1525         struct metadata_value *value = data;
1526
1527         switch (value->type) {
1528         case DBUS_TYPE_STRING:
1529                 g_free(value->value.str);
1530                 break;
1531         }
1532
1533         g_free(value);
1534 }
1535
1536 static gboolean parse_player_metadata(struct media_player *mp,
1537                                                         DBusMessageIter *iter)
1538 {
1539         DBusMessageIter dict;
1540         DBusMessageIter var;
1541         GHashTable *track;
1542         int ctype;
1543         gboolean title = FALSE;
1544         uint64_t uid;
1545
1546         ctype = dbus_message_iter_get_arg_type(iter);
1547         if (ctype != DBUS_TYPE_ARRAY)
1548                 return FALSE;
1549
1550         dbus_message_iter_recurse(iter, &dict);
1551
1552         track = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
1553                                                         metadata_value_free);
1554
1555         while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
1556                                                         DBUS_TYPE_INVALID) {
1557                 DBusMessageIter entry;
1558                 const char *key;
1559                 struct metadata_value *value;
1560                 int id;
1561
1562                 if (ctype != DBUS_TYPE_DICT_ENTRY)
1563                         goto parse_error;
1564
1565                 dbus_message_iter_recurse(&dict, &entry);
1566                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1567                         goto parse_error;
1568
1569                 dbus_message_iter_get_basic(&entry, &key);
1570                 dbus_message_iter_next(&entry);
1571
1572                 id = metadata_to_val(key);
1573                 if (id < 0)
1574                         goto parse_error;
1575
1576                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1577                         goto parse_error;
1578
1579                 dbus_message_iter_recurse(&entry, &var);
1580
1581                 value = g_new0(struct metadata_value, 1);
1582                 value->type = dbus_message_iter_get_arg_type(&var);
1583
1584                 switch (id) {
1585                 case AVRCP_MEDIA_ATTRIBUTE_TITLE:
1586                         title = TRUE;
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) {
1591                                 g_free(value);
1592                                 goto parse_error;
1593                         }
1594
1595                         dbus_message_iter_get_basic(&var, &value->value.str);
1596                         break;
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) {
1601                                 g_free(value);
1602                                 goto parse_error;
1603                         }
1604
1605                         dbus_message_iter_get_basic(&var, &value->value.num);
1606                         break;
1607                 default:
1608                         goto parse_error;
1609                 }
1610
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);
1615                         break;
1616                 default:
1617                         DBG("%s=%u", key, value->value.num);
1618                 }
1619
1620                 g_hash_table_replace(track, GUINT_TO_POINTER(id), value);
1621                 dbus_message_iter_next(&dict);
1622         }
1623
1624         if (g_hash_table_size(track) == 0) {
1625                 g_hash_table_unref(track);
1626                 track = NULL;
1627         } else if (title == FALSE) {
1628                 struct metadata_value *value = g_new(struct metadata_value, 1);
1629                 uint32_t id = AVRCP_MEDIA_ATTRIBUTE_TITLE;
1630
1631                 value->type = DBUS_TYPE_STRING;
1632                 value->value.str = g_strdup("");
1633                 g_hash_table_insert(track, GUINT_TO_POINTER(id), value);
1634         }
1635
1636         if (mp->track != NULL)
1637                 g_hash_table_unref(mp->track);
1638
1639         mp->track = track;
1640         mp->position = 0;
1641         g_timer_start(mp->timer);
1642         uid = get_uid(mp);
1643
1644         avrcp_player_event(mp->player, AVRCP_EVENT_TRACK_CHANGED, &uid);
1645         avrcp_player_event(mp->player, AVRCP_EVENT_TRACK_REACHED_START,
1646                                                                 NULL);
1647
1648         return TRUE;
1649
1650 parse_error:
1651         if (track)
1652                 g_hash_table_unref(track);
1653
1654         return FALSE;
1655 }
1656
1657 static gboolean track_changed(DBusConnection *connection, DBusMessage *msg,
1658                                                         void *user_data)
1659 {
1660         struct media_player *mp = user_data;
1661         DBusMessageIter iter;
1662
1663         DBG("sender=%s path=%s", mp->sender, mp->path);
1664
1665         dbus_message_iter_init(msg, &iter);
1666
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));
1671         }
1672
1673         return TRUE;
1674 }
1675
1676 static struct media_player *media_player_create(struct media_adapter *adapter,
1677                                                 const char *sender,
1678                                                 const char *path,
1679                                                 int *err)
1680 {
1681         struct media_player *mp;
1682
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();
1688
1689         mp->watch = g_dbus_add_disconnect_watch(adapter->conn, sender,
1690                                                 media_player_exit, mp,
1691                                                 NULL);
1692         mp->property_watch = g_dbus_add_signal_watch(adapter->conn, sender,
1693                                                 path, MEDIA_PLAYER_INTERFACE,
1694                                                 "PropertyChanged",
1695                                                 property_changed,
1696                                                 mp, NULL);
1697         mp->track_watch = g_dbus_add_signal_watch(adapter->conn, sender,
1698                                                 path, MEDIA_PLAYER_INTERFACE,
1699                                                 "TrackChanged",
1700                                                 track_changed,
1701                                                 mp, NULL);
1702         mp->player = avrcp_register_player(&adapter->src, &player_cb, mp,
1703                                                 media_player_free);
1704         if (!mp->player) {
1705                 if (err)
1706                         *err = -EPROTONOSUPPORT;
1707                 media_player_destroy(mp);
1708                 return NULL;
1709         }
1710
1711         mp->settings = g_hash_table_new(g_direct_hash, g_direct_equal);
1712
1713         adapter->players = g_slist_append(adapter->players, mp);
1714
1715         info("Player registered: sender=%s path=%s", sender, path);
1716
1717         if (err)
1718                 *err = 0;
1719
1720         return mp;
1721 }
1722
1723 static gboolean parse_player_properties(struct media_player *mp,
1724                                                         DBusMessageIter *iter)
1725 {
1726         DBusMessageIter dict;
1727         int ctype;
1728
1729         ctype = dbus_message_iter_get_arg_type(iter);
1730         if (ctype != DBUS_TYPE_ARRAY)
1731                 return FALSE;
1732
1733         dbus_message_iter_recurse(iter, &dict);
1734
1735         while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
1736                                                         DBUS_TYPE_INVALID) {
1737                 DBusMessageIter entry;
1738                 const char *key;
1739
1740                 if (ctype != DBUS_TYPE_DICT_ENTRY)
1741                         return FALSE;
1742
1743                 dbus_message_iter_recurse(&dict, &entry);
1744                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1745                         return FALSE;
1746
1747                 dbus_message_iter_get_basic(&entry, &key);
1748                 dbus_message_iter_next(&entry);
1749
1750                 if (set_property(mp, key, &entry) == FALSE)
1751                         return FALSE;
1752
1753                 dbus_message_iter_next(&dict);
1754         }
1755
1756         return TRUE;
1757 }
1758
1759 static DBusMessage *register_player(DBusConnection *conn, DBusMessage *msg,
1760                                         void *data)
1761 {
1762         struct media_adapter *adapter = data;
1763         struct media_player *mp;
1764         DBusMessageIter args;
1765         const char *sender, *path;
1766         int err;
1767
1768         sender = dbus_message_get_sender(msg);
1769
1770         dbus_message_iter_init(msg, &args);
1771
1772         dbus_message_iter_get_basic(&args, &path);
1773         dbus_message_iter_next(&args);
1774
1775         if (media_adapter_find_player(adapter, sender, path) != NULL)
1776                 return btd_error_already_exists(msg);
1777
1778         mp = media_player_create(adapter, sender, path, &err);
1779         if (mp == NULL) {
1780                 if (err == -EPROTONOSUPPORT)
1781                         return btd_error_not_supported(msg);
1782                 else
1783                         return btd_error_invalid_args(msg);
1784         }
1785
1786         if (parse_player_properties(mp, &args) == FALSE) {
1787                 media_player_destroy(mp);
1788                 return btd_error_invalid_args(msg);
1789         }
1790
1791         dbus_message_iter_next(&args);
1792
1793         if (parse_player_metadata(mp, &args) == FALSE) {
1794                 media_player_destroy(mp);
1795                 return btd_error_invalid_args(msg);
1796         }
1797
1798         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1799 }
1800
1801 static DBusMessage *unregister_player(DBusConnection *conn, DBusMessage *msg,
1802                                         void *data)
1803 {
1804         struct media_adapter *adapter = data;
1805         struct media_player *player;
1806         const char *sender, *path;
1807
1808         if (!dbus_message_get_args(msg, NULL,
1809                                 DBUS_TYPE_OBJECT_PATH, &path,
1810                                 DBUS_TYPE_INVALID))
1811                 return NULL;
1812
1813         sender = dbus_message_get_sender(msg);
1814
1815         player = media_adapter_find_player(adapter, sender, path);
1816         if (player == NULL)
1817                 return btd_error_does_not_exist(msg);
1818
1819         media_player_remove(player);
1820
1821         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1822 }
1823
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) },
1836         { },
1837 };
1838
1839 static void path_free(void *data)
1840 {
1841         struct media_adapter *adapter = data;
1842
1843         while (adapter->endpoints)
1844                 release_endpoint(adapter->endpoints->data);
1845
1846         dbus_connection_unref(adapter->conn);
1847
1848         adapters = g_slist_remove(adapters, adapter);
1849
1850         g_free(adapter->path);
1851         g_free(adapter);
1852 }
1853
1854 int media_register(DBusConnection *conn, const char *path, const bdaddr_t *src)
1855 {
1856         struct media_adapter *adapter;
1857
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);
1862
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);
1867                 path_free(adapter);
1868                 return -1;
1869         }
1870
1871         adapters = g_slist_append(adapters, adapter);
1872
1873         return 0;
1874 }
1875
1876 void media_unregister(const char *path)
1877 {
1878         GSList *l;
1879
1880         for (l = adapters; l; l = l->next) {
1881                 struct media_adapter *adapter = l->data;
1882
1883                 if (g_strcmp0(path, adapter->path) == 0) {
1884                         g_dbus_unregister_interface(adapter->conn, path,
1885                                                         MEDIA_INTERFACE);
1886                         return;
1887                 }
1888         }
1889 }
1890
1891 struct a2dp_sep *media_endpoint_get_sep(struct media_endpoint *endpoint)
1892 {
1893         return endpoint->sep;
1894 }
1895
1896 const char *media_endpoint_get_uuid(struct media_endpoint *endpoint)
1897 {
1898         return endpoint->uuid;
1899 }
1900
1901 uint8_t media_endpoint_get_codec(struct media_endpoint *endpoint)
1902 {
1903         return endpoint->codec;
1904 }