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 BT_DBG("Invalid Type\n");
221 return BLUETOOTH_ERROR_INTERNAL;
227 GDBusProxy *__bt_get_control_properties_proxy(void)
229 GDBusProxy *proxy = NULL;
230 GError *error = NULL;
231 char *control_path = NULL;
232 GDBusConnection *conn = NULL;
234 control_path = __bt_get_control_device_path();
235 retv_if(control_path == NULL, NULL);
236 BT_DBG("control_path = %s", control_path);
238 conn = _bt_gdbus_get_system_gconn();
239 retv_if(conn == NULL, NULL);
241 proxy = g_dbus_proxy_new_sync(conn,
242 G_DBUS_PROXY_FLAGS_NONE, NULL,
243 BT_BLUEZ_NAME, control_path,
244 BT_PROPERTIES_INTERFACE, NULL, &error);
246 BT_ERR("Unable to allocate new proxy");
248 BT_ERR("%s", error->message);
249 g_clear_error(&error);
257 GDBusProxy *__bt_get_transport_properties_proxy(void)
259 GDBusProxy *proxy = NULL;
260 GError *error = NULL;
261 char *transport_path = NULL;
262 GDBusConnection *conn = NULL;
264 transport_path = __bt_get_transport_device_path();
265 retv_if(transport_path == NULL, NULL);
266 BT_DBG("transport_path = %s", transport_path);
268 conn = _bt_gdbus_get_system_gconn();
269 retv_if(conn == NULL, NULL);
271 proxy = g_dbus_proxy_new_sync(conn,
272 G_DBUS_PROXY_FLAGS_NONE, NULL,
273 BT_BLUEZ_NAME, transport_path,
274 BT_PROPERTIES_INTERFACE, NULL, &error);
276 BT_ERR("Unable to allocate new proxy");
278 BT_ERR("%s", error->message);
279 g_clear_error(&error);
287 static int __bt_media_attr_to_event(const char *str)
289 if (!strcasecmp(str, "Equalizer"))
290 return BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS;
291 else if (!strcasecmp(str, "Repeat"))
292 return BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS;
293 else if (!strcasecmp(str, "Shuffle"))
294 return BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS;
295 else if (!strcasecmp(str, "Scan"))
296 return BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS;
297 else if (!strcasecmp(str, "Position"))
298 return BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS;
299 else if (!strcasecmp(str, "Track"))
300 return BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED;
301 else if (!strcasecmp(str, "Status"))
302 return BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED;
307 static int __bt_media_attr_to_type(const char *str)
309 if (!strcasecmp(str, "Equalizer"))
311 else if (!strcasecmp(str, "Repeat"))
313 else if (!strcasecmp(str, "Shuffle"))
315 else if (!strcasecmp(str, "Scan"))
317 else if (!strcasecmp(str, "Position"))
319 else if (!strcasecmp(str, "Track"))
321 else if (!strcasecmp(str, "Status"))
327 static const char *__bt_media_type_to_str(int type)
348 static const char *__bt_transport_type_to_str(int type)
359 static int __bt_media_attrval_to_val(int type, const char *value)
365 if (!strcmp(value, "off"))
367 else if (!strcmp(value, "on"))
370 ret = EQUALIZER_INVALID;
374 if (!strcmp(value, "off"))
375 ret = REPEAT_MODE_OFF;
376 else if (!strcmp(value, "singletrack"))
377 ret = REPEAT_SINGLE_TRACK;
378 else if (!strcmp(value, "alltracks"))
379 ret = REPEAT_ALL_TRACK;
380 else if (!strcmp(value, "group"))
383 ret = REPEAT_INVALID;
387 if (!strcmp(value, "off"))
388 ret = SHUFFLE_MODE_OFF;
389 else if (!strcmp(value, "alltracks"))
390 ret = SHUFFLE_ALL_TRACK;
391 else if (!strcmp(value, "group"))
394 ret = SHUFFLE_INVALID;
398 if (!strcmp(value, "off"))
400 else if (!strcmp(value, "alltracks"))
401 ret = SCAN_ALL_TRACK;
402 else if (!strcmp(value, "group"))
409 if (!strcmp(value, "stopped"))
410 ret = STATUS_STOPPED;
411 else if (!strcmp(value, "playing"))
412 ret = STATUS_PLAYING;
413 else if (!strcmp(value, "paused"))
415 else if (!strcmp(value, "forward-seek"))
416 ret = STATUS_FORWARD_SEEK;
417 else if (!strcmp(value, "reverse-seek"))
418 ret = STATUS_REVERSE_SEEK;
419 else if (!strcmp(value, "error"))
422 ret = STATUS_INVALID;
427 int _bt_avrcp_control_get_property(int type, unsigned int *value)
429 GDBusProxy *proxy = NULL;
431 int ret = BLUETOOTH_ERROR_NONE;
433 GVariant *reply = NULL;
434 GVariant *temp = NULL;
436 BT_CHECK_PARAMETER(value, return);
438 proxy = __bt_get_control_properties_proxy();
439 retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
441 reply = g_dbus_proxy_call_sync(proxy,
442 "Get", g_variant_new("(ss)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type)),
443 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
445 g_object_unref(proxy);
448 BT_ERR("Can't get managed objects");
450 BT_ERR("%s", err->message);
453 return BLUETOOTH_ERROR_INTERNAL;
461 name = (char *)g_variant_get_data(reply);
463 *value = __bt_media_attrval_to_val(type, name);
464 BT_INFO("Type[%s] and Value[%s]", __bt_media_type_to_str(type), name);
467 g_variant_get(reply, "(v)", &temp);
468 *value = g_variant_get_uint32(temp);
469 g_variant_unref(temp);
470 BT_INFO("Type[%s] and Value[%d]", __bt_media_type_to_str(type), *value);
473 BT_ERR("Invalid Type [%d]", type);
474 ret = BLUETOOTH_ERROR_INTERNAL;
477 g_variant_unref(reply);
481 int _bt_avrcp_control_set_property(int type, unsigned int value)
483 GValue *attr_value = NULL;
484 GDBusProxy *proxy = NULL;
485 GError *error = NULL;
486 GVariant *reply, *param;
488 g_value_init(attr_value, G_TYPE_STRING);
492 param = g_variant_new("s", equalizer_status[value].property);
493 BT_INFO("equalizer_status %s", equalizer_status[value].property);
496 param = g_variant_new("s", repeat_status[value].property);
497 BT_INFO("repeat_status %s", repeat_status[value].property);
500 param = g_variant_new("s", shuffle_settings[value].property);
501 BT_INFO("shuffle_settings %s", shuffle_settings[value].property);
504 param = g_variant_new("s", scan_status[value].property);
505 BT_INFO("scan_status %s", scan_status[value].property);
508 BT_ERR("Invalid property type: %d", type);
509 g_value_unset(attr_value);
510 return BLUETOOTH_ERROR_INTERNAL;
513 proxy = __bt_get_control_properties_proxy();
514 retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
516 reply = g_dbus_proxy_call_sync(proxy,
517 "Set", g_variant_new("(ssv)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type), param),
518 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
520 g_object_unref(proxy);
521 g_variant_unref(param);
524 BT_ERR("Can't get managed objects");
526 BT_ERR("SetProperty Fail: %s", error->message);
527 g_clear_error(&error);
528 return BLUETOOTH_ERROR_INTERNAL;
532 g_variant_unref(reply);
533 g_value_unset(attr_value);
535 return BLUETOOTH_ERROR_NONE;
538 int _bt_avrcp_transport_set_property(int type, unsigned int value)
540 GValue *attr_value = NULL;
541 GDBusProxy *proxy = NULL;
542 GError *error = NULL;
543 GVariant *reply, *param;
544 uint16_t property_level = (uint16_t)value;
546 g_value_init(attr_value, G_TYPE_STRING);
550 param = g_variant_new("q", property_level);
551 BT_INFO("delay level %d", property_level);
554 param = g_variant_new("q", property_level);
555 BT_INFO("volume level %d", property_level);
558 BT_ERR("Invalid property type: %d", type);
559 g_value_unset(attr_value);
560 return BLUETOOTH_ERROR_INTERNAL;
563 proxy = __bt_get_transport_properties_proxy();
564 retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
566 reply = g_dbus_proxy_call_sync(proxy,
567 "Set", g_variant_new("(ssv)", BT_MEDIATRANSPORT_INTERFACE, __bt_transport_type_to_str(type), param),
568 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
570 g_object_unref(proxy);
571 g_variant_unref(param);
574 BT_ERR("Can't get managed objects");
576 BT_ERR("SetProperty Fail: %s", error->message);
577 g_clear_error(&error);
578 return BLUETOOTH_ERROR_INTERNAL;
582 g_variant_unref(reply);
583 g_value_unset(attr_value);
585 return BLUETOOTH_ERROR_NONE;
588 static int __bt_avrcp_control_parse_properties(
589 media_metadata_attributes_t *metadata,
592 GVariant *value = NULL;
594 char *value_string = NULL;
595 unsigned int value_uint;
596 const char *key = NULL;
598 g_variant_iter_init(&iter, item);
599 while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) {
600 if (strcasecmp(key, "Title") == 0) {
601 value_string = (char *)g_variant_get_string(value, NULL);
602 BT_DBG("Value : %s ", value_string);
603 metadata->title = g_strdup(value_string);
604 } else if (strcasecmp(key, "Artist") == 0) {
605 value_string = (char *)g_variant_get_string(value, NULL);
606 BT_DBG("Value : %s ", value_string);
607 metadata->artist = g_strdup(value_string);
608 } else if (strcasecmp(key, "Album") == 0) {
609 value_string = (char *)g_variant_get_string(value, NULL);
610 BT_DBG("Value : %s ", value_string);
611 metadata->album = g_strdup(value_string);
612 } else if (strcasecmp(key, "Genre") == 0) {
613 value_string = (char *)g_variant_get_string(value, NULL);
614 BT_DBG("Value : %s ", value_string);
615 metadata->genre = g_strdup(value_string);
616 } else if (strcasecmp(key, "Duration") == 0) {
617 value_uint = g_variant_get_uint32(value);
618 BT_DBG("Duration : %d", value_uint);
619 metadata->duration = value_uint;
620 } else if (strcasecmp(key, "NumberOfTracks") == 0) {
621 value_uint = g_variant_get_uint32(value);
622 metadata->total_tracks = value_uint;
623 } else if (strcasecmp(key, "TrackNumber") == 0) {
624 value_uint = g_variant_get_uint32(value);
625 metadata->number = value_uint;
627 BT_DBG("%s not supported, ignoring", key);
630 if (!metadata->title)
631 metadata->title = g_strdup("");
632 if (!metadata->artist)
633 metadata->artist = g_strdup("");
634 if (!metadata->album)
635 metadata->album = g_strdup("");
636 if (!metadata->genre)
637 metadata->genre = g_strdup("");
639 return BLUETOOTH_ERROR_NONE;
643 int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata)
645 GDBusProxy *proxy = NULL;
646 GVariant *reply = NULL;
647 GVariant *item = NULL;
649 GDBusConnection *conn = NULL;
650 char *control_path = NULL;
651 char *interface_name = NULL;
652 char *property_name = NULL;
653 GVariant *parameters = NULL;
654 int ret = BLUETOOTH_ERROR_NONE;
656 retv_if(metadata == NULL, BLUETOOTH_ERROR_INTERNAL);
658 conn = _bt_gdbus_get_system_gconn();
659 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
661 control_path = __bt_get_control_device_path();
662 retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
663 BT_DBG("control_path %s", control_path);
665 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
666 BT_BLUEZ_NAME, control_path,
667 BT_PROPERTIES_INTERFACE, NULL, &err);
669 BT_ERR("Unable to allocate new proxy \n");
671 BT_ERR("%s", err->message);
674 return BLUETOOTH_ERROR_INTERNAL;
677 interface_name = g_strdup(BT_PLAYER_CONTROL_INTERFACE);
678 property_name = g_strdup("Track");
680 parameters = g_variant_new("(ss)", interface_name, property_name);
682 g_free(interface_name);
683 g_free(property_name);
685 reply = g_dbus_proxy_call_sync(proxy, "Get", parameters,
686 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
688 g_object_unref(proxy);
691 BT_ERR("Error returned in method call");
693 BT_ERR("%s", err->message);
696 return BLUETOOTH_ERROR_INTERNAL;
699 g_variant_get(reply, "(v)", &item);
701 ret = __bt_avrcp_control_parse_properties(metadata, item);
703 g_variant_unref(reply);
708 void _bt_handle_avrcp_control_event(GVariant *reply, const char *path)
710 GVariant *param = NULL;
711 const char *property = NULL;
714 BT_ERR("Error returned in method call\n");
719 GVariant *value = NULL;
720 g_variant_iter_init(&iter, reply);
721 while (g_variant_iter_loop(&iter, "{sv}", &property,
723 if ((strcasecmp(property, "Equalizer") == 0) ||
724 (strcasecmp(property, "Repeat") == 0) ||
725 (strcasecmp(property, "Shuffle") == 0) ||
726 (strcasecmp(property, "Scan") == 0) ||
727 (strcasecmp(property, "Status") == 0)) {
729 unsigned int type, val = 0;
731 valstr = g_variant_get_string(value, NULL);
732 BT_DBG("Value : %s ", valstr);
733 type = __bt_media_attr_to_type(property);
735 val = __bt_media_attrval_to_val(type, valstr);
737 /* Send event to application */
738 param = g_variant_new("(u)", val);
739 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
740 __bt_media_attr_to_event(property), param);
741 } else if (strcasecmp(property, "Position") == 0) {
744 val = g_variant_get_uint32(value);
745 BT_DBG("Value : %d ", val);
747 /* Send event to application */
748 param = g_variant_new("(u)", val);
749 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
750 __bt_media_attr_to_event(property), param);
751 } else if (strcasecmp(property, "Track") == 0) {
752 int ret = BLUETOOTH_ERROR_NONE;
753 media_metadata_attributes_t metadata;
755 memset(&metadata, 0x00, sizeof(media_metadata_attributes_t));
757 ret = __bt_avrcp_control_parse_properties(
759 if (BLUETOOTH_ERROR_NONE != ret) {
760 /* Free key and value because of break unless free not required */
761 free((char *)property);
762 g_variant_unref(value);
763 g_free((char *)metadata.title);
764 g_free((char *)metadata.artist);
765 g_free((char *)metadata.album);
766 g_free((char *)metadata.genre);
770 /* Send event to application */
771 param = g_variant_new("(ssssuuu)",
776 metadata.total_tracks,
779 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
780 BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED, param);
782 g_free((char *)metadata.title);
783 g_free((char *)metadata.artist);
784 g_free((char *)metadata.album);
785 g_free((char *)metadata.genre);
787 BT_DBG("Property not handled");