diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.06-PR2152.patch b/packages/mediacenter/xbmc/patches/xbmc-990.06-PR2152.patch index f9d3f01434..3bb40ef921 100644 --- a/packages/mediacenter/xbmc/patches/xbmc-990.06-PR2152.patch +++ b/packages/mediacenter/xbmc/patches/xbmc-990.06-PR2152.patch @@ -1,28 +1,7 @@ -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 +diff -Naur xbmc-12.0.1/xbmc/cores/AudioEngine/AESinkFactory.cpp xbmc-12.0.1.patch/xbmc/cores/AudioEngine/AESinkFactory.cpp +--- xbmc-12.0.1/xbmc/cores/AudioEngine/AESinkFactory.cpp 2013-02-08 00:07:33.000000000 +0100 ++++ xbmc-12.0.1.patch/xbmc/cores/AudioEngine/AESinkFactory.cpp 2013-02-09 22:42:48.089803355 +0100 +@@ -129,15 +129,15 @@ return NULL; } @@ -41,7 +20,7 @@ index b066ecd..9917f11 100644 { #if defined(TARGET_WINDOWS) ENUMERATE_SINK(DirectSound); -@@ -147,10 +147,10 @@ void CAESinkFactory::EnumerateEx(AESinkInfoList &list) +@@ -147,10 +147,10 @@ ENUMERATE_SINK(AUDIOTRACK); #elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD) #if defined(HAS_ALSA) @@ -54,11 +33,10 @@ index b066ecd..9917f11 100644 #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 +diff -Naur xbmc-12.0.1/xbmc/cores/AudioEngine/AESinkFactory.h xbmc-12.0.1.patch/xbmc/cores/AudioEngine/AESinkFactory.h +--- xbmc-12.0.1/xbmc/cores/AudioEngine/AESinkFactory.h 2013-02-08 00:07:33.000000000 +0100 ++++ xbmc-12.0.1.patch/xbmc/cores/AudioEngine/AESinkFactory.h 2013-02-09 22:42:48.089803355 +0100 +@@ -40,6 +40,6 @@ public: static void ParseDevice(std::string &device, std::string &driver); static IAESink *Create(std::string &device, AEAudioFormat &desiredFormat, bool rawPassthrough); @@ -66,234 +44,27 @@ index 99c53f9..185f562 100644 + 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 +diff -Naur xbmc-12.0.1/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +--- xbmc-12.0.1/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp 2013-02-08 00:07:33.000000000 +0100 ++++ xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp 2013-02-09 22:42:48.101803299 +0100 @@ -59,6 +59,8 @@ m_audiophile (true ), m_running (false ), m_reOpen (false ), + m_closeSink (false ), -+ m_realSuspend (false ), ++ m_sinkIsSuspended (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()); +@@ -74,21 +76,18 @@ + m_outputStageFn (NULL ), + m_streamStageFn (NULL ) + { ++ unsigned int c_retry = 5; + CAESinkFactory::EnumerateEx(m_sinkInfoList); - for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt) -- { ++ while(m_sinkInfoList.size() == 0 && c_retry > 0) + { - 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) @@ -305,12 +76,18 @@ index 30da558..36c4d57 100644 - while(std::getline(ss, line, '\n')) - CLog::Log(LOGNOTICE, " %s", line.c_str()); - } -- } ++ 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()); + PrintSinks(); } CSoftAE::~CSoftAE() -@@ -189,6 +178,20 @@ void CSoftAE::OpenSink() +@@ -179,6 +178,20 @@ m_wake.Set(); } @@ -331,7 +108,7 @@ index 30da558..36c4d57 100644 /* this must NEVER be called from outside the main thread or Initialization */ void CSoftAE::InternalOpenSink() { -@@ -315,15 +318,8 @@ void CSoftAE::InternalOpenSink() +@@ -305,15 +318,8 @@ CExclusiveLock sinkLock(m_sinkLock); reInit = true; @@ -349,7 +126,7 @@ index 30da558..36c4d57 100644 /* get the display name of the device */ GetDeviceFriendlyName(device); -@@ -877,10 +873,19 @@ IAEStream *CSoftAE::FreeStream(IAEStream *stream) +@@ -867,10 +873,17 @@ RemoveStream(m_playingStreams, (CSoftAEStream*)stream); RemoveStream(m_streams , (CSoftAEStream*)stream); lock.Leave(); @@ -357,11 +134,9 @@ index 30da558..36c4d57 100644 - /* 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) ++ // Close completely when we go to suspend, reopen as it was old behaviour. ++ // Not opening when masterstream stops means clipping on S/PDIF. ++ if(m_isSuspended) + { + m_closeEvent.Reset(); + m_closeSink = true; @@ -373,7 +148,7 @@ index 30da558..36c4d57 100644 delete (CSoftAEStream*)stream; return NULL; -@@ -986,14 +991,52 @@ bool CSoftAE::Suspend() +@@ -976,14 +989,54 @@ CSoftAEStream *stream = *itt; stream->Flush(); } @@ -388,15 +163,18 @@ index 30da558..36c4d57 100644 + 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; ++ // we don't want that Run reopens our device, so we wait. ++ m_saveSuspend.Reset(); ++ // 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(); @@ -409,13 +187,12 @@ index 30da558..36c4d57 100644 { +#if defined(TARGET_LINUX) + // We must make sure, that we don't return empty. -+ if(m_realSuspend || m_sinkInfoList.empty()) ++ if(m_isSuspended || 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(); + } @@ -426,7 +203,24 @@ index 30da558..36c4d57 100644 m_reOpen = true; return true; -@@ -1030,6 +1073,12 @@ void CSoftAE::Run() +@@ -1000,6 +1053,16 @@ + { + bool restart = false; + ++ /* Clean Up what the suspend guy might have forgotten */ ++ // ProcessSuspending() cannot guarantee that we get our sink back softresumed ++ // that is a big problem as another thread could start adding packets ++ // this must be checked here, before writing anything on the sinks ++ if(m_sinkIsSuspended) ++ { ++ CLog::Log(LOGDEBUG, "CSoftAE::Run - Someone has forgotten to resume us (device resumed)"); ++ m_sink->SoftResume(); ++ m_sinkIsSuspended = false; ++ } + if ((this->*m_outputStageFn)(hasAudio) > 0) + hasAudio = false; /* taken some audio - reset our silence flag */ + +@@ -1020,6 +1083,12 @@ restart = true; } @@ -439,15 +233,17 @@ index 30da558..36c4d57 100644 /* Handle idle or forced suspend */ ProcessSuspend(); -@@ -1040,6 +1089,7 @@ void CSoftAE::Run() +@@ -1028,8 +1097,8 @@ + { + CLog::Log(LOGDEBUG, "CSoftAE::Run - Sink restart flagged"); InternalOpenSink(); - m_isSuspended = false; // exit Suspend state +- 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) +@@ -1280,6 +1349,24 @@ return encodedFrames; } @@ -472,113 +268,12 @@ index 30da558..36c4d57 100644 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(); - } +@@ -1395,10 +1482,9 @@ -+ // 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() + inline void CSoftAE::ProcessSuspend() { - bool sinkIsSuspended = false; +- bool sinkIsSuspended = false; ++ m_sinkIsSuspended = false; unsigned int curSystemClock = 0; - -#if defined(TARGET_WINDOWS) @@ -586,7 +281,7 @@ index 36c4d57..ae8a0e4 100644 if (!m_softSuspend && m_playingStreams.empty() && m_playing_sounds.empty() && !g_advancedSettings.m_streamSilence) { -@@ -1488,7 +1487,6 @@ inline void CSoftAE::ProcessSuspend() +@@ -1410,37 +1496,54 @@ if (m_softSuspend) curSystemClock = XbmcThreads::SystemClockMillis(); #endif @@ -594,30 +289,145 @@ index 36c4d57..ae8a0e4 100644 /* 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() +- while ((m_isSuspended || (m_softSuspend && (curSystemClock > m_softSuspendTimer))) && +- m_running && !m_reOpen) ++ /* In case of Suspend stay in there until Resume is called from outer thread */ ++ while (m_isSuspended || ((m_softSuspend && (curSystemClock > m_softSuspendTimer)) && ++ m_running && !m_reOpen)) + { +- if (m_sink && !sinkIsSuspended) ++ if (!m_isSuspended && m_sink && !m_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_sinkIsSuspended = false; //sink cannot be suspended + m_softSuspend = false; //break suspend loop break; } else +- sinkIsSuspended = true; //sink has suspended processing + { + CLog::Log(LOGDEBUG, "Suspended the Sink"); - sinkIsSuspended = true; //sink has suspended processing ++ m_sinkIsSuspended = true; //sink has suspended processing + } sinkLock.Leave(); } ++ // Signal that the Suspend 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_isSuspended) ++ m_saveSuspend.Set(); -@@ -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 + /* 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_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 +- m_softSuspend = false; //break suspend loop ++ m_reOpen = m_reOpen || !m_sink->SoftResume(); // sink returns false if it requires reinit ++ m_sinkIsSuspended = false; //sink processing data ++ m_softSuspend = false; //break suspend loop (under some conditions) + 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 +diff -Naur xbmc-12.0.1/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h +--- xbmc-12.0.1/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h 2013-02-08 00:07:33.000000000 +0100 ++++ xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h 2013-02-09 22:42:48.101803299 +0100 +@@ -116,6 +116,7 @@ + void OpenSink(); + + void InternalOpenSink(); ++ void InternalCloseSink(); + void ResetEncoder(); + bool SetupEncoder(AEAudioFormat &format); + void Deinitialize(); +@@ -136,11 +137,15 @@ + + /* internal vars */ + bool m_running, m_reOpen; ++ bool m_closeSink; ++ bool m_sinkIsSuspended; /* The sink is in unusable state, e.g. SoftSuspended */ + 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; ++ CEvent m_saveSuspend; + + CCriticalSection m_runningLock; /* released when the thread exits */ + CCriticalSection m_streamLock; /* m_streams lock */ +@@ -242,5 +247,6 @@ + void RunNormalizeStage (unsigned int channelCount, void *out, unsigned int mixed); + + void RemoveStream(StreamList &streams, CSoftAEStream *stream); ++ void PrintSinks(); + }; + +diff -Naur xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +--- xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp 2013-02-08 00:07:33.000000000 +0100 ++++ xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp 2013-02-09 22:42:48.101803299 +0100 +@@ -426,7 +426,6 @@ + + if (m_pcm) + { +- snd_pcm_drop (m_pcm); + snd_pcm_close(m_pcm); + m_pcm = NULL; + } +@@ -487,7 +486,13 @@ + unsigned int CAESinkALSA::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio) + { + if (!m_pcm) +- return 0; ++ { ++ SoftResume(); ++ if(!m_pcm) ++ return 0; ++ ++ CLog::Log(LOGDEBUG, "CAESinkALSA - the grAEken is hunger, feed it (I am the downmost fallback - fix your code)"); ++ } + + int ret; + +@@ -676,12 +681,17 @@ + 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) ++ { ++ if(force) ++ snd_config_update_free_global(); ++ + snd_config_update(); ++ } + + snd_config_t *config; + snd_config_copy(&config, snd_config); +@@ -1125,6 +1135,27 @@ return true; } @@ -645,122 +455,121 @@ index 328593c..647be04 100644 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 +diff -Naur xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h +--- xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h 2013-02-08 00:07:33.000000000 +0100 ++++ xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h 2013-02-09 22:42:48.099803309 +0100 +@@ -49,8 +49,10 @@ 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); +- static void EnumerateDevicesEx(AEDeviceInfoList &list); ++ 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(); + CAEChannelInfo GetChannelLayout(AEAudioFormat format); + void GetAESParams(const AEAudioFormat format, std::string& params); +diff -Naur xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp +--- xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp 2013-02-08 00:07:33.000000000 +0100 ++++ xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp 2013-02-09 22:42:48.090803350 +0100 +@@ -234,7 +234,7 @@ + m_volume_changed = true; + } - /* idle for platform-defined time */ - m_wake.WaitMSec(SOFTAE_IDLE_WAIT_MSEC); +-void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list) ++void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) + { + m_info.m_channels.Reset(); + m_info.m_dataFormats.clear(); +diff -Naur xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h +--- xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h 2013-02-08 00:07:33.000000000 +0100 ++++ xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h 2013-02-09 22:43:15.490676456 +0100 +@@ -43,7 +43,7 @@ + virtual void Drain (); + virtual bool HasVolume (); + virtual void SetVolume (float volume); +- static void EnumerateDevicesEx(AEDeviceInfoList &list); ++ static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false); -- /* 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; + private: + virtual void Process(); +diff -Naur xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp +--- xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp 2013-02-08 00:07:33.000000000 +0100 ++++ xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp 2013-02-09 22:42:48.091803346 +0100 +@@ -464,7 +464,7 @@ + return (double)m_dwBufferLen / (double)m_AvgBytesPerSec; + } - CCriticalSection m_runningLock; /* released when the thread exits */ - CCriticalSection m_streamLock; /* m_streams lock */ --- -1.7.10 - +-void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList) ++void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force) + { + CAEDeviceInfo deviceInfo; + +diff -Naur xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h +--- xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h 2013-02-08 00:07:33.000000000 +0100 ++++ xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h 2013-02-09 22:43:40.853559163 +0100 +@@ -43,7 +43,7 @@ + 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 -Naur xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp +--- xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp 2013-02-08 00:07:33.000000000 +0100 ++++ xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp 2013-02-09 22:42:48.092803341 +0100 +@@ -427,7 +427,7 @@ + // ??? + } + +-void CAESinkOSS::EnumerateDevicesEx(AEDeviceInfoList &list) ++void CAESinkOSS::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) + { + int mixerfd; + const char * mixerdev = "/dev/mixer"; +diff -Naur xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h +--- xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h 2013-02-08 00:07:33.000000000 +0100 ++++ xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h 2013-02-09 22:42:48.093803336 +0100 +@@ -43,7 +43,7 @@ + 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 -Naur xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp +--- xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp 2013-02-08 00:07:33.000000000 +0100 ++++ xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp 2013-02-09 22:42:48.093803336 +0100 +@@ -559,7 +559,7 @@ + return false; + } + +-void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList) ++void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force) + { + IMMDeviceEnumerator* pEnumerator = NULL; + IMMDeviceCollection* pEnumDevices = NULL; +diff -Naur xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h +--- xbmc-12.0.1/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h 2013-02-08 00:07:33.000000000 +0100 ++++ xbmc-12.0.1.patch/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h 2013-02-09 22:42:48.094803332 +0100 +@@ -45,7 +45,7 @@ + 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 @@ + 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 */ +-}; +\ Kein Zeilenumbruch am Dateiende. ++};