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 GDBusProxy *proxy = NULL;
541 GError *error = NULL;
542 GVariant *reply, *param;
543 uint16_t property_level = (uint16_t)value;
547 param = g_variant_new("q", property_level);
548 BT_INFO("delay level %d", property_level);
551 param = g_variant_new("q", property_level);
552 BT_INFO("volume level %d", property_level);
555 BT_ERR("Invalid property type: %d", type);
556 return BLUETOOTH_ERROR_INTERNAL;
559 proxy = __bt_get_transport_properties_proxy();
560 retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
562 reply = g_dbus_proxy_call_sync(proxy,
563 "Set", g_variant_new("(ssv)", BT_MEDIATRANSPORT_INTERFACE, __bt_transport_type_to_str(type), param),
564 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
566 g_object_unref(proxy);
567 g_variant_unref(param);
570 BT_ERR("Can't get managed objects");
572 BT_ERR("SetProperty Fail: %s", error->message);
573 g_clear_error(&error);
574 return BLUETOOTH_ERROR_INTERNAL;
578 g_variant_unref(reply);
580 return BLUETOOTH_ERROR_NONE;
583 static int __bt_avrcp_control_parse_properties(
584 media_metadata_attributes_t *metadata,
587 GVariant *value = NULL;
589 char *value_string = NULL;
590 unsigned int value_uint;
591 const char *key = NULL;
593 g_variant_iter_init(&iter, item);
594 while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) {
595 if (strcasecmp(key, "Title") == 0) {
596 value_string = (char *)g_variant_get_string(value, NULL);
597 BT_DBG("Value : %s ", value_string);
598 metadata->title = g_strdup(value_string);
599 } else if (strcasecmp(key, "Artist") == 0) {
600 value_string = (char *)g_variant_get_string(value, NULL);
601 BT_DBG("Value : %s ", value_string);
602 metadata->artist = g_strdup(value_string);
603 } else if (strcasecmp(key, "Album") == 0) {
604 value_string = (char *)g_variant_get_string(value, NULL);
605 BT_DBG("Value : %s ", value_string);
606 metadata->album = g_strdup(value_string);
607 } else if (strcasecmp(key, "Genre") == 0) {
608 value_string = (char *)g_variant_get_string(value, NULL);
609 BT_DBG("Value : %s ", value_string);
610 metadata->genre = g_strdup(value_string);
611 } else if (strcasecmp(key, "Duration") == 0) {
612 value_uint = g_variant_get_uint32(value);
613 BT_DBG("Duration : %d", value_uint);
614 metadata->duration = value_uint;
615 } else if (strcasecmp(key, "NumberOfTracks") == 0) {
616 value_uint = g_variant_get_uint32(value);
617 metadata->total_tracks = value_uint;
618 } else if (strcasecmp(key, "TrackNumber") == 0) {
619 value_uint = g_variant_get_uint32(value);
620 metadata->number = value_uint;
622 BT_DBG("%s not supported, ignoring", key);
625 if (!metadata->title)
626 metadata->title = g_strdup("");
627 if (!metadata->artist)
628 metadata->artist = g_strdup("");
629 if (!metadata->album)
630 metadata->album = g_strdup("");
631 if (!metadata->genre)
632 metadata->genre = g_strdup("");
634 return BLUETOOTH_ERROR_NONE;
638 int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata)
640 GDBusProxy *proxy = NULL;
641 GVariant *reply = NULL;
642 GVariant *item = NULL;
644 GDBusConnection *conn = NULL;
645 char *control_path = NULL;
646 char *interface_name = NULL;
647 char *property_name = NULL;
648 GVariant *parameters = NULL;
649 int ret = BLUETOOTH_ERROR_NONE;
651 retv_if(metadata == NULL, BLUETOOTH_ERROR_INTERNAL);
653 conn = _bt_gdbus_get_system_gconn();
654 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
656 control_path = __bt_get_control_device_path();
657 retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
658 BT_DBG("control_path %s", control_path);
660 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
661 BT_BLUEZ_NAME, control_path,
662 BT_PROPERTIES_INTERFACE, NULL, &err);
664 BT_ERR("Unable to allocate new proxy \n");
666 BT_ERR("%s", err->message);
669 return BLUETOOTH_ERROR_INTERNAL;
672 interface_name = g_strdup(BT_PLAYER_CONTROL_INTERFACE);
673 property_name = g_strdup("Track");
675 parameters = g_variant_new("(ss)", interface_name, property_name);
677 g_free(interface_name);
678 g_free(property_name);
680 reply = g_dbus_proxy_call_sync(proxy, "Get", parameters,
681 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
683 g_object_unref(proxy);
686 BT_ERR("Error returned in method call");
688 BT_ERR("%s", err->message);
691 return BLUETOOTH_ERROR_INTERNAL;
694 g_variant_get(reply, "(v)", &item);
696 ret = __bt_avrcp_control_parse_properties(metadata, item);
698 g_variant_unref(reply);
703 void _bt_handle_avrcp_control_event(GVariant *reply, const char *path)
705 GVariant *param = NULL;
706 const char *property = NULL;
709 BT_ERR("Error returned in method call\n");
714 GVariant *value = NULL;
715 g_variant_iter_init(&iter, reply);
716 while (g_variant_iter_loop(&iter, "{sv}", &property,
718 if ((strcasecmp(property, "Equalizer") == 0) ||
719 (strcasecmp(property, "Repeat") == 0) ||
720 (strcasecmp(property, "Shuffle") == 0) ||
721 (strcasecmp(property, "Scan") == 0) ||
722 (strcasecmp(property, "Status") == 0)) {
724 unsigned int type, val = 0;
726 valstr = g_variant_get_string(value, NULL);
727 BT_DBG("Value : %s ", valstr);
728 type = __bt_media_attr_to_type(property);
730 val = __bt_media_attrval_to_val(type, valstr);
732 /* Send event to application */
733 param = g_variant_new("(u)", val);
734 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
735 __bt_media_attr_to_event(property), param);
736 } else if (strcasecmp(property, "Position") == 0) {
739 val = g_variant_get_uint32(value);
740 BT_DBG("Value : %d ", val);
742 /* Send event to application */
743 param = g_variant_new("(u)", val);
744 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
745 __bt_media_attr_to_event(property), param);
746 } else if (strcasecmp(property, "Track") == 0) {
747 int ret = BLUETOOTH_ERROR_NONE;
748 media_metadata_attributes_t metadata;
750 memset(&metadata, 0x00, sizeof(media_metadata_attributes_t));
752 ret = __bt_avrcp_control_parse_properties(
754 if (BLUETOOTH_ERROR_NONE != ret) {
755 /* Free key and value because of break unless free not required */
756 free((char *)property);
757 g_variant_unref(value);
758 g_free((char *)metadata.title);
759 g_free((char *)metadata.artist);
760 g_free((char *)metadata.album);
761 g_free((char *)metadata.genre);
765 /* Send event to application */
766 param = g_variant_new("(ssssuuu)",
771 metadata.total_tracks,
774 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
775 BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED, param);
777 g_free((char *)metadata.title);
778 g_free((char *)metadata.artist);
779 g_free((char *)metadata.album);
780 g_free((char *)metadata.genre);
782 BT_DBG("Property not handled");