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;
58 void _bt_set_control_device_path(const char *path)
63 g_free(avrcp_control_path);
64 BT_DBG("control_path = %s", path);
65 avrcp_control_path = g_strdup(path);
68 void _bt_remove_control_device_path(const char *path)
72 if (avrcp_control_path &&
73 !g_strcmp0(avrcp_control_path, path)) {
74 BT_DBG("control_path = %s", path);
75 g_free(avrcp_control_path);
76 avrcp_control_path = NULL;
80 static char *__bt_get_control_device_path(void)
84 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
88 if (avrcp_control_path != NULL)
89 return avrcp_control_path;
91 retv_if(!_bt_is_headset_type_connected(BT_AVRCP,
92 connected_address), NULL);
94 BT_DBG("device address = %s", connected_address);
96 adapter_path = _bt_get_device_object_path(connected_address);
97 retv_if(adapter_path == NULL, NULL);
99 control_path = g_strdup_printf(BT_MEDIA_CONTROL_PATH, adapter_path);
100 g_free(adapter_path);
102 avrcp_control_path = control_path;
103 BT_DBG("control_path = %s", control_path);
107 static int __bt_media_send_control_msg(const char *name)
109 GVariant *reply = NULL;
111 GDBusConnection *conn = NULL;
112 GDBusProxy *proxy = NULL;
113 char *control_path = NULL;
115 retv_if(name == NULL, BLUETOOTH_ERROR_INTERNAL);
117 BT_INFO("Command [%s]", name);
119 conn = _bt_gdbus_get_system_gconn();
120 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
122 control_path = __bt_get_control_device_path();
123 retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
124 BT_DBG("control_path %s", control_path);
126 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
127 BT_BLUEZ_NAME, control_path,
128 BT_PLAYER_CONTROL_INTERFACE, NULL, &err);
130 BT_ERR("Unable to allocate new proxy \n");
132 BT_ERR("%s", err->message);
135 return BLUETOOTH_ERROR_INTERNAL;
138 reply = g_dbus_proxy_call_sync(proxy, name, NULL,
139 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
141 g_object_unref(proxy);
144 BT_ERR("Error returned in method call");
146 BT_ERR("%s", err->message);
149 return BLUETOOTH_ERROR_INTERNAL;
152 g_variant_unref(reply);
155 return BLUETOOTH_ERROR_NONE;
158 int _bt_avrcp_control_cmd(int type)
160 int ret = BLUETOOTH_ERROR_INTERNAL;
165 ret = __bt_media_send_control_msg("Play");
168 ret = __bt_media_send_control_msg("Pause");
171 ret = __bt_media_send_control_msg("Stop");
174 ret = __bt_media_send_control_msg("Next");
177 ret = __bt_media_send_control_msg("Previous");
179 case PRESS_FAST_FORWARD:
180 ret = __bt_media_send_control_msg("PressFastForward");
182 case RELEASE_FAST_FORWARD:
183 ret = __bt_media_send_control_msg("ReleaseFastForward");
186 ret = __bt_media_send_control_msg("PressRewind");
189 ret = __bt_media_send_control_msg("ReleaseRewind");
192 BT_DBG("Invalid Type\n");
193 return BLUETOOTH_ERROR_INTERNAL;
199 GDBusProxy *__bt_get_control_properties_proxy(void)
201 GDBusProxy *proxy = NULL;
202 GError *error = NULL;
203 char *control_path = NULL;
204 GDBusConnection *conn = NULL;
206 control_path = __bt_get_control_device_path();
207 retv_if(control_path == NULL, NULL);
208 BT_DBG("control_path = %s", control_path);
210 conn = _bt_gdbus_get_system_gconn();
211 retv_if(conn == NULL, NULL);
213 proxy = g_dbus_proxy_new_sync(conn,
214 G_DBUS_PROXY_FLAGS_NONE, NULL,
215 BT_BLUEZ_NAME, control_path,
216 BT_PROPERTIES_INTERFACE, NULL, &error);
218 BT_ERR("Unable to allocate new proxy");
220 BT_ERR("%s", error->message);
221 g_clear_error(&error);
229 static int __bt_media_attr_to_event(const char *str)
231 if (!strcasecmp(str, "Equalizer"))
232 return BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS;
233 else if (!strcasecmp(str, "Repeat"))
234 return BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS;
235 else if (!strcasecmp(str, "Shuffle"))
236 return BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS;
237 else if (!strcasecmp(str, "Scan"))
238 return BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS;
239 else if (!strcasecmp(str, "Position"))
240 return BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS;
241 else if (!strcasecmp(str, "Track"))
242 return BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED;
243 else if (!strcasecmp(str, "Status"))
244 return BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED;
249 static int __bt_media_attr_to_type(const char *str)
251 if (!strcasecmp(str, "Equalizer"))
253 else if (!strcasecmp(str, "Repeat"))
255 else if (!strcasecmp(str, "Shuffle"))
257 else if (!strcasecmp(str, "Scan"))
259 else if (!strcasecmp(str, "Position"))
261 else if (!strcasecmp(str, "Track"))
263 else if (!strcasecmp(str, "Status"))
269 static const char *__bt_media_type_to_str(int type)
290 static int __bt_media_attrval_to_val(int type, const char *value)
296 if (!strcmp(value, "off"))
298 else if (!strcmp(value, "on"))
301 ret = EQUALIZER_INVALID;
305 if (!strcmp(value, "off"))
306 ret = REPEAT_MODE_OFF;
307 else if (!strcmp(value, "singletrack"))
308 ret = REPEAT_SINGLE_TRACK;
309 else if (!strcmp(value, "alltracks"))
310 ret = REPEAT_ALL_TRACK;
311 else if (!strcmp(value, "group"))
314 ret = REPEAT_INVALID;
318 if (!strcmp(value, "off"))
319 ret = SHUFFLE_MODE_OFF;
320 else if (!strcmp(value, "alltracks"))
321 ret = SHUFFLE_ALL_TRACK;
322 else if (!strcmp(value, "group"))
325 ret = SHUFFLE_INVALID;
329 if (!strcmp(value, "off"))
331 else if (!strcmp(value, "alltracks"))
332 ret = SCAN_ALL_TRACK;
333 else if (!strcmp(value, "group"))
340 if (!strcmp(value, "stopped"))
341 ret = STATUS_STOPPED;
342 else if (!strcmp(value, "playing"))
343 ret = STATUS_PLAYING;
344 else if (!strcmp(value, "paused"))
346 else if (!strcmp(value, "forward-seek"))
347 ret = STATUS_FORWARD_SEEK;
348 else if (!strcmp(value, "reverse-seek"))
349 ret = STATUS_REVERSE_SEEK;
350 else if (!strcmp(value, "error"))
353 ret = STATUS_INVALID;
358 int _bt_avrcp_control_get_property(int type, unsigned int *value)
360 GDBusProxy *proxy = NULL;
362 int ret = BLUETOOTH_ERROR_NONE;
364 GVariant *reply = NULL;
365 GVariant *temp = NULL;
367 BT_CHECK_PARAMETER(value, return);
369 proxy = __bt_get_control_properties_proxy();
370 retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
372 reply = g_dbus_proxy_call_sync(proxy,
373 "Get", g_variant_new("(ss)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type)),
374 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
376 g_object_unref(proxy);
379 BT_ERR("Can't get managed objects");
381 BT_ERR("%s", err->message);
384 return BLUETOOTH_ERROR_INTERNAL;
392 name = (char *)g_variant_get_data(reply);
394 *value = __bt_media_attrval_to_val(type, name);
395 BT_INFO("Type[%s] and Value[%s]", __bt_media_type_to_str(type), name);
398 g_variant_get(reply, "(v)", &temp);
399 *value = g_variant_get_uint32(temp);
400 g_variant_unref(temp);
401 BT_INFO("Type[%s] and Value[%d]", __bt_media_type_to_str(type), *value);
404 BT_ERR("Invalid Type [%d]", type);
405 ret = BLUETOOTH_ERROR_INTERNAL;
408 g_variant_unref(reply);
412 int _bt_avrcp_control_set_property(int type, unsigned int value)
414 GValue *attr_value = NULL;
415 GDBusProxy *proxy = NULL;
416 GError *error = NULL;
417 GVariant *reply, *param;
419 g_value_init(attr_value, G_TYPE_STRING);
423 param = g_variant_new("s", equalizer_status[value].property);
424 BT_INFO("equalizer_status %s", equalizer_status[value].property);
427 param = g_variant_new("s", repeat_status[value].property);
428 BT_INFO("repeat_status %s", repeat_status[value].property);
431 param = g_variant_new("s", shuffle_settings[value].property);
432 BT_INFO("shuffle_settings %s", shuffle_settings[value].property);
435 param = g_variant_new("s", scan_status[value].property);
436 BT_INFO("scan_status %s", scan_status[value].property);
439 BT_ERR("Invalid property type: %d", type);
440 g_value_unset(attr_value);
441 return BLUETOOTH_ERROR_INTERNAL;
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 "Set", g_variant_new("(ssv)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type), param),
449 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
451 g_object_unref(proxy);
452 g_variant_unref(param);
455 BT_ERR("Can't get managed objects");
457 BT_ERR("SetProperty Fail: %s", error->message);
458 g_clear_error(&error);
459 return BLUETOOTH_ERROR_INTERNAL;
463 g_variant_unref(reply);
464 g_value_unset(attr_value);
466 return BLUETOOTH_ERROR_NONE;
469 static int __bt_avrcp_control_parse_properties(
470 media_metadata_attributes_t *metadata,
473 GVariant *value = NULL;
475 char *value_string = NULL;
476 unsigned int value_uint;
477 const char *key = NULL;
479 g_variant_iter_init(&iter, item);
480 while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) {
481 if (strcasecmp(key, "Title") == 0) {
482 value_string = (char *)g_variant_get_string(value, NULL);
483 BT_DBG("Value : %s ", value_string);
484 metadata->title = g_strdup(value_string);
485 } else if (strcasecmp(key, "Artist") == 0) {
486 value_string = (char *)g_variant_get_string(value, NULL);
487 BT_DBG("Value : %s ", value_string);
488 metadata->artist = g_strdup(value_string);
489 } else if (strcasecmp(key, "Album") == 0) {
490 value_string = (char *)g_variant_get_string(value, NULL);
491 BT_DBG("Value : %s ", value_string);
492 metadata->album = g_strdup(value_string);
493 } else if (strcasecmp(key, "Genre") == 0) {
494 value_string = (char *)g_variant_get_string(value, NULL);
495 BT_DBG("Value : %s ", value_string);
496 metadata->genre = g_strdup(value_string);
497 } else if (strcasecmp(key, "Duration") == 0) {
498 value_uint = g_variant_get_uint32(value);
499 metadata->duration = value_uint;
500 } else if (strcasecmp(key, "NumberOfTracks") == 0) {
501 value_uint = g_variant_get_uint32(value);
502 metadata->total_tracks = value_uint;
503 } else if (strcasecmp(key, "TrackNumber") == 0) {
504 value_uint = g_variant_get_uint32(value);
505 metadata->number = value_uint;
507 BT_DBG("%s not supported, ignoring", key);
510 if (!metadata->title)
511 metadata->title = g_strdup("");
512 if (!metadata->artist)
513 metadata->artist = g_strdup("");
514 if (!metadata->album)
515 metadata->album = g_strdup("");
516 if (!metadata->genre)
517 metadata->genre = g_strdup("");
519 return BLUETOOTH_ERROR_NONE;
523 int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata)
525 GDBusProxy *proxy = NULL;
526 GVariant *reply = NULL;
527 GVariant *item = NULL;
529 GDBusConnection *conn = NULL;
530 char *control_path = NULL;
531 char *interface_name = NULL;
532 char *property_name = NULL;
533 GVariant *parameters = NULL;
534 int ret = BLUETOOTH_ERROR_NONE;
536 retv_if(metadata == NULL, BLUETOOTH_ERROR_INTERNAL);
538 conn = _bt_gdbus_get_system_gconn();
539 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
541 control_path = __bt_get_control_device_path();
542 retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
543 BT_DBG("control_path %s", control_path);
545 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
546 BT_BLUEZ_NAME, control_path,
547 BT_PROPERTIES_INTERFACE, NULL, &err);
549 BT_ERR("Unable to allocate new proxy \n");
551 BT_ERR("%s", err->message);
554 return BLUETOOTH_ERROR_INTERNAL;
557 interface_name = g_strdup(BT_PLAYER_CONTROL_INTERFACE);
558 property_name = g_strdup("Track");
560 parameters = g_variant_new("(ss)", interface_name, property_name);
562 g_free(interface_name);
563 g_free(property_name);
565 reply = g_dbus_proxy_call_sync(proxy, "Get", parameters,
566 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
568 g_object_unref(proxy);
571 BT_ERR("Error returned in method call");
573 BT_ERR("%s", err->message);
576 return BLUETOOTH_ERROR_INTERNAL;
579 g_variant_get(reply, "(v)", &item);
581 ret = __bt_avrcp_control_parse_properties(metadata, item);
583 g_variant_unref(reply);
588 void _bt_handle_avrcp_control_event(GVariant *reply, const char *path)
590 GVariant *param = NULL;
591 const char *property = NULL;
594 BT_ERR("Error returned in method call\n");
599 GVariant *value = NULL;
600 g_variant_iter_init(&iter, reply);
601 while (g_variant_iter_loop(&iter, "{sv}", &property,
603 if ((strcasecmp(property, "Equalizer") == 0) ||
604 (strcasecmp(property, "Repeat") == 0) ||
605 (strcasecmp(property, "Shuffle") == 0) ||
606 (strcasecmp(property, "Scan") == 0) ||
607 (strcasecmp(property, "Status") == 0)) {
609 unsigned int type, val = 0;
611 valstr = g_variant_get_string(value, NULL);
612 BT_DBG("Value : %s ", valstr);
613 type = __bt_media_attr_to_type(property);
615 val = __bt_media_attrval_to_val(type, valstr);
617 /* Send event to application */
618 param = g_variant_new("(u)", val);
619 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
620 __bt_media_attr_to_event(property), param);
621 } else if (strcasecmp(property, "Position") == 0) {
624 val = g_variant_get_uint32(value);
625 BT_DBG("Value : %d ", val);
627 /* Send event to application */
628 param = g_variant_new("(u)", val);
629 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
630 __bt_media_attr_to_event(property), param);
631 } else if (strcasecmp(property, "Track") == 0) {
632 int ret = BLUETOOTH_ERROR_NONE;
633 media_metadata_attributes_t metadata;
635 memset(&metadata, 0x00, sizeof(media_metadata_attributes_t));
637 ret = __bt_avrcp_control_parse_properties(
639 if (BLUETOOTH_ERROR_NONE != ret) {
640 /* Free key and value because of break unless free not required */
641 free((char *)property);
642 g_variant_unref(value);
643 g_free((char *)metadata.title);
644 g_free((char *)metadata.artist);
645 g_free((char *)metadata.album);
646 g_free((char *)metadata.genre);
650 /* Send event to application */
651 param = g_variant_new("(ssssuuu)",
656 metadata.total_tracks,
659 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
660 BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED, param);
662 g_free((char *)metadata.title);
663 g_free((char *)metadata.artist);
664 g_free((char *)metadata.album);
665 g_free((char *)metadata.genre);
667 BT_DBG("Property not handled");