summaryrefslogtreecommitdiffstats
path: root/bluetooth/bluetootheventhandler.cpp
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/bluetootheventhandler.cpp
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/bluetootheventhandler.cpp')
-rw-r--r--bluetooth/bluetootheventhandler.cpp142
1 files changed, 139 insertions, 3 deletions
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);
+}