From a5fe25e7496cf4a8369e1f34e66c9e55d2c95ed1 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Tue, 6 Nov 2018 23:02:11 -0800 Subject: binding: bluetooth: add new avrcp controls verb Since MediaPlayer1 controls are part of bluez it makes sense to keep them here for now Bug-AGL: SPEC-1630 Change-Id: Ia02341179a322082357b0e7eff07264e34197d57 Signed-off-by: Matt Ranostay --- README.md | 11 +++++++++++ binding/bluetooth-api.c | 43 +++++++++++++++++++++++++++++++++++++++++++ binding/bluetooth-api.h | 12 ++++++++++++ binding/bluetooth-bluez.c | 18 +++++++++++++++++- 4 files changed, 83 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6634b43..24ea06b 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ Bluetooth service uses the respective BlueZ package to connect to bluetooth devi | unsubscribe | unsubscribe to bluetooth events | *Request:* {"value": "device_changes"} | | managed_objects | retrieve managed bluetooth devices | see managed_objects verb section | | adapter_state | retrieve or change adapter scan settings | see adapter_state verb section | +| avrcp_controls | avrcp controls for MediaPlayer1 playback | see avrcp_controls verb section | | connect | connect to already paired device | see connect/disconnect verb section | | disconnect | disconnect to already connected device | see connect/disconnect verb section | | pair | initialize a pairing request | *Request:* {"device":"dev_88_0F_10_96_D3_20"} | @@ -124,6 +125,16 @@ adapter_state verb allows setting and retrieving of requested adapter settings: | powered | Adapter power state (optional, rfkill should be disabled already) | | filter | Display devices only with respective UUIDS listed (write only setting) | +#### avrcp_controls verb + +avrcp_controls verb allow controlling the playback of the defined device + +| Name | Description | +|-----------------|----------------------------------------------------------------------------------------------| +| adapter | Name of the adapter (i.e. hci0) | +| device | Must be the name of the device (i.e. dev_88_0F_10_96_D3_20) | +| action | Playback control action to take (e.g Play, Pause, Stop, Next, Previous, FastForward, Rewind) | + ### connect/disconnect verbs NOTE: uuid in this respect is not related to the afb framework but the Bluetooth profile UUID diff --git a/binding/bluetooth-api.c b/binding/bluetooth-api.c index 5d26f3a..7e3e1eb 100644 --- a/binding/bluetooth-api.c +++ b/binding/bluetooth-api.c @@ -1029,6 +1029,44 @@ out_free: } +static void bluetooth_avrcp_controls(afb_req_t request) +{ + struct bluetooth_state *ns = bluetooth_get_userdata(request); + const char *action = afb_req_value(request, "action"); + gchar *device, *player; + GVariant *reply; + GError *error = NULL; + + if (!action) { + afb_req_fail(request, "failed", "No action given"); + return; + } + + device = return_bluez_path(request); + if (!device) { + afb_req_fail(request, "failed", "No path given"); + return; + } + + /* TODO: handle multiple players per device */ + player = g_strconcat(device, "/player0", NULL); + g_free(device); + + reply = mediaplayer_call(ns, player, action, NULL, &error); + + if (!reply) { + afb_req_fail_f(request, "failed", + "mediaplayer %s method %s error %s", + player, action, BLUEZ_ERRMSG(error)); + g_free(player); + g_error_free(error); + return; + } + + g_free(player); + afb_req_success(request, NULL, "Bluetooth - AVRCP controls"); +} + static void bluetooth_version(afb_req_t request) { json_object *jresp = json_object_new_object(); @@ -1089,6 +1127,11 @@ static const struct afb_verb_v3 bluetooth_verbs[] = { .session = AFB_SESSION_NONE, .callback = bluetooth_remove_device, .info = "Removed paired device", + }, { + .verb = "avrcp_controls", + .session = AFB_SESSION_NONE, + .callback = bluetooth_avrcp_controls, + .info = "AVRCP controls" }, { .verb = "version", .session = AFB_SESSION_NONE, diff --git a/binding/bluetooth-api.h b/binding/bluetooth-api.h index f8ce9d8..0d72afc 100644 --- a/binding/bluetooth-api.h +++ b/binding/bluetooth-api.h @@ -33,6 +33,7 @@ #define BLUEZ_AGENT_INTERFACE BLUEZ_SERVICE ".Agent1" #define BLUEZ_AGENTMANAGER_INTERFACE BLUEZ_SERVICE ".AgentManager1" #define BLUEZ_DEVICE_INTERFACE BLUEZ_SERVICE ".Device1" +#define BLUEZ_MEDIAPLAYER_INTERFACE BLUEZ_SERVICE ".MediaPlayer1" #define BLUEZ_OBJECT_PATH "/" #define BLUEZ_PATH "/org/bluez" @@ -64,6 +65,7 @@ #define BLUEZ_AT_DEVICE "device" #define BLUEZ_AT_AGENT "agent" #define BLUEZ_AT_AGENTMANAGER "agent-manager" +#define BLUEZ_AT_MEDIAPLAYER "mediaplayer" #define BLUEZ_DEFAULT_ADAPTER "hci0" @@ -184,6 +186,14 @@ static inline GVariant *agentmanager_call(struct bluetooth_state *ns, method, params, error); } +static inline GVariant *mediaplayer_call(struct bluetooth_state *ns, + const char *player, const char *method, + GVariant *params, GError **error) +{ + return bluez_call(ns, BLUEZ_AT_MEDIAPLAYER, player, + method, params, error); +} + static inline gboolean adapter_set_property(struct bluetooth_state *ns, const char *adapter, gboolean is_json_name, const char *name, json_object *jval, GError **error) @@ -235,4 +245,6 @@ void bluez_decode_call_error(struct bluetooth_state *ns, const char *method, GError **error); + + #endif /* BLUETOOTH_API_H */ diff --git a/binding/bluetooth-bluez.c b/binding/bluetooth-bluez.c index 052ea7b..824843b 100644 --- a/binding/bluetooth-bluez.c +++ b/binding/bluetooth-bluez.c @@ -155,6 +155,19 @@ void bluez_decode_call_error(struct bluetooth_state *ns, NB_ERROR_UNKNOWN_SERVICE, "unknown service %s", type_arg); + } else if (!strcmp(method, "Play") || + !strcmp(method, "Pause") || + !strcmp(method, "Stop") || + !strcmp(method, "Next") || + !strcmp(method, "Previous") || + !strcmp(method, "FastForward") || + !strcmp(method, "Rewind")) { + + g_clear_error(error); + g_set_error(error, NB_ERROR, + NB_ERROR_UNKNOWN_PROPERTY, + "unknown method %s", + method); } } } @@ -167,7 +180,8 @@ GVariant *bluez_call(struct bluetooth_state *ns, GVariant *reply; if (!path && (!strcmp(access_type, BLUEZ_AT_DEVICE) || - !strcmp(access_type, BLUEZ_AT_ADAPTER))) { + !strcmp(access_type, BLUEZ_AT_ADAPTER) || + !strcmp(access_type, BLUEZ_AT_MEDIAPLAYER))) { g_set_error(error, NB_ERROR, NB_ERROR_MISSING_ARGUMENT, "missing %s argument", access_type); @@ -181,6 +195,8 @@ GVariant *bluez_call(struct bluetooth_state *ns, } else if (!strcmp(access_type, BLUEZ_AT_AGENTMANAGER)) { path = BLUEZ_PATH; interface = BLUEZ_AGENTMANAGER_INTERFACE; + } else if (!strcmp(access_type, BLUEZ_AT_MEDIAPLAYER)) { + interface = BLUEZ_MEDIAPLAYER_INTERFACE; } else { g_set_error(error, NB_ERROR, NB_ERROR_ILLEGAL_ARGUMENT, "illegal %s argument", -- cgit 1.2.3-korg