Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 56 additions & 7 deletions linux/mediacontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,39 +184,41 @@ void MediaController::handleConversationalAwareness(const QByteArray &data) {
}

void MediaController::activateA2dpProfile() {
if (connectedDeviceMacAddress.isEmpty()) {
LOG_WARN("Connected device MAC address is empty, cannot activate A2DP profile");
if (connectedDeviceMacAddress.isEmpty() || m_deviceOutputName.isEmpty()) {
LOG_WARN("Connected device MAC address or output name is empty, cannot activate A2DP profile");
return;
}

LOG_INFO("Activating A2DP profile for AirPods");
int result = QProcess::execute(
"pactl", QStringList()
<< "set-card-profile"
<< "bluez_card." + connectedDeviceMacAddress << "a2dp-sink");
<< m_deviceOutputName << "a2dp-sink");
if (result != 0) {
LOG_ERROR("Failed to activate A2DP profile");
}
}

void MediaController::removeAudioOutputDevice() {
if (connectedDeviceMacAddress.isEmpty()) {
LOG_WARN("Connected device MAC address is empty, cannot remove audio output device");
if (connectedDeviceMacAddress.isEmpty() || m_deviceOutputName.isEmpty()) {
LOG_WARN("Connected device MAC address or output name is empty, cannot remove audio output device");
return;
}

LOG_INFO("Removing AirPods as audio output device");
int result = QProcess::execute(
"pactl", QStringList()
<< "set-card-profile"
<< "bluez_card." + connectedDeviceMacAddress << "off");
<< m_deviceOutputName << "off");
if (result != 0) {
LOG_ERROR("Failed to remove AirPods as audio output device");
}
}

void MediaController::setConnectedDeviceMacAddress(const QString &macAddress) {
connectedDeviceMacAddress = macAddress;
m_deviceOutputName = getAudioDeviceName();
LOG_INFO("Device output name set to: " << m_deviceOutputName);
}

MediaController::MediaState MediaController::mediaStateFromPlayerctlOutput(
Expand Down Expand Up @@ -252,4 +254,51 @@ MediaController::~MediaController() {
playerctlProcess->waitForFinished(1000);
}
}
}
}

QString MediaController::getAudioDeviceName()
{
if (connectedDeviceMacAddress.isEmpty()) { return QString(); }

// Use a cleaner MAC address format for PulseAudio matching
QProcess process;
process.start("pactl", QStringList() << "list" << "sinks");
process.waitForFinished();

QString output = process.readAllStandardOutput();
if (output.isEmpty())
{
QProcess process;
process.start("pactl", QStringList() << "list" << "sinks");
process.waitForFinished();
output = process.readAllStandardOutput();

if (output.isEmpty())
{
LOG_ERROR("Failed to get PulseAudio and PipeWire sink list");
return QString();
}
}

QStringList lines = output.split("\n");

QString currentSinkName;
bool foundDevice = false;

for (const QString &line : lines)
{
if (line.contains("device.name"))
{
currentSinkName = line.mid(line.indexOf(u'"') + 1).trimmed().removeLast();
}

// Look for Bluetooth MAC address in various formats
if (currentSinkName.contains(connectedDeviceMacAddress, Qt::CaseInsensitive))
{
foundDevice = true;
return currentSinkName;
}
}

return QString();
}
2 changes: 2 additions & 0 deletions linux/mediacontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,15 @@ class MediaController : public QObject

private:
MediaState mediaStateFromPlayerctlOutput(const QString &output);
QString getAudioDeviceName();

QDBusInterface *mprisInterface = nullptr;
QProcess *playerctlProcess = nullptr;
bool wasPausedByApp = false;
int initialVolume = -1;
QString connectedDeviceMacAddress;
EarDetectionBehavior earDetectionBehavior = PauseWhenOneRemoved;
QString m_deviceOutputName;
};

#endif // MEDIACONTROLLER_H