Rollback changes to submit TIZEN:COMMON project
[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 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_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         BT_DBG("property %s\n", property);
161
162         dbus_g_method_return(context);
163         return TRUE;
164 }
165
166 static const char *loopstatus_to_repeat(const char *value)
167 {
168         if (strcasecmp(value, "None") == 0)
169                 return "off";
170         else if (strcasecmp(value, "Track") == 0)
171                 return "singletrack";
172         else if (strcasecmp(value, "Playlist") == 0)
173                 return "alltracks";
174
175         return NULL;
176 }
177
178 void set_shuffle(DBusMessageIter *iter)
179 {
180         dbus_bool_t shuffle;
181         const char *value;
182         unsigned int status;
183
184         if (dbus_message_iter_get_arg_type(iter) !=
185                                         DBUS_TYPE_BOOLEAN) {
186                 BT_DBG("Invalid arguments in method call");
187                 return;
188         }
189
190         dbus_message_iter_get_basic(iter, &shuffle);
191         value = shuffle ? "alltracks" : "off";
192
193         if (g_strcmp0(value, "alltracks") == 0)
194                 status = SHUFFLE_ALL_TRACK;
195         else if (g_strcmp0(value, "off") == 0)
196                 status = SHUFFLE_MODE_OFF;
197         else
198                 status = SHUFFLE_INVALID;
199
200         _bt_send_event(BT_AVRCP_EVENT,
201                         BLUETOOTH_EVENT_AVRCP_SETTING_SHUFFLE_STATUS,
202                         DBUS_TYPE_UINT32, &status,
203                         DBUS_TYPE_INVALID);
204 }
205
206 void set_loopstatus(DBusMessageIter *iter)
207 {
208         const char *value;
209         unsigned int status;
210
211         if (dbus_message_iter_get_arg_type(iter) !=
212                                         DBUS_TYPE_STRING) {
213                 BT_DBG("Invalid arguments in method call");
214                 return;
215         }
216
217         dbus_message_iter_get_basic(iter, &value);
218
219         value = loopstatus_to_repeat(value);
220
221         if (g_strcmp0(value, "singletrack") == 0)
222                 status = REPEAT_SINGLE_TRACK;
223         else if (g_strcmp0(value, "alltracks") == 0)
224                 status = REPEAT_ALL_TRACK;
225         else if (g_strcmp0(value, "off") == 0)
226                 status = REPEAT_MODE_OFF;
227         else
228                 status = REPEAT_INVALID;
229
230         _bt_send_event(BT_AVRCP_EVENT,
231                         BLUETOOTH_EVENT_AVRCP_SETTING_REPEAT_STATUS,
232                         DBUS_TYPE_UINT32, &status,
233                         DBUS_TYPE_INVALID);
234 }
235
236 static DBusHandlerResult bt_properties_message(DBusConnection *connection,
237                                                 DBusMessage *message)
238 {
239         DBusMessageIter iter, sub;
240         const char *name, *interface;
241         DBusMessage *reply;
242
243         if (!dbus_message_iter_init(message, &iter)){
244                 reply = dbus_message_new_error(message,
245                         DBUS_ERROR_INVALID_ARGS, "No arguments given");
246                 goto done;
247         }
248
249         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING){
250                 reply = dbus_message_new_error(message,
251                         DBUS_ERROR_INVALID_ARGS, "Invalid argument type");
252                 goto done;
253         }
254
255         dbus_message_iter_get_basic(&iter, &interface);
256         dbus_message_iter_next(&iter);
257
258         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING){
259                 reply = dbus_message_new_error(message,
260                         DBUS_ERROR_INVALID_ARGS, "Invalid argument type");
261                 goto done;
262         }
263
264         dbus_message_iter_get_basic(&iter, &name);
265         dbus_message_iter_next(&iter);
266
267         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT){
268                 reply = dbus_message_new_error(message,
269                         DBUS_ERROR_INVALID_ARGS, "Invalid argument type");
270                 goto done;
271         }
272
273         dbus_message_iter_recurse(&iter, &sub);
274
275         if (g_strcmp0(interface, BT_MEDIA_PLAYER_INTERFACE) == 0){
276                 if (g_strcmp0(name, "LoopStatus") == 0)
277                         set_loopstatus(&sub);
278                 else if (g_strcmp0(name, "Shuffle") == 0)
279                         set_shuffle(&sub);
280         }
281
282         reply = dbus_message_new_method_return(message);
283         if (reply == NULL)
284                 return DBUS_HANDLER_RESULT_NEED_MEMORY;
285
286 done:
287         dbus_connection_send(connection, reply, NULL);
288         dbus_message_unref(reply);
289
290         return DBUS_HANDLER_RESULT_HANDLED;
291 }
292
293 static DBusHandlerResult bt_dbus_message(DBusConnection *connection,
294                                 DBusMessage *message, void *user_data)
295 {
296         const char *interface;
297
298         interface = dbus_message_get_interface(message);
299
300         if (interface == NULL)
301                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
302
303         if (g_strcmp0(interface, BT_PROPERTIES_INTERFACE) == 0)
304                 return bt_properties_message(connection, message);
305
306         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
307 }
308
309 static DBusObjectPathVTable bt_object_table = {
310         .message_function       = bt_dbus_message,
311 };
312
313 gboolean bt_dbus_register_object_path(DBusConnection *connection,
314                                                 const char *path)
315 {
316         if (!dbus_connection_register_object_path(connection, path,
317                                 &bt_object_table, NULL))
318                 return FALSE;
319
320         return TRUE;
321 }
322
323 void bt_dbus_unregister_object_path(DBusConnection *connection,
324                                                 const char *path)
325 {
326         dbus_connection_unregister_object_path(connection, path);
327 }
328
329 static inline void bt_dbus_queue_dispatch(DBusConnection *conn,
330                                         DBusDispatchStatus status)
331 {
332         if (status == DBUS_DISPATCH_DATA_REMAINS){
333                 dbus_connection_ref(conn);
334                  while (dbus_connection_dispatch(conn)
335                                 == DBUS_DISPATCH_DATA_REMAINS)
336                                 ;
337
338                 dbus_connection_unref(conn);
339         }
340 }
341
342 static void bt_dbus_dispatch_status(DBusConnection *conn,
343                                 DBusDispatchStatus status, void *data)
344 {
345         if (!dbus_connection_get_is_connected(conn))
346                 return;
347
348         bt_dbus_queue_dispatch(conn, status);
349 }
350
351 DBusConnection *bt_dbus_setup_private(DBusBusType type, DBusError *error)
352 {
353         DBusConnection *conn;
354         DBusDispatchStatus status;
355
356         conn = dbus_bus_get_private(type, error);
357
358         if (conn == NULL)
359                 return NULL;
360
361         dbus_connection_set_dispatch_status_function(conn,
362                                 bt_dbus_dispatch_status, NULL, NULL);
363
364         status = dbus_connection_get_dispatch_status(conn);
365         bt_dbus_queue_dispatch(conn, status);
366
367         return conn;
368 }
369
370 static void __bt_media_append_variant(DBusMessageIter *iter,
371                         int type, void *value)
372 {
373         char sig[2] = { type, '\0'};
374         DBusMessageIter value_iter;
375
376         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig,
377                                                         &value_iter);
378
379         dbus_message_iter_append_basic(&value_iter, type, value);
380
381         dbus_message_iter_close_container(iter, &value_iter);
382 }
383
384 static void __bt_media_append_dict_entry(DBusMessageIter *iter,
385                         const char *key, int type, void *property)
386 {
387         DBusMessageIter dict_entry;
388         const char *str_ptr;
389
390         if (type == DBUS_TYPE_STRING) {
391                 str_ptr = *((const char **)property);
392                 ret_if(str_ptr == NULL);
393         }
394
395         dbus_message_iter_open_container(iter,
396                                         DBUS_TYPE_DICT_ENTRY,
397                                         NULL, &dict_entry);
398
399         dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &key);
400
401         __bt_media_append_variant(&dict_entry, type, property);
402
403         dbus_message_iter_close_container(iter, &dict_entry);
404 }
405
406 static void __bt_media_append_array_variant(DBusMessageIter *iter, int type,
407                         void *val, int n_elements)
408 {
409         DBusMessageIter variant, array;
410         char type_sig[2] = { type, '\0' };
411         char array_sig[3] = { DBUS_TYPE_ARRAY, type, '\0' };
412
413         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
414                                                 array_sig, &variant);
415
416         dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
417                                                 type_sig, &array);
418
419         if (dbus_type_is_fixed(type) == TRUE) {
420                 dbus_message_iter_append_fixed_array(&array, type, val,
421                                                         n_elements);
422         } else if (type == DBUS_TYPE_STRING ||
423                                 type == DBUS_TYPE_OBJECT_PATH) {
424                 const char ***str_array = val;
425                 int i;
426
427                 for (i = 0; i < n_elements; i++)
428                         dbus_message_iter_append_basic(&array, type,
429                                                 &((*str_array)[i]));
430         }
431
432         dbus_message_iter_close_container(&variant, &array);
433         dbus_message_iter_close_container(iter, &variant);
434 }
435
436 static void __bt_media_append_array(DBusMessageIter *dict, const char *key,
437                         int type, void *val, int n_elements)
438 {
439         DBusMessageIter entry;
440
441         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
442                                                         NULL, &entry);
443
444         BT_DBG("key = %s", key);
445         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
446
447         __bt_media_append_array_variant(&entry, type, val, n_elements);
448
449         dbus_message_iter_close_container(dict, &entry);
450 }
451
452 static void __bt_media_append_metadata_variant(DBusMessageIter *iter,
453                 const char *key, int type, void *property, int count)
454 {
455         DBusMessageIter value, metadata;
456
457         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
458                                                                 &value);
459
460         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
461                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
462                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
463                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata);
464
465         if (type == DBUS_TYPE_ARRAY)
466                 __bt_media_append_array(&metadata, key,
467                         DBUS_TYPE_STRING, property, count);
468         else
469         __bt_media_append_dict_entry(&metadata, key, type, property);
470
471         dbus_message_iter_close_container(&value, &metadata);
472         dbus_message_iter_close_container(iter, &value);
473 }
474
475 static void __bt_media_append_metadata_dict_entry(DBusMessageIter *iter,
476                         const char *key, int type, void *property, int count)
477 {
478         DBusMessageIter dict_entry;
479         const char *str_ptr;
480         char * metadata = "Metadata";
481
482         if (type == DBUS_TYPE_STRING) {
483                 str_ptr = *((const char **)property);
484                 ret_if(str_ptr == NULL);
485         }
486
487         dbus_message_iter_open_container(iter,
488                                         DBUS_TYPE_DICT_ENTRY,
489                                         NULL, &dict_entry);
490
491         dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &metadata);
492
493         __bt_media_append_metadata_variant(&dict_entry, key, type, property, count);
494
495         dbus_message_iter_close_container(iter, &dict_entry);
496 }
497
498 static void __bt_metadata_append_property_changed(DBusMessageIter *property_dict,
499                                         media_metadata_attributes_t *metadata)
500 {
501         if(property_dict == NULL || metadata == NULL)
502                 return
503
504         __bt_media_append_metadata_dict_entry(property_dict,
505                 "xesam:title",
506                 DBUS_TYPE_STRING, &metadata->title, 0);
507
508         __bt_media_append_array(property_dict,
509                 "xesam:artist",
510                 DBUS_TYPE_ARRAY,&metadata->artist, 1);
511
512         __bt_media_append_metadata_dict_entry(property_dict,
513                 "xesam:album",
514                 DBUS_TYPE_STRING, &metadata->album, 0);
515
516         __bt_media_append_array(property_dict,
517                 "xesam:genre",
518                 DBUS_TYPE_ARRAY,&metadata->genre, 1);
519
520         __bt_media_append_metadata_dict_entry(property_dict,
521                 "mpris:length",
522                 DBUS_TYPE_INT64, &metadata->duration, 0);
523
524         __bt_media_append_metadata_dict_entry(property_dict,
525                 "xesam:trackNumber",
526                 DBUS_TYPE_INT32, &metadata->tracknumber, 0);
527 }
528
529 static gboolean __bt_media_emit_property_changed(
530                                 DBusConnection *connection,
531                                 const char *path,
532                                 const char *interface,
533                                 const char *name,
534                                 int type,
535                                 void *property)
536 {
537         DBusMessage *sig;
538         DBusMessageIter entry, dict;
539         gboolean ret;
540
541         BT_DBG("+");
542         sig = dbus_message_new_signal(path, DBUS_INTERFACE_PROPERTIES,
543                                                 "PropertiesChanged");
544         retv_if(sig == NULL, FALSE);
545
546         dbus_message_iter_init_append(sig, &entry);
547         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &interface);
548
549         dbus_message_iter_open_container(&entry, DBUS_TYPE_ARRAY,
550                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
551                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
552                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
553
554         if (g_strcmp0(name, "Metadata") == 0)
555                 __bt_metadata_append_property_changed(&dict,
556                         (media_metadata_attributes_t *)property);
557         else
558                 __bt_media_append_dict_entry(&dict,
559                                         name, type, property);
560
561         dbus_message_iter_close_container(&entry, &dict);
562
563         ret = dbus_connection_send(connection, sig, NULL);
564         dbus_message_unref(sig);
565
566         BT_DBG("-");
567
568         return ret;
569 }
570
571 int _bt_register_media_player(void)
572 {
573         DBusMessage *msg;
574         DBusMessage *reply;
575         DBusMessageIter iter;
576         DBusMessageIter property_dict;
577         DBusError err;
578         char *object;
579         char *adapter_path;
580         DBusConnection *conn;
581         DBusGConnection *gconn;
582
583         media_player_settings_t player_settings = {0,};
584         media_metadata_attributes_t metadata = {0,};
585
586         player_settings.loopstatus  = REPEAT_MODE_OFF;
587         player_settings.playbackstatus = STATUS_STOPPED;
588         player_settings.shuffle = FALSE;
589         player_settings.position = 0;
590
591         metadata.title = "\0";
592         metadata.album = "\0";
593         metadata.tracknumber = 0;
594         metadata.duration = 0;
595
596         gconn = _bt_get_system_gconn();
597         retv_if(gconn  == NULL, BLUETOOTH_ERROR_INTERNAL);
598
599         conn = bt_dbus_setup_private(DBUS_BUS_SYSTEM, NULL);
600         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
601         g_bt_dbus_conn = conn;
602
603         if (!bt_media_obj) {
604                 bt_media_obj = __bt_media_agent_new();
605
606                 retv_if(bt_media_obj == NULL, BLUETOOTH_ERROR_INTERNAL);
607
608                 dbus_g_connection_register_g_object(gconn,
609                                                         BT_MEDIA_OBJECT_PATH,
610                                                         G_OBJECT(bt_media_obj));
611         }
612
613         if (!bt_dbus_register_object_path(conn, BT_MEDIA_OBJECT_PATH)){
614                 BT_DBG("Could not register interface %s",
615                                         MPRIS_PLAYER_INTERFACE);
616         }
617
618         adapter_path = _bt_get_adapter_path();
619         retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
620
621         msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path,
622                                         BT_MEDIA_INTERFACE, "RegisterPlayer");
623
624         g_free(adapter_path);
625
626         retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
627
628         object = g_strdup(BT_MEDIA_OBJECT_PATH);
629
630         dbus_message_iter_init_append(msg, &iter);
631         dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &object);
632         g_free(object);
633
634         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
635                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
636                         DBUS_TYPE_STRING_AS_STRING
637                         DBUS_TYPE_VARIANT_AS_STRING
638                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &property_dict);
639
640         __bt_media_append_dict_entry(&property_dict,
641                 "LoopStatus",
642                 DBUS_TYPE_STRING,
643                 &loopstatus_settings[player_settings.loopstatus].property);
644
645         __bt_media_append_dict_entry(&property_dict,
646                 "Shuffle",
647                 DBUS_TYPE_BOOLEAN,
648                 &player_settings.shuffle);
649
650         __bt_media_append_dict_entry(&property_dict,
651                 "PlaybackStatus",
652                 DBUS_TYPE_STRING,
653                 &playback_status[player_settings.playbackstatus].property);
654
655         __bt_media_append_dict_entry(&property_dict,
656                 "Position",
657                 DBUS_TYPE_INT64, &player_settings.position);
658
659         __bt_media_append_metadata_dict_entry(&property_dict,
660                 "xesam:title",
661                 DBUS_TYPE_STRING, &metadata.title, 0);
662
663         metadata.artists = g_malloc0(sizeof(char *));
664         metadata.artists[0] = "";
665
666         __bt_media_append_metadata_dict_entry(&property_dict,
667                 "xesam:artist",
668                 DBUS_TYPE_ARRAY, &metadata.artists, 1);
669
670         __bt_media_append_metadata_dict_entry(&property_dict,
671                 "xesam:album",
672                 DBUS_TYPE_STRING, &metadata.album, 0);
673
674         metadata.genres = g_malloc0(sizeof(char *));
675         metadata.genres[0] = "";
676
677         __bt_media_append_metadata_dict_entry(&property_dict,
678                 "xesam:genre",
679                 DBUS_TYPE_ARRAY, &metadata.genres, 1);
680
681         __bt_media_append_metadata_dict_entry(&property_dict,
682                 "mpris:length",
683                 DBUS_TYPE_INT64, &metadata.duration, 0);
684
685         __bt_media_append_metadata_dict_entry(&property_dict,
686                 "xesam:trackNumber",
687                 DBUS_TYPE_INT32, &metadata.tracknumber, 0);
688
689         dbus_message_iter_close_container(&iter, &property_dict);
690
691         dbus_error_init(&err);
692         reply = dbus_connection_send_with_reply_and_block(conn,
693                                         msg, -1, &err);
694         dbus_message_unref(msg);
695
696         if (!reply) {
697                 BT_DBG("Error in registering the Music Player \n");
698
699                 if (dbus_error_is_set(&err)) {
700                         BT_ERR("%s", err.message);
701                         dbus_error_free(&err);
702                         return BLUETOOTH_ERROR_INTERNAL;
703                 }
704
705                 if (bt_media_obj) {
706                         dbus_g_connection_unregister_g_object(gconn,
707                                                 G_OBJECT(bt_media_obj));
708                         g_object_unref(bt_media_obj);
709                         bt_media_obj = NULL;
710                 }
711         }
712
713         if (reply)
714                 dbus_message_unref(reply);
715
716         g_free(metadata.artist);
717         g_free(metadata.genre);
718
719         return BLUETOOTH_ERROR_NONE;
720 }
721
722 int _bt_unregister_media_player(void)
723 {
724         DBusMessage *msg;
725         DBusMessage *reply;
726         DBusError err;
727         char *object;
728         char *adapter_path;
729         DBusConnection *conn;
730
731         conn = g_bt_dbus_conn;
732         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
733
734         adapter_path = _bt_get_adapter_path();
735         retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
736
737         msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path,
738                                 BT_MEDIA_INTERFACE, "UnregisterPlayer");
739
740         g_free(adapter_path);
741
742         retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
743
744         object = g_strdup(BT_MEDIA_OBJECT_PATH);
745
746         dbus_message_append_args(msg,
747                                 DBUS_TYPE_OBJECT_PATH, &object,
748                                 DBUS_TYPE_INVALID);
749
750         g_free(object);
751
752         dbus_error_init(&err);
753         reply = dbus_connection_send_with_reply_and_block(conn,
754                                 msg, -1, &err);
755         dbus_message_unref(msg);
756
757         if (!reply) {
758                 BT_ERR("Error in unregistering the Music Player \n");
759
760                 if (dbus_error_is_set(&err)) {
761                         BT_DBG("%s", err.message);
762                         dbus_error_free(&err);
763                         return BLUETOOTH_ERROR_INTERNAL;
764                 }
765         } else {
766                 dbus_message_unref(reply);
767         }
768
769         if (bt_media_obj) {
770                 dbus_g_connection_unregister_g_object(_bt_get_system_gconn(),
771                                                 G_OBJECT(bt_media_obj));
772                 g_object_unref(bt_media_obj);
773                 bt_media_obj = NULL;
774         }
775
776         bt_dbus_unregister_object_path(conn, BT_MEDIA_OBJECT_PATH);
777         g_bt_dbus_conn = NULL;
778
779         return BLUETOOTH_ERROR_NONE;
780 }
781
782 int _bt_avrcp_set_interal_property(int type, media_player_settings_t *properties)
783 {
784         DBusConnection *conn;
785         int value;
786         media_metadata_attributes_t meta_data;
787         dbus_bool_t shuffle;
788
789         conn = g_bt_dbus_conn;
790         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
791
792         switch (type) {
793         case LOOPSTATUS:
794                 value = properties->loopstatus;
795                 if (!__bt_media_emit_property_changed(
796                         conn,
797                         BT_MEDIA_OBJECT_PATH,
798                         BT_MEDIA_PLAYER_INTERFACE,
799                         "LoopStatus",
800                         DBUS_TYPE_STRING,
801                         &loopstatus_settings[value].property)) {
802                         BT_DBG("Error sending the PropertyChanged signal \n");
803                         return BLUETOOTH_ERROR_INTERNAL;
804                 }
805                 break;
806         case SHUFFLE:
807                 value = properties->shuffle;
808                 if (g_strcmp0(repeat_settings[value].property, "alltracks") == 0)
809                         shuffle = 1;
810                 else
811                         shuffle = 0;
812
813                 if (!__bt_media_emit_property_changed(
814                         conn,
815                         BT_MEDIA_OBJECT_PATH,
816                         BT_MEDIA_PLAYER_INTERFACE,
817                         "Shuffle",
818                         DBUS_TYPE_BOOLEAN,
819                         &shuffle)) {
820                         BT_DBG("Error sending the PropertyChanged signal \n");
821                         return BLUETOOTH_ERROR_INTERNAL;
822                 }
823                 break;
824         case PLAYBACKSTATUS:
825                 value = properties->playbackstatus;
826                 if (!__bt_media_emit_property_changed(
827                         conn,
828                         BT_MEDIA_OBJECT_PATH,
829                         BT_MEDIA_PLAYER_INTERFACE,
830                         "PlaybackStatus",
831                         DBUS_TYPE_STRING,
832                         &playback_status[value].property)) {
833                         BT_DBG("Error sending the PropertyChanged signal \n");
834                         return BLUETOOTH_ERROR_INTERNAL;
835                 }
836                 break;
837         case POSITION:
838                 value = properties->position;
839                 if (!__bt_media_emit_property_changed(
840                         conn,
841                         BT_MEDIA_OBJECT_PATH,
842                         BT_MEDIA_PLAYER_INTERFACE,
843                         "Position",
844                         DBUS_TYPE_UINT32,
845                         &value)) {
846                         BT_DBG("Error sending the PropertyChanged signal \n");
847                         return BLUETOOTH_ERROR_INTERNAL;
848                 }
849                 break;
850         case METADATA:
851                 meta_data = properties->metadata;
852                 if (!__bt_media_emit_property_changed(
853                         conn,
854                         BT_MEDIA_OBJECT_PATH,
855                         BT_MEDIA_PLAYER_INTERFACE,
856                         "Metadata",
857                         DBUS_TYPE_ARRAY,
858                         &meta_data)) {
859                         BT_DBG("Error sending the PropertyChanged signal \n");
860                         return BLUETOOTH_ERROR_INTERNAL;
861                 }
862                 break;
863         default:
864                 BT_DBG("Invalid Type\n");
865                 return BLUETOOTH_ERROR_INTERNAL;
866         }
867
868         return BLUETOOTH_ERROR_NONE;
869 }
870
871 int _bt_avrcp_set_properties(media_player_settings_t *properties)
872 {
873         if (_bt_avrcp_set_interal_property(LOOPSTATUS,
874                         properties) != BLUETOOTH_ERROR_NONE) {
875                 return BLUETOOTH_ERROR_INTERNAL;
876         }
877
878         if (_bt_avrcp_set_interal_property(SHUFFLE,
879                         properties) != BLUETOOTH_ERROR_NONE) {
880                 return BLUETOOTH_ERROR_INTERNAL;
881         }
882
883         if (_bt_avrcp_set_interal_property(PLAYBACKSTATUS,
884                         properties) != BLUETOOTH_ERROR_NONE) {
885                 return BLUETOOTH_ERROR_INTERNAL;
886         }
887
888         if (_bt_avrcp_set_interal_property(POSITION,
889                         properties) != BLUETOOTH_ERROR_NONE) {
890                 return BLUETOOTH_ERROR_INTERNAL;
891         }
892
893         if (_bt_avrcp_set_interal_property(METADATA,
894                         properties) != BLUETOOTH_ERROR_NONE) {
895                 return BLUETOOTH_ERROR_INTERNAL;
896         }
897
898         return BLUETOOTH_ERROR_NONE;
899 }
900
901 int _bt_avrcp_set_property(int type, unsigned int value)
902 {
903         media_player_settings_t properties;
904
905         BT_DBG("+");
906
907         switch (type) {
908         case LOOPSTATUS:
909                 properties.loopstatus = value;
910                 break;
911         case SHUFFLE:
912                 properties.shuffle = value;
913                 break;
914         case PLAYBACKSTATUS:
915                 properties.playbackstatus = value;
916                 break;
917         case POSITION:
918                 properties.position = value;
919                 break;
920         default:
921                 BT_DBG("Invalid Type\n");
922                 return BLUETOOTH_ERROR_INTERNAL;
923         }
924
925         _bt_avrcp_set_interal_property(type, &properties);
926
927         BT_DBG("-");
928
929         return BLUETOOTH_ERROR_NONE;
930 }