Skip to content

Commit

Permalink
Merge pull request #16881 from fritsch/pulsemonitor
Browse files Browse the repository at this point in the history
AESinkPulse: Implement Hotplug monitor
  • Loading branch information
notspiff committed Nov 13, 2019
2 parents 998f52d + 4302b54 commit 7ba1415
Show file tree
Hide file tree
Showing 11 changed files with 384 additions and 108 deletions.
5 changes: 4 additions & 1 deletion xbmc/cores/AudioEngine/AESinkFactory.cpp
Expand Up @@ -85,12 +85,15 @@ IAESink *CAESinkFactory::Create(std::string &device, AEAudioFormat &desiredForma
return nullptr;
}

void CAESinkFactory::EnumerateEx(std::vector<AESinkInfo> &list, bool force)
void CAESinkFactory::EnumerateEx(std::vector<AESinkInfo>& list, bool force, std::string driver)
{
AESinkInfo info;

for(auto reg : m_AESinkRegEntry)
{
if (!driver.empty() && driver != reg.second.sinkName)
continue;

info.m_deviceInfoList.clear();
info.m_sinkName = reg.second.sinkName;
reg.second.enumerateFunc(info.m_deviceInfoList, force);
Expand Down
2 changes: 1 addition & 1 deletion xbmc/cores/AudioEngine/AESinkFactory.h
Expand Up @@ -48,7 +48,7 @@ class CAESinkFactory

static void ParseDevice(std::string &device, std::string &driver);
static IAESink *Create(std::string &device, AEAudioFormat &desiredFormat);
static void EnumerateEx(std::vector<AESinkInfo> &list, bool force);
static void EnumerateEx(std::vector<AESinkInfo>& list, bool force, std::string driver);
static void Cleanup();

protected:
Expand Down
43 changes: 38 additions & 5 deletions xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
Expand Up @@ -448,6 +448,7 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg)
return;

case CActiveAEControlProtocol::DEVICECHANGE:
case CActiveAEControlProtocol::DEVICECOUNTCHANGE:
LoadSettings();
if (!m_settings.device.empty() && CAESinkFactory::HasSinks())
{
Expand Down Expand Up @@ -494,7 +495,7 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg)
{
case CActiveAEControlProtocol::INIT:
m_extError = false;
m_sink.EnumerateSinkList(false);
m_sink.EnumerateSinkList(false, "");
LoadSettings();
Configure();
if (!m_isWinSysReg)
Expand Down Expand Up @@ -622,7 +623,7 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg)
m_extLastDeviceChange.push(now);
UnconfigureSink();
m_controlPort.PurgeOut(CActiveAEControlProtocol::DEVICECHANGE);
m_sink.EnumerateSinkList(true);
m_sink.EnumerateSinkList(true, "");
LoadSettings();
m_extError = false;
Configure();
Expand All @@ -637,6 +638,29 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg)
m_extTimeout = 500;
}
return;
case CActiveAEControlProtocol::DEVICECOUNTCHANGE:
const char* param;
param = reinterpret_cast<const char*>(msg->data);
CLog::Log(LOGDEBUG, "CActiveAE - device count change event from driver: %s", param);
m_sink.EnumerateSinkList(true, param);
if (!m_sink.DeviceExist(m_settings.driver, m_currDevice))
{
UnconfigureSink();
LoadSettings();
m_extError = false;
Configure();
if (!m_extError)
{
m_state = AE_TOP_CONFIGURED_PLAY;
m_extTimeout = 0;
}
else
{
m_state = AE_TOP_ERROR;
m_extTimeout = 500;
}
}
return;
case CActiveAEControlProtocol::PAUSESTREAM:
CActiveAEStream *stream;
stream = *(CActiveAEStream**)msg->data;
Expand Down Expand Up @@ -835,7 +859,8 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg)
if (!displayReset)
{
m_controlPort.PurgeOut(CActiveAEControlProtocol::DEVICECHANGE);
m_sink.EnumerateSinkList(true);
m_controlPort.PurgeOut(CActiveAEControlProtocol::DEVICECOUNTCHANGE);
m_sink.EnumerateSinkList(true, "");
LoadSettings();
}
Configure();
Expand All @@ -855,6 +880,7 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg)
m_extDeferData = false;
return;
case CActiveAEControlProtocol::DEVICECHANGE:
case CActiveAEControlProtocol::DEVICECOUNTCHANGE:
return;
default:
break;
Expand Down Expand Up @@ -1355,12 +1381,12 @@ void CActiveAE::Configure(AEAudioFormat *desiredFmt)

// input buffers
m_vizBuffersInput = new CActiveAEBufferPool(m_internalFormat);
m_vizBuffersInput->Create(2000);
m_vizBuffersInput->Create(2000 + m_stats.GetMaxDelay() * 1000);

// resample buffers
m_vizBuffers = new CActiveAEBufferPoolResample(m_internalFormat, vizFormat, m_settings.resampleQuality);
//! @todo use cache of sync + water level
m_vizBuffers->Create(2000, false, false);
m_vizBuffers->Create(2000 + m_stats.GetMaxDelay() * 1000, false, false);
m_vizInitialized = false;
}
}
Expand Down Expand Up @@ -2861,6 +2887,13 @@ void CActiveAE::DeviceChange()
m_controlPort.SendOutMessage(CActiveAEControlProtocol::DEVICECHANGE);
}

void CActiveAE::DeviceCountChange(std::string driver)
{
const char* name = driver.c_str();
m_controlPort.SendOutMessage(CActiveAEControlProtocol::DEVICECOUNTCHANGE, name,
driver.length() + 1);
}

bool CActiveAE::GetCurrentSinkFormat(AEAudioFormat &SinkFormat)
{
SinkFormat = m_stats.GetCurrentSinkFormat();
Expand Down
2 changes: 2 additions & 0 deletions xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h
Expand Up @@ -73,6 +73,7 @@ class CActiveAEControlProtocol : public Protocol
RECONFIGURE,
SUSPEND,
DEVICECHANGE,
DEVICECOUNTCHANGE,
MUTE,
VOLUME,
PAUSESTREAM,
Expand Down Expand Up @@ -254,6 +255,7 @@ class CActiveAE : public IAE, public IDispResource, private CThread
bool IsSettingVisible(const std::string &settingId) override;
void KeepConfiguration(unsigned int millis) override;
void DeviceChange() override;
void DeviceCountChange(std::string driver) override;
bool GetCurrentSinkFormat(AEAudioFormat &SinkFormat) override;

void RegisterAudioCallback(IAudioCallback* pCallback) override;
Expand Down
47 changes: 41 additions & 6 deletions xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp
Expand Up @@ -205,6 +205,26 @@ bool CActiveAESink::NeedIECPacking()
return true;
}

bool CActiveAESink::DeviceExist(std::string driver, std::string device)
{
if (driver.empty() && m_sink)
driver = m_sink->GetName();

for (const auto& itt : m_sinkInfoList)
{
if (itt.m_sinkName != driver)
continue;

for (auto itt2 : itt.m_deviceInfoList)
{
CAEDeviceInfo& info = itt2;
if (info.m_deviceName == device)
return true;
}
}
return false;
}

enum SINK_STATES
{
S_TOP = 0, // 0
Expand Down Expand Up @@ -661,33 +681,48 @@ void CActiveAESink::Process()
}
}

void CActiveAESink::EnumerateSinkList(bool force)
void CActiveAESink::EnumerateSinkList(bool force, std::string driver)
{
if (!m_sinkInfoList.empty() && !force)
return;

if (!CAESinkFactory::HasSinks())
return;

std::vector<AE::AESinkInfo> tmpList(m_sinkInfoList);

unsigned int c_retry = 4;
m_sinkInfoList.clear();
CAESinkFactory::EnumerateEx(m_sinkInfoList, false);

if (!driver.empty())
{
for (auto const& info : tmpList)
{
if (info.m_sinkName != driver)
m_sinkInfoList.push_back(info);
}
}

CAESinkFactory::EnumerateEx(m_sinkInfoList, false, driver);
while (m_sinkInfoList.empty() && c_retry > 0)
{
CLog::Log(LOGNOTICE, "No Devices found - retry: %d", c_retry);
Sleep(1500);
c_retry--;
// retry the enumeration
CAESinkFactory::EnumerateEx(m_sinkInfoList, true);
CAESinkFactory::EnumerateEx(m_sinkInfoList, true, driver);
}
CLog::Log(LOGNOTICE, "Found %lu Lists of Devices", m_sinkInfoList.size());
PrintSinks();
PrintSinks(driver);
}

void CActiveAESink::PrintSinks()
void CActiveAESink::PrintSinks(std::string& driver)
{
for (auto itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
{
if (!driver.empty() && itt->m_sinkName != driver)
continue;

CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str());
int count = 0;
for (auto itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
Expand All @@ -704,7 +739,7 @@ void CActiveAESink::PrintSinks()

void CActiveAESink::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
{
EnumerateSinkList(false);
EnumerateSinkList(false, "");

for (auto itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
{
Expand Down
5 changes: 3 additions & 2 deletions xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.h
Expand Up @@ -83,20 +83,21 @@ class CActiveAESink : private CThread
{
public:
explicit CActiveAESink(CEvent *inMsgEvent);
void EnumerateSinkList(bool force);
void EnumerateSinkList(bool force, std::string driver);
void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough);
void Start();
void Dispose();
AEDeviceType GetDeviceType(const std::string &device);
bool HasPassthroughDevice();
bool SupportsFormat(const std::string &device, AEAudioFormat &format);
bool DeviceExist(std::string driver, std::string device);
CSinkControlProtocol m_controlPort;
CSinkDataProtocol m_dataPort;

protected:
void Process() override;
void StateMachine(int signal, Protocol *port, Message *msg);
void PrintSinks();
void PrintSinks(std::string& driver);
void GetDeviceFriendlyName(std::string &device);
void OpenSink();
void ReturnBuffers();
Expand Down
5 changes: 5 additions & 0 deletions xbmc/cores/AudioEngine/Interfaces/AE.h
Expand Up @@ -222,6 +222,11 @@ class IAE
*/
virtual void DeviceChange() {}

/**
* Instruct AE to re-initialize, e.g. after ELD change event
*/
virtual void DeviceCountChange(std::string driver) {}

/**
* Get the current sink data format
*
Expand Down

0 comments on commit 7ba1415

Please sign in to comment.