summaryrefslogtreecommitdiff
path: root/xineExternal.c
diff options
context:
space:
mode:
Diffstat (limited to 'xineExternal.c')
-rw-r--r--xineExternal.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/xineExternal.c b/xineExternal.c
new file mode 100644
index 0000000..b0ea701
--- /dev/null
+++ b/xineExternal.c
@@ -0,0 +1,258 @@
+
+#include "xineCommon.h"
+
+#include "xineExternal.h"
+#include "xineLib.h"
+
+
+
+namespace PluginXine
+{
+
+ cXineExternal::cXineExternal()
+ : cThread()
+ , m_fdControl(-1)
+ , m_fdResult(-1)
+ , m_shutdown(false)
+ , m_connected(false)
+ , m_xineLib(0)
+ , m_enabled(false)
+ {
+ }
+
+ cXineExternal::~cXineExternal()
+ {
+ StopExternal();
+ }
+
+ void cXineExternal::StartExternal()
+ {
+ cThread::Start();
+ }
+
+ void cXineExternal::StopExternal()
+ {
+ cMutexLock shutdownMutexLock(&m_shutdownMutex);
+ m_shutdown = true;
+ m_shutdownCondVar.Broadcast();
+
+ disconnect();
+ }
+
+ bool cXineExternal::readCommand()
+ {
+ int len = 0;
+
+ while (!m_shutdown
+ && len < EXTERNAL_COMMAND_MAX_LEN)
+ {
+ cPoller poller(m_fdControl);
+ if (poller.Poll(100))
+ {
+ void (* const sigPipeHandler)(int) = ::signal(SIGPIPE, SIG_IGN);
+
+ int r = ::read(m_fdControl, &m_command[ len ], 1);
+ int myErrno = errno;
+
+ ::signal(SIGPIPE, sigPipeHandler);
+
+ if (r < 0)
+ {
+ if (EAGAIN == myErrno)
+ return false;
+
+ if (m_connected)
+ {
+ errno = myErrno;
+ ::perror("vdr-xine: reading external command failed");
+ }
+ }
+
+ if (r <= 0)
+ {
+ disconnect();
+ return false;
+ }
+
+ if ('\n' == m_command[ len ])
+ break;
+
+ len += r;
+ }
+ }
+
+ if (m_shutdown)
+ return false;
+
+ if (len >= EXTERNAL_COMMAND_MAX_LEN
+ && m_command[ EXTERNAL_COMMAND_MAX_LEN - 1 ] != '\n')
+ {
+ ::fprintf(stderr, "vdr-xine: external command length exceeded!\n");
+ disconnect();
+ return false;
+ }
+
+ m_command[ len ] = '\0';
+
+ return (len > 0);
+ }
+
+ bool cXineExternal::writeResult(const char *result)
+ {
+ int l = ::strlen(result);
+
+ while (l > 0)
+ {
+ void (* const sigPipeHandler)(int) = ::signal(SIGPIPE, SIG_IGN);
+
+ int r = ::write(m_fdResult, &result, l);
+ int myErrno = errno;
+
+ ::signal(SIGPIPE, sigPipeHandler);
+
+ if (r < 0)
+ {
+ if (EAGAIN == myErrno)
+ continue;
+
+ errno = myErrno;
+ ::perror("vdr-xine: writing external result failed");
+ }
+
+ if (r <= 0)
+ {
+ disconnect();
+ return false;
+ }
+
+ result += r;
+ l -= r;
+ }
+
+ return true;
+ }
+
+ void cXineExternal::cmdPlay(const char *const mrl)
+ {
+ if (m_xineLib)
+ {
+ m_xineLib->execFuncPlayExternal(mrl);
+ m_xineLib->execFuncWait();
+ }
+ }
+
+ void cXineExternal::enable(const bool enable)
+ {
+ cMutexLock lock(&m_enabledMutex);
+
+ if (m_enabled && !enable)
+ cmdPlay(0);
+
+ m_enabled = enable;
+ }
+
+ void cXineExternal::externalStreamFinished()
+ {
+ ::fprintf(stderr, "vdr-xine: external stream finished\n");
+
+ cmdPlay(0);
+
+ writeResult("play finished\n");
+ }
+
+ void cXineExternal::Action(void)
+ {
+ while (!m_shutdown)
+ {
+ if (!isConnected())
+ {
+// ::fprintf(stderr, "?");
+ checkConnect();
+ }
+ else
+ {
+// ::fprintf(stderr, "!");
+
+ if (readCommand())
+ {
+ cMutexLock lock(&m_enabledMutex);
+
+ if (!m_enabled)
+ {
+ ::fprintf(stderr, "vdr-xine: external commands not allowed!\n");
+ disconnect();
+ }
+ else
+ {
+ if (0 == strncmp(m_command, "play ", 5))
+ {
+ cmdPlay(m_command + 5);
+ }
+ else
+ {
+ ::fprintf(stderr, "vdr-xine: external command '%s' unknown!\n", m_command);
+ disconnect();
+ }
+ }
+ }
+ }
+
+ if (!m_shutdown)
+ {
+ cMutexLock shutdownMutexLock(&m_shutdownMutex);
+ if (!m_shutdown)
+ m_shutdownCondVar.TimedWait(m_shutdownMutex, 100);
+ }
+ }
+ }
+
+ bool cXineExternal::isConnected()
+ {
+ return (-1 != m_fdControl);
+ }
+
+ bool cXineExternal::checkConnect()
+ {
+ m_fdResult = ::open(m_xineLib->m_fifoNameExtResult.c_str() , O_WRONLY | O_NONBLOCK);
+ if (-1 == m_fdResult)
+ return false;
+
+ ::fprintf(stderr, "vdr-xine: external connecting ...\n");
+
+ m_fdControl = ::open(m_xineLib->m_fifoNameExtControl.c_str(), O_RDONLY);
+
+ ::fcntl(m_fdResult, F_SETFL, ~O_NONBLOCK & ::fcntl(m_fdResult, F_GETFL, 0));
+
+ if (isConnected())
+ {
+ ::fprintf(stderr, "vdr-xine: external connected!\n");
+
+ m_connected = true;
+ return true;
+ }
+
+ ::fprintf(stderr, "vdr-xine: external connect failed!\n");
+
+ return false;
+ }
+
+ void cXineExternal::disconnect()
+ {
+ m_connected = false;
+
+ cmdPlay(0);
+
+ if (-1 != m_fdControl)
+ {
+ ::close(m_fdControl);
+ m_fdControl = -1;
+ }
+
+ if (-1 != m_fdResult)
+ {
+ ::close(m_fdResult);
+ m_fdResult = -1;
+ }
+ }
+
+};