diff options
author | Trent Nelson <trent.a.b.nelson@gmail.com> | 2014-02-21 12:09:34 -0700 |
---|---|---|
committer | Trent Nelson <trent.a.b.nelson@gmail.com> | 2014-02-21 12:09:34 -0700 |
commit | 4298c43dc3a6d80cc60a55172c68f10544b479cb (patch) | |
tree | 83a5e615e34b2c7d755df2be36f1db63940dc462 | |
parent | af78970361fe4651198bc96994b8fe9b4fdc052e (diff) | |
parent | dfb802828cd1d8defff8121d081ab56611cef7ca (diff) |
Merge pull request #4133 from FernetMenta/aefixes
ActiveAE: add method for re-init after device/eld change
-rw-r--r-- | xbmc/cores/AudioEngine/AEFactory.cpp | 6 | ||||
-rw-r--r-- | xbmc/cores/AudioEngine/AEFactory.h | 1 | ||||
-rw-r--r-- | xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 35 | ||||
-rw-r--r-- | xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h | 4 | ||||
-rw-r--r-- | xbmc/cores/AudioEngine/Interfaces/AE.h | 5 | ||||
-rw-r--r-- | xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp | 57 | ||||
-rw-r--r-- | xbmc/cores/AudioEngine/Sinks/AESinkPULSE.h | 4 | ||||
-rw-r--r-- | xbmc/utils/ActorProtocol.cpp | 44 | ||||
-rw-r--r-- | xbmc/utils/ActorProtocol.h | 2 |
9 files changed, 155 insertions, 3 deletions
diff --git a/xbmc/cores/AudioEngine/AEFactory.cpp b/xbmc/cores/AudioEngine/AEFactory.cpp index 3094bdf7fd..fff42a6130 100644 --- a/xbmc/cores/AudioEngine/AEFactory.cpp +++ b/xbmc/cores/AudioEngine/AEFactory.cpp @@ -404,3 +404,9 @@ void CAEFactory::KeepConfiguration(unsigned int millis) if (AE) AE->KeepConfiguration(millis); } + +void CAEFactory::DeviceChange() +{ + if (AE) + AE->DeviceChange(); +} diff --git a/xbmc/cores/AudioEngine/AEFactory.h b/xbmc/cores/AudioEngine/AEFactory.h index 9a340cc3c1..1d55513464 100644 --- a/xbmc/cores/AudioEngine/AEFactory.h +++ b/xbmc/cores/AudioEngine/AEFactory.h @@ -76,6 +76,7 @@ public: static void SettingOptionsAudioStreamsilenceFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); static bool IsSettingVisible(const std::string &condition, const std::string &value, const std::string &settingId); static void KeepConfiguration(unsigned int millis); + static void DeviceChange(); static void RegisterAudioCallback(IAudioCallback* pCallback); static void UnregisterAudioCallback(); diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp index 63a8983d04..c871ee893e 100644 --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp @@ -425,6 +425,36 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg) } msg->Reply(CActiveAEControlProtocol::ACC); return; + case CActiveAEControlProtocol::DEVICECHANGE: + time_t now; + time(&now); + while (!m_extLastDeviceChange.empty() && (now - m_extLastDeviceChange.front() > 0)) + { + m_extLastDeviceChange.pop(); + } + if (m_extLastDeviceChange.size() > 2) + { + CLog::Log(LOGWARNING,"CActiveAE - received %ld device change events within one second", m_extLastDeviceChange.size()); + return; + } + m_extLastDeviceChange.push(now); + UnconfigureSink(); + m_sink.EnumerateSinkList(true); + 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; + } + m_controlPort.PurgeOut(CActiveAEControlProtocol::DEVICECHANGE); + return; case CActiveAEControlProtocol::PAUSESTREAM: CActiveAEStream *stream; stream = *(CActiveAEStream**)msg->data; @@ -2292,6 +2322,11 @@ void CActiveAE::KeepConfiguration(unsigned int millis) m_controlPort.SendOutMessage(CActiveAEControlProtocol::KEEPCONFIG, &timeMs, sizeof(unsigned int)); } +void CActiveAE::DeviceChange() +{ + m_controlPort.SendOutMessage(CActiveAEControlProtocol::DEVICECHANGE); +} + void CActiveAE::OnLostDevice() { Message *reply; diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h index debc8e140f..225c694775 100644 --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h @@ -28,6 +28,7 @@ #include "cores/AudioEngine/Interfaces/AESound.h" #include "cores/AudioEngine/AEFactory.h" #include "guilib/DispResource.h" +#include <queue> // ffmpeg #include "DllAvFormat.h" @@ -73,6 +74,7 @@ public: INIT = 0, RECONFIGURE, SUSPEND, + DEVICECHANGE, MUTE, VOLUME, PAUSESTREAM, @@ -224,6 +226,7 @@ public: virtual bool SupportsQualityLevel(enum AEQuality level); virtual bool IsSettingVisible(const std::string &settingId); virtual void KeepConfiguration(unsigned int millis); + virtual void DeviceChange(); virtual void RegisterAudioCallback(IAudioCallback* pCallback); virtual void UnregisterAudioCallback(); @@ -292,6 +295,7 @@ protected: XbmcThreads::EndTime m_extDrainTimer; unsigned int m_extKeepConfig; bool m_extDeferData; + std::queue<time_t> m_extLastDeviceChange; enum { diff --git a/xbmc/cores/AudioEngine/Interfaces/AE.h b/xbmc/cores/AudioEngine/Interfaces/AE.h index f91dc4c369..dd3289746f 100644 --- a/xbmc/cores/AudioEngine/Interfaces/AE.h +++ b/xbmc/cores/AudioEngine/Interfaces/AE.h @@ -232,5 +232,10 @@ public: * @param millis time for which old configuration should be kept */ virtual void KeepConfiguration(unsigned int millis) {return; } + + /** + * Instruct AE to re-initialize, e.g. after ELD change event + */ + virtual void DeviceChange() {return; } }; diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp index a04a2a8d24..127fc62ea5 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp @@ -189,6 +189,34 @@ static void StreamLatencyUpdateCallback(pa_stream *s, void *userdata) pa_threaded_mainloop *m = (pa_threaded_mainloop *)userdata; pa_threaded_mainloop_signal(m, 0); } + +static void SinkChangedCallback(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) +{ + CAESinkPULSE* p = (CAESinkPULSE*) userdata; + if(!p) + return; + + CSingleLock lock(p->m_sec); + if (p->IsInitialized()) + { + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) + { + CLog::Log(LOGDEBUG, "Sink appeared"); + CAEFactory::DeviceChange(); + } + else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) + { + CLog::Log(LOGDEBUG, "Sink removed"); + CAEFactory::DeviceChange(); + } + else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE) + { + CLog::Log(LOGDEBUG, "Sink changed"); + //CAEFactory::DeviceChange(); + } + } +} + struct SinkInfoStruct { AEDeviceInfoList *list; @@ -406,7 +434,10 @@ CAESinkPULSE::~CAESinkPULSE() bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device) { - m_IsAllocated = false; + { + CSingleLock lock(m_sec); + m_IsAllocated = false; + } m_passthrough = false; m_BytesPerSecond = 0; m_BufferSize = 0; @@ -423,6 +454,16 @@ bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device) pa_threaded_mainloop_lock(m_MainLoop); + { + // Register Callback for Sink changes + CSingleLock lock(m_sec); + pa_context_set_subscribe_callback(m_Context, SinkChangedCallback, this); + const pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SINK; + pa_operation *op = pa_context_subscribe(m_Context, mask, NULL, this); + if (op != NULL) + pa_operation_unref(op); + } + struct pa_channel_map map; pa_channel_map_init(&map); @@ -595,20 +636,24 @@ bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device) } pa_threaded_mainloop_unlock(m_MainLoop); - - m_IsAllocated = true; + format.m_frameSize = frameSize; format.m_frameSamples = format.m_frames * format.m_channelLayout.Count(); m_format = format; format.m_dataFormat = m_passthrough ? AE_FMT_S16NE : format.m_dataFormat; Pause(false); + { + CSingleLock lock(m_sec); + m_IsAllocated = true; + } return true; } void CAESinkPULSE::Deinitialize() { + CSingleLock lock(m_sec); m_IsAllocated = false; m_passthrough = false; @@ -764,6 +809,12 @@ void CAESinkPULSE::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) } } +bool CAESinkPULSE::IsInitialized() +{ + CSingleLock lock(m_sec); + return m_IsAllocated; +} + bool CAESinkPULSE::Pause(bool pause) { pa_threaded_mainloop_lock(m_MainLoop); diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.h b/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.h index 9fa301f00f..39fda73a86 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.h +++ b/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.h @@ -22,9 +22,11 @@ #include "system.h" #include "cores/AudioEngine/Interfaces/AESink.h" +#include "cores/AudioEngine/AEFactory.h" #include "Utils/AEDeviceInfo.h" #include "Utils/AEUtil.h" #include <pulse/pulseaudio.h> +#include "threads/CriticalSection.h" class CAESinkPULSE : public IAESink { @@ -46,6 +48,8 @@ public: virtual void SetVolume(float volume); static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false); + bool IsInitialized(); + CCriticalSection m_sec; private: bool Pause(bool pause); static inline bool WaitForOperation(pa_operation *op, pa_threaded_mainloop *mainloop, const char *LogEntry); diff --git a/xbmc/utils/ActorProtocol.cpp b/xbmc/utils/ActorProtocol.cpp index ac5b5ebe17..9ea07bd5d6 100644 --- a/xbmc/utils/ActorProtocol.cpp +++ b/xbmc/utils/ActorProtocol.cpp @@ -251,3 +251,47 @@ void Protocol::Purge() while (ReceiveOutMessage(&msg)) msg->Release(); } + +void Protocol::PurgeIn(int signal) +{ + Message *msg; + std::queue<Message*> msgs; + + CSingleLock lock(criticalSection); + + while (!inMessages.empty()) + { + msg = inMessages.front(); + inMessages.pop(); + if (msg->signal != signal) + msgs.push(msg); + } + while (!msgs.empty()) + { + msg = msgs.front(); + msgs.pop(); + inMessages.push(msg); + } +} + +void Protocol::PurgeOut(int signal) +{ + Message *msg; + std::queue<Message*> msgs; + + CSingleLock lock(criticalSection); + + while (!outMessages.empty()) + { + msg = outMessages.front(); + outMessages.pop(); + if (msg->signal != signal) + msgs.push(msg); + } + while (!msgs.empty()) + { + msg = msgs.front(); + msgs.pop(); + outMessages.push(msg); + } +} diff --git a/xbmc/utils/ActorProtocol.h b/xbmc/utils/ActorProtocol.h index 336da06492..100b1acd0b 100644 --- a/xbmc/utils/ActorProtocol.h +++ b/xbmc/utils/ActorProtocol.h @@ -69,6 +69,8 @@ public: bool ReceiveOutMessage(Message **msg); bool ReceiveInMessage(Message **msg); void Purge(); + void PurgeIn(int signal); + void PurgeOut(int signal); void DeferIn(bool value) {inDefered = value;}; void DeferOut(bool value) {outDefered = value;}; void Lock() {criticalSection.lock();}; |