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 ret = __bt_media_send_control_msg("VolumeUp");
195 ret = __bt_media_send_control_msg("VolumeDown");
198 BT_DBG("Invalid Type\n");
199 return BLUETOOTH_ERROR_INTERNAL;
205 GDBusProxy *__bt_get_control_properties_proxy(void)
207 GDBusProxy *proxy = NULL;
208 GError *error = NULL;
209 char *control_path = NULL;
210 GDBusConnection *conn = NULL;
212 control_path = __bt_get_control_device_path();
213 retv_if(control_path == NULL, NULL);
214 BT_DBG("control_path = %s", control_path);
216 conn = _bt_gdbus_get_system_gconn();
217 retv_if(conn == NULL, NULL);
219 proxy = g_dbus_proxy_new_sync(conn,
220 G_DBUS_PROXY_FLAGS_NONE, NULL,
221 BT_BLUEZ_NAME, control_path,
222 BT_PROPERTIES_INTERFACE, NULL, &error);
224 BT_ERR("Unable to allocate new proxy");
226 BT_ERR("%s", error->message);
227 g_clear_error(&error);
235 static int __bt_media_attr_to_event(const char *str)
237 if (!strcasecmp(str, "Equalizer"))
238 return BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS;
239 else if (!strcasecmp(str, "Repeat"))
240 return BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS;
241 else if (!strcasecmp(str, "Shuffle"))
242 return BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS;
243 else if (!strcasecmp(str, "Scan"))
244 return BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS;
245 else if (!strcasecmp(str, "Position"))
246 return BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS;
247 else if (!strcasecmp(str, "Track"))
248 return BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED;
249 else if (!strcasecmp(str, "Status"))
250 return BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED;
255 static int __bt_media_attr_to_type(const char *str)
257 if (!strcasecmp(str, "Equalizer"))
259 else if (!strcasecmp(str, "Repeat"))
261 else if (!strcasecmp(str, "Shuffle"))
263 else if (!strcasecmp(str, "Scan"))
265 else if (!strcasecmp(str, "Position"))
267 else if (!strcasecmp(str, "Track"))
269 else if (!strcasecmp(str, "Status"))
275 static const char *__bt_media_type_to_str(int type)
296 static int __bt_media_attrval_to_val(int type, const char *value)
302 if (!strcmp(value, "off"))
304 else if (!strcmp(value, "on"))
307 ret = EQUALIZER_INVALID;
311 if (!strcmp(value, "off"))
312 ret = REPEAT_MODE_OFF;
313 else if (!strcmp(value, "singletrack"))
314 ret = REPEAT_SINGLE_TRACK;
315 else if (!strcmp(value, "alltracks"))
316 ret = REPEAT_ALL_TRACK;
317 else if (!strcmp(value, "group"))
320 ret = REPEAT_INVALID;
324 if (!strcmp(value, "off"))
325 ret = SHUFFLE_MODE_OFF;
326 else if (!strcmp(value, "alltracks"))
327 ret = SHUFFLE_ALL_TRACK;
328 else if (!strcmp(value, "group"))
331 ret = SHUFFLE_INVALID;
335 if (!strcmp(value, "off"))
337 else if (!strcmp(value, "alltracks"))
338 ret = SCAN_ALL_TRACK;
339 else if (!strcmp(value, "group"))
346 if (!strcmp(value, "stopped"))
347 ret = STATUS_STOPPED;
348 else if (!strcmp(value, "playing"))
349 ret = STATUS_PLAYING;
350 else if (!strcmp(value, "paused"))
352 else if (!strcmp(value, "forward-seek"))
353 ret = STATUS_FORWARD_SEEK;
354 else if (!strcmp(value, "reverse-seek"))
355 ret = STATUS_REVERSE_SEEK;
356 else if (!strcmp(value, "error"))
359 ret = STATUS_INVALID;
364 int _bt_avrcp_control_get_property(int type, unsigned int *value)
366 GDBusProxy *proxy = NULL;
368 int ret = BLUETOOTH_ERROR_NONE;
370 GVariant *reply = NULL;
371 GVariant *temp = NULL;
373 BT_CHECK_PARAMETER(value, return);
375 proxy = __bt_get_control_properties_proxy();
376 retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
378 reply = g_dbus_proxy_call_sync(proxy,
379 "Get", g_variant_new("(ss)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type)),
380 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
382 g_object_unref(proxy);
385 BT_ERR("Can't get managed objects");
387 BT_ERR("%s", err->message);
390 return BLUETOOTH_ERROR_INTERNAL;
398 name = (char *)g_variant_get_data(reply);
400 *value = __bt_media_attrval_to_val(type, name);
401 BT_INFO("Type[%s] and Value[%s]", __bt_media_type_to_str(type), name);
404 g_variant_get(reply, "(v)", &temp);
405 *value = g_variant_get_uint32(temp);
406 g_variant_unref(temp);
407 BT_INFO("Type[%s] and Value[%d]", __bt_media_type_to_str(type), *value);
410 BT_ERR("Invalid Type [%d]", type);
411 ret = BLUETOOTH_ERROR_INTERNAL;
414 g_variant_unref(reply);
418 int _bt_avrcp_control_set_property(int type, unsigned int value)
420 GValue *attr_value = NULL;
421 GDBusProxy *proxy = NULL;
422 GError *error = NULL;
423 GVariant *reply, *param;
425 g_value_init(attr_value, G_TYPE_STRING);
429 param = g_variant_new("s", equalizer_status[value].property);
430 BT_INFO("equalizer_status %s", equalizer_status[value].property);
433 param = g_variant_new("s", repeat_status[value].property);
434 BT_INFO("repeat_status %s", repeat_status[value].property);
437 param = g_variant_new("s", shuffle_settings[value].property);
438 BT_INFO("shuffle_settings %s", shuffle_settings[value].property);
441 param = g_variant_new("s", scan_status[value].property);
442 BT_INFO("scan_status %s", scan_status[value].property);
445 BT_ERR("Invalid property type: %d", type);
446 g_value_unset(attr_value);
447 return BLUETOOTH_ERROR_INTERNAL;
450 proxy = __bt_get_control_properties_proxy();
451 retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
453 reply = g_dbus_proxy_call_sync(proxy,
454 "Set", g_variant_new("(ssv)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type), param),
455 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
457 g_object_unref(proxy);
458 g_variant_unref(param);
461 BT_ERR("Can't get managed objects");
463 BT_ERR("SetProperty Fail: %s", error->message);
464 g_clear_error(&error);
465 return BLUETOOTH_ERROR_INTERNAL;
469 g_variant_unref(reply);
470 g_value_unset(attr_value);
472 return BLUETOOTH_ERROR_NONE;
475 static int __bt_avrcp_control_parse_properties(
476 media_metadata_attributes_t *metadata,
479 GVariant *value = NULL;
481 char *value_string = NULL;
482 unsigned int value_uint;
483 const char *key = NULL;
485 g_variant_iter_init(&iter, item);
486 while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) {
487 if (strcasecmp(key, "Title") == 0) {
488 value_string = (char *)g_variant_get_string(value, NULL);
489 BT_DBG("Value : %s ", value_string);
490 metadata->title = g_strdup(value_string);
491 } else if (strcasecmp(key, "Artist") == 0) {
492 value_string = (char *)g_variant_get_string(value, NULL);
493 BT_DBG("Value : %s ", value_string);
494 metadata->artist = g_strdup(value_string);
495 } else if (strcasecmp(key, "Album") == 0) {
496 value_string = (char *)g_variant_get_string(value, NULL);
497 BT_DBG("Value : %s ", value_string);
498 metadata->album = g_strdup(value_string);
499 } else if (strcasecmp(key, "Genre") == 0) {
500 value_string = (char *)g_variant_get_string(value, NULL);
501 BT_DBG("Value : %s ", value_string);
502 metadata->genre = g_strdup(value_string);
503 } else if (strcasecmp(key, "Duration") == 0) {
504 value_uint = g_variant_get_uint32(value);
505 BT_DBG("Duration : %d", value_uint);
506 metadata->duration = value_uint;
507 } else if (strcasecmp(key, "NumberOfTracks") == 0) {
508 value_uint = g_variant_get_uint32(value);
509 metadata->total_tracks = value_uint;
510 } else if (strcasecmp(key, "TrackNumber") == 0) {
511 value_uint = g_variant_get_uint32(value);
512 metadata->number = value_uint;
514 BT_DBG("%s not supported, ignoring", key);
517 if (!metadata->title)
518 metadata->title = g_strdup("");
519 if (!metadata->artist)
520 metadata->artist = g_strdup("");
521 if (!metadata->album)
522 metadata->album = g_strdup("");
523 if (!metadata->genre)
524 metadata->genre = g_strdup("");
526 return BLUETOOTH_ERROR_NONE;
530 int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata)
532 GDBusProxy *proxy = NULL;
533 GVariant *reply = NULL;
534 GVariant *item = NULL;
536 GDBusConnection *conn = NULL;
537 char *control_path = NULL;
538 char *interface_name = NULL;
539 char *property_name = NULL;
540 GVariant *parameters = NULL;
541 int ret = BLUETOOTH_ERROR_NONE;
543 retv_if(metadata == NULL, BLUETOOTH_ERROR_INTERNAL);
545 conn = _bt_gdbus_get_system_gconn();
546 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
548 control_path = __bt_get_control_device_path();
549 retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
550 BT_DBG("control_path %s", control_path);
552 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
553 BT_BLUEZ_NAME, control_path,
554 BT_PROPERTIES_INTERFACE, NULL, &err);
556 BT_ERR("Unable to allocate new proxy \n");
558 BT_ERR("%s", err->message);
561 return BLUETOOTH_ERROR_INTERNAL;
564 interface_name = g_strdup(BT_PLAYER_CONTROL_INTERFACE);
565 property_name = g_strdup("Track");
567 parameters = g_variant_new("(ss)", interface_name, property_name);
569 g_free(interface_name);
570 g_free(property_name);
572 reply = g_dbus_proxy_call_sync(proxy, "Get", parameters,
573 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
575 g_object_unref(proxy);
578 BT_ERR("Error returned in method call");
580 BT_ERR("%s", err->message);
583 return BLUETOOTH_ERROR_INTERNAL;
586 g_variant_get(reply, "(v)", &item);
588 ret = __bt_avrcp_control_parse_properties(metadata, item);
590 g_variant_unref(reply);
595 void _bt_handle_avrcp_control_event(GVariant *reply, const char *path)
597 GVariant *param = NULL;
598 const char *property = NULL;
601 BT_ERR("Error returned in method call\n");
606 GVariant *value = NULL;
607 g_variant_iter_init(&iter, reply);
608 while (g_variant_iter_loop(&iter, "{sv}", &property,
610 if ((strcasecmp(property, "Equalizer") == 0) ||
611 (strcasecmp(property, "Repeat") == 0) ||
612 (strcasecmp(property, "Shuffle") == 0) ||
613 (strcasecmp(property, "Scan") == 0) ||
614 (strcasecmp(property, "Status") == 0)) {
616 unsigned int type, val = 0;
618 valstr = g_variant_get_string(value, NULL);
619 BT_DBG("Value : %s ", valstr);
620 type = __bt_media_attr_to_type(property);
622 val = __bt_media_attrval_to_val(type, valstr);
624 /* Send event to application */
625 param = g_variant_new("(u)", val);
626 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
627 __bt_media_attr_to_event(property), param);
628 } else if (strcasecmp(property, "Position") == 0) {
631 val = g_variant_get_uint32(value);
632 BT_DBG("Value : %d ", val);
634 /* Send event to application */
635 param = g_variant_new("(u)", val);
636 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
637 __bt_media_attr_to_event(property), param);
638 } else if (strcasecmp(property, "Track") == 0) {
639 int ret = BLUETOOTH_ERROR_NONE;
640 media_metadata_attributes_t metadata;
642 memset(&metadata, 0x00, sizeof(media_metadata_attributes_t));
644 ret = __bt_avrcp_control_parse_properties(
646 if (BLUETOOTH_ERROR_NONE != ret) {
647 /* Free key and value because of break unless free not required */
648 free((char *)property);
649 g_variant_unref(value);
650 g_free((char *)metadata.title);
651 g_free((char *)metadata.artist);
652 g_free((char *)metadata.album);
653 g_free((char *)metadata.genre);
657 /* Send event to application */
658 param = g_variant_new("(ssssuuu)",
663 metadata.total_tracks,
666 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
667 BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED, param);
669 g_free((char *)metadata.title);
670 g_free((char *)metadata.artist);
671 g_free((char *)metadata.album);
672 g_free((char *)metadata.genre);
674 BT_DBG("Property not handled");