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 /pages | |
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.
Diffstat (limited to 'pages')
-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> |