Add AVRCP control volume up / down method
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-avrcp-controller.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include "bt-internal-types.h"
19 #include "bt-service-common.h"
20 #include "bt-service-avrcp-controller.h"
21 #include "bt-service-audio.h"
22 #include "bt-service-event.h"
23
24 static bt_player_settinngs_t repeat_status[] = {
25         { REPEAT_INVALID, "" },
26         { REPEAT_MODE_OFF, "off" },
27         { REPEAT_SINGLE_TRACK, "singletrack" },
28         { REPEAT_ALL_TRACK, "alltracks" },
29         { REPEAT_GROUP, "group" },
30         { REPEAT_INVALID, "" }
31 };
32
33 static bt_player_settinngs_t equalizer_status[] = {
34         { EQUALIZER_INVALID, "" },
35         { EQUALIZER_OFF, "off" },
36         { EQUALIZER_ON, "on" },
37         { EQUALIZER_INVALID, "" },
38 };
39
40 static bt_player_settinngs_t scan_status[] = {
41         { SCAN_INVALID, "" },
42         { SCAN_MODE_OFF, "off" },
43         { SCAN_ALL_TRACK, "alltracks" },
44         { SCAN_GROUP, "group" },
45         { SCAN_INVALID, "" },
46 };
47
48 static bt_player_settinngs_t shuffle_settings[] = {
49         { SHUFFLE_INVALID, "" },
50         { SHUFFLE_MODE_OFF, "off" },
51         { SHUFFLE_ALL_TRACK, "alltracks" },
52         { SHUFFLE_GROUP, "group" },
53         { SHUFFLE_INVALID, "" }
54 };
55
56 static char *avrcp_control_path = NULL;
57 static char *avrcp_transport_path = NULL;
58
59 void _bt_set_control_device_path(const char *path)
60 {
61
62         ret_if(path == NULL);
63
64         g_free(avrcp_control_path);
65         BT_DBG("control_path = %s", path);
66         avrcp_control_path = g_strdup(path);
67 }
68
69 void _bt_remove_control_device_path(const char *path)
70 {
71         ret_if(path == NULL);
72
73         if (avrcp_control_path &&
74                         !g_strcmp0(avrcp_control_path, path)) {
75                 BT_DBG("control_path = %s", path);
76                 g_free(avrcp_control_path);
77                 avrcp_control_path = NULL;
78         }
79 }
80
81 static char *__bt_get_control_device_path(void)
82 {
83         char *adapter_path;
84         char *control_path;
85         char connected_address[BT_ADDRESS_STRING_SIZE + 1];
86
87         BT_DBG("+");
88
89         if (avrcp_control_path != NULL)
90                 return avrcp_control_path;
91
92         retv_if(!_bt_is_headset_type_connected(BT_AVRCP,
93                         connected_address), NULL);
94
95         BT_DBG("device address = %s", connected_address);
96
97         adapter_path = _bt_get_device_object_path(connected_address);
98         retv_if(adapter_path == NULL, NULL);
99
100         control_path = g_strdup_printf(BT_MEDIA_CONTROL_PATH, adapter_path);
101         g_free(adapter_path);
102
103         avrcp_control_path = control_path;
104         BT_DBG("control_path = %s", control_path);
105         return control_path;
106 }
107
108 static char *__bt_get_transport_device_path(void)
109 {
110         char *adapter_path;
111         char *transport_path;
112         char connected_address[BT_ADDRESS_STRING_SIZE + 1];
113
114         BT_DBG("+");
115
116         if (avrcp_transport_path != NULL)
117                 return avrcp_transport_path;
118
119         retv_if(!_bt_is_headset_type_connected(BT_AVRCP,
120                         connected_address), NULL);
121
122         BT_DBG("device address = %s", connected_address);
123
124         adapter_path = _bt_get_device_object_path(connected_address);
125         retv_if(adapter_path == NULL, NULL);
126
127         transport_path = g_strdup_printf(BT_MEDIA_TRANSPORT_PATH, adapter_path);
128         g_free(adapter_path);
129
130         avrcp_transport_path = transport_path;
131         BT_DBG("transport_path = %s", transport_path);
132         return transport_path;
133 }
134
135 static int __bt_media_send_control_msg(const char *name)
136 {
137         GVariant *reply = NULL;
138         GError *err = NULL;
139         GDBusConnection *conn = NULL;
140         GDBusProxy *proxy = NULL;
141         char *control_path = NULL;
142
143         retv_if(name == NULL, BLUETOOTH_ERROR_INTERNAL);
144
145         BT_INFO("Command [%s]", name);
146
147         conn = _bt_gdbus_get_system_gconn();
148         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
149
150         control_path = __bt_get_control_device_path();
151         retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
152         BT_DBG("control_path %s", control_path);
153
154         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
155                         BT_BLUEZ_NAME, control_path,
156                         BT_PLAYER_CONTROL_INTERFACE, NULL, &err);
157         if (proxy == NULL) {
158                 BT_ERR("Unable to allocate new proxy \n");
159                 if (err) {
160                         BT_ERR("%s", err->message);
161                         g_clear_error(&err);
162                 }
163                 return BLUETOOTH_ERROR_INTERNAL;
164         }
165
166         reply = g_dbus_proxy_call_sync(proxy, name, NULL,
167                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
168
169         g_object_unref(proxy);
170
171         if (!reply) {
172                 BT_ERR("Error returned in method call");
173                 if (err) {
174                         BT_ERR("%s", err->message);
175                         g_clear_error(&err);
176                 }
177                 return BLUETOOTH_ERROR_INTERNAL;
178         }
179
180         g_variant_unref(reply);
181
182         BT_DBG("-");
183         return BLUETOOTH_ERROR_NONE;
184 }
185
186 int _bt_avrcp_control_cmd(int type)
187 {
188         int ret = BLUETOOTH_ERROR_INTERNAL;
189         BT_DBG("+");
190
191         switch (type) {
192         case PLAY:
193                 ret = __bt_media_send_control_msg("Play");
194                 break;
195         case PAUSE:
196                 ret = __bt_media_send_control_msg("Pause");
197                 break;
198         case STOP:
199                 ret = __bt_media_send_control_msg("Stop");
200                 break;
201         case NEXT:
202                 ret = __bt_media_send_control_msg("Next");
203                 break;
204         case PREVIOUS:
205                 ret = __bt_media_send_control_msg("Previous");
206                 break;
207         case PRESS_FAST_FORWARD:
208                 ret = __bt_media_send_control_msg("PressFastForward");
209                 break;
210         case RELEASE_FAST_FORWARD:
211                 ret = __bt_media_send_control_msg("ReleaseFastForward");
212                 break;
213         case PRESS_REWIND:
214                 ret = __bt_media_send_control_msg("PressRewind");
215                 break;
216         case RELEASE_REWIND:
217                 ret = __bt_media_send_control_msg("ReleaseRewind");
218                 break;
219         case VOLUME_UP:
220                 ret = __bt_media_send_control_msg("VolumeUp");
221                 break;
222         case VOLUME_DOWN:
223                 ret = __bt_media_send_control_msg("VolumeDown");
224                 break;
225         default:
226                 BT_DBG("Invalid Type\n");
227                 return BLUETOOTH_ERROR_INTERNAL;
228         }
229         BT_DBG("-");
230         return ret;
231 }
232
233 GDBusProxy *__bt_get_control_properties_proxy(void)
234 {
235         GDBusProxy *proxy = NULL;
236         GError *error = NULL;
237         char *control_path = NULL;
238         GDBusConnection *conn = NULL;
239
240         control_path = __bt_get_control_device_path();
241         retv_if(control_path == NULL, NULL);
242         BT_DBG("control_path = %s", control_path);
243
244         conn = _bt_gdbus_get_system_gconn();
245         retv_if(conn == NULL, NULL);
246
247         proxy = g_dbus_proxy_new_sync(conn,
248                         G_DBUS_PROXY_FLAGS_NONE, NULL,
249                         BT_BLUEZ_NAME, control_path,
250                         BT_PROPERTIES_INTERFACE, NULL, &error);
251         if (proxy == NULL) {
252                 BT_ERR("Unable to allocate new proxy");
253                 if (error) {
254                         BT_ERR("%s", error->message);
255                         g_clear_error(&error);
256                 }
257                 return NULL;
258         }
259
260         return proxy;
261 }
262
263 GDBusProxy *__bt_get_transport_properties_proxy(void)
264 {
265         GDBusProxy *proxy = NULL;
266         GError *error = NULL;
267         char *transport_path = NULL;
268         GDBusConnection *conn = NULL;
269
270         transport_path = __bt_get_transport_device_path();
271         retv_if(transport_path == NULL, NULL);
272         BT_DBG("transport_path = %s", transport_path);
273
274         conn = _bt_gdbus_get_system_gconn();
275         retv_if(conn == NULL, NULL);
276
277         proxy = g_dbus_proxy_new_sync(conn,
278                         G_DBUS_PROXY_FLAGS_NONE, NULL,
279                         BT_BLUEZ_NAME, transport_path,
280                         BT_PROPERTIES_INTERFACE, NULL, &error);
281         if (proxy == NULL) {
282                 BT_ERR("Unable to allocate new proxy");
283                 if (error) {
284                         BT_ERR("%s", error->message);
285                         g_clear_error(&error);
286                 }
287                 return NULL;
288         }
289
290         return proxy;
291 }
292
293 static int __bt_media_attr_to_event(const char *str)
294 {
295         if (!strcasecmp(str, "Equalizer"))
296                 return BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS;
297         else if (!strcasecmp(str, "Repeat"))
298                 return BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS;
299         else if (!strcasecmp(str, "Shuffle"))
300                 return BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS;
301         else if (!strcasecmp(str, "Scan"))
302                 return BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS;
303         else if (!strcasecmp(str, "Position"))
304                 return BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS;
305         else if (!strcasecmp(str, "Track"))
306                 return BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED;
307         else if (!strcasecmp(str, "Status"))
308                 return BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED;
309
310         return 0;
311 }
312
313 static int __bt_media_attr_to_type(const char *str)
314 {
315         if (!strcasecmp(str, "Equalizer"))
316                 return EQUALIZER;
317         else if (!strcasecmp(str, "Repeat"))
318                 return REPEAT;
319         else if (!strcasecmp(str, "Shuffle"))
320                 return SHUFFLE;
321         else if (!strcasecmp(str, "Scan"))
322                 return SCAN;
323         else if (!strcasecmp(str, "Position"))
324                 return POSITION;
325         else if (!strcasecmp(str, "Track"))
326                 return METADATA;
327         else if (!strcasecmp(str, "Status"))
328                 return STATUS;
329
330         return 0;
331 }
332
333 static const char *__bt_media_type_to_str(int type)
334 {
335         switch (type) {
336         case EQUALIZER:
337                 return "Equalizer";
338         case REPEAT:
339                 return "Repeat";
340         case SHUFFLE:
341                 return "Shuffle";
342         case SCAN:
343                 return "Scan";
344         case POSITION:
345                 return "Position";
346         case METADATA:
347                 return "Track";
348         case STATUS:
349                 return "Status";
350         }
351         return NULL;
352 }
353
354 static const char *__bt_transport_type_to_str(int type)
355 {
356         switch (type) {
357         case DELAY:
358                 return "Delay";
359         case VOLUME:
360                 return "Volume";
361         }
362         return NULL;
363 }
364
365 static int __bt_media_attrval_to_val(int type, const char *value)
366 {
367         int ret = 0;
368
369         switch (type) {
370         case EQUALIZER:
371                 if (!strcmp(value, "off"))
372                         ret = EQUALIZER_OFF;
373                 else if (!strcmp(value, "on"))
374                         ret = EQUALIZER_ON;
375                 else
376                         ret = EQUALIZER_INVALID;
377                 break;
378
379         case REPEAT:
380                 if (!strcmp(value, "off"))
381                         ret = REPEAT_MODE_OFF;
382                 else if (!strcmp(value, "singletrack"))
383                         ret = REPEAT_SINGLE_TRACK;
384                 else if (!strcmp(value, "alltracks"))
385                         ret = REPEAT_ALL_TRACK;
386                 else if (!strcmp(value, "group"))
387                         ret = REPEAT_GROUP;
388                 else
389                         ret = REPEAT_INVALID;
390                 break;
391
392         case SHUFFLE:
393                 if (!strcmp(value, "off"))
394                         ret = SHUFFLE_MODE_OFF;
395                 else if (!strcmp(value, "alltracks"))
396                         ret = SHUFFLE_ALL_TRACK;
397                 else if (!strcmp(value, "group"))
398                         ret = SHUFFLE_GROUP;
399                 else
400                         ret = SHUFFLE_INVALID;
401                 break;
402
403         case SCAN:
404                 if (!strcmp(value, "off"))
405                         ret = SCAN_MODE_OFF;
406                 else if (!strcmp(value, "alltracks"))
407                         ret = SCAN_ALL_TRACK;
408                 else if (!strcmp(value, "group"))
409                         ret = SCAN_GROUP;
410                 else
411                         ret = SCAN_INVALID;
412                 break;
413
414         case STATUS:
415                 if (!strcmp(value, "stopped"))
416                         ret = STATUS_STOPPED;
417                 else if (!strcmp(value, "playing"))
418                         ret = STATUS_PLAYING;
419                 else if (!strcmp(value, "paused"))
420                         ret = STATUS_PAUSED;
421                 else if (!strcmp(value, "forward-seek"))
422                         ret = STATUS_FORWARD_SEEK;
423                 else if (!strcmp(value, "reverse-seek"))
424                         ret = STATUS_REVERSE_SEEK;
425                 else if (!strcmp(value, "error"))
426                         ret = STATUS_ERROR;
427                 else
428                         ret = STATUS_INVALID;
429         }
430         return ret;
431 }
432
433 int _bt_avrcp_control_get_property(int type, unsigned int *value)
434 {
435         GDBusProxy *proxy = NULL;
436         char *name = NULL;
437         int ret = BLUETOOTH_ERROR_NONE;
438         GError *err = NULL;
439         GVariant *reply = NULL;
440         GVariant *temp = NULL;
441
442         BT_CHECK_PARAMETER(value, return);
443
444         proxy = __bt_get_control_properties_proxy();
445         retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
446
447         reply = g_dbus_proxy_call_sync(proxy,
448                                         "Get", g_variant_new("(ss)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type)),
449                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
450
451         g_object_unref(proxy);
452
453         if (!reply) {
454                 BT_ERR("Can't get managed objects");
455                 if (err) {
456                         BT_ERR("%s", err->message);
457                         g_clear_error(&err);
458                 }
459                 return BLUETOOTH_ERROR_INTERNAL;
460         } else {
461                         switch (type) {
462                         case EQUALIZER:
463                         case REPEAT:
464                         case SHUFFLE:
465                         case SCAN:
466                         case STATUS:
467                                 name = (char *)g_variant_get_data(reply);
468                                 if (name)
469                                         *value = __bt_media_attrval_to_val(type, name);
470                                 BT_INFO("Type[%s] and Value[%s]", __bt_media_type_to_str(type), name);
471                                 break;
472                         case POSITION:
473                                 g_variant_get(reply, "(v)", &temp);
474                                 *value = g_variant_get_uint32(temp);
475                                 g_variant_unref(temp);
476                                 BT_INFO("Type[%s] and Value[%d]", __bt_media_type_to_str(type), *value);
477                                 break;
478                         default:
479                                 BT_ERR("Invalid Type [%d]", type);
480                                 ret =  BLUETOOTH_ERROR_INTERNAL;
481                         }
482                 }
483         g_variant_unref(reply);
484         return ret;
485 }
486
487 int _bt_avrcp_control_set_property(int type, unsigned int value)
488 {
489         GValue *attr_value = NULL;
490         GDBusProxy *proxy = NULL;
491         GError *error = NULL;
492         GVariant *reply, *param;
493
494         g_value_init(attr_value, G_TYPE_STRING);
495
496         switch (type) {
497         case EQUALIZER:
498                 param = g_variant_new("s", equalizer_status[value].property);
499                 BT_INFO("equalizer_status %s", equalizer_status[value].property);
500                 break;
501         case REPEAT:
502                 param = g_variant_new("s", repeat_status[value].property);
503                 BT_INFO("repeat_status %s", repeat_status[value].property);
504                 break;
505         case SHUFFLE:
506                 param = g_variant_new("s", shuffle_settings[value].property);
507                 BT_INFO("shuffle_settings %s", shuffle_settings[value].property);
508                 break;
509         case SCAN:
510                 param = g_variant_new("s", scan_status[value].property);
511                 BT_INFO("scan_status %s", scan_status[value].property);
512                 break;
513         default:
514                 BT_ERR("Invalid property type: %d", type);
515                 g_value_unset(attr_value);
516                 return BLUETOOTH_ERROR_INTERNAL;
517         }
518
519         proxy = __bt_get_control_properties_proxy();
520         retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
521
522         reply = g_dbus_proxy_call_sync(proxy,
523                                         "Set", g_variant_new("(ssv)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type), param),
524                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
525
526         g_object_unref(proxy);
527         g_variant_unref(param);
528
529         if (!reply) {
530                 BT_ERR("Can't get managed objects");
531                 if (error) {
532                         BT_ERR("SetProperty Fail: %s", error->message);
533                         g_clear_error(&error);
534                         return BLUETOOTH_ERROR_INTERNAL;
535                 }
536         }
537
538         g_variant_unref(reply);
539         g_value_unset(attr_value);
540
541         return BLUETOOTH_ERROR_NONE;
542 }
543
544 int _bt_avrcp_transport_set_property(int type, unsigned int value)
545 {
546         GDBusProxy *proxy = NULL;
547         GError *error = NULL;
548         GVariant *reply, *param;
549         uint16_t property_level = (uint16_t)value;
550
551         switch (type) {
552         case DELAY:
553                 param = g_variant_new("q", property_level);
554                 BT_INFO("delay level %d", property_level);
555                 break;
556         case VOLUME:
557                 param = g_variant_new("q", property_level);
558                 BT_INFO("volume level %d", property_level);
559                 break;
560         default:
561                 BT_ERR("Invalid property type: %d", type);
562                 return BLUETOOTH_ERROR_INTERNAL;
563         }
564
565         proxy = __bt_get_transport_properties_proxy();
566         retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
567
568         reply = g_dbus_proxy_call_sync(proxy,
569                                         "Set", g_variant_new("(ssv)", BT_MEDIATRANSPORT_INTERFACE, __bt_transport_type_to_str(type), param),
570                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
571
572         g_object_unref(proxy);
573         g_variant_unref(param);
574
575         if (!reply) {
576                 BT_ERR("Can't get managed objects");
577                 if (error) {
578                         BT_ERR("SetProperty Fail: %s", error->message);
579                         g_clear_error(&error);
580                         return BLUETOOTH_ERROR_INTERNAL;
581                 }
582         }
583
584         g_variant_unref(reply);
585
586         return BLUETOOTH_ERROR_NONE;
587 }
588
589 static int __bt_avrcp_control_parse_properties(
590                                 media_metadata_attributes_t *metadata,
591                                 GVariant *item)
592 {
593         GVariant *value = NULL;
594         GVariantIter iter;
595         char *value_string = NULL;
596         unsigned int value_uint;
597         const char *key = NULL;
598
599         g_variant_iter_init(&iter, item);
600         while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) {
601                 if (strcasecmp(key, "Title") == 0) {
602                         value_string = (char *)g_variant_get_string(value, NULL);
603                         BT_DBG("Value : %s ", value_string);
604                         metadata->title = g_strdup(value_string);
605                 } else if (strcasecmp(key, "Artist") == 0) {
606                         value_string = (char *)g_variant_get_string(value, NULL);
607                         BT_DBG("Value : %s ", value_string);
608                         metadata->artist = g_strdup(value_string);
609                 } else if (strcasecmp(key, "Album") == 0) {
610                         value_string = (char *)g_variant_get_string(value, NULL);
611                         BT_DBG("Value : %s ", value_string);
612                         metadata->album = g_strdup(value_string);
613                 } else if (strcasecmp(key, "Genre") == 0) {
614                         value_string = (char *)g_variant_get_string(value, NULL);
615                         BT_DBG("Value : %s ", value_string);
616                         metadata->genre = g_strdup(value_string);
617                 } else if (strcasecmp(key, "Duration") == 0) {
618                         value_uint = g_variant_get_uint32(value);
619                         BT_DBG("Duration : %d", value_uint);
620                         metadata->duration = value_uint;
621                 } else if (strcasecmp(key, "NumberOfTracks") == 0) {
622                         value_uint = g_variant_get_uint32(value);
623                         metadata->total_tracks = value_uint;
624                 } else if (strcasecmp(key, "TrackNumber") == 0) {
625                         value_uint = g_variant_get_uint32(value);
626                         metadata->number = value_uint;
627                 } else
628                         BT_DBG("%s not supported, ignoring", key);
629         }
630
631         if (!metadata->title)
632                 metadata->title = g_strdup("");
633         if (!metadata->artist)
634                 metadata->artist = g_strdup("");
635         if (!metadata->album)
636                 metadata->album = g_strdup("");
637         if (!metadata->genre)
638                 metadata->genre = g_strdup("");
639
640         return BLUETOOTH_ERROR_NONE;
641
642 }
643
644 int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata)
645 {
646         GDBusProxy *proxy = NULL;
647         GVariant *reply = NULL;
648         GVariant *item = NULL;
649         GError *err = NULL;
650         GDBusConnection *conn = NULL;
651         char *control_path = NULL;
652         char *interface_name = NULL;
653         char *property_name = NULL;
654         GVariant *parameters = NULL;
655         int ret = BLUETOOTH_ERROR_NONE;
656
657         retv_if(metadata == NULL, BLUETOOTH_ERROR_INTERNAL);
658
659         conn = _bt_gdbus_get_system_gconn();
660         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
661
662         control_path = __bt_get_control_device_path();
663         retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
664         BT_DBG("control_path %s", control_path);
665
666         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
667                         BT_BLUEZ_NAME, control_path,
668                         BT_PROPERTIES_INTERFACE, NULL, &err);
669         if (proxy == NULL) {
670                 BT_ERR("Unable to allocate new proxy \n");
671                 if (err) {
672                         BT_ERR("%s", err->message);
673                         g_clear_error(&err);
674                 }
675                 return BLUETOOTH_ERROR_INTERNAL;
676         }
677
678         interface_name = g_strdup(BT_PLAYER_CONTROL_INTERFACE);
679         property_name = g_strdup("Track");
680
681         parameters = g_variant_new("(ss)", interface_name, property_name);
682
683         g_free(interface_name);
684         g_free(property_name);
685
686         reply = g_dbus_proxy_call_sync(proxy, "Get", parameters,
687                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
688
689         g_object_unref(proxy);
690
691         if (!reply) {
692                 BT_ERR("Error returned in method call");
693                 if (err) {
694                         BT_ERR("%s", err->message);
695                         g_clear_error(&err);
696                 }
697                 return BLUETOOTH_ERROR_INTERNAL;
698         }
699
700         g_variant_get(reply, "(v)", &item);
701
702         ret = __bt_avrcp_control_parse_properties(metadata, item);
703
704         g_variant_unref(reply);
705         BT_DBG("-");
706         return ret;
707 }
708
709 void _bt_handle_avrcp_control_event(GVariant *reply, const char *path)
710 {
711         GVariant *param = NULL;
712         const char *property = NULL;
713
714         if (!reply) {
715                 BT_ERR("Error returned in method call\n");
716                 return;
717         }
718
719         GVariantIter iter;
720         GVariant *value = NULL;
721         g_variant_iter_init(&iter, reply);
722         while (g_variant_iter_loop(&iter, "{sv}", &property,
723                                 &value)) {
724                 if ((strcasecmp(property, "Equalizer") == 0) ||
725                         (strcasecmp(property, "Repeat") == 0) ||
726                         (strcasecmp(property, "Shuffle") == 0) ||
727                         (strcasecmp(property, "Scan") == 0) ||
728                         (strcasecmp(property, "Status") == 0)) {
729                                 const char *valstr;
730                                 unsigned int type, val = 0;
731
732                                 valstr = g_variant_get_string(value, NULL);
733                                 BT_DBG("Value : %s ", valstr);
734                                 type = __bt_media_attr_to_type(property);
735                                 if (valstr)
736                                         val = __bt_media_attrval_to_val(type, valstr);
737
738                                 /* Send event to application */
739                                 param = g_variant_new("(u)", val);
740                                 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
741                                         __bt_media_attr_to_event(property), param);
742                 } else if (strcasecmp(property, "Position") == 0) {
743                         unsigned int val;
744
745                         val = g_variant_get_uint32(value);
746                         BT_DBG("Value : %d ", val);
747
748                         /* Send event to application */
749                         param = g_variant_new("(u)", val);
750                         _bt_send_event(BT_AVRCP_CONTROL_EVENT,
751                                 __bt_media_attr_to_event(property), param);
752                 } else if (strcasecmp(property, "Track") == 0) {
753                         int ret = BLUETOOTH_ERROR_NONE;
754                         media_metadata_attributes_t metadata;
755
756                         memset(&metadata, 0x00, sizeof(media_metadata_attributes_t));
757
758                         ret = __bt_avrcp_control_parse_properties(
759                                                                 &metadata, value);
760                         if (BLUETOOTH_ERROR_NONE != ret) {
761                                 /* Free key and value because of break unless free not required */
762                                 free((char *)property);
763                                 g_variant_unref(value);
764                                 g_free((char *)metadata.title);
765                                 g_free((char *)metadata.artist);
766                                 g_free((char *)metadata.album);
767                                 g_free((char *)metadata.genre);
768                                 break;
769                         }
770
771                                 /* Send event to application */
772                         param = g_variant_new("(ssssuuu)",
773                                                         metadata.title,
774                                                         metadata.artist,
775                                                         metadata.album,
776                                                         metadata.genre,
777                                                         metadata.total_tracks,
778                                                         metadata.number,
779                                                         metadata.duration);
780                         _bt_send_event(BT_AVRCP_CONTROL_EVENT,
781                                 BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED, param);
782
783                         g_free((char *)metadata.title);
784                         g_free((char *)metadata.artist);
785                         g_free((char *)metadata.album);
786                         g_free((char *)metadata.genre);
787                 } else {
788                         BT_DBG("Property not handled");
789                 }
790         }
791
792         BT_DBG("-");
793 }