Fix the build error in capi-network-bluetooth
[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 DBUS_TYPE_VARIANT_AS_STRING
642                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &property_dict);
643
644         __bt_media_append_dict_entry(&property_dict,
645                 "LoopStatus",
646                 DBUS_TYPE_STRING,
647                 &loopstatus_settings[player_settings.loopstatus].property);
648
649         __bt_media_append_dict_entry(&property_dict,
650                 "Shuffle",
651                 DBUS_TYPE_BOOLEAN,
652                 &player_settings.shuffle);
653
654         __bt_media_append_dict_entry(&property_dict,
655                 "PlaybackStatus",
656                 DBUS_TYPE_STRING,
657                 &playback_status[player_settings.playbackstatus].property);
658
659         __bt_media_append_dict_entry(&property_dict,
660                 "Position",
661                 DBUS_TYPE_INT64, &player_settings.position);
662
663         __bt_media_append_metadata_dict_entry(&property_dict,
664                 "xesam:title",
665                 DBUS_TYPE_STRING, &metadata.title, 0);
666
667         metadata.artists = g_malloc0(sizeof(char *));
668         metadata.artists[0] = "";
669
670         __bt_media_append_metadata_dict_entry(&property_dict,
671                 "xesam:artist",
672                 DBUS_TYPE_ARRAY, &metadata.artist, 1);
673
674         __bt_media_append_metadata_dict_entry(&property_dict,
675                 "xesam:album",
676                 DBUS_TYPE_STRING, &metadata.album, 0);
677
678         metadata.genres = g_malloc0(sizeof(char *));
679         metadata.genres[0] = "";
680
681         __bt_media_append_metadata_dict_entry(&property_dict,
682                 "xesam:genre",
683                 DBUS_TYPE_ARRAY, &metadata.genre, 1);
684
685         __bt_media_append_metadata_dict_entry(&property_dict,
686                 "mpris:length",
687                 DBUS_TYPE_INT64, &metadata.duration, 0);
688
689         __bt_media_append_metadata_dict_entry(&property_dict,
690                 "xesam:trackNumber",
691                 DBUS_TYPE_INT32, &metadata.tracknumber, 0);
692
693         dbus_message_iter_close_container(&iter, &property_dict);
694
695         dbus_error_init(&err);
696         reply = dbus_connection_send_with_reply_and_block(conn,
697                                         msg, -1, &err);
698         dbus_message_unref(msg);
699
700         if (!reply) {
701                 BT_DBG("Error in registering the Music Player \n");
702
703                 if (dbus_error_is_set(&err)) {
704                         BT_ERR("%s", err.message);
705                         dbus_error_free(&err);
706                         return BLUETOOTH_ERROR_INTERNAL;
707                 }
708
709                 if (bt_media_obj) {
710                         dbus_g_connection_unregister_g_object(gconn,
711                                                 G_OBJECT(bt_media_obj));
712                         g_object_unref(bt_media_obj);
713                         bt_media_obj = NULL;
714                 }
715         }
716
717         if (reply)
718                 dbus_message_unref(reply);
719
720         g_free(metadata.artist);
721         g_free(metadata.genre);
722
723         return BLUETOOTH_ERROR_NONE;
724 }
725
726 int _bt_unregister_media_player(void)
727 {
728         DBusMessage *msg;
729         DBusMessage *reply;
730         DBusError err;
731         char *object;
732         char *adapter_path;
733         DBusConnection *conn;
734
735         conn = g_bt_dbus_conn;
736         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
737
738         adapter_path = _bt_get_adapter_path();
739         retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
740
741         msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path,
742                                 BT_MEDIA_INTERFACE, "UnregisterPlayer");
743
744         g_free(adapter_path);
745
746         retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
747
748         object = g_strdup(BT_MEDIA_OBJECT_PATH);
749
750         dbus_message_append_args(msg,
751                                 DBUS_TYPE_OBJECT_PATH, &object,
752                                 DBUS_TYPE_INVALID);
753
754         g_free(object);
755
756         dbus_error_init(&err);
757         reply = dbus_connection_send_with_reply_and_block(conn,
758                                 msg, -1, &err);
759         dbus_message_unref(msg);
760
761         if (!reply) {
762                 BT_ERR("Error in unregistering the Music Player \n");
763
764                 if (dbus_error_is_set(&err)) {
765                         BT_DBG("%s", err.message);
766                         dbus_error_free(&err);
767                         return BLUETOOTH_ERROR_INTERNAL;
768                 }
769         } else {
770                 dbus_message_unref(reply);
771         }
772
773         if (bt_media_obj) {
774                 dbus_g_connection_unregister_g_object(_bt_get_system_gconn(),
775                                                 G_OBJECT(bt_media_obj));
776                 g_object_unref(bt_media_obj);
777                 bt_media_obj = NULL;
778         }
779
780         bt_dbus_unregister_object_path(conn, BT_MEDIA_OBJECT_PATH);
781         g_bt_dbus_conn = NULL;
782
783         return BLUETOOTH_ERROR_NONE;
784 }
785
786 int _bt_avrcp_set_interal_property(int type, media_player_settings_t *properties)
787 {
788         DBusConnection *conn;
789         int value;
790         media_metadata_attributes_t meta_data;
791         dbus_bool_t shuffle;
792
793         conn = g_bt_dbus_conn;
794         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
795
796         switch (type) {
797         case LOOPSTATUS:
798                 value = properties->loopstatus;
799                 if (!__bt_media_emit_property_changed(
800                         conn,
801                         BT_MEDIA_OBJECT_PATH,
802                         BT_MEDIA_PLAYER_INTERFACE,
803                         "LoopStatus",
804                         DBUS_TYPE_STRING,
805                         &loopstatus_settings[value].property)) {
806                         BT_DBG("Error sending the PropertyChanged signal \n");
807                         return BLUETOOTH_ERROR_INTERNAL;
808                 }
809                 break;
810         case SHUFFLE:
811                 value = properties->shuffle;
812                 if (g_strcmp0(repeat_settings[value].property, "alltracks") == 0)
813                         shuffle = 1;
814                 else
815                         shuffle = 0;
816
817                 if (!__bt_media_emit_property_changed(
818                         conn,
819                         BT_MEDIA_OBJECT_PATH,
820                         BT_MEDIA_PLAYER_INTERFACE,
821                         "Shuffle",
822                         DBUS_TYPE_BOOLEAN,
823                         &shuffle)) {
824                         BT_DBG("Error sending the PropertyChanged signal \n");
825                         return BLUETOOTH_ERROR_INTERNAL;
826                 }
827                 break;
828         case PLAYBACKSTATUS:
829                 value = properties->playbackstatus;
830                 if (!__bt_media_emit_property_changed(
831                         conn,
832                         BT_MEDIA_OBJECT_PATH,
833                         BT_MEDIA_PLAYER_INTERFACE,
834                         "PlaybackStatus",
835                         DBUS_TYPE_STRING,
836                         &playback_status[value].property)) {
837                         BT_DBG("Error sending the PropertyChanged signal \n");
838                         return BLUETOOTH_ERROR_INTERNAL;
839                 }
840                 break;
841         case POSITION:
842                 value = properties->position;
843                 if (!__bt_media_emit_property_changed(
844                         conn,
845                         BT_MEDIA_OBJECT_PATH,
846                         BT_MEDIA_PLAYER_INTERFACE,
847                         "Position",
848                         DBUS_TYPE_UINT32,
849                         &value)) {
850                         BT_DBG("Error sending the PropertyChanged signal \n");
851                         return BLUETOOTH_ERROR_INTERNAL;
852                 }
853                 break;
854         case METADATA:
855                 meta_data = properties->metadata;
856                 if (!__bt_media_emit_property_changed(
857                         conn,
858                         BT_MEDIA_OBJECT_PATH,
859                         BT_MEDIA_PLAYER_INTERFACE,
860                         "Metadata",
861                         DBUS_TYPE_ARRAY,
862                         &meta_data)) {
863                         BT_DBG("Error sending the PropertyChanged signal \n");
864                         return BLUETOOTH_ERROR_INTERNAL;
865                 }
866                 break;
867         default:
868                 BT_DBG("Invalid Type\n");
869                 return BLUETOOTH_ERROR_INTERNAL;
870         }
871
872         return BLUETOOTH_ERROR_NONE;
873 }
874
875 int _bt_avrcp_set_properties(media_player_settings_t *properties)
876 {
877         if (_bt_avrcp_set_interal_property(LOOPSTATUS,
878                         properties) != BLUETOOTH_ERROR_NONE) {
879                 return BLUETOOTH_ERROR_INTERNAL;
880         }
881
882         if (_bt_avrcp_set_interal_property(SHUFFLE,
883                         properties) != BLUETOOTH_ERROR_NONE) {
884                 return BLUETOOTH_ERROR_INTERNAL;
885         }
886
887         if (_bt_avrcp_set_interal_property(PLAYBACKSTATUS,
888                         properties) != BLUETOOTH_ERROR_NONE) {
889                 return BLUETOOTH_ERROR_INTERNAL;
890         }
891
892         if (_bt_avrcp_set_interal_property(POSITION,
893                         properties) != BLUETOOTH_ERROR_NONE) {
894                 return BLUETOOTH_ERROR_INTERNAL;
895         }
896
897         if (_bt_avrcp_set_interal_property(METADATA,
898                         properties) != BLUETOOTH_ERROR_NONE) {
899                 return BLUETOOTH_ERROR_INTERNAL;
900         }
901
902         return BLUETOOTH_ERROR_NONE;
903 }
904
905 int _bt_avrcp_set_property(int type, unsigned int value)
906 {
907         media_player_settings_t properties;
908
909         BT_DBG("+");
910
911         switch (type) {
912         case LOOPSTATUS:
913                 properties.loopstatus = value;
914                 break;
915         case SHUFFLE:
916                 properties.shuffle = value;
917                 break;
918         case PLAYBACKSTATUS:
919                 properties.playbackstatus = value;
920                 break;
921         case POSITION:
922                 properties.position = value;
923                 break;
924         default:
925                 BT_DBG("Invalid Type\n");
926                 return BLUETOOTH_ERROR_INTERNAL;
927         }
928
929         _bt_avrcp_set_interal_property(type, &properties);
930
931         BT_DBG("-");
932
933         return BLUETOOTH_ERROR_NONE;
934 }