summaryrefslogtreecommitdiffstats
path: root/bluetooth
diff options
context:
space:
mode:
authorScott Murray <scott.murray@konsulko.com>2022-02-28 13:04:45 -0500
committerScott Murray <scott.murray@konsulko.com>2022-02-28 13:04:45 -0500
commit1332cc7d0a618ee88b4d19813340665332d406ca (patch)
treefe500276505160f5fd8ba8acb46334633ed0788a /bluetooth
parent0de8ac83e6a190d5fc124587d1f9f0a7f0198ce3 (diff)
Add Bluetooth media control supportmarlin_12.93.0marlin/12.93.012.93.0
Rework to expose Bluetooth AVRCP media control in the Bluetooth class, and use that support to implement a Bluetooth backend in the Mediaplayer class. This replaces the scheme that existed with the agl-service-mediaplayer binding where it abstracted away the Bluetooth support itself. However, care has been take to make sure that the exposed API to users of libqtappfw-mediaplayer has not changed. Bug-AGL: SPEC-4231 Signed-off-by: Scott Murray <scott.murray@konsulko.com> Change-Id: I76b4f75621ce0121364eea3259b074bf3067ee88
Diffstat (limited to 'bluetooth')
-rw-r--r--bluetooth/bluetooth.cpp195
-rw-r--r--bluetooth/bluetooth.h106
-rw-r--r--bluetooth/bluetootheventhandler.cpp142
-rw-r--r--bluetooth/bluetootheventhandler.h43
4 files changed, 427 insertions, 59 deletions
diff --git a/bluetooth/bluetooth.cpp b/bluetooth/bluetooth.cpp
index c58b64b..5c7fd31 100644
--- a/bluetooth/bluetooth.cpp
+++ b/bluetooth/bluetooth.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018-2021 Konsulko Group
+ * Copyright (C) 2018-2022 Konsulko Group
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,10 +23,17 @@
#include "bluetootheventhandler.h"
-Bluetooth::Bluetooth (bool register_agent, QQmlContext *context, QObject * parent) :
+Bluetooth::Bluetooth(bool register_agent,
+ QQmlContext *context,
+ bool handle_media,
+ QObject * parent) :
QObject(parent),
m_context(context),
- m_agent(register_agent)
+ m_agent(register_agent),
+ m_handle_media(handle_media),
+ m_connected(false),
+ m_connected_device(""),
+ m_media_connected(false)
{
m_bluetooth = new BluetoothModel();
BluetoothModelFilter *m_model = new BluetoothModelFilter();
@@ -39,7 +46,7 @@ Bluetooth::Bluetooth (bool register_agent, QQmlContext *context, QObject * paren
m_model->setFilterFixedString("false");
context->setContextProperty("BluetoothDiscoveryModel", m_model);
- m_event_handler = new BluetoothEventHandler(this, register_agent);
+ m_event_handler = new BluetoothEventHandler(this, register_agent, handle_media);
uuids.insert("a2dp", "0000110a-0000-1000-8000-00805f9b34fb");
uuids.insert("avrcp", "0000110e-0000-1000-8000-00805f9b34fb");
@@ -61,12 +68,19 @@ void Bluetooth::setDiscoverable(bool state)
m_discoverable = state;
- emit discoverableChanged();
+ emit discoverableChanged(state);
}
void Bluetooth::start()
{
- bluez_init(m_agent, m_agent, m_event_handler->init_cb, m_event_handler);
+ // NOTE: An explicit "start" is somewhat required at present as calling
+ // bluez_init in the constructor means state update signals get
+ // emitted before the QML in an app seems able to receive them.
+ // A slightly better alternative might be something like a
+ // "refresh" function, or documenting that apps must explicitly
+ // call getters of relevant values on start.
+
+ bluez_init(m_agent, m_agent, m_event_handler->init_cb, m_event_handler);
}
void Bluetooth::discovery_command(bool state)
@@ -153,7 +167,7 @@ void Bluetooth::disconnect(QString device)
bluez_device_disconnect(device_cstr, NULL);
}
-void Bluetooth::send_confirmation(int pincode)
+void Bluetooth::send_confirmation(const int pincode)
{
QString pincode_str;
pincode_str.setNum(pincode);
@@ -163,7 +177,75 @@ void Bluetooth::send_confirmation(int pincode)
bluez_confirm_pairing(pincode_cstr);
}
-void Bluetooth::init_adapter_state(QString adapter)
+void Bluetooth::media_control(MediaAction action)
+{
+ QString action_name;
+ bool action_allowed = true;
+ bluez_media_control_t bluez_action;
+ switch (action) {
+ case Connect:
+ bluez_action = BLUEZ_MEDIA_CONTROL_CONNECT;
+ action_name = "Connect";
+ action_allowed = !m_media_connected;
+ break;
+ case Disconnect:
+ bluez_action = BLUEZ_MEDIA_CONTROL_DISCONNECT;
+ action_name = "Disconnect";
+ action_allowed = m_media_connected;
+ break;
+ case Play:
+ bluez_action = BLUEZ_MEDIA_CONTROL_PLAY;
+ action_name = "Play";
+ break;
+ case Pause:
+ bluez_action = BLUEZ_MEDIA_CONTROL_PAUSE;
+ action_name = "Pause";
+ break;
+ case Stop:
+ bluez_action = BLUEZ_MEDIA_CONTROL_STOP;
+ action_name = "Stop";
+ break;
+ case Next:
+ bluez_action = BLUEZ_MEDIA_CONTROL_NEXT;
+ action_name = "Next";
+ break;
+ case Previous:
+ bluez_action = BLUEZ_MEDIA_CONTROL_PREVIOUS;
+ action_name = "Previous";
+ break;
+ case FastForward:
+ bluez_action = BLUEZ_MEDIA_CONTROL_FASTFORWARD;
+ action_name = "Fastforward";
+ break;
+ case Rewind:
+ bluez_action = BLUEZ_MEDIA_CONTROL_REWIND;
+ action_name = "Rewind";
+ break;
+ case Loop:
+ // Not implemented, but potentially possible with bluez-glib addition
+ default:
+ break;
+ }
+#ifdef BLUETOOTH_EVENT_DEBUG
+ qDebug() << "Bluetooth::media_control: enter, action = " << action_name;
+ qDebug() << "Bluetooth::media_control: m_connected = " << m_connected
+ << ", m_media_connected = " << m_media_connected;
+#endif
+
+ if (!(m_connected && action_allowed)) {
+ qDebug() << "Bluetooth::media_control: not connected or invalid action!";
+ return;
+ }
+
+ QByteArray device_ba = m_connected_device.toLocal8Bit();
+ const char *device_cstr = device_ba.data();
+ bluez_device_avrcp_controls(device_cstr, bluez_action);
+}
+
+
+// Private
+
+void Bluetooth::init_adapter_state(const QString &adapter)
{
// Get initial power state
GVariant *reply = NULL;
@@ -171,7 +253,7 @@ void Bluetooth::init_adapter_state(QString adapter)
if (rc && reply) {
GVariantDict *props_dict = g_variant_dict_new(reply);
gboolean powered = FALSE;
- if (g_variant_dict_lookup(props_dict, "Powered", "b", &powered)) {
+ if (g_variant_dict_lookup(props_dict, "Powered", "b", &powered)) {
if (m_power != powered) {
m_power = powered;
emit powerChanged(m_power);
@@ -179,10 +261,16 @@ void Bluetooth::init_adapter_state(QString adapter)
}
g_variant_dict_unref(props_dict);
g_variant_unref(reply);
- }
+ }
// Get initial device list
refresh_device_list();
+
+ // Do a refresh of the media state to handle the situation where
+ // a client app has been started after a phone has been connected
+ // (and thus misses seeing the related events go by).
+ if (m_handle_media)
+ refresh_media_state();
}
void Bluetooth::refresh_device_list(void)
@@ -202,8 +290,12 @@ void Bluetooth::refresh_device_list(void)
GVariant *var = NULL;
while (g_variant_iter_next(array, "{&sv}", &key, &var)) {
BluetoothDevice *device = m_bluetooth->updateDeviceProperties(nullptr, key, var);
- if (device)
+ if (device) {
m_bluetooth->addDevice(device);
+ if (device->connected()) {
+ update_connected_state(device->id(), true);
+ }
+ }
g_variant_unref(var);
}
@@ -211,6 +303,42 @@ void Bluetooth::refresh_device_list(void)
g_variant_unref(reply);
}
+void Bluetooth::refresh_media_state()
+{
+ if (!(m_handle_media && m_connected && m_connected_device.count()))
+ return;
+
+ QByteArray device_ba = m_connected_device.toLocal8Bit();
+ const char *device_cstr = device_ba.data();
+
+ GVariant *reply = NULL;
+ if (!bluez_get_media_control_properties(device_cstr, &reply))
+ return;
+
+ GVariantDict *props_dict = g_variant_dict_new(reply);
+ if (!props_dict) {
+ g_variant_unref(reply);
+ return;
+ }
+
+ gboolean connected = FALSE;
+ if (g_variant_dict_lookup(props_dict, "Connected", "b", &connected)) {
+ update_media_connected_state(connected);
+
+ GVariant *player_reply = NULL;
+ if(bluez_get_media_player_properties(device_cstr, &player_reply)) {
+ QVariantMap tmp;
+ m_event_handler->parse_media_player_properties(player_reply, tmp);
+ if (!tmp.empty())
+ update_media_properties(tmp);
+
+ g_variant_unref(player_reply);
+ }
+ }
+ g_variant_dict_unref(props_dict);
+ g_variant_unref(reply);
+}
+
void Bluetooth::set_discovery_filter(void)
{
QList<QString> values = uuids.values();
@@ -233,7 +361,7 @@ void Bluetooth::set_discovery_filter(void)
g_free(transport);
}
-void Bluetooth::update_adapter_power(bool powered)
+void Bluetooth::update_adapter_power(const bool powered)
{
if (!powered)
m_bluetooth->removeAllDevices();
@@ -251,11 +379,50 @@ void Bluetooth::update_adapter_power(bool powered)
bool discoverable = m_discoverable;
m_discoverable = false;
if (discoverable != m_discoverable)
- emit discoverableChanged();
+ emit discoverableChanged(false);
+ }
+}
+
+void Bluetooth::update_connected_state(const QString &device, const bool connected)
+{
+#ifdef BLUETOOTH_EVENT_DEBUG
+ qDebug() << "Bluetooth::update_connected_state: device = " << device
+ << ", connected = " << connected;
+#endif
+ if (m_connected != connected) {
+ if (!m_connected) {
+ // Connecting
+ m_connected = true;
+ m_connected_device = device;
+ emit connectedChanged(true);
+ } else if (m_connected_device == device) {
+ // Disconnecting
+ m_connected = false;
+ m_connected_device = "";
+ emit connectedChanged(false);
+ } else {
+ qDebug() << "Bluetooth::update_connected_state: ignoring " << device;
+ }
}
}
-void Bluetooth::request_confirmation(int pincode)
+void Bluetooth::update_media_connected_state(const bool connected)
+{
+#ifdef BLUETOOTH_EVENT_DEBUG
+ qDebug() << "Bluetooth::update_media_connected_state: connected = " << connected;
+#endif
+ if (m_media_connected != connected) {
+ m_media_connected = connected;
+ emit mediaConnectedChanged(connected);
+ }
+}
+
+void Bluetooth::update_media_properties(const QVariantMap &metadata)
+{
+ emit mediaPropertiesChanged(metadata);
+}
+
+void Bluetooth::request_confirmation(const int pincode)
{
QString pincode_str;
pincode_str.setNum(pincode);
diff --git a/bluetooth/bluetooth.h b/bluetooth/bluetooth.h
index c7ef55c..09fb4d9 100644
--- a/bluetooth/bluetooth.h
+++ b/bluetooth/bluetooth.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018-2021 Konsulko Group
+ * Copyright (C) 2018-2022 Konsulko Group
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,64 +26,90 @@ class BluetoothEventHandler;
class Bluetooth : public QObject
{
- Q_OBJECT
- Q_PROPERTY(bool power READ power WRITE setPower NOTIFY powerChanged)
- Q_PROPERTY(bool discoverable READ discoverable WRITE setDiscoverable NOTIFY discoverableChanged)
+ Q_OBJECT
+ Q_PROPERTY(bool power READ power WRITE setPower NOTIFY powerChanged)
+ Q_PROPERTY(bool discoverable READ discoverable WRITE setDiscoverable NOTIFY discoverableChanged)
+ Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
+ Q_PROPERTY(bool mediaConnected READ mediaConnected NOTIFY mediaConnectedChanged)
- public:
- explicit Bluetooth(bool register_agent, QQmlContext *context, QObject * parent = Q_NULLPTR);
- virtual ~Bluetooth();
+public:
+ explicit Bluetooth(bool register_agent,
+ QQmlContext *context,
+ bool handle_media = false,
+ QObject *parent = Q_NULLPTR);
+ virtual ~Bluetooth();
- void setPower(bool);
- void setDiscoverable(bool);
+ void setPower(bool);
+ void setDiscoverable(bool);
- Q_INVOKABLE void start(void);
+ Q_INVOKABLE void start(void);
- Q_INVOKABLE void start_discovery(void);
- Q_INVOKABLE void stop_discovery(void);
+ Q_INVOKABLE void start_discovery(void);
+ Q_INVOKABLE void stop_discovery(void);
- Q_INVOKABLE void remove_device(QString device);
- Q_INVOKABLE void pair(QString device);
- Q_INVOKABLE void cancel_pair(void);
+ Q_INVOKABLE void remove_device(QString device);
+ Q_INVOKABLE void pair(QString device);
+ Q_INVOKABLE void cancel_pair(void);
- Q_INVOKABLE void connect(QString device, QString uuid);
- Q_INVOKABLE void connect(QString device);
+ Q_INVOKABLE void connect(QString device, QString uuid);
+ Q_INVOKABLE void connect(QString device);
- Q_INVOKABLE void disconnect(QString device, QString uuid);
- Q_INVOKABLE void disconnect(QString device);
+ Q_INVOKABLE void disconnect(QString device, QString uuid);
+ Q_INVOKABLE void disconnect(QString device);
- Q_INVOKABLE void send_confirmation(int pincode);
+ Q_INVOKABLE void send_confirmation(int pincode);
- bool power() const { return m_power; };
- bool discoverable() const { return m_discoverable; };
+ enum MediaAction {
+ Connect, Disconnect,
+ Play, Pause, Stop, Next, Previous, FastForward, Rewind, Loop
+ };
+ Q_ENUM(MediaAction)
- signals:
- void powerChanged(bool state);
- void discoverableChanged();
+ Q_INVOKABLE void media_control(MediaAction action);
+ Q_INVOKABLE void refresh_media_state();
- //void connectionEvent(QJsonObject data);
+ bool power() const { return m_power; };
+ bool discoverable() const { return m_discoverable; };
+ bool connected() const { return m_connected; };
+ bool mediaConnected() const { return m_media_connected; };
+
+signals:
+ void powerChanged(bool state);
+ void discoverableChanged(bool state);
+ void connectedChanged(bool state);
+ void mediaConnectedChanged(bool state);
+
+ void mediaPropertiesChanged(QVariantMap metadata);
void requestConfirmationEvent(QString pincode);
- private:
- QQmlContext *m_context;
- BluetoothModel *m_bluetooth;
- BluetoothEventHandler *m_event_handler;
+private:
+ QQmlContext *m_context;
+ BluetoothModel *m_bluetooth;
+ BluetoothEventHandler *m_event_handler;
bool m_agent;
+ bool m_handle_media;
- void init_adapter_state(QString);
+ void init_adapter_state(const QString &adapter);
void refresh_device_list(void);
- void set_discovery_filter(void);
- void discovery_command(bool);
- void update_adapter_power(bool);
- void request_confirmation(int);
+ void set_discovery_filter(void);
+ void discovery_command(const bool);
+ void update_adapter_power(const bool powered);
+ void update_connected_state(const QString &device, const bool connected);
+ void update_media_connected_state(const bool connected);
+ void update_media_properties(const QVariantMap &metadata);
+ void request_confirmation(const int pincode);
+
+ QString process_uuid(QString uuid) { if (uuid.length() == 36) return uuid; return uuids.value(uuid); };
- QString process_uuid(QString uuid) { if (uuid.length() == 36) return uuid; return uuids.value(uuid); };
+ // values
+ bool m_power;
+ bool m_discoverable;
+ bool m_connected;
+ bool m_media_connected;
- // values
- bool m_power;
- bool m_discoverable;
+ QString m_connected_device;
- QMap<QString, QString> uuids;
+ QMap<QString, QString> uuids;
friend class BluetoothEventHandler;
};
diff --git a/bluetooth/bluetootheventhandler.cpp b/bluetooth/bluetootheventhandler.cpp
index 0acd5f5..a0154bb 100644
--- a/bluetooth/bluetootheventhandler.cpp
+++ b/bluetooth/bluetootheventhandler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 Konsulko Group
+ * Copyright (C) 2021,2022 Konsulko Group
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,20 +16,27 @@
#include <QDebug>
#include <bluez-glib.h>
-
#include "bluetootheventhandler.h"
#include "bluetooth.h"
#include "bluetoothmodel.h"
+#undef BLUETOOTH_EVENT_DEBUG
+
-BluetoothEventHandler::BluetoothEventHandler (Bluetooth *parent, bool register_agent) :
+BluetoothEventHandler::BluetoothEventHandler(Bluetooth *parent, bool register_agent, bool handle_media) :
m_parent(parent),
m_agent(register_agent)
{
bluez_add_adapter_event_callback(adapter_event_cb, this);
bluez_add_device_event_callback(device_event_cb, this);
+
if (register_agent)
bluez_add_agent_event_callback(agent_event_cb, this);
+
+ if (handle_media) {
+ bluez_add_media_control_event_callback(media_control_event_cb, this);
+ bluez_add_media_player_event_callback(media_player_event_cb, this);
+ }
}
BluetoothEventHandler::~BluetoothEventHandler()
@@ -38,6 +45,10 @@ BluetoothEventHandler::~BluetoothEventHandler()
void BluetoothEventHandler::handle_init_event(gchar *adapter, gboolean status)
{
+#ifdef BLUETOOTH_EVENT_DEBUG
+ qDebug() << "BluetoothEventHandler::handle_init_event: enter, status = " << (int) status;
+#endif
+
if (status)
m_parent->init_adapter_state(QString(adapter));
else
@@ -48,6 +59,15 @@ void BluetoothEventHandler::handle_adapter_event(gchar *adapter,
bluez_event_t event,
GVariant *properties)
{
+#ifdef BLUETOOTH_EVENT_DEBUG
+ qDebug() << "BluetoothEventHandler::handle_adapter_event: enter";
+ gchar *p = properties ? g_variant_print(properties, TRUE) : g_strdup("(null)");
+ qDebug() << "BluetoothEventHandler::handle_adapter_event: adapter = "
+ << adapter << ", event = " << (int) event;
+ qDebug() << "BluetoothEventHandler::handle_adapter_event: properties = " << p;
+ g_free(p);
+#endif
+
if (!adapter || event != BLUEZ_EVENT_CHANGE)
return;
@@ -71,6 +91,15 @@ void BluetoothEventHandler::handle_device_event(gchar *adapter,
bluez_event_t event,
GVariant *properties)
{
+#ifdef BLUETOOTH_EVENT_DEBUG
+ qDebug() << "BluetoothEventHandler::handle_device_event: enter";
+ gchar *p = properties ? g_variant_print(properties, TRUE) : g_strdup("(null)");
+ qDebug() << "BluetoothEventHandler::handle_device_event: adapter = "
+ << adapter << ", device = " << device << ", event = " << (int) event;
+ qDebug() << "BluetoothEventHandler::handle_device_event: properties = " << p;
+ g_free(p);
+#endif
+
if (!device)
return;
@@ -91,6 +120,72 @@ void BluetoothEventHandler::handle_device_event(gchar *adapter,
// device not previously in model
m_parent->m_bluetooth->addDevice(new_device);
}
+
+ // Update parent's connected state
+ // NOTE: Currently not worrying about multiple devices being connected
+ GVariantDict *props_dict = g_variant_dict_new(properties);
+ if (props_dict) {
+ gboolean connected = FALSE;
+ if (g_variant_dict_lookup(props_dict, "Connected", "b", &connected)) {
+ m_parent->update_connected_state(QString(device), connected);
+ }
+ g_variant_dict_unref(props_dict);
+ }
+}
+
+void BluetoothEventHandler::handle_media_control_event(gchar *adapter,
+ gchar *device,
+ bluez_event_t event,
+ GVariant *properties)
+{
+#ifdef BLUETOOTH_EVENT_DEBUG
+ qDebug() << "BluetoothEventHandler::handle_media_control_event: enter";
+ gchar *p = properties ? g_variant_print(properties, TRUE) : g_strdup("(null)");
+ qDebug() << "BluetoothEventHandler::handle_media_control_event: adapter = "
+ << adapter << ", device = " << device << ", event = " << (int) event;
+ qDebug() << "BluetoothEventHandler::handle_media_control_event: properties = " << p;
+ g_free(p);
+#endif
+
+ if (event != BLUEZ_EVENT_CHANGE)
+ return;
+
+ // Update parent's media connected state
+ // NOTE: Currently not worrying about multiple devices being connected
+ GVariantDict *props_dict = g_variant_dict_new(properties);
+ if (props_dict) {
+ gboolean connected = FALSE;
+ if (g_variant_dict_lookup(props_dict, "Connected", "b", &connected)) {
+ m_parent->update_media_connected_state(connected);
+ }
+ g_variant_dict_unref(props_dict);
+ }
+
+}
+
+void BluetoothEventHandler::handle_media_player_event(gchar *adapter,
+ gchar *device,
+ gchar *player,
+ bluez_event_t event,
+ GVariant *properties)
+{
+#ifdef BLUETOOTH_EVENT_DEBUG
+ qDebug() << "BluetoothEventHandler::handle_media_player_event: enter";
+ gchar *p = properties ? g_variant_print(properties, TRUE) : g_strdup("(null)");
+ qDebug() << "BluetoothEventHandler::handle_media_player_event: adapter = "
+ << adapter << ", device = " << device << ", player = " << player
+ << ", event = " << (int) event;
+ qDebug() << "BluetoothEventHandler::handle_media_player_event: properties = " << p;
+ g_free(p);
+#endif
+
+ if (event != BLUEZ_EVENT_REMOVE) {
+ QVariantMap tmp;
+ parse_media_player_properties(properties, tmp);
+ if (!tmp.empty()) {
+ m_parent->update_media_properties(tmp);
+ }
+ }
}
void BluetoothEventHandler::handle_agent_event(gchar *device,
@@ -119,3 +214,44 @@ void BluetoothEventHandler::handle_pair_event(gchar *device, gboolean status)
qDebug() << "pairing failed";
}
+void BluetoothEventHandler::parse_media_player_properties(GVariant *properties, QVariantMap &metadata)
+{
+ GVariantDict *props_dict = g_variant_dict_new(properties);
+ if (!props_dict)
+ return;
+
+ GVariant *v = NULL;
+ if (g_variant_dict_lookup(props_dict, "Track", "@a{sv}", &v)) {
+ GVariantDict *track_dict = g_variant_dict_new(v);
+ QVariantMap track;
+ gchar *p = NULL;
+
+ if (g_variant_dict_lookup(track_dict, "Title", "&s", &p))
+ track.insert(QString("title"), QVariant(QString(p)));
+
+ if (g_variant_dict_lookup(track_dict, "Artist", "&s", &p))
+ track.insert(QString("artist"), QVariant(QString(p)));
+
+ if (g_variant_dict_lookup(track_dict, "Album", "&s", &p))
+ track.insert(QString("album"), QVariant(QString(p)));
+
+ unsigned int duration = 0;
+ if (g_variant_dict_lookup(track_dict, "Duration", "u", &duration))
+ track.insert(QString("duration"), QVariant(duration));
+
+ g_variant_dict_unref(track_dict);
+
+ metadata.insert("track", track);
+ }
+
+ unsigned int position = 0;
+ if (g_variant_dict_lookup(props_dict, "Position", "u", &position)) {
+ metadata.insert("position", QVariant(position));
+ }
+
+ gchar *p = NULL;
+ if (g_variant_dict_lookup(props_dict, "Status", "&s", &p))
+ metadata.insert(QString("status"), QVariant(QString(p)));
+
+ g_variant_dict_unref(props_dict);
+}
diff --git a/bluetooth/bluetootheventhandler.h b/bluetooth/bluetootheventhandler.h
index ff970f5..c4dd67a 100644
--- a/bluetooth/bluetootheventhandler.h
+++ b/bluetooth/bluetootheventhandler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 Konsulko Group
+ * Copyright (C) 2021,2022 Konsulko Group
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@ class Bluetooth;
class BluetoothEventHandler
{
public:
- explicit BluetoothEventHandler(Bluetooth *parent, bool register_agent);
+ explicit BluetoothEventHandler(Bluetooth *parent, bool register_agent, bool handle_media = false);
virtual ~BluetoothEventHandler();
static void init_cb(gchar *adapter, gboolean status, gpointer user_data) {
@@ -40,6 +40,10 @@ class BluetoothEventHandler
((BluetoothEventHandler*) user_data)->handle_pair_event(device, status);
}
+ // Helper function callable by parent (instead of vice versa), since Bluetooth
+ // object should not expose glib types.
+ void parse_media_player_properties(GVariant *properties, QVariantMap &metadata);
+
private:
Bluetooth *m_parent;
bool m_agent;
@@ -59,11 +63,46 @@ class BluetoothEventHandler
if (user_data)
((BluetoothEventHandler*) user_data)->handle_agent_event(device, event, properties);
}
+
+ static void media_control_event_cb(gchar *adapter,
+ gchar *device,
+ bluez_event_t event,
+ GVariant *properties,
+ gpointer user_data) {
+ if (user_data)
+ ((BluetoothEventHandler*) user_data)->handle_media_control_event(adapter,
+ device,
+ event,
+ properties);
+ }
+
+ static void media_player_event_cb(gchar *adapter,
+ gchar *device,
+ gchar *player,
+ bluez_event_t event,
+ GVariant *properties,
+ gpointer user_data) {
+ if (user_data)
+ ((BluetoothEventHandler*) user_data)->handle_media_player_event(adapter,
+ device,
+ player,
+ event,
+ properties);
+ }
void handle_init_event(gchar *adapter, gboolean status);
void handle_adapter_event(gchar *adapter, bluez_event_t event, GVariant *properties);
void handle_device_event(gchar *adapter, gchar *device, bluez_event_t event, GVariant *properties);
void handle_agent_event(gchar *device, bluez_agent_event_t event, GVariant *properties);
+ void handle_media_control_event(gchar *adapter,
+ gchar *device,
+ bluez_event_t event,
+ GVariant *properties);
+ void handle_media_player_event(gchar *adapter,
+ gchar *device,
+ gchar *player,
+ bluez_event_t event,
+ GVariant *properties);
void handle_connect_event(gchar *device, gboolean status);
void handle_pair_event(gchar *device, gboolean status);
};