SVACE Fixes
[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         default:
220                 BT_DBG("Invalid Type\n");
221                 return BLUETOOTH_ERROR_INTERNAL;
222         }
223         BT_DBG("-");
224         return ret;
225 }
226
227 GDBusProxy *__bt_get_control_properties_proxy(void)
228 {
229         GDBusProxy *proxy = NULL;
230         GError *error = NULL;
231         char *control_path = NULL;
232         GDBusConnection *conn = NULL;
233
234         control_path = __bt_get_control_device_path();
235         retv_if(control_path == NULL, NULL);
236         BT_DBG("control_path = %s", control_path);
237
238         conn = _bt_gdbus_get_system_gconn();
239         retv_if(conn == NULL, NULL);
240
241         proxy = g_dbus_proxy_new_sync(conn,
242                         G_DBUS_PROXY_FLAGS_NONE, NULL,
243                         BT_BLUEZ_NAME, control_path,
244                         BT_PROPERTIES_INTERFACE, NULL, &error);
245         if (proxy == NULL) {
246                 BT_ERR("Unable to allocate new proxy");
247                 if (error) {
248                         BT_ERR("%s", error->message);
249                         g_clear_error(&error);
250                 }
251                 return NULL;
252         }
253
254         return proxy;
255 }
256
257 GDBusProxy *__bt_get_transport_properties_proxy(void)
258 {
259         GDBusProxy *proxy = NULL;
260         GError *error = NULL;
261         char *transport_path = NULL;
262         GDBusConnection *conn = NULL;
263
264         transport_path = __bt_get_transport_device_path();
265         retv_if(transport_path == NULL, NULL);
266         BT_DBG("transport_path = %s", transport_path);
267
268         conn = _bt_gdbus_get_system_gconn();
269         retv_if(conn == NULL, NULL);
270
271         proxy = g_dbus_proxy_new_sync(conn,
272                         G_DBUS_PROXY_FLAGS_NONE, NULL,
273                         BT_BLUEZ_NAME, transport_path,
274                         BT_PROPERTIES_INTERFACE, NULL, &error);
275         if (proxy == NULL) {
276                 BT_ERR("Unable to allocate new proxy");
277                 if (error) {
278                         BT_ERR("%s", error->message);
279                         g_clear_error(&error);
280                 }
281                 return NULL;
282         }
283
284         return proxy;
285 }
286
287 static int __bt_media_attr_to_event(const char *str)
288 {
289         if (!strcasecmp(str, "Equalizer"))
290                 return BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS;
291         else if (!strcasecmp(str, "Repeat"))
292                 return BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS;
293         else if (!strcasecmp(str, "Shuffle"))
294                 return BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS;
295         else if (!strcasecmp(str, "Scan"))
296                 return BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS;
297         else if (!strcasecmp(str, "Position"))
298                 return BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS;
299         else if (!strcasecmp(str, "Track"))
300                 return BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED;
301         else if (!strcasecmp(str, "Status"))
302                 return BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED;
303
304         return 0;
305 }
306
307 static int __bt_media_attr_to_type(const char *str)
308 {
309         if (!strcasecmp(str, "Equalizer"))
310                 return EQUALIZER;
311         else if (!strcasecmp(str, "Repeat"))
312                 return REPEAT;
313         else if (!strcasecmp(str, "Shuffle"))
314                 return SHUFFLE;
315         else if (!strcasecmp(str, "Scan"))
316                 return SCAN;
317         else if (!strcasecmp(str, "Position"))
318                 return POSITION;
319         else if (!strcasecmp(str, "Track"))
320                 return METADATA;
321         else if (!strcasecmp(str, "Status"))
322                 return STATUS;
323
324         return 0;
325 }
326
327 static const char *__bt_media_type_to_str(int type)
328 {
329         switch (type) {
330         case EQUALIZER:
331                 return "Equalizer";
332         case REPEAT:
333                 return "Repeat";
334         case SHUFFLE:
335                 return "Shuffle";
336         case SCAN:
337                 return "Scan";
338         case POSITION:
339                 return "Position";
340         case METADATA:
341                 return "Track";
342         case STATUS:
343                 return "Status";
344         }
345         return NULL;
346 }
347
348 static const char *__bt_transport_type_to_str(int type)
349 {
350         switch (type) {
351         case DELAY:
352                 return "Delay";
353         case VOLUME:
354                 return "Volume";
355         }
356         return NULL;
357 }
358
359 static int __bt_media_attrval_to_val(int type, const char *value)
360 {
361         int ret = 0;
362
363         switch (type) {
364         case EQUALIZER:
365                 if (!strcmp(value, "off"))
366                         ret = EQUALIZER_OFF;
367                 else if (!strcmp(value, "on"))
368                         ret = EQUALIZER_ON;
369                 else
370                         ret = EQUALIZER_INVALID;
371                 break;
372
373         case REPEAT:
374                 if (!strcmp(value, "off"))
375                         ret = REPEAT_MODE_OFF;
376                 else if (!strcmp(value, "singletrack"))
377                         ret = REPEAT_SINGLE_TRACK;
378                 else if (!strcmp(value, "alltracks"))
379                         ret = REPEAT_ALL_TRACK;
380                 else if (!strcmp(value, "group"))
381                         ret = REPEAT_GROUP;
382                 else
383                         ret = REPEAT_INVALID;
384                 break;
385
386         case SHUFFLE:
387                 if (!strcmp(value, "off"))
388                         ret = SHUFFLE_MODE_OFF;
389                 else if (!strcmp(value, "alltracks"))
390                         ret = SHUFFLE_ALL_TRACK;
391                 else if (!strcmp(value, "group"))
392                         ret = SHUFFLE_GROUP;
393                 else
394                         ret = SHUFFLE_INVALID;
395                 break;
396
397         case SCAN:
398                 if (!strcmp(value, "off"))
399                         ret = SCAN_MODE_OFF;
400                 else if (!strcmp(value, "alltracks"))
401                         ret = SCAN_ALL_TRACK;
402                 else if (!strcmp(value, "group"))
403                         ret = SCAN_GROUP;
404                 else
405                         ret = SCAN_INVALID;
406                 break;
407
408         case STATUS:
409                 if (!strcmp(value, "stopped"))
410                         ret = STATUS_STOPPED;
411                 else if (!strcmp(value, "playing"))
412                         ret = STATUS_PLAYING;
413                 else if (!strcmp(value, "paused"))
414                         ret = STATUS_PAUSED;
415                 else if (!strcmp(value, "forward-seek"))
416                         ret = STATUS_FORWARD_SEEK;
417                 else if (!strcmp(value, "reverse-seek"))
418                         ret = STATUS_REVERSE_SEEK;
419                 else if (!strcmp(value, "error"))
420                         ret = STATUS_ERROR;
421                 else
422                         ret = STATUS_INVALID;
423         }
424         return ret;
425 }
426
427 int _bt_avrcp_control_get_property(int type, unsigned int *value)
428 {
429         GDBusProxy *proxy = NULL;
430         char *name = NULL;
431         int ret = BLUETOOTH_ERROR_NONE;
432         GError *err = NULL;
433         GVariant *reply = NULL;
434         GVariant *temp = NULL;
435
436         BT_CHECK_PARAMETER(value, return);
437
438         proxy = __bt_get_control_properties_proxy();
439         retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
440
441         reply = g_dbus_proxy_call_sync(proxy,
442                                         "Get", g_variant_new("(ss)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type)),
443                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
444
445         g_object_unref(proxy);
446
447         if (!reply) {
448                 BT_ERR("Can't get managed objects");
449                 if (err) {
450                         BT_ERR("%s", err->message);
451                         g_clear_error(&err);
452                 }
453                 return BLUETOOTH_ERROR_INTERNAL;
454         } else {
455                         switch (type) {
456                         case EQUALIZER:
457                         case REPEAT:
458                         case SHUFFLE:
459                         case SCAN:
460                         case STATUS:
461                                 name = (char *)g_variant_get_data(reply);
462                                 if (name)
463                                         *value = __bt_media_attrval_to_val(type, name);
464                                 BT_INFO("Type[%s] and Value[%s]", __bt_media_type_to_str(type), name);
465                                 break;
466                         case POSITION:
467                                 g_variant_get(reply, "(v)", &temp);
468                                 *value = g_variant_get_uint32(temp);
469                                 g_variant_unref(temp);
470                                 BT_INFO("Type[%s] and Value[%d]", __bt_media_type_to_str(type), *value);
471                                 break;
472                         default:
473                                 BT_ERR("Invalid Type [%d]", type);
474                                 ret =  BLUETOOTH_ERROR_INTERNAL;
475                         }
476                 }
477         g_variant_unref(reply);
478         return ret;
479 }
480
481 int _bt_avrcp_control_set_property(int type, unsigned int value)
482 {
483         GValue *attr_value = NULL;
484         GDBusProxy *proxy = NULL;
485         GError *error = NULL;
486         GVariant *reply, *param;
487
488         g_value_init(attr_value, G_TYPE_STRING);
489
490         switch (type) {
491         case EQUALIZER:
492                 param = g_variant_new("s", equalizer_status[value].property);
493                 BT_INFO("equalizer_status %s", equalizer_status[value].property);
494                 break;
495         case REPEAT:
496                 param = g_variant_new("s", repeat_status[value].property);
497                 BT_INFO("repeat_status %s", repeat_status[value].property);
498                 break;
499         case SHUFFLE:
500                 param = g_variant_new("s", shuffle_settings[value].property);
501                 BT_INFO("shuffle_settings %s", shuffle_settings[value].property);
502                 break;
503         case SCAN:
504                 param = g_variant_new("s", scan_status[value].property);
505                 BT_INFO("scan_status %s", scan_status[value].property);
506                 break;
507         default:
508                 BT_ERR("Invalid property type: %d", type);
509                 g_value_unset(attr_value);
510                 return BLUETOOTH_ERROR_INTERNAL;
511         }
512
513         proxy = __bt_get_control_properties_proxy();
514         retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
515
516         reply = g_dbus_proxy_call_sync(proxy,
517                                         "Set", g_variant_new("(ssv)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type), param),
518                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
519
520         g_object_unref(proxy);
521         g_variant_unref(param);
522
523         if (!reply) {
524                 BT_ERR("Can't get managed objects");
525                 if (error) {
526                         BT_ERR("SetProperty Fail: %s", error->message);
527                         g_clear_error(&error);
528                         return BLUETOOTH_ERROR_INTERNAL;
529                 }
530         }
531
532         g_variant_unref(reply);
533         g_value_unset(attr_value);
534
535         return BLUETOOTH_ERROR_NONE;
536 }
537
538 int _bt_avrcp_transport_set_property(int type, unsigned int value)
539 {
540         GDBusProxy *proxy = NULL;
541         GError *error = NULL;
542         GVariant *reply, *param;
543         uint16_t property_level = (uint16_t)value;
544
545         switch (type) {
546         case DELAY:
547                 param = g_variant_new("q", property_level);
548                 BT_INFO("delay level %d", property_level);
549                 break;
550         case VOLUME:
551                 param = g_variant_new("q", property_level);
552                 BT_INFO("volume level %d", property_level);
553                 break;
554         default:
555                 BT_ERR("Invalid property type: %d", type);
556                 return BLUETOOTH_ERROR_INTERNAL;
557         }
558
559         proxy = __bt_get_transport_properties_proxy();
560         retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
561
562         reply = g_dbus_proxy_call_sync(proxy,
563                                         "Set", g_variant_new("(ssv)", BT_MEDIATRANSPORT_INTERFACE, __bt_transport_type_to_str(type), param),
564                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
565
566         g_object_unref(proxy);
567         g_variant_unref(param);
568
569         if (!reply) {
570                 BT_ERR("Can't get managed objects");
571                 if (error) {
572                         BT_ERR("SetProperty Fail: %s", error->message);
573                         g_clear_error(&error);
574                         return BLUETOOTH_ERROR_INTERNAL;
575                 }
576         }
577
578         g_variant_unref(reply);
579
580         return BLUETOOTH_ERROR_NONE;
581 }
582
583 static int __bt_avrcp_control_parse_properties(
584                                 media_metadata_attributes_t *metadata,
585                                 GVariant *item)
586 {
587         GVariant *value = NULL;
588         GVariantIter iter;
589         char *value_string = NULL;
590         unsigned int value_uint;
591         const char *key = NULL;
592
593         g_variant_iter_init(&iter, item);
594         while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) {
595                 if (strcasecmp(key, "Title") == 0) {
596                         value_string = (char *)g_variant_get_string(value, NULL);
597                         BT_DBG("Value : %s ", value_string);
598                         metadata->title = g_strdup(value_string);
599                 } else if (strcasecmp(key, "Artist") == 0) {
600                         value_string = (char *)g_variant_get_string(value, NULL);
601                         BT_DBG("Value : %s ", value_string);
602                         metadata->artist = g_strdup(value_string);
603                 } else if (strcasecmp(key, "Album") == 0) {
604                         value_string = (char *)g_variant_get_string(value, NULL);
605                         BT_DBG("Value : %s ", value_string);
606                         metadata->album = g_strdup(value_string);
607                 } else if (strcasecmp(key, "Genre") == 0) {
608                         value_string = (char *)g_variant_get_string(value, NULL);
609                         BT_DBG("Value : %s ", value_string);
610                         metadata->genre = g_strdup(value_string);
611                 } else if (strcasecmp(key, "Duration") == 0) {
612                         value_uint = g_variant_get_uint32(value);
613                         BT_DBG("Duration : %d", value_uint);
614                         metadata->duration = value_uint;
615                 } else if (strcasecmp(key, "NumberOfTracks") == 0) {
616                         value_uint = g_variant_get_uint32(value);
617                         metadata->total_tracks = value_uint;
618                 } else if (strcasecmp(key, "TrackNumber") == 0) {
619                         value_uint = g_variant_get_uint32(value);
620                         metadata->number = value_uint;
621                 } else
622                         BT_DBG("%s not supported, ignoring", key);
623         }
624
625         if (!metadata->title)
626                 metadata->title = g_strdup("");
627         if (!metadata->artist)
628                 metadata->artist = g_strdup("");
629         if (!metadata->album)
630                 metadata->album = g_strdup("");
631         if (!metadata->genre)
632                 metadata->genre = g_strdup("");
633
634         return BLUETOOTH_ERROR_NONE;
635
636 }
637
638 int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata)
639 {
640         GDBusProxy *proxy = NULL;
641         GVariant *reply = NULL;
642         GVariant *item = NULL;
643         GError *err = NULL;
644         GDBusConnection *conn = NULL;
645         char *control_path = NULL;
646         char *interface_name = NULL;
647         char *property_name = NULL;
648         GVariant *parameters = NULL;
649         int ret = BLUETOOTH_ERROR_NONE;
650
651         retv_if(metadata == NULL, BLUETOOTH_ERROR_INTERNAL);
652
653         conn = _bt_gdbus_get_system_gconn();
654         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
655
656         control_path = __bt_get_control_device_path();
657         retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
658         BT_DBG("control_path %s", control_path);
659
660         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
661                         BT_BLUEZ_NAME, control_path,
662                         BT_PROPERTIES_INTERFACE, NULL, &err);
663         if (proxy == NULL) {
664                 BT_ERR("Unable to allocate new proxy \n");
665                 if (err) {
666                         BT_ERR("%s", err->message);
667                         g_clear_error(&err);
668                 }
669                 return BLUETOOTH_ERROR_INTERNAL;
670         }
671
672         interface_name = g_strdup(BT_PLAYER_CONTROL_INTERFACE);
673         property_name = g_strdup("Track");
674
675         parameters = g_variant_new("(ss)", interface_name, property_name);
676
677         g_free(interface_name);
678         g_free(property_name);
679
680         reply = g_dbus_proxy_call_sync(proxy, "Get", parameters,
681                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
682
683         g_object_unref(proxy);
684
685         if (!reply) {
686                 BT_ERR("Error returned in method call");
687                 if (err) {
688                         BT_ERR("%s", err->message);
689                         g_clear_error(&err);
690                 }
691                 return BLUETOOTH_ERROR_INTERNAL;
692         }
693
694         g_variant_get(reply, "(v)", &item);
695
696         ret = __bt_avrcp_control_parse_properties(metadata, item);
697
698         g_variant_unref(reply);
699         BT_DBG("-");
700         return ret;
701 }
702
703 void _bt_handle_avrcp_control_event(GVariant *reply, const char *path)
704 {
705         GVariant *param = NULL;
706         const char *property = NULL;
707
708         if (!reply) {
709                 BT_ERR("Error returned in method call\n");
710                 return;
711         }
712
713         GVariantIter iter;
714         GVariant *value = NULL;
715         g_variant_iter_init(&iter, reply);
716         while (g_variant_iter_loop(&iter, "{sv}", &property,
717                                 &value)) {
718                 if ((strcasecmp(property, "Equalizer") == 0) ||
719                         (strcasecmp(property, "Repeat") == 0) ||
720                         (strcasecmp(property, "Shuffle") == 0) ||
721                         (strcasecmp(property, "Scan") == 0) ||
722                         (strcasecmp(property, "Status") == 0)) {
723                                 const char *valstr;
724                                 unsigned int type, val = 0;
725
726                                 valstr = g_variant_get_string(value, NULL);
727                                 BT_DBG("Value : %s ", valstr);
728                                 type = __bt_media_attr_to_type(property);
729                                 if (valstr)
730                                         val = __bt_media_attrval_to_val(type, valstr);
731
732                                 /* Send event to application */
733                                 param = g_variant_new("(u)", val);
734                                 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
735                                         __bt_media_attr_to_event(property), param);
736                 } else if (strcasecmp(property, "Position") == 0) {
737                         unsigned int val;
738
739                         val = g_variant_get_uint32(value);
740                         BT_DBG("Value : %d ", val);
741
742                         /* Send event to application */
743                         param = g_variant_new("(u)", val);
744                         _bt_send_event(BT_AVRCP_CONTROL_EVENT,
745                                 __bt_media_attr_to_event(property), param);
746                 } else if (strcasecmp(property, "Track") == 0) {
747                         int ret = BLUETOOTH_ERROR_NONE;
748                         media_metadata_attributes_t metadata;
749
750                         memset(&metadata, 0x00, sizeof(media_metadata_attributes_t));
751
752                         ret = __bt_avrcp_control_parse_properties(
753                                                                 &metadata, value);
754                         if (BLUETOOTH_ERROR_NONE != ret) {
755                                 /* Free key and value because of break unless free not required */
756                                 free((char *)property);
757                                 g_variant_unref(value);
758                                 g_free((char *)metadata.title);
759                                 g_free((char *)metadata.artist);
760                                 g_free((char *)metadata.album);
761                                 g_free((char *)metadata.genre);
762                                 break;
763                         }
764
765                                 /* Send event to application */
766                         param = g_variant_new("(ssssuuu)",
767                                                         metadata.title,
768                                                         metadata.artist,
769                                                         metadata.album,
770                                                         metadata.genre,
771                                                         metadata.total_tracks,
772                                                         metadata.number,
773                                                         metadata.duration);
774                         _bt_send_event(BT_AVRCP_CONTROL_EVENT,
775                                 BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED, param);
776
777                         g_free((char *)metadata.title);
778                         g_free((char *)metadata.artist);
779                         g_free((char *)metadata.album);
780                         g_free((char *)metadata.genre);
781                 } else {
782                         BT_DBG("Property not handled");
783                 }
784         }
785
786         BT_DBG("-");
787 }