AESinkPULSE: Use Callback to use Factory's DeviceChange()
authorfritsch <Peter.Fruehberger@gmail.com>
Mon, 3 Feb 2014 18:57:19 +0000 (19:57 +0100)
committerRainer Hochecker <fernetmenta@online.de>
Thu, 20 Feb 2014 19:31:21 +0000 (20:31 +0100)
xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp
xbmc/cores/AudioEngine/Sinks/AESinkPULSE.h

index a04a2a8..9d1554d 100644 (file)
@@ -189,6 +189,29 @@ 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();
+    }
+  }
+}
+
 struct SinkInfoStruct
 {
   AEDeviceInfoList *list;
@@ -406,7 +429,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 +449,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 +631,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 +804,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);
index 9fa301f..39fda73 100644 (file)
 #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);