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 BT_DBG("Duration : %d", value_uint);
500 metadata->duration = value_uint;
501 } else if (strcasecmp(key, "NumberOfTracks") == 0) {
502 value_uint = g_variant_get_uint32(value);
503 metadata->total_tracks = value_uint;
504 } else if (strcasecmp(key, "TrackNumber") == 0) {
505 value_uint = g_variant_get_uint32(value);
506 metadata->number = value_uint;
508 BT_DBG("%s not supported, ignoring", key);
511 if (!metadata->title)
512 metadata->title = g_strdup("");
513 if (!metadata->artist)
514 metadata->artist = g_strdup("");
515 if (!metadata->album)
516 metadata->album = g_strdup("");
517 if (!metadata->genre)
518 metadata->genre = g_strdup("");
520 return BLUETOOTH_ERROR_NONE;
524 int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata)
526 GDBusProxy *proxy = NULL;
527 GVariant *reply = NULL;
528 GVariant *item = NULL;
530 GDBusConnection *conn = NULL;
531 char *control_path = NULL;
532 char *interface_name = NULL;
533 char *property_name = NULL;
534 GVariant *parameters = NULL;
535 int ret = BLUETOOTH_ERROR_NONE;
537 retv_if(metadata == NULL, BLUETOOTH_ERROR_INTERNAL);
539 conn = _bt_gdbus_get_system_gconn();
540 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
542 control_path = __bt_get_control_device_path();
543 retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
544 BT_DBG("control_path %s", control_path);
546 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
547 BT_BLUEZ_NAME, control_path,
548 BT_PROPERTIES_INTERFACE, NULL, &err);
550 BT_ERR("Unable to allocate new proxy \n");
552 BT_ERR("%s", err->message);
555 return BLUETOOTH_ERROR_INTERNAL;
558 interface_name = g_strdup(BT_PLAYER_CONTROL_INTERFACE);
559 property_name = g_strdup("Track");
561 parameters = g_variant_new("(ss)", interface_name, property_name);
563 g_free(interface_name);
564 g_free(property_name);
566 reply = g_dbus_proxy_call_sync(proxy, "Get", parameters,
567 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
569 g_object_unref(proxy);
572 BT_ERR("Error returned in method call");
574 BT_ERR("%s", err->message);
577 return BLUETOOTH_ERROR_INTERNAL;
580 g_variant_get(reply, "(v)", &item);
582 ret = __bt_avrcp_control_parse_properties(metadata, item);
584 g_variant_unref(reply);
589 void _bt_handle_avrcp_control_event(GVariant *reply, const char *path)
591 GVariant *param = NULL;
592 const char *property = NULL;
595 BT_ERR("Error returned in method call\n");
600 GVariant *value = NULL;
601 g_variant_iter_init(&iter, reply);
602 while (g_variant_iter_loop(&iter, "{sv}", &property,
604 if ((strcasecmp(property, "Equalizer") == 0) ||
605 (strcasecmp(property, "Repeat") == 0) ||
606 (strcasecmp(property, "Shuffle") == 0) ||
607 (strcasecmp(property, "Scan") == 0) ||
608 (strcasecmp(property, "Status") == 0)) {
610 unsigned int type, val = 0;
612 valstr = g_variant_get_string(value, NULL);
613 BT_DBG("Value : %s ", valstr);
614 type = __bt_media_attr_to_type(property);
616 val = __bt_media_attrval_to_val(type, valstr);
618 /* Send event to application */
619 param = g_variant_new("(u)", val);
620 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
621 __bt_media_attr_to_event(property), param);
622 } else if (strcasecmp(property, "Position") == 0) {
625 val = g_variant_get_uint32(value);
626 BT_DBG("Value : %d ", val);
628 /* Send event to application */
629 param = g_variant_new("(u)", val);
630 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
631 __bt_media_attr_to_event(property), param);
632 } else if (strcasecmp(property, "Track") == 0) {
633 int ret = BLUETOOTH_ERROR_NONE;
634 media_metadata_attributes_t metadata;
636 memset(&metadata, 0x00, sizeof(media_metadata_attributes_t));
638 ret = __bt_avrcp_control_parse_properties(
640 if (BLUETOOTH_ERROR_NONE != ret) {
641 /* Free key and value because of break unless free not required */
642 free((char *)property);
643 g_variant_unref(value);
644 g_free((char *)metadata.title);
645 g_free((char *)metadata.artist);
646 g_free((char *)metadata.album);
647 g_free((char *)metadata.genre);
651 /* Send event to application */
652 param = g_variant_new("(ssssuuu)",
657 metadata.total_tracks,
660 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
661 BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED, param);
663 g_free((char *)metadata.title);
664 g_free((char *)metadata.artist);
665 g_free((char *)metadata.album);
666 g_free((char *)metadata.genre);
668 BT_DBG("Property not handled");