4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * Girishashok Joshi <girish.joshi@samsung.com>
8 * Chanyeol Park <chanyeol.park@samsung.com>
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
24 #include <dbus/dbus-glib-lowlevel.h>
25 #include <dbus/dbus-glib.h>
26 #include <dbus/dbus.h>
30 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
31 #include <syspopup_caller.h>
34 #include "bluetooth-api.h"
35 #include "bt-internal-types.h"
37 #include "bt-service-common.h"
38 #include "bt-service-avrcp.h"
39 #include "bt-service-event.h"
40 #include "bt-service-util.h"
41 #include "bt-service-audio.h"
43 struct player_settinngs_t {
48 static struct player_settinngs_t loopstatus_settings[] = {
49 { REPEAT_INVALID, "" },
50 { REPEAT_MODE_OFF, "None" },
51 { REPEAT_SINGLE_TRACK, "Track" },
52 { REPEAT_ALL_TRACK, "Playlist" },
53 { REPEAT_INVALID, "" }
57 static struct player_settinngs_t shuffle_settings[] = {
58 { SHUFFLE_INVALID, "" },
59 { SHUFFLE_MODE_OFF, "off" },
60 { SHUFFLE_ALL_TRACK, "alltracks" },
61 { SHUFFLE_GROUP, "group" },
62 { SHUFFLE_INVALID, "" }
65 static struct player_settinngs_t player_status[] = {
66 { STATUS_STOPPED, "stopped" },
67 { STATUS_PLAYING, "playing" },
68 { STATUS_PAUSED, "paused" },
69 { STATUS_FORWARD_SEEK, "forward-seek" },
70 { STATUS_REVERSE_SEEK, "reverse-seek" },
71 { STATUS_ERROR, "error" },
72 { STATUS_INVALID, "" }
75 static struct player_settinngs_t repeat_status[] = {
76 { REPEAT_INVALID, "" },
77 { REPEAT_MODE_OFF, "off" },
78 { REPEAT_SINGLE_TRACK, "singletrack" },
79 { REPEAT_ALL_TRACK, "alltracks" },
80 { REPEAT_GROUP, "group" },
81 { REPEAT_INVALID, "" }
84 static struct player_settinngs_t equalizer_status[] = {
85 { EQUALIZER_INVALID, "" },
86 { EQUALIZER_OFF, "off" },
87 { EQUALIZER_ON, "on" },
88 { EQUALIZER_INVALID, "" },
91 static struct player_settinngs_t scan_status[] = {
93 { SCAN_MODE_OFF, "off" },
94 { SCAN_ALL_TRACK, "alltracks" },
95 { SCAN_GROUP, "group" },
99 DBusConnection *g_bt_dbus_conn = NULL;
100 static char *avrcp_control_path = NULL;
102 static DBusHandlerResult _bt_avrcp_handle_set_property(DBusConnection *connection,
103 DBusMessage *message, void *user_data)
108 gboolean shuffle_status;
109 DBusMessageIter args;
110 const char *property = NULL;
111 const char *interface = NULL;
112 DBusMessage *reply = NULL;
113 DBusHandlerResult result = DBUS_HANDLER_RESULT_HANDLED;
114 DBusMessageIter entry;
118 dbus_message_iter_init(message, &args);
119 dbus_message_iter_get_basic(&args, &interface);
120 dbus_message_iter_next(&args);
122 if (g_strcmp0(interface, BT_MEDIA_PLAYER_INTERFACE) != 0) {
123 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
127 dbus_message_iter_get_basic(&args, &property);
128 dbus_message_iter_next(&args);
129 dbus_message_iter_recurse(&args, &entry);
130 type = dbus_message_iter_get_arg_type(&entry);
132 BT_DBG("property %s\n", property);
134 if (g_strcmp0(property, "Shuffle") == 0) {
135 if (type != DBUS_TYPE_BOOLEAN) {
137 reply = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
138 "Invalid arguments");
139 dbus_connection_send(connection, reply, NULL);
140 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
143 dbus_message_iter_get_basic(&entry, &shuffle_status);
144 BT_DBG("value %d\n", shuffle_status);
145 if (shuffle_status == TRUE)
146 status = SHUFFLE_ALL_TRACK;
148 status = SHUFFLE_MODE_OFF;
150 _bt_send_event(BT_AVRCP_EVENT,
151 BLUETOOTH_EVENT_AVRCP_SETTING_SHUFFLE_STATUS,
152 DBUS_TYPE_UINT32, &status,
155 } else if (g_strcmp0(property, "LoopStatus") == 0) {
156 if (type != DBUS_TYPE_STRING) {
158 reply = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
159 "Invalid arguments");
160 dbus_connection_send(connection, reply, NULL);
161 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
164 dbus_message_iter_get_basic(&entry, &value);
165 BT_DBG("value %s\n", value);
167 if (g_strcmp0(value, "Track") == 0)
168 status = REPEAT_SINGLE_TRACK;
169 else if (g_strcmp0(value, "Playlist") == 0)
170 status = REPEAT_ALL_TRACK;
171 else if (g_strcmp0(value, "None") == 0)
172 status = REPEAT_MODE_OFF;
174 status = REPEAT_INVALID;
176 _bt_send_event(BT_AVRCP_EVENT,
177 BLUETOOTH_EVENT_AVRCP_SETTING_REPEAT_STATUS,
178 DBUS_TYPE_UINT32, &status,
183 dbus_message_unref(reply);
188 static DBusHandlerResult _bt_avrcp_message_handle(DBusConnection *conn, DBusMessage *msg, void *user_data)
192 if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PROPERTIES, "Set"))
193 return _bt_avrcp_handle_set_property(conn, msg, user_data);
196 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
199 static DBusObjectPathVTable bt_object_table = {
200 .message_function = _bt_avrcp_message_handle,
203 gboolean bt_dbus_register_object_path(DBusConnection *connection,
206 if (!dbus_connection_register_object_path(connection, path,
207 &bt_object_table, NULL))
212 void bt_dbus_unregister_object_path(DBusConnection *connection,
215 dbus_connection_unregister_object_path(connection, path);
218 static void __bt_media_append_variant(DBusMessageIter *iter,
219 int type, void *value)
221 char sig[2] = { type, '\0'};
222 DBusMessageIter value_iter;
224 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig,
227 dbus_message_iter_append_basic(&value_iter, type, value);
229 dbus_message_iter_close_container(iter, &value_iter);
232 static void __bt_media_append_dict_entry(DBusMessageIter *iter,
233 const char *key, int type, void *property)
235 DBusMessageIter dict_entry;
238 if (type == DBUS_TYPE_STRING) {
239 str_ptr = *((const char **)property);
240 ret_if(str_ptr == NULL);
243 dbus_message_iter_open_container(iter,
244 DBUS_TYPE_DICT_ENTRY,
247 dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &key);
249 __bt_media_append_variant(&dict_entry, type, property);
251 dbus_message_iter_close_container(iter, &dict_entry);
254 static gboolean __bt_media_emit_property_changed(
255 DBusConnection *connection,
257 const char *interface,
263 DBusMessageIter entry, dict;
266 sig = dbus_message_new_signal(path, DBUS_INTERFACE_PROPERTIES,
267 "PropertiesChanged");
268 retv_if(sig == NULL, FALSE);
270 dbus_message_iter_init_append(sig, &entry);
271 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &interface);
272 dbus_message_iter_open_container(&entry, DBUS_TYPE_ARRAY,
273 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
274 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
275 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
277 __bt_media_append_dict_entry(&dict,
278 name, type, property);
280 dbus_message_iter_close_container(&entry, &dict);
282 ret = dbus_connection_send(connection, sig, NULL);
283 dbus_message_unref(sig);
288 void _bt_set_control_device_path(const char *path)
291 ret_if(path == NULL);
293 g_free(avrcp_control_path);
294 BT_DBG("control_path = %s", path);
295 avrcp_control_path = g_strdup(path);
298 void _bt_remove_control_device_path(const char *path)
300 ret_if(path == NULL);
302 if (avrcp_control_path &&
303 !g_strcmp0(avrcp_control_path, path)) {
304 BT_DBG("control_path = %s", path);
305 g_free(avrcp_control_path);
306 avrcp_control_path = NULL;
310 static char *__bt_get_control_device_path(void)
314 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
318 retv_if(avrcp_control_path != NULL, avrcp_control_path);
320 retv_if(!_bt_is_headset_type_connected(BT_AVRCP,
321 connected_address), NULL);
323 BT_DBG("device address = %s", connected_address);
325 adapter_path = _bt_get_device_object_path(connected_address);
326 retv_if(adapter_path == NULL, NULL);
328 control_path = g_strdup_printf(BT_MEDIA_CONTROL_PATH, adapter_path);
329 g_free(adapter_path);
331 avrcp_control_path = control_path;
332 BT_DBG("control_path = %s", control_path);
336 static int __bt_media_send_control_msg(const char *name)
341 DBusConnection *conn;
344 retv_if(name == NULL, BLUETOOTH_ERROR_INTERNAL);
346 conn = _bt_get_system_conn();
347 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
349 control_path = __bt_get_control_device_path();
350 retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
351 BT_DBG("control_path %s", control_path);
353 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, control_path,
354 BT_PLAYER_CONTROL_INTERFACE, name);
356 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
358 dbus_error_init(&err);
359 reply = dbus_connection_send_with_reply_and_block(conn,
361 dbus_message_unref(msg);
364 BT_ERR("Error in Sending Control Command");
366 if (dbus_error_is_set(&err)) {
367 BT_ERR("%s", err.message);
368 dbus_error_free(&err);
370 return BLUETOOTH_ERROR_INTERNAL;
373 dbus_message_unref(reply);
376 return BLUETOOTH_ERROR_NONE;
380 int _bt_register_media_player(void)
385 DBusMessageIter iter;
386 DBusMessageIter property_dict;
390 DBusConnection *conn;
391 DBusGConnection *gconn;
392 gboolean shuffle_status;
394 media_player_settings_t player_settings = {0,};
396 player_settings.repeat = REPEAT_MODE_OFF;
398 player_settings.shuffle = SHUFFLE_MODE_OFF;
399 player_settings.status = STATUS_STOPPED;
400 player_settings.position = 0;
403 gconn = _bt_get_system_gconn();
404 retv_if(gconn == NULL, BLUETOOTH_ERROR_INTERNAL);
406 conn = _bt_get_system_conn();
407 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
408 g_bt_dbus_conn = conn;
411 if (!bt_dbus_register_object_path(conn, BT_MEDIA_OBJECT_PATH)){
412 BT_DBG("Could not register interface %s",
413 BT_MEDIA_PLAYER_INTERFACE);
416 adapter_path = _bt_get_adapter_path();
417 retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
419 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path,
420 BT_MEDIA_INTERFACE, "RegisterPlayer");
422 g_free(adapter_path);
424 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
426 object = g_strdup(BT_MEDIA_OBJECT_PATH);
428 dbus_message_iter_init_append(msg, &iter);
429 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &object);
432 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
433 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
434 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
435 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &property_dict);
437 __bt_media_append_dict_entry(&property_dict,
440 &loopstatus_settings[player_settings.repeat].property);
442 if (player_settings.shuffle == SHUFFLE_MODE_OFF)
443 shuffle_status = FALSE;
445 shuffle_status = TRUE;
447 __bt_media_append_dict_entry(&property_dict,
452 __bt_media_append_dict_entry(&property_dict,
455 &player_status[player_settings.status].property);
458 __bt_media_append_dict_entry(&property_dict,
460 DBUS_TYPE_UINT32, &player_settings.position);
462 dbus_message_iter_close_container(&iter, &property_dict);
464 dbus_error_init(&err);
465 reply = dbus_connection_send_with_reply_and_block(conn,
467 dbus_message_unref(msg);
470 BT_ERR("Error in registering the Music Player \n");
472 if (dbus_error_is_set(&err)) {
473 BT_ERR("%s", err.message);
474 dbus_error_free(&err);
475 return BLUETOOTH_ERROR_INTERNAL;
480 dbus_message_unref(reply);
483 return BLUETOOTH_ERROR_NONE;
486 int _bt_unregister_media_player(void)
494 DBusConnection *conn;
496 conn = g_bt_dbus_conn;
497 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
499 adapter_path = _bt_get_adapter_path();
500 retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
502 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path,
503 BT_MEDIA_INTERFACE, "UnregisterPlayer");
506 g_free(adapter_path);
508 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
510 object = g_strdup(BT_MEDIA_OBJECT_PATH);
512 dbus_message_append_args(msg,
513 DBUS_TYPE_OBJECT_PATH, &object,
518 dbus_error_init(&err);
519 reply = dbus_connection_send_with_reply_and_block(conn,
521 dbus_message_unref(msg);
524 BT_ERR("Error in unregistering the Music Player \n");
526 if (dbus_error_is_set(&err)) {
527 BT_ERR("%s", err.message);
528 dbus_error_free(&err);
529 return BLUETOOTH_ERROR_INTERNAL;
532 dbus_message_unref(reply);
535 bt_dbus_unregister_object_path(conn, BT_MEDIA_OBJECT_PATH);
536 g_bt_dbus_conn = NULL;
539 return BLUETOOTH_ERROR_NONE;
542 static void __bt_media_append_metadata_entry(DBusMessageIter *metadata,
543 void *key_type, void *value, int type)
546 DBusMessageIter string_entry;
548 dbus_message_iter_open_container(metadata,
549 DBUS_TYPE_DICT_ENTRY,
550 NULL, &string_entry);
552 dbus_message_iter_append_basic(&string_entry, DBUS_TYPE_STRING, key_type);
554 __bt_media_append_variant(&string_entry, type, value);
556 dbus_message_iter_close_container(metadata, &string_entry);
560 static void __bt_media_append_metadata_array(DBusMessageIter *metadata,
561 void *key_type, void *value, int type)
564 DBusMessageIter string_entry, variant, array;
565 char array_sig[3] = { type, DBUS_TYPE_STRING, '\0' };
567 dbus_message_iter_open_container(metadata,
568 DBUS_TYPE_DICT_ENTRY,
569 NULL, &string_entry);
570 dbus_message_iter_append_basic(&string_entry, DBUS_TYPE_STRING, key_type);
572 dbus_message_iter_open_container(&string_entry, DBUS_TYPE_VARIANT,
573 array_sig, &variant);
575 dbus_message_iter_open_container(&variant, type,
576 DBUS_TYPE_STRING_AS_STRING, &array);
577 dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, value);
579 dbus_message_iter_close_container(&variant, &array);
580 dbus_message_iter_close_container(&string_entry, &variant);
581 dbus_message_iter_close_container(metadata, &string_entry);
585 int _bt_avrcp_set_track_info(media_metadata_attributes_t *meta_data)
589 DBusMessageIter iter;
590 DBusMessageIter property_dict, metadata_dict, metadata_variant, metadata;
591 DBusConnection *conn;
592 char *interface = BT_MEDIA_PLAYER_INTERFACE;
593 char * metadata_str = "Metadata";
594 const char *key_type;
596 retv_if(meta_data == NULL, BLUETOOTH_ERROR_INTERNAL);
598 conn = g_bt_dbus_conn;
599 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
601 sig = dbus_message_new_signal(BT_MEDIA_OBJECT_PATH, DBUS_INTERFACE_PROPERTIES,
602 "PropertiesChanged");
603 retv_if(sig == NULL, FALSE);
605 dbus_message_iter_init_append(sig, &iter);
606 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface);
608 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
609 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
610 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
611 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &property_dict);
613 dbus_message_iter_open_container(&property_dict,
614 DBUS_TYPE_DICT_ENTRY,
615 NULL, &metadata_dict);
617 dbus_message_iter_append_basic(&metadata_dict, DBUS_TYPE_STRING, &metadata_str);
619 dbus_message_iter_open_container(&metadata_dict, DBUS_TYPE_VARIANT, "a{sv}",
622 dbus_message_iter_open_container(&metadata_variant, DBUS_TYPE_ARRAY,
623 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
624 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
625 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata);
627 if (meta_data->title) {
628 key_type = "xesam:title";
629 __bt_media_append_metadata_entry(&metadata, &key_type,
630 &meta_data->title, DBUS_TYPE_STRING);
633 if (meta_data->artist) {
634 key_type = "xesam:artist";
635 __bt_media_append_metadata_array(&metadata, &key_type,
636 &meta_data->artist, DBUS_TYPE_ARRAY);
639 if (meta_data->album) {
640 key_type = "xesam:album";
641 __bt_media_append_metadata_entry(&metadata, &key_type,
642 &meta_data->album, DBUS_TYPE_STRING);
645 if (meta_data->genre) {
646 key_type = "xesam:genre";
647 __bt_media_append_metadata_array(&metadata, &key_type,
648 &meta_data->genre, DBUS_TYPE_ARRAY);
651 if (0 != meta_data->total_tracks) {
652 key_type = "xesam:totalTracks";
653 __bt_media_append_metadata_entry(&metadata, &key_type,
654 &meta_data->total_tracks, DBUS_TYPE_INT32);
657 if (0 != meta_data->number) {
658 key_type = "xesam:trackNumber";
659 __bt_media_append_metadata_entry(&metadata, &key_type,
660 &meta_data->number, DBUS_TYPE_INT32);
663 if (0 != meta_data->duration) {
664 key_type = "mpris:length";
665 __bt_media_append_metadata_entry(&metadata, &key_type,
666 &meta_data->duration, DBUS_TYPE_INT64);
669 dbus_message_iter_close_container(&metadata_variant, &metadata);
670 dbus_message_iter_close_container(&metadata_dict, &metadata_variant);
671 dbus_message_iter_close_container(&property_dict, &metadata_dict);
672 dbus_message_iter_close_container(&iter, &property_dict);
674 if (!dbus_connection_send(conn, sig, NULL))
675 BT_ERR("Unable to send TrackChanged signal\n");
677 dbus_message_unref(sig);
679 return BLUETOOTH_ERROR_NONE;
683 int _bt_avrcp_set_interal_property(int type, media_player_settings_t *properties)
686 DBusConnection *conn;
688 media_metadata_attributes_t meta_data;
691 conn = g_bt_dbus_conn;
692 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
696 value = properties->repeat;
697 if (!__bt_media_emit_property_changed(
699 BT_MEDIA_OBJECT_PATH,
700 BT_MEDIA_PLAYER_INTERFACE,
703 &loopstatus_settings[value].property)) {
704 BT_ERR("Error sending the PropertyChanged signal \n");
705 return BLUETOOTH_ERROR_INTERNAL;
709 value = properties->shuffle;
710 if (g_strcmp0(shuffle_settings[value].property, "off") == 0)
715 if (!__bt_media_emit_property_changed(
717 BT_MEDIA_OBJECT_PATH,
718 BT_MEDIA_PLAYER_INTERFACE,
722 BT_DBG("Error sending the PropertyChanged signal \n");
723 return BLUETOOTH_ERROR_INTERNAL;
727 value = properties->status;
728 if (!__bt_media_emit_property_changed(
730 BT_MEDIA_OBJECT_PATH,
731 BT_MEDIA_PLAYER_INTERFACE,
734 &player_status[value].property)) {
735 BT_DBG("Error sending the PropertyChanged signal \n");
736 return BLUETOOTH_ERROR_INTERNAL;
740 value = properties->position;
741 if (!__bt_media_emit_property_changed(
743 BT_MEDIA_OBJECT_PATH,
744 BT_MEDIA_PLAYER_INTERFACE,
748 BT_DBG("Error sending the PropertyChanged signal \n");
749 return BLUETOOTH_ERROR_INTERNAL;
753 meta_data = properties->metadata;
754 if (!__bt_media_emit_property_changed(
756 BT_MEDIA_OBJECT_PATH,
757 BT_MEDIA_PLAYER_INTERFACE,
761 BT_DBG("Error sending the PropertyChanged signal \n");
762 return BLUETOOTH_ERROR_INTERNAL;
766 BT_DBG("Invalid Type\n");
767 return BLUETOOTH_ERROR_INTERNAL;
770 return BLUETOOTH_ERROR_NONE;
773 int _bt_avrcp_set_properties(media_player_settings_t *properties)
777 if (_bt_avrcp_set_interal_property(REPEAT,
778 properties) != BLUETOOTH_ERROR_NONE) {
779 return BLUETOOTH_ERROR_INTERNAL;
781 if (_bt_avrcp_set_interal_property(SHUFFLE,
782 properties) != BLUETOOTH_ERROR_NONE) {
783 return BLUETOOTH_ERROR_INTERNAL;
786 if (_bt_avrcp_set_interal_property(STATUS,
787 properties) != BLUETOOTH_ERROR_NONE) {
788 return BLUETOOTH_ERROR_INTERNAL;
791 if (_bt_avrcp_set_interal_property(POSITION,
792 properties) != BLUETOOTH_ERROR_NONE) {
793 return BLUETOOTH_ERROR_INTERNAL;
796 if (_bt_avrcp_set_interal_property(METADATA,
797 properties) != BLUETOOTH_ERROR_NONE) {
798 return BLUETOOTH_ERROR_INTERNAL;
801 return BLUETOOTH_ERROR_NONE;
804 int _bt_avrcp_set_property(int type, unsigned int value)
807 media_player_settings_t properties;
811 properties.repeat = value;
814 properties.shuffle = value;
817 properties.status = value;
820 properties.position = value;
823 BT_DBG("Invalid Type\n");
824 return BLUETOOTH_ERROR_INTERNAL;
827 if (_bt_avrcp_set_interal_property(type,
828 &properties) != BLUETOOTH_ERROR_NONE)
829 return BLUETOOTH_ERROR_INTERNAL;
833 return BLUETOOTH_ERROR_NONE;
836 int _bt_avrcp_control_cmd(int type)
838 int ret = BLUETOOTH_ERROR_INTERNAL;
843 ret = __bt_media_send_control_msg("Play");
846 ret = __bt_media_send_control_msg("Pause");
849 ret = __bt_media_send_control_msg("Stop");
852 ret = __bt_media_send_control_msg("Next");
855 ret = __bt_media_send_control_msg("Previous");
858 ret = __bt_media_send_control_msg("FastForward");
861 ret = __bt_media_send_control_msg("Rewind");
864 BT_DBG("Invalid Type\n");
865 return BLUETOOTH_ERROR_INTERNAL;
871 DBusGProxy *__bt_get_control_properties_proxy(void)
875 DBusGConnection *conn;
877 control_path = __bt_get_control_device_path();
878 retv_if(control_path == NULL, NULL);
879 BT_DBG("control_path = %s", control_path);
881 conn = _bt_get_system_gconn();
882 retv_if(conn == NULL, NULL);
884 proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
885 control_path, BT_PROPERTIES_INTERFACE);
889 static int __bt_media_attr_to_event(const char *str)
891 if (!strcasecmp(str, "Equalizer"))
892 return BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS;
893 else if (!strcasecmp(str, "Repeat"))
894 return BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS;
895 else if (!strcasecmp(str, "Shuffle"))
896 return BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS;
897 else if (!strcasecmp(str, "Scan"))
898 return BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS;
899 else if (!strcasecmp(str, "Position"))
900 return BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS;
901 else if (!strcasecmp(str, "Track"))
902 return BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED;
903 else if (!strcasecmp(str, "Status"))
904 return BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED;
909 static int __bt_media_attr_to_type(const char *str)
911 if (!strcasecmp(str, "Equalizer"))
913 else if (!strcasecmp(str, "Repeat"))
915 else if (!strcasecmp(str, "Shuffle"))
917 else if (!strcasecmp(str, "Scan"))
919 else if (!strcasecmp(str, "Position"))
921 else if (!strcasecmp(str, "Track"))
923 else if (!strcasecmp(str, "Status"))
929 static const char *__bt_media_type_to_str(int type)
950 static int __bt_media_attrval_to_val(int type, const char *value)
956 if (!strcmp(value, "off"))
958 else if (!strcmp(value, "on"))
961 ret = EQUALIZER_INVALID;
965 if (!strcmp(value, "off"))
966 ret = REPEAT_MODE_OFF;
967 else if (!strcmp(value, "singletrack"))
968 ret = REPEAT_SINGLE_TRACK;
969 else if (!strcmp(value, "alltracks"))
970 ret = REPEAT_ALL_TRACK;
971 else if (!strcmp(value, "group"))
974 ret = REPEAT_INVALID;
978 if (!strcmp(value, "off"))
979 ret = SHUFFLE_MODE_OFF;
980 else if (!strcmp(value, "alltracks"))
981 ret = SHUFFLE_ALL_TRACK;
982 else if (!strcmp(value, "group"))
985 ret = SHUFFLE_INVALID;
989 if (!strcmp(value, "off"))
991 else if (!strcmp(value, "alltracks"))
992 ret = SCAN_ALL_TRACK;
993 else if (!strcmp(value, "group"))
1000 if (!strcmp(value, "stopped"))
1001 ret = STATUS_STOPPED;
1002 else if (!strcmp(value, "playing"))
1003 ret = STATUS_PLAYING;
1004 else if (!strcmp(value, "paused"))
1005 ret = STATUS_PAUSED;
1006 else if (!strcmp(value, "forward-seek"))
1007 ret = STATUS_FORWARD_SEEK;
1008 else if (!strcmp(value, "reverse-seek"))
1009 ret = STATUS_REVERSE_SEEK;
1010 else if (!strcmp(value, "error"))
1013 ret = STATUS_INVALID;
1018 int _bt_avrcp_control_get_property(int type, unsigned int *value)
1022 int ret = BLUETOOTH_ERROR_NONE;
1024 GValue attr_value = { 0 };
1026 BT_CHECK_PARAMETER(value, return);
1028 proxy = __bt_get_control_properties_proxy();
1029 retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
1031 if (!dbus_g_proxy_call(proxy, "Get", &err,
1032 G_TYPE_STRING, BT_PLAYER_CONTROL_INTERFACE,
1033 G_TYPE_STRING, __bt_media_type_to_str(type),
1035 G_TYPE_VALUE, &attr_value,
1038 BT_ERR("Getting property failed: [%s]\n", err->message);
1041 g_object_unref(proxy);
1042 return BLUETOOTH_ERROR_INTERNAL;
1044 g_object_unref(proxy);
1052 name = (char *)g_value_get_string(&attr_value);
1053 *value = __bt_media_attrval_to_val(type, name);
1054 BT_DBG("Type[%s] and Value[%s]", __bt_media_type_to_str(type), name);
1057 *value = g_value_get_uint(&attr_value);
1060 BT_DBG("Invalid Type\n");
1061 ret = BLUETOOTH_ERROR_INTERNAL;
1067 int _bt_avrcp_control_set_property(int type, unsigned int value)
1069 GValue attr_value = { 0 };
1071 GError *error = NULL;
1073 proxy = __bt_get_control_properties_proxy();
1075 retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
1076 g_value_init(&attr_value, G_TYPE_STRING);
1080 g_value_set_string(&attr_value, equalizer_status[value].property);
1081 BT_DBG("equalizer_status %s", equalizer_status[value].property);
1084 g_value_set_string(&attr_value, repeat_status[value].property);
1085 BT_DBG("repeat_status %s", repeat_status[value].property);
1088 g_value_set_string(&attr_value, shuffle_settings[value].property);
1089 BT_DBG("shuffle_settings %s", shuffle_settings[value].property);
1092 g_value_set_string(&attr_value, scan_status[value].property);
1093 BT_DBG("scan_status %s", scan_status[value].property);
1096 BT_ERR("Invalid property type: %d", type);
1097 return BLUETOOTH_ERROR_INTERNAL;
1100 dbus_g_proxy_call(proxy, "Set", &error,
1101 G_TYPE_STRING, BT_PLAYER_CONTROL_INTERFACE,
1102 G_TYPE_STRING, __bt_media_type_to_str(type),
1103 G_TYPE_VALUE, &attr_value,
1104 G_TYPE_INVALID, G_TYPE_INVALID);
1106 g_value_unset(&attr_value);
1107 g_object_unref(proxy);
1110 BT_ERR("SetProperty Fail: %s", error->message);
1111 g_error_free(error);
1112 return BLUETOOTH_ERROR_INTERNAL;
1115 return BLUETOOTH_ERROR_NONE;
1118 static gboolean __bt_avrcp_control_parse_metadata(
1119 char **value_string,
1120 unsigned int *value_uint,
1122 DBusMessageIter *iter)
1124 if (dbus_message_iter_get_arg_type(iter) != type)
1127 if (type == DBUS_TYPE_STRING) {
1129 dbus_message_iter_get_basic(iter, &value);
1130 *value_string = g_strdup(value);
1131 } else if (type == DBUS_TYPE_UINT32) {
1133 dbus_message_iter_get_basic(iter, &value);
1134 *value_uint = value;
1142 static int __bt_avrcp_control_parse_properties(
1143 media_metadata_attributes_t *metadata,
1144 DBusMessageIter *iter)
1146 DBusMessageIter dict;
1147 DBusMessageIter var;
1150 unsigned int value_uint;
1152 ctype = dbus_message_iter_get_arg_type(iter);
1153 if (ctype != DBUS_TYPE_ARRAY) {
1154 BT_ERR("ctype error %d", ctype);
1155 return BLUETOOTH_ERROR_INTERNAL;
1158 dbus_message_iter_recurse(iter, &dict);
1160 while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
1161 DBUS_TYPE_INVALID) {
1162 DBusMessageIter entry;
1165 if (ctype != DBUS_TYPE_DICT_ENTRY) {
1166 BT_ERR("ctype error %d", ctype);
1167 return BLUETOOTH_ERROR_INTERNAL;
1170 dbus_message_iter_recurse(&dict, &entry);
1171 if (dbus_message_iter_get_arg_type(&entry) !=
1173 BT_ERR("ctype not DBUS_TYPE_STRING");
1174 return BLUETOOTH_ERROR_INTERNAL;
1177 dbus_message_iter_get_basic(&entry, &key);
1178 dbus_message_iter_next(&entry);
1180 if (dbus_message_iter_get_arg_type(&entry) !=
1181 DBUS_TYPE_VARIANT) {
1182 BT_ERR("ctype not DBUS_TYPE_VARIANT");
1186 dbus_message_iter_recurse(&entry, &var);
1188 BT_ERR("Key value is %s", key);
1190 if (strcasecmp(key, "Title") == 0) {
1191 if (!__bt_avrcp_control_parse_metadata(&value_string,
1192 &value_uint, DBUS_TYPE_STRING, &var))
1193 return BLUETOOTH_ERROR_INTERNAL;
1194 BT_DBG("Value : %s ", value_string);
1195 metadata->title = value_string;
1196 } else if (strcasecmp(key, "Artist") == 0) {
1197 if (!__bt_avrcp_control_parse_metadata(&value_string,
1198 &value_uint, DBUS_TYPE_STRING, &var))
1199 return BLUETOOTH_ERROR_INTERNAL;
1200 BT_DBG("Value : %s ", value_string);
1201 metadata->artist = value_string;
1202 } else if (strcasecmp(key, "Album") == 0) {
1203 if (!__bt_avrcp_control_parse_metadata(&value_string,
1204 &value_uint, DBUS_TYPE_STRING, &var))
1205 return BLUETOOTH_ERROR_INTERNAL;
1206 BT_DBG("Value : %s ", value_string);
1207 metadata->album = value_string;
1208 } else if (strcasecmp(key, "Genre") == 0) {
1209 if (!__bt_avrcp_control_parse_metadata(&value_string,
1210 &value_uint, DBUS_TYPE_STRING, &var))
1211 return BLUETOOTH_ERROR_INTERNAL;
1212 BT_DBG("Value : %s ", value_string);
1213 metadata->genre = value_string;
1214 } else if (strcasecmp(key, "Duration") == 0) {
1215 if (!__bt_avrcp_control_parse_metadata(&value_string,
1216 &value_uint, DBUS_TYPE_UINT32, &var))
1217 return BLUETOOTH_ERROR_INTERNAL;
1218 metadata->duration = value_uint;
1219 } else if (strcasecmp(key, "NumberOfTracks") == 0) {
1220 if (!__bt_avrcp_control_parse_metadata(&value_string,
1221 &value_uint, DBUS_TYPE_UINT32, &var))
1222 return BLUETOOTH_ERROR_INTERNAL;
1223 metadata->total_tracks = value_uint;
1224 } else if (strcasecmp(key, "TrackNumber") == 0) {
1225 if (!__bt_avrcp_control_parse_metadata(&value_string,
1226 &value_uint, DBUS_TYPE_UINT32, &var))
1227 return BLUETOOTH_ERROR_INTERNAL;
1228 metadata->number = value_uint;
1230 BT_DBG("%s not supported, ignoring", key);
1231 dbus_message_iter_next(&dict);
1234 if (!metadata->title)
1235 metadata->title = g_strdup("");
1236 if (!metadata->artist)
1237 metadata->artist = g_strdup("");
1238 if (!metadata->album)
1239 metadata->album = g_strdup("");
1240 if (!metadata->genre)
1241 metadata->genre = g_strdup("");
1243 return BLUETOOTH_ERROR_NONE;
1246 int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata)
1251 DBusConnection *conn;
1253 char *interface_name;
1254 char *property_name;
1255 DBusMessageIter arr, iter;
1256 int ret = BLUETOOTH_ERROR_NONE;
1258 retv_if(metadata == NULL, BLUETOOTH_ERROR_INTERNAL);
1260 conn = _bt_get_system_conn();
1261 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1263 control_path = __bt_get_control_device_path();
1264 retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
1265 BT_DBG("control_path %s", control_path);
1267 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, control_path,
1268 BT_PROPERTIES_INTERFACE, "Get");
1270 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
1272 interface_name = g_strdup(BT_PLAYER_CONTROL_INTERFACE);
1273 property_name = g_strdup("Track");
1275 dbus_message_append_args(msg,
1276 DBUS_TYPE_STRING, &interface_name,
1277 DBUS_TYPE_STRING, &property_name,
1280 dbus_error_init(&err);
1281 reply = dbus_connection_send_with_reply_and_block(conn,
1284 g_free(interface_name);
1285 g_free(property_name);
1286 dbus_message_unref(msg);
1289 BT_ERR("Error in getting Metadata");
1290 if (dbus_error_is_set(&err)) {
1291 BT_ERR("%s", err.message);
1292 dbus_error_free(&err);
1294 return BLUETOOTH_ERROR_INTERNAL;
1297 dbus_message_iter_init(reply, &iter);
1298 dbus_message_iter_recurse(&iter, &arr);
1300 ret = __bt_avrcp_control_parse_properties(metadata, &arr);
1301 dbus_message_unref(reply);
1307 void _bt_handle_avrcp_control_event(DBusMessageIter *msg_iter, const char *path)
1309 DBusMessageIter value_iter;
1310 DBusMessageIter dict_iter;
1311 DBusMessageIter item_iter;
1312 const char *property = NULL;
1314 dbus_message_iter_recurse(msg_iter, &item_iter);
1316 if (dbus_message_iter_get_arg_type(&item_iter)
1317 != DBUS_TYPE_DICT_ENTRY) {
1318 BT_ERR("This is bad format dbus");
1322 dbus_message_iter_recurse(&item_iter, &dict_iter);
1324 dbus_message_iter_get_basic(&dict_iter, &property);
1325 ret_if(property == NULL);
1327 BT_DBG("property : %s ", property);
1328 ret_if(!dbus_message_iter_next(&dict_iter));
1330 if ((strcasecmp(property, "Equalizer") == 0) ||
1331 (strcasecmp(property, "Repeat") == 0) ||
1332 (strcasecmp(property, "Shuffle") == 0) ||
1333 (strcasecmp(property, "Scan") == 0) ||
1334 (strcasecmp(property, "Status") == 0)) {
1339 dbus_message_iter_recurse(&dict_iter, &value_iter);
1340 dbus_message_iter_get_basic(&value_iter, &valstr);
1341 BT_DBG("Value : %s ", valstr);
1342 type = __bt_media_attr_to_type(property);
1343 value = __bt_media_attrval_to_val(type, valstr);
1345 /* Send event to application */
1346 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
1347 __bt_media_attr_to_event(property),
1348 DBUS_TYPE_UINT32, &value,
1350 } else if (strcasecmp(property, "Position") == 0) {
1353 dbus_message_iter_recurse(&dict_iter, &value_iter);
1354 dbus_message_iter_get_basic(&value_iter, &value);
1355 BT_DBG("Value : %d ", value);
1357 /* Send event to application */
1358 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
1359 __bt_media_attr_to_event(property),
1360 DBUS_TYPE_UINT32, &value,
1362 } else if (strcasecmp(property, "Track") == 0) {
1363 int ret = BLUETOOTH_ERROR_NONE;
1364 media_metadata_attributes_t metadata;
1366 dbus_message_iter_recurse(&dict_iter, &value_iter);
1367 memset(&metadata, 0x00, sizeof(media_metadata_attributes_t));
1369 ret = __bt_avrcp_control_parse_properties(
1370 &metadata, &value_iter);
1371 if (BLUETOOTH_ERROR_NONE != ret)
1374 /* Send event to application */
1375 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
1376 BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED,
1377 DBUS_TYPE_STRING, &metadata.title,
1378 DBUS_TYPE_STRING, &metadata.artist,
1379 DBUS_TYPE_STRING, &metadata.album,
1380 DBUS_TYPE_STRING, &metadata.genre,
1381 DBUS_TYPE_UINT32, &metadata.total_tracks,
1382 DBUS_TYPE_UINT32, &metadata.number,
1383 DBUS_TYPE_UINT32, &metadata.duration,
1386 g_free(metadata.title);
1387 g_free(metadata.artist);
1388 g_free(metadata.album);
1389 g_free(metadata.genre);
1391 BT_DBG("Preprty not handled");