[OTP] Fix PTS fail cases
[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
58 void _bt_set_control_device_path(const char *path)
59 {
60
61         ret_if(path == NULL);
62
63         g_free(avrcp_control_path);
64         BT_DBG("control_path = %s", path);
65         avrcp_control_path = g_strdup(path);
66 }
67
68 void _bt_remove_control_device_path(const char *path)
69 {
70         ret_if(path == NULL);
71
72         if (avrcp_control_path &&
73                         !g_strcmp0(avrcp_control_path, path)) {
74                 BT_DBG("control_path = %s", path);
75                 g_free(avrcp_control_path);
76                 avrcp_control_path = NULL;
77         }
78 }
79
80 static char *__bt_get_control_device_path(void)
81 {
82         char *adapter_path;
83         char *control_path;
84         char connected_address[BT_ADDRESS_STRING_SIZE + 1];
85
86         BT_DBG("+");
87
88         if (avrcp_control_path != NULL)
89                 return avrcp_control_path;
90
91         retv_if(!_bt_is_headset_type_connected(BT_AVRCP,
92                         connected_address), NULL);
93
94         BT_DBG("device address = %s", connected_address);
95
96         adapter_path = _bt_get_device_object_path(connected_address);
97         retv_if(adapter_path == NULL, NULL);
98
99         control_path = g_strdup_printf(BT_MEDIA_CONTROL_PATH, adapter_path);
100         g_free(adapter_path);
101
102         avrcp_control_path = control_path;
103         BT_DBG("control_path = %s", control_path);
104         return control_path;
105 }
106
107 static int __bt_media_send_control_msg(const char *name)
108 {
109         GVariant *reply = NULL;
110         GError *err = NULL;
111         GDBusConnection *conn = NULL;
112         GDBusProxy *proxy = NULL;
113         char *control_path = NULL;
114
115         retv_if(name == NULL, BLUETOOTH_ERROR_INTERNAL);
116
117         BT_INFO("Command [%s]", name);
118
119         conn = _bt_gdbus_get_system_gconn();
120         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
121
122         control_path = __bt_get_control_device_path();
123         retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
124         BT_DBG("control_path %s", control_path);
125
126         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
127                         BT_BLUEZ_NAME, control_path,
128                         BT_PLAYER_CONTROL_INTERFACE, NULL, &err);
129         if (proxy == NULL) {
130                 BT_ERR("Unable to allocate new proxy \n");
131                 if (err) {
132                         BT_ERR("%s", err->message);
133                         g_clear_error(&err);
134                 }
135                 return BLUETOOTH_ERROR_INTERNAL;
136         }
137
138         reply = g_dbus_proxy_call_sync(proxy, name, NULL,
139                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
140
141         g_object_unref(proxy);
142
143         if (!reply) {
144                 BT_ERR("Error returned in method call");
145                 if (err) {
146                         BT_ERR("%s", err->message);
147                         g_clear_error(&err);
148                 }
149                 return BLUETOOTH_ERROR_INTERNAL;
150         }
151
152         g_variant_unref(reply);
153
154         BT_DBG("-");
155         return BLUETOOTH_ERROR_NONE;
156 }
157
158 int _bt_avrcp_control_cmd(int type)
159 {
160         int ret = BLUETOOTH_ERROR_INTERNAL;
161         BT_DBG("+");
162
163         switch (type) {
164         case PLAY:
165                 ret = __bt_media_send_control_msg("Play");
166                 break;
167         case PAUSE:
168                 ret = __bt_media_send_control_msg("Pause");
169                 break;
170         case STOP:
171                 ret = __bt_media_send_control_msg("Stop");
172                 break;
173         case NEXT:
174                 ret = __bt_media_send_control_msg("Next");
175                 break;
176         case PREVIOUS:
177                 ret = __bt_media_send_control_msg("Previous");
178                 break;
179         case PRESS_FAST_FORWARD:
180                 ret = __bt_media_send_control_msg("PressFastForward");
181                 break;
182         case RELEASE_FAST_FORWARD:
183                 ret = __bt_media_send_control_msg("ReleaseFastForward");
184                 break;
185         case PRESS_REWIND:
186                 ret = __bt_media_send_control_msg("PressRewind");
187                 break;
188         case RELEASE_REWIND:
189                 ret = __bt_media_send_control_msg("ReleaseRewind");
190                 break;
191         default:
192                 BT_DBG("Invalid Type\n");
193                 return BLUETOOTH_ERROR_INTERNAL;
194         }
195         BT_DBG("-");
196         return ret;
197 }
198
199 GDBusProxy *__bt_get_control_properties_proxy(void)
200 {
201         GDBusProxy *proxy = NULL;
202         GError *error = NULL;
203         char *control_path = NULL;
204         GDBusConnection *conn = NULL;
205
206         control_path = __bt_get_control_device_path();
207         retv_if(control_path == NULL, NULL);
208         BT_DBG("control_path = %s", control_path);
209
210         conn = _bt_gdbus_get_system_gconn();
211         retv_if(conn == NULL, NULL);
212
213         proxy = g_dbus_proxy_new_sync(conn,
214                         G_DBUS_PROXY_FLAGS_NONE, NULL,
215                         BT_BLUEZ_NAME, control_path,
216                         BT_PROPERTIES_INTERFACE, NULL, &error);
217         if (proxy == NULL) {
218                 BT_ERR("Unable to allocate new proxy");
219                 if (error) {
220                         BT_ERR("%s", error->message);
221                         g_clear_error(&error);
222                 }
223                 return NULL;
224         }
225
226         return proxy;
227 }
228
229 static int __bt_media_attr_to_event(const char *str)
230 {
231         if (!strcasecmp(str, "Equalizer"))
232                 return BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS;
233         else if (!strcasecmp(str, "Repeat"))
234                 return BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS;
235         else if (!strcasecmp(str, "Shuffle"))
236                 return BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS;
237         else if (!strcasecmp(str, "Scan"))
238                 return BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS;
239         else if (!strcasecmp(str, "Position"))
240                 return BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS;
241         else if (!strcasecmp(str, "Track"))
242                 return BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED;
243         else if (!strcasecmp(str, "Status"))
244                 return BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED;
245
246         return 0;
247 }
248
249 static int __bt_media_attr_to_type(const char *str)
250 {
251         if (!strcasecmp(str, "Equalizer"))
252                 return EQUALIZER;
253         else if (!strcasecmp(str, "Repeat"))
254                 return REPEAT;
255         else if (!strcasecmp(str, "Shuffle"))
256                 return SHUFFLE;
257         else if (!strcasecmp(str, "Scan"))
258                 return SCAN;
259         else if (!strcasecmp(str, "Position"))
260                 return POSITION;
261         else if (!strcasecmp(str, "Track"))
262                 return METADATA;
263         else if (!strcasecmp(str, "Status"))
264                 return STATUS;
265
266         return 0;
267 }
268
269 static const char *__bt_media_type_to_str(int type)
270 {
271         switch (type) {
272         case EQUALIZER:
273                 return "Equalizer";
274         case REPEAT:
275                 return "Repeat";
276         case SHUFFLE:
277                 return "Shuffle";
278         case SCAN:
279                 return "Scan";
280         case POSITION:
281                 return "Position";
282         case METADATA:
283                 return "Track";
284         case STATUS:
285                 return "Status";
286         }
287         return NULL;
288 }
289
290 static int __bt_media_attrval_to_val(int type, const char *value)
291 {
292         int ret = 0;
293
294         switch (type) {
295         case EQUALIZER:
296                 if (!strcmp(value, "off"))
297                         ret = EQUALIZER_OFF;
298                 else if (!strcmp(value, "on"))
299                         ret = EQUALIZER_ON;
300                 else
301                         ret = EQUALIZER_INVALID;
302                 break;
303
304         case REPEAT:
305                 if (!strcmp(value, "off"))
306                         ret = REPEAT_MODE_OFF;
307                 else if (!strcmp(value, "singletrack"))
308                         ret = REPEAT_SINGLE_TRACK;
309                 else if (!strcmp(value, "alltracks"))
310                         ret = REPEAT_ALL_TRACK;
311                 else if (!strcmp(value, "group"))
312                         ret = REPEAT_GROUP;
313                 else
314                         ret = REPEAT_INVALID;
315                 break;
316
317         case SHUFFLE:
318                 if (!strcmp(value, "off"))
319                         ret = SHUFFLE_MODE_OFF;
320                 else if (!strcmp(value, "alltracks"))
321                         ret = SHUFFLE_ALL_TRACK;
322                 else if (!strcmp(value, "group"))
323                         ret = SHUFFLE_GROUP;
324                 else
325                         ret = SHUFFLE_INVALID;
326                 break;
327
328         case SCAN:
329                 if (!strcmp(value, "off"))
330                         ret = SCAN_MODE_OFF;
331                 else if (!strcmp(value, "alltracks"))
332                         ret = SCAN_ALL_TRACK;
333                 else if (!strcmp(value, "group"))
334                         ret = SCAN_GROUP;
335                 else
336                         ret = SCAN_INVALID;
337                 break;
338
339         case STATUS:
340                 if (!strcmp(value, "stopped"))
341                         ret = STATUS_STOPPED;
342                 else if (!strcmp(value, "playing"))
343                         ret = STATUS_PLAYING;
344                 else if (!strcmp(value, "paused"))
345                         ret = STATUS_PAUSED;
346                 else if (!strcmp(value, "forward-seek"))
347                         ret = STATUS_FORWARD_SEEK;
348                 else if (!strcmp(value, "reverse-seek"))
349                         ret = STATUS_REVERSE_SEEK;
350                 else if (!strcmp(value, "error"))
351                         ret = STATUS_ERROR;
352                 else
353                         ret = STATUS_INVALID;
354         }
355         return ret;
356 }
357
358 int _bt_avrcp_control_get_property(int type, unsigned int *value)
359 {
360         GDBusProxy *proxy = NULL;
361         char *name = NULL;
362         int ret = BLUETOOTH_ERROR_NONE;
363         GError *err = NULL;
364         GVariant *reply = NULL;
365         GVariant *temp = NULL;
366
367         BT_CHECK_PARAMETER(value, return);
368
369         proxy = __bt_get_control_properties_proxy();
370         retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
371
372         reply = g_dbus_proxy_call_sync(proxy,
373                                         "Get", g_variant_new("(ss)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type)),
374                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
375
376         g_object_unref(proxy);
377
378         if (!reply) {
379                 BT_ERR("Can't get managed objects");
380                 if (err) {
381                         BT_ERR("%s", err->message);
382                         g_clear_error(&err);
383                 }
384                 return BLUETOOTH_ERROR_INTERNAL;
385         } else {
386                         switch (type) {
387                         case EQUALIZER:
388                         case REPEAT:
389                         case SHUFFLE:
390                         case SCAN:
391                         case STATUS:
392                                 name = (char *)g_variant_get_data(reply);
393                                 if (name)
394                                         *value = __bt_media_attrval_to_val(type, name);
395                                 BT_INFO("Type[%s] and Value[%s]", __bt_media_type_to_str(type), name);
396                                 break;
397                         case POSITION:
398                                 g_variant_get(reply, "(v)", &temp);
399                                 *value = g_variant_get_uint32(temp);
400                                 g_variant_unref(temp);
401                                 BT_INFO("Type[%s] and Value[%d]", __bt_media_type_to_str(type), *value);
402                                 break;
403                         default:
404                                 BT_ERR("Invalid Type [%d]", type);
405                                 ret =  BLUETOOTH_ERROR_INTERNAL;
406                         }
407                 }
408         g_variant_unref(reply);
409         return ret;
410 }
411
412 int _bt_avrcp_control_set_property(int type, unsigned int value)
413 {
414         GValue *attr_value = NULL;
415         GDBusProxy *proxy = NULL;
416         GError *error = NULL;
417         GVariant *reply, *param;
418
419         g_value_init(attr_value, G_TYPE_STRING);
420
421         switch (type) {
422         case EQUALIZER:
423                 param = g_variant_new("s", equalizer_status[value].property);
424                 BT_INFO("equalizer_status %s", equalizer_status[value].property);
425                 break;
426         case REPEAT:
427                 param = g_variant_new("s", repeat_status[value].property);
428                 BT_INFO("repeat_status %s", repeat_status[value].property);
429                 break;
430         case SHUFFLE:
431                 param = g_variant_new("s", shuffle_settings[value].property);
432                 BT_INFO("shuffle_settings %s", shuffle_settings[value].property);
433                 break;
434         case SCAN:
435                 param = g_variant_new("s", scan_status[value].property);
436                 BT_INFO("scan_status %s", scan_status[value].property);
437                 break;
438         default:
439                 BT_ERR("Invalid property type: %d", type);
440                 g_value_unset(attr_value);
441                 return BLUETOOTH_ERROR_INTERNAL;
442         }
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                                         "Set", g_variant_new("(ssv)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type), param),
449                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
450
451         g_object_unref(proxy);
452         g_variant_unref(param);
453
454         if (!reply) {
455                 BT_ERR("Can't get managed objects");
456                 if (error) {
457                         BT_ERR("SetProperty Fail: %s", error->message);
458                         g_clear_error(&error);
459                         return BLUETOOTH_ERROR_INTERNAL;
460                 }
461         }
462
463         g_variant_unref(reply);
464         g_value_unset(attr_value);
465
466         return BLUETOOTH_ERROR_NONE;
467 }
468
469 static int __bt_avrcp_control_parse_properties(
470                                 media_metadata_attributes_t *metadata,
471                                 GVariant *item)
472 {
473         GVariant *value = NULL;
474         GVariantIter iter;
475         char *value_string = NULL;
476         unsigned int value_uint;
477         const char *key = NULL;
478
479         g_variant_iter_init(&iter, item);
480         while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) {
481                 if (strcasecmp(key, "Title") == 0) {
482                         value_string = (char *)g_variant_get_string(value, NULL);
483                         BT_DBG("Value : %s ", value_string);
484                         metadata->title = g_strdup(value_string);
485                 } else if (strcasecmp(key, "Artist") == 0) {
486                         value_string = (char *)g_variant_get_string(value, NULL);
487                         BT_DBG("Value : %s ", value_string);
488                         metadata->artist = g_strdup(value_string);
489                 } else if (strcasecmp(key, "Album") == 0) {
490                         value_string = (char *)g_variant_get_string(value, NULL);
491                         BT_DBG("Value : %s ", value_string);
492                         metadata->album = g_strdup(value_string);
493                 } else if (strcasecmp(key, "Genre") == 0) {
494                         value_string = (char *)g_variant_get_string(value, NULL);
495                         BT_DBG("Value : %s ", value_string);
496                         metadata->genre = g_strdup(value_string);
497                 } else if (strcasecmp(key, "Duration") == 0) {
498                         value_uint = g_variant_get_uint32(value);
499                         BT_DBG("Duration : %d", value_uint);
500                         metadata->duration = value_uint;
501                 } else if (strcasecmp(key, "NumberOfTracks") == 0) {
502                         value_uint = g_variant_get_uint32(value);
503                         metadata->total_tracks = value_uint;
504                 } else if (strcasecmp(key, "TrackNumber") == 0) {
505                         value_uint = g_variant_get_uint32(value);
506                         metadata->number = value_uint;
507                 } else
508                         BT_DBG("%s not supported, ignoring", key);
509         }
510
511         if (!metadata->title)
512                 metadata->title = g_strdup("");
513         if (!metadata->artist)
514                 metadata->artist = g_strdup("");
515         if (!metadata->album)
516                 metadata->album = g_strdup("");
517         if (!metadata->genre)
518                 metadata->genre = g_strdup("");
519
520         return BLUETOOTH_ERROR_NONE;
521
522 }
523
524 int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata)
525 {
526         GDBusProxy *proxy = NULL;
527         GVariant *reply = NULL;
528         GVariant *item = NULL;
529         GError *err = NULL;
530         GDBusConnection *conn = NULL;
531         char *control_path = NULL;
532         char *interface_name = NULL;
533         char *property_name = NULL;
534         GVariant *parameters = NULL;
535         int ret = BLUETOOTH_ERROR_NONE;
536
537         retv_if(metadata == NULL, BLUETOOTH_ERROR_INTERNAL);
538
539         conn = _bt_gdbus_get_system_gconn();
540         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
541
542         control_path = __bt_get_control_device_path();
543         retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
544         BT_DBG("control_path %s", control_path);
545
546         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
547                         BT_BLUEZ_NAME, control_path,
548                         BT_PROPERTIES_INTERFACE, NULL, &err);
549         if (proxy == NULL) {
550                 BT_ERR("Unable to allocate new proxy \n");
551                 if (err) {
552                         BT_ERR("%s", err->message);
553                         g_clear_error(&err);
554                 }
555                 return BLUETOOTH_ERROR_INTERNAL;
556         }
557
558         interface_name = g_strdup(BT_PLAYER_CONTROL_INTERFACE);
559         property_name = g_strdup("Track");
560
561         parameters = g_variant_new("(ss)", interface_name, property_name);
562
563         g_free(interface_name);
564         g_free(property_name);
565
566         reply = g_dbus_proxy_call_sync(proxy, "Get", parameters,
567                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
568
569         g_object_unref(proxy);
570
571         if (!reply) {
572                 BT_ERR("Error returned in method call");
573                 if (err) {
574                         BT_ERR("%s", err->message);
575                         g_clear_error(&err);
576                 }
577                 return BLUETOOTH_ERROR_INTERNAL;
578         }
579
580         g_variant_get(reply, "(v)", &item);
581
582         ret = __bt_avrcp_control_parse_properties(metadata, item);
583
584         g_variant_unref(reply);
585         BT_DBG("-");
586         return ret;
587 }
588
589 void _bt_handle_avrcp_control_event(GVariant *reply, const char *path)
590 {
591         GVariant *param = NULL;
592         const char *property = NULL;
593
594         if (!reply) {
595                 BT_ERR("Error returned in method call\n");
596                 return;
597         }
598
599         GVariantIter iter;
600         GVariant *value = NULL;
601         g_variant_iter_init(&iter, reply);
602         while (g_variant_iter_loop(&iter, "{sv}", &property,
603                                 &value)) {
604                 if ((strcasecmp(property, "Equalizer") == 0) ||
605                         (strcasecmp(property, "Repeat") == 0) ||
606                         (strcasecmp(property, "Shuffle") == 0) ||
607                         (strcasecmp(property, "Scan") == 0) ||
608                         (strcasecmp(property, "Status") == 0)) {
609                                 const char *valstr;
610                                 unsigned int type, val = 0;
611
612                                 valstr = g_variant_get_string(value, NULL);
613                                 BT_DBG("Value : %s ", valstr);
614                                 type = __bt_media_attr_to_type(property);
615                                 if (valstr)
616                                         val = __bt_media_attrval_to_val(type, valstr);
617
618                                 /* Send event to application */
619                                 param = g_variant_new("(u)", val);
620                                 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
621                                         __bt_media_attr_to_event(property), param);
622                 } else if (strcasecmp(property, "Position") == 0) {
623                         unsigned int val;
624
625                         val = g_variant_get_uint32(value);
626                         BT_DBG("Value : %d ", val);
627
628                         /* Send event to application */
629                         param = g_variant_new("(u)", val);
630                         _bt_send_event(BT_AVRCP_CONTROL_EVENT,
631                                 __bt_media_attr_to_event(property), param);
632                 } else if (strcasecmp(property, "Track") == 0) {
633                         int ret = BLUETOOTH_ERROR_NONE;
634                         media_metadata_attributes_t metadata;
635
636                         memset(&metadata, 0x00, sizeof(media_metadata_attributes_t));
637
638                         ret = __bt_avrcp_control_parse_properties(
639                                                                 &metadata, value);
640                         if (BLUETOOTH_ERROR_NONE != ret) {
641                                 /* Free key and value because of break unless free not required */
642                                 free((char *)property);
643                                 g_variant_unref(value);
644                                 g_free((char *)metadata.title);
645                                 g_free((char *)metadata.artist);
646                                 g_free((char *)metadata.album);
647                                 g_free((char *)metadata.genre);
648                                 break;
649                         }
650
651                                 /* Send event to application */
652                         param = g_variant_new("(ssssuuu)",
653                                                         metadata.title,
654                                                         metadata.artist,
655                                                         metadata.album,
656                                                         metadata.genre,
657                                                         metadata.total_tracks,
658                                                         metadata.number,
659                                                         metadata.duration);
660                         _bt_send_event(BT_AVRCP_CONTROL_EVENT,
661                                 BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED, param);
662
663                         g_free((char *)metadata.title);
664                         g_free((char *)metadata.artist);
665                         g_free((char *)metadata.album);
666                         g_free((char *)metadata.genre);
667                 } else {
668                         BT_DBG("Property not handled");
669                 }
670         }
671
672         BT_DBG("-");
673 }