Skip to content
Open
Changes from all 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
45 changes: 37 additions & 8 deletions linux/media/mediacontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,12 @@ void MediaController::handleEarDetection(EarDetection *earDetection)
shouldResume = primaryInEar || secondaryInEar;
}

if (shouldPause && isActiveOutputDeviceAirPods())
// Pause if conditions are met (removed isActiveOutputDeviceAirPods check as it
// fails on some systems where PulseAudio can't detect the Bluetooth card)
if (shouldPause)
{
if (getCurrentMediaState() == Playing)
{
LOG_DEBUG("Pausing playback for ear detection");
pause();
}
LOG_INFO("Ear detection triggered pause");
pause();
}

// Then handle device profile switching
Expand All @@ -65,8 +64,9 @@ void MediaController::handleEarDetection(EarDetection *earDetection)
activateA2dpProfile();

// Resume if conditions are met and we previously paused
if (shouldResume && !pausedByAppServices.isEmpty() && isActiveOutputDeviceAirPods())
if (shouldResume && !pausedByAppServices.isEmpty())
{
LOG_INFO("Ear detection triggered resume");
play();
}
}
Expand Down Expand Up @@ -307,6 +307,24 @@ void MediaController::play()
return;
}

// If we paused via playerctl fallback, resume via playerctl
if (pausedByAppServices.contains("playerctl"))
{
LOG_INFO("Resuming media via playerctl");
int result = QProcess::execute("playerctl", QStringList() << "play");
if (result == 0)
{
LOG_INFO("Resumed media via playerctl");
pausedByAppServices.clear();
}
else
{
LOG_WARN("playerctl play returned: " << result);
}
return;
}
Comment on lines +310 to +325
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Failure path leaves stale state, causing repeated failures.

If playerctl play fails (e.g., playerctl not installed, no player available), pausedByAppServices is not cleared and the function returns early. Subsequent resume attempts will keep trying playerctl and failing indefinitely.

Consider clearing the state on failure or falling back to DBus:

Suggested fix
     int result = QProcess::execute("playerctl", QStringList() << "play");
     if (result == 0)
     {
       LOG_INFO("Resumed media via playerctl");
-      pausedByAppServices.clear();
     }
     else
     {
       LOG_WARN("playerctl play returned: " << result);
     }
+    pausedByAppServices.clear();  // Clear regardless to avoid infinite retry loop
     return;
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// If we paused via playerctl fallback, resume via playerctl
if (pausedByAppServices.contains("playerctl"))
{
LOG_INFO("Resuming media via playerctl");
int result = QProcess::execute("playerctl", QStringList() << "play");
if (result == 0)
{
LOG_INFO("Resumed media via playerctl");
pausedByAppServices.clear();
}
else
{
LOG_WARN("playerctl play returned: " << result);
}
return;
}
// If we paused via playerctl fallback, resume via playerctl
if (pausedByAppServices.contains("playerctl"))
{
LOG_INFO("Resuming media via playerctl");
int result = QProcess::execute("playerctl", QStringList() << "play");
if (result == 0)
{
LOG_INFO("Resumed media via playerctl");
}
else
{
LOG_WARN("playerctl play returned: " << result);
}
pausedByAppServices.clear(); // Clear regardless to avoid infinite retry loop
return;
}
🤖 Prompt for AI Agents
In @linux/media/mediacontroller.cpp around lines 310 - 325, The current early
return after QProcess::execute("playerctl", ...) leaves pausedByAppServices
containing "playerctl" on failure and causes repeated failed attempts; update
the playerctl branch in resume logic (the block that checks
pausedByAppServices.contains("playerctl") and calls QProcess::execute) to clear
or remove the "playerctl" entry from pausedByAppServices on both success and
failure before returning, and on failure additionally attempt the DBus fallback
path (same code used by the non-playerctl path) or log a clear error and
continue to other resume mechanisms; ensure you reference pausedByAppServices,
QProcess::execute, LOG_WARN/LOG_INFO and the surrounding resume method so the
state is always cleared on failure to avoid repeated retries.


// Try to resume via DBus
QDBusConnection bus = QDBusConnection::sessionBus();
int resumedCount = 0;

Expand Down Expand Up @@ -400,7 +418,18 @@ void MediaController::pause()
}
else
{
LOG_INFO("No playing media players found to pause");
// Fallback to playerctl if DBus didn't find any playing media
LOG_INFO("No playing media found via DBus, trying playerctl fallback");
int result = QProcess::execute("playerctl", QStringList() << "pause");
if (result == 0)
{
LOG_INFO("Paused media via playerctl fallback");
pausedByAppServices << "playerctl";
}
else
{
LOG_DEBUG("playerctl fallback returned: " << result);
}
}
}

Expand Down