Skip to content

Commit

Permalink
Merge pull request xbmc#25043 from neo1973/pipewire_pulse
Browse files Browse the repository at this point in the history
 [AudioEngine] Make a smarter choice between PulseAudio and PipeWire
  • Loading branch information
neo1973 authored Apr 26, 2024
2 parents 4ee6643 + 6cad373 commit 85519a6
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 16 deletions.
54 changes: 50 additions & 4 deletions xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
#include <memory>
#include <mutex>

#include <pulse/context.h>
#include <pulse/introspect.h>

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

Expand All @@ -27,7 +30,7 @@ class CDriverMonitor
public:
CDriverMonitor() = default;
virtual ~CDriverMonitor();
bool Start();
bool Start(bool allowPipeWireCompatServer);
bool IsInitialized();

CCriticalSection m_sec;
Expand Down Expand Up @@ -315,6 +318,21 @@ static void SinkChangedCallback(pa_context *c, pa_subscription_event_type_t t, u
}
}

struct ServerInfoStruct
{
pa_threaded_mainloop* m_mainloop;
bool m_isInfoSet{false};
std::string m_serverName;
};

static void ServerInfoCallback(pa_context* c, const pa_server_info* i, void* userdata)
{
auto serverInfo = reinterpret_cast<ServerInfoStruct*>(userdata);
serverInfo->m_serverName = i->server_name;
serverInfo->m_isInfoSet = true;
pa_threaded_mainloop_signal(serverInfo->m_mainloop, 0);
}

struct SinkInfoStruct
{
AEDeviceInfoList *list;
Expand Down Expand Up @@ -656,7 +674,7 @@ bool CDriverMonitor::IsInitialized()
return m_isInit;
}

bool CDriverMonitor::Start()
bool CDriverMonitor::Start(bool allowPipeWireCompatServer)
{
if (!SetupContext(nullptr, "KodiDriver", &m_pContext, &m_pMainLoop))
{
Expand All @@ -666,6 +684,30 @@ bool CDriverMonitor::Start()

pa_threaded_mainloop_lock(m_pMainLoop);

ServerInfoStruct serverInfo;
serverInfo.m_mainloop = m_pMainLoop;
pa_context_get_server_info(m_pContext, ServerInfoCallback, &serverInfo);
while (!serverInfo.m_isInfoSet)
pa_threaded_mainloop_wait(m_pMainLoop);

CLog::Log(LOGINFO, "PulseAudio: Server name: {}", serverInfo.m_serverName);

#ifdef HAS_PIPEWIRE
// If Kodi is build with PipeWire support we prefer native PipeWire over the
// PulseAudio compatibility layer IF NOT PulseAudio is explicitly selected
if (!allowPipeWireCompatServer)
{
// Check the PulseAudio server name. If it contains PipeWire in any form
// it is the compatibility layer provided by PipeWire
if (StringUtils::Contains(serverInfo.m_serverName, "pipewire", true))
{
CLog::Log(LOGINFO, "PulseAudio: Server is PipeWire, bail and use native PipeWire interface");
pa_threaded_mainloop_unlock(m_pMainLoop);
return false;
}
}
#endif

m_isInit = true;

std::unique_lock<CCriticalSection> lock(m_sec);
Expand All @@ -687,7 +729,7 @@ bool CDriverMonitor::Start()

std::unique_ptr<CDriverMonitor> CAESinkPULSE::m_pMonitor;

bool CAESinkPULSE::Register()
bool CAESinkPULSE::Register(bool allowPipeWireCompatServer)
{
// check if pulseaudio is actually available
pa_simple *s;
Expand All @@ -708,7 +750,11 @@ bool CAESinkPULSE::Register()
}

m_pMonitor = std::make_unique<CDriverMonitor>();
m_pMonitor->Start();
if (!m_pMonitor->Start(allowPipeWireCompatServer))
{
m_pMonitor.reset();
return false;
}

AE::AESinkRegEntry entry;
entry.sinkName = "PULSE";
Expand Down
2 changes: 1 addition & 1 deletion xbmc/cores/AudioEngine/Sinks/AESinkPULSE.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class CAESinkPULSE : public IAESink
CAESinkPULSE();
~CAESinkPULSE() override;

static bool Register();
static bool Register(bool allowPipeWireCompatServer);
static std::unique_ptr<IAESink> Create(std::string& device, AEAudioFormat& desiredFormat);
static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false);
static void Cleanup();
Expand Down
6 changes: 3 additions & 3 deletions xbmc/platform/freebsd/PlatformFreebsd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ bool CPlatformFreebsd::InitStageOne()
}
else if (sink == "pulseaudio")
{
OPTIONALS::PulseAudioRegister();
OPTIONALS::PulseAudioRegister(true);
}
else if (sink == "oss")
{
Expand All @@ -102,11 +102,11 @@ bool CPlatformFreebsd::InitStageOne()
else if (sink == "alsa+pulseaudio")
{
OPTIONALS::ALSARegister();
OPTIONALS::PulseAudioRegister();
OPTIONALS::PulseAudioRegister(true);
}
else
{
if (!OPTIONALS::PulseAudioRegister())
if (!OPTIONALS::PulseAudioRegister(false))
{
if (!OPTIONALS::ALSARegister())
{
Expand Down
6 changes: 3 additions & 3 deletions xbmc/platform/linux/OptionalsReg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ bool OPTIONALS::ALSARegister()

#ifdef HAS_PULSEAUDIO
#include "cores/AudioEngine/Sinks/AESinkPULSE.h"
bool OPTIONALS::PulseAudioRegister()
bool OPTIONALS::PulseAudioRegister(bool allowPipeWireCompatServer)
{
bool ret = CAESinkPULSE::Register();
bool ret = CAESinkPULSE::Register(allowPipeWireCompatServer);
return ret;
}
#else
bool OPTIONALS::PulseAudioRegister()
bool OPTIONALS::PulseAudioRegister(bool)
{
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion xbmc/platform/linux/OptionalsReg.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ bool ALSARegister();

namespace OPTIONALS
{
bool PulseAudioRegister();
bool PulseAudioRegister(bool allowPipeWireCompatServer);
}

//-----------------------------------------------------------------------------
Expand Down
8 changes: 4 additions & 4 deletions xbmc/platform/linux/PlatformLinux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ bool CPlatformLinux::InitStageOne()
}
else if (sink == "pulseaudio")
{
OPTIONALS::PulseAudioRegister();
OPTIONALS::PulseAudioRegister(true);
}
else if (sink == "pipewire")
{
Expand All @@ -114,13 +114,13 @@ bool CPlatformLinux::InitStageOne()
else if (sink == "alsa+pulseaudio")
{
OPTIONALS::ALSARegister();
OPTIONALS::PulseAudioRegister();
OPTIONALS::PulseAudioRegister(true);
}
else
{
if (!OPTIONALS::PipewireRegister())
if (!OPTIONALS::PulseAudioRegister(false))
{
if (!OPTIONALS::PulseAudioRegister())
if (!OPTIONALS::PipewireRegister())
{
if (!OPTIONALS::ALSARegister())
{
Expand Down

0 comments on commit 85519a6

Please sign in to comment.