<commit_before>#include "output_hls.h"
#include <mist/stream.h>
#include <unistd.h>

namespace Mist {
  ///\brief Builds an index file for HTTP Live streaming.
  ///\return The index file for HTTP Live Streaming.
  std::string OutHLS::liveIndex(){
    std::stringstream result;
    result << "#EXTM3U\r\n";
    int audioId = -1;
    std::string audioName;
    for (std::map<int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
      if (it->second.codec == "AAC"){
        audioId = it->first;
        audioName = it->second.getIdentifier();
        break;
      }
    }
    for (std::map<int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
      if (it->second.codec == "H264"){
        int bWidth = it->second.bps * 2;
        if (audioId != -1){
          bWidth += myMeta.tracks[audioId].bps * 2;
        }
        result << "#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" << bWidth * 10 << "\r\n";
        result << it->first;
        if (audioId != -1){
          result << "_" << audioId;
        }
        result << "/index.m3u8\r\n";
      }
    }
    DEBUG_MSG(DLVL_HIGH, "Sending this index: %s", result.str().c_str());
    return result.str();
  }

  std::string OutHLS::liveIndex(int tid){
    updateMeta();
    std::stringstream result;
    //parse single track
    int longestFragment = 0;
    if (!myMeta.tracks[tid].fragments.size()){
      DEBUG_MSG(DLVL_FAIL, "liveIndex called with track %d, which has no fragments!", tid);
      return "";
    }
    for (std::deque<DTSC::Fragment>::iterator it = myMeta.tracks[tid].fragments.begin(); (it + 1) != myMeta.tracks[tid].fragments.end(); it++){
      if (it->getDuration() > longestFragment){
        longestFragment = it->getDuration();
      }
    }
    result << "#EXTM3U\r\n#EXT-X-TARGETDURATION:" << (longestFragment / 1000) + 1 << "\r\n";

    std::deque<std::string> lines;
    for (std::deque<DTSC::Fragment>::iterator it = myMeta.tracks[tid].fragments.begin(); it != myMeta.tracks[tid].fragments.end(); it++){
      long long int starttime = myMeta.tracks[tid].getKey(it->getNumber()).getTime();
      std::stringstream line;
      long long duration = it->getDuration();
      if (duration < 0){
        duration = myMeta.tracks[tid].lastms - starttime;
      }
      line << "#EXTINF:" << ((duration + 500) / 1000) << ", no desc\r\n" << starttime << "_" << duration + starttime << ".ts\r\n";
      lines.push_back(line.str());
    }

    //skip the first fragment if live and there are more than 2 fragments.
    unsigned int skippedLines = 0;
    if (myMeta.live){
      if (lines.size() > 2){
        lines.pop_front();
        skippedLines++;
      }
      //only print the last segment when VoD
      lines.pop_back();
    }

    result << "#EXT-X-MEDIA-SEQUENCE:" << myMeta.tracks[tid].missedFrags + skippedLines << "\r\n";

    while (lines.size()){
      result << lines.front();
      lines.pop_front();
    }
    if ( !myMeta.live){
      result << "#EXT-X-ENDLIST\r\n";
    }
#if DEBUG >= 8
    std::cerr << "Sending this index:" << std::endl << result.str() << std::endl;
#endif
    return result.str();
  } //liveIndex

  OutHLS::OutHLS(Socket::Connection & conn) : HTTPOutput(conn) {
    haveAvcc = false;
    realTime = 0;
    myConn.setBlocking(true);
  }

  OutHLS::~OutHLS() {}

  void OutHLS::init(Util::Config * cfg){
    HTTPOutput::init(cfg);
    capa["name"] = "HLS";
    capa["desc"] = "Enables HTTP protocol Apple-specific streaming (also known as HLS).";
    capa["url_rel"] = "/hls/$/index.m3u8";
    capa["url_prefix"] = "/hls/$/";
    capa["codecs"][0u][0u].append("H264");
    capa["codecs"][0u][1u].append("AAC");
    capa["codecs"][0u][1u].append("MP3");
    capa["methods"][0u]["handler"] = "http";
    capa["methods"][0u]["type"] = "html5/application/vnd.apple.mpegurl";
    capa["methods"][0u]["priority"] = 9ll;
  }

  ///this function generates the PMT packet
  std::string OutHLS::createPMT(){
    TS::ProgramMappingTable PMT;
    PMT.PID(4096);
    PMT.setTableId(2);
    PMT.setSectionLength(0xB017);
    PMT.setProgramNumber(1);
    PMT.setVersionNumber(0);
    PMT.setCurrentNextIndicator(0);
    PMT.setSectionNumber(0);
    PMT.setLastSectionNumber(0);
    PMT.setPCRPID(0x100 + (*(selectedTracks.begin())) - 1);
    PMT.setProgramInfoLength(0);
    short id = 0;
    //for all selected tracks
    for (std::set<long unsigned int>::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){
      if (myMeta.tracks[*it].codec == "H264"){
        PMT.setStreamType(0x1B,id);
      }else if (myMeta.tracks[*it].codec == "AAC"){
        PMT.setStreamType(0x0F,id);
      }else if (myMeta.tracks[*it].codec == "MP3"){
        PMT.setStreamType(0x03,id);
      }
      PMT.setElementaryPID(0x100 + (*it) - 1, id);
      PMT.setESInfoLength(0,id);
      id++;
    }
    PMT.calcCRC();
    return PMT.getStrBuf();
  }

  void OutHLS::fillPacket(bool & first, const char * data, size_t dataLen, char & ContCounter){
    static std::map<int, int> contCounter;
    if (!PackData.BytesFree()){
      if (PacketNumber % 42 == 0){
        TS::Packet tmpPack;
        tmpPack.FromPointer(TS::PAT);
        tmpPack.ContinuityCounter(++contCounter[tmpPack.PID()]);
        H.Chunkify(tmpPack.ToString(), 188, myConn);
        tmpPack.FromPointer(createPMT().c_str());
        tmpPack.ContinuityCounter(++contCounter[tmpPack.PID()]);
        H.Chunkify(tmpPack.ToString(), 188, myConn);
        PacketNumber += 2;
      }
      H.Chunkify(PackData.ToString(), 188, myConn);
      PacketNumber ++;
      PackData.Clear();
    }

    if (!dataLen){return;}

    if (PackData.BytesFree() == 184){
      PackData.PID(0x100 - 1 + currentPacket.getTrackId());
      PackData.ContinuityCounter(ContCounter++);
      if (first){
        PackData.UnitStart(1);
        if (currentPacket.getInt("keyframe")){
          PackData.RandomAccess(1);
          PackData.PCR(currentPacket.getTime() * 27000);
        }
        first = false;
      }

    }

    int tmp = PackData.FillFree(data, dataLen);
    if (tmp != dataLen){
      fillPacket(first, data+tmp, dataLen-tmp, ContCounter);
    }
  }

  void OutHLS::sendNext(){
    bool first = true;
    char * dataPointer = 0;
    unsigned int dataLen = 0;
    currentPacket.getString("data", dataPointer, dataLen); //data

    if (currentPacket.getTime() >= until){
      stop();
      wantRequest = true;
      parseData = false;
      H.Chunkify("", 0, myConn);
      H.Clean();
      return;
    }

    std::string bs;
    //prepare bufferstring
    if (myMeta.tracks[currentPacket.getTrackId()].type == "video"){
      bs = TS::Packet::getPESVideoLeadIn(0ul, currentPacket.getTime() * 90);
      fillPacket(first, bs.data(), bs.size(), VideoCounter);
      if (myMeta.tracks[currentPacket.getTrackId()].codec == "H264"){
        //End of previous nal unit, somehow needed for h264
        fillPacket(first, "\000\000\000\001\011\360", 6, VideoCounter);
      }

      if (currentPacket.getInt("keyframe")){
        if (!haveAvcc){
          avccbox.setPayload(myMeta.tracks[currentPacket.getTrackId()].init);
          haveAvcc = true;
        }
        bs = avccbox.asAnnexB();
        fillPacket(first, bs.data(), bs.size(), VideoCounter);
      }

      unsigned int i = 0;
      while (i + 4 < (unsigned int)dataLen){
        unsigned int ThisNaluSize = (dataPointer[i] << 24) + (dataPointer[i+1] << 16) + (dataPointer[i+2] << 8) + dataPointer[i+3];
        if (ThisNaluSize + i + 4 > (unsigned int)dataLen){
          DEBUG_MSG(DLVL_WARN, "Too big NALU detected (%u > %d) - skipping!", ThisNaluSize + i + 4, dataLen);
          break;
        }
        fillPacket(first, "\000\000\000\001",4, VideoCounter);
        fillPacket(first, dataPointer+i+4,ThisNaluSize, VideoCounter);
        i += ThisNaluSize+4;
      }
      if (PackData.BytesFree() < 184){
        PackData.AddStuffing();
        fillPacket(first, 0, 0, VideoCounter);
      }
    }else if (myMeta.tracks[currentPacket.getTrackId()].type == "audio"){
      if (AppleCompat){
        bs = TS::Packet::getPESAudioLeadIn(7+dataLen, lastVid);
      }else{
        bs = TS::Packet::getPESAudioLeadIn(7+dataLen, currentPacket.getTime() * 90);
      }
      fillPacket(first, bs.data(), bs.size(), AudioCounter);
      bs = TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init);
      fillPacket(first, bs.data(), bs.size(), AudioCounter);
      fillPacket(first, dataPointer,dataLen, AudioCounter);
      if (PackData.BytesFree() < 184){
        PackData.AddStuffing();
        fillPacket(first, 0, 0, AudioCounter);
      }
    }
  }

  int OutHLS::canSeekms(unsigned int ms){
    //no tracks? Frame too new by definition.
    if ( !myMeta.tracks.size()){
      return 1;
    }
    //loop trough all the tracks
    for (std::map<int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
      //return "too late" if one track is past this point
      if (ms < it->second.firstms){
        return -1;
      }
      //return "too early" if one track is not yet at this point
      if (ms > it->second.lastms){
        return 1;
      }
    }
    return 0;
  }

  void OutHLS::onHTTP(){
    AppleCompat = (H.GetHeader("User-Agent").find("Apple") != std::string::npos);
    initialize();
    if (H.url.find(".m3u") == std::string::npos){
      std::string tmpStr = H.getUrl().substr(5+streamName.size());
      long long unsigned int from;
      if (sscanf(tmpStr.c_str(), "/%u_%u/%llu_%llu.ts", &vidTrack, &audTrack, &from, &until) != 4){
        if (sscanf(tmpStr.c_str(), "/%u/%llu_%llu.ts", &vidTrack, &from, &until) != 3){
          DEBUG_MSG(DLVL_MEDIUM, "Could not parse URL: %s", H.getUrl().c_str());
          H.Clean();
          H.SetBody("The HLS URL wasn't understood - what did you want, exactly?\n");
          myConn.SendNow(H.BuildResponse("404", "URL mismatch"));
          H.Clean(); //clean for any possible next requests
          return;
        }else{
          selectedTracks.clear();
          selectedTracks.insert(vidTrack);
        }
      }else{
        selectedTracks.clear();
        selectedTracks.insert(vidTrack);
        selectedTracks.insert(audTrack);
      }

      if (myMeta.live){
        /// \todo Detection of out-of-range parts.
        int seekable = canSeekms(from);
        if (seekable < 0){
          H.Clean();
          H.SetBody("The requested fragment is no longer kept in memory on the server and cannot be served.\n");
          myConn.SendNow(H.BuildResponse("412", "Fragment out of range"));
          H.Clean(); //clean for any possible next requests
          DEBUG_MSG(DLVL_WARN, "Fragment @ %llu too old", from);
          return;
        }
        if (seekable > 0){
          H.Clean();
          H.SetBody("Proxy, re-request this in a second or two.\n");
          myConn.SendNow(H.BuildResponse("208", "Ask again later"));
          H.Clean(); //clean for any possible next requests
          DEBUG_MSG(DLVL_WARN, "Fragment @ %llu not available yet", from);
          return;
        }
      }

      seek(from);
      lastVid = from * 90;

      H.SetHeader("Content-Type", "video/mp2t");
      H.StartResponse(H, myConn);
      PacketNumber = 0;
      parseData = true;
      wantRequest = false;
    }else{
      initialize();
      std::string request = H.url.substr(H.url.find("/", 5) + 1);
      H.Clean();
      if (H.url.find(".m3u8") != std::string::npos){
        H.SetHeader("Content-Type", "audio/x-mpegurl");
      }else{
        H.SetHeader("Content-Type", "audio/mpegurl");
      }
      H.SetHeader("Cache-Control", "no-cache");
      std::string manifest;
      if (request.find("/") == std::string::npos){
        manifest = liveIndex();
      }else{
        int selectId = atoi(request.substr(0,request.find("/")).c_str());
        manifest = liveIndex(selectId);
      }
      H.SetBody(manifest);
      H.SendResponse("200", "OK", myConn);
    }
  }
}
<commit_msg>Fixed PCR location for HLS streams<commit_after>#include "output_hls.h"
#include <mist/stream.h>
#include <unistd.h>

namespace Mist {
  ///\brief Builds an index file for HTTP Live streaming.
  ///\return The index file for HTTP Live Streaming.
  std::string OutHLS::liveIndex(){
    std::stringstream result;
    result << "#EXTM3U\r\n";
    int audioId = -1;
    std::string audioName;
    for (std::map<int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
      if (it->second.codec == "AAC"){
        audioId = it->first;
        audioName = it->second.getIdentifier();
        break;
      }
    }
    for (std::map<int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
      if (it->second.codec == "H264"){
        int bWidth = it->second.bps * 2;
        if (audioId != -1){
          bWidth += myMeta.tracks[audioId].bps * 2;
        }
        result << "#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" << bWidth * 10 << "\r\n";
        result << it->first;
        if (audioId != -1){
          result << "_" << audioId;
        }
        result << "/index.m3u8\r\n";
      }
    }
    DEBUG_MSG(DLVL_HIGH, "Sending this index: %s", result.str().c_str());
    return result.str();
  }

  std::string OutHLS::liveIndex(int tid){
    updateMeta();
    std::stringstream result;
    //parse single track
    int longestFragment = 0;
    if (!myMeta.tracks[tid].fragments.size()){
      DEBUG_MSG(DLVL_FAIL, "liveIndex called with track %d, which has no fragments!", tid);
      return "";
    }
    for (std::deque<DTSC::Fragment>::iterator it = myMeta.tracks[tid].fragments.begin(); (it + 1) != myMeta.tracks[tid].fragments.end(); it++){
      if (it->getDuration() > longestFragment){
        longestFragment = it->getDuration();
      }
    }
    result << "#EXTM3U\r\n#EXT-X-TARGETDURATION:" << (longestFragment / 1000) + 1 << "\r\n";

    std::deque<std::string> lines;
    for (std::deque<DTSC::Fragment>::iterator it = myMeta.tracks[tid].fragments.begin(); it != myMeta.tracks[tid].fragments.end(); it++){
      long long int starttime = myMeta.tracks[tid].getKey(it->getNumber()).getTime();
      std::stringstream line;
      long long duration = it->getDuration();
      if (duration < 0){
        duration = myMeta.tracks[tid].lastms - starttime;
      }
      line << "#EXTINF:" << ((duration + 500) / 1000) << ", no desc\r\n" << starttime << "_" << duration + starttime << ".ts\r\n";
      lines.push_back(line.str());
    }

    //skip the first fragment if live and there are more than 2 fragments.
    unsigned int skippedLines = 0;
    if (myMeta.live){
      if (lines.size() > 2){
        lines.pop_front();
        skippedLines++;
      }
      //only print the last segment when VoD
      lines.pop_back();
    }

    result << "#EXT-X-MEDIA-SEQUENCE:" << myMeta.tracks[tid].missedFrags + skippedLines << "\r\n";

    while (lines.size()){
      result << lines.front();
      lines.pop_front();
    }
    if ( !myMeta.live){
      result << "#EXT-X-ENDLIST\r\n";
    }
#if DEBUG >= 8
    std::cerr << "Sending this index:" << std::endl << result.str() << std::endl;
#endif
    return result.str();
  } //liveIndex

  OutHLS::OutHLS(Socket::Connection & conn) : HTTPOutput(conn) {
    haveAvcc = false;
    realTime = 0;
    myConn.setBlocking(true);
  }

  OutHLS::~OutHLS() {}

  void OutHLS::init(Util::Config * cfg){
    HTTPOutput::init(cfg);
    capa["name"] = "HLS";
    capa["desc"] = "Enables HTTP protocol Apple-specific streaming (also known as HLS).";
    capa["url_rel"] = "/hls/$/index.m3u8";
    capa["url_prefix"] = "/hls/$/";
    capa["codecs"][0u][0u].append("H264");
    capa["codecs"][0u][1u].append("AAC");
    capa["codecs"][0u][1u].append("MP3");
    capa["methods"][0u]["handler"] = "http";
    capa["methods"][0u]["type"] = "html5/application/vnd.apple.mpegurl";
    capa["methods"][0u]["priority"] = 9ll;
  }

  ///this function generates the PMT packet
  std::string OutHLS::createPMT(){
    TS::ProgramMappingTable PMT;
    PMT.PID(4096);
    PMT.setTableId(2);
    PMT.setSectionLength(0xB017);
    PMT.setProgramNumber(1);
    PMT.setVersionNumber(0);
    PMT.setCurrentNextIndicator(0);
    PMT.setSectionNumber(0);
    PMT.setLastSectionNumber(0);
    int vidTrack = -1;
    for (std::set<int>::iterator it == selectedTracks.begin(); it != selectedTracks.end(); it++){
      if (myMeta.tracks[*it].type == "video"){
        vidTrack = *it;
        break;
      }
    }
    if (vidTrack == -1){
      vidTrack = *(selectedTracks.begin());
    }
    PMT.setPCRPID(0x100 + vidTrack - 1);
    PMT.setProgramInfoLength(0);
    short id = 0;
    //for all selected tracks
    for (std::set<long unsigned int>::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){
      if (myMeta.tracks[*it].codec == "H264"){
        PMT.setStreamType(0x1B,id);
      }else if (myMeta.tracks[*it].codec == "AAC"){
        PMT.setStreamType(0x0F,id);
      }else if (myMeta.tracks[*it].codec == "MP3"){
        PMT.setStreamType(0x03,id);
      }
      PMT.setElementaryPID(0x100 + (*it) - 1, id);
      PMT.setESInfoLength(0,id);
      id++;
    }
    PMT.calcCRC();
    return PMT.getStrBuf();
  }

  void OutHLS::fillPacket(bool & first, const char * data, size_t dataLen, char & ContCounter){
    static std::map<int, int> contCounter;
    if (!PackData.BytesFree()){
      if (PacketNumber % 42 == 0){
        TS::Packet tmpPack;
        tmpPack.FromPointer(TS::PAT);
        tmpPack.ContinuityCounter(++contCounter[tmpPack.PID()]);
        H.Chunkify(tmpPack.ToString(), 188, myConn);
        tmpPack.FromPointer(createPMT().c_str());
        tmpPack.ContinuityCounter(++contCounter[tmpPack.PID()]);
        H.Chunkify(tmpPack.ToString(), 188, myConn);
        PacketNumber += 2;
      }
      H.Chunkify(PackData.ToString(), 188, myConn);
      PacketNumber ++;
      PackData.Clear();
    }

    if (!dataLen){return;}

    if (PackData.BytesFree() == 184){
      PackData.PID(0x100 - 1 + currentPacket.getTrackId());
      PackData.ContinuityCounter(ContCounter++);
      if (first){
        PackData.UnitStart(1);
        if (currentPacket.getInt("keyframe")){
          PackData.RandomAccess(1);
          PackData.PCR(currentPacket.getTime() * 27000);
        }
        first = false;
      }

    }

    int tmp = PackData.FillFree(data, dataLen);
    if (tmp != dataLen){
      fillPacket(first, data+tmp, dataLen-tmp, ContCounter);
    }
  }

  void OutHLS::sendNext(){
    bool first = true;
    char * dataPointer = 0;
    unsigned int dataLen = 0;
    currentPacket.getString("data", dataPointer, dataLen); //data

    if (currentPacket.getTime() >= until){
      stop();
      wantRequest = true;
      parseData = false;
      H.Chunkify("", 0, myConn);
      H.Clean();
      return;
    }

    std::string bs;
    //prepare bufferstring
    if (myMeta.tracks[currentPacket.getTrackId()].type == "video"){
      bs = TS::Packet::getPESVideoLeadIn(0ul, currentPacket.getTime() * 90);
      fillPacket(first, bs.data(), bs.size(), VideoCounter);
      if (myMeta.tracks[currentPacket.getTrackId()].codec == "H264"){
        //End of previous nal unit, somehow needed for h264
        fillPacket(first, "\000\000\000\001\011\360", 6, VideoCounter);
      }

      if (currentPacket.getInt("keyframe")){
        if (!haveAvcc){
          avccbox.setPayload(myMeta.tracks[currentPacket.getTrackId()].init);
          haveAvcc = true;
        }
        bs = avccbox.asAnnexB();
        fillPacket(first, bs.data(), bs.size(), VideoCounter);
      }

      unsigned int i = 0;
      while (i + 4 < (unsigned int)dataLen){
        unsigned int ThisNaluSize = (dataPointer[i] << 24) + (dataPointer[i+1] << 16) + (dataPointer[i+2] << 8) + dataPointer[i+3];
        if (ThisNaluSize + i + 4 > (unsigned int)dataLen){
          DEBUG_MSG(DLVL_WARN, "Too big NALU detected (%u > %d) - skipping!", ThisNaluSize + i + 4, dataLen);
          break;
        }
        fillPacket(first, "\000\000\000\001",4, VideoCounter);
        fillPacket(first, dataPointer+i+4,ThisNaluSize, VideoCounter);
        i += ThisNaluSize+4;
      }
      if (PackData.BytesFree() < 184){
        PackData.AddStuffing();
        fillPacket(first, 0, 0, VideoCounter);
      }
    }else if (myMeta.tracks[currentPacket.getTrackId()].type == "audio"){
      if (AppleCompat){
        bs = TS::Packet::getPESAudioLeadIn(7+dataLen, lastVid);
      }else{
        bs = TS::Packet::getPESAudioLeadIn(7+dataLen, currentPacket.getTime() * 90);
      }
      fillPacket(first, bs.data(), bs.size(), AudioCounter);
      bs = TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init);
      fillPacket(first, bs.data(), bs.size(), AudioCounter);
      fillPacket(first, dataPointer,dataLen, AudioCounter);
      if (PackData.BytesFree() < 184){
        PackData.AddStuffing();
        fillPacket(first, 0, 0, AudioCounter);
      }
    }
  }

  int OutHLS::canSeekms(unsigned int ms){
    //no tracks? Frame too new by definition.
    if ( !myMeta.tracks.size()){
      return 1;
    }
    //loop trough all the tracks
    for (std::map<int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
      //return "too late" if one track is past this point
      if (ms < it->second.firstms){
        return -1;
      }
      //return "too early" if one track is not yet at this point
      if (ms > it->second.lastms){
        return 1;
      }
    }
    return 0;
  }

  void OutHLS::onHTTP(){
    AppleCompat = (H.GetHeader("User-Agent").find("Apple") != std::string::npos);
    initialize();
    if (H.url.find(".m3u") == std::string::npos){
      std::string tmpStr = H.getUrl().substr(5+streamName.size());
      long long unsigned int from;
      if (sscanf(tmpStr.c_str(), "/%u_%u/%llu_%llu.ts", &vidTrack, &audTrack, &from, &until) != 4){
        if (sscanf(tmpStr.c_str(), "/%u/%llu_%llu.ts", &vidTrack, &from, &until) != 3){
          DEBUG_MSG(DLVL_MEDIUM, "Could not parse URL: %s", H.getUrl().c_str());
          H.Clean();
          H.SetBody("The HLS URL wasn't understood - what did you want, exactly?\n");
          myConn.SendNow(H.BuildResponse("404", "URL mismatch"));
          H.Clean(); //clean for any possible next requests
          return;
        }else{
          selectedTracks.clear();
          selectedTracks.insert(vidTrack);
        }
      }else{
        selectedTracks.clear();
        selectedTracks.insert(vidTrack);
        selectedTracks.insert(audTrack);
      }

      if (myMeta.live){
        /// \todo Detection of out-of-range parts.
        int seekable = canSeekms(from);
        if (seekable < 0){
          H.Clean();
          H.SetBody("The requested fragment is no longer kept in memory on the server and cannot be served.\n");
          myConn.SendNow(H.BuildResponse("412", "Fragment out of range"));
          H.Clean(); //clean for any possible next requests
          DEBUG_MSG(DLVL_WARN, "Fragment @ %llu too old", from);
          return;
        }
        if (seekable > 0){
          H.Clean();
          H.SetBody("Proxy, re-request this in a second or two.\n");
          myConn.SendNow(H.BuildResponse("208", "Ask again later"));
          H.Clean(); //clean for any possible next requests
          DEBUG_MSG(DLVL_WARN, "Fragment @ %llu not available yet", from);
          return;
        }
      }

      seek(from);
      lastVid = from * 90;

      H.SetHeader("Content-Type", "video/mp2t");
      H.StartResponse(H, myConn);
      PacketNumber = 0;
      parseData = true;
      wantRequest = false;
    }else{
      initialize();
      std::string request = H.url.substr(H.url.find("/", 5) + 1);
      H.Clean();
      if (H.url.find(".m3u8") != std::string::npos){
        H.SetHeader("Content-Type", "audio/x-mpegurl");
      }else{
        H.SetHeader("Content-Type", "audio/mpegurl");
      }
      H.SetHeader("Cache-Control", "no-cache");
      std::string manifest;
      if (request.find("/") == std::string::npos){
        manifest = liveIndex();
      }else{
        int selectId = atoi(request.substr(0,request.find("/")).c_str());
        manifest = liveIndex(selectId);
      }
      H.SetBody(manifest);
      H.SendResponse("200", "OK", myConn);
    }
  }
}
<|endoftext|>


<commit_before>//                       MFEM Example 6 - Parallel Version
//                              PUMI Modification
//
// Compile with: make ex6p
//
// Sample runs:  mpirun -np 8 ex6p
//
// Description:  This is a version of Example 1 with a simple adaptive mesh
//               refinement loop. The problem being solved is again the Laplace
//               equation -Delta u = 1 with homogeneous Dirichlet boundary
//               conditions. The problem is solved on a sequence of meshes which
//               are adapted in a conforming (tetrahedrons) manner according
//               to a simple SPR ZZ error estimator.
//
//               This PUMI variation also performs a "uniform" refinement,
//               similar to MFEM examples, for coarse meshes. However, the
//               refinement is performed using the PUMI API. A new option "-ar"
//               is added to modify the "adapt_ratio" which is the fraction of
//               allowable error that scales the output size field of the error
//               estimator.
//
// NOTE:         Model/Mesh files for this example are in the (large) data file
//               repository of MFEM here https://github.com/mfem/data under the
//               folder named "pumi", which consists of the following sub-folders:
//               a) geom -->  model files
//               b) parallel --> parallel pumi mesh files
//               c) serial --> serial pumi mesh files

#include "mfem.hpp"
#include <fstream>
#include <iostream>

#ifdef MFEM_USE_SIMMETRIX
#include <SimUtil.h>
#include <gmi_sim.h>
#endif
#include <apfMDS.h>
#include <gmi_null.h>
#include <PCU.h>
#include <spr.h>
#include <apfConvert.h>
#include <gmi_mesh.h>
#include <crv.h>

#ifndef MFEM_USE_PUMI
#error This example requires that MFEM is built with MFEM_USE_PUMI=YES
#endif

using namespace std;
using namespace mfem;

int main(int argc, char *argv[])
{
   // 1. Initialize MPI.
   int num_procs, myid;
   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
   MPI_Comm_rank(MPI_COMM_WORLD, &myid);

   // 2. Parse command-line options.
   const char *mesh_file = "../../data/pumi/parallel/Kova/Kova100k_8.smb";
#ifdef MFEM_USE_SIMMETRIX
   const char *model_file = "../../data/pumi/geom/Kova.x_t";
   const char *smd_file = NULL;
#else
   const char *model_file = "../../data/pumi/geom/Kova.dmg";
#endif
   int order = 1;
   bool static_cond = false;
   bool visualization = 1;
   int geom_order = 1;
   double adapt_ratio = 0.05;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&order, "-o", "--order",
                  "Finite element order (polynomial degree) or -1 for"
                  " isoparametric space.");
   args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
                  "--no-static-condensation", "Enable static condensation.");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.AddOption(&model_file, "-p", "--model",
                  "parasolid or .dmg model to use.");
#ifdef MFEM_USE_SIMMETRIX
   args.AddOption(&smd_file, "-sm", "--smd_model",
                  "smd model file to use.");
#endif
   args.AddOption(&geom_order, "-go", "--geometry_order",
                  "Geometric order of the model");
   args.AddOption(&adapt_ratio, "-ar", "--adapt_ratio",
                  "adaptation factor used in MeshAdapt");
   args.Parse();
   if (!args.Good())
   {
      if (myid == 0)
      {
         args.PrintUsage(cout);
      }
      MPI_Finalize();
      return 1;
   }
   if (myid == 0)
   {
      args.PrintOptions(cout);
   }

   // 3. Read the SCOREC Mesh.
   PCU_Comm_Init();
#ifdef MFEM_USE_SIMMETRIX
   Sim_readLicenseFile(0);
   gmi_sim_start();
   gmi_register_sim();
#endif
   gmi_register_mesh();

   apf::Mesh2* pumi_mesh;
#ifdef MFEM_USE_SIMMETRIX
   if (smd_file)
   {
      gmi_model *mixed_model = gmi_sim_load(model_file, smd_file);
      pumi_mesh = apf::loadMdsMesh(mixed_model, mesh_file);
   }
   else
#endif
   {
      pumi_mesh = apf::loadMdsMesh(model_file, mesh_file);
   }

   // 4. Increase the geometry order and refine the mesh if necessary.  Parallel
   //    uniform refinement is performed if the total number of elements is less
   //    than 100,000.
   int dim = pumi_mesh->getDimension();
   int nEle = pumi_mesh->count(dim);
   int ref_levels = (int)floor(log(100000./nEle)/log(2.)/dim);

   if (geom_order > 1)
   {
      crv::BezierCurver bc(pumi_mesh, geom_order, 2);
      bc.run();
   }

   // Perform Uniform refinement
   if (myid == 1)
   {
      std::cout << " ref level : " <<     ref_levels << std::endl;
   }

   if (ref_levels > 1)
   {
      ma::Input* uniInput = ma::configureUniformRefine(pumi_mesh, ref_levels);

      if ( geom_order > 1)
      {
         crv::adapt(uniInput);
      }
      else
      {
         ma::adapt(uniInput);
      }
   }

   pumi_mesh->verify();

   // 5. Create the parallel MFEM mesh object from the parallel PUMI mesh.  We
   //    can handle triangular and tetrahedral meshes. Note that the mesh
   //    resolution is performed on the PUMI mesh.
   ParMesh *pmesh = new ParPumiMesh(MPI_COMM_WORLD, pumi_mesh);

   // 6. Define a parallel finite element space on the parallel mesh. Here we
   //    use continuous Lagrange finite elements of the specified order. If
   //    order < 1, we instead use an isoparametric/isogeometric space.
   FiniteElementCollection *fec;
   if (order > 0)
   {
      fec = new H1_FECollection(order, dim);
   }
   else if (pmesh->GetNodes())
   {
      fec = pmesh->GetNodes()->OwnFEC();
      if (myid == 1)
      {
         cout << "Using isoparametric FEs: " << fec->Name() << endl;
      }
   }
   else
   {
      fec = new H1_FECollection(order = 1, dim);
   }
   ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
   HYPRE_BigInt size = fespace->GlobalTrueVSize();
   if (myid == 1)
   {
      cout << "Number of finite element unknowns: " << size << endl;
   }

   // 7. Set up the parallel linear form b(.) which corresponds to the
   //    right-hand side of the FEM linear system, which in this case is
   //    (1,phi_i) where phi_i are the basis functions in fespace.
   ParLinearForm *b = new ParLinearForm(fespace);
   ConstantCoefficient one(1.0);
   b->AddDomainIntegrator(new DomainLFIntegrator(one));

   // 8. Define the solution vector x as a parallel finite element grid function
   //    corresponding to fespace. Initialize x with initial guess of zero,
   //    which satisfies the boundary conditions.
   ParGridFunction x(fespace);
   x = 0.0;

   // 9. Connect to GLVis.
   char vishost[] = "localhost";
   int  visport   = 19916;

   socketstream sout;
   if (visualization)
   {
      sout.open(vishost, visport);
      if (!sout)
      {
         if (myid == 0)
         {
            cout << "Unable to connect to GLVis server at "
                 << vishost << ':' << visport << endl;
            cout << "GLVis visualization disabled.\n";
         }
         visualization = false;
      }

      sout.precision(8);
   }

   // 10. Set up the parallel bilinear form a(.,.) on the finite element space
   //     corresponding to the Laplacian operator -Delta, by adding the
   //     Diffusion domain integrator.
   ParBilinearForm *a = new ParBilinearForm(fespace);
   a->AddDomainIntegrator(new DiffusionIntegrator(one));

   // 11. Assemble the parallel bilinear form and the corresponding linear
   //     system, applying any necessary transformations such as: parallel
   //     assembly, eliminating boundary conditions, applying conforming
   //     constraints for non-conforming AMR, static condensation, etc.
   if (static_cond) { a->EnableStaticCondensation(); }

   // 12. The main AMR loop. In each iteration we solve the problem on the
   //     current mesh, visualize the solution, and adapt the mesh.
   apf::Field* Tmag_field = 0;
   apf::Field* temp_field = 0;
   apf::Field* ipfield = 0;
   apf::Field* sizefield = 0;
   int max_iter = 3;

   for (int Itr = 0; Itr < max_iter; Itr++)
   {
      HYPRE_BigInt global_dofs = fespace->GlobalTrueVSize();
      if (myid == 1)
      {
         cout << "\nAMR iteration " << Itr << endl;
         cout << "Number of unknowns: " << global_dofs << endl;
      }

      // Assemble.
      a->Assemble();
      b->Assemble();

      // Essential boundary condition.
      Array<int> ess_tdof_list;
      if (pmesh->bdr_attributes.Size())
      {
         Array<int> ess_bdr(pmesh->bdr_attributes.Max());
         ess_bdr = 1;
         fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
      }

      // Form linear system.
      HypreParMatrix A;
      Vector B, X;
      const int copy_interior = 1;
      a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B, copy_interior);

      // 13. Define and apply a parallel PCG solver for AX=B with the BoomerAMG
      //     preconditioner from hypre.
      HypreBoomerAMG amg;
      amg.SetPrintLevel(0);
      CGSolver pcg(A.GetComm());
      pcg.SetPreconditioner(amg);
      pcg.SetOperator(A);
      pcg.SetRelTol(1e-6);
      pcg.SetMaxIter(200);
      pcg.SetPrintLevel(3); // print the first and the last iterations only
      pcg.Mult(B, X);

      // 14. Recover the parallel grid function corresponding to X. This is the
      //     local finite element solution on each processor.
      a->RecoverFEMSolution(X, *b, x);

      // 15. Save in parallel the displaced mesh and the inverted solution (which
      //     gives the backward displacements to the original grid). This output
      //     can be viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
      {
         ostringstream mesh_name, sol_name;
         mesh_name << "mesh." << setfill('0') << setw(6) << myid;
         sol_name << "sol." << setfill('0') << setw(6) << myid;

         ofstream mesh_ofs(mesh_name.str().c_str());
         mesh_ofs.precision(8);
         pmesh->Print(mesh_ofs);

         ofstream sol_ofs(sol_name.str().c_str());
         sol_ofs.precision(8);
         x.Save(sol_ofs);
      }

      // 16. Send the above data by socket to a GLVis server.  Use the "n" and "b"
      //     keys in GLVis to visualize the displacements.
      if (visualization)
      {
         sout << "parallel " << num_procs << " " << myid << "\n";
         sout << "solution\n" << *pmesh << x << flush;
      }

      // 17. Field transfer. Scalar solution field and magnitude field for error
      //     estimation are created the PUMI mesh.
      if (order > geom_order)
      {
         Tmag_field = apf::createField(pumi_mesh, "field_mag",
                                       apf::SCALAR, apf::getLagrange(order));
         temp_field = apf::createField(pumi_mesh, "T_field",
                                       apf::SCALAR, apf::getLagrange(order));
      }
      else
      {
         Tmag_field = apf::createFieldOn(pumi_mesh, "field_mag",apf::SCALAR);
         temp_field = apf::createFieldOn(pumi_mesh, "T_field", apf::SCALAR);
      }

      ParPumiMesh* pPPmesh = dynamic_cast<ParPumiMesh*>(pmesh);
      pPPmesh->FieldMFEMtoPUMI(pumi_mesh, &x, temp_field, Tmag_field);

      ipfield= spr::getGradIPField(Tmag_field, "MFEM_gradip", 2);
      sizefield = spr::getSPRSizeField(ipfield, adapt_ratio);

      apf::destroyField(Tmag_field);
      apf::destroyField(ipfield);

      // 18. Perform MesAdapt.
      ma::Input* erinput = ma::configure(pumi_mesh, sizefield);
      erinput->shouldFixShape = true;
      erinput->maximumIterations = 2;
      if ( geom_order > 1)
      {
         crv::adapt(erinput);
      }
      else
      {
         ma::adapt(erinput);
      }

      ParMesh* Adapmesh = new ParPumiMesh(MPI_COMM_WORLD, pumi_mesh);
      pPPmesh->UpdateMesh(Adapmesh);
      delete Adapmesh;

      // 19. Update the FiniteElementSpace, GridFunction, and bilinear form.
      fespace->Update();
      x.Update();
      x = 0.0;

      pPPmesh->FieldPUMItoMFEM(pumi_mesh, temp_field, &x);
      a->Update();
      b->Update();

      // Destroy fields.
      apf::destroyField(temp_field);
      apf::destroyField(sizefield);
   }

   // 20. Free the used memory.
   delete a;
   delete b;
   delete fespace;
   if (order > 0) { delete fec; }
   delete pmesh;

   pumi_mesh->destroyNative();
   apf::destroyMesh(pumi_mesh);
   PCU_Comm_Free();

#ifdef MFEM_USE_SIMMETRIX
   gmi_sim_stop();
   Sim_unregisterAllKeys();
#endif

   MPI_Finalize();

   return 0;
}
<commit_msg>pumi/ex6p: const adapt input instances<commit_after>//                       MFEM Example 6 - Parallel Version
//                              PUMI Modification
//
// Compile with: make ex6p
//
// Sample runs:  mpirun -np 8 ex6p
//
// Description:  This is a version of Example 1 with a simple adaptive mesh
//               refinement loop. The problem being solved is again the Laplace
//               equation -Delta u = 1 with homogeneous Dirichlet boundary
//               conditions. The problem is solved on a sequence of meshes which
//               are adapted in a conforming (tetrahedrons) manner according
//               to a simple SPR ZZ error estimator.
//
//               This PUMI variation also performs a "uniform" refinement,
//               similar to MFEM examples, for coarse meshes. However, the
//               refinement is performed using the PUMI API. A new option "-ar"
//               is added to modify the "adapt_ratio" which is the fraction of
//               allowable error that scales the output size field of the error
//               estimator.
//
// NOTE:         Model/Mesh files for this example are in the (large) data file
//               repository of MFEM here https://github.com/mfem/data under the
//               folder named "pumi", which consists of the following sub-folders:
//               a) geom -->  model files
//               b) parallel --> parallel pumi mesh files
//               c) serial --> serial pumi mesh files

#include "mfem.hpp"
#include <fstream>
#include <iostream>

#ifdef MFEM_USE_SIMMETRIX
#include <SimUtil.h>
#include <gmi_sim.h>
#endif
#include <apfMDS.h>
#include <gmi_null.h>
#include <PCU.h>
#include <spr.h>
#include <apfConvert.h>
#include <gmi_mesh.h>
#include <crv.h>

#ifndef MFEM_USE_PUMI
#error This example requires that MFEM is built with MFEM_USE_PUMI=YES
#endif

using namespace std;
using namespace mfem;

int main(int argc, char *argv[])
{
   // 1. Initialize MPI.
   int num_procs, myid;
   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
   MPI_Comm_rank(MPI_COMM_WORLD, &myid);

   // 2. Parse command-line options.
   const char *mesh_file = "../../data/pumi/parallel/Kova/Kova100k_8.smb";
#ifdef MFEM_USE_SIMMETRIX
   const char *model_file = "../../data/pumi/geom/Kova.x_t";
   const char *smd_file = NULL;
#else
   const char *model_file = "../../data/pumi/geom/Kova.dmg";
#endif
   int order = 1;
   bool static_cond = false;
   bool visualization = 1;
   int geom_order = 1;
   double adapt_ratio = 0.05;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&order, "-o", "--order",
                  "Finite element order (polynomial degree) or -1 for"
                  " isoparametric space.");
   args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
                  "--no-static-condensation", "Enable static condensation.");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.AddOption(&model_file, "-p", "--model",
                  "parasolid or .dmg model to use.");
#ifdef MFEM_USE_SIMMETRIX
   args.AddOption(&smd_file, "-sm", "--smd_model",
                  "smd model file to use.");
#endif
   args.AddOption(&geom_order, "-go", "--geometry_order",
                  "Geometric order of the model");
   args.AddOption(&adapt_ratio, "-ar", "--adapt_ratio",
                  "adaptation factor used in MeshAdapt");
   args.Parse();
   if (!args.Good())
   {
      if (myid == 0)
      {
         args.PrintUsage(cout);
      }
      MPI_Finalize();
      return 1;
   }
   if (myid == 0)
   {
      args.PrintOptions(cout);
   }

   // 3. Read the SCOREC Mesh.
   PCU_Comm_Init();
#ifdef MFEM_USE_SIMMETRIX
   Sim_readLicenseFile(0);
   gmi_sim_start();
   gmi_register_sim();
#endif
   gmi_register_mesh();

   apf::Mesh2* pumi_mesh;
#ifdef MFEM_USE_SIMMETRIX
   if (smd_file)
   {
      gmi_model *mixed_model = gmi_sim_load(model_file, smd_file);
      pumi_mesh = apf::loadMdsMesh(mixed_model, mesh_file);
   }
   else
#endif
   {
      pumi_mesh = apf::loadMdsMesh(model_file, mesh_file);
   }

   // 4. Increase the geometry order and refine the mesh if necessary.  Parallel
   //    uniform refinement is performed if the total number of elements is less
   //    than 100,000.
   int dim = pumi_mesh->getDimension();
   int nEle = pumi_mesh->count(dim);
   int ref_levels = (int)floor(log(100000./nEle)/log(2.)/dim);

   if (geom_order > 1)
   {
      crv::BezierCurver bc(pumi_mesh, geom_order, 2);
      bc.run();
   }

   // Perform Uniform refinement
   if (myid == 1)
   {
      std::cout << " ref level : " <<     ref_levels << std::endl;
   }

   if (ref_levels > 1)
   {
      const ma::Input* uniInput = ma::configureUniformRefine(pumi_mesh, ref_levels);

      if ( geom_order > 1)
      {
         crv::adapt(uniInput);
      }
      else
      {
         ma::adapt(uniInput);
      }
   }

   pumi_mesh->verify();

   // 5. Create the parallel MFEM mesh object from the parallel PUMI mesh.  We
   //    can handle triangular and tetrahedral meshes. Note that the mesh
   //    resolution is performed on the PUMI mesh.
   ParMesh *pmesh = new ParPumiMesh(MPI_COMM_WORLD, pumi_mesh);

   // 6. Define a parallel finite element space on the parallel mesh. Here we
   //    use continuous Lagrange finite elements of the specified order. If
   //    order < 1, we instead use an isoparametric/isogeometric space.
   FiniteElementCollection *fec;
   if (order > 0)
   {
      fec = new H1_FECollection(order, dim);
   }
   else if (pmesh->GetNodes())
   {
      fec = pmesh->GetNodes()->OwnFEC();
      if (myid == 1)
      {
         cout << "Using isoparametric FEs: " << fec->Name() << endl;
      }
   }
   else
   {
      fec = new H1_FECollection(order = 1, dim);
   }
   ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
   HYPRE_BigInt size = fespace->GlobalTrueVSize();
   if (myid == 1)
   {
      cout << "Number of finite element unknowns: " << size << endl;
   }

   // 7. Set up the parallel linear form b(.) which corresponds to the
   //    right-hand side of the FEM linear system, which in this case is
   //    (1,phi_i) where phi_i are the basis functions in fespace.
   ParLinearForm *b = new ParLinearForm(fespace);
   ConstantCoefficient one(1.0);
   b->AddDomainIntegrator(new DomainLFIntegrator(one));

   // 8. Define the solution vector x as a parallel finite element grid function
   //    corresponding to fespace. Initialize x with initial guess of zero,
   //    which satisfies the boundary conditions.
   ParGridFunction x(fespace);
   x = 0.0;

   // 9. Connect to GLVis.
   char vishost[] = "localhost";
   int  visport   = 19916;

   socketstream sout;
   if (visualization)
   {
      sout.open(vishost, visport);
      if (!sout)
      {
         if (myid == 0)
         {
            cout << "Unable to connect to GLVis server at "
                 << vishost << ':' << visport << endl;
            cout << "GLVis visualization disabled.\n";
         }
         visualization = false;
      }

      sout.precision(8);
   }

   // 10. Set up the parallel bilinear form a(.,.) on the finite element space
   //     corresponding to the Laplacian operator -Delta, by adding the
   //     Diffusion domain integrator.
   ParBilinearForm *a = new ParBilinearForm(fespace);
   a->AddDomainIntegrator(new DiffusionIntegrator(one));

   // 11. Assemble the parallel bilinear form and the corresponding linear
   //     system, applying any necessary transformations such as: parallel
   //     assembly, eliminating boundary conditions, applying conforming
   //     constraints for non-conforming AMR, static condensation, etc.
   if (static_cond) { a->EnableStaticCondensation(); }

   // 12. The main AMR loop. In each iteration we solve the problem on the
   //     current mesh, visualize the solution, and adapt the mesh.
   apf::Field* Tmag_field = 0;
   apf::Field* temp_field = 0;
   apf::Field* ipfield = 0;
   apf::Field* sizefield = 0;
   int max_iter = 3;

   for (int Itr = 0; Itr < max_iter; Itr++)
   {
      HYPRE_BigInt global_dofs = fespace->GlobalTrueVSize();
      if (myid == 1)
      {
         cout << "\nAMR iteration " << Itr << endl;
         cout << "Number of unknowns: " << global_dofs << endl;
      }

      // Assemble.
      a->Assemble();
      b->Assemble();

      // Essential boundary condition.
      Array<int> ess_tdof_list;
      if (pmesh->bdr_attributes.Size())
      {
         Array<int> ess_bdr(pmesh->bdr_attributes.Max());
         ess_bdr = 1;
         fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
      }

      // Form linear system.
      HypreParMatrix A;
      Vector B, X;
      const int copy_interior = 1;
      a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B, copy_interior);

      // 13. Define and apply a parallel PCG solver for AX=B with the BoomerAMG
      //     preconditioner from hypre.
      HypreBoomerAMG amg;
      amg.SetPrintLevel(0);
      CGSolver pcg(A.GetComm());
      pcg.SetPreconditioner(amg);
      pcg.SetOperator(A);
      pcg.SetRelTol(1e-6);
      pcg.SetMaxIter(200);
      pcg.SetPrintLevel(3); // print the first and the last iterations only
      pcg.Mult(B, X);

      // 14. Recover the parallel grid function corresponding to X. This is the
      //     local finite element solution on each processor.
      a->RecoverFEMSolution(X, *b, x);

      // 15. Save in parallel the displaced mesh and the inverted solution (which
      //     gives the backward displacements to the original grid). This output
      //     can be viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
      {
         ostringstream mesh_name, sol_name;
         mesh_name << "mesh." << setfill('0') << setw(6) << myid;
         sol_name << "sol." << setfill('0') << setw(6) << myid;

         ofstream mesh_ofs(mesh_name.str().c_str());
         mesh_ofs.precision(8);
         pmesh->Print(mesh_ofs);

         ofstream sol_ofs(sol_name.str().c_str());
         sol_ofs.precision(8);
         x.Save(sol_ofs);
      }

      // 16. Send the above data by socket to a GLVis server.  Use the "n" and "b"
      //     keys in GLVis to visualize the displacements.
      if (visualization)
      {
         sout << "parallel " << num_procs << " " << myid << "\n";
         sout << "solution\n" << *pmesh << x << flush;
      }

      // 17. Field transfer. Scalar solution field and magnitude field for error
      //     estimation are created the PUMI mesh.
      if (order > geom_order)
      {
         Tmag_field = apf::createField(pumi_mesh, "field_mag",
                                       apf::SCALAR, apf::getLagrange(order));
         temp_field = apf::createField(pumi_mesh, "T_field",
                                       apf::SCALAR, apf::getLagrange(order));
      }
      else
      {
         Tmag_field = apf::createFieldOn(pumi_mesh, "field_mag",apf::SCALAR);
         temp_field = apf::createFieldOn(pumi_mesh, "T_field", apf::SCALAR);
      }

      ParPumiMesh* pPPmesh = dynamic_cast<ParPumiMesh*>(pmesh);
      pPPmesh->FieldMFEMtoPUMI(pumi_mesh, &x, temp_field, Tmag_field);

      ipfield= spr::getGradIPField(Tmag_field, "MFEM_gradip", 2);
      sizefield = spr::getSPRSizeField(ipfield, adapt_ratio);

      apf::destroyField(Tmag_field);
      apf::destroyField(ipfield);

      // 18. Perform MesAdapt.
      const ma::Input* erinput = ma::configure(pumi_mesh, sizefield);
      if ( geom_order > 1)
      {
         crv::adapt(erinput);
      }
      else
      {
         ma::adapt(erinput);
      }

      ParMesh* Adapmesh = new ParPumiMesh(MPI_COMM_WORLD, pumi_mesh);
      pPPmesh->UpdateMesh(Adapmesh);
      delete Adapmesh;

      // 19. Update the FiniteElementSpace, GridFunction, and bilinear form.
      fespace->Update();
      x.Update();
      x = 0.0;

      pPPmesh->FieldPUMItoMFEM(pumi_mesh, temp_field, &x);
      a->Update();
      b->Update();

      // Destroy fields.
      apf::destroyField(temp_field);
      apf::destroyField(sizefield);
   }

   // 20. Free the used memory.
   delete a;
   delete b;
   delete fespace;
   if (order > 0) { delete fec; }
   delete pmesh;

   pumi_mesh->destroyNative();
   apf::destroyMesh(pumi_mesh);
   PCU_Comm_Free();

#ifdef MFEM_USE_SIMMETRIX
   gmi_sim_stop();
   Sim_unregisterAllKeys();
#endif

   MPI_Finalize();

   return 0;
}
<|endoftext|>


<commit_before>/***********************************************************************
	filename: 	CEGUIMouseCursor.cpp
	created:	21/2/2004
	author:		Paul D Turner

	purpose:	Implements MouseCursor class
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUIMouseCursor.h"
#include "CEGUIExceptions.h"
#include "CEGUILogger.h"
#include "CEGUISystem.h"
#include "CEGUIRenderer.h"
#include "CEGUIImagesetManager.h"
#include "CEGUIImageset.h"
#include "CEGUIImage.h"

// Start of CEGUI namespace section
namespace CEGUI
{
const String MouseCursor::EventNamespace("MouseCursor");

/*************************************************************************
	Static Data Definitions
*************************************************************************/
// singleton instance pointer
template<> MouseCursor* Singleton<MouseCursor>::ms_Singleton	= 0;

/*************************************************************************
	Event name constants
*************************************************************************/
const String MouseCursor::EventImageChanged( "ImageChanged" );

/*************************************************************************
	constructor
*************************************************************************/
MouseCursor::MouseCursor(void)
{
    Rect screenArea(System::getSingleton().getRenderer()->getRect());

	// mouse defaults to middle of the constrained area
	d_position.d_x = screenArea.getWidth() / 2;
	d_position.d_y = screenArea.getHeight() / 2;
	d_position.d_z = 1.0f;

	// default constraint is to whole screen
	setConstraintArea(&screenArea);

	// mouse defaults to visible
	d_visible = true;

	// no default image though
	d_cursorImage = 0;

	Logger::getSingleton().logEvent("CEGUI::MouseCursor singleton created.");
}

/*************************************************************************
	Destructor
*************************************************************************/
MouseCursor::~MouseCursor(void)
{
	Logger::getSingleton().logEvent("CEGUI::MouseCursor singleton destroyed.");
}

/*************************************************************************
	Set the current mouse cursor image
*************************************************************************/
void MouseCursor::setImage(const Image* image)
{
	d_cursorImage = image;
	MouseCursorEventArgs args(this);
	args.image = image;
	onImageChanged(args);
}

/*************************************************************************
	Set the current mouse cursor image
*************************************************************************/
void MouseCursor::setImage(const String& imageset, const String& image_name)
{
	setImage(&ImagesetManager::getSingleton().getImageset(imageset)->getImage(image_name));
}

/*************************************************************************
	Draw the mouse cursor
*************************************************************************/
void MouseCursor::draw(void) const
{
	if (d_visible && (d_cursorImage != 0))
	{
		d_cursorImage->draw( d_position, System::getSingleton().getRenderer()->getRect() );
	}
}

/*************************************************************************
	Set the current mouse cursor position
*************************************************************************/
void MouseCursor::setPosition(const Point& position)
{
	d_position.d_x = position.d_x;
	d_position.d_y = position.d_y;
	constrainPosition();
}

/*************************************************************************
	Offset the mouse cursor position by the deltas specified in 'offset'.
*************************************************************************/
void MouseCursor::offsetPosition(const Point& offset)
{
	d_position.d_x += offset.d_x;
	d_position.d_y += offset.d_y;
	constrainPosition();
}

/*************************************************************************
	Checks the mouse cursor position is within the current 'constrain'
	Rect and adjusts as required.
*************************************************************************/
void MouseCursor::constrainPosition(void)
{
    Rect absarea(getConstraintArea());

	if (d_position.d_x >= absarea.d_right)
		d_position.d_x = absarea.d_right -1;

	if (d_position.d_y >= absarea.d_bottom)
		d_position.d_y = absarea.d_bottom -1;

	if (d_position.d_y < absarea.d_top)
		d_position.d_y = absarea.d_top;

	if (d_position.d_x < absarea.d_left)
		d_position.d_x = absarea.d_left;
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
void MouseCursor::setConstraintArea(const Rect* area)
{
	Rect renderer_area = System::getSingleton().getRenderer()->getRect();

	if (!area)
	{
		d_constraints.d_min.d_x = cegui_reldim(renderer_area.d_left / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(renderer_area.d_top / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(renderer_area.d_right / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(renderer_area.d_bottom / renderer_area.getHeight());
	}
	else
	{
        Rect finalArea(area->getIntersection(renderer_area));
		d_constraints.d_min.d_x = cegui_reldim(finalArea.d_left / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(finalArea.d_top / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(finalArea.d_right / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(finalArea.d_bottom / renderer_area.getHeight());
	}

	constrainPosition();
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
void MouseCursor::setUnifiedConstraintArea(const URect* area)
{
	Rect renderer_area = System::getSingleton().getRenderer()->getRect();

	if (area)
	{
        d_constraints = *area;
	}
	else
	{
		d_constraints.d_min.d_x = cegui_reldim(renderer_area.d_left / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(renderer_area.d_top / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(renderer_area.d_right / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(renderer_area.d_bottom / renderer_area.getHeight());
	}

	constrainPosition();
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
Rect MouseCursor::getConstraintArea(void) const
{
    return Rect(d_constraints.asAbsolute(System::getSingleton().getRenderer()->getSize()));
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
const URect& MouseCursor::getUnifiedConstraintArea(void) const
{
    return d_constraints;
}

/*************************************************************************
	Return the current mouse cursor position in display resolution
	independant values.
*************************************************************************/
Point MouseCursor::getDisplayIndependantPosition(void) const
{
	Size dsz(System::getSingleton().getRenderer()->getSize());

	return Point(d_position.d_x / (dsz.d_width - 1.0f), d_position.d_y / (dsz.d_height - 1.0f));
}

//////////////////////////////////////////////////////////////////////////
/*************************************************************************

	Begin event triggers section

*************************************************************************/
//////////////////////////////////////////////////////////////////////////

void MouseCursor::onImageChanged(MouseCursorEventArgs& e)
{
	fireEvent(EventImageChanged, e, EventNamespace);
}

MouseCursor& MouseCursor::getSingleton(void)
{
	return Singleton<MouseCursor>::getSingleton();
}

MouseCursor* MouseCursor::getSingletonPtr(void)
{
	return Singleton<MouseCursor>::getSingletonPtr();
}

} // End of  CEGUI namespace section
<commit_msg>Mouse cursor fix bug #49<commit_after>/***********************************************************************
	filename: 	CEGUIMouseCursor.cpp
	created:	21/2/2004
	author:		Paul D Turner

	purpose:	Implements MouseCursor class
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUIMouseCursor.h"
#include "CEGUIExceptions.h"
#include "CEGUILogger.h"
#include "CEGUISystem.h"
#include "CEGUIRenderer.h"
#include "CEGUIImagesetManager.h"
#include "CEGUIImageset.h"
#include "CEGUIImage.h"

// Start of CEGUI namespace section
namespace CEGUI
{
const String MouseCursor::EventNamespace("MouseCursor");

/*************************************************************************
	Static Data Definitions
*************************************************************************/
// singleton instance pointer
template<> MouseCursor* Singleton<MouseCursor>::ms_Singleton	= 0;

/*************************************************************************
	Event name constants
*************************************************************************/
const String MouseCursor::EventImageChanged( "ImageChanged" );

/*************************************************************************
	constructor
*************************************************************************/
MouseCursor::MouseCursor(void)
{
    Rect screenArea(System::getSingleton().getRenderer()->getRect());

	// mouse defaults to middle of the constrained area
	d_position.d_x = screenArea.getWidth() / 2;
	d_position.d_y = screenArea.getHeight() / 2;
	d_position.d_z = 0.0f;

	// default constraint is to whole screen
	setConstraintArea(&screenArea);

	// mouse defaults to visible
	d_visible = true;

	// no default image though
	d_cursorImage = 0;

	Logger::getSingleton().logEvent("CEGUI::MouseCursor singleton created.");
}

/*************************************************************************
	Destructor
*************************************************************************/
MouseCursor::~MouseCursor(void)
{
	Logger::getSingleton().logEvent("CEGUI::MouseCursor singleton destroyed.");
}

/*************************************************************************
	Set the current mouse cursor image
*************************************************************************/
void MouseCursor::setImage(const Image* image)
{
	d_cursorImage = image;
	MouseCursorEventArgs args(this);
	args.image = image;
	onImageChanged(args);
}

/*************************************************************************
	Set the current mouse cursor image
*************************************************************************/
void MouseCursor::setImage(const String& imageset, const String& image_name)
{
	setImage(&ImagesetManager::getSingleton().getImageset(imageset)->getImage(image_name));
}

/*************************************************************************
	Draw the mouse cursor
*************************************************************************/
void MouseCursor::draw(void) const
{
	if (d_visible && (d_cursorImage != 0))
	{
		d_cursorImage->draw( d_position, System::getSingleton().getRenderer()->getRect() );
	}
}

/*************************************************************************
	Set the current mouse cursor position
*************************************************************************/
void MouseCursor::setPosition(const Point& position)
{
	d_position.d_x = position.d_x;
	d_position.d_y = position.d_y;
	constrainPosition();
}

/*************************************************************************
	Offset the mouse cursor position by the deltas specified in 'offset'.
*************************************************************************/
void MouseCursor::offsetPosition(const Point& offset)
{
	d_position.d_x += offset.d_x;
	d_position.d_y += offset.d_y;
	constrainPosition();
}

/*************************************************************************
	Checks the mouse cursor position is within the current 'constrain'
	Rect and adjusts as required.
*************************************************************************/
void MouseCursor::constrainPosition(void)
{
    Rect absarea(getConstraintArea());

	if (d_position.d_x >= absarea.d_right)
		d_position.d_x = absarea.d_right -1;

	if (d_position.d_y >= absarea.d_bottom)
		d_position.d_y = absarea.d_bottom -1;

	if (d_position.d_y < absarea.d_top)
		d_position.d_y = absarea.d_top;

	if (d_position.d_x < absarea.d_left)
		d_position.d_x = absarea.d_left;
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
void MouseCursor::setConstraintArea(const Rect* area)
{
	Rect renderer_area = System::getSingleton().getRenderer()->getRect();

	if (!area)
	{
		d_constraints.d_min.d_x = cegui_reldim(renderer_area.d_left / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(renderer_area.d_top / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(renderer_area.d_right / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(renderer_area.d_bottom / renderer_area.getHeight());
	}
	else
	{
        Rect finalArea(area->getIntersection(renderer_area));
		d_constraints.d_min.d_x = cegui_reldim(finalArea.d_left / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(finalArea.d_top / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(finalArea.d_right / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(finalArea.d_bottom / renderer_area.getHeight());
	}

	constrainPosition();
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
void MouseCursor::setUnifiedConstraintArea(const URect* area)
{
	Rect renderer_area = System::getSingleton().getRenderer()->getRect();

	if (area)
	{
        d_constraints = *area;
	}
	else
	{
		d_constraints.d_min.d_x = cegui_reldim(renderer_area.d_left / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(renderer_area.d_top / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(renderer_area.d_right / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(renderer_area.d_bottom / renderer_area.getHeight());
	}

	constrainPosition();
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
Rect MouseCursor::getConstraintArea(void) const
{
    return Rect(d_constraints.asAbsolute(System::getSingleton().getRenderer()->getSize()));
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
const URect& MouseCursor::getUnifiedConstraintArea(void) const
{
    return d_constraints;
}

/*************************************************************************
	Return the current mouse cursor position in display resolution
	independant values.
*************************************************************************/
Point MouseCursor::getDisplayIndependantPosition(void) const
{
	Size dsz(System::getSingleton().getRenderer()->getSize());

	return Point(d_position.d_x / (dsz.d_width - 1.0f), d_position.d_y / (dsz.d_height - 1.0f));
}

//////////////////////////////////////////////////////////////////////////
/*************************************************************************

	Begin event triggers section

*************************************************************************/
//////////////////////////////////////////////////////////////////////////

void MouseCursor::onImageChanged(MouseCursorEventArgs& e)
{
	fireEvent(EventImageChanged, e, EventNamespace);
}

MouseCursor& MouseCursor::getSingleton(void)
{
	return Singleton<MouseCursor>::getSingleton();
}

MouseCursor* MouseCursor::getSingletonPtr(void)
{
	return Singleton<MouseCursor>::getSingletonPtr();
}

} // End of  CEGUI namespace section
<|endoftext|>


<commit_before>
#include "NNApplication.h"

#include "SpriteSample.h"
#include "AnimationSample.h"
#include "XMLSample.h"
#include "SpriteAtlasSample.h"
#include "CameraSample.h"
#include "FMODSoundSample.h"
#include "NetworkSample.h"

#ifdef _DEBUG
#pragma comment(lib, "NNGameFramework_DEBUG.lib")
#else
#pragma comment(lib, "NNGameFramework.lib")
#endif

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nShowCmd )
{
#ifdef _DEBUG
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
	//_CrtSetBreakAlloc( );

	AllocConsole();
	FILE* console;
	freopen_s( &console, "CONOUT$", "wt", stdout );

	printf_s("Console Open \n");
#endif

	NNApplication* Application = NNApplication::GetInstance();

	Application->Init( L"D2D Test", 800, 600, D2D );

	// NNSceneDirector::GetInstance()->ChangeScene( NetworkSample::Create() );
	// NNSceneDirector::GetInstance()->ChangeScene( SpriteSample::Create() );
	 NNSceneDirector::GetInstance()->ChangeScene( AnimationSample::Create() );
	// NNSceneDirector::GetInstance()->ChangeScene( XMLSample::Create() );
	// NNSceneDirector::GetInstance()->ChangeScene( SpriteAtlasSample::Create() );
	// NNSceneDirector::GetInstance()->ChangeScene( CameraSample::Create() );
	// NNSceneDirector::GetInstance()->ChangeScene( FMODSoundSample::Create() );

	Application->Run();
	Application->Release();

#ifdef _DEBUG
	FreeConsole();
#endif

	return 0;
}<commit_msg>$ test commit<commit_after>
#include "NNApplication.h"

#include "SpriteSample.h"
#include "AnimationSample.h"
#include "XMLSample.h"
#include "SpriteAtlasSample.h"
#include "CameraSample.h"
#include "FMODSoundSample.h"
#include "NetworkSample.h"

#ifdef _DEBUG
#pragma comment(lib, "NNGameFramework_DEBUG.lib")
#else
#pragma comment(lib, "NNGameFramework.lib")
#endif

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nShowCmd )
{
#ifdef _DEBUG
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
	//_CrtSetBreakAlloc( );

	AllocConsole();
	FILE* console;
	freopen_s( &console, "CONOUT$", "wt", stdout );

	printf_s("Console Open \n");
#endif

	NNApplication* Application = NNApplication::GetInstance();

	Application->Init( L"D2D Test", 800, 600, D2D );

	// NNSceneDirector::GetInstance()->ChangeScene( NetworkSample::Create() );
	// NNSceneDirector::GetInstance()->ChangeScene( SpriteSample::Create() );
	 NNSceneDirector::GetInstance()->ChangeScene( AnimationSample::Create() );
	// NNSceneDirector::GetInstance()->ChangeScene( XMLSample::Create() );
	// NNSceneDirector::GetInstance()->ChangeScene( SpriteAtlasSample::Create() );
	// NNSceneDirector::GetInstance()->ChangeScene( CameraSample::Create() );
	// NNSceneDirector::GetInstance()->ChangeScene( FMODSoundSample::Create() );

	Application->Run();
	Application->Release();

#ifdef _DEBUG
	FreeConsole();
#endif

	return 0;
}<|endoftext|>


<commit_before>/*
Copyright 2014 John Bailey

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include "MetricDumper.hpp"
#include "MetricOptions.hpp"

#include <iomanip>

#define IS_OUTPUT_TREE_FORM( _fmt ) (((_fmt) == METRIC_DUMP_FORMAT_TREE ) || ((_fmt) == METRIC_DUMP_FORMAT_SPARSE_TREE ))

const std::string MetricDumper::m_namePrefix[METRIC_UNIT_MAX] = {
	"",
	"File: ",
	"\tFunction: ",
	"\tMethod: "
};
const std::string MetricDumper::m_dumpPrefix[METRIC_UNIT_MAX] = {
	"",
	"\t",
	"\t\t",
	"\t\t"
};

void MetricDumper::dumpMetric(std::ostream& out, const MetricUnit* const p_unit, const MetricType_e p_metric, const MetricDumpFormat_e p_fmt, const std::string& p_sep, const bool p_recurse, const std::string& p_suffix,bool p_useShortNames)
{
	MetricUnit::counter_t val = p_unit->getCounter(p_metric, p_recurse);
	const MetricUnitType_e metricType = p_unit->GetType();

	if ((p_fmt != METRIC_DUMP_FORMAT_SPARSE_TREE) ||
		(val != 0))
	{
		if (IS_OUTPUT_TREE_FORM(p_fmt)) {
			std::string metricName;

			if (p_useShortNames)
			{
				metricName = MetricUnit::getMetricShortName(p_metric);
			}
			else
			{
				metricName = MetricUnit::getMetricName(p_metric);
			}

			out << m_dumpPrefix[metricType] << metricName << p_suffix << ": ";
		}

		uint32_t scaling = MetricUnit::getMetricScaling(p_metric);

		if (scaling == 1)
		{
			out << val << p_sep;
		}
		else
		{
			out << std::setprecision(6) << ((float)(val)) / scaling << p_sep;
		}
	}
}

void MetricDumper::dump(std::ostream& out, const MetricUnit* const p_topLevel, const MetricOptions& p_options)
{
	std::string sep;
	const MetricUnitType_e metricUnitType = p_topLevel->GetType();
	const bool useShortNames = p_options.getUseShortNames();
	const MetricDumpFormat_e p_fmt = p_options.getOutputFormat();

	if (p_options.getOutputMetric(metricUnitType))
	{
		switch (p_fmt) {
		case METRIC_DUMP_FORMAT_TREE:
		case METRIC_DUMP_FORMAT_SPARSE_TREE:
			// TODO: Should be endl
			sep = "\r\n";
			break;
		case METRIC_DUMP_FORMAT_TSV:
			sep = "\t";
			break;
		case METRIC_DUMP_FORMAT_CSV:
			sep = ",";
			break;
		}

		if ((p_fmt == METRIC_DUMP_FORMAT_TSV) ||
			(p_fmt == METRIC_DUMP_FORMAT_CSV)) {

			if (metricUnitType == METRIC_UNIT_GLOBAL)
			{
				out << "Name" << sep;
				int loop;
				for (loop = 0;
					loop < METRIC_TYPE_MAX;
					loop++)
				{
					const MetricType_e metric = static_cast<MetricType_e>(loop);
					const bool localAndCumulativeOutputs = MetricUnit::isMetricCumulative(metric) && MetricUnit::isMetricLocalAndCumulative(metric);

					/* TODO: Output a warning in the case that anything in p_options.OutputMetrics isn't understood */
					if (p_options.ShouldIncludeMetric( MetricUnit::getMetricShortName(metric)))
					{
						std::string metricName;

						if (useShortNames)
						{
							metricName = MetricUnit::getMetricShortName(metric);
						}
						else
						{
							metricName = MetricUnit::getMetricName(metric);
						}

						out << metricName;

						if (localAndCumulativeOutputs)
						{
							out << "(local)" << sep << metricName << "(cumulative)";
						}
						out << sep;
					}
				}
				out << std::endl;
			}
		}

		if (IS_OUTPUT_TREE_FORM(p_fmt)) {
			out << m_namePrefix[metricUnitType];
		}

		out << p_topLevel->getUnitName(p_options) << sep;

		unsigned loop;
		for (loop = 0;
			loop < METRIC_TYPE_MAX;
			loop++)
		{
			const MetricType_e metric = static_cast<MetricType_e>(loop);
			const bool metricIsCumulative = MetricUnit::isMetricCumulative(metric);
			/* TODO: duped above */
			const bool localAndCumulativeOutputs = metricIsCumulative && MetricUnit::isMetricLocalAndCumulative(metric);

			/* Filter out metrics which only apply at file/method level */
			if (p_options.ShouldIncludeMetric( MetricUnit::getMetricShortName(metric)) && MetricUnit::doesMetricApplyForUnit(metric, metricUnitType))
			{
				std::string sfx = "";
				bool output_sep = false;
				if (localAndCumulativeOutputs)
				{
					if (metricUnitType == METRIC_UNIT_FILE)
					{
						dumpMetric(out, p_topLevel, (MetricType_e)loop, p_fmt, sep, false, "(local)",useShortNames);
						sfx = "(cumulative)";
					}
					else if (!IS_OUTPUT_TREE_FORM(p_fmt))
					{
						output_sep = true;
					}
				}
				dumpMetric(out, p_topLevel, (MetricType_e)loop, p_fmt, sep, metricIsCumulative, sfx,useShortNames);
				if (output_sep)
				{
					out << sep;
				}
			}
		}

		if ((p_fmt == METRIC_DUMP_FORMAT_TSV) ||
			(p_fmt == METRIC_DUMP_FORMAT_CSV)) {
			out << std::endl;
		}
	}

	const MetricUnit::SubUnitMap_t* const subUnits = p_topLevel->getSubUnits();

	for (MetricUnit::SubUnitMap_t::const_iterator unitIt = subUnits->begin();
		 unitIt != subUnits->end();
		 ++unitIt)
	{
		dump(out, (*unitIt).second, p_options);
	}
}

<commit_msg>Updates #78 by fixing up CSV and TSV output<commit_after>/*
Copyright 2014 John Bailey

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include "MetricDumper.hpp"
#include "MetricOptions.hpp"

#include <iomanip>

#define IS_OUTPUT_TREE_FORM( _fmt ) (((_fmt) == METRIC_DUMP_FORMAT_TREE ) || ((_fmt) == METRIC_DUMP_FORMAT_SPARSE_TREE ))

const std::string MetricDumper::m_namePrefix[METRIC_UNIT_MAX] = {
	"",
	"File: ",
	"\tFunction: ",
	"\tMethod: "
};
const std::string MetricDumper::m_dumpPrefix[METRIC_UNIT_MAX] = {
	"",
	"\t",
	"\t\t",
	"\t\t"
};

void MetricDumper::dumpMetric(std::ostream& out, const MetricUnit* const p_unit, const MetricType_e p_metric, const MetricDumpFormat_e p_fmt, const std::string& p_sep, const bool p_recurse, const std::string& p_suffix,bool p_useShortNames)
{
	MetricUnit::counter_t val = p_unit->getCounter(p_metric, p_recurse);
	const MetricUnitType_e metricType = p_unit->GetType();

	if ((p_fmt != METRIC_DUMP_FORMAT_SPARSE_TREE) ||
		(val != 0))
	{
		if (IS_OUTPUT_TREE_FORM(p_fmt)) {
			std::string metricName;

			if (p_useShortNames)
			{
				metricName = MetricUnit::getMetricShortName(p_metric);
			}
			else
			{
				metricName = MetricUnit::getMetricName(p_metric);
			}

			out << m_dumpPrefix[metricType] << metricName << p_suffix << ": ";
		}

		uint32_t scaling = MetricUnit::getMetricScaling(p_metric);

		if (scaling == 1)
		{
			out << val << p_sep;
		}
		else
		{
			out << std::setprecision(6) << ((float)(val)) / scaling << p_sep;
		}
	}
}

void MetricDumper::dump(std::ostream& out, const MetricUnit* const p_topLevel, const MetricOptions& p_options)
{
	std::string sep;
	const MetricUnitType_e metricUnitType = p_topLevel->GetType();
	const bool useShortNames = p_options.getUseShortNames();
	const MetricDumpFormat_e p_fmt = p_options.getOutputFormat();

	if (p_options.getOutputMetric(metricUnitType))
	{
		switch (p_fmt) {
		case METRIC_DUMP_FORMAT_TREE:
		case METRIC_DUMP_FORMAT_SPARSE_TREE:
			// TODO: Should be endl
			sep = "\r\n";
			break;
		case METRIC_DUMP_FORMAT_TSV:
			sep = "\t";
			break;
		case METRIC_DUMP_FORMAT_CSV:
			sep = ",";
			break;
		}

		if ((p_fmt == METRIC_DUMP_FORMAT_TSV) ||
			(p_fmt == METRIC_DUMP_FORMAT_CSV)) {

			if (metricUnitType == METRIC_UNIT_GLOBAL)
			{
				out << "Name" << sep;
				int loop;
				for (loop = 0;
					loop < METRIC_TYPE_MAX;
					loop++)
				{
					const MetricType_e metric = static_cast<MetricType_e>(loop);
					const bool localAndCumulativeOutputs = MetricUnit::isMetricCumulative(metric) && MetricUnit::isMetricLocalAndCumulative(metric);
					std::string quote_wrapper = "";

					if (p_fmt == METRIC_DUMP_FORMAT_CSV)
					{
						quote_wrapper = "\"";
					}

					/* TODO: Output a warning in the case that anything in p_options.OutputMetrics isn't understood */
					if (p_options.ShouldIncludeMetric( MetricUnit::getMetricShortName(metric)))
					{
						std::string metricName;

						if (useShortNames)
						{
							metricName = MetricUnit::getMetricShortName(metric);
						}
						else
						{
							metricName = MetricUnit::getMetricName(metric);
						}

						out << quote_wrapper << metricName;

						if (localAndCumulativeOutputs)
						{
							out << "(local)" << quote_wrapper << sep << quote_wrapper << metricName << "(cumulative)";
						}
						out << quote_wrapper << sep;
					}
				}
				out << std::endl;
			}
		}

		if (IS_OUTPUT_TREE_FORM(p_fmt)) {
			out << m_namePrefix[metricUnitType];
		}

		out << p_topLevel->getUnitName(p_options) << sep;

		unsigned loop;
		for (loop = 0;
			loop < METRIC_TYPE_MAX;
			loop++)
		{
			const MetricType_e metric = static_cast<MetricType_e>(loop);
			const bool metricIsCumulative = MetricUnit::isMetricCumulative(metric);
			/* TODO: duped above */
			const bool localAndCumulativeOutputs = metricIsCumulative && MetricUnit::isMetricLocalAndCumulative(metric);

			if (p_options.ShouldIncludeMetric( MetricUnit::getMetricShortName(metric)))
			{
				/* Filter out metrics which only apply at file/method level */
				if (MetricUnit::doesMetricApplyForUnit(metric, metricUnitType))
				{
					std::string sfx = "";
					if (localAndCumulativeOutputs)
					{
						if (metricUnitType == METRIC_UNIT_FILE)
						{
							dumpMetric(out, p_topLevel, (MetricType_e)loop, p_fmt, sep, false, "(local)", useShortNames);
							sfx = "(cumulative)";
						}
						else if ((p_fmt == METRIC_DUMP_FORMAT_TSV) ||
							     (p_fmt == METRIC_DUMP_FORMAT_CSV))
						{
							out << sep;
						}

					}
					dumpMetric(out, p_topLevel, (MetricType_e)loop, p_fmt, sep, metricIsCumulative, sfx, useShortNames);
				}
				else if ((p_fmt == METRIC_DUMP_FORMAT_TSV) ||
					     (p_fmt == METRIC_DUMP_FORMAT_CSV))
				{
					out << sep;
					if (localAndCumulativeOutputs)
					{
						out << sep;
					}
				}
			}
		}

		if ((p_fmt == METRIC_DUMP_FORMAT_TSV) ||
			(p_fmt == METRIC_DUMP_FORMAT_CSV)) {
			out << std::endl;
		}
	}

	const MetricUnit::SubUnitMap_t* const subUnits = p_topLevel->getSubUnits();

	for (MetricUnit::SubUnitMap_t::const_iterator unitIt = subUnits->begin();
		 unitIt != subUnits->end();
		 ++unitIt)
	{
		dump(out, (*unitIt).second, p_options);
	}
}

<|endoftext|>


<commit_before>// NodeCoreAudio.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"

#include <v8.h>
using namespace v8;
#pragma comment(lib, "node")
#include <node.h>

#include <WinSock2.h>
#include <IPHlpApi.h>
#include <stdio.h>
#include <Windows.h>
#pragma comment(lib, "IPHLPAPI.lib")
#include <string>
#include "AudioEngine.h"

#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))

struct Baton {
	uv_work_t request;
	Persistent<Function> callback;
	int error_code;
	std::string error_message;

	// Custom data
	int32_t result;
};

void CallCallback(uv_work_t* req) {
	HandleScope scope;
	Baton* baton = static_cast<Baton*>(req->data);

	baton->callback.Dispose();
	delete baton;
} // end CallCallback

namespace NodeCoreAudio {
	Handle<Value> InitializeAudioEngine(const Arguments &args) {
		HandleScope scope;

		if (!args[0]->IsFunction()) {
			return ThrowException( Exception::TypeError(String::New("Callback function required")) );
		}

		Local<Function> callback = Local<Function>::Cast(args[0]);

		Baton* baton = new Baton();
		baton->request.data = baton;
		baton->callback = Persistent<Function>::New(callback);

		//uv_queue_work(uv_default_loop(), &baton->request, AsyncWork, AsyncAfter);

		Audio::AudioEngine* pAudioEngine= new Audio::AudioEngine( baton->callback );

		return scope.Close(Undefined());

	} // end InitializeAudioEngine()
}

void AsyncWork(uv_work_t* req) {
	// No HandleScope!

	Baton* baton = static_cast<Baton*>(req->data);

	// Do work in threadpool here.
	// Set baton->error_code/message on failures.
}

extern "C" void NODE_EXTERN init (Handle<Object> target)
{
	HandleScope scope;
	Local<FunctionTemplate> initializeAudioEngine = FunctionTemplate::New( NodeCoreAudio::InitializeAudioEngine );

	target->Set( String::NewSymbol("initializeAudioEngine"), initializeAudioEngine->GetFunction() );
}

NODE_MODULE(NodeCoreAudio, init)
<commit_msg>start to setup NodeCoreAudio as an AudioEngine factory<commit_after>// NodeCoreAudio.cpp : Defines the exported functions for the DLL application.
//
#define BUILDING_NODE_EXTENSION
#include "stdafx.h"

#include <v8.h>
using namespace v8;
#pragma comment(lib, "node")
#include <node.h>

#include <string>
#include "AudioEngine.h"

#include <WinSock2.h>
#include <IPHlpApi.h>
#include <stdio.h>
#include <Windows.h>
#pragma comment(lib, "IPHLPAPI.lib")

#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))

struct Baton {
	uv_work_t request;
	Persistent<Function> callback;
	int error_code;
	std::string error_message;

	// Custom data
	int32_t result;
};

void CallCallback(uv_work_t* req) {
	HandleScope scope;
	Baton* baton = static_cast<Baton*>(req->data);

	baton->callback.Dispose();
	delete baton;
} // end CallCallback

namespace CoreAudio {
	Handle<Value> InitializeAudioEngine(const Arguments &args) {

		HandleScope scope;
		return scope.Close(Audio::AudioEngine::NewInstance(args));

// 		HandleScope scope;
//
// 		if (!args[0]->IsFunction()) {
// 			return ThrowException( Exception::TypeError(String::New("Callback function required")) );
// 		}
//
// 		Local<Function> callback = Local<Function>::Cast(args[0]);
//
// 		Baton* baton = new Baton();
// 		baton->request.data = baton;
// 		baton->callback = Persistent<Function>::New(callback);
//
// 		//uv_queue_work(uv_default_loop(), &baton->request, AsyncWork, AsyncAfter);
//
// 		Audio::AudioEngine* pAudioEngine= new Audio::AudioEngine( baton->callback );
//
// 		return scope.Close(Undefined());

	} // end InitializeAudioEngine()
}

// void AsyncWork(uv_work_t* req) {
// 	// No HandleScope!
//
// 	Baton* baton = static_cast<Baton*>(req->data);
//
// 	// Do work in threadpool here.
// 	// Set baton->error_code/message on failures.
// }

// extern "C" void NODE_EXTERN init (Handle<Object> target)
// {
// 	HandleScope scope;
// 	Local<FunctionTemplate> initializeAudioEngine = FunctionTemplate::New( NodeCoreAudio::InitializeAudioEngine );
//
// 	target->Set( String::NewSymbol("initializeAudioEngine"), initializeAudioEngine->GetFunction() );
// }

Handle<Value> CreateEngine(const Arguments& args) {
	HandleScope scope;
	return scope.Close(Audio::AudioEngine::NewInstance(args));
}

void InitAll(Handle<Object> target) {
	Audio::AudioEngine::Init( target );

	target->Set(String::NewSymbol("createAudioEngine"),
		FunctionTemplate::New(CreateEngine)->GetFunction());
}

NODE_MODULE( NodeCoreAudio, InitAll )
<|endoftext|>


<commit_before>#include <iostream>
#include <nta/Version.hpp>

int main(int argc, char *argv[])
{
  if (strcmp(argv[1], NUPIC_CORE_VERSION) != 0) {
    std::cout << "Unexpected version of nupic.core! Expected \""
              << argv[1]
              << "\", but detected \""
              << NUPIC_CORE_VERSION << "\""
              << std::endl;
    return 1;
  }

  return 0;
}
<commit_msg>Including missing string.h header<commit_after>#include <string.h>
#include <iostream>
#include <nta/Version.hpp>

int main(int argc, char *argv[])
{
  if (strcmp(argv[1], NUPIC_CORE_VERSION) != 0) {
    std::cout << "Unexpected version of nupic.core! Expected \""
              << argv[1]
              << "\", but detected \""
              << NUPIC_CORE_VERSION << "\""
              << std::endl;
    return 1;
  }

  return 0;
}
<|endoftext|>