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 #include <syspopup_caller.h>
32 #include "bluetooth-api.h"
33 #include "bt-internal-types.h"
35 #include "bt-service-common.h"
36 #include "bt-service-avrcp.h"
37 #include "bt-service-event.h"
38 #include "bt-service-util.h"
39 #include "bt-service-audio.h"
41 struct player_settinngs_t {
46 static struct player_settinngs_t loopstatus_settings[] = {
47 { REPEAT_INVALID, "" },
48 { REPEAT_MODE_OFF, "None" },
49 { REPEAT_SINGLE_TRACK, "Track" },
50 { REPEAT_ALL_TRACK, "Playlist" },
51 { REPEAT_INVALID, "" }
55 static struct player_settinngs_t shuffle_settings[] = {
56 { SHUFFLE_INVALID, "" },
57 { SHUFFLE_MODE_OFF, "off" },
58 { SHUFFLE_ALL_TRACK, "alltracks" },
59 { SHUFFLE_GROUP, "group" },
60 { SHUFFLE_INVALID, "" }
63 static struct player_settinngs_t player_status[] = {
64 { STATUS_STOPPED, "stopped" },
65 { STATUS_PLAYING, "playing" },
66 { STATUS_PAUSED, "paused" },
67 { STATUS_FORWARD_SEEK, "forward-seek" },
68 { STATUS_REVERSE_SEEK, "reverse-seek" },
69 { STATUS_ERROR, "error" },
70 { STATUS_INVALID, "" }
73 static struct player_settinngs_t repeat_status[] = {
74 { REPEAT_INVALID, "" },
75 { REPEAT_MODE_OFF, "off" },
76 { REPEAT_SINGLE_TRACK, "singletrack" },
77 { REPEAT_ALL_TRACK, "alltracks" },
78 { REPEAT_GROUP, "group" },
79 { REPEAT_INVALID, "" }
82 static struct player_settinngs_t equalizer_status[] = {
83 { EQUALIZER_INVALID, "" },
84 { EQUALIZER_OFF, "off" },
85 { EQUALIZER_ON, "on" },
86 { EQUALIZER_INVALID, "" },
89 static struct player_settinngs_t scan_status[] = {
91 { SCAN_MODE_OFF, "off" },
92 { SCAN_ALL_TRACK, "alltracks" },
93 { SCAN_GROUP, "group" },
96 DBusConnection *g_bt_dbus_conn = NULL;
97 static char *avrcp_control_path = NULL;
99 static DBusHandlerResult _bt_avrcp_handle_set_property(DBusConnection *connection,
100 DBusMessage *message, void *user_data)
105 gboolean shuffle_status;
106 DBusMessageIter args;
107 const char *property = NULL;
108 const char *interface = NULL;
109 DBusMessage *reply = NULL;
110 DBusHandlerResult result = DBUS_HANDLER_RESULT_HANDLED;
111 DBusMessageIter entry;
115 dbus_message_iter_init(message, &args);
116 dbus_message_iter_get_basic(&args, &interface);
117 dbus_message_iter_next(&args);
119 if (g_strcmp0(interface, BT_MEDIA_PLAYER_INTERFACE) != 0) {
120 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
124 dbus_message_iter_get_basic(&args, &property);
125 dbus_message_iter_next(&args);
126 dbus_message_iter_recurse(&args, &entry);
127 type = dbus_message_iter_get_arg_type(&entry);
129 BT_DBG("property %s\n", property);
131 if (g_strcmp0(property, "Shuffle") == 0) {
132 if (type != DBUS_TYPE_BOOLEAN) {
134 reply = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
135 "Invalid arguments");
136 dbus_connection_send(connection, reply, NULL);
137 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
140 dbus_message_iter_get_basic(&entry, &shuffle_status);
141 BT_DBG("value %d\n", shuffle_status);
142 if (shuffle_status == TRUE)
143 status = SHUFFLE_ALL_TRACK;
145 status = SHUFFLE_MODE_OFF;
147 _bt_send_event(BT_AVRCP_EVENT,
148 BLUETOOTH_EVENT_AVRCP_SETTING_SHUFFLE_STATUS,
149 DBUS_TYPE_UINT32, &status,
152 } else if (g_strcmp0(property, "LoopStatus") == 0) {
153 if (type != DBUS_TYPE_STRING) {
155 reply = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
156 "Invalid arguments");
157 dbus_connection_send(connection, reply, NULL);
158 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
161 dbus_message_iter_get_basic(&entry, &value);
162 BT_DBG("value %s\n", value);
164 if (g_strcmp0(value, "Track") == 0)
165 status = REPEAT_SINGLE_TRACK;
166 else if (g_strcmp0(value, "Playlist") == 0)
167 status = REPEAT_ALL_TRACK;
168 else if (g_strcmp0(value, "None") == 0)
169 status = REPEAT_MODE_OFF;
171 status = REPEAT_INVALID;
173 _bt_send_event(BT_AVRCP_EVENT,
174 BLUETOOTH_EVENT_AVRCP_SETTING_REPEAT_STATUS,
175 DBUS_TYPE_UINT32, &status,
180 dbus_message_unref(reply);
185 static DBusHandlerResult _bt_avrcp_message_handle(DBusConnection *conn, DBusMessage *msg, void *user_data)
189 if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PROPERTIES, "Set"))
190 return _bt_avrcp_handle_set_property(conn, msg, user_data);
193 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
196 static DBusObjectPathVTable bt_object_table = {
197 .message_function = _bt_avrcp_message_handle,
200 gboolean bt_dbus_register_object_path(DBusConnection *connection,
203 if (!dbus_connection_register_object_path(connection, path,
204 &bt_object_table, NULL))
209 void bt_dbus_unregister_object_path(DBusConnection *connection,
212 dbus_connection_unregister_object_path(connection, path);
215 static void __bt_media_append_variant(DBusMessageIter *iter,
216 int type, void *value)
218 char sig[2] = { type, '\0'};
219 DBusMessageIter value_iter;
221 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig,
224 dbus_message_iter_append_basic(&value_iter, type, value);
226 dbus_message_iter_close_container(iter, &value_iter);
229 static void __bt_media_append_dict_entry(DBusMessageIter *iter,
230 const char *key, int type, void *property)
232 DBusMessageIter dict_entry;
235 if (type == DBUS_TYPE_STRING) {
236 str_ptr = *((const char **)property);
237 ret_if(str_ptr == NULL);
240 dbus_message_iter_open_container(iter,
241 DBUS_TYPE_DICT_ENTRY,
244 dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &key);
246 __bt_media_append_variant(&dict_entry, type, property);
248 dbus_message_iter_close_container(iter, &dict_entry);
251 static gboolean __bt_media_emit_property_changed(
252 DBusConnection *connection,
254 const char *interface,
260 DBusMessageIter entry, dict;
263 sig = dbus_message_new_signal(path, DBUS_INTERFACE_PROPERTIES,
264 "PropertiesChanged");
265 retv_if(sig == NULL, FALSE);
267 dbus_message_iter_init_append(sig, &entry);
268 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &interface);
269 dbus_message_iter_open_container(&entry, DBUS_TYPE_ARRAY,
270 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
271 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
272 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
274 __bt_media_append_dict_entry(&dict,
275 name, type, property);
277 dbus_message_iter_close_container(&entry, &dict);
279 ret = dbus_connection_send(connection, sig, NULL);
280 dbus_message_unref(sig);
285 void _bt_set_control_device_path(const char *path)
288 ret_if(path == NULL);
290 g_free(avrcp_control_path);
291 BT_DBG("control_path = %s", path);
292 avrcp_control_path = g_strdup(path);
295 void _bt_remove_control_device_path(const char *path)
297 ret_if(path == NULL);
299 if (avrcp_control_path &&
300 !g_strcmp0(avrcp_control_path, path)) {
301 BT_DBG("control_path = %s", path);
302 g_free(avrcp_control_path);
303 avrcp_control_path = NULL;
307 static char *__bt_get_control_device_path(void)
311 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
315 retv_if(avrcp_control_path != NULL, avrcp_control_path);
317 retv_if(!_bt_is_headset_type_connected(BT_AVRCP,
318 connected_address), NULL);
320 BT_DBG("device address = %s", connected_address);
322 adapter_path = _bt_get_device_object_path(connected_address);
323 retv_if(adapter_path == NULL, NULL);
325 control_path = g_strdup_printf(BT_MEDIA_CONTROL_PATH, adapter_path);
326 g_free(adapter_path);
328 avrcp_control_path = control_path;
329 BT_DBG("control_path = %s", control_path);
333 static int __bt_media_send_control_msg(const char *name)
338 DBusConnection *conn;
341 retv_if(name == NULL, BLUETOOTH_ERROR_INTERNAL);
343 conn = _bt_get_system_conn();
344 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
346 control_path = __bt_get_control_device_path();
347 retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
348 BT_DBG("control_path %s", control_path);
350 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, control_path,
351 BT_PLAYER_CONTROL_INTERFACE, name);
353 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
355 dbus_error_init(&err);
356 reply = dbus_connection_send_with_reply_and_block(conn,
358 dbus_message_unref(msg);
361 BT_ERR("Error in Sending Control Command");
363 if (dbus_error_is_set(&err)) {
364 BT_ERR("%s", err.message);
365 dbus_error_free(&err);
367 return BLUETOOTH_ERROR_INTERNAL;
370 dbus_message_unref(reply);
373 return BLUETOOTH_ERROR_NONE;
377 int _bt_register_media_player(void)
382 DBusMessageIter iter;
383 DBusMessageIter property_dict;
387 DBusConnection *conn;
388 DBusGConnection *gconn;
389 gboolean shuffle_status;
391 media_player_settings_t player_settings = {0,};
393 player_settings.repeat = REPEAT_MODE_OFF;
395 player_settings.shuffle = SHUFFLE_MODE_OFF;
396 player_settings.status = STATUS_STOPPED;
397 player_settings.position = 0;
400 gconn = _bt_get_system_gconn();
401 retv_if(gconn == NULL, BLUETOOTH_ERROR_INTERNAL);
403 conn = _bt_get_system_conn();
404 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
405 g_bt_dbus_conn = conn;
408 if (!bt_dbus_register_object_path(conn, BT_MEDIA_OBJECT_PATH)){
409 BT_DBG("Could not register interface %s",
410 BT_MEDIA_PLAYER_INTERFACE);
413 adapter_path = _bt_get_adapter_path();
414 retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
416 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path,
417 BT_MEDIA_INTERFACE, "RegisterPlayer");
419 g_free(adapter_path);
421 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
423 object = g_strdup(BT_MEDIA_OBJECT_PATH);
425 dbus_message_iter_init_append(msg, &iter);
426 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &object);
429 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
430 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
431 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
432 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &property_dict);
434 __bt_media_append_dict_entry(&property_dict,
437 &loopstatus_settings[player_settings.repeat].property);
439 if (player_settings.shuffle == SHUFFLE_MODE_OFF)
440 shuffle_status = FALSE;
442 shuffle_status = TRUE;
444 __bt_media_append_dict_entry(&property_dict,
449 __bt_media_append_dict_entry(&property_dict,
452 &player_status[player_settings.status].property);
455 __bt_media_append_dict_entry(&property_dict,
457 DBUS_TYPE_UINT32, &player_settings.position);
459 dbus_message_iter_close_container(&iter, &property_dict);
461 dbus_error_init(&err);
462 reply = dbus_connection_send_with_reply_and_block(conn,
464 dbus_message_unref(msg);
467 BT_ERR("Error in registering the Music Player \n");
469 if (dbus_error_is_set(&err)) {
470 BT_ERR("%s", err.message);
471 dbus_error_free(&err);
472 return BLUETOOTH_ERROR_INTERNAL;
477 dbus_message_unref(reply);
480 return BLUETOOTH_ERROR_NONE;
483 int _bt_unregister_media_player(void)
491 DBusConnection *conn;
493 conn = g_bt_dbus_conn;
494 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
496 adapter_path = _bt_get_adapter_path();
497 retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
499 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path,
500 BT_MEDIA_INTERFACE, "UnregisterPlayer");
503 g_free(adapter_path);
505 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
507 object = g_strdup(BT_MEDIA_OBJECT_PATH);
509 dbus_message_append_args(msg,
510 DBUS_TYPE_OBJECT_PATH, &object,
515 dbus_error_init(&err);
516 reply = dbus_connection_send_with_reply_and_block(conn,
518 dbus_message_unref(msg);
521 BT_ERR("Error in unregistering the Music Player \n");
523 if (dbus_error_is_set(&err)) {
524 BT_ERR("%s", err.message);
525 dbus_error_free(&err);
526 return BLUETOOTH_ERROR_INTERNAL;
529 dbus_message_unref(reply);
532 bt_dbus_unregister_object_path(conn, BT_MEDIA_OBJECT_PATH);
533 g_bt_dbus_conn = NULL;
536 return BLUETOOTH_ERROR_NONE;
539 static void __bt_media_append_metadata_entry(DBusMessageIter *metadata,
540 void *key_type, void *value, int type)
543 DBusMessageIter string_entry;
545 dbus_message_iter_open_container(metadata,
546 DBUS_TYPE_DICT_ENTRY,
547 NULL, &string_entry);
549 dbus_message_iter_append_basic(&string_entry, DBUS_TYPE_STRING, key_type);
551 __bt_media_append_variant(&string_entry, type, value);
553 dbus_message_iter_close_container(metadata, &string_entry);
557 static void __bt_media_append_metadata_array(DBusMessageIter *metadata,
558 void *key_type, void *value, int type)
561 DBusMessageIter string_entry, variant, array;
562 char array_sig[3] = { type, DBUS_TYPE_STRING, '\0' };
564 dbus_message_iter_open_container(metadata,
565 DBUS_TYPE_DICT_ENTRY,
566 NULL, &string_entry);
567 dbus_message_iter_append_basic(&string_entry, DBUS_TYPE_STRING, key_type);
569 dbus_message_iter_open_container(&string_entry, DBUS_TYPE_VARIANT,
570 array_sig, &variant);
572 dbus_message_iter_open_container(&variant, type,
573 DBUS_TYPE_STRING_AS_STRING, &array);
574 dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, value);
576 dbus_message_iter_close_container(&variant, &array);
577 dbus_message_iter_close_container(&string_entry, &variant);
578 dbus_message_iter_close_container(metadata, &string_entry);
582 int _bt_avrcp_set_track_info(media_metadata_attributes_t *meta_data)
586 DBusMessageIter iter;
587 DBusMessageIter property_dict, metadata_dict, metadata_variant, metadata;
588 DBusConnection *conn;
589 char *interface = BT_MEDIA_PLAYER_INTERFACE;
590 char * metadata_str = "Metadata";
591 const char *key_type;
593 retv_if(meta_data == NULL, BLUETOOTH_ERROR_INTERNAL);
595 conn = g_bt_dbus_conn;
596 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
598 sig = dbus_message_new_signal(BT_MEDIA_OBJECT_PATH, DBUS_INTERFACE_PROPERTIES,
599 "PropertiesChanged");
600 retv_if(sig == NULL, FALSE);
602 dbus_message_iter_init_append(sig, &iter);
603 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface);
605 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
606 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
607 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
608 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &property_dict);
610 dbus_message_iter_open_container(&property_dict,
611 DBUS_TYPE_DICT_ENTRY,
612 NULL, &metadata_dict);
614 dbus_message_iter_append_basic(&metadata_dict, DBUS_TYPE_STRING, &metadata_str);
616 dbus_message_iter_open_container(&metadata_dict, DBUS_TYPE_VARIANT, "a{sv}",
619 dbus_message_iter_open_container(&metadata_variant, DBUS_TYPE_ARRAY,
620 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
621 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
622 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata);
624 if (meta_data->title) {
625 key_type = "xesam:title";
626 __bt_media_append_metadata_entry(&metadata, &key_type,
627 &meta_data->title, DBUS_TYPE_STRING);
630 if (meta_data->artist) {
631 key_type = "xesam:artist";
632 __bt_media_append_metadata_array(&metadata, &key_type,
633 &meta_data->artist, DBUS_TYPE_ARRAY);
636 if (meta_data->album) {
637 key_type = "xesam:album";
638 __bt_media_append_metadata_entry(&metadata, &key_type,
639 &meta_data->album, DBUS_TYPE_STRING);
642 if (meta_data->genre) {
643 key_type = "xesam:genre";
644 __bt_media_append_metadata_array(&metadata, &key_type,
645 &meta_data->genre, DBUS_TYPE_ARRAY);
648 if (0 != meta_data->total_tracks) {
649 key_type = "xesam:totalTracks";
650 __bt_media_append_metadata_entry(&metadata, &key_type,
651 &meta_data->total_tracks, DBUS_TYPE_INT32);
654 if (0 != meta_data->number) {
655 key_type = "xesam:trackNumber";
656 __bt_media_append_metadata_entry(&metadata, &key_type,
657 &meta_data->number, DBUS_TYPE_INT32);
660 if (0 != meta_data->duration) {
661 key_type = "mpris:length";
662 __bt_media_append_metadata_entry(&metadata, &key_type,
663 &meta_data->duration, DBUS_TYPE_INT64);
666 dbus_message_iter_close_container(&metadata_variant, &metadata);
667 dbus_message_iter_close_container(&metadata_dict, &metadata_variant);
668 dbus_message_iter_close_container(&property_dict, &metadata_dict);
669 dbus_message_iter_close_container(&iter, &property_dict);
671 if (!dbus_connection_send(conn, sig, NULL))
672 BT_ERR("Unable to send TrackChanged signal\n");
674 dbus_message_unref(sig);
676 return BLUETOOTH_ERROR_NONE;
680 int _bt_avrcp_set_interal_property(int type, media_player_settings_t *properties)
683 DBusConnection *conn;
685 media_metadata_attributes_t meta_data;
688 conn = g_bt_dbus_conn;
689 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
693 value = properties->repeat;
694 if (!__bt_media_emit_property_changed(
696 BT_MEDIA_OBJECT_PATH,
697 BT_MEDIA_PLAYER_INTERFACE,
700 &loopstatus_settings[value].property)) {
701 BT_ERR("Error sending the PropertyChanged signal \n");
702 return BLUETOOTH_ERROR_INTERNAL;
706 value = properties->shuffle;
707 if (g_strcmp0(shuffle_settings[value].property, "off") == 0)
712 if (!__bt_media_emit_property_changed(
714 BT_MEDIA_OBJECT_PATH,
715 BT_MEDIA_PLAYER_INTERFACE,
719 BT_DBG("Error sending the PropertyChanged signal \n");
720 return BLUETOOTH_ERROR_INTERNAL;
724 value = properties->status;
725 if (!__bt_media_emit_property_changed(
727 BT_MEDIA_OBJECT_PATH,
728 BT_MEDIA_PLAYER_INTERFACE,
731 &player_status[value].property)) {
732 BT_DBG("Error sending the PropertyChanged signal \n");
733 return BLUETOOTH_ERROR_INTERNAL;
737 value = properties->position;
738 if (!__bt_media_emit_property_changed(
740 BT_MEDIA_OBJECT_PATH,
741 BT_MEDIA_PLAYER_INTERFACE,
745 BT_DBG("Error sending the PropertyChanged signal \n");
746 return BLUETOOTH_ERROR_INTERNAL;
750 meta_data = properties->metadata;
751 if (!__bt_media_emit_property_changed(
753 BT_MEDIA_OBJECT_PATH,
754 BT_MEDIA_PLAYER_INTERFACE,
758 BT_DBG("Error sending the PropertyChanged signal \n");
759 return BLUETOOTH_ERROR_INTERNAL;
763 BT_DBG("Invalid Type\n");
764 return BLUETOOTH_ERROR_INTERNAL;
767 return BLUETOOTH_ERROR_NONE;
770 int _bt_avrcp_set_properties(media_player_settings_t *properties)
774 if (_bt_avrcp_set_interal_property(REPEAT,
775 properties) != BLUETOOTH_ERROR_NONE) {
776 return BLUETOOTH_ERROR_INTERNAL;
778 if (_bt_avrcp_set_interal_property(SHUFFLE,
779 properties) != BLUETOOTH_ERROR_NONE) {
780 return BLUETOOTH_ERROR_INTERNAL;
783 if (_bt_avrcp_set_interal_property(STATUS,
784 properties) != BLUETOOTH_ERROR_NONE) {
785 return BLUETOOTH_ERROR_INTERNAL;
788 if (_bt_avrcp_set_interal_property(POSITION,
789 properties) != BLUETOOTH_ERROR_NONE) {
790 return BLUETOOTH_ERROR_INTERNAL;
793 if (_bt_avrcp_set_interal_property(METADATA,
794 properties) != BLUETOOTH_ERROR_NONE) {
795 return BLUETOOTH_ERROR_INTERNAL;
798 return BLUETOOTH_ERROR_NONE;
801 int _bt_avrcp_set_property(int type, unsigned int value)
804 media_player_settings_t properties;
808 properties.repeat = value;
811 properties.shuffle = value;
814 properties.status = value;
817 properties.position = value;
820 BT_DBG("Invalid Type\n");
821 return BLUETOOTH_ERROR_INTERNAL;
824 if (_bt_avrcp_set_interal_property(type,
825 &properties) != BLUETOOTH_ERROR_NONE)
826 return BLUETOOTH_ERROR_INTERNAL;
830 return BLUETOOTH_ERROR_NONE;
833 int _bt_avrcp_control_cmd(int type)
835 int ret = BLUETOOTH_ERROR_INTERNAL;
840 ret = __bt_media_send_control_msg("Play");
843 ret = __bt_media_send_control_msg("Pause");
846 ret = __bt_media_send_control_msg("Stop");
849 ret = __bt_media_send_control_msg("Next");
852 ret = __bt_media_send_control_msg("Previous");
855 ret = __bt_media_send_control_msg("FastForward");
858 ret = __bt_media_send_control_msg("Rewind");
861 BT_DBG("Invalid Type\n");
862 return BLUETOOTH_ERROR_INTERNAL;
868 DBusGProxy *__bt_get_control_properties_proxy(void)
872 DBusGConnection *conn;
874 control_path = __bt_get_control_device_path();
875 retv_if(control_path == NULL, NULL);
876 BT_DBG("control_path = %s", control_path);
878 conn = _bt_get_system_gconn();
879 retv_if(conn == NULL, NULL);
881 proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
882 control_path, BT_PROPERTIES_INTERFACE);
886 static int __bt_media_attr_to_event(const char *str)
888 if (!strcasecmp(str, "Equalizer"))
889 return BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS;
890 else if (!strcasecmp(str, "Repeat"))
891 return BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS;
892 else if (!strcasecmp(str, "Shuffle"))
893 return BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS;
894 else if (!strcasecmp(str, "Scan"))
895 return BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS;
896 else if (!strcasecmp(str, "Position"))
897 return BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS;
898 else if (!strcasecmp(str, "Track"))
899 return BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED;
900 else if (!strcasecmp(str, "Status"))
901 return BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED;
906 static int __bt_media_attr_to_type(const char *str)
908 if (!strcasecmp(str, "Equalizer"))
910 else if (!strcasecmp(str, "Repeat"))
912 else if (!strcasecmp(str, "Shuffle"))
914 else if (!strcasecmp(str, "Scan"))
916 else if (!strcasecmp(str, "Position"))
918 else if (!strcasecmp(str, "Track"))
920 else if (!strcasecmp(str, "Status"))
926 static const char *__bt_media_type_to_str(int type)
947 static int __bt_media_attrval_to_val(int type, const char *value)
953 if (!strcmp(value, "off"))
955 else if (!strcmp(value, "on"))
958 ret = EQUALIZER_INVALID;
962 if (!strcmp(value, "off"))
963 ret = REPEAT_MODE_OFF;
964 else if (!strcmp(value, "singletrack"))
965 ret = REPEAT_SINGLE_TRACK;
966 else if (!strcmp(value, "alltracks"))
967 ret = REPEAT_ALL_TRACK;
968 else if (!strcmp(value, "group"))
971 ret = REPEAT_INVALID;
975 if (!strcmp(value, "off"))
976 ret = SHUFFLE_MODE_OFF;
977 else if (!strcmp(value, "alltracks"))
978 ret = SHUFFLE_ALL_TRACK;
979 else if (!strcmp(value, "group"))
982 ret = SHUFFLE_INVALID;
986 if (!strcmp(value, "off"))
988 else if (!strcmp(value, "alltracks"))
989 ret = SCAN_ALL_TRACK;
990 else if (!strcmp(value, "group"))
997 if (!strcmp(value, "stopped"))
998 ret = STATUS_STOPPED;
999 else if (!strcmp(value, "playing"))
1000 ret = STATUS_PLAYING;
1001 else if (!strcmp(value, "paused"))
1002 ret = STATUS_PAUSED;
1003 else if (!strcmp(value, "forward-seek"))
1004 ret = STATUS_FORWARD_SEEK;
1005 else if (!strcmp(value, "reverse-seek"))
1006 ret = STATUS_REVERSE_SEEK;
1007 else if (!strcmp(value, "error"))
1010 ret = STATUS_INVALID;
1015 int _bt_avrcp_control_get_property(int type, unsigned int *value)
1019 int ret = BLUETOOTH_ERROR_NONE;
1021 GValue attr_value = { 0 };
1023 BT_CHECK_PARAMETER(value, return);
1025 proxy = __bt_get_control_properties_proxy();
1026 retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
1028 if (!dbus_g_proxy_call(proxy, "Get", &err,
1029 G_TYPE_STRING, BT_PLAYER_CONTROL_INTERFACE,
1030 G_TYPE_STRING, __bt_media_type_to_str(type),
1032 G_TYPE_VALUE, &attr_value,
1035 BT_ERR("Getting property failed: [%s]\n", err->message);
1038 g_object_unref(proxy);
1039 return BLUETOOTH_ERROR_INTERNAL;
1041 g_object_unref(proxy);
1049 name = (char *)g_value_get_string(&attr_value);
1050 *value = __bt_media_attrval_to_val(type, name);
1051 BT_DBG("Type[%s] and Value[%s]", __bt_media_type_to_str(type), name);
1054 *value = g_value_get_uint(&attr_value);
1057 BT_DBG("Invalid Type\n");
1058 ret = BLUETOOTH_ERROR_INTERNAL;
1064 int _bt_avrcp_control_set_property(int type, unsigned int value)
1066 GValue attr_value = { 0 };
1068 GError *error = NULL;
1070 proxy = __bt_get_control_properties_proxy();
1072 retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
1073 g_value_init(&attr_value, G_TYPE_STRING);
1077 g_value_set_string(&attr_value, equalizer_status[value].property);
1078 BT_DBG("equalizer_status %s", equalizer_status[value].property);
1081 g_value_set_string(&attr_value, repeat_status[value].property);
1082 BT_DBG("repeat_status %s", repeat_status[value].property);
1085 g_value_set_string(&attr_value, shuffle_settings[value].property);
1086 BT_DBG("shuffle_settings %s", shuffle_settings[value].property);
1089 g_value_set_string(&attr_value, scan_status[value].property);
1090 BT_DBG("scan_status %s", scan_status[value].property);
1093 BT_ERR("Invalid property type: %d", type);
1094 return BLUETOOTH_ERROR_INTERNAL;
1097 dbus_g_proxy_call(proxy, "Set", &error,
1098 G_TYPE_STRING, BT_PLAYER_CONTROL_INTERFACE,
1099 G_TYPE_STRING, __bt_media_type_to_str(type),
1100 G_TYPE_VALUE, &attr_value,
1101 G_TYPE_INVALID, G_TYPE_INVALID);
1103 g_value_unset(&attr_value);
1104 g_object_unref(proxy);
1107 BT_ERR("SetProperty Fail: %s", error->message);
1108 g_error_free(error);
1109 return BLUETOOTH_ERROR_INTERNAL;
1112 return BLUETOOTH_ERROR_NONE;
1115 static gboolean __bt_avrcp_control_parse_metadata(
1116 char **value_string,
1117 unsigned int *value_uint,
1119 DBusMessageIter *iter)
1121 if (dbus_message_iter_get_arg_type(iter) != type)
1124 if (type == DBUS_TYPE_STRING) {
1126 dbus_message_iter_get_basic(iter, &value);
1127 *value_string = g_strdup(value);
1128 } else if (type == DBUS_TYPE_UINT32) {
1130 dbus_message_iter_get_basic(iter, &value);
1131 *value_uint = value;
1139 static int __bt_avrcp_control_parse_properties(
1140 media_metadata_attributes_t *metadata,
1141 DBusMessageIter *iter)
1143 DBusMessageIter dict;
1144 DBusMessageIter var;
1147 unsigned int value_uint;
1149 ctype = dbus_message_iter_get_arg_type(iter);
1150 if (ctype != DBUS_TYPE_ARRAY) {
1151 BT_ERR("ctype error %d", ctype);
1152 return BLUETOOTH_ERROR_INTERNAL;
1155 dbus_message_iter_recurse(iter, &dict);
1157 while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
1158 DBUS_TYPE_INVALID) {
1159 DBusMessageIter entry;
1162 if (ctype != DBUS_TYPE_DICT_ENTRY) {
1163 BT_ERR("ctype error %d", ctype);
1164 return BLUETOOTH_ERROR_INTERNAL;
1167 dbus_message_iter_recurse(&dict, &entry);
1168 if (dbus_message_iter_get_arg_type(&entry) !=
1170 BT_ERR("ctype not DBUS_TYPE_STRING");
1171 return BLUETOOTH_ERROR_INTERNAL;
1174 dbus_message_iter_get_basic(&entry, &key);
1175 dbus_message_iter_next(&entry);
1177 if (dbus_message_iter_get_arg_type(&entry) !=
1178 DBUS_TYPE_VARIANT) {
1179 BT_ERR("ctype not DBUS_TYPE_VARIANT");
1183 dbus_message_iter_recurse(&entry, &var);
1185 BT_ERR("Key value is %s", key);
1187 if (strcasecmp(key, "Title") == 0) {
1188 if (!__bt_avrcp_control_parse_metadata(&value_string,
1189 &value_uint, DBUS_TYPE_STRING, &var))
1190 return BLUETOOTH_ERROR_INTERNAL;
1191 BT_DBG("Value : %s ", value_string);
1192 metadata->title = value_string;
1193 } else if (strcasecmp(key, "Artist") == 0) {
1194 if (!__bt_avrcp_control_parse_metadata(&value_string,
1195 &value_uint, DBUS_TYPE_STRING, &var))
1196 return BLUETOOTH_ERROR_INTERNAL;
1197 BT_DBG("Value : %s ", value_string);
1198 metadata->artist = value_string;
1199 } else if (strcasecmp(key, "Album") == 0) {
1200 if (!__bt_avrcp_control_parse_metadata(&value_string,
1201 &value_uint, DBUS_TYPE_STRING, &var))
1202 return BLUETOOTH_ERROR_INTERNAL;
1203 BT_DBG("Value : %s ", value_string);
1204 metadata->album = value_string;
1205 } else if (strcasecmp(key, "Genre") == 0) {
1206 if (!__bt_avrcp_control_parse_metadata(&value_string,
1207 &value_uint, DBUS_TYPE_STRING, &var))
1208 return BLUETOOTH_ERROR_INTERNAL;
1209 BT_DBG("Value : %s ", value_string);
1210 metadata->genre = value_string;
1211 } else if (strcasecmp(key, "Duration") == 0) {
1212 if (!__bt_avrcp_control_parse_metadata(&value_string,
1213 &value_uint, DBUS_TYPE_UINT32, &var))
1214 return BLUETOOTH_ERROR_INTERNAL;
1215 metadata->duration = value_uint;
1216 } else if (strcasecmp(key, "NumberOfTracks") == 0) {
1217 if (!__bt_avrcp_control_parse_metadata(&value_string,
1218 &value_uint, DBUS_TYPE_UINT32, &var))
1219 return BLUETOOTH_ERROR_INTERNAL;
1220 metadata->total_tracks = value_uint;
1221 } else if (strcasecmp(key, "TrackNumber") == 0) {
1222 if (!__bt_avrcp_control_parse_metadata(&value_string,
1223 &value_uint, DBUS_TYPE_UINT32, &var))
1224 return BLUETOOTH_ERROR_INTERNAL;
1225 metadata->number = value_uint;
1227 BT_DBG("%s not supported, ignoring", key);
1228 dbus_message_iter_next(&dict);
1231 if (!metadata->title)
1232 metadata->title = g_strdup("");
1233 if (!metadata->artist)
1234 metadata->artist = g_strdup("");
1235 if (!metadata->album)
1236 metadata->album = g_strdup("");
1237 if (!metadata->genre)
1238 metadata->genre = g_strdup("");
1240 return BLUETOOTH_ERROR_NONE;
1243 int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata)
1248 DBusConnection *conn;
1250 char *interface_name;
1251 char *property_name;
1252 DBusMessageIter arr, iter;
1253 int ret = BLUETOOTH_ERROR_NONE;
1255 retv_if(metadata == NULL, BLUETOOTH_ERROR_INTERNAL);
1257 conn = _bt_get_system_conn();
1258 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1260 control_path = __bt_get_control_device_path();
1261 retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
1262 BT_DBG("control_path %s", control_path);
1264 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, control_path,
1265 BT_PROPERTIES_INTERFACE, "Get");
1267 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
1269 interface_name = g_strdup(BT_PLAYER_CONTROL_INTERFACE);
1270 property_name = g_strdup("Track");
1272 dbus_message_append_args(msg,
1273 DBUS_TYPE_STRING, &interface_name,
1274 DBUS_TYPE_STRING, &property_name,
1277 dbus_error_init(&err);
1278 reply = dbus_connection_send_with_reply_and_block(conn,
1281 g_free(interface_name);
1282 g_free(property_name);
1283 dbus_message_unref(msg);
1286 BT_ERR("Error in getting Metadata");
1287 if (dbus_error_is_set(&err)) {
1288 BT_ERR("%s", err.message);
1289 dbus_error_free(&err);
1291 return BLUETOOTH_ERROR_INTERNAL;
1294 dbus_message_iter_init(reply, &iter);
1295 dbus_message_iter_recurse(&iter, &arr);
1297 ret = __bt_avrcp_control_parse_properties(metadata, &arr);
1298 dbus_message_unref(reply);
1304 void _bt_handle_avrcp_control_event(DBusMessageIter *msg_iter, const char *path)
1306 DBusMessageIter value_iter;
1307 DBusMessageIter dict_iter;
1308 DBusMessageIter item_iter;
1309 const char *property = NULL;
1311 dbus_message_iter_recurse(msg_iter, &item_iter);
1313 if (dbus_message_iter_get_arg_type(&item_iter)
1314 != DBUS_TYPE_DICT_ENTRY) {
1315 BT_ERR("This is bad format dbus");
1319 dbus_message_iter_recurse(&item_iter, &dict_iter);
1321 dbus_message_iter_get_basic(&dict_iter, &property);
1322 ret_if(property == NULL);
1324 BT_DBG("property : %s ", property);
1325 ret_if(!dbus_message_iter_next(&dict_iter));
1327 if ((strcasecmp(property, "Equalizer") == 0) ||
1328 (strcasecmp(property, "Repeat") == 0) ||
1329 (strcasecmp(property, "Shuffle") == 0) ||
1330 (strcasecmp(property, "Scan") == 0) ||
1331 (strcasecmp(property, "Status") == 0)) {
1336 dbus_message_iter_recurse(&dict_iter, &value_iter);
1337 dbus_message_iter_get_basic(&value_iter, &valstr);
1338 BT_DBG("Value : %s ", valstr);
1339 type = __bt_media_attr_to_type(property);
1340 value = __bt_media_attrval_to_val(type, valstr);
1342 /* Send event to application */
1343 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
1344 __bt_media_attr_to_event(property),
1345 DBUS_TYPE_UINT32, &value,
1347 } else if (strcasecmp(property, "Position") == 0) {
1350 dbus_message_iter_recurse(&dict_iter, &value_iter);
1351 dbus_message_iter_get_basic(&value_iter, &value);
1352 BT_DBG("Value : %d ", value);
1354 /* Send event to application */
1355 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
1356 __bt_media_attr_to_event(property),
1357 DBUS_TYPE_UINT32, &value,
1359 } else if (strcasecmp(property, "Track") == 0) {
1360 int ret = BLUETOOTH_ERROR_NONE;
1361 media_metadata_attributes_t metadata;
1363 dbus_message_iter_recurse(&dict_iter, &value_iter);
1364 memset(&metadata, 0x00, sizeof(media_metadata_attributes_t));
1366 ret = __bt_avrcp_control_parse_properties(
1367 &metadata, &value_iter);
1368 if (BLUETOOTH_ERROR_NONE != ret)
1371 /* Send event to application */
1372 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
1373 BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED,
1374 DBUS_TYPE_STRING, &metadata.title,
1375 DBUS_TYPE_STRING, &metadata.artist,
1376 DBUS_TYPE_STRING, &metadata.album,
1377 DBUS_TYPE_STRING, &metadata.genre,
1378 DBUS_TYPE_UINT32, &metadata.total_tracks,
1379 DBUS_TYPE_UINT32, &metadata.number,
1380 DBUS_TYPE_UINT32, &metadata.duration,
1383 g_free(metadata.title);
1384 g_free(metadata.artist);
1385 g_free(metadata.album);
1386 g_free(metadata.genre);
1388 BT_DBG("Preprty not handled");