mirror of
https://github.com/kavishdevar/librepods.git
synced 2026-01-28 22:01:50 +00:00
[Linux] Let users edit Phone bluetooth MAC via GUI (#195)
initial commit
This commit is contained in:
@@ -154,8 +154,28 @@ ApplicationWindow {
|
||||
visible: airPodsTrayApp.airpodsConnected
|
||||
text: "Conversational Awareness"
|
||||
checked: airPodsTrayApp.deviceInfo.conversationalAwareness
|
||||
// Disable when no phone MAC set or using default placeholder
|
||||
enabled: !(PHONE_MAC_ADDRESS === "" || PHONE_MAC_ADDRESS === "00:00:00:00:00:00")
|
||||
onCheckedChanged: airPodsTrayApp.setConversationalAwareness(checked)
|
||||
}
|
||||
|
||||
// Instruction when Conversational Awareness is disabled due to missing phone MAC
|
||||
Row {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 8
|
||||
visible: airPodsTrayApp.airpodsConnected && (PHONE_MAC_ADDRESS === "" || PHONE_MAC_ADDRESS === "00:00:00:00:00:00")
|
||||
|
||||
Label {
|
||||
text: "Set your phone's MAC in Settings to use this feature"
|
||||
font.pixelSize: 12
|
||||
color: "gray"
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Open Settings"
|
||||
onClicked: stackView.push(settingsPage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RoundButton {
|
||||
@@ -269,6 +289,23 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: 10
|
||||
visible: airPodsTrayApp.airpodsConnected
|
||||
|
||||
TextField {
|
||||
id: newPhoneMacField
|
||||
placeholderText: (PHONE_MAC_ADDRESS !== "" ? PHONE_MAC_ADDRESS : "00:00:00:00:00:00")
|
||||
maximumLength: 32
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Change Phone MAC"
|
||||
onClicked: airPodsTrayApp.setPhoneMac(newPhoneMacField.text)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Button {
|
||||
text: "Show Magic Cloud Keys QR"
|
||||
onClicked: keysQrDialog.show()
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include "airpods_packets.h"
|
||||
#include "logger.h"
|
||||
@@ -40,6 +41,7 @@ class AirPodsTrayApp : public QObject {
|
||||
Q_PROPERTY(int retryAttempts READ retryAttempts WRITE setRetryAttempts NOTIFY retryAttemptsChanged)
|
||||
Q_PROPERTY(bool hideOnStart READ hideOnStart CONSTANT)
|
||||
Q_PROPERTY(DeviceInfo *deviceInfo READ deviceInfo CONSTANT)
|
||||
Q_PROPERTY(QString phoneMacStatus READ phoneMacStatus NOTIFY phoneMacStatusChanged)
|
||||
|
||||
public:
|
||||
AirPodsTrayApp(bool debugMode, bool hideOnStart, QQmlApplicationEngine *parent = nullptr)
|
||||
@@ -119,6 +121,7 @@ public:
|
||||
int retryAttempts() const { return m_retryAttempts; }
|
||||
bool hideOnStart() const { return m_hideOnStart; }
|
||||
DeviceInfo *deviceInfo() const { return m_deviceInfo; }
|
||||
QString phoneMacStatus() const { return m_phoneMacStatus; }
|
||||
|
||||
private:
|
||||
bool debugMode;
|
||||
@@ -310,6 +313,51 @@ public slots:
|
||||
emit crossDeviceEnabledChanged(enabled);
|
||||
}
|
||||
|
||||
void setPhoneMac(const QString &mac)
|
||||
{
|
||||
if (mac.isEmpty()) {
|
||||
LOG_WARN("Empty MAC provided, ignoring");
|
||||
m_phoneMacStatus = QStringLiteral("No MAC provided (ignoring)");
|
||||
emit phoneMacStatusChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
// Basic MAC address validation (accepts formats like AA:BB:CC:DD:EE:FF, AABBCCDDEEFF, AA-BB-CC-DD-EE-FF)
|
||||
QRegularExpression re("^([0-9A-Fa-f]{2}([-:]?)){5}[0-9A-Fa-f]{2}$");
|
||||
if (!re.match(mac).hasMatch()) {
|
||||
LOG_ERROR("Invalid MAC address format: " << mac);
|
||||
m_phoneMacStatus = QStringLiteral("Invalid MAC: ") + mac;
|
||||
emit phoneMacStatusChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
// Set environment variable for the running process
|
||||
qputenv("PHONE_MAC_ADDRESS", mac.toUtf8());
|
||||
LOG_INFO("PHONE_MAC_ADDRESS environment variable set to: " << mac);
|
||||
|
||||
m_phoneMacStatus = QStringLiteral("Updated MAC: ") + mac;
|
||||
emit phoneMacStatusChanged();
|
||||
|
||||
// Update QML context property so UI placeholders reflect the new value
|
||||
if (parent) {
|
||||
parent->rootContext()->setContextProperty("PHONE_MAC_ADDRESS", mac);
|
||||
}
|
||||
|
||||
// If a phone socket exists, restart connection using the new MAC
|
||||
if (phoneSocket && phoneSocket->isOpen()) {
|
||||
phoneSocket->close();
|
||||
phoneSocket->deleteLater();
|
||||
phoneSocket = nullptr;
|
||||
}
|
||||
connectToPhone();
|
||||
}
|
||||
|
||||
void updatePhoneMacStatus(const QString &status)
|
||||
{
|
||||
m_phoneMacStatus = status;
|
||||
emit phoneMacStatusChanged();
|
||||
}
|
||||
|
||||
bool writePacketToSocket(const QByteArray &packet, const QString &logMessage)
|
||||
{
|
||||
if (socket && socket->isOpen())
|
||||
@@ -658,6 +706,7 @@ private slots:
|
||||
}
|
||||
QBluetoothAddress phoneAddress("00:00:00:00:00:00"); // Default address, will be overwritten if PHONE_MAC_ADDRESS is set
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
|
||||
if (!env.value("PHONE_MAC_ADDRESS").isEmpty())
|
||||
{
|
||||
phoneAddress = QBluetoothAddress(env.value("PHONE_MAC_ADDRESS"));
|
||||
@@ -854,6 +903,7 @@ signals:
|
||||
void notificationsEnabledChanged(bool enabled);
|
||||
void retryAttemptsChanged(int attempts);
|
||||
void oneBudANCModeChanged(bool enabled);
|
||||
void phoneMacStatusChanged();
|
||||
|
||||
private:
|
||||
QBluetoothSocket *socket = nullptr;
|
||||
@@ -870,6 +920,7 @@ private:
|
||||
DeviceInfo *m_deviceInfo;
|
||||
BleManager *m_bleManager;
|
||||
SystemSleepMonitor *m_systemSleepMonitor = nullptr;
|
||||
QString m_phoneMacStatus;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
@@ -917,6 +968,16 @@ int main(int argc, char *argv[]) {
|
||||
qmlRegisterType<DeviceInfo>("me.kavishdevar.DeviceInfo", 1, 0, "DeviceInfo");
|
||||
AirPodsTrayApp *trayApp = new AirPodsTrayApp(debugMode, hideOnStart, &engine);
|
||||
engine.rootContext()->setContextProperty("airPodsTrayApp", trayApp);
|
||||
|
||||
// Expose PHONE_MAC_ADDRESS environment variable to QML for placeholder in settings
|
||||
{
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
QString phoneMacEnv = env.value("PHONE_MAC_ADDRESS", "");
|
||||
engine.rootContext()->setContextProperty("PHONE_MAC_ADDRESS", phoneMacEnv);
|
||||
// Initialize the visible status in the GUI
|
||||
trayApp->updatePhoneMacStatus(phoneMacEnv.isEmpty() ? QStringLiteral("No phone MAC set") : phoneMacEnv);
|
||||
}
|
||||
|
||||
engine.addImageProvider("qrcode", new QRCodeImageProvider());
|
||||
trayApp->loadMainModule();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user