Problem with transfer mode, xine plugin and ActualDevice

Message ID 4377BD47.8060308@gmx.de
State New
Headers

Commit Message

Reinhard Nissl Nov. 13, 2005, 10:25 p.m. UTC
  Hi,

Luca Olivetti wrote:

> Btw, this is the patch I'm using now (against original 0.7.6), and it
> seems to work, but I'm not sure it's due to simple luck or it is working
> by design (e.g. if I switch the order of cControl::Shutdown() and
> Skins.Message in the OnClientConnect handler it won't work).

As you wrote in a previous email: it's a threading issue.

Please try the attached patch against 0.7.6, which now uses VDR's main 
thread to switch the primary device.

Bye.
  

Comments

Luca Olivetti Nov. 13, 2005, 10:58 p.m. UTC | #1
En/na Reinhard Nissl ha escrit:
> Hi,
> 
> Luca Olivetti wrote:
> 
>> Btw, this is the patch I'm using now (against original 0.7.6), and it
>> seems to work, but I'm not sure it's due to simple luck or it is working
>> by design (e.g. if I switch the order of cControl::Shutdown() and
>> Skins.Message in the OnClientConnect handler it won't work).
> 
> As you wrote in a previous email: it's a threading issue.
> 
> Please try the attached patch against 0.7.6, which now uses VDR's main
> thread to switch the primary device.

It works, thanks.

Bye
  

Patch

--- ../xine-0.7.6/xine.c	2005-08-24 00:01:55.000000000 +0200
+++ xine.c	2005-11-13 22:21:10.000000000 +0100
@@ -156,7 +156,7 @@  void cPluginXine::Housekeeping(void)
 cOsdObject *cPluginXine::MainMenuAction(void)
 {
   // Perform the action when selected from the main VDR menu.
-  m_settings.TogglePrebufferMode();
+  PluginXine::cXineDevice::MainMenuTrampoline();
       
   return NULL;
 }
--- ../xine-0.7.6/xineDevice.c	2005-09-11 21:17:06.000000000 +0200
+++ xineDevice.c	2005-11-13 22:56:06.000000000 +0100
@@ -2580,8 +2588,14 @@  store_frame(jumboPESdata, todo, __LINE__
   
   void cXineDevice::MakePrimaryDevice(bool On)
   {
+    xfprintf(stderr, "-------------------------\n");
+    xfprintf(stderr, "MakePrimaryDevice: %d\n", On);
+    xfprintf(stderr, "=========================\n");
+
     if (On)
       new cXineOsdProvider(*this);
+    else
+      cOsdProvider::Shutdown();
     
     originalPrimaryDevice = 0;
   }
@@ -2619,6 +2633,51 @@  store_frame(jumboPESdata, todo, __LINE__
       m_currentOsd->ReshowCurrentOsd(dontOptimize, frameWidth, frameHeight);
   }
 
+  void cXineDevice::mainMenuTrampoline()
+  {
+    cMutexLock switchPrimaryDeviceLock(&m_switchPrimaryDeviceMutex);
+    if (m_switchPrimaryDeviceDeviceNo < 0)
+      return;
+
+    cControl::Shutdown();
+
+    if (m_switchPrimaryDeviceDeviceNo == (1 + DeviceNumber()))
+    {  
+      char *msg = 0;
+      ::asprintf(&msg, tr("Switching primary DVB to %s..."), m_plugin->Name());
+
+      Skins.Message(mtInfo, msg);
+      ::free(msg);
+    }
+
+    SetPrimaryDevice(m_switchPrimaryDeviceDeviceNo);
+
+    if (m_switchPrimaryDeviceDeviceNo != (1 + DeviceNumber()))
+    {
+      char *msg = 0;
+      ::asprintf(&msg, tr("Switched primary DVB back from %s"), m_plugin->Name());
+
+      Skins.Message(mtInfo, msg);
+      ::free(msg);
+    }
+
+    m_switchPrimaryDeviceCond.Broadcast();
+  }
+
+  void cXineDevice::switchPrimaryDevice(const int deviceNo, const bool waitForExecution)
+  {
+    while (cRemote::HasKeys())
+      cCondWait::SleepMs(10);
+
+    cMutexLock switchPrimaryDeviceLock(&m_switchPrimaryDeviceMutex);
+    m_switchPrimaryDeviceDeviceNo = deviceNo;
+
+    cRemote::CallPlugin(m_plugin->Name());
+
+    if (waitForExecution)
+      m_switchPrimaryDeviceCond.Wait(m_switchPrimaryDeviceMutex);
+  }
+
   void cXineDevice::OnClientConnect()
   {
     reshowCurrentOsd();
@@ -2630,7 +2689,8 @@  store_frame(jumboPESdata, todo, __LINE__
     {
       cDevice *primaryDevice = cDevice::PrimaryDevice();
       if (this != primaryDevice)
-        SetPrimaryDevice(1 + DeviceNumber());
+        switchPrimaryDevice(1 + DeviceNumber(), true);
+
       originalPrimaryDevice = primaryDevice;
     }
 
@@ -2647,7 +2707,7 @@  store_frame(jumboPESdata, todo, __LINE__
       && originalPrimaryDevice)
     {
       if (this != originalPrimaryDevice)
-        SetPrimaryDevice(1 + originalPrimaryDevice->DeviceNumber());
+        switchPrimaryDevice(1 + originalPrimaryDevice->DeviceNumber(), false);
     }
   }
   
@@ -2697,6 +2757,8 @@  store_frame(jumboPESdata, todo, __LINE__
     , m_currentOsd(0)
     , m_spuDecoder(0)
     , m_audioChannel(0)
+    , m_plugin(plugin)
+    , m_switchPrimaryDeviceDeviceNo(-1)
     , m_xineLib(plugin, settings, m_osdMutex, remote)
   {
     m_xineLib.SetEventSink(this);
--- ../xine-0.7.6/xineDevice.h	2005-09-11 18:08:56.000000000 +0200
+++ xineDevice.h	2005-11-13 22:56:23.000000000 +0100
@@ -97,6 +97,13 @@  namespace PluginXine
     virtual void OnClientDisconnect();
     virtual void ReshowCurrentOSD(const int frameWidth, const int frameHeight);
     
+    cPlugin *const m_plugin;
+    int m_switchPrimaryDeviceDeviceNo;
+    cMutex m_switchPrimaryDeviceMutex;
+    cCondVar m_switchPrimaryDeviceCond;
+    void switchPrimaryDevice(const int deviceNo, const bool waitForExecution);
+    void mainMenuTrampoline();
+    
   public:
     virtual int64_t GetSTC(void);
     
@@ -126,6 +133,11 @@  namespace PluginXine
     static void Stop();
     static cXineDevice *GetDevice();
 
+    static void MainMenuTrampoline()
+    {
+      GetDevice()->mainMenuTrampoline();
+    }
+
     bool hasNoSignalStream() const
     {
       return m_xineLib.hasNoSignalStream();