summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDieter Hametner <dh (plus) vdr (at) gekrumbel (dot) de>2008-06-21 02:04:29 +0200
committerDieter Hametner <dh (plus) vdr (at) gekrumbel (dot) de>2008-06-21 02:04:29 +0200
commit79f74de951779431ac46535ed1a0c2824a925c4f (patch)
tree6111b5f439e62fe10c1b8c602297e9bcfa41b51f
parent54ac5eaaab8065473fb023c713e383b7fe5d15a9 (diff)
downloadvdr-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.ecpp72
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>