diff options
author | Dieter Hametner <dh (plus) vdr (at) gekrumbel (dot) de> | 2008-06-21 02:04:29 +0200 |
---|---|---|
committer | Dieter Hametner <dh (plus) vdr (at) gekrumbel (dot) de> | 2008-06-21 02:04:29 +0200 |
commit | 79f74de951779431ac46535ed1a0c2824a925c4f (patch) | |
tree | 6111b5f439e62fe10c1b8c602297e9bcfa41b51f | |
parent | 54ac5eaaab8065473fb023c713e383b7fe5d15a9 (diff) | |
download | vdr-plugin-live-79f74de951779431ac46535ed1a0c2824a925c4f.tar.gz vdr-plugin-live-79f74de951779431ac46535ed1a0c2824a925c4f.tar.bz2 |
Added streaming of recordings via http.
The recordings must be complete and no conversion of the stream takes
place. Thus the current implementation is only usable in the local LAN.
-rw-r--r-- | pages/recstream.ecpp | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/pages/recstream.ecpp b/pages/recstream.ecpp new file mode 100644 index 0000000..d8fb3a9 --- /dev/null +++ b/pages/recstream.ecpp @@ -0,0 +1,72 @@ +<%pre> +#include <string> +#include <iostream> +#include <fstream> +#include <algorithm> +#include <tnt/httperror.h> +#include <tnt/httpheader.h> +#include <vdr/recording.h> +#include "setup.h" +#include "recman.h" + +using namespace std; +using namespace vdrlive; + +off_t RecSize(cRecording const * recording) +{ + cFileName recFile(recording->FileName(), false, false); + off_t recSize = 0; + for (cUnbufferedFile *recData = recFile.Open(); recData; recData = recFile.NextFile()) { + struct stat buf; + if (0 == stat(recFile.Name(), &buf)) { + recSize += buf.st_size; + // dsyslog("LIVE: size of recording part %s is %ld", recFile.Name(), buf.st_size); + } + else { + esyslog("LIVE: can't determine size of %s", recFile.Name()); + } + } + // dsyslog("LIVE: total size of %s is %ld", recording->FileName(), recSize); + return recSize; +} + +</%pre> +<%args> + string recid; +</%args> +<%session scope="global"> +bool logged_in(false); +</%session> +<%cpp> +//if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + +cRecording const * recording = LiveRecordingsManager()->GetByMd5Hash(recid); +if (recording) { + reply.setKeepAliveHeader(); + reply.setContentLengthHeader(RecSize(recording)); + reply.setDirectMode(); + + cFileName recFile(recording->FileName(), false, false); + // dsyslog("LIVE: start send video data."); + for (cUnbufferedFile *recData = recFile.Open(); recData; recData = recFile.NextFile()) { + char buffer[KILOBYTE(16)]; + ssize_t bytesRead = 0; + // dsyslog("LIVE: send file %s", recFile->Name()); + while (0 < (bytesRead = recData->Read(buffer, sizeof(buffer)))) { + // dsyslog("LIVE: copy %zd bytes", bytesRead); + reply.out().write(buffer, bytesRead); + if (!reply.out()) { + return HTTP_GONE; + } + } + // dsyslog("LIVE: bytesRead = %zd", bytesRead); + if (bytesRead < 0) { + return HTTP_PARTIAL_CONTENT; + } + } + // dsyslog("LIVE: finished send video data."); + reply.out() << std::flush; + return HTTP_OK; +} +return DECLINED; +</%cpp> |