diff options
| author | methodus <methodus@web.de> | 2012-09-29 22:48:56 +0200 | 
|---|---|---|
| committer | methodus <methodus@web.de> | 2012-09-29 22:48:56 +0200 | 
| commit | dd3e8652f530c35febcc3f595e38443395f79198 (patch) | |
| tree | eb4cab34cff88b43aaa657491356ab5f9c7cbde8 /httptnt | |
| parent | 97b083ac833ada3c18a5639ee782e575ca583acf (diff) | |
| download | vdr-plugin-upnp-dd3e8652f530c35febcc3f595e38443395f79198.tar.gz vdr-plugin-upnp-dd3e8652f530c35febcc3f595e38443395f79198.tar.bz2 | |
Streamer almost completed. First tests successful. However, there are no plugins, yet.
Diffstat (limited to 'httptnt')
| -rw-r--r-- | httptnt/resourceStreamer.ecpp | 105 | 
1 files changed, 105 insertions, 0 deletions
| diff --git a/httptnt/resourceStreamer.ecpp b/httptnt/resourceStreamer.ecpp new file mode 100644 index 0000000..2c64fed --- /dev/null +++ b/httptnt/resourceStreamer.ecpp @@ -0,0 +1,105 @@ +<%args> +objectID; +int resourceID = 0; +</%args> +<%pre> +#include <string> +#include <stdint.h> +#include <limits> +#include <memory> +#include "../include/tools.h" +#include "../include/media/mediaManager.h" +#include "../include/server.h" + +#include <tnt/httpreply.h> +#include <tnt/httprequest.h> +#include <tnt/http.h> + +using namespace upnp; +</%pre> +<# +int doRequest(tnt::HttpReply reply, tnt::HttpRequest request, std::string objectID, int resourceID) { +#> +<%cpp> +  if(objectID.empty()){ +    reply.out() << "Object ID missing"; +    return HTTP_BAD_REQUEST; +  } + +  cMediaServer* server = cMediaServer::GetInstance(); +  cMediaManager& manager = server->GetManager(); +  std::auto_ptr<cResourceStreamer> streamer(manager.GetResourceStreamer(objectID, resourceID)); + +  if(!streamer.get()){ +    reply.out() << "Object ID not found or invalid"; +    return HTTP_NOT_FOUND; +  } + +  int code = HTTP_OK; + +  reply.setContentType(streamer->GetContentType()); +  reply.setHeader("friendlyName.dlna.org  ", server->GetServerDescription().friendlyName); +  reply.setHeader("contentFeatures.dlna.org  ", streamer->GetContentFeatures()); +  reply.setHeader("transferMode.dlna.org  ", streamer->GetTransferMode(reply.getHeader("transferMode.dlna.org"))); + +  if(streamer->GetContentLength() > 0){ +    reply.setContentLengthHeader(streamer->GetContentLength()); +    if(streamer->Seekable()) reply.setHeader("Accept-Ranges", "bytes"); +  } + +  if(!request.isMethodHEAD()){ + +    int offset = 0, length = std::numeric_limits<long>::max(); +    bool hasRange = false; + +    if(streamer->Seekable() && streamer->GetContentLength() > 0){ +      if(request.hasHeader("Range")){ +        std::string rangeRequest = request.getHeader("Range"); +        if(rangeRequest.find("bytes=",0) == 0){ +          int minus = rangeRequest.find_first_of('-',6); +          offset  = atoi(rangeRequest.substr(6, minus - 6).c_str()); +          length = atoi(rangeRequest.substr(minus + 1).c_str()) - offset; + +          if(length == 0) length = std::numeric_limits<long>::max(); + +          hasRange = (offset == 0 && length == std::numeric_limits<long>::max()) ? false : true; +        } +      } + +      streamer->Seek(offset, SEEK_SET); +    } + +    char buffer[KB(16)]; +    ssize_t bytesRead = 0; +    size_t totalBytesRead = 0; +    size_t toRead = std::min<size_t>(length, sizeof(buffer)); +    while (0 < (bytesRead = streamer->Read(buffer, toRead)) && length > 0) { +      reply.out().write(buffer, bytesRead); +      if (!reply.out()) { +        code = HTTP_GONE; +        goto ret; +      } +      length -= bytesRead; +      totalBytesRead += bytesRead; +      toRead = std::min<size_t>(length, sizeof(buffer)); +    } + +    reply.setContentLengthHeader(totalBytesRead); + +    if ((bytesRead < 0 || length <= 0) && hasRange) { +      std::stringstream ss; +      ss << "bytes " << offset << "-" << offset + totalBytesRead << "/" << streamer->GetContentLength(); +      reply.setHeader("Content-Range", ss.str()); +      code = HTTP_PARTIAL_CONTENT; +      goto ret; +    } + +  } + +  ret: +  //reply.out() << std::flush; +  return code; +</%cpp> +<# +} +#> | 
