aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Ranostay <matt.ranostay@konsulko.com>2018-11-06 23:02:11 -0800
committerMatt Ranostay <matt.ranostay@konsulko.com>2018-11-12 03:58:47 -0800
commita5fe25e7496cf4a8369e1f34e66c9e55d2c95ed1 (patch)
treeb999b55195278036550836f1336eb9f805cc00a6
parent50078d83552f02051a5706b3dfea0953eff3a02b (diff)
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 <matt.ranostay@konsulko.com>
-rw-r--r--README.md11
-rw-r--r--binding/bluetooth-api.c43
-rw-r--r--binding/bluetooth-api.h12
-rw-r--r--binding/bluetooth-bluez.c18
4 files changed, 83 insertions, 1 deletions
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();
@@ -1090,6 +1128,11 @@ static const struct afb_verb_v3 bluetooth_verbs[] = {
.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,
.callback = bluetooth_version,
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",