From 7f2c5787dbfb7024c5031c10434b57c55b0953ba Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Fri, 8 Feb 2013 01:37:26 +0100 Subject: [PATCH] xbmc: add PR2152 upstream patch Signed-off-by: Stephan Raue --- .../xbmc-464-fix-no-devices-found.patch | 276 ------- .../xbmc/patches/xbmc-990.06-PR2152.patch | 766 ++++++++++++++++++ 2 files changed, 766 insertions(+), 276 deletions(-) delete mode 100644 packages/mediacenter/xbmc/patches/xbmc-464-fix-no-devices-found.patch create mode 100644 packages/mediacenter/xbmc/patches/xbmc-990.06-PR2152.patch diff --git a/packages/mediacenter/xbmc/patches/xbmc-464-fix-no-devices-found.patch b/packages/mediacenter/xbmc/patches/xbmc-464-fix-no-devices-found.patch deleted file mode 100644 index 2a3d2ca95f..0000000000 --- a/packages/mediacenter/xbmc/patches/xbmc-464-fix-no-devices-found.patch +++ /dev/null @@ -1,276 +0,0 @@ -From ac29de2eff8fe144fdbe0330dc38036cf546a372 Mon Sep 17 00:00:00 2001 -From: fritsch -Date: Thu, 31 Jan 2013 21:27:56 +0100 -Subject: [PATCH 1/2] AE: make forced enumeration possible - this can be used - to delay startup when now devices are present - ---- - xbmc/cores/AudioEngine/AESinkFactory.cpp | 10 +++++----- - xbmc/cores/AudioEngine/AESinkFactory.h | 2 +- - xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp | 11 +++++++++++ - xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 4 ++-- - xbmc/cores/AudioEngine/Sinks/AESinkALSA.h | 2 +- - xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp | 2 +- - xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h | 2 +- - xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp | 2 +- - xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h | 2 +- - xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp | 2 +- - xbmc/cores/AudioEngine/Sinks/AESinkOSS.h | 2 +- - xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp | 2 +- - xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h | 4 ++-- - 13 files changed, 29 insertions(+), 18 deletions(-) - -diff --git a/xbmc/cores/AudioEngine/AESinkFactory.cpp b/xbmc/cores/AudioEngine/AESinkFactory.cpp -index b066ecd..9917f11 100644 ---- a/xbmc/cores/AudioEngine/AESinkFactory.cpp -+++ b/xbmc/cores/AudioEngine/AESinkFactory.cpp -@@ -129,15 +129,15 @@ IAESink *CAESinkFactory::Create(std::string &device, AEAudioFormat &desiredForma - return NULL; - } - --#define ENUMERATE_SINK(SINK) { \ -+#define ENUMERATE_SINK(SINK, force) { \ - AESinkInfo info; \ - info.m_sinkName = #SINK; \ -- CAESink ##SINK::EnumerateDevicesEx(info.m_deviceInfoList); \ -+ CAESink ##SINK::EnumerateDevicesEx(info.m_deviceInfoList, force); \ - if(!info.m_deviceInfoList.empty()) \ - list.push_back(info); \ - } - --void CAESinkFactory::EnumerateEx(AESinkInfoList &list) -+void CAESinkFactory::EnumerateEx(AESinkInfoList &list, bool force) - { - #if defined(TARGET_WINDOWS) - ENUMERATE_SINK(DirectSound); -@@ -147,10 +147,10 @@ void CAESinkFactory::EnumerateEx(AESinkInfoList &list) - ENUMERATE_SINK(AUDIOTRACK); - #elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD) - #if defined(HAS_ALSA) -- ENUMERATE_SINK(ALSA); -+ ENUMERATE_SINK(ALSA, force); - #endif - -- ENUMERATE_SINK(OSS); -+ ENUMERATE_SINK(OSS, force); - #endif - - } -diff --git a/xbmc/cores/AudioEngine/AESinkFactory.h b/xbmc/cores/AudioEngine/AESinkFactory.h -index 99c53f9..6f8a4e5 100644 ---- a/xbmc/cores/AudioEngine/AESinkFactory.h -+++ b/xbmc/cores/AudioEngine/AESinkFactory.h -@@ -40,6 +40,6 @@ class CAESinkFactory - public: - static void ParseDevice(std::string &device, std::string &driver); - static IAESink *Create(std::string &device, AEAudioFormat &desiredFormat, bool rawPassthrough); -- static void EnumerateEx(AESinkInfoList &list); -+ static void EnumerateEx(AESinkInfoList &list, bool force = false); - }; - -diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp -index 410e20c..8a19ac4 100644 ---- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp -+++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp -@@ -39,6 +39,7 @@ - #include "Interfaces/AESink.h" - #include "Utils/AEUtil.h" - #include "Encoders/AEEncoderFFmpeg.h" -+#include - - using namespace std; - -@@ -74,7 +75,17 @@ - m_outputStageFn (NULL ), - m_streamStageFn (NULL ) - { -+ unsigned int c_retry = 5; - CAESinkFactory::EnumerateEx(m_sinkInfoList); -+ while(m_sinkInfoList.size() == 0 && c_retry > 0) -+ { -+ CLog::Log(LOGNOTICE, "No Devices found - retry: %d", c_retry); -+ usleep(2000000); -+ c_retry--; -+ // retry the enumeration -+ CAESinkFactory::EnumerateEx(m_sinkInfoList, true); -+ } -+ CLog::Log(LOGNOTICE, "Found %lu Lists of Devices", m_sinkInfoList.size()); - for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt) - { - CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str()); -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -index 91218a4..b0d6bb1 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -@@ -676,11 +676,11 @@ bool CAESinkALSA::OpenPCMDevice(const std::string &name, const std::string ¶ - return false; - } - --void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list) -+void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) - { - /* ensure that ALSA has been initialized */ - snd_lib_error_set_handler(sndLibErrorHandler); -- if(!snd_config) -+ if(!snd_config || force) - snd_config_update(); - - snd_config_t *config; -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h -index db1ba80..c1b1c76 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h -@@ -50,7 +50,7 @@ class CAESinkALSA : public IAESink - virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); - virtual void Drain (); - -- static void EnumerateDevicesEx(AEDeviceInfoList &list); -+ static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false); - private: - CAEChannelInfo GetChannelLayout(AEAudioFormat format); - void GetAESParams(const AEAudioFormat format, std::string& params); -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp -index e8a7876..8f23b41 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp -@@ -236,7 +236,7 @@ void CAESinkAUDIOTRACK::SetVolume(float volume) - m_volume_changed = true; - } - --void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list) -+void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) - { - m_info.m_channels.Reset(); - m_info.m_dataFormats.clear(); -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h -index 46b3551..bbb7856 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h -@@ -43,7 +43,7 @@ class CAESinkAUDIOTRACK : public CThread, public IAESink - virtual void Drain (); - virtual bool HasVolume (); - virtual void SetVolume (float volume); -- static void EnumerateDevicesEx(AEDeviceInfoList &list); -+ static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false); - - private: - virtual void Process(); -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp -index 4d3d41e..c9680e7 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp -@@ -464,7 +464,7 @@ double CAESinkDirectSound::GetCacheTotal() - return (double)m_dwBufferLen / (double)m_AvgBytesPerSec; - } - --void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList) -+void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force) - { - CAEDeviceInfo deviceInfo; - -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h -index 9f54090..2e6209b 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h -@@ -43,7 +43,7 @@ class CAESinkDirectSound : public IAESink - virtual double GetCacheTime (); - virtual double GetCacheTotal (); - virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); -- static void EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList); -+ static void EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList, bool force = false); - private: - void AEChannelsFromSpeakerMask(DWORD speakers); - DWORD SpeakerMaskFromAEChannels(const CAEChannelInfo &channels); -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp -index 06b9a7f..970e236 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp -@@ -427,7 +427,7 @@ void CAESinkOSS::Drain() - // ??? - } - --void CAESinkOSS::EnumerateDevicesEx(AEDeviceInfoList &list) -+void CAESinkOSS::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) - { - int mixerfd; - const char * mixerdev = "/dev/mixer"; -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h b/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h -index aa8a9f8..7e2db8b 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h -@@ -43,7 +43,7 @@ class CAESinkOSS : public IAESink - virtual double GetCacheTotal () { return 0.0; } /* FIXME */ - virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); - virtual void Drain (); -- static void EnumerateDevicesEx(AEDeviceInfoList &list); -+ static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false); - private: - int m_fd; - std::string m_device; -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp -index 8475d60..f238d75 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp -@@ -559,7 +559,7 @@ bool CAESinkWASAPI::SoftResume() - return false; - } - --void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList) -+void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force) - { - IMMDeviceEnumerator* pEnumerator = NULL; - IMMDeviceCollection* pEnumDevices = NULL; -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h -index a0c567a..7111ea9 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h -@@ -45,7 +45,7 @@ class CAESinkWASAPI : public IAESink - virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); - virtual bool SoftSuspend (); - virtual bool SoftResume (); -- static void EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList); -+ static void EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList, bool force = false); - private: - bool InitializeExclusive(AEAudioFormat &format); - void AEChannelsFromSpeakerMask(DWORD speakers); -@@ -78,4 +78,4 @@ class CAESinkWASAPI : public IAESink - unsigned int m_uiBufferLen; /* wasapi endpoint buffer size, in frames */ - double m_avgTimeWaiting; /* time between next buffer of data from SoftAE and driver call for data */ - double m_sinkLatency; /* time in seconds of total duration of the two WASAPI buffers */ --}; -\ No newline at end of file -+}; --- -1.7.10 - - -From b236f0a78079f522f8f9743098820e6301e27625 Mon Sep 17 00:00:00 2001 -From: fritsch -Date: Fri, 1 Feb 2013 13:05:24 +0100 -Subject: [PATCH 2/2] AE: recreate alsa source tree to find new devices - ---- - xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -index b0d6bb1..61848a1 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -@@ -681,7 +681,13 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) - /* ensure that ALSA has been initialized */ - snd_lib_error_set_handler(sndLibErrorHandler); - if(!snd_config || force) -+ { -+ if(force) -+ snd_config_update_free_global(); -+ - snd_config_update(); -+ } -+ - - snd_config_t *config; - snd_config_copy(&config, snd_config); --- -1.7.10 - diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.06-PR2152.patch b/packages/mediacenter/xbmc/patches/xbmc-990.06-PR2152.patch new file mode 100644 index 0000000000..f9d3f01434 --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.06-PR2152.patch @@ -0,0 +1,766 @@ +From 76c77d69ad5c08ee3dd0713201d263f50d6593ca Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Fri, 1 Feb 2013 15:33:19 +0100 +Subject: [PATCH 1/5] AE: introduce force flag into interface + +--- + xbmc/cores/AudioEngine/AESinkFactory.cpp | 10 +++++----- + xbmc/cores/AudioEngine/AESinkFactory.h | 2 +- + xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 2 +- + xbmc/cores/AudioEngine/Sinks/AESinkALSA.h | 2 +- + xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp | 2 +- + xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h | 2 +- + xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp | 2 +- + xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h | 2 +- + xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp | 2 +- + xbmc/cores/AudioEngine/Sinks/AESinkOSS.h | 2 +- + xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp | 2 +- + xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h | 4 ++-- + 12 files changed, 17 insertions(+), 17 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/AESinkFactory.cpp b/xbmc/cores/AudioEngine/AESinkFactory.cpp +index b066ecd..9917f11 100644 +--- a/xbmc/cores/AudioEngine/AESinkFactory.cpp ++++ b/xbmc/cores/AudioEngine/AESinkFactory.cpp +@@ -129,15 +129,15 @@ IAESink *CAESinkFactory::Create(std::string &device, AEAudioFormat &desiredForma + return NULL; + } + +-#define ENUMERATE_SINK(SINK) { \ ++#define ENUMERATE_SINK(SINK, force) { \ + AESinkInfo info; \ + info.m_sinkName = #SINK; \ +- CAESink ##SINK::EnumerateDevicesEx(info.m_deviceInfoList); \ ++ CAESink ##SINK::EnumerateDevicesEx(info.m_deviceInfoList, force); \ + if(!info.m_deviceInfoList.empty()) \ + list.push_back(info); \ + } + +-void CAESinkFactory::EnumerateEx(AESinkInfoList &list) ++void CAESinkFactory::EnumerateEx(AESinkInfoList &list, bool force) + { + #if defined(TARGET_WINDOWS) + ENUMERATE_SINK(DirectSound); +@@ -147,10 +147,10 @@ void CAESinkFactory::EnumerateEx(AESinkInfoList &list) + ENUMERATE_SINK(AUDIOTRACK); + #elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD) + #if defined(HAS_ALSA) +- ENUMERATE_SINK(ALSA); ++ ENUMERATE_SINK(ALSA, force); + #endif + +- ENUMERATE_SINK(OSS); ++ ENUMERATE_SINK(OSS, force); + #endif + + } +diff --git a/xbmc/cores/AudioEngine/AESinkFactory.h b/xbmc/cores/AudioEngine/AESinkFactory.h +index 99c53f9..185f562 100644 +--- a/xbmc/cores/AudioEngine/AESinkFactory.h ++++ b/xbmc/cores/AudioEngine/AESinkFactory.h +@@ -40,6 +40,6 @@ class CAESinkFactory + public: + static void ParseDevice(std::string &device, std::string &driver); + static IAESink *Create(std::string &device, AEAudioFormat &desiredFormat, bool rawPassthrough); +- static void EnumerateEx(AESinkInfoList &list); ++ static void EnumerateEx(AESinkInfoList &list, bool force = false); /* The force flag can be used to indicate the rescan devices */ + }; + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +index 91218a4..df4098e 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +@@ -676,7 +676,7 @@ bool CAESinkALSA::OpenPCMDevice(const std::string &name, const std::string ¶ + return false; + } + +-void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list) ++void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) + { + /* ensure that ALSA has been initialized */ + snd_lib_error_set_handler(sndLibErrorHandler); +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h +index db1ba80..c1b1c76 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h +@@ -50,7 +50,7 @@ class CAESinkALSA : public IAESink + virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); + virtual void Drain (); + +- static void EnumerateDevicesEx(AEDeviceInfoList &list); ++ static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false); + private: + CAEChannelInfo GetChannelLayout(AEAudioFormat format); + void GetAESParams(const AEAudioFormat format, std::string& params); +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp +index e8a7876..8f23b41 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp +@@ -236,7 +236,7 @@ void CAESinkAUDIOTRACK::SetVolume(float scale) + m_volume_changed = true; + } + +-void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list) ++void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) + { + m_info.m_channels.Reset(); + m_info.m_dataFormats.clear(); +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h +index 46b3551..bbb7856 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h +@@ -43,7 +43,7 @@ class CAESinkAUDIOTRACK : public CThread, public IAESink + virtual void Drain (); + virtual bool HasVolume (); + virtual void SetVolume (float volume); +- static void EnumerateDevicesEx(AEDeviceInfoList &list); ++ static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false); + + private: + virtual void Process(); +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp +index 4d3d41e..c9680e7 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp +@@ -464,7 +464,7 @@ double CAESinkDirectSound::GetCacheTotal() + return (double)m_dwBufferLen / (double)m_AvgBytesPerSec; + } + +-void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList) ++void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force) + { + CAEDeviceInfo deviceInfo; + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h +index 9f54090..2e6209b 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h +@@ -43,7 +43,7 @@ class CAESinkDirectSound : public IAESink + virtual double GetCacheTime (); + virtual double GetCacheTotal (); + virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); +- static void EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList); ++ static void EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList, bool force = false); + private: + void AEChannelsFromSpeakerMask(DWORD speakers); + DWORD SpeakerMaskFromAEChannels(const CAEChannelInfo &channels); +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp +index 06b9a7f..970e236 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp +@@ -427,7 +427,7 @@ void CAESinkOSS::Drain() + // ??? + } + +-void CAESinkOSS::EnumerateDevicesEx(AEDeviceInfoList &list) ++void CAESinkOSS::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) + { + int mixerfd; + const char * mixerdev = "/dev/mixer"; +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h b/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h +index aa8a9f8..7e2db8b 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h +@@ -43,7 +43,7 @@ class CAESinkOSS : public IAESink + virtual double GetCacheTotal () { return 0.0; } /* FIXME */ + virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); + virtual void Drain (); +- static void EnumerateDevicesEx(AEDeviceInfoList &list); ++ static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false); + private: + int m_fd; + std::string m_device; +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp +index 8475d60..f238d75 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp +@@ -559,7 +559,7 @@ bool CAESinkWASAPI::SoftResume() + return false; + } + +-void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList) ++void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force) + { + IMMDeviceEnumerator* pEnumerator = NULL; + IMMDeviceCollection* pEnumDevices = NULL; +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h +index a0c567a..7111ea9 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h +@@ -45,7 +45,7 @@ class CAESinkWASAPI : public IAESink + virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); + virtual bool SoftSuspend (); + virtual bool SoftResume (); +- static void EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList); ++ static void EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList, bool force = false); + private: + bool InitializeExclusive(AEAudioFormat &format); + void AEChannelsFromSpeakerMask(DWORD speakers); +@@ -78,4 +78,4 @@ class CAESinkWASAPI : public IAESink + unsigned int m_uiBufferLen; /* wasapi endpoint buffer size, in frames */ + double m_avgTimeWaiting; /* time between next buffer of data from SoftAE and driver call for data */ + double m_sinkLatency; /* time in seconds of total duration of the two WASAPI buffers */ +-}; +\ No newline at end of file ++}; +-- +1.7.10 + + +From 6064764b619a51d5d234d9c83023af6820277dce Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Fri, 1 Feb 2013 15:25:35 +0100 +Subject: [PATCH 2/5] AE: (Alsa) Wait for at least one audio output device + when starting up for max 10 seconds + +--- + xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp | 10 ++++++++++ + xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 7 ++++++- + 2 files changed, 16 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +index 410e20c..30da558 100644 +--- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp ++++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +@@ -74,7 +74,17 @@ + m_outputStageFn (NULL ), + m_streamStageFn (NULL ) + { ++ unsigned int c_retry = 5; + CAESinkFactory::EnumerateEx(m_sinkInfoList); ++ while(m_sinkInfoList.size() == 0 && c_retry > 0) ++ { ++ CLog::Log(LOGNOTICE, "No Devices found - retry: %d", c_retry); ++ Sleep(2000); ++ c_retry--; ++ // retry the enumeration ++ CAESinkFactory::EnumerateEx(m_sinkInfoList, true); ++ } ++ CLog::Log(LOGNOTICE, "Found %lu Lists of Devices", m_sinkInfoList.size()); + for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt) + { + CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str()); +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +index df4098e..bc91096 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +@@ -680,8 +680,13 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) + { + /* ensure that ALSA has been initialized */ + snd_lib_error_set_handler(sndLibErrorHandler); +- if(!snd_config) ++ if(!snd_config || force) ++ { ++ if(force) ++ snd_config_update_free_global(); ++ + snd_config_update(); ++ } + + snd_config_t *config; + snd_config_copy(&config, snd_config); +-- +1.7.10 + + +From 066769f4dd4128232bbcbeb645376ffa8886d263 Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Sat, 2 Feb 2013 11:46:22 +0100 +Subject: [PATCH 3/5] AE: Fix suspend / resume with alsa - (Warning: Race + condition AddPackets still to fix) + +--- + xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp | 138 +++++++++++++++++----- + xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h | 5 + + xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 1 - + 3 files changed, 111 insertions(+), 33 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +index 30da558..36c4d57 100644 +--- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp ++++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +@@ -59,6 +59,8 @@ + m_audiophile (true ), + m_running (false ), + m_reOpen (false ), ++ m_closeSink (false ), ++ m_realSuspend (false ), + m_isSuspended (false ), + m_softSuspend (false ), + m_softSuspendTimer (0 ), +@@ -85,20 +87,7 @@ + CAESinkFactory::EnumerateEx(m_sinkInfoList, true); + } + CLog::Log(LOGNOTICE, "Found %lu Lists of Devices", m_sinkInfoList.size()); +- for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt) +- { +- CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str()); +- int count = 0; +- for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2) +- { +- CLog::Log(LOGNOTICE, " Device %d", ++count); +- CAEDeviceInfo& info = *itt2; +- std::stringstream ss((std::string)info); +- std::string line; +- while(std::getline(ss, line, '\n')) +- CLog::Log(LOGNOTICE, " %s", line.c_str()); +- } +- } ++ PrintSinks(); + } + + CSoftAE::~CSoftAE() +@@ -189,6 +178,20 @@ void CSoftAE::OpenSink() + m_wake.Set(); + } + ++void CSoftAE::InternalCloseSink() ++{ ++ /* close the old sink if it was open */ ++ if (m_sink) ++ { ++ CExclusiveLock sinkLock(m_sinkLock); ++ m_sink->Drain(); ++ m_sink->Deinitialize(); ++ delete m_sink; ++ m_sink = NULL; ++ } ++ m_closeSink = false; ++ m_closeEvent.Set(); ++} + /* this must NEVER be called from outside the main thread or Initialization */ + void CSoftAE::InternalOpenSink() + { +@@ -315,15 +318,8 @@ void CSoftAE::InternalOpenSink() + CExclusiveLock sinkLock(m_sinkLock); + + reInit = true; +- +- /* we are going to open, so close the old sink if it was open */ +- if (m_sink) +- { +- m_sink->Drain(); +- m_sink->Deinitialize(); +- delete m_sink; +- m_sink = NULL; +- } ++ //close the sink cause it gets reinited ++ InternalCloseSink(); + + /* get the display name of the device */ + GetDeviceFriendlyName(device); +@@ -877,10 +873,19 @@ IAEStream *CSoftAE::FreeStream(IAEStream *stream) + RemoveStream(m_playingStreams, (CSoftAEStream*)stream); + RemoveStream(m_streams , (CSoftAEStream*)stream); + lock.Leave(); +- +- /* if it was the master stream we need to reopen before deletion */ +- if (m_masterStream == stream) +- OpenSink(); ++ // Close completely when we go to suspend, reopen as it was old behaviour ++ // m_realSuspend is currently only used on Linux Systems as it is needed ++ // for suspend and resume. Not opening when masterstream stops means ++ // clipping on S/PDIF. ++ if(m_realSuspend) ++ { ++ m_closeEvent.Reset(); ++ m_closeSink = true; ++ m_closeEvent.Wait(); ++ m_wake.Set(); ++ } ++ else if (m_masterStream == stream) ++ OpenSink(); + + delete (CSoftAEStream*)stream; + return NULL; +@@ -986,14 +991,52 @@ bool CSoftAE::Suspend() + CSoftAEStream *stream = *itt; + stream->Flush(); + } ++ #if defined(TARGET_LINUX) ++ /*workaround sinks not playing sound after resume */ ++ StopAllSounds(); ++ CExclusiveLock sinkLock(m_sinkLock); ++ for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt) ++ { ++ itt->m_deviceInfoList.pop_back(); ++ } ++ if(m_sink) ++ { ++ /* Deinitialize and delete current m_sink */ ++ // we don't want that Run reopens our device. ++ // This is the only place m_realSuspend gets set true. ++ // If you find another one - please call for help. ++ // First thing when rewriting: kill this flag and make it generic again. ++ m_realSuspend = true; ++ m_sink->Drain(); ++ m_sink->Deinitialize(); ++ delete m_sink; ++ m_sink = NULL; ++ } ++ // The device list is now empty and must be reenumerated afterwards. ++ m_sinkInfoList.clear(); ++ #endif + + return true; + } + + bool CSoftAE::Resume() + { ++#if defined(TARGET_LINUX) ++ // We must make sure, that we don't return empty. ++ if(m_realSuspend || m_sinkInfoList.empty()) ++ { ++ CLog::Log(LOGDEBUG, "CSoftAE::Resume - Re Enumerating Sinks"); ++ CExclusiveLock sinkLock(m_sinkLock); ++ // Forced enumeration - we are sure that we start completely fresh. ++ CAESinkFactory::EnumerateEx(m_sinkInfoList, true); ++ m_realSuspend = false; ++ sinkLock.Leave(); // we leave here explicitly to not lock while printing new sinks ++ PrintSinks(); ++ } ++#endif + CLog::Log(LOGDEBUG, "CSoftAE::Resume - Resuming AE processing"); + m_isSuspended = false; ++ // we flag reopen + m_reOpen = true; + + return true; +@@ -1030,6 +1073,12 @@ void CSoftAE::Run() + restart = true; + } + ++ //we are told to close the sink ++ if(m_closeSink) ++ { ++ InternalCloseSink(); ++ } ++ + /* Handle idle or forced suspend */ + ProcessSuspend(); + +@@ -1040,6 +1089,7 @@ void CSoftAE::Run() + InternalOpenSink(); + m_isSuspended = false; // exit Suspend state + } ++ + #if defined(TARGET_ANDROID) + else if (m_playingStreams.empty() + && m_playing_sounds.empty() +@@ -1290,6 +1340,24 @@ int CSoftAE::RunTranscodeStage(bool hasAudio) + return encodedFrames; + } + ++void CSoftAE::PrintSinks() ++{ ++ for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt) ++ { ++ CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str()); ++ int count = 0; ++ for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2) ++ { ++ CLog::Log(LOGNOTICE, " Device %d", ++count); ++ CAEDeviceInfo& info = *itt2; ++ std::stringstream ss((std::string)info); ++ std::string line; ++ while(std::getline(ss, line, '\n')) ++ CLog::Log(LOGNOTICE, " %s", line.c_str()); ++ } ++ } ++} ++ + unsigned int CSoftAE::RunRawStreamStage(unsigned int channelCount, void *out, bool &restart) + { + StreamList resumeStreams; +@@ -1424,14 +1492,14 @@ inline void CSoftAE::ProcessSuspend() + /* idle while in Suspend() state until Resume() called */ + /* idle if nothing to play and user hasn't enabled */ + /* continuous streaming (silent stream) in as.xml */ +- while ((m_isSuspended || (m_softSuspend && (curSystemClock > m_softSuspendTimer))) && +- m_running && !m_reOpen) ++ while (m_realSuspend || ((m_isSuspended || (m_softSuspend && (curSystemClock > m_softSuspendTimer))) && ++ m_running && !m_reOpen)) + { +- if (m_sink && !sinkIsSuspended) ++ if (!m_realSuspend && m_sink && !sinkIsSuspended) + { + /* put the sink in Suspend mode */ + CExclusiveLock sinkLock(m_sinkLock); +- if (!m_sink->SoftSuspend()) ++ if (m_sink && !m_sink->SoftSuspend()) + { + sinkIsSuspended = false; //sink cannot be suspended + m_softSuspend = false; //break suspend loop +@@ -1442,11 +1510,17 @@ inline void CSoftAE::ProcessSuspend() + sinkLock.Leave(); + } + ++ // make sure that a outer thread does not have to wait forever ++ if(m_closeSink) ++ { ++ InternalCloseSink(); ++ } ++ + /* idle for platform-defined time */ + m_wake.WaitMSec(SOFTAE_IDLE_WAIT_MSEC); + + /* check if we need to resume for stream or sound */ +- if (!m_isSuspended && (!m_playingStreams.empty() || !m_playing_sounds.empty())) ++ if (!m_realSuspend && !m_isSuspended && (!m_playingStreams.empty() || !m_playing_sounds.empty())) + { + m_reOpen = !m_sink->SoftResume(); // sink returns false if it requires reinit + sinkIsSuspended = false; //sink processing data +diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h +index 56fb417..f3787c9 100644 +--- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h ++++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h +@@ -116,6 +116,7 @@ class CSoftAE : public IThreadedAE + void OpenSink(); + + void InternalOpenSink(); ++ void InternalCloseSink(); + void ResetEncoder(); + bool SetupEncoder(AEAudioFormat &format); + void Deinitialize(); +@@ -136,11 +137,14 @@ class CSoftAE : public IThreadedAE + + /* internal vars */ + bool m_running, m_reOpen; ++ bool m_closeSink; ++ bool m_realSuspend; /* this flag is needed to unload a sink without calling OpenInternal again */ + bool m_isSuspended; /* engine suspended by external function to release audio context */ + bool m_softSuspend; /* latches after last stream or sound played for timer below for idle */ + unsigned int m_softSuspendTimer; /* time in milliseconds to hold sink open before soft suspend for idle */ + CEvent m_reOpenEvent; + CEvent m_wake; ++ CEvent m_closeEvent; + + CCriticalSection m_runningLock; /* released when the thread exits */ + CCriticalSection m_streamLock; /* m_streams lock */ +@@ -242,5 +246,6 @@ class CSoftAE : public IThreadedAE + void RunNormalizeStage (unsigned int channelCount, void *out, unsigned int mixed); + + void RemoveStream(StreamList &streams, CSoftAEStream *stream); ++ void PrintSinks(); + }; + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +index bc91096..328593c 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +@@ -426,7 +426,6 @@ void CAESinkALSA::Deinitialize() + + if (m_pcm) + { +- snd_pcm_drop (m_pcm); + snd_pcm_close(m_pcm); + m_pcm = NULL; + } +-- +1.7.10 + + +From bf5dd9592078037faf5a12e1437c8ef3e8eea1d7 Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Tue, 5 Feb 2013 21:17:10 +0100 +Subject: [PATCH 4/5] AE: Enable SoftSuspend on Linux (Stop h0gg1ng the sound + device) + +--- + xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp | 8 +++++--- + xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 21 +++++++++++++++++++++ + xbmc/cores/AudioEngine/Sinks/AESinkALSA.h | 2 ++ + 3 files changed, 28 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +index 36c4d57..ae8a0e4 100644 +--- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp ++++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +@@ -1475,8 +1475,7 @@ inline void CSoftAE::ProcessSuspend() + { + bool sinkIsSuspended = false; + unsigned int curSystemClock = 0; +- +-#if defined(TARGET_WINDOWS) ++#if defined(TARGET_WINDOWS) || defined(TARGET_LINUX) + if (!m_softSuspend && m_playingStreams.empty() && m_playing_sounds.empty() && + !g_advancedSettings.m_streamSilence) + { +@@ -1488,7 +1487,6 @@ inline void CSoftAE::ProcessSuspend() + if (m_softSuspend) + curSystemClock = XbmcThreads::SystemClockMillis(); + #endif +- + /* idle while in Suspend() state until Resume() called */ + /* idle if nothing to play and user hasn't enabled */ + /* continuous streaming (silent stream) in as.xml */ +@@ -1506,7 +1504,10 @@ inline void CSoftAE::ProcessSuspend() + break; + } + else ++ { ++ CLog::Log(LOGDEBUG, "Suspended the Sink"); + sinkIsSuspended = true; //sink has suspended processing ++ } + sinkLock.Leave(); + } + +@@ -1525,6 +1526,7 @@ inline void CSoftAE::ProcessSuspend() + m_reOpen = !m_sink->SoftResume(); // sink returns false if it requires reinit + sinkIsSuspended = false; //sink processing data + m_softSuspend = false; //break suspend loop ++ CLog::Log(LOGDEBUG, "Resumed the Sink"); + break; + } + } +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +index 328593c..647be04 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +@@ -1129,6 +1129,27 @@ bool CAESinkALSA::GetELD(snd_hctl_t *hctl, int device, CAEDeviceInfo& info, bool + return true; + } + ++bool CAESinkALSA::SoftSuspend() ++{ ++ if(m_pcm) // it is still there ++ Deinitialize(); ++ ++ return true; ++} ++bool CAESinkALSA::SoftResume() ++{ ++ // reinit all the clibber ++ if(!m_pcm) ++ { ++ if (!snd_config) ++ snd_config_update(); ++ ++ Initialize(m_initFormat, m_initDevice); ++ } ++ //we want that AE loves us again ++ return false; // force reinit ++} ++ + void CAESinkALSA::sndLibErrorHandler(const char *file, int line, const char *function, int err, const char *fmt, ...) + { + va_list arg; +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h +index c1b1c76..c60f840 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h +@@ -49,6 +49,8 @@ class CAESinkALSA : public IAESink + virtual double GetCacheTotal (); + virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); + virtual void Drain (); ++ virtual bool SoftSuspend(); ++ virtual bool SoftResume(); + + static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false); + private: +-- +1.7.10 + + +From 03be1460010107832a63d53f8d3fd539255ec1ac Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Wed, 6 Feb 2013 09:03:34 +0100 +Subject: [PATCH 5/5] AE: Wait until we are in a safe state before further + deinitializing the sink (care for deadlocks) + +--- + xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp | 39 +++++++++++++++++----- + xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h | 1 + + 2 files changed, 31 insertions(+), 9 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +index ae8a0e4..343758c 100644 +--- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp ++++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +@@ -1006,11 +1006,18 @@ bool CSoftAE::Suspend() + // This is the only place m_realSuspend gets set true. + // If you find another one - please call for help. + // First thing when rewriting: kill this flag and make it generic again. ++ m_saveSuspend.Reset(); + m_realSuspend = true; ++ // wait until we are looping in ProcessSuspend() ++ m_saveSuspend.Wait(); + m_sink->Drain(); + m_sink->Deinitialize(); + delete m_sink; + m_sink = NULL; ++ // signal anybody, that the sink is closed now ++ // this should help us not to run into deadlocks ++ if(m_closeSink) ++ m_closeEvent.Set(); + } + // The device list is now empty and must be reenumerated afterwards. + m_sinkInfoList.clear(); +@@ -1086,6 +1093,13 @@ void CSoftAE::Run() + if (m_reOpen || restart || !m_sink) + { + CLog::Log(LOGDEBUG, "CSoftAE::Run - Sink restart flagged"); ++ // ProcessSuspending() cannot guarantee that we get our sink back softresumed ++ if(m_sink && m_softSuspend) ++ { ++ m_sink->SoftResume(); ++ m_softSuspend = false; ++ CLog::Log(LOGDEBUG, "CSoftAE::Run - Soft resumed the sink outside"); ++ } + InternalOpenSink(); + m_isSuspended = false; // exit Suspend state + } +@@ -1510,22 +1524,29 @@ inline void CSoftAE::ProcessSuspend() + } + sinkLock.Leave(); + } +- +- // make sure that a outer thread does not have to wait forever +- if(m_closeSink) +- { +- InternalCloseSink(); +- } ++ // Signal that the realSuspend can go on now. ++ // Idea: Outer thread calls Suspend() - but ++ // because of AddPackets does not care about locks, we must make ++ // sure, that our school bus (AE::Run) is currently driving through ++ // some gas station, before we move away the sink. ++ if(m_realSuspend) ++ m_saveSuspend.Set(); + + /* idle for platform-defined time */ + m_wake.WaitMSec(SOFTAE_IDLE_WAIT_MSEC); + +- /* check if we need to resume for stream or sound */ ++ /* check if we need to resume for stream or sound or somebody wants to open us ++ * the suspend checks are only there to: ++ * a) not run out of softSuspend directly when we are sleeping ++ * b) nail(!) the thread during real Suspend into this method ++ * Note: It is not enough to check the streams buffer, cause it might not be filled yet ++ * We have to check after ProcessSuspending() if the sink is still in softsleep and resume it ++ */ + if (!m_realSuspend && !m_isSuspended && (!m_playingStreams.empty() || !m_playing_sounds.empty())) + { +- m_reOpen = !m_sink->SoftResume(); // sink returns false if it requires reinit ++ m_reOpen = m_reOpen || !m_sink->SoftResume(); // sink returns false if it requires reinit + sinkIsSuspended = false; //sink processing data +- m_softSuspend = false; //break suspend loop ++ m_softSuspend = false; //break suspend loop (under some conditions) + CLog::Log(LOGDEBUG, "Resumed the Sink"); + break; + } +diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h +index f3787c9..9d6399e 100644 +--- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h ++++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h +@@ -145,6 +145,7 @@ class CSoftAE : public IThreadedAE + CEvent m_reOpenEvent; + CEvent m_wake; + CEvent m_closeEvent; ++ CEvent m_saveSuspend; + + CCriticalSection m_runningLock; /* released when the thread exits */ + CCriticalSection m_streamLock; /* m_streams lock */ +-- +1.7.10 +