Add AVRCP control volume up / down method
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-avrcp-controller.c
old mode 100755 (executable)
new mode 100644 (file)
index 40a4962..be6ce19
@@ -54,6 +54,7 @@ static bt_player_settinngs_t shuffle_settings[] = {
 };
 
 static char *avrcp_control_path = NULL;
+static char *avrcp_transport_path = NULL;
 
 void _bt_set_control_device_path(const char *path)
 {
@@ -85,7 +86,8 @@ static char *__bt_get_control_device_path(void)
 
        BT_DBG("+");
 
-       retv_if(avrcp_control_path != NULL, avrcp_control_path);
+       if (avrcp_control_path != NULL)
+               return avrcp_control_path;
 
        retv_if(!_bt_is_headset_type_connected(BT_AVRCP,
                        connected_address), NULL);
@@ -103,6 +105,33 @@ static char *__bt_get_control_device_path(void)
        return control_path;
 }
 
+static char *__bt_get_transport_device_path(void)
+{
+       char *adapter_path;
+       char *transport_path;
+       char connected_address[BT_ADDRESS_STRING_SIZE + 1];
+
+       BT_DBG("+");
+
+       if (avrcp_transport_path != NULL)
+               return avrcp_transport_path;
+
+       retv_if(!_bt_is_headset_type_connected(BT_AVRCP,
+                       connected_address), NULL);
+
+       BT_DBG("device address = %s", connected_address);
+
+       adapter_path = _bt_get_device_object_path(connected_address);
+       retv_if(adapter_path == NULL, NULL);
+
+       transport_path = g_strdup_printf(BT_MEDIA_TRANSPORT_PATH, adapter_path);
+       g_free(adapter_path);
+
+       avrcp_transport_path = transport_path;
+       BT_DBG("transport_path = %s", transport_path);
+       return transport_path;
+}
+
 static int __bt_media_send_control_msg(const char *name)
 {
        GVariant *reply = NULL;
@@ -113,7 +142,9 @@ static int __bt_media_send_control_msg(const char *name)
 
        retv_if(name == NULL, BLUETOOTH_ERROR_INTERNAL);
 
-       conn = _bt_get_system_conn();
+       BT_INFO("Command [%s]", name);
+
+       conn = _bt_gdbus_get_system_gconn();
        retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
 
        control_path = __bt_get_control_device_path();
@@ -173,11 +204,23 @@ int _bt_avrcp_control_cmd(int type)
        case PREVIOUS:
                ret = __bt_media_send_control_msg("Previous");
                break;
-       case FAST_FORWARD:
-               ret = __bt_media_send_control_msg("FastForward");
+       case PRESS_FAST_FORWARD:
+               ret = __bt_media_send_control_msg("PressFastForward");
+               break;
+       case RELEASE_FAST_FORWARD:
+               ret = __bt_media_send_control_msg("ReleaseFastForward");
+               break;
+       case PRESS_REWIND:
+               ret = __bt_media_send_control_msg("PressRewind");
+               break;
+       case RELEASE_REWIND:
+               ret = __bt_media_send_control_msg("ReleaseRewind");
                break;
-       case REWIND:
-               ret = __bt_media_send_control_msg("Rewind");
+       case VOLUME_UP:
+               ret = __bt_media_send_control_msg("VolumeUp");
+               break;
+       case VOLUME_DOWN:
+               ret = __bt_media_send_control_msg("VolumeDown");
                break;
        default:
                BT_DBG("Invalid Type\n");
@@ -198,7 +241,7 @@ GDBusProxy *__bt_get_control_properties_proxy(void)
        retv_if(control_path == NULL, NULL);
        BT_DBG("control_path = %s", control_path);
 
-       conn = _bt_get_system_conn();
+       conn = _bt_gdbus_get_system_gconn();
        retv_if(conn == NULL, NULL);
 
        proxy = g_dbus_proxy_new_sync(conn,
@@ -217,6 +260,36 @@ GDBusProxy *__bt_get_control_properties_proxy(void)
        return proxy;
 }
 
+GDBusProxy *__bt_get_transport_properties_proxy(void)
+{
+       GDBusProxy *proxy = NULL;
+       GError *error = NULL;
+       char *transport_path = NULL;
+       GDBusConnection *conn = NULL;
+
+       transport_path = __bt_get_transport_device_path();
+       retv_if(transport_path == NULL, NULL);
+       BT_DBG("transport_path = %s", transport_path);
+
+       conn = _bt_gdbus_get_system_gconn();
+       retv_if(conn == NULL, NULL);
+
+       proxy = g_dbus_proxy_new_sync(conn,
+                       G_DBUS_PROXY_FLAGS_NONE, NULL,
+                       BT_BLUEZ_NAME, transport_path,
+                       BT_PROPERTIES_INTERFACE, NULL, &error);
+       if (proxy == NULL) {
+               BT_ERR("Unable to allocate new proxy");
+               if (error) {
+                       BT_ERR("%s", error->message);
+                       g_clear_error(&error);
+               }
+               return NULL;
+       }
+
+       return proxy;
+}
+
 static int __bt_media_attr_to_event(const char *str)
 {
        if (!strcasecmp(str, "Equalizer"))
@@ -278,6 +351,17 @@ static const char *__bt_media_type_to_str(int type)
        return NULL;
 }
 
+static const char *__bt_transport_type_to_str(int type)
+{
+       switch (type) {
+       case DELAY:
+               return "Delay";
+       case VOLUME:
+               return "Volume";
+       }
+       return NULL;
+}
+
 static int __bt_media_attrval_to_val(int type, const char *value)
 {
        int ret = 0;
@@ -353,6 +437,7 @@ int _bt_avrcp_control_get_property(int type, unsigned int *value)
        int ret = BLUETOOTH_ERROR_NONE;
        GError *err = NULL;
        GVariant *reply = NULL;
+       GVariant *temp = NULL;
 
        BT_CHECK_PARAMETER(value, return);
 
@@ -360,7 +445,7 @@ int _bt_avrcp_control_get_property(int type, unsigned int *value)
        retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
 
        reply = g_dbus_proxy_call_sync(proxy,
-                                       "Get", g_variant_new("ss", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type)),
+                                       "Get", g_variant_new("(ss)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type)),
                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
 
        g_object_unref(proxy);
@@ -379,15 +464,19 @@ int _bt_avrcp_control_get_property(int type, unsigned int *value)
                        case SHUFFLE:
                        case SCAN:
                        case STATUS:
-                               name =(char *)g_variant_get_string(reply, NULL);
-                               *value = __bt_media_attrval_to_val(type, name);
-                               BT_DBG("Type[%s] and Value[%s]", __bt_media_type_to_str(type), name);
+                               name = (char *)g_variant_get_data(reply);
+                               if (name)
+                                       *value = __bt_media_attrval_to_val(type, name);
+                               BT_INFO("Type[%s] and Value[%s]", __bt_media_type_to_str(type), name);
                                break;
                        case POSITION:
-                               *value = g_variant_get_uint32(reply);
+                               g_variant_get(reply, "(v)", &temp);
+                               *value = g_variant_get_uint32(temp);
+                               g_variant_unref(temp);
+                               BT_INFO("Type[%s] and Value[%d]", __bt_media_type_to_str(type), *value);
                                break;
                        default:
-                               BT_DBG("Invalid Type\n");
+                               BT_ERR("Invalid Type [%d]", type);
                                ret =  BLUETOOTH_ERROR_INTERNAL;
                        }
                }
@@ -407,19 +496,19 @@ int _bt_avrcp_control_set_property(int type, unsigned int value)
        switch (type) {
        case EQUALIZER:
                param = g_variant_new("s", equalizer_status[value].property);
-               BT_DBG("equalizer_status %s", equalizer_status[value].property);
+               BT_INFO("equalizer_status %s", equalizer_status[value].property);
                break;
        case REPEAT:
                param = g_variant_new("s", repeat_status[value].property);
-               BT_DBG("repeat_status %s", repeat_status[value].property);
+               BT_INFO("repeat_status %s", repeat_status[value].property);
                break;
        case SHUFFLE:
                param = g_variant_new("s", shuffle_settings[value].property);
-               BT_DBG("shuffle_settings %s", shuffle_settings[value].property);
+               BT_INFO("shuffle_settings %s", shuffle_settings[value].property);
                break;
        case SCAN:
                param = g_variant_new("s", scan_status[value].property);
-               BT_DBG("scan_status %s", scan_status[value].property);
+               BT_INFO("scan_status %s", scan_status[value].property);
                break;
        default:
                BT_ERR("Invalid property type: %d", type);
@@ -431,7 +520,7 @@ int _bt_avrcp_control_set_property(int type, unsigned int value)
        retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
 
        reply = g_dbus_proxy_call_sync(proxy,
-                                       "Set", g_variant_new("ssv", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type), param),
+                                       "Set", g_variant_new("(ssv)", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type), param),
                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
 
        g_object_unref(proxy);
@@ -452,6 +541,51 @@ int _bt_avrcp_control_set_property(int type, unsigned int value)
        return BLUETOOTH_ERROR_NONE;
 }
 
+int _bt_avrcp_transport_set_property(int type, unsigned int value)
+{
+       GDBusProxy *proxy = NULL;
+       GError *error = NULL;
+       GVariant *reply, *param;
+       uint16_t property_level = (uint16_t)value;
+
+       switch (type) {
+       case DELAY:
+               param = g_variant_new("q", property_level);
+               BT_INFO("delay level %d", property_level);
+               break;
+       case VOLUME:
+               param = g_variant_new("q", property_level);
+               BT_INFO("volume level %d", property_level);
+               break;
+       default:
+               BT_ERR("Invalid property type: %d", type);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       proxy = __bt_get_transport_properties_proxy();
+       retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
+
+       reply = g_dbus_proxy_call_sync(proxy,
+                                       "Set", g_variant_new("(ssv)", BT_MEDIATRANSPORT_INTERFACE, __bt_transport_type_to_str(type), param),
+                                       G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+
+       g_object_unref(proxy);
+       g_variant_unref(param);
+
+       if (!reply) {
+               BT_ERR("Can't get managed objects");
+               if (error) {
+                       BT_ERR("SetProperty Fail: %s", error->message);
+                       g_clear_error(&error);
+                       return BLUETOOTH_ERROR_INTERNAL;
+               }
+       }
+
+       g_variant_unref(reply);
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
 static int __bt_avrcp_control_parse_properties(
                                media_metadata_attributes_t *metadata,
                                GVariant *item)
@@ -463,25 +597,26 @@ static int __bt_avrcp_control_parse_properties(
        const char *key = NULL;
 
        g_variant_iter_init(&iter, item);
-       while (g_variant_iter_loop(&iter, "{sv}", &key, &value)){
-               if (strcasecmp(key, "Title") == 0){
+       while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) {
+               if (strcasecmp(key, "Title") == 0) {
                        value_string = (char *)g_variant_get_string(value, NULL);
                        BT_DBG("Value : %s ", value_string);
-                       metadata->title = value_string;
+                       metadata->title = g_strdup(value_string);
                } else if (strcasecmp(key, "Artist") == 0) {
-                       value_string =(char *)g_variant_get_string(value, NULL);
+                       value_string = (char *)g_variant_get_string(value, NULL);
                        BT_DBG("Value : %s ", value_string);
-                       metadata->artist = value_string;
+                       metadata->artist = g_strdup(value_string);
                } else if (strcasecmp(key, "Album") == 0) {
-                       value_string =(char *)g_variant_get_string(value, NULL);
+                       value_string = (char *)g_variant_get_string(value, NULL);
                        BT_DBG("Value : %s ", value_string);
-                       metadata->album = value_string;
+                       metadata->album = g_strdup(value_string);
                } else if (strcasecmp(key, "Genre") == 0) {
-                       value_string =(char *)g_variant_get_string(value, NULL);
+                       value_string = (char *)g_variant_get_string(value, NULL);
                        BT_DBG("Value : %s ", value_string);
-                       metadata->genre = value_string;
+                       metadata->genre = g_strdup(value_string);
                } else if (strcasecmp(key, "Duration") == 0) {
                        value_uint = g_variant_get_uint32(value);
+                       BT_DBG("Duration : %d", value_uint);
                        metadata->duration = value_uint;
                } else if (strcasecmp(key, "NumberOfTracks") == 0) {
                        value_uint = g_variant_get_uint32(value);
@@ -521,7 +656,7 @@ int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata)
 
        retv_if(metadata == NULL, BLUETOOTH_ERROR_INTERNAL);
 
-       conn = _bt_get_system_conn();
+       conn = _bt_gdbus_get_system_gconn();
        retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
 
        control_path = __bt_get_control_device_path();
@@ -590,14 +725,15 @@ void _bt_handle_avrcp_control_event(GVariant *reply, const char *path)
                        (strcasecmp(property, "Repeat") == 0) ||
                        (strcasecmp(property, "Shuffle") == 0) ||
                        (strcasecmp(property, "Scan") == 0) ||
-                       (strcasecmp(property, "Status") == 0)){
+                       (strcasecmp(property, "Status") == 0)) {
                                const char *valstr;
-                               unsigned int type, val;
+                               unsigned int type, val = 0;
 
                                valstr = g_variant_get_string(value, NULL);
                                BT_DBG("Value : %s ", valstr);
                                type = __bt_media_attr_to_type(property);
-                               val = __bt_media_attrval_to_val(type, valstr);
+                               if (valstr)
+                                       val = __bt_media_attrval_to_val(type, valstr);
 
                                /* Send event to application */
                                param = g_variant_new("(u)", val);
@@ -620,11 +756,15 @@ void _bt_handle_avrcp_control_event(GVariant *reply, const char *path)
                        memset(&metadata, 0x00, sizeof(media_metadata_attributes_t));
 
                        ret = __bt_avrcp_control_parse_properties(
-                                                               &metadata, reply);
-                       if (BLUETOOTH_ERROR_NONE != ret){
+                                                               &metadata, value);
+                       if (BLUETOOTH_ERROR_NONE != ret) {
                                /* Free key and value because of break unless free not required */
                                free((char *)property);
                                g_variant_unref(value);
+                               g_free((char *)metadata.title);
+                               g_free((char *)metadata.artist);
+                               g_free((char *)metadata.album);
+                               g_free((char *)metadata.genre);
                                break;
                        }