summaryrefslogtreecommitdiff
path: root/plugins/streamdev/streamdev-cvs/client/device.c
diff options
context:
space:
mode:
authorkwacker <vdr@w-i-r.com>2010-04-11 13:46:11 +0200
committerkwacker <vdr@w-i-r.com>2010-04-11 13:46:11 +0200
commit9b144d30e0ea8ce900c37b96ba2cbdda14b0ae88 (patch)
tree3a52de029f950dcd9f9856a53fd67abef8519e68 /plugins/streamdev/streamdev-cvs/client/device.c
parent9cd931834ecadbf5efefdf484abb966e9248ebbb (diff)
downloadx-vdr-9b144d30e0ea8ce900c37b96ba2cbdda14b0ae88.tar.gz
x-vdr-9b144d30e0ea8ce900c37b96ba2cbdda14b0ae88.tar.bz2
Burn 0.2.0-beta3 und Streamdev mit Paches aktualisiert
Diffstat (limited to 'plugins/streamdev/streamdev-cvs/client/device.c')
-rw-r--r--plugins/streamdev/streamdev-cvs/client/device.c306
1 files changed, 306 insertions, 0 deletions
diff --git a/plugins/streamdev/streamdev-cvs/client/device.c b/plugins/streamdev/streamdev-cvs/client/device.c
new file mode 100644
index 0000000..551d7c2
--- /dev/null
+++ b/plugins/streamdev/streamdev-cvs/client/device.c
@@ -0,0 +1,306 @@
+/*
+ * $Id: device.c,v 1.25 2010/02/17 12:39:03 schmirl Exp $
+ */
+
+#include "client/device.h"
+#include "client/setup.h"
+#include "client/filter.h"
+
+#include "tools/select.h"
+
+#include <vdr/channels.h>
+#include <vdr/ringbuffer.h>
+#include <vdr/eit.h>
+#include <vdr/timers.h>
+
+#include <time.h>
+#include <iostream>
+
+using namespace std;
+
+#define VIDEOBUFSIZE MEGABYTE(3)
+
+cStreamdevDevice *cStreamdevDevice::m_Device = NULL;
+
+cStreamdevDevice::cStreamdevDevice(void) {
+ m_Channel = NULL;
+ m_TSBuffer = NULL;
+
+ m_Filters = new cStreamdevFilters;
+ StartSectionHandler();
+ isyslog("streamdev-client: got device number %d", CardIndex() + 1);
+
+ m_Device = this;
+ m_Pids = 0;
+ m_DvrClosed = true;
+
+ if (StreamdevClientSetup.SyncEPG)
+ ClientSocket.SynchronizeEPG();
+}
+
+cStreamdevDevice::~cStreamdevDevice() {
+ Dprintf("Device gets destructed\n");
+
+ Lock();
+ m_Device = NULL;
+ m_Filters->SetConnection(-1);
+ ClientSocket.Quit();
+ ClientSocket.Reset();
+ Unlock();
+
+ Cancel(3);
+
+#if APIVERSNUM >= 10515
+ StopSectionHandler();
+#endif
+ DELETENULL(m_Filters);
+ DELETENULL(m_TSBuffer);
+}
+
+bool cStreamdevDevice::ProvidesSource(int Source) const {
+ Dprintf("ProvidesSource, Source=%d\n", Source);
+ return true;
+}
+
+bool cStreamdevDevice::ProvidesTransponder(const cChannel *Channel) const
+{
+ Dprintf("ProvidesTransponder\n");
+ return true;
+}
+
+bool cStreamdevDevice::IsTunedToTransponder(const cChannel *Channel)
+{
+ bool res = false;
+ if (ClientSocket.DataSocket(siLive) != NULL
+ && TRANSPONDER(Channel, m_Channel)
+ && Channel->Ca() == CA_FTA
+ && m_Channel->Ca() == CA_FTA)
+ res = true;
+ return res;
+}
+
+bool cStreamdevDevice::ProvidesChannel(const cChannel *Channel, int Priority,
+ bool *NeedsDetachReceivers) const {
+ bool res = false;
+ bool prio = Priority < 0 || Priority > this->Priority();
+ bool ndr = false;
+
+ if (!StreamdevClientSetup.StartClient)
+ return false;
+
+ Dprintf("ProvidesChannel, Channel=%s, Prio=%d\n", Channel->Name(), Priority);
+
+ if (StreamdevClientSetup.MinPriority <= StreamdevClientSetup.MaxPriority)
+ {
+ if (Priority < StreamdevClientSetup.MinPriority ||
+ Priority > StreamdevClientSetup.MaxPriority)
+ return false;
+ }
+ else
+ {
+ if (Priority < StreamdevClientSetup.MinPriority &&
+ Priority > StreamdevClientSetup.MaxPriority)
+ return false;
+ }
+
+ if (ClientSocket.DataSocket(siLive) != NULL
+ && TRANSPONDER(Channel, m_Channel))
+ res = true;
+ else {
+ res = prio && ClientSocket.ProvidesChannel(Channel, Priority);
+ ndr = true;
+ }
+
+ if (NeedsDetachReceivers)
+ *NeedsDetachReceivers = ndr;
+ Dprintf("prov res = %d, ndr = %d\n", res, ndr);
+ return res;
+}
+
+bool cStreamdevDevice::SetChannelDevice(const cChannel *Channel,
+ bool LiveView) {
+ Dprintf("SetChannelDevice Channel: %s, LiveView: %s\n", Channel->Name(),
+ LiveView ? "true" : "false");
+
+ if (LiveView)
+ return false;
+
+ if (ClientSocket.DataSocket(siLive) != NULL
+ && TRANSPONDER(Channel, m_Channel)
+ && Channel->Ca() == CA_FTA
+ && m_Channel->Ca() == CA_FTA)
+ return true;
+
+ DetachAllReceivers();
+ m_Channel = Channel;
+ bool r = ClientSocket.SetChannelDevice(m_Channel);
+ Dprintf("setchanneldevice r=%d\n", r);
+ return r;
+}
+
+bool cStreamdevDevice::SetPid(cPidHandle *Handle, int Type, bool On) {
+ Dprintf("SetPid, Pid=%d, Type=%d, On=%d, used=%d\n", Handle->pid, Type, On,
+ Handle->used);
+ LOCK_THREAD;
+
+ if (On && !m_TSBuffer) {
+ Dprintf("SetPid: no data connection -> OpenDvr()");
+ OpenDvrInt();
+ }
+
+ bool res = true;
+ if (Handle->pid && (On || !Handle->used)) {
+ res = ClientSocket.SetPid(Handle->pid, On);
+
+ m_Pids += (!res) ? 0 : On ? 1 : -1;
+ if (m_Pids < 0)
+ m_Pids = 0;
+
+ if(m_Pids < 1 && m_DvrClosed) {
+ Dprintf("SetPid: 0 pids left -> CloseDvr()");
+ CloseDvrInt();
+ }
+ }
+
+ return res;
+}
+
+bool cStreamdevDevice::OpenDvrInt(void) {
+ Dprintf("OpenDvrInt\n");
+ LOCK_THREAD;
+
+ CloseDvrInt();
+ if (m_TSBuffer) {
+ Dprintf("cStreamdevDevice::OpenDvrInt(): DVR connection already open\n");
+ return true;
+ }
+
+ Dprintf("cStreamdevDevice::OpenDvrInt(): Connecting ...\n");
+ if (ClientSocket.CreateDataConnection(siLive)) {
+ m_TSBuffer = new cTSBuffer(*ClientSocket.DataSocket(siLive), MEGABYTE(2), CardIndex() + 1);
+ return true;
+ }
+ esyslog("cStreamdevDevice::OpenDvrInt(): DVR connection FAILED");
+ return false;
+}
+
+bool cStreamdevDevice::OpenDvr(void) {
+ Dprintf("OpenDvr\n");
+ LOCK_THREAD;
+
+ m_DvrClosed = false;
+ return OpenDvrInt();
+}
+
+void cStreamdevDevice::CloseDvrInt(void) {
+ Dprintf("CloseDvrInt\n");
+ LOCK_THREAD;
+
+ if (ClientSocket.CheckConnection()) {
+ if (!m_DvrClosed) {
+ Dprintf("cStreamdevDevice::CloseDvrInt(): m_DvrClosed=false -> not closing yet\n");
+ return;
+ }
+ if (m_Pids > 0) {
+ Dprintf("cStreamdevDevice::CloseDvrInt(): %d active pids -> not closing yet\n", m_Pids);
+ return;
+ }
+ } else {
+ Dprintf("cStreamdevDevice::CloseDvrInt(): Control connection gone !\n");
+ }
+
+ Dprintf("cStreamdevDevice::CloseDvrInt(): Closing DVR connection\n");
+ // Hack for VDR 1.5.x clients (sometimes sending ABRT after TUNE)
+ // TODO: Find a clean solution to fix this
+ ClientSocket.SetChannelDevice(m_Channel);
+ ClientSocket.CloseDvr();
+ DELETENULL(m_TSBuffer);
+}
+
+void cStreamdevDevice::CloseDvr(void) {
+ Dprintf("CloseDvr\n");
+ LOCK_THREAD;
+
+ m_DvrClosed = true;
+ CloseDvrInt();
+}
+
+bool cStreamdevDevice::GetTSPacket(uchar *&Data) {
+ if (m_TSBuffer && m_Device) {
+ Data = m_TSBuffer->Get();
+#if 1 // TODO: this should be fixed in vdr cTSBuffer
+ // simple disconnect detection
+ static int m_TSFails = 0;
+ if (!Data) {
+ LOCK_THREAD;
+ if(!ClientSocket.DataSocket(siLive)) {
+ return false; // triggers CloseDvr() + OpenDvr() in cDevice
+ }
+ cPoller Poller(*ClientSocket.DataSocket(siLive));
+ errno = 0;
+ if (Poller.Poll() && !errno) {
+ char tmp[1];
+ if (recv(*ClientSocket.DataSocket(siLive), tmp, 1, MSG_PEEK) == 0 && !errno) {
+esyslog("cStreamDevice::GetTSPacket: GetChecked: NOTHING (%d)", m_TSFails);
+ m_TSFails++;
+ if (m_TSFails > 10) {
+ isyslog("cStreamdevDevice::GetTSPacket(): disconnected");
+ m_Pids = 0;
+ CloseDvrInt();
+ m_TSFails = 0;
+ return false;
+ }
+ return true;
+ }
+ }
+ m_TSFails = 0;
+ }
+#endif
+ return true;
+ }
+ return false;
+}
+
+int cStreamdevDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask) {
+ Dprintf("OpenFilter\n");
+
+ if (!StreamdevClientSetup.StreamFilters)
+ return -1;
+
+
+ if (!ClientSocket.DataSocket(siLiveFilter)) {
+ if (ClientSocket.CreateDataConnection(siLiveFilter)) {
+ m_Filters->SetConnection(*ClientSocket.DataSocket(siLiveFilter));
+ } else {
+ isyslog("cStreamdevDevice::OpenFilter: connect failed: %m");
+ return -1;
+ }
+ }
+
+ if (ClientSocket.SetFilter(Pid, Tid, Mask, true))
+ return m_Filters->OpenFilter(Pid, Tid, Mask);
+
+ return -1;
+}
+
+bool cStreamdevDevice::Init(void) {
+ if (m_Device == NULL && StreamdevClientSetup.StartClient)
+ new cStreamdevDevice;
+ return true;
+}
+
+bool cStreamdevDevice::ReInit(void) {
+ if(m_Device) {
+ m_Device->Lock();
+ m_Device->m_Filters->SetConnection(-1);
+ m_Device->m_Pids = 0;
+ }
+ ClientSocket.Quit();
+ ClientSocket.Reset();
+ if (m_Device != NULL) {
+ //DELETENULL(m_Device->m_TSBuffer);
+ m_Device->Unlock();
+ }
+ return StreamdevClientSetup.StartClient ? Init() : true;
+}
+