2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "bt-internal-types.h"
19 #include "bt-service-common.h"
20 #include "bt-service-avrcp-controller.h"
21 #include "bt-service-audio.h"
22 #include "bt-service-event.h"
24 static bt_player_settinngs_t repeat_status[] = {
25 { REPEAT_INVALID, "" },
26 { REPEAT_MODE_OFF, "off" },
27 { REPEAT_SINGLE_TRACK, "singletrack" },
28 { REPEAT_ALL_TRACK, "alltracks" },
29 { REPEAT_GROUP, "group" },
30 { REPEAT_INVALID, "" }
33 static bt_player_settinngs_t equalizer_status[] = {
34 { EQUALIZER_INVALID, "" },
35 { EQUALIZER_OFF, "off" },
36 { EQUALIZER_ON, "on" },
37 { EQUALIZER_INVALID, "" },
40 static bt_player_settinngs_t scan_status[] = {
42 { SCAN_MODE_OFF, "off" },
43 { SCAN_ALL_TRACK, "alltracks" },
44 { SCAN_GROUP, "group" },
48 static bt_player_settinngs_t shuffle_settings[] = {
49 { SHUFFLE_INVALID, "" },
50 { SHUFFLE_MODE_OFF, "off" },
51 { SHUFFLE_ALL_TRACK, "alltracks" },
52 { SHUFFLE_GROUP, "group" },
53 { SHUFFLE_INVALID, "" }
56 static char *avrcp_control_path = NULL;
57 static char *avrcp_transport_path = NULL;
59 void _bt_set_control_device_path(const char *path)
64 g_free(avrcp_control_path);
65 BT_DBG("control_path = %s", path);
66 avrcp_control_path = g_strdup(path);
69 void _bt_remove_control_device_path(const char *path)
73 if (avrcp_control_path &&
74 !g_strcmp0(avrcp_control_path, path)) {
75 BT_DBG("control_path = %s", path);
76 g_free(avrcp_control_path);
77 avrcp_control_path = NULL;
81 static char *__bt_get_control_device_path(void)
85 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
89 if (avrcp_control_path != NULL)
90 return avrcp_control_path;
92 retv_if(!_bt_is_headset_type_connected(BT_AVRCP,
93 connected_address), NULL);
95 BT_DBG("device address = %s", connected_address);
97 adapter_path = _bt_get_device_object_path(connected_address);
98 retv_if(adapter_path == NULL, NULL);
100 control_path = g_strdup_printf(BT_MEDIA_CONTROL_PATH, adapter_path);
101 g_free(adapter_path);
103 avrcp_control_path = control_path;
104 BT_DBG("control_path = %s", control_path);
108 static char *__bt_get_transport_device_path(void)
111 char *transport_path;
112 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
116 if (avrcp_transport_path != NULL)
117 return avrcp_transport_path;
119 retv_if(!_bt_is_headset_type_connected(BT_AVRCP,
120 connected_address), NULL);
122 BT_DBG("device address = %s", connected_address);
124 adapter_path = _bt_get_device_object_path(connected_address);
125 retv_if(adapter_path == NULL, NULL);
127 transport_path = g_strdup_printf(BT_MEDIA_TRANSPORT_PATH, adapter_path);
128 g_free(adapter_path);
130 avrcp_transport_path = transport_path;
131 BT_DBG("transport_path = %s", transport_path);
132 return transport_path;
135 static int __bt_media_send_control_msg(const char *name)
137 GVariant *reply = NULL;
139 GDBusConnection *conn = NULL;
140 GDBusProxy *proxy = NULL;
141 char *control_path = NULL;
143 retv_if(name == NULL, BLUETOOTH_ERROR_INTERNAL);
145 BT_INFO("Command [%s]", name);
147 conn = _bt_gdbus_get_system_gconn();
148 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
150 control_path = __bt_get_control_device_path();
151 retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
152 BT_DBG("control_path %s", control_path);
154 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
155 BT_BLUEZ_NAME, control_path,
156 BT_PLAYER_CONTROL_INTERFACE, NULL, &err);
158 BT_ERR("Unable to allocate new proxy \n");
160 BT_ERR("%s", err->message);
163 return BLUETOOTH_ERROR_INTERNAL;
166 reply = g_dbus_proxy_call_sync(proxy, name, NULL,
167 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
169 g_object_unref(proxy);
172 BT_ERR("Error returned in method call");
174 BT_ERR("%s", err->message);
177 return BLUETOOTH_ERROR_INTERNAL;
180 g_variant_unref(reply);
183 return BLUETOOTH_ERROR_NONE;
186 int _bt_avrcp_control_cmd(int type)
188 int ret = BLUETOOTH_ERROR_INTERNAL;
193 ret = __bt_media_send_control_msg("Play");
196 ret = __bt_media_send_control_msg("Pause");
199 ret = __bt_media_send_control_msg("Stop");
202 ret = __bt_media_send_control_msg("Next");
205 ret = __bt_media_send_control_msg("Previous");
207 case PRESS_FAST_FORWARD:
208 ret = __bt_media_send_control_msg("PressFastForward");
210 case RELEASE_FAST_FORWARD:
211 ret = __bt_media_send_control_msg("ReleaseFastForward");
214 ret = __bt_media_send_control_msg("PressRewind");
217 ret = __bt_media_send_control_msg("ReleaseRewind");
220 ret = __bt_media_send_control_msg("VolumeUp");
223 ret = __bt_media_send_control_msg("VolumeDown");
226 BT_DBG("Invalid Type\n");
227 return BLUETOOTH_ERROR_INTERNAL;
233 GDBusProxy *__bt_get_control_properties_proxy(void)
235 GDBusProxy *proxy = NULL;
236 GError *error = NULL;
237 char *control_path = NULL;
238 GDBusConnection *conn = NULL;
240 control_path = __bt_get_control_device_path();
241 retv_if(control_path == NULL, NULL);
242 BT_DBG("control_path = %s", control_path);
244 conn = _bt_gdbus_get_system_gconn();
245 retv_if(conn == NULL, NULL);
247 proxy = g_dbus_proxy_new_sync(conn,
248 G_DBUS_PROXY_FLAGS_NONE, NULL,
249 BT_BLUEZ_NAME, control_path,
250 BT_PROPERTIES_INTERFACE, NULL, &error);
252 BT_ERR("Unable to allocate new proxy");
254 BT_ERR("%s", error->message);
255 g_clear_error(&error);
263 GDBusProxy *__bt_get_transport_properties_proxy(void)
265 GDBusProxy *proxy = NULL;
266 GError *error = NULL;
267 char *transport_path = NULL;
268 GDBusConnection *conn = NULL;
270 transport_path = __bt_get_transport_device_path();
271 retv_if(transport_path == NULL, NULL);
272 BT_DBG("transport_path = %s", transport_path);
274 conn = _bt_gdbus_get_system_gconn();
275 retv_if(conn == NULL, NULL);
277 proxy = g_dbus_proxy_new_sync(conn,
278 G_DBUS_PROXY_FLAGS_NONE, NULL,
279 BT_BLUEZ_NAME, transport_path,
280 BT_PROPERTIES_INTERFACE, NULL, &error);
282 BT_ERR("Unable to allocate new proxy");
284 BT_ERR("%s", error->message);
285 g_clear_error(&error);
293 static int __bt_media_attr_to_event(const char *str)
295 if (!strcasecmp(str, "Equalizer"))
296 return BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS;
297 else if (!strcasecmp(str, "Repeat"))
298 return BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS;
299 else if (!strcasecmp(str, "Shuffle"))
300 return BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS;
301 else if (!strcasecmp(str, "Scan"))
302 return BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS;
303 else if (!strcasecmp(str, "Position"))
304 return BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS;
305 else if (!strcasecmp(str, "Track"))
306 return BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED;
307 else if (!strcasecmp(str, "Status"))
308 return BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED;
313 static int __bt_media_attr_to_type(const char *str)
315 if (!strcasecmp(str, "Equalizer"))
317 else if (!strcasecmp(str, "Repeat"))
319 else if (!strcasecmp(str, "Shuffle"))
321 else if (!strcasecmp(str, "Scan"))
323 else if (!strcasecmp(str, "Position"))
325 else if (!strcasecmp(str, "Track"))
327 else if (!strcasecmp(str, "Status"))
333 static const char *__bt_media_type_to_str(int type)
354 static const char *__bt_transport_type_to_str(int type)
365 static int __bt_media_attrval_to_val(int type, const char *value)
371 if (!strcmp(value, "off"))
373 else if (!strcmp(value, "on"))
376 ret = EQUALIZER_INVALID;
380 if (!strcmp(value, "off"))
381 ret = REPEAT_MODE_OFF;
382 else if (!strcmp(value, "singletrack"))
383 ret = REPEAT_SINGLE_TRACK;
384 else if (!strcmp(value, "alltracks"))
385 ret = REPEAT_ALL_TRACK;
386 else if (!strcmp(value, "group"))
389 ret = REPEAT_INVALID;
393 if (!strcmp(value, "off"))
394 ret = SHUFFLE_MODE_OFF;
395 else if (!strcmp(value, "alltracks"))
396 ret = SHUFFLE_ALL_TRACK;
397 else if (!strcmp(value, "group"))
400 ret = SHUFFLE_INVALID;
404 if (!strcmp(value, "off"))
406 else if (!strcmp(value, "alltracks"))
407 ret = SCAN_ALL_TRACK;
408 else if (!strcmp(value, "group"))
415 if (!strcmp(value, "stopped"))
416 ret = STATUS_STOPPED;
417 else if (!strcmp(value, "playing"))
418 ret = STATUS_PLAYING;
419 else if (!strcmp(value, "paused"))
421 else if (!strcmp(value, "forward-seek"))
422 ret = STATUS_FORWARD_SEEK;
423 else if (!strcmp(value, "reverse-seek"))
424 ret = STATUS_REVERSE_SEEK;
425 else if (!strcmp(value, "error"))
428 ret = STATUS_INVALID;
433 int _bt_avrcp_control_get_property(int type, unsigned int *value)
435 GDBusProxy *proxy = NULL;
437 int ret = BLUETOOTH_ERROR_NONE;
439 GVariant *reply = NULL;
440 GVariant *temp = NULL;
442 BT_CHECK_PARAMETER(value, return);
444 proxy = __bt_get_control_properties_proxy();
445 retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
447 reply = g_dbus_proxy_call_sync(proxy,
448 "Get", g_variant_new("(ss)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type)),
449 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
451 g_object_unref(proxy);
454 BT_ERR("Can't get managed objects");
456 BT_ERR("%s", err->message);
459 return BLUETOOTH_ERROR_INTERNAL;
467 name = (char *)g_variant_get_data(reply);
469 *value = __bt_media_attrval_to_val(type, name);
470 BT_INFO("Type[%s] and Value[%s]", __bt_media_type_to_str(type), name);
473 g_variant_get(reply, "(v)", &temp);
474 *value = g_variant_get_uint32(temp);
475 g_variant_unref(temp);
476 BT_INFO("Type[%s] and Value[%d]", __bt_media_type_to_str(type), *value);
479 BT_ERR("Invalid Type [%d]", type);
480 ret = BLUETOOTH_ERROR_INTERNAL;
483 g_variant_unref(reply);
487 int _bt_avrcp_control_set_property(int type, unsigned int value)
489 GValue *attr_value = NULL;
490 GDBusProxy *proxy = NULL;
491 GError *error = NULL;
492 GVariant *reply, *param;
494 g_value_init(attr_value, G_TYPE_STRING);
498 param = g_variant_new("s", equalizer_status[value].property);
499 BT_INFO("equalizer_status %s", equalizer_status[value].property);
502 param = g_variant_new("s", repeat_status[value].property);
503 BT_INFO("repeat_status %s", repeat_status[value].property);
506 param = g_variant_new("s", shuffle_settings[value].property);
507 BT_INFO("shuffle_settings %s", shuffle_settings[value].property);
510 param = g_variant_new("s", scan_status[value].property);
511 BT_INFO("scan_status %s", scan_status[value].property);
514 BT_ERR("Invalid property type: %d", type);
515 g_value_unset(attr_value);
516 return BLUETOOTH_ERROR_INTERNAL;
519 proxy = __bt_get_control_properties_proxy();
520 retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
522 reply = g_dbus_proxy_call_sync(proxy,
523 "Set", g_variant_new("(ssv)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type), param),
524 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
526 g_object_unref(proxy);
527 g_variant_unref(param);
530 BT_ERR("Can't get managed objects");
532 BT_ERR("SetProperty Fail: %s", error->message);
533 g_clear_error(&error);
534 return BLUETOOTH_ERROR_INTERNAL;
538 g_variant_unref(reply);
539 g_value_unset(attr_value);
541 return BLUETOOTH_ERROR_NONE;
544 int _bt_avrcp_transport_set_property(int type, unsigned int value)
546 GDBusProxy *proxy = NULL;
547 GError *error = NULL;
548 GVariant *reply, *param;
549 uint16_t property_level = (uint16_t)value;
553 param = g_variant_new("q", property_level);
554 BT_INFO("delay level %d", property_level);
557 param = g_variant_new("q", property_level);
558 BT_INFO("volume level %d", property_level);
561 BT_ERR("Invalid property type: %d", type);
562 return BLUETOOTH_ERROR_INTERNAL;
565 proxy = __bt_get_transport_properties_proxy();
566 retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
568 reply = g_dbus_proxy_call_sync(proxy,
569 "Set", g_variant_new("(ssv)", BT_MEDIATRANSPORT_INTERFACE, __bt_transport_type_to_str(type), param),
570 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
572 g_object_unref(proxy);
573 g_variant_unref(param);
576 BT_ERR("Can't get managed objects");
578 BT_ERR("SetProperty Fail: %s", error->message);
579 g_clear_error(&error);
580 return BLUETOOTH_ERROR_INTERNAL;
584 g_variant_unref(reply);
586 return BLUETOOTH_ERROR_NONE;
589 static int __bt_avrcp_control_parse_properties(
590 media_metadata_attributes_t *metadata,
593 GVariant *value = NULL;
595 char *value_string = NULL;
596 unsigned int value_uint;
597 const char *key = NULL;
599 g_variant_iter_init(&iter, item);
600 while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) {
601 if (strcasecmp(key, "Title") == 0) {
602 value_string = (char *)g_variant_get_string(value, NULL);
603 BT_DBG("Value : %s ", value_string);
604 metadata->title = g_strdup(value_string);
605 } else if (strcasecmp(key, "Artist") == 0) {
606 value_string = (char *)g_variant_get_string(value, NULL);
607 BT_DBG("Value : %s ", value_string);
608 metadata->artist = g_strdup(value_string);
609 } else if (strcasecmp(key, "Album") == 0) {
610 value_string = (char *)g_variant_get_string(value, NULL);
611 BT_DBG("Value : %s ", value_string);
612 metadata->album = g_strdup(value_string);
613 } else if (strcasecmp(key, "Genre") == 0) {
614 value_string = (char *)g_variant_get_string(value, NULL);
615 BT_DBG("Value : %s ", value_string);
616 metadata->genre = g_strdup(value_string);
617 } else if (strcasecmp(key, "Duration") == 0) {
618 value_uint = g_variant_get_uint32(value);
619 BT_DBG("Duration : %d", value_uint);
620 metadata->duration = value_uint;
621 } else if (strcasecmp(key, "NumberOfTracks") == 0) {
622 value_uint = g_variant_get_uint32(value);
623 metadata->total_tracks = value_uint;
624 } else if (strcasecmp(key, "TrackNumber") == 0) {
625 value_uint = g_variant_get_uint32(value);
626 metadata->number = value_uint;
628 BT_DBG("%s not supported, ignoring", key);
631 if (!metadata->title)
632 metadata->title = g_strdup("");
633 if (!metadata->artist)
634 metadata->artist = g_strdup("");
635 if (!metadata->album)
636 metadata->album = g_strdup("");
637 if (!metadata->genre)
638 metadata->genre = g_strdup("");
640 return BLUETOOTH_ERROR_NONE;
644 int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata)
646 GDBusProxy *proxy = NULL;
647 GVariant *reply = NULL;
648 GVariant *item = NULL;
650 GDBusConnection *conn = NULL;
651 char *control_path = NULL;
652 char *interface_name = NULL;
653 char *property_name = NULL;
654 GVariant *parameters = NULL;
655 int ret = BLUETOOTH_ERROR_NONE;
657 retv_if(metadata == NULL, BLUETOOTH_ERROR_INTERNAL);
659 conn = _bt_gdbus_get_system_gconn();
660 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
662 control_path = __bt_get_control_device_path();
663 retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
664 BT_DBG("control_path %s", control_path);
666 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
667 BT_BLUEZ_NAME, control_path,
668 BT_PROPERTIES_INTERFACE, NULL, &err);
670 BT_ERR("Unable to allocate new proxy \n");
672 BT_ERR("%s", err->message);
675 return BLUETOOTH_ERROR_INTERNAL;
678 interface_name = g_strdup(BT_PLAYER_CONTROL_INTERFACE);
679 property_name = g_strdup("Track");
681 parameters = g_variant_new("(ss)", interface_name, property_name);
683 g_free(interface_name);
684 g_free(property_name);
686 reply = g_dbus_proxy_call_sync(proxy, "Get", parameters,
687 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
689 g_object_unref(proxy);
692 BT_ERR("Error returned in method call");
694 BT_ERR("%s", err->message);
697 return BLUETOOTH_ERROR_INTERNAL;
700 g_variant_get(reply, "(v)", &item);
702 ret = __bt_avrcp_control_parse_properties(metadata, item);
704 g_variant_unref(reply);
709 void _bt_handle_avrcp_control_event(GVariant *reply, const char *path)
711 GVariant *param = NULL;
712 const char *property = NULL;
715 BT_ERR("Error returned in method call\n");
720 GVariant *value = NULL;
721 g_variant_iter_init(&iter, reply);
722 while (g_variant_iter_loop(&iter, "{sv}", &property,
724 if ((strcasecmp(property, "Equalizer") == 0) ||
725 (strcasecmp(property, "Repeat") == 0) ||
726 (strcasecmp(property, "Shuffle") == 0) ||
727 (strcasecmp(property, "Scan") == 0) ||
728 (strcasecmp(property, "Status") == 0)) {
730 unsigned int type, val = 0;
732 valstr = g_variant_get_string(value, NULL);
733 BT_DBG("Value : %s ", valstr);
734 type = __bt_media_attr_to_type(property);
736 val = __bt_media_attrval_to_val(type, valstr);
738 /* Send event to application */
739 param = g_variant_new("(u)", val);
740 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
741 __bt_media_attr_to_event(property), param);
742 } else if (strcasecmp(property, "Position") == 0) {
745 val = g_variant_get_uint32(value);
746 BT_DBG("Value : %d ", val);
748 /* Send event to application */
749 param = g_variant_new("(u)", val);
750 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
751 __bt_media_attr_to_event(property), param);
752 } else if (strcasecmp(property, "Track") == 0) {
753 int ret = BLUETOOTH_ERROR_NONE;
754 media_metadata_attributes_t metadata;
756 memset(&metadata, 0x00, sizeof(media_metadata_attributes_t));
758 ret = __bt_avrcp_control_parse_properties(
760 if (BLUETOOTH_ERROR_NONE != ret) {
761 /* Free key and value because of break unless free not required */
762 free((char *)property);
763 g_variant_unref(value);
764 g_free((char *)metadata.title);
765 g_free((char *)metadata.artist);
766 g_free((char *)metadata.album);
767 g_free((char *)metadata.genre);
771 /* Send event to application */
772 param = g_variant_new("(ssssuuu)",
777 metadata.total_tracks,
780 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
781 BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED, param);
783 g_free((char *)metadata.title);
784 g_free((char *)metadata.artist);
785 g_free((char *)metadata.album);
786 g_free((char *)metadata.genre);
788 BT_DBG("Property not handled");