Merge "Fix build for x64 arch: Remove harcoded path" into tizen
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-avrcp.c
1 /*
2  * bluetooth-frwk
3  *
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <dbus/dbus-glib-lowlevel.h>
21 #include <dbus/dbus-glib.h>
22 #include <dbus/dbus.h>
23 #include <glib.h>
24 #include <dlog.h>
25 #include <string.h>
26 #ifndef LIBNOTIFY_SUPPORT
27 #include <syspopup_caller.h>
28 #endif
29
30 #include "bluetooth-api.h"
31 #include "bt-internal-types.h"
32
33 #include "bt-service-common.h"
34 #include "bt-service-avrcp.h"
35 #include "bt-service-event.h"
36 #include "bt-service-util.h"
37
38 struct player_settinngs_t {
39         int key;
40         const char *property;
41 };
42
43 static struct player_settinngs_t loopstatus_settings[] = {
44         { REPEAT_INVALID, "" },
45         { REPEAT_MODE_OFF, "None" },
46         { REPEAT_SINGLE_TRACK, "Track" },
47         { REPEAT_ALL_TRACK, "Playlist" },
48         { REPEAT_INVALID, "" }
49 };
50
51 static struct player_settinngs_t playback_status[] = {
52         { STATUS_STOPPED, "Stopped" },
53         { STATUS_PLAYING, "Playing" },
54         { STATUS_PAUSED, "Paused" },
55         { STATUS_INVALID, "" }
56 };
57
58 static struct player_settinngs_t repeat_settings[] = {
59         { REPEAT_INVALID, "" },
60         { REPEAT_MODE_OFF, "off" },
61         { REPEAT_SINGLE_TRACK, "singletrack" },
62         { REPEAT_ALL_TRACK, "alltracks" },
63         { REPEAT_INVALID, "" }
64 };
65
66 typedef struct {
67         GObject parent;
68 } BtMediaAgent;
69
70 typedef struct {
71         GObjectClass parent;
72 } BtMediaAgentClass;
73
74 GType bt_media_agent_get_type(void);
75
76 DBusConnection *g_bt_dbus_conn = NULL;
77
78 #define BT_MEDIA_TYPE_AGENT (bt_media_agent_get_type())
79 #define BT_MEDIA_GET_AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), BT_MEDIA_TYPE_AGENT, BtMediaAgent))
80 #define BT_MEDIA_IS_AGENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), BT_MEDIA_TYPE_AGENT))
81 #define BT_MEDIA_AGENT_CLASS(class) (G_TYPE_CHECK_CLASS_CAST((class), BT_MEDIA_TYPE_AGENT, \
82                                                                                 BtMediaAgentClass))
83 #define BT_MEDIA_GET_AGENT_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), BT_MEDIA_TYPE_AGENT, \
84                                                                                 BtMediaAgentClass))
85 #define BT_MEDIA_IS_AGENT_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE((class), BT_MEDIA_TYPE_AGENT))
86
87 G_DEFINE_TYPE(BtMediaAgent, bt_media_agent, G_TYPE_OBJECT)
88
89 static gboolean bt_media_agent_set_property(BtMediaAgent *agent,
90                                                 const char *property, GValue *value,
91                                                 DBusGMethodInvocation *context);
92
93 static BtMediaAgent *bt_media_obj = NULL;
94
95 #include "bt-media-agent-method.h"
96
97 typedef enum {
98         BT_MEDIA_AGENT_ERROR_INVALID_PARAM,
99         BT_MEDIA_AGENT_ERROR_NOT_AVAILABLE,
100         BT_MEDIA_AGENT_ERROR_BUSY,
101 } BtMediaAgentError;
102
103 #define BT_MEDIA_AGENT_ERROR (bt_media_agent_error_quark())
104
105 static GQuark bt_media_agent_error_quark(void)
106 {
107         static GQuark quark = 0;
108         if (!quark)
109                 quark = g_quark_from_static_string("agent");
110
111         return quark;
112 }
113
114 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
115
116 static GError *bt_media_agent_error(BtMediaAgentError error, const char *err_msg)
117 {
118         return g_error_new(BT_MEDIA_AGENT_ERROR, error, err_msg, NULL);
119 }
120
121 static void bt_media_agent_init(BtMediaAgent *agent)
122 {
123         BT_DBG("agent %p\n", agent);
124 }
125
126 static void bt_media_agent_finalize(GObject *agent)
127 {
128         BT_DBG("Free agent %p\n", agent);
129
130         G_OBJECT_CLASS(bt_media_agent_parent_class)->finalize(agent);
131 }
132
133 static void bt_media_agent_class_init(BtMediaAgentClass *klass)
134 {
135         GObjectClass *object_class = (GObjectClass *) klass;
136
137         BT_DBG("class %p\n", klass);
138
139         object_class->finalize = bt_media_agent_finalize;
140
141         dbus_g_object_type_install_info(BT_MEDIA_TYPE_AGENT,
142                                         &dbus_glib_bt_media_agent_object_info);
143 }
144
145 static BtMediaAgent *__bt_media_agent_new(void)
146 {
147         BtMediaAgent *agent;
148
149         agent = BT_MEDIA_GET_AGENT(g_object_new(BT_MEDIA_TYPE_AGENT, NULL));
150
151         BT_DBG("agent %p\n", agent);
152
153         return agent;
154 }
155
156 static gboolean bt_media_agent_set_property(BtMediaAgent *agent,
157                                                 const char *property, GValue *val,
158                                                 DBusGMethodInvocation *context)
159 {
160         GError *error;
161         const gchar *value;
162         unsigned int status;
163
164         BT_DBG("property %s\n", property);
165
166         dbus_g_method_return(context);
167         return TRUE;
168
169 }
170
171 static const char *loopstatus_to_repeat(const char *value)
172 {
173         if (strcasecmp(value, "None") == 0)
174                 return "off";
175         else if (strcasecmp(value, "Track") == 0)
176                 return "singletrack";
177         else if (strcasecmp(value, "Playlist") == 0)
178                 return "alltracks";
179
180         return NULL;
181 }
182
183 void set_shuffle(DBusMessageIter *iter)
184 {
185         dbus_bool_t shuffle;
186         const char *value;
187         unsigned int status;
188
189         if (dbus_message_iter_get_arg_type(iter) !=
190                                         DBUS_TYPE_BOOLEAN) {
191                 BT_DBG("Invalid arguments in method call");
192                 return;
193         }
194
195         dbus_message_iter_get_basic(iter, &shuffle);
196         value = shuffle ? "alltracks" : "off";
197
198         if (g_strcmp0(value, "alltracks") == 0)
199                 status = SHUFFLE_ALL_TRACK;
200         else if (g_strcmp0(value, "off") == 0)
201                 status = SHUFFLE_MODE_OFF;
202         else
203                 status = SHUFFLE_INVALID;
204
205         _bt_send_event(BT_AVRCP_EVENT,
206                         BLUETOOTH_EVENT_AVRCP_SETTING_SHUFFLE_STATUS,
207                         DBUS_TYPE_UINT32, &status,
208                         DBUS_TYPE_INVALID);
209 }
210
211 void set_loopstatus(DBusMessageIter *iter)
212 {
213         const char *value;
214         unsigned int status;
215
216         if (dbus_message_iter_get_arg_type(iter) !=
217                                         DBUS_TYPE_STRING) {
218                 BT_DBG("Invalid arguments in method call");
219                 return;
220         }
221
222         dbus_message_iter_get_basic(iter, &value);
223
224         value = loopstatus_to_repeat(value);
225
226         if (g_strcmp0(value, "singletrack") == 0)
227                 status = REPEAT_SINGLE_TRACK;
228         else if (g_strcmp0(value, "alltracks") == 0)
229                 status = REPEAT_ALL_TRACK;
230         else if (g_strcmp0(value, "off") == 0)
231                 status = REPEAT_MODE_OFF;
232         else
233                 status = REPEAT_INVALID;
234
235         _bt_send_event(BT_AVRCP_EVENT,
236                         BLUETOOTH_EVENT_AVRCP_SETTING_REPEAT_STATUS,
237                         DBUS_TYPE_UINT32, &status,
238                         DBUS_TYPE_INVALID);
239 }
240
241 static DBusHandlerResult bt_properties_message(DBusConnection *connection,
242                                                 DBusMessage *message)
243 {
244         DBusMessageIter iter, sub;
245         const char *name, *interface;
246         DBusMessage *reply;
247
248         if (!dbus_message_iter_init(message, &iter)){
249                 reply = dbus_message_new_error(message,
250                         DBUS_ERROR_INVALID_ARGS, "No arguments given");
251                 goto done;
252         }
253
254         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING){
255                 reply = dbus_message_new_error(message,
256                         DBUS_ERROR_INVALID_ARGS, "Invalid argument type");
257                 goto done;
258         }
259
260         dbus_message_iter_get_basic(&iter, &interface);
261         dbus_message_iter_next(&iter);
262
263         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING){
264                 reply = dbus_message_new_error(message,
265                         DBUS_ERROR_INVALID_ARGS, "Invalid argument type");
266                 goto done;
267         }
268
269         dbus_message_iter_get_basic(&iter, &name);
270         dbus_message_iter_next(&iter);
271
272         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT){
273                 reply = dbus_message_new_error(message,
274                         DBUS_ERROR_INVALID_ARGS, "Invalid argument type");
275                 goto done;
276         }
277
278         dbus_message_iter_recurse(&iter, &sub);
279
280         if (g_strcmp0(interface, BT_MEDIA_PLAYER_INTERFACE) == 0){
281                 if (g_strcmp0(name, "LoopStatus") == 0)
282                         set_loopstatus(&sub);
283                 else if (g_strcmp0(name, "Shuffle") == 0)
284                         set_shuffle(&sub);
285         }
286
287         reply = dbus_message_new_method_return(message);
288         if (reply == NULL)
289                 return DBUS_HANDLER_RESULT_NEED_MEMORY;
290
291 done:
292         dbus_connection_send(connection, reply, NULL);
293         dbus_message_unref(reply);
294
295         return DBUS_HANDLER_RESULT_HANDLED;
296 }
297
298 static DBusHandlerResult bt_dbus_message(DBusConnection *connection,
299                                 DBusMessage *message, void *user_data)
300 {
301         const char *interface;
302
303         interface = dbus_message_get_interface(message);
304
305         if (interface == NULL)
306                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
307
308         if (g_strcmp0(interface, BT_PROPERTIES_INTERFACE) == 0)
309                 return bt_properties_message(connection, message);
310
311         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
312 }
313
314 static DBusObjectPathVTable bt_object_table = {
315         .message_function       = bt_dbus_message,
316 };
317
318 gboolean bt_dbus_register_object_path(DBusConnection *connection,
319                                                 const char *path)
320 {
321         if (!dbus_connection_register_object_path(connection, path,
322                                 &bt_object_table, NULL))
323                 return FALSE;
324
325         return TRUE;
326 }
327
328 void bt_dbus_unregister_object_path(DBusConnection *connection,
329                                                 const char *path)
330 {
331         dbus_connection_unregister_object_path(connection, path);
332 }
333
334 static inline void bt_dbus_queue_dispatch(DBusConnection *conn,
335                                         DBusDispatchStatus status)
336 {
337         if (status == DBUS_DISPATCH_DATA_REMAINS){
338                 dbus_connection_ref(conn);
339                  while (dbus_connection_dispatch(conn)
340                                 == DBUS_DISPATCH_DATA_REMAINS)
341                                 ;
342
343                 dbus_connection_unref(conn);
344         }
345 }
346
347 static void bt_dbus_dispatch_status(DBusConnection *conn,
348                                 DBusDispatchStatus status, void *data)
349 {
350         if (!dbus_connection_get_is_connected(conn))
351                 return;
352
353         bt_dbus_queue_dispatch(conn, status);
354 }
355
356 DBusConnection *bt_dbus_setup_private(DBusBusType type, DBusError *error)
357 {
358         DBusConnection *conn;
359         DBusDispatchStatus status;
360
361         conn = dbus_bus_get_private(type, error);
362
363         if (conn == NULL)
364                 return NULL;
365
366         dbus_connection_set_dispatch_status_function(conn,
367                                 bt_dbus_dispatch_status, NULL, NULL);
368
369         status = dbus_connection_get_dispatch_status(conn);
370         bt_dbus_queue_dispatch(conn, status);
371
372         return conn;
373 }
374
375 static void __bt_media_append_variant(DBusMessageIter *iter,
376                         int type, void *value)
377 {
378         char sig[2] = { type, '\0'};
379         DBusMessageIter value_iter;
380
381         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig,
382                                                         &value_iter);
383
384         dbus_message_iter_append_basic(&value_iter, type, value);
385
386         dbus_message_iter_close_container(iter, &value_iter);
387 }
388
389 static void __bt_media_append_dict_entry(DBusMessageIter *iter,
390                         const char *key, int type, void *property)
391 {
392         DBusMessageIter dict_entry;
393         const char *str_ptr;
394
395         if (type == DBUS_TYPE_STRING) {
396                 str_ptr = *((const char **)property);
397                 ret_if(str_ptr == NULL);
398         }
399
400         dbus_message_iter_open_container(iter,
401                                         DBUS_TYPE_DICT_ENTRY,
402                                         NULL, &dict_entry);
403
404         dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &key);
405
406         __bt_media_append_variant(&dict_entry, type, property);
407
408         dbus_message_iter_close_container(iter, &dict_entry);
409 }
410
411 static void __bt_media_append_array_variant(DBusMessageIter *iter, int type,
412                         void *val, int n_elements)
413 {
414         DBusMessageIter variant, array;
415         char type_sig[2] = { type, '\0' };
416         char array_sig[3] = { DBUS_TYPE_ARRAY, type, '\0' };
417
418         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
419                                                 array_sig, &variant);
420
421         dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
422                                                 type_sig, &array);
423
424         if (dbus_type_is_fixed(type) == TRUE) {
425                 dbus_message_iter_append_fixed_array(&array, type, val,
426                                                         n_elements);
427         } else if (type == DBUS_TYPE_STRING ||
428                                 type == DBUS_TYPE_OBJECT_PATH) {
429                 const char ***str_array = val;
430                 int i;
431
432                 for (i = 0; i < n_elements; i++)
433                         dbus_message_iter_append_basic(&array, type,
434                                                 &((*str_array)[i]));
435         }
436
437         dbus_message_iter_close_container(&variant, &array);
438         dbus_message_iter_close_container(iter, &variant);
439 }
440
441 static void __bt_media_append_array(DBusMessageIter *dict, const char *key,
442                         int type, void *val, int n_elements)
443 {
444         DBusMessageIter entry;
445
446         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
447                                                         NULL, &entry);
448
449         BT_DBG("key = %s", key);
450         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
451
452         __bt_media_append_array_variant(&entry, type, val, n_elements);
453
454         dbus_message_iter_close_container(dict, &entry);
455 }
456
457 static void __bt_media_append_metadata_variant(DBusMessageIter *iter,
458                 const char *key, int type, void *property, int count)
459 {
460         DBusMessageIter value, metadata;
461
462         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
463                                                                 &value);
464
465         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
466                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
467                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
468                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata);
469
470         if (type == DBUS_TYPE_ARRAY)
471                 __bt_media_append_array(&metadata, key,
472                         DBUS_TYPE_STRING, property, count);
473         else
474         __bt_media_append_dict_entry(&metadata, key, type, property);
475
476         dbus_message_iter_close_container(&value, &metadata);
477         dbus_message_iter_close_container(iter, &value);
478 }
479
480 static void __bt_media_append_metadata_dict_entry(DBusMessageIter *iter,
481                         const char *key, int type, void *property, int count)
482 {
483         DBusMessageIter dict_entry;
484         const char *str_ptr;
485         char * metadata = "Metadata";
486
487         if (type == DBUS_TYPE_STRING) {
488                 str_ptr = *((const char **)property);
489                 ret_if(str_ptr == NULL);
490         }
491
492         dbus_message_iter_open_container(iter,
493                                         DBUS_TYPE_DICT_ENTRY,
494                                         NULL, &dict_entry);
495
496         dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &metadata);
497
498         __bt_media_append_metadata_variant(&dict_entry, key, type, property, count);
499
500         dbus_message_iter_close_container(iter, &dict_entry);
501 }
502
503 static void __bt_metadata_append_property_changed(DBusMessageIter *property_dict,
504                                         media_metadata_attributes_t *metadata)
505 {
506         if(property_dict == NULL || metadata == NULL)
507                 return
508
509         __bt_media_append_metadata_dict_entry(property_dict,
510                 "xesam:title",
511                 DBUS_TYPE_STRING, &metadata->title, 0);
512
513         __bt_media_append_array(property_dict,
514                 "xesam:artist",
515                 DBUS_TYPE_ARRAY,&metadata->artist, 1);
516
517         __bt_media_append_metadata_dict_entry(property_dict,
518                 "xesam:album",
519                 DBUS_TYPE_STRING, &metadata->album, 0);
520
521         __bt_media_append_array(property_dict,
522                 "xesam:genre",
523                 DBUS_TYPE_ARRAY,&metadata->genre, 1);
524
525         __bt_media_append_metadata_dict_entry(property_dict,
526                 "mpris:length",
527                 DBUS_TYPE_INT64, &metadata->duration, 0);
528
529         __bt_media_append_metadata_dict_entry(property_dict,
530                 "xesam:trackNumber",
531                 DBUS_TYPE_INT32, &metadata->tracknumber, 0);
532 }
533
534 static gboolean __bt_media_emit_property_changed(
535                                 DBusConnection *connection,
536                                 const char *path,
537                                 const char *interface,
538                                 const char *name,
539                                 int type,
540                                 void *property)
541 {
542         DBusMessage *sig;
543         DBusMessageIter entry, dict;
544         gboolean ret;
545
546         BT_DBG("+");
547         sig = dbus_message_new_signal(path, DBUS_INTERFACE_PROPERTIES,
548                                                 "PropertiesChanged");
549         retv_if(sig == NULL, FALSE);
550
551         dbus_message_iter_init_append(sig, &entry);
552         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &interface);
553
554         dbus_message_iter_open_container(&entry, DBUS_TYPE_ARRAY,
555                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
556                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
557                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
558
559         if (g_strcmp0(name, "Metadata") == 0)
560                 __bt_metadata_append_property_changed(&dict,
561                         (media_metadata_attributes_t *)property);
562         else
563                 __bt_media_append_dict_entry(&dict,
564                                         name, type, property);
565
566         dbus_message_iter_close_container(&entry, &dict);
567
568         ret = dbus_connection_send(connection, sig, NULL);
569         dbus_message_unref(sig);
570
571         BT_DBG("-");
572
573         return ret;
574 }
575
576 int _bt_register_media_player(void)
577 {
578         DBusMessage *msg;
579         DBusMessage *reply;
580         DBusMessageIter iter;
581         DBusMessageIter property_dict;
582         DBusError err;
583         char *object;
584         char *adapter_path;
585         DBusConnection *conn;
586         DBusGConnection *gconn;
587
588         media_player_settings_t player_settings = {0,};
589         media_metadata_attributes_t metadata = {0,};
590
591         player_settings.loopstatus  = REPEAT_MODE_OFF;
592         player_settings.playbackstatus = STATUS_STOPPED;
593         player_settings.shuffle = FALSE;
594         player_settings.position = 0;
595
596         metadata.title = "\0";
597         metadata.album = "\0";
598         metadata.tracknumber = 0;
599         metadata.duration = 0;
600
601         gconn = _bt_get_system_gconn();
602         retv_if(gconn  == NULL, BLUETOOTH_ERROR_INTERNAL);
603
604         conn = bt_dbus_setup_private(DBUS_BUS_SYSTEM, NULL);
605         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
606         g_bt_dbus_conn = conn;
607
608         if (!bt_media_obj) {
609                 bt_media_obj = __bt_media_agent_new();
610
611                 retv_if(bt_media_obj == NULL, BLUETOOTH_ERROR_INTERNAL);
612
613                 dbus_g_connection_register_g_object(gconn,
614                                                         BT_MEDIA_OBJECT_PATH,
615                                                         G_OBJECT(bt_media_obj));
616         }
617
618         if (!bt_dbus_register_object_path(conn, BT_MEDIA_OBJECT_PATH)){
619                 BT_DBG("Could not register interface %s",
620                                         MPRIS_PLAYER_INTERFACE);
621         }
622
623         adapter_path = _bt_get_adapter_path();
624         retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
625
626         msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path,
627                                         BT_MEDIA_INTERFACE, "RegisterPlayer");
628
629         g_free(adapter_path);
630
631         retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
632
633         object = g_strdup(BT_MEDIA_OBJECT_PATH);
634
635         dbus_message_iter_init_append(msg, &iter);
636         dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &object);
637         g_free(object);
638
639         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
640                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
641                         DBUS_TYPE_STRING_AS_STRING
642                         DBUS_TYPE_VARIANT_AS_STRING
643                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &property_dict);
644
645         __bt_media_append_dict_entry(&property_dict,
646                 "LoopStatus",
647                 DBUS_TYPE_STRING,
648                 &loopstatus_settings[player_settings.loopstatus].property);
649
650         __bt_media_append_dict_entry(&property_dict,
651                 "Shuffle",
652                 DBUS_TYPE_BOOLEAN,
653                 &player_settings.shuffle);
654
655         __bt_media_append_dict_entry(&property_dict,
656                 "PlaybackStatus",
657                 DBUS_TYPE_STRING,
658                 &playback_status[player_settings.playbackstatus].property);
659
660         __bt_media_append_dict_entry(&property_dict,
661                 "Position",
662                 DBUS_TYPE_INT64, &player_settings.position);
663
664         __bt_media_append_metadata_dict_entry(&property_dict,
665                 "xesam:title",
666                 DBUS_TYPE_STRING, &metadata.title, 0);
667
668         metadata.artists = g_malloc0(sizeof(char *));
669         metadata.artists[0] = "";
670
671         __bt_media_append_metadata_dict_entry(&property_dict,
672                 "xesam:artist",
673                 DBUS_TYPE_ARRAY, &metadata.artists, 1);
674
675         __bt_media_append_metadata_dict_entry(&property_dict,
676                 "xesam:album",
677                 DBUS_TYPE_STRING, &metadata.album, 0);
678
679         metadata.genres = g_malloc0(sizeof(char *));
680         metadata.genres[0] = "";
681
682         __bt_media_append_metadata_dict_entry(&property_dict,
683                 "xesam:genre",
684                 DBUS_TYPE_ARRAY, &metadata.genres, 1);
685
686         __bt_media_append_metadata_dict_entry(&property_dict,
687                 "mpris:length",
688                 DBUS_TYPE_INT64, &metadata.duration, 0);
689
690         __bt_media_append_metadata_dict_entry(&property_dict,
691                 "xesam:trackNumber",
692                 DBUS_TYPE_INT32, &metadata.tracknumber, 0);
693
694         dbus_message_iter_close_container(&iter, &property_dict);
695
696         dbus_error_init(&err);
697         reply = dbus_connection_send_with_reply_and_block(conn,
698                                         msg, -1, &err);
699         dbus_message_unref(msg);
700
701         if (!reply) {
702                 BT_DBG("Error in registering the Music Player \n");
703
704                 if (dbus_error_is_set(&err)) {
705                         BT_ERR("%s", err.message);
706                         dbus_error_free(&err);
707                         return BLUETOOTH_ERROR_INTERNAL;
708                 }
709
710                 if (bt_media_obj) {
711                         dbus_g_connection_unregister_g_object(gconn,
712                                                 G_OBJECT(bt_media_obj));
713                         g_object_unref(bt_media_obj);
714                         bt_media_obj = NULL;
715                 }
716         }
717
718         if (reply)
719                 dbus_message_unref(reply);
720
721         g_free(metadata.artist);
722         g_free(metadata.genre);
723
724         return BLUETOOTH_ERROR_NONE;
725 }
726
727 int _bt_unregister_media_player(void)
728 {
729         DBusMessage *msg;
730         DBusMessage *reply;
731         DBusError err;
732         char *object;
733         char *adapter_path;
734         DBusConnection *conn;
735
736         conn = g_bt_dbus_conn;
737         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
738
739         adapter_path = _bt_get_adapter_path();
740         retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
741
742         msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path,
743                                 BT_MEDIA_INTERFACE, "UnregisterPlayer");
744
745         g_free(adapter_path);
746
747         retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
748
749         object = g_strdup(BT_MEDIA_OBJECT_PATH);
750
751         dbus_message_append_args(msg,
752                                 DBUS_TYPE_OBJECT_PATH, &object,
753                                 DBUS_TYPE_INVALID);
754
755         g_free(object);
756
757         dbus_error_init(&err);
758         reply = dbus_connection_send_with_reply_and_block(conn,
759                                 msg, -1, &err);
760         dbus_message_unref(msg);
761
762         if (!reply) {
763                 BT_ERR("Error in unregistering the Music Player \n");
764
765                 if (dbus_error_is_set(&err)) {
766                         BT_DBG("%s", err.message);
767                         dbus_error_free(&err);
768                         return BLUETOOTH_ERROR_INTERNAL;
769                 }
770         } else {
771                 dbus_message_unref(reply);
772         }
773
774         if (bt_media_obj) {
775                 dbus_g_connection_unregister_g_object(_bt_get_system_gconn(),
776                                                 G_OBJECT(bt_media_obj));
777                 g_object_unref(bt_media_obj);
778                 bt_media_obj = NULL;
779         }
780
781         bt_dbus_unregister_object_path(conn, BT_MEDIA_OBJECT_PATH);
782         g_bt_dbus_conn = NULL;
783
784         return BLUETOOTH_ERROR_NONE;
785 }
786
787 int _bt_avrcp_set_interal_property(int type, media_player_settings_t *properties)
788 {
789         DBusConnection *conn;
790         int value;
791         media_metadata_attributes_t meta_data;
792         dbus_bool_t shuffle;
793
794         conn = g_bt_dbus_conn;
795         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
796
797         switch (type) {
798         case LOOPSTATUS:
799                 value = properties->loopstatus;
800                 if (!__bt_media_emit_property_changed(
801                         conn,
802                         BT_MEDIA_OBJECT_PATH,
803                         BT_MEDIA_PLAYER_INTERFACE,
804                         "LoopStatus",
805                         DBUS_TYPE_STRING,
806                         &loopstatus_settings[value].property)) {
807                         BT_DBG("Error sending the PropertyChanged signal \n");
808                         return BLUETOOTH_ERROR_INTERNAL;
809                 }
810                 break;
811         case SHUFFLE:
812                 value = properties->shuffle;
813                 if (g_strcmp0(repeat_settings[value].property, "alltracks") == 0)
814                         shuffle = 1;
815                 else
816                         shuffle = 0;
817
818                 if (!__bt_media_emit_property_changed(
819                         conn,
820                         BT_MEDIA_OBJECT_PATH,
821                         BT_MEDIA_PLAYER_INTERFACE,
822                         "Shuffle",
823                         DBUS_TYPE_BOOLEAN,
824                         &shuffle)) {
825                         BT_DBG("Error sending the PropertyChanged signal \n");
826                         return BLUETOOTH_ERROR_INTERNAL;
827                 }
828                 break;
829         case PLAYBACKSTATUS:
830                 value = properties->playbackstatus;
831                 if (!__bt_media_emit_property_changed(
832                         conn,
833                         BT_MEDIA_OBJECT_PATH,
834                         BT_MEDIA_PLAYER_INTERFACE,
835                         "PlaybackStatus",
836                         DBUS_TYPE_STRING,
837                         &playback_status[value].property)) {
838                         BT_DBG("Error sending the PropertyChanged signal \n");
839                         return BLUETOOTH_ERROR_INTERNAL;
840                 }
841                 break;
842         case POSITION:
843                 value = properties->position;
844                 if (!__bt_media_emit_property_changed(
845                         conn,
846                         BT_MEDIA_OBJECT_PATH,
847                         BT_MEDIA_PLAYER_INTERFACE,
848                         "Position",
849                         DBUS_TYPE_UINT32,
850                         &value)) {
851                         BT_DBG("Error sending the PropertyChanged signal \n");
852                         return BLUETOOTH_ERROR_INTERNAL;
853                 }
854                 break;
855         case METADATA:
856                 meta_data = properties->metadata;
857                 if (!__bt_media_emit_property_changed(
858                         conn,
859                         BT_MEDIA_OBJECT_PATH,
860                         BT_MEDIA_PLAYER_INTERFACE,
861                         "Metadata",
862                         DBUS_TYPE_ARRAY,
863                         &meta_data)) {
864                         BT_DBG("Error sending the PropertyChanged signal \n");
865                         return BLUETOOTH_ERROR_INTERNAL;
866                 }
867                 break;
868         default:
869                 BT_DBG("Invalid Type\n");
870                 return BLUETOOTH_ERROR_INTERNAL;
871         }
872
873         return BLUETOOTH_ERROR_NONE;
874 }
875
876 int _bt_avrcp_set_properties(media_player_settings_t *properties)
877 {
878         if (_bt_avrcp_set_interal_property(LOOPSTATUS,
879                         properties) != BLUETOOTH_ERROR_NONE) {
880                 return BLUETOOTH_ERROR_INTERNAL;
881         }
882
883         if (_bt_avrcp_set_interal_property(SHUFFLE,
884                         properties) != BLUETOOTH_ERROR_NONE) {
885                 return BLUETOOTH_ERROR_INTERNAL;
886         }
887
888         if (_bt_avrcp_set_interal_property(PLAYBACKSTATUS,
889                         properties) != BLUETOOTH_ERROR_NONE) {
890                 return BLUETOOTH_ERROR_INTERNAL;
891         }
892
893         if (_bt_avrcp_set_interal_property(POSITION,
894                         properties) != BLUETOOTH_ERROR_NONE) {
895                 return BLUETOOTH_ERROR_INTERNAL;
896         }
897
898         if (_bt_avrcp_set_interal_property(METADATA,
899                         properties) != BLUETOOTH_ERROR_NONE) {
900                 return BLUETOOTH_ERROR_INTERNAL;
901         }
902
903         return BLUETOOTH_ERROR_NONE;
904 }
905
906 int _bt_avrcp_set_property(int type, unsigned int value)
907 {
908         media_player_settings_t properties;
909
910         BT_DBG("+");
911
912         switch (type) {
913         case LOOPSTATUS:
914                 properties.loopstatus = value;
915                 break;
916         case SHUFFLE:
917                 properties.shuffle = value;
918                 break;
919         case PLAYBACKSTATUS:
920                 properties.playbackstatus = value;
921                 break;
922         case POSITION:
923                 properties.position = value;
924                 break;
925         default:
926                 BT_DBG("Invalid Type\n");
927                 return BLUETOOTH_ERROR_INTERNAL;
928         }
929
930         _bt_avrcp_set_interal_property(type, &properties);
931
932         BT_DBG("-");
933
934         return BLUETOOTH_ERROR_NONE;
935 }