From 71b0e527129a125b1810c4921189845f4e7c4820 Mon Sep 17 00:00:00 2001 From: Rolf Ahrenberg Date: Sun, 17 Feb 2008 19:18:47 +0000 Subject: [PATCH] Added support for fifo dvr and modificationsfor vdr-1.5.15. --- README | 4 ++++ common.h | 5 ++++- device.c | 25 ++++++++++++++++++++++++- device.h | 3 ++- protocolext.c | 28 ++++++++++------------------ protocolext.h | 5 ++--- protocolhttp.c | 19 ++++++++----------- sectionfilter.c | 12 ++++-------- sectionfilter.h | 4 ++-- setup.c | 6 ++---- 10 files changed, 62 insertions(+), 49 deletions(-) diff --git a/README b/README index 6b0233f..46466ec 100644 --- a/README +++ b/README @@ -166,6 +166,10 @@ Notes: - The following section filters are recommended to be disabled: "NIT (0x40)", "SDT (0x42)", "TDT (0x70)" +- The IPTV devices look for a "/tmp/vdr-iptv.dvr" fifo at + startup. If the fifo is found and succesfully opened, the device writes + the current data stream into it. This can be used for debugging purposes. + Acknowledgements: - The IPTV section filtering code is derived from Linux kernel. diff --git a/common.h b/common.h index efa4a61..95c38ec 100644 --- a/common.h +++ b/common.h @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: common.h,v 1.19 2008/01/04 23:36:37 ajhseppa Exp $ + * $Id: common.h,v 1.20 2008/02/17 19:18:47 rahrenbe Exp $ */ #ifndef __IPTV_COMMON_H @@ -29,6 +29,9 @@ #define trVDR(s) tr(s) #endif +#define IPTV_FILTER_FILENAME "/tmp/vdr-iptv%d.filter%d" +#define IPTV_DVR_FILENAME "/tmp/vdr-iptv%d.dvr" + #define IPTV_DEVICE_INFO_ALL 0 #define IPTV_DEVICE_INFO_GENERAL 1 #define IPTV_DEVICE_INFO_PIDS 2 diff --git a/device.c b/device.c index ed12d13..4b1f97e 100644 --- a/device.c +++ b/device.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: device.c,v 1.83 2008/02/01 21:54:24 rahrenbe Exp $ + * $Id: device.c,v 1.84 2008/02/17 19:18:47 rahrenbe Exp $ */ #include "config.h" @@ -17,6 +17,7 @@ unsigned int cIptvDevice::deviceCount = 0; cIptvDevice::cIptvDevice(unsigned int Index) : deviceIndex(Index), + dvrFd(-1), isPacketDelivered(false), isOpenDvr(false), sidScanEnabled(false), @@ -43,11 +44,24 @@ cIptvDevice::cIptvDevice(unsigned int Index) pSidScanner = new cSidScanner; if (pSidScanner) AttachFilter(pSidScanner); + // Check if dvr fifo exists + struct stat sb; + cString filename = cString::sprintf(IPTV_DVR_FILENAME, deviceIndex); + stat(filename, &sb); + if (S_ISFIFO(sb.st_mode)) { + dvrFd = open(filename, O_WRONLY | O_NONBLOCK); + if (dvrFd >= 0) + dsyslog("IPTV device %d redirecting input stream to '%s'", deviceIndex, *filename); + } } cIptvDevice::~cIptvDevice() { debug("cIptvDevice::~cIptvDevice(%d)\n", deviceIndex); +#if defined(APIVERSNUM) && APIVERSNUM >= 10515 + // Stop section handler of iptv device + StopSectionHandler(); +#endif DELETE_POINTER(pIptvStreamer); DELETE_POINTER(pUdpProtocol); DELETE_POINTER(pHttpProtocol); @@ -63,6 +77,12 @@ cIptvDevice::~cIptvDevice() // Destroy all filters for (int i = 0; i < eMaxSecFilterCount; ++i) DeleteFilter(i); + // Close dvr fifo + if (dvrFd >= 0) { + int fd = dvrFd; + dvrFd = -1; + close(fd); + } } bool cIptvDevice::Initialize(unsigned int DeviceCount) @@ -436,6 +456,9 @@ bool cIptvDevice::GetTSPacket(uchar *&Data) Data = p; // Update pid statistics AddPidStatistic(ts_pid(p), payload(p)); + // Send data also to dvr fifo + if (dvrFd >= 0) + write(dvrFd, p, TS_SIZE); // Analyze incomplete streams with built-in pid analyzer if (pidScanEnabled && pPidScanner) pPidScanner->Process(p); diff --git a/device.h b/device.h index b2e66a6..f24d934 100644 --- a/device.h +++ b/device.h @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: device.h,v 1.38 2008/01/31 22:28:53 rahrenbe Exp $ + * $Id: device.h,v 1.39 2008/02/17 19:18:47 rahrenbe Exp $ */ #ifndef __IPTV_DEVICE_H @@ -35,6 +35,7 @@ private: eMaxSecFilterCount = 32 }; unsigned int deviceIndex; + int dvrFd; bool isPacketDelivered; bool isOpenDvr; bool sidScanEnabled; diff --git a/protocolext.c b/protocolext.c index 30c704c..f57f5a6 100644 --- a/protocolext.c +++ b/protocolext.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: protocolext.c,v 1.23 2008/01/30 21:57:33 rahrenbe Exp $ + * $Id: protocolext.c,v 1.24 2008/02/17 19:18:47 rahrenbe Exp $ */ #include @@ -22,11 +22,10 @@ cIptvProtocolExt::cIptvProtocolExt() : pid(-1), + scriptFile(""), scriptParameter(0) { debug("cIptvProtocolExt::cIptvProtocolExt()\n"); - scriptFile = strdup(""); - listenAddr = strdup("127.0.0.1"); } cIptvProtocolExt::~cIptvProtocolExt() @@ -34,9 +33,6 @@ cIptvProtocolExt::~cIptvProtocolExt() debug("cIptvProtocolExt::~cIptvProtocolExt()\n"); // Drop the socket connection cIptvProtocolExt::Close(); - // Free allocated memory - free(scriptFile); - free(listenAddr); } void cIptvProtocolExt::ExecuteScript(void) @@ -56,15 +52,12 @@ void cIptvProtocolExt::ExecuteScript(void) for (int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++) close(i); // Execute the external script - char* cmd = NULL; - asprintf(&cmd, "%s %d %d", scriptFile, scriptParameter, socketPort); - debug("cIptvProtocolExt::ExecuteScript(child): %s\n", cmd); - if (execl("/bin/sh", "sh", "-c", cmd, NULL) == -1) { - error("ERROR: Script execution failed: %s", cmd); - free(cmd); + cString cmd = cString::sprintf("%s %d %d", *scriptFile, scriptParameter, socketPort); + debug("cIptvProtocolExt::ExecuteScript(child): %s\n", *cmd); + if (execl("/bin/sh", "sh", "-c", *cmd, NULL) == -1) { + error("ERROR: Script execution failed: %s", *cmd); _exit(-1); } - free(cmd); _exit(0); } else { @@ -87,7 +80,7 @@ void cIptvProtocolExt::TerminateScript(void) retval = 0; waitms += timeoutms; if ((waitms % 2000) == 0) { - error("ERROR: Script '%s' won't terminate - killing it!", scriptFile); + error("ERROR: Script '%s' won't terminate - killing it!", *scriptFile); kill(pid, SIGKILL); } // Clear wait status to make sure child exit status is accessible @@ -146,10 +139,9 @@ bool cIptvProtocolExt::Set(const char* Location, const int Parameter, const int if (!isempty(Location)) { struct stat stbuf; // Update script file and parameter - free(scriptFile); - asprintf(&scriptFile, "%s/%s", IptvConfig.GetConfigDirectory(), Location); + scriptFile = cString::sprintf("%s/%s", IptvConfig.GetConfigDirectory(), Location); if ((stat(scriptFile, &stbuf) != 0) || (strstr(scriptFile, "..") != 0)) { - error("ERROR: Non-existent or relative path script '%s'", scriptFile); + error("ERROR: Non-existent or relative path script '%s'", *scriptFile); return false; } scriptParameter = Parameter; @@ -162,5 +154,5 @@ bool cIptvProtocolExt::Set(const char* Location, const int Parameter, const int cString cIptvProtocolExt::GetInformation(void) { //debug("cIptvProtocolExt::GetInformation()"); - return cString::sprintf("ext://%s:%d", scriptFile, scriptParameter); + return cString::sprintf("ext://%s:%d", *scriptFile, scriptParameter); } diff --git a/protocolext.h b/protocolext.h index 068cc28..3b21d00 100644 --- a/protocolext.h +++ b/protocolext.h @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: protocolext.h,v 1.9 2008/01/04 23:36:37 ajhseppa Exp $ + * $Id: protocolext.h,v 1.10 2008/02/17 19:18:47 rahrenbe Exp $ */ #ifndef __IPTV_PROTOCOLEXT_H @@ -16,8 +16,7 @@ class cIptvProtocolExt : public cIptvUdpSocket, public cIptvProtocolIf { private: int pid; - char* listenAddr; - char* scriptFile; + cString scriptFile; int scriptParameter; private: diff --git a/protocolhttp.c b/protocolhttp.c index 0390bec..2218908 100644 --- a/protocolhttp.c +++ b/protocolhttp.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: protocolhttp.c,v 1.23 2008/01/30 21:57:33 rahrenbe Exp $ + * $Id: protocolhttp.c,v 1.24 2008/02/17 19:18:47 rahrenbe Exp $ */ #include @@ -88,17 +88,14 @@ bool cIptvProtocolHttp::Connect(void) } // Formulate and send HTTP request - char buffer[256]; - memset(buffer, '\0', sizeof(buffer)); - snprintf(buffer, sizeof(buffer), - "GET %s HTTP/1.1\r\n" - "Host: %s\r\n" - "User-Agent: vdr-iptv\r\n" - "Range: bytes=0-\r\n" - "Connection: Close\r\n" - "\r\n", streamPath, streamAddr); + cString buffer = cString::sprintf("GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "User-Agent: vdr-iptv\r\n" + "Range: bytes=0-\r\n" + "Connection: Close\r\n" + "\r\n", streamPath, streamAddr); - //debug("Sending http request: %s\n", buffer); + debug("Sending http request: %s\n", *buffer); err = send(socketDesc, buffer, strlen(buffer), 0); ERROR_IF_FUNC(err < 0, "send()", CloseSocket(), return false); diff --git a/sectionfilter.c b/sectionfilter.c index 61d03cf..3027283 100644 --- a/sectionfilter.c +++ b/sectionfilter.c @@ -3,13 +3,10 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: sectionfilter.c,v 1.18 2008/01/30 21:57:33 rahrenbe Exp $ + * $Id: sectionfilter.c,v 1.19 2008/02/17 19:18:47 rahrenbe Exp $ */ #include "sectionfilter.h" -#include "statistics.h" - -#define IPTV_FILTER_FILENAME "/tmp/vdr-iptv%d.filter%d" cIptvSectionFilter::cIptvSectionFilter(int Index, int devInd, u_short Pid, u_char Tid, u_char Mask) @@ -21,7 +18,8 @@ cIptvSectionFilter::cIptvSectionFilter(int Index, int devInd, seclen(0), tsfeedp(0), pid(Pid), - id(Index) + id(Index), + pipeName("") { //debug("cIptvSectionFilter::cIptvSectionFilter(%d)\n", Index); memset(secbuf_base, '\0', sizeof(secbuf_base)); @@ -30,7 +28,6 @@ cIptvSectionFilter::cIptvSectionFilter(int Index, int devInd, memset(filter_mode, '\0', sizeof(filter_mode)); memset(maskandmode, '\0', sizeof(maskandmode)); memset(maskandnotmode, '\0', sizeof(maskandnotmode)); - memset(pipeName, '\0', sizeof(pipeName)); SetPipeName(devInd); @@ -68,14 +65,13 @@ cIptvSectionFilter::~cIptvSectionFilter() close(fifoDescriptor); close(readDescriptor); unlink(pipeName); - memset(pipeName, '\0', sizeof(pipeName)); fifoDescriptor = -1; readDescriptor = -1; } void cIptvSectionFilter::SetPipeName(int deviceIndex) { - snprintf(pipeName, sizeof(pipeName), IPTV_FILTER_FILENAME, deviceIndex, id); + pipeName = cString::sprintf(IPTV_FILTER_FILENAME, deviceIndex, id); } int cIptvSectionFilter::GetReadDesc() diff --git a/sectionfilter.h b/sectionfilter.h index 0e42313..b6f5705 100644 --- a/sectionfilter.h +++ b/sectionfilter.h @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: sectionfilter.h,v 1.7 2007/10/08 23:51:58 rahrenbe Exp $ + * $Id: sectionfilter.h,v 1.8 2008/02/17 19:18:47 rahrenbe Exp $ */ #ifndef __IPTV_SECTIONFILTER_H @@ -65,7 +65,7 @@ private: uint8_t maskandmode[DMX_MAX_FILTER_SIZE]; uint8_t maskandnotmode[DMX_MAX_FILTER_SIZE]; - char pipeName[128]; + cString pipeName; inline uint16_t section_length(const uint8_t *buf); diff --git a/setup.c b/setup.c index 6124b14..7d13f9e 100644 --- a/setup.c +++ b/setup.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: setup.c,v 1.53 2008/02/01 21:54:24 rahrenbe Exp $ + * $Id: setup.c,v 1.54 2008/02/17 19:18:47 rahrenbe Exp $ */ #include @@ -417,9 +417,7 @@ cIptvMenuChannelItem::cIptvMenuChannelItem(cChannel *Channel) void cIptvMenuChannelItem::Set(void) { - char *buffer = NULL; - asprintf(&buffer, "%d\t%s", channel->Number(), channel->Name()); - SetText(buffer, false); + SetText(cString::sprintf("%d\t%s", channel->Number(), channel->Name()), false); } // --- cIptvMenuChannels -----------------------------------------------------