<%pre>

#include <filecache.h>
#include <tntfeatures.h>
#include <ffmpeg.h>
#include <fstream>
#include <tnt/mimedb.h>
#include <tnt/sessionunlocker.h>

#include <vdr/tools.h>
#include <unistd.h>

using namespace vdrlive;

</%pre>
<%session scope="global">
bool logged_in(false);
FFmpegThread *f_worker = NULL;
</%session>
<%cpp>
if(f_worker) f_worker->Touch();
tnt::SessionUnlocker unlck = tnt::SessionUnlocker(request, true);

reply.setHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT");

// assign Mime type to repply
tnt::MimeDb mimeDb("/etc/mime.types");
std::string mime = mimeDb.getMimetype(request.getPathInfo());
reply.setContentType(mime);

// check for session cookie. TODO: handle secure cookie for ssl
std::string session;
if (request.hasCookie("tntnet")) {
	session = request.getCookie("tntnet");
}

// forge target path from requested path.
std::string path(request.getPathInfo());
if (path.substr(0, 7) == "/media/") {
	path.replace(0, 7, "/tmp/live-hls-buffer/");
}
else return DECLINED;

// try to open the target file
uint8_t retry;
if (path.rfind(".m3u8") != std::string::npos && path.find("master_") != std::string::npos) retry = 100;
else retry = 5;
std::ifstream f;
do {
	f.open ( path.c_str(), std::ios::binary );
	if (!f.is_open()) {
		usleep(200e3);
	}
} while (!f.is_open() && --retry);

// fail if file did not appear
if (!f.is_open()) {
	dsyslog("vdrlive::stream_data: DECLINED");
	return DECLINED;
}

// wait until TARGETDURATION in playlist is != 0
if (path.rfind(".m3u8") != std::string::npos && path.find("ffmpeg_") != std::string::npos) {
	std::string line;
	int count = 20;
	while(getline(f, line) && count) {
		if (line.find("#EXT-X-TARGETDURATION:") != std::string::npos) {
			if (! (atoi(line.erase(0, 22).c_str()))) {
				count--;
				f.close();
				usleep(100e3);
				f.open( path.c_str(), std::ios::binary );
			}
		}
	}
	f.clear(); // unset eof flag
}

usleep(100e3);
f.seekg( 0, std::ios::end );
std::streamsize size = f.tellg();
f.seekg( 0, std::ios::beg );

unsigned httpReturn = HTTP_OK;
std::string range = request.getHeader(tnt::httpheader::range);
off_t offset = 0, stop = size-1;
if (!range.empty()) {
	range.erase(0,6);
	std::stringstream ss(range);
	char tmp;
	ss >> offset >> tmp >> stop;
	dsyslog("vdrlive::stream_data::range(%ld to %ld)", offset, stop);
	if (offset > size) return HTTP_RANGE_NOT_SATISFIABLE;
	if ((stop+1) > size) stop = size - 1;
	httpReturn = HTTP_PARTIAL_CONTENT;
	std::stringstream contentRange;
	contentRange << offset << ('-') << stop << ('/') << size;
	reply.setHeader(tnt::httpheader::contentRange, contentRange.str());
	f.seekg( offset, std::ios::beg );
}

char buffer[KILOBYTE(64)];
size_t r, c = stop - offset+ 1;
while (r = f.readsome(buffer, (c < (long int) sizeof(buffer))?c:sizeof(buffer))) {
	reply.out().write(buffer, r);
	c -= r;
	if (!reply.out()) {
		return HTTP_GONE;
	}
#if TNT_WATCHDOG_SILENCE
	request.touch(); // retrigger the watchdog.
#endif
}

reply.out() << std::flush;
return httpReturn;
</%cpp>
