Reinhard Nissl wrote:
Hi,
Klaus Schmidinger wrote:
In my case, I don't show an OSD. I just use this functionality as a trampoline to have the VDR main thread execute my code for switching the primary device, as it doesn't work reliably when it is done in any other thread.
So you are right, when a plugin opens an OSD (which is the typical case), one will only see the OSD of the last plugin. On the other hand, it would be useful to know for the caller, that the MenuMenuAction of the specified plugin will be called when CallPlugin() returned true. Otherwise it would need more "intelligent" code at the caller to achieve the call under race conditions.
In the case where the above is of no interest, there is no need to have an additional mutex lock in CallPlugin(), as Put() has one in remote.c:79.
I'm not particularly fond of that FIFO of yours. However, I do realize that it is useful to tell the caller of cRemote::CallPlugin() whether the call was successful. The attached patch vdr-1.3.46-callplugin.diff makes cRemote::CallPlugin() return false if there is currently a plugin call pending.
The code looks good to me. Am I right that CallPlugin() shall now only be used to open the plugins main menu, i. e. no longer any other processing in the context of the main thread?
The ability to "catch the main thread" will be implemented by the second attached patch (vdr-1.3.46-mainthreadhook.diff), so that no "dirty tricks" should be necessary. This patch may have its line numbers a little off, because I have already made other changes to these files, but I wanted to give you a chance to look at this and maybe comment on it before I release version 1.3.47 later today.
I assume that this new interface function should be used for the code which has nothing to do with the plugins main menu but was put in that MainMenuAction() to execute the code in the context of the main thread.
Right. That was a dirty trick and I didn't want to manifest that ;-)
In my case, the following code is to be executed in the new function:
void cXineDevice::mainMenuTrampoline() { #if VDRVERSNUM >= 10332 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();
#endif }
I see here a new problem, as I need to call cControl::Shutdown(), but when VDR's main thread returns to it's main loop, it still may use "Menu" which is most likely invalid at that time:
// Main thread hooks of plugins: PluginManager.MainThreadHook(); // User Input: cOsdObject *Interact = Menu ? Menu : cControl::Control();
Maybe PluginManager.MainThreadHook() should be called earlier.
Originally I was thinking about actually putting it further down. How about we put it to the very end of the "while (!Interrupted) {" loop? That way it shouldn't interfere with anything.
I'll make it that way for version 1.3.47, which I will be releasing shortly.
Klaus