<commit_before>/*******************************************************************************
 * Copyright (c) 2013, Art Clarke.  All rights reserved.
 *
 * This file is part of Humble-Video.
 *
 * Humble-Video is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Humble-Video is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Humble-Video.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
/*
 * Decoder.cpp
 *
 *  Created on: Jul 23, 2013
 *      Author: aclarke
 */

#include "Decoder.h"
#include <io/humble/ferry/HumbleException.h>
#include <io/humble/ferry/RefPointer.h>
#include <io/humble/ferry/Logger.h>
#include <io/humble/video/Error.h>
#include <io/humble/video/IndexEntryImpl.h>
#include <io/humble/video/MediaAudioImpl.h>
#include <io/humble/video/MediaPictureImpl.h>
#include <io/humble/video/MediaPacketImpl.h>
#include <io/humble/video/MediaSubtitleImpl.h>

VS_LOG_SETUP(VS_CPP_PACKAGE);

using namespace io::humble::ferry;

namespace io {
namespace humble {
namespace video {

Decoder::Decoder(Codec* codec, const AVCodecContext* src) : Coder(codec, src) {
  if (!codec)
    throw HumbleInvalidArgument("no codec passed in");

  if (!codec->canDecode())
    throw HumbleInvalidArgument("passed in codec cannot decode");
  VS_LOG_TRACE("Created decoder");
}

Decoder::~Decoder() {

}

void
Decoder::flush() {
  if (getState() != STATE_OPENED)
    throw HumbleRuntimeError("Attempt to flush Decoder when not opened");
  avcodec_flush_buffers(mCtx);
}

int32_t
Decoder::getFrameSize() {
  int32_t retval = mCtx->frame_size;
  RefPointer<Codec> codec = getCodec();
  if (codec->getType() == MediaDescriptor::MEDIA_AUDIO)
  {
    if (retval <= 1)
    {
      // Rats; some PCM encoders give a frame size of 1, which is too
      //small.  We pick a more sensible value.
      retval = 576;
    }
  }
  return retval;
}

void
Decoder::ensurePictureParamsMatch(MediaPicture* pict)
{
  if (!pict)
    VS_THROW(HumbleInvalidArgument("null picture passed to decoder"));

  if (getWidth() != pict->getWidth())
    VS_THROW(HumbleInvalidArgument("width on picture does not match what decoder expects"));

  if (getHeight() != pict->getHeight())
    VS_THROW(HumbleInvalidArgument("height on picture does not match what decoder expects"));

  if (getPixelFormat() != pict->getFormat())
    VS_THROW(HumbleInvalidArgument("Pixel format on picture does not match what decoder expects"));

}

void
Decoder::ensureAudioParamsMatch(MediaAudio* audio)
{
  if (!audio)
    VS_THROW(HumbleInvalidArgument("null audio passed to decoder"));

  if (getChannels() != audio->getChannels())
    VS_THROW(HumbleInvalidArgument("audio channels does not match what decoder expects"));

  if (getSampleRate() != audio->getSampleRate())
    VS_THROW(HumbleInvalidArgument("audio sample rate does not match what decoder expects"));

  if (getSampleFormat() != audio->getFormat())
    VS_THROW(HumbleInvalidArgument("audio sample format does not match what decoder expects"));

}

int
Decoder::prepareFrame(AVFrame* frame, int flags) {
  if (!mCachedMedia)
    return Coder::prepareFrame(frame, flags);

  switch (getCodecType()) {
  case MediaDescriptor::MEDIA_AUDIO: {
    MediaAudioImpl* audio = dynamic_cast<MediaAudioImpl*>(mCachedMedia.value());
    if (!audio ||
        audio->getSampleRate() != frame->sample_rate ||
        audio->getChannelLayout() != frame->channel_layout ||
        audio->getFormat() != frame->format)
      return Coder::prepareFrame(frame, flags);
    av_frame_unref(frame);
    // reuse our audio frame.
    av_frame_ref(frame, audio->getCtx());
  }
  break;
  case MediaDescriptor::MEDIA_VIDEO: {
    MediaPictureImpl* pict = dynamic_cast<MediaPictureImpl*>(mCachedMedia.value());
    if (!pict ||
        pict->getWidth() != frame->width ||
        pict->getHeight() != frame->height ||
        pict->getFormat() != frame->format)
      return Coder::prepareFrame(frame, flags);
    av_frame_unref(frame);
    // reuse our audio frame.
    av_frame_ref(frame, pict->getCtx());
  }
  break;
  default:
    VS_LOG_ERROR("Got unknown codec type to allocate for");
    break;
  }
  return 0;
}

int32_t
Decoder::decodeAudio(MediaAudio* aOutput, MediaPacket* aPacket,
    int32_t byteOffset) {
  MediaAudioImpl* output = dynamic_cast<MediaAudioImpl*>(aOutput);
  MediaPacketImpl* packet = dynamic_cast<MediaPacketImpl*>(aPacket);

  if (byteOffset < 0) {
    VS_THROW(HumbleInvalidArgument("byteOffset must be >= 0"));
  }
  if (STATE_OPENED != getState())
    VS_THROW(HumbleRuntimeError("Attempt to decodeAudio, but Decoder is not opened"));

  // let's check the audio parameters.
  ensureAudioParamsMatch(aOutput);

  if (packet) {
    if (!packet->isComplete()) {
      VS_THROW(HumbleRuntimeError("Passed in a non-null but not complete packet; this is an error"));
    }
    if (byteOffset >= packet->getSize()) {
      VS_THROW(HumbleRuntimeError("Byteoffset is greater than total length of data in packet"));
    }
  } else {
    if (byteOffset > 0) {
      VS_LOG_WARN("Passing null packet with a non zero byte offset makes no sense");
    }
  }

  // arguments now confirmed; let's do a decode
  int32_t retval = -1;
  int got_frame = 0;

  // let's get the ffmpeg structures
  AVPacket* inPkt = packet ? packet->getCtx() : 0;

  // now we're going to copy the inPkt to do the byte-offset stuff. This
  // will copy by reference.
  AVPacket tmp;
  AVPacket* pkt = &tmp;
  av_init_packet(pkt);
  if (inPkt) {
    // copy in the actual packet
    av_copy_packet(pkt, inPkt);
    // now, adjust the data and size pointers
    pkt->data = pkt->data + byteOffset;
    pkt->size = pkt->size - byteOffset;
  } else {
    pkt->data = 0;
    pkt->size = 0;
  }
  // 'empty' out the input samples
  output->setComplete(false);

  AVFrame *frame = av_frame_alloc();
  if (!frame)
    VS_THROW(HumbleBadAlloc());
  /** DO NOT THROW EXCEPTIONS **/
  // create a frame to decode into, so that FFmpeg doesn't get knickers
  // in a twist re: allocation; but we will attempt to re-use our output
  // frame by setting a call back that Coder::getBuffer2 will use.

  mCachedMedia.reset(output, true);
  // try out decode
  retval = avcodec_decode_audio4(mCtx, frame, &got_frame, pkt);
  // always free the packet so that we don't have an exception make us leak it.
  av_free_packet(pkt);
  if (got_frame) {
    // copy the output frame to our frame
    output->copy(frame, true);
  }
  // release the temporary reference
  mCachedMedia = 0;
  av_frame_unref(frame);
  av_freep(&frame);
  /** END DO NOT THROW EXCEPTIONS **/
  if (retval < 0) {
    // let's make an error
    RefPointer<Error> error = Error::make(retval);
    VS_THROW(HumbleRuntimeError::make("Error while decoding: %s", error ? error->getDescription() : ""));
  }
  return retval;
}

int32_t
Decoder::decodeVideo(MediaPicture* aOutput, MediaPacket* aPacket,
    int32_t byteOffset) {
  MediaPictureImpl* output = dynamic_cast<MediaPictureImpl*>(aOutput);
  MediaPacketImpl* packet = dynamic_cast<MediaPacketImpl*>(aPacket);

  if (byteOffset < 0) {
    VS_THROW(HumbleInvalidArgument("byteOffset must be >= 0"));
  }
  if (STATE_OPENED != getState())
    VS_THROW(HumbleRuntimeError("Attempt to decodeAudio, but Decoder is not opened"));

  // let's check the picture parameters.
  ensurePictureParamsMatch(output);

  if (packet) {
    if (!packet->isComplete()) {
      VS_THROW(HumbleRuntimeError("Passed in a non-null but not complete packet; this is an error"));
    }
    if (byteOffset >= packet->getSize()) {
      VS_THROW(HumbleRuntimeError("Byteoffset is greater than total length of data in packet"));
    }
  } else {
    if (byteOffset > 0) {
      VS_LOG_WARN("Passing null packet with a non zero byte offset makes no sense");
    }
  }

  // arguments now confirmed; let's do a decode
  int32_t retval = -1;
  int got_frame = 0;

  // let's get the ffmpeg structures
  AVPacket* inPkt = packet ? packet->getCtx() : 0;

  // now we're going to copy the inPkt to do the byte-offset stuff. This
  // will copy by reference.
  AVPacket tmp;
  AVPacket* pkt = &tmp;
  av_init_packet(pkt);
  if (inPkt) {
    // copy in the actual packet
    av_copy_packet(pkt, inPkt);
    // now, adjust the data and size pointers
    pkt->data = pkt->data + byteOffset;
    pkt->size = pkt->size - byteOffset;
  } else {
    pkt->data = 0;
    pkt->size = 0;
  }
  // 'empty' out the input samples
  output->setComplete(false);

  AVFrame *frame = av_frame_alloc();
  if (!frame)
    VS_THROW(HumbleBadAlloc());
  /** DO NOT THROW EXCEPTIONS **/
  // create a frame to decode into, so that FFmpeg doesn't get knickers
  // in a twist re: allocation; but we will attempt to re-use our output
  // frame by setting a call back that Coder::getBuffer2 will use.

  mCachedMedia.reset(output, true);
  // try out decode
  retval = avcodec_decode_video2(mCtx, frame, &got_frame, pkt);
  // always free the packet so that we don't have an exception make us leak it.
  av_free_packet(pkt);
  if (got_frame) {
    // copy the output frame to our frame
    output->copy(frame, true);
  }
  // release the temporary reference
  mCachedMedia = 0;
  av_frame_unref(frame);
  av_freep(&frame);
  /** END DO NOT THROW EXCEPTIONS **/
  if (retval < 0) {
    // let's make an error
    RefPointer<Error> error = Error::make(retval);
    VS_THROW(HumbleRuntimeError::make("Error while decoding: %s", error ? error->getDescription() : ""));
  }
  return retval;
}

int32_t
Decoder::decodeSubtitle(MediaSubtitle* output, MediaPacket* packet,
    int32_t byteOffset) {
  (void) output;
  (void) packet;
  (void) byteOffset;
  return -1;
}

Decoder*
Decoder::make(Codec* codec)
{
  if (!codec)
    throw HumbleInvalidArgument("no codec passed in");

  if (!codec->canDecode())
    throw HumbleInvalidArgument("passed in codec cannot decode");

  RefPointer<Decoder> retval;
  // new Decoder DOES NOT increment refcount but the reset should catch it.
  retval.reset(new Decoder(codec, 0), true);
  return retval.get();
}

Decoder*
Decoder::make(Decoder* src)
{
  if (!src)
    throw HumbleInvalidArgument("no Decoder to copy");

  RefPointer<Codec> codec = src->getCodec();
  return make(codec.value(), src->mCtx);
}

Decoder*
Decoder::make(Codec* codec, const AVCodecContext* src) {
  if (!src)
    throw HumbleInvalidArgument("no Decoder to copy");
  if (!src->codec_id)
    throw HumbleRuntimeError("No codec set on coder???");

  RefPointer<Decoder> retval;
  // new Decoder DOES NOT increment refcount but the reset should catch it.
  retval.reset(new Decoder(codec, src), true);
  return retval.get();
}

} /* namespace video */
} /* namespace humble */
} /* namespace io */
<commit_msg>throw exception on subtitle decode because it's not implemented<commit_after>/*******************************************************************************
 * Copyright (c) 2013, Art Clarke.  All rights reserved.
 *
 * This file is part of Humble-Video.
 *
 * Humble-Video is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Humble-Video is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Humble-Video.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
/*
 * Decoder.cpp
 *
 *  Created on: Jul 23, 2013
 *      Author: aclarke
 */

#include "Decoder.h"
#include <io/humble/ferry/HumbleException.h>
#include <io/humble/ferry/RefPointer.h>
#include <io/humble/ferry/Logger.h>
#include <io/humble/video/Error.h>
#include <io/humble/video/IndexEntryImpl.h>
#include <io/humble/video/MediaAudioImpl.h>
#include <io/humble/video/MediaPictureImpl.h>
#include <io/humble/video/MediaPacketImpl.h>
#include <io/humble/video/MediaSubtitleImpl.h>

VS_LOG_SETUP(VS_CPP_PACKAGE);

using namespace io::humble::ferry;

namespace io {
namespace humble {
namespace video {

Decoder::Decoder(Codec* codec, const AVCodecContext* src) : Coder(codec, src) {
  if (!codec)
    throw HumbleInvalidArgument("no codec passed in");

  if (!codec->canDecode())
    throw HumbleInvalidArgument("passed in codec cannot decode");
  VS_LOG_TRACE("Created decoder");
}

Decoder::~Decoder() {

}

void
Decoder::flush() {
  if (getState() != STATE_OPENED)
    throw HumbleRuntimeError("Attempt to flush Decoder when not opened");
  avcodec_flush_buffers(mCtx);
}

int32_t
Decoder::getFrameSize() {
  int32_t retval = mCtx->frame_size;
  RefPointer<Codec> codec = getCodec();
  if (codec->getType() == MediaDescriptor::MEDIA_AUDIO)
  {
    if (retval <= 1)
    {
      // Rats; some PCM encoders give a frame size of 1, which is too
      //small.  We pick a more sensible value.
      retval = 576;
    }
  }
  return retval;
}

void
Decoder::ensurePictureParamsMatch(MediaPicture* pict)
{
  if (!pict)
    VS_THROW(HumbleInvalidArgument("null picture passed to decoder"));

  if (getWidth() != pict->getWidth())
    VS_THROW(HumbleInvalidArgument("width on picture does not match what decoder expects"));

  if (getHeight() != pict->getHeight())
    VS_THROW(HumbleInvalidArgument("height on picture does not match what decoder expects"));

  if (getPixelFormat() != pict->getFormat())
    VS_THROW(HumbleInvalidArgument("Pixel format on picture does not match what decoder expects"));

}

void
Decoder::ensureAudioParamsMatch(MediaAudio* audio)
{
  if (!audio)
    VS_THROW(HumbleInvalidArgument("null audio passed to decoder"));

  if (getChannels() != audio->getChannels())
    VS_THROW(HumbleInvalidArgument("audio channels does not match what decoder expects"));

  if (getSampleRate() != audio->getSampleRate())
    VS_THROW(HumbleInvalidArgument("audio sample rate does not match what decoder expects"));

  if (getSampleFormat() != audio->getFormat())
    VS_THROW(HumbleInvalidArgument("audio sample format does not match what decoder expects"));

}

int
Decoder::prepareFrame(AVFrame* frame, int flags) {
  if (!mCachedMedia)
    return Coder::prepareFrame(frame, flags);

  switch (getCodecType()) {
  case MediaDescriptor::MEDIA_AUDIO: {
    MediaAudioImpl* audio = dynamic_cast<MediaAudioImpl*>(mCachedMedia.value());
    if (!audio ||
        audio->getSampleRate() != frame->sample_rate ||
        audio->getChannelLayout() != frame->channel_layout ||
        audio->getFormat() != frame->format)
      return Coder::prepareFrame(frame, flags);
    av_frame_unref(frame);
    // reuse our audio frame.
    av_frame_ref(frame, audio->getCtx());
  }
  break;
  case MediaDescriptor::MEDIA_VIDEO: {
    MediaPictureImpl* pict = dynamic_cast<MediaPictureImpl*>(mCachedMedia.value());
    if (!pict ||
        pict->getWidth() != frame->width ||
        pict->getHeight() != frame->height ||
        pict->getFormat() != frame->format)
      return Coder::prepareFrame(frame, flags);
    av_frame_unref(frame);
    // reuse our audio frame.
    av_frame_ref(frame, pict->getCtx());
  }
  break;
  default:
    VS_LOG_ERROR("Got unknown codec type to allocate for");
    break;
  }
  return 0;
}

int32_t
Decoder::decodeAudio(MediaAudio* aOutput, MediaPacket* aPacket,
    int32_t byteOffset) {
  MediaAudioImpl* output = dynamic_cast<MediaAudioImpl*>(aOutput);
  MediaPacketImpl* packet = dynamic_cast<MediaPacketImpl*>(aPacket);

  if (byteOffset < 0) {
    VS_THROW(HumbleInvalidArgument("byteOffset must be >= 0"));
  }
  if (STATE_OPENED != getState())
    VS_THROW(HumbleRuntimeError("Attempt to decodeAudio, but Decoder is not opened"));

  // let's check the audio parameters.
  ensureAudioParamsMatch(aOutput);

  if (packet) {
    if (!packet->isComplete()) {
      VS_THROW(HumbleRuntimeError("Passed in a non-null but not complete packet; this is an error"));
    }
    if (byteOffset >= packet->getSize()) {
      VS_THROW(HumbleRuntimeError("Byteoffset is greater than total length of data in packet"));
    }
  } else {
    if (byteOffset > 0) {
      VS_LOG_WARN("Passing null packet with a non zero byte offset makes no sense");
    }
  }

  // arguments now confirmed; let's do a decode
  int32_t retval = -1;
  int got_frame = 0;

  // let's get the ffmpeg structures
  AVPacket* inPkt = packet ? packet->getCtx() : 0;

  // now we're going to copy the inPkt to do the byte-offset stuff. This
  // will copy by reference.
  AVPacket tmp;
  AVPacket* pkt = &tmp;
  av_init_packet(pkt);
  if (inPkt) {
    // copy in the actual packet
    av_copy_packet(pkt, inPkt);
    // now, adjust the data and size pointers
    pkt->data = pkt->data + byteOffset;
    pkt->size = pkt->size - byteOffset;
  } else {
    pkt->data = 0;
    pkt->size = 0;
  }
  // 'empty' out the input samples
  output->setComplete(false);

  AVFrame *frame = av_frame_alloc();
  if (!frame)
    VS_THROW(HumbleBadAlloc());
  /** DO NOT THROW EXCEPTIONS **/
  // create a frame to decode into, so that FFmpeg doesn't get knickers
  // in a twist re: allocation; but we will attempt to re-use our output
  // frame by setting a call back that Coder::getBuffer2 will use.

  mCachedMedia.reset(output, true);
  // try out decode
  retval = avcodec_decode_audio4(mCtx, frame, &got_frame, pkt);
  // always free the packet so that we don't have an exception make us leak it.
  av_free_packet(pkt);
  if (got_frame) {
    // copy the output frame to our frame
    output->copy(frame, true);
  }
  // release the temporary reference
  mCachedMedia = 0;
  av_frame_unref(frame);
  av_freep(&frame);
  /** END DO NOT THROW EXCEPTIONS **/
  if (retval < 0) {
    // let's make an error
    RefPointer<Error> error = Error::make(retval);
    VS_THROW(HumbleRuntimeError::make("Error while decoding: %s", error ? error->getDescription() : ""));
  }
  return retval;
}

int32_t
Decoder::decodeVideo(MediaPicture* aOutput, MediaPacket* aPacket,
    int32_t byteOffset) {
  MediaPictureImpl* output = dynamic_cast<MediaPictureImpl*>(aOutput);
  MediaPacketImpl* packet = dynamic_cast<MediaPacketImpl*>(aPacket);

  if (byteOffset < 0) {
    VS_THROW(HumbleInvalidArgument("byteOffset must be >= 0"));
  }
  if (STATE_OPENED != getState())
    VS_THROW(HumbleRuntimeError("Attempt to decodeAudio, but Decoder is not opened"));

  // let's check the picture parameters.
  ensurePictureParamsMatch(output);

  if (packet) {
    if (!packet->isComplete()) {
      VS_THROW(HumbleRuntimeError("Passed in a non-null but not complete packet; this is an error"));
    }
    if (byteOffset >= packet->getSize()) {
      VS_THROW(HumbleRuntimeError("Byteoffset is greater than total length of data in packet"));
    }
  } else {
    if (byteOffset > 0) {
      VS_LOG_WARN("Passing null packet with a non zero byte offset makes no sense");
    }
  }

  // arguments now confirmed; let's do a decode
  int32_t retval = -1;
  int got_frame = 0;

  // let's get the ffmpeg structures
  AVPacket* inPkt = packet ? packet->getCtx() : 0;

  // now we're going to copy the inPkt to do the byte-offset stuff. This
  // will copy by reference.
  AVPacket tmp;
  AVPacket* pkt = &tmp;
  av_init_packet(pkt);
  if (inPkt) {
    // copy in the actual packet
    av_copy_packet(pkt, inPkt);
    // now, adjust the data and size pointers
    pkt->data = pkt->data + byteOffset;
    pkt->size = pkt->size - byteOffset;
  } else {
    pkt->data = 0;
    pkt->size = 0;
  }
  // 'empty' out the input samples
  output->setComplete(false);

  AVFrame *frame = av_frame_alloc();
  if (!frame)
    VS_THROW(HumbleBadAlloc());
  /** DO NOT THROW EXCEPTIONS **/
  // create a frame to decode into, so that FFmpeg doesn't get knickers
  // in a twist re: allocation; but we will attempt to re-use our output
  // frame by setting a call back that Coder::getBuffer2 will use.

  mCachedMedia.reset(output, true);
  // try out decode
  retval = avcodec_decode_video2(mCtx, frame, &got_frame, pkt);
  // always free the packet so that we don't have an exception make us leak it.
  av_free_packet(pkt);
  if (got_frame) {
    // copy the output frame to our frame
    output->copy(frame, true);
  }
  // release the temporary reference
  mCachedMedia = 0;
  av_frame_unref(frame);
  av_freep(&frame);
  /** END DO NOT THROW EXCEPTIONS **/
  if (retval < 0) {
    // let's make an error
    RefPointer<Error> error = Error::make(retval);
    VS_THROW(HumbleRuntimeError::make("Error while decoding: %s", error ? error->getDescription() : ""));
  }
  return retval;
}

int32_t
Decoder::decodeSubtitle(MediaSubtitle* output, MediaPacket* packet,
    int32_t byteOffset) {
  (void) output;
  (void) packet;
  (void) byteOffset;
  VS_THROW(HumbleRuntimeError("Not implemented yet."));
  return -1;
}

Decoder*
Decoder::make(Codec* codec)
{
  if (!codec)
    throw HumbleInvalidArgument("no codec passed in");

  if (!codec->canDecode())
    throw HumbleInvalidArgument("passed in codec cannot decode");

  RefPointer<Decoder> retval;
  // new Decoder DOES NOT increment refcount but the reset should catch it.
  retval.reset(new Decoder(codec, 0), true);
  return retval.get();
}

Decoder*
Decoder::make(Decoder* src)
{
  if (!src)
    throw HumbleInvalidArgument("no Decoder to copy");

  RefPointer<Codec> codec = src->getCodec();
  return make(codec.value(), src->mCtx);
}

Decoder*
Decoder::make(Codec* codec, const AVCodecContext* src) {
  if (!src)
    throw HumbleInvalidArgument("no Decoder to copy");
  if (!src->codec_id)
    throw HumbleRuntimeError("No codec set on coder???");

  RefPointer<Decoder> retval;
  // new Decoder DOES NOT increment refcount but the reset should catch it.
  retval.reset(new Decoder(codec, src), true);
  return retval.get();
}

} /* namespace video */
} /* namespace humble */
} /* namespace io */
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 <folly/FileUtil.h>
#include <folly/io/async/SSLContext.h>
#include <gtest/gtest.h>
#include "common/files/FileUtil.h"

using namespace facebook::files;

/*
 * This test is meant to verify that SSLContext correctly sets its minimum
 * protocol version and is not blocked by OpenSSL's default config.
 */
namespace folly {

// need OpenSSL version 1.1.1 for the SSL_CTX_get_min_proto_version function
// should reduce this prereq's scope if new tests are added that don't need it
#if FOLLY_OPENSSL_PREREQ(1, 1, 1)

/*
 * The default OpenSSL config file contents for version OpenSSL 1.1.1c FIPS  28
 * May 2019. This should set the MinProtocol to TLS 1.2 and SECLEVEL to 2.
 */
const std::string kOpenSSLConf = folly::stripLeftMargin(R"(
    CipherString = @SECLEVEL=2:kEECDH:kRSA:kEDH:kPSK:kDHEPSK:kECDHEPSK:-aDSS:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
    Ciphersuites = TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_SHA256
    MinProtocol = TLSv1.2
)");

class SSLContextRegressionTest : public testing::Test {
 public:
  void SetUp() override {
    TemporaryFile confFile(nullptr, "", true);
    FileUtil::writeStringToFile(StringPiece(kOpenSSLConf), confFile.filename());

    // simulate the system environment by loading a config file that should
    // represent the CentOS 8 configuration
    int result = CONF_modules_load_file(confFile.filename(), nullptr, 0);
    ASSERT_EQ(result, 1) << "Failed to load OpenSSL conf from temporary file.";
  }
};

// Tests that specifying a TLS version actually sets the underlying SSL
// context's minimum to that same version (and not the default in the config).
TEST_F(SSLContextRegressionTest, IsNotAffectedBySystemEnvironment) {
  auto ctx = std::make_shared<SSLContext>(SSLContext::SSLVersion::TLSv1);
  ASSERT_EQ(SSL_CTX_get_min_proto_version(ctx->getSSLCtx()), TLS1_VERSION);
}

#endif

} // namespace folly
<commit_msg>Remove dependence on common for a test<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 <folly/FileUtil.h>
#include <folly/experimental/TestUtil.h>
#include <folly/io/async/SSLContext.h>
#include <folly/portability/GTest.h>

/*
 * This test is meant to verify that SSLContext correctly sets its minimum
 * protocol version and is not blocked by OpenSSL's default config.
 */
namespace folly {

// need OpenSSL version 1.1.1 for the SSL_CTX_get_min_proto_version function
// should reduce this prereq's scope if new tests are added that don't need it
#if FOLLY_OPENSSL_PREREQ(1, 1, 1)

/*
 * The default OpenSSL config file contents for version OpenSSL 1.1.1c FIPS  28
 * May 2019. This should set the MinProtocol to TLS 1.2 and SECLEVEL to 2.
 */
const std::string kOpenSSLConf = folly::stripLeftMargin(R"(
    CipherString = @SECLEVEL=2:kEECDH:kRSA:kEDH:kPSK:kDHEPSK:kECDHEPSK:-aDSS:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
    Ciphersuites = TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_SHA256
    MinProtocol = TLSv1.2
)");

class SSLContextRegressionTest : public testing::Test {
 public:
  void SetUp() override {
    TemporaryFile confFile{};
    FileUtil::writeStringToFile(StringPiece(kOpenSSLConf), confFile.filename());

    // simulate the system environment by loading a config file that should
    // represent the CentOS 8 configuration
    int result = CONF_modules_load_file(confFile.filename(), nullptr, 0);
    ASSERT_EQ(result, 1) << "Failed to load OpenSSL conf from temporary file.";
  }
};

// Tests that specifying a TLS version actually sets the underlying SSL
// context's minimum to that same version (and not the default in the config).
TEST_F(SSLContextRegressionTest, IsNotAffectedBySystemEnvironment) {
  auto ctx = std::make_shared<SSLContext>(SSLContext::SSLVersion::TLSv1);
  ASSERT_EQ(SSL_CTX_get_min_proto_version(ctx->getSSLCtx()), TLS1_VERSION);
}

#endif

} // namespace folly
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2004 Robert Osfield
 *
 * This application is open source and may be redistributed and/or modified
 * freely and without restriction, both in commericial and non commericial
 * applications, as long as this copyright notice is maintained.
 *
 * This application is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
*/

/* file:        src/osgPlugins/trans/ReaderWriterTRANS.cpp
 * author:      Mike Weiblen http://mew.cx/ 2004-07-15
 * copyright:   (C) 2004 Michael Weiblen
 * license:     OpenSceneGraph Public License (OSGPL)
*/

#include <osg/Notify>
#include <osg/Matrix>
#include <osg/MatrixTransform>

#include <osgDB/ReaderWriter>
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>
#include <osgDB/ReadFile>

#include <stdio.h>

#define EXTENSION_NAME "trans"

static bool getFilenameAndParams(const std::string& input, std::string& filename, std::string& params)
{
    // find the start of the params list, accounting for nesting of [] and () brackets,
    // note, we are working backwards.
    int noNestedBrackets = 0;
    std::string::size_type pos = input.size();
    for(; pos>0; )
    {
        --pos;
        char c = input[pos];
        if (c==']') ++noNestedBrackets;
        else if (c=='[') --noNestedBrackets;
        else if (c==')') ++noNestedBrackets;
        else if (c=='(') --noNestedBrackets;
        else if (c=='.' && noNestedBrackets==0) break;
    }

    // get the next "extension", which actually contains the pseudo-loader parameters
    params = input.substr(pos+1, std::string::npos );
    if( params.empty() )
    {
        osg::notify(osg::WARN) << "Missing parameters for " EXTENSION_NAME " pseudo-loader" << std::endl;
        return false;
    }

    // clear the params sting of any brackets.
    std::string::size_type params_pos = params.size();
    for(; params_pos>0; )
    {
        --params_pos;
        char c = params[params_pos];
        if (c==']' || c=='[' || c==')' || c=='(')
        {
            params.erase(params_pos,1);
        }
    }

    // strip the "params extension", which must leave a sub-filename.
    filename = input.substr(0, pos );

    return true;
}

///////////////////////////////////////////////////////////////////////////

/**
 * An OSG reader plugin for the ".trans" pseudo-loader, which inserts a
 * translation transform above the loaded geometry.
 * This pseudo-loader make it simple to change the origin of a saved model
 * by specifying a correcting translation as part of the filename.
 *
 * Usage: <modelfile.ext>.<tx>,<ty>,<tz>.globe
 * where:
 *      <modelfile.ext> = an model filename.
 *      <tx> = translation along the X axis.
 *      <ty> = translation along the Y axis.
 *      <tz> = translation along the Z axis.
 *
 * example: osgviewer cow.osg.25,0,0.trans cessna.osg
 */

class ReaderWriterTRANS : public osgDB::ReaderWriter
{
public:
    ReaderWriterTRANS()
    {
        supportsExtension(EXTENSION_NAME,"Translation Psuedo loader.");
    }

    virtual const char* className() const { return "translation pseudo-loader"; }

    virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
    {
        std::string ext = osgDB::getLowerCaseFileExtension(fileName);
        if( !acceptsExtension(ext) )
            return ReadResult::FILE_NOT_HANDLED;

        osg::notify(osg::INFO) << "ReaderWriterTRANS( \"" << fileName << "\" )" << std::endl;

        // strip the pseudo-loader extension
        std::string tmpName = osgDB::getNameLessExtension( fileName );

        if (tmpName.empty())
            return ReadResult::FILE_NOT_HANDLED;

        std::string subFileName, params;
        if (!getFilenameAndParams(tmpName, subFileName, params))
        {
            return ReadResult::FILE_NOT_HANDLED;
        }

        if( subFileName.empty())
        {
            osg::notify(osg::WARN) << "Missing subfilename for " EXTENSION_NAME " pseudo-loader" << std::endl;
            return ReadResult::FILE_NOT_HANDLED;
        }

        osg::notify(osg::INFO) << " params = \"" << params << "\"" << std::endl;
        osg::notify(osg::INFO) << " subFileName = \"" << subFileName << "\"" << std::endl;

        float tx, ty, tz;
        int count = sscanf( params.c_str(), "%f,%f,%f", &tx, &ty, &tz );
        if( count != 3 )
        {
            osg::notify(osg::WARN) << "Bad parameters for " EXTENSION_NAME " pseudo-loader: \"" << params << "\"" << std::endl;
            return ReadResult::FILE_NOT_HANDLED;
        }

        // recursively load the subfile.
        osg::Node *node = osgDB::readNodeFile( subFileName, options );
        if( !node )
        {
            // propagate the read failure upwards
            osg::notify(osg::WARN) << "Subfile \"" << subFileName << "\" could not be loaded" << std::endl;
            return ReadResult::FILE_NOT_HANDLED;
        }

        osg::MatrixTransform *xform = new osg::MatrixTransform;
        xform->setDataVariance( osg::Object::STATIC );
        xform->setMatrix( osg::Matrix::translate( tx, ty, tz ) );
        xform->addChild( node );
        return xform;
    }
};

// Add ourself to the Registry to instantiate the reader/writer.
REGISTER_OSGPLUGIN(trans, ReaderWriterTRANS)

/*EOF*/

<commit_msg>Converted osg::notify to OSG_INFO etc.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2004 Robert Osfield
 *
 * This application is open source and may be redistributed and/or modified
 * freely and without restriction, both in commericial and non commericial
 * applications, as long as this copyright notice is maintained.
 *
 * This application is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
*/

/* file:        src/osgPlugins/trans/ReaderWriterTRANS.cpp
 * author:      Mike Weiblen http://mew.cx/ 2004-07-15
 * copyright:   (C) 2004 Michael Weiblen
 * license:     OpenSceneGraph Public License (OSGPL)
*/

#include <osg/Notify>
#include <osg/Matrix>
#include <osg/MatrixTransform>

#include <osgDB/ReaderWriter>
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>
#include <osgDB/ReadFile>

#include <stdio.h>

#define EXTENSION_NAME "trans"

static bool getFilenameAndParams(const std::string& input, std::string& filename, std::string& params)
{
    // find the start of the params list, accounting for nesting of [] and () brackets,
    // note, we are working backwards.
    int noNestedBrackets = 0;
    std::string::size_type pos = input.size();
    for(; pos>0; )
    {
        --pos;
        char c = input[pos];
        if (c==']') ++noNestedBrackets;
        else if (c=='[') --noNestedBrackets;
        else if (c==')') ++noNestedBrackets;
        else if (c=='(') --noNestedBrackets;
        else if (c=='.' && noNestedBrackets==0) break;
    }

    // get the next "extension", which actually contains the pseudo-loader parameters
    params = input.substr(pos+1, std::string::npos );
    if( params.empty() )
    {
        OSG_WARN << "Missing parameters for " EXTENSION_NAME " pseudo-loader" << std::endl;
        return false;
    }

    // clear the params sting of any brackets.
    std::string::size_type params_pos = params.size();
    for(; params_pos>0; )
    {
        --params_pos;
        char c = params[params_pos];
        if (c==']' || c=='[' || c==')' || c=='(')
        {
            params.erase(params_pos,1);
        }
    }

    // strip the "params extension", which must leave a sub-filename.
    filename = input.substr(0, pos );

    return true;
}

///////////////////////////////////////////////////////////////////////////

/**
 * An OSG reader plugin for the ".trans" pseudo-loader, which inserts a
 * translation transform above the loaded geometry.
 * This pseudo-loader make it simple to change the origin of a saved model
 * by specifying a correcting translation as part of the filename.
 *
 * Usage: <modelfile.ext>.<tx>,<ty>,<tz>.globe
 * where:
 *      <modelfile.ext> = an model filename.
 *      <tx> = translation along the X axis.
 *      <ty> = translation along the Y axis.
 *      <tz> = translation along the Z axis.
 *
 * example: osgviewer cow.osg.25,0,0.trans cessna.osg
 */

class ReaderWriterTRANS : public osgDB::ReaderWriter
{
public:
    ReaderWriterTRANS()
    {
        supportsExtension(EXTENSION_NAME,"Translation Psuedo loader.");
    }

    virtual const char* className() const { return "translation pseudo-loader"; }

    virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
    {
        std::string ext = osgDB::getLowerCaseFileExtension(fileName);
        if( !acceptsExtension(ext) )
            return ReadResult::FILE_NOT_HANDLED;

        OSG_INFO << "ReaderWriterTRANS( \"" << fileName << "\" )" << std::endl;

        // strip the pseudo-loader extension
        std::string tmpName = osgDB::getNameLessExtension( fileName );

        if (tmpName.empty())
            return ReadResult::FILE_NOT_HANDLED;

        std::string subFileName, params;
        if (!getFilenameAndParams(tmpName, subFileName, params))
        {
            return ReadResult::FILE_NOT_HANDLED;
        }

        if( subFileName.empty())
        {
            OSG_WARN << "Missing subfilename for " EXTENSION_NAME " pseudo-loader" << std::endl;
            return ReadResult::FILE_NOT_HANDLED;
        }

        OSG_INFO << " params = \"" << params << "\"" << std::endl;
        OSG_INFO << " subFileName = \"" << subFileName << "\"" << std::endl;

        float tx, ty, tz;
        int count = sscanf( params.c_str(), "%f,%f,%f", &tx, &ty, &tz );
        if( count != 3 )
        {
            OSG_WARN << "Bad parameters for " EXTENSION_NAME " pseudo-loader: \"" << params << "\"" << std::endl;
            return ReadResult::FILE_NOT_HANDLED;
        }

        // recursively load the subfile.
        osg::Node *node = osgDB::readNodeFile( subFileName, options );
        if( !node )
        {
            // propagate the read failure upwards
            OSG_WARN << "Subfile \"" << subFileName << "\" could not be loaded" << std::endl;
            return ReadResult::FILE_NOT_HANDLED;
        }

        osg::MatrixTransform *xform = new osg::MatrixTransform;
        xform->setDataVariance( osg::Object::STATIC );
        xform->setMatrix( osg::Matrix::translate( tx, ty, tz ) );
        xform->addChild( node );
        return xform;
    }
};

// Add ourself to the Registry to instantiate the reader/writer.
REGISTER_OSGPLUGIN(trans, ReaderWriterTRANS)

/*EOF*/

<|endoftext|>


<commit_before>/*
   Clique: a scalable implementation of the multifrontal algorithm

   Copyright (C) 2011-2012 Jack Poulson, Lexing Ying, and
   The University of Texas at Austin

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

namespace cliq {

template<typename F>
void Solve
( const DistSymmInfo& info, const DistSymmFrontTree<F>& L, Matrix<F>& localX );

template<typename F>
void SymmetricSolve
( const DistSparseMatrix<F>& A, DistVector<F>& x,
  bool sequential=true, int numDistSeps=1, int numSeqSeps=1, int cutoff=128 );
template<typename F>
void HermitianSolve
( const DistSparseMatrix<F>& A, DistVector<F>& x,
  bool sequential=true, int numDistSeps=1, int numSeqSeps=1, int cutoff=128 );

template<typename F>
void SymmetricSolve
( const DistSparseMatrix<F>& A, DistMultiVector<F>& X,
  bool sequential=true, int numDistSeps=1, int numSeqSeps=1, int cutoff=128 );
template<typename F>
void HermitianSolve
( const DistSparseMatrix<F>& A, DistMultiVector<F>& X,
  bool sequential=true, int numDistSeps=1, int numSeqSeps=1, int cutoff=128 );

//----------------------------------------------------------------------------//
// Implementation begins here                                                 //
//----------------------------------------------------------------------------//

template<typename F>
inline void Solve
( const DistSymmInfo& info, const DistSymmFrontTree<F>& L, Matrix<F>& localX )
{
#ifndef RELEASE
    PushCallStack("Solve");
#endif
    const bool blockLDL = ( L.frontType == BLOCK_LDL_2D );
    if( !blockLDL )
    {
        // Solve against unit diagonal L
        LowerSolve( NORMAL, UNIT, info, L, localX );

        // Solve against diagonal
        DiagonalSolve( info, L, localX );

        // Solve against the (conjugate-)transpose of the unit diagonal L
        if( L.isHermitian )
            LowerSolve( ADJOINT, UNIT, info, L, localX );
        else
            LowerSolve( TRANSPOSE, UNIT, info, L, localX );
    }
    else
    {
        // Solve against block diagonal factor, L D
        LowerSolve( NORMAL, NON_UNIT, info, L, localX );

        // Solve against the (conjugate-)transpose of the block unit diagonal L
        if( L.isHermitian )
            LowerSolve( ADJOINT, NON_UNIT, info, L, localX );
        else
            LowerSolve( TRANSPOSE, NON_UNIT, info, L, localX );
    }
#ifndef RELEASE
    PopCallStack();
#endif
}

template<typename F>
inline void SymmetricSolve
( const DistSparseMatrix<F>& A, DistVector<F>& x,
  bool sequential=true, int numDistSeps=1, int numSeqSeps=1, int cutoff=128 )
{
#ifndef RELEASE
    PushCallStack("SymmetricSolve");
#endif
    DistSymmInfo info;
    DistSeparatorTree sepTree;
    DistMap map, inverseMap;
    NestedDissection
    ( A.Graph(), map, sepTree, info,
      sequential, numDistSeps, numSeqSeps, cutoff );
    map.FormInverse( inverseMap );

    DistSymmFrontTree<F> frontTree( TRANSPOSE, A, map, sepTree, info );
    LDL( info, frontTree, LDL_1D );

    DistNodalVector<F> xNodal;
    xNodal.Pull( inverseMap, info, x );
    Solve( info, frontTree, xNodal.localVec );
    xNodal.Push( inverseMap, info, x );
#ifndef RELEASE
    PopCallStack();
#endif
}

template<typename F>
inline void HermitianSolve
( const DistSparseMatrix<F>& A, DistVector<F>& x,
  bool sequential=true, int numDistSeps=1, int numSeqSeps=1, int cutoff=128 )
{
#ifndef RELEASE
    PushCallStack("HermitianSolve");
#endif
    DistSymmInfo info;
    DistSeparatorTree sepTree;
    DistMap map, inverseMap;
    NestedDissection
    ( A.Graph(), map, sepTree, info,
      sequential, numDistSeps, numSeqSeps, cutoff );
    map.FormInverse( inverseMap );

    DistSymmFrontTree<F> frontTree( ADJOINT, A, map, sepTree, info );
    LDL( info, frontTree, LDL_1D );

    DistNodalVector<F> xNodal;
    xNodal.Pull( inverseMap, info, x );
    Solve( info, frontTree, xNodal.localVec );
    xNodal.Push( inverseMap, info, x );
#ifndef RELEASE
    PopCallStack();
#endif
}

template<typename F>
inline void SymmetricSolve
( const DistSparseMatrix<F>& A, DistMultiVector<F>& X,
  bool sequential=true, int numDistSeps=1, int numSeqSeps=1, int cutoff=128 )
{
#ifndef RELEASE
    PushCallStack("SymmetricSolve");
#endif
    DistSymmInfo info;
    DistSeparatorTree sepTree;
    DistMap map, inverseMap;
    NestedDissection
    ( A.Graph(), map, sepTree, info,
      sequential, numDistSeps, numSeqSeps, cutoff );
    map.FormInverse( inverseMap );

    DistSymmFrontTree<F> frontTree( TRANSPOSE, A, map, sepTree, info );
    LDL( info, frontTree, LDL_1D );

    DistNodalMultiVector<F> XNodal;
    XNodal.Pull( inverseMap, info, X );
    Solve( info, frontTree, XNodal.localMultiVec );
    XNodal.Push( inverseMap, info, X );
#ifndef RELEASE
    PopCallStack();
#endif
}

template<typename F>
inline void HermitianSolve
( const DistSparseMatrix<F>& A, DistMultiVector<F>& X,
  bool sequential=true, int numDistSeps=1, int numSeqSeps=1, int cutoff=128 )
{
#ifndef RELEASE
    PushCallStack("HermitianSolve");
#endif
    DistSymmInfo info;
    DistSeparatorTree sepTree;
    DistMap map, inverseMap;
    NestedDissection
    ( A.Graph(), map, sepTree, info,
      sequential, numDistSeps, numSeqSeps, cutoff );
    map.FormInverse( inverseMap );

    DistSymmFrontTree<F> frontTree( ADJOINT, A, map, sepTree, info );
    LDL( info, frontTree, LDL_1D );

    DistNodalMultiVector<F> XNodal;
    XNodal.Pull( inverseMap, info, X );
    Solve( info, frontTree, XNodal.localMultiVec );
    XNodal.Push( inverseMap, info, X );
#ifndef RELEASE
    PopCallStack();
#endif
}

} // namespace cliq
<commit_msg>Fixing syntax error in HermitianSolve and SymmetricSolve.<commit_after>/*
   Clique: a scalable implementation of the multifrontal algorithm

   Copyright (C) 2011-2012 Jack Poulson, Lexing Ying, and
   The University of Texas at Austin

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

namespace cliq {

template<typename F>
void Solve
( const DistSymmInfo& info, const DistSymmFrontTree<F>& L, Matrix<F>& localX );

template<typename F>
void SymmetricSolve
( const DistSparseMatrix<F>& A, DistVector<F>& x,
  bool sequential=true, int numDistSeps=1, int numSeqSeps=1, int cutoff=128 );
template<typename F>
void HermitianSolve
( const DistSparseMatrix<F>& A, DistVector<F>& x,
  bool sequential=true, int numDistSeps=1, int numSeqSeps=1, int cutoff=128 );

template<typename F>
void SymmetricSolve
( const DistSparseMatrix<F>& A, DistMultiVector<F>& X,
  bool sequential=true, int numDistSeps=1, int numSeqSeps=1, int cutoff=128 );
template<typename F>
void HermitianSolve
( const DistSparseMatrix<F>& A, DistMultiVector<F>& X,
  bool sequential=true, int numDistSeps=1, int numSeqSeps=1, int cutoff=128 );

//----------------------------------------------------------------------------//
// Implementation begins here                                                 //
//----------------------------------------------------------------------------//

template<typename F>
inline void Solve
( const DistSymmInfo& info, const DistSymmFrontTree<F>& L, Matrix<F>& localX )
{
#ifndef RELEASE
    PushCallStack("Solve");
#endif
    const bool blockLDL = ( L.frontType == BLOCK_LDL_2D );
    if( !blockLDL )
    {
        // Solve against unit diagonal L
        LowerSolve( NORMAL, UNIT, info, L, localX );

        // Solve against diagonal
        DiagonalSolve( info, L, localX );

        // Solve against the (conjugate-)transpose of the unit diagonal L
        if( L.isHermitian )
            LowerSolve( ADJOINT, UNIT, info, L, localX );
        else
            LowerSolve( TRANSPOSE, UNIT, info, L, localX );
    }
    else
    {
        // Solve against block diagonal factor, L D
        LowerSolve( NORMAL, NON_UNIT, info, L, localX );

        // Solve against the (conjugate-)transpose of the block unit diagonal L
        if( L.isHermitian )
            LowerSolve( ADJOINT, NON_UNIT, info, L, localX );
        else
            LowerSolve( TRANSPOSE, NON_UNIT, info, L, localX );
    }
#ifndef RELEASE
    PopCallStack();
#endif
}

template<typename F>
inline void SymmetricSolve
( const DistSparseMatrix<F>& A, DistVector<F>& x,
  bool sequential, int numDistSeps, int numSeqSeps, int cutoff )
{
#ifndef RELEASE
    PushCallStack("SymmetricSolve");
#endif
    DistSymmInfo info;
    DistSeparatorTree sepTree;
    DistMap map, inverseMap;
    NestedDissection
    ( A.Graph(), map, sepTree, info,
      sequential, numDistSeps, numSeqSeps, cutoff );
    map.FormInverse( inverseMap );

    DistSymmFrontTree<F> frontTree( TRANSPOSE, A, map, sepTree, info );
    LDL( info, frontTree, LDL_1D );

    DistNodalVector<F> xNodal;
    xNodal.Pull( inverseMap, info, x );
    Solve( info, frontTree, xNodal.localVec );
    xNodal.Push( inverseMap, info, x );
#ifndef RELEASE
    PopCallStack();
#endif
}

template<typename F>
inline void HermitianSolve
( const DistSparseMatrix<F>& A, DistVector<F>& x,
  bool sequential, int numDistSeps, int numSeqSeps, int cutoff )
{
#ifndef RELEASE
    PushCallStack("HermitianSolve");
#endif
    DistSymmInfo info;
    DistSeparatorTree sepTree;
    DistMap map, inverseMap;
    NestedDissection
    ( A.Graph(), map, sepTree, info,
      sequential, numDistSeps, numSeqSeps, cutoff );
    map.FormInverse( inverseMap );

    DistSymmFrontTree<F> frontTree( ADJOINT, A, map, sepTree, info );
    LDL( info, frontTree, LDL_1D );

    DistNodalVector<F> xNodal;
    xNodal.Pull( inverseMap, info, x );
    Solve( info, frontTree, xNodal.localVec );
    xNodal.Push( inverseMap, info, x );
#ifndef RELEASE
    PopCallStack();
#endif
}

template<typename F>
inline void SymmetricSolve
( const DistSparseMatrix<F>& A, DistMultiVector<F>& X,
  bool sequential, int numDistSeps, int numSeqSeps, int cutoff )
{
#ifndef RELEASE
    PushCallStack("SymmetricSolve");
#endif
    DistSymmInfo info;
    DistSeparatorTree sepTree;
    DistMap map, inverseMap;
    NestedDissection
    ( A.Graph(), map, sepTree, info,
      sequential, numDistSeps, numSeqSeps, cutoff );
    map.FormInverse( inverseMap );

    DistSymmFrontTree<F> frontTree( TRANSPOSE, A, map, sepTree, info );
    LDL( info, frontTree, LDL_1D );

    DistNodalMultiVector<F> XNodal;
    XNodal.Pull( inverseMap, info, X );
    Solve( info, frontTree, XNodal.localMultiVec );
    XNodal.Push( inverseMap, info, X );
#ifndef RELEASE
    PopCallStack();
#endif
}

template<typename F>
inline void HermitianSolve
( const DistSparseMatrix<F>& A, DistMultiVector<F>& X,
  bool sequential, int numDistSeps, int numSeqSeps, int cutoff )
{
#ifndef RELEASE
    PushCallStack("HermitianSolve");
#endif
    DistSymmInfo info;
    DistSeparatorTree sepTree;
    DistMap map, inverseMap;
    NestedDissection
    ( A.Graph(), map, sepTree, info,
      sequential, numDistSeps, numSeqSeps, cutoff );
    map.FormInverse( inverseMap );

    DistSymmFrontTree<F> frontTree( ADJOINT, A, map, sepTree, info );
    LDL( info, frontTree, LDL_1D );

    DistNodalMultiVector<F> XNodal;
    XNodal.Pull( inverseMap, info, X );
    Solve( info, frontTree, XNodal.localMultiVec );
    XNodal.Push( inverseMap, info, X );
#ifndef RELEASE
    PopCallStack();
#endif
}

} // namespace cliq
<|endoftext|>


<commit_before>
#ifndef _EDGES_SET
#define _EDGES_SET

#include <map>
#include <vector>
#include <utility>

namespace Graph {

  template<typename T>
    using Map = std::map<int, std::vector<std::pair<int, T>>>;

  template <typename T>
    class EdgesSet {
      public:
      void add(int src, int dst, T edge_info);
      std::vector<std::pair<int, T>>& operator[](int src);

      uint32_t size();
      typename Map<T>::iterator begin();
      typename Map<T>::iterator end();

      private:
        Map<T> edges_;
    };

  template <typename T>
    std::vector<std::pair<int, T>>& EdgesSet<T>::operator[](int src) {
      return edges_[src];
    }

  template <typename T>
    void EdgesSet<T>::add(int src, int dst, T edge_info) {
      edges_[src].emplace_back(make_pair(dst, edge_info));
    }

  template <typename T>
    uint32_t EdgesSet<T>::size() {
      return edges_.size();
    }

  template <typename T>
    typename Map<T>::iterator EdgesSet<T>::begin() {
      return edges_.begin();
    }

  template <typename T>
    typename Map<T>::iterator EdgesSet<T>::end() {
      return edges_.end();
    }
}

#endif
<commit_msg>graph: remove unnecessary object copying<commit_after>
#ifndef _EDGES_SET
#define _EDGES_SET

#include <map>
#include <vector>
#include <utility>

namespace Graph {

  template<typename T>
    using Map = std::map<int, std::vector<std::pair<int, T>>>;

  template <typename T>
    class EdgesSet {
      public:
      void add(int src, int dst, T edge_info);
      std::vector<std::pair<int, T>>& operator[](int src);

      uint32_t size();
      typename Map<T>::iterator begin();
      typename Map<T>::iterator end();

      private:
        Map<T> edges_;
    };

  template <typename T>
    std::vector<std::pair<int, T>>& EdgesSet<T>::operator[](int src) {
      return edges_[src];
    }

  template <typename T>
    void EdgesSet<T>::add(int src, int dst, T edge_info) {
      edges_[src].emplace_back(dst, edge_info);
    }

  template <typename T>
    uint32_t EdgesSet<T>::size() {
      return edges_.size();
    }

  template <typename T>
    typename Map<T>::iterator EdgesSet<T>::begin() {
      return edges_.begin();
    }

  template <typename T>
    typename Map<T>::iterator EdgesSet<T>::end() {
      return edges_.end();
    }
}

#endif
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2019, Brian Lee, Vinitha Ranganeni
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     1. Redistributions of source code must retain the above copyright notice
//        this list of conditions and the following disclaimer.
//     2. Redistributions in binary form must reproduce the above copyright
//        notice, this list of conditions and the following disclaimer in the
//        documentation and/or other materials provided with the distribution.
//     3. Neither the name of the copyright holder nor the names of its
//        contributors may be used to endorse or promote products derived from
//        this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////////////

#ifndef LIBCOZMO_DISTANCE_ORIENTATION_HPP_
#define LIBCOZMO_DISTANCE_ORIENTATION_HPP_

#include <memory>
#include "statespace/SE2.hpp"
#include "distance/distance.hpp"

namespace libcozmo {
namespace distance {

/// Distance metric class
///
/// This class implements a distace metric of a continuous orientation i.e.
/// distance of two states are defined by the difference of their orientation
/// in range [0, 2pi].
class Orientation : public virtual Distance {
 public:
    /// Constructs metric with given statespace
    ///
    /// \param statespace The statespace the metric operates in
    explicit Orientation(const std::shared_ptr<statespace::SE2> statespace);
    ~Orientation() {}

    /// Documentation inherited
    double get_distance(
        const libcozmo::statespace::StateSpace::State& _state_1,
        const libcozmo::statespace::StateSpace::State& _state_2) const override;

 private:
    const std::shared_ptr<statespace::SE2> m_statespace;
};

}  // namespace distance
}  // namespace libcozmo

#endif  // LIBCOZMO_DISTANCE_ORIENTATION_HPP_
<commit_msg>PR edits<commit_after>//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2019, Brian Lee, Vinitha Ranganeni
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     1. Redistributions of source code must retain the above copyright notice
//        this list of conditions and the following disclaimer.
//     2. Redistributions in binary form must reproduce the above copyright
//        notice, this list of conditions and the following disclaimer in the
//        documentation and/or other materials provided with the distribution.
//     3. Neither the name of the copyright holder nor the names of its
//        contributors may be used to endorse or promote products derived from
//        this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////////////

#ifndef LIBCOZMO_DISTANCE_ORIENTATION_HPP_
#define LIBCOZMO_DISTANCE_ORIENTATION_HPP_

#include <memory>
#include "statespace/SE2.hpp"
#include "distance/distance.hpp"

namespace libcozmo {
namespace distance {

/// Distance metric class
///
/// This class implements a distance metric of a continuous orientation i.e.
/// distance of two states are defined by the difference of their orientation
/// in range [0, 2pi].
class Orientation : public virtual Distance {
 public:
    /// Constructs metric with given statespace
    ///
    /// \param statespace The statespace the metric operates in
    explicit Orientation(const std::shared_ptr<statespace::SE2> statespace);
    ~Orientation() {}

    /// Documentation inherited
    double get_distance(
        const libcozmo::statespace::StateSpace::State& _state_1,
        const libcozmo::statespace::StateSpace::State& _state_2) const override;

 private:
    const std::shared_ptr<statespace::SE2> m_statespace;
};

}  // namespace distance
}  // namespace libcozmo

#endif  // LIBCOZMO_DISTANCE_ORIENTATION_HPP_
<|endoftext|>


<commit_before>#include "stdafx.h"

#include <SADXModLoader.h>

#include "minmax.h"
#include "input.h"
#include "rumble.h"

namespace rumble
{
	struct RumbleTimer
	{
		bool applied;
		Uint8 port;
		Motor motor;
		Sint32 frames;
	};

	static ObjectMaster* instances[GAMEPAD_COUNT][2] = {};

	inline ObjectMaster* get_instance(Uint32 port, Motor motor)
	{
		return instances[port][(int)motor - 1];
	}

	inline void set_instance(Uint32 port, Motor motor, ObjectMaster* ptr)
	{
		auto i = (int)motor - 1;
		instances[port][i] = ptr;
	}

	Sint32 __cdecl pdVibMxStop_hook(Uint32 port)
	{
		for (auto& i : instances)
		{
			if (i[0])
			{
				DeleteObject_(i[0]);
				i[0] = nullptr;
			}

			if (i[1])
			{
				DeleteObject_(i[1]);
				i[1] = nullptr;
			}
		}

		for (Uint32 i = 0; i < GAMEPAD_COUNT; i++)
		{
			auto& pad = DreamPad::Controllers[i];
			if (pad.GetActiveMotor() != Motor::None)
			{
				pad.SetActiveMotor(Motor::Both, false);
			}
		}

		return 0;
	}

	static void __cdecl Rumble_Main_hook(ObjectMaster* _this)
	{
		auto data = (RumbleTimer*)_this->UnknownA_ptr;
		auto& pad  = DreamPad::Controllers[data->port];

		if (data->frames-- <= 0)
		{
			DeleteObject_(_this);
			pad.SetActiveMotor(data->motor, false);
		}
		else if (!data->applied)
		{
			pad.SetActiveMotor(data->motor, true);
			data->applied = true;
		}
	}

	static void __cdecl Rumble_Delete(ObjectMaster* _this)
	{
		auto data = (RumbleTimer*)_this->UnknownA_ptr;
		_this->UnknownA_ptr = nullptr;

		auto instance = get_instance(data->port, data->motor);
		if (instance == _this)
		{
			set_instance(data->port, data->motor, nullptr);
		}

		delete data;
	}

	static void __cdecl Rumble_Load_hook(Uint32 port, Uint32 time, Motor motor)
	{
		if (port >= GAMEPAD_COUNT)
		{
			for (ushort i = 0; i < GAMEPAD_COUNT; i++)
			{
				Rumble_Load_hook(i, time, motor);
			}
			return;
		}

		auto time_scaled = max(4 * time, (Uint32)(DreamPad::Controllers[port].settings.rumbleMinTime / (1000.0f / 60.0f)));
		auto instance = get_instance(port, motor);

		// HACK: Fixes tornado in Windy Valley, allowing it to queue rumble requests and pulse the motor.
		if (!(motor & Motor::Small) && instance != nullptr)
		{
			auto data = (RumbleTimer*)instance->UnknownA_ptr;
			data->frames = time_scaled;
			data->applied = false;
			DreamPad::Controllers[port].SetActiveMotor(motor, false);
		}
		else
		{
			auto _this = LoadObject((LoadObj)0, 0, Rumble_Main_hook);

			if (_this == nullptr)
			{
				return;
			}

			set_instance(port, motor, _this);

			auto data = new RumbleTimer;

			data->applied = false;
			data->port    = port;
			data->motor   = motor;
			data->frames  = time_scaled;

			_this->DeleteSub = Rumble_Delete;
			_this->UnknownA_ptr = data;

			if (input::debug)
			{
				auto time_ms = (Uint32)(time_scaled * (1000.0f / (60.0f / (float)FrameIncrement)));
				PrintDebug("[Input] [%u] Rumble %u: %s, %u frames (%ums)\n",
					FrameCounter, data->port, (motor == Motor::Small ? "R" : "L"), time_scaled, time_ms);
			}
		}
	}

	/// <summary>
	/// Rumbles the large motor. Used for things like explosions, springs, dash panels, etc.
	/// </summary>
	/// <param name="port">Controller port.></param>
	/// <param name="time">Time to rumble.</param>
	void __cdecl RumbleA(Uint32 port, Uint32 time)
	{
		if (RumbleEnabled && !DemoPlaying && input::_ControllerEnabled[port])
		{
			Rumble_Load_hook(port, clamp(time, 1u, 255u), Motor::Large);
		}
	}

	/// <summary>
	/// Rumbles the small motor. Used for things like taking damage.
	/// </summary>
	/// <param name="port">Controller port.</param>
	/// <param name="time">Time to rumble.</param>
	/// <param name="a3">Unknown.</param>
	/// <param name="a4">Unknown.</param>
	void __cdecl RumbleB(Uint32 port, Uint32 time, int a3, int a4)
	{
		Uint32 idk; // ecx@4
		int _a3; // eax@12
		int _time; // eax@16

		if (RumbleEnabled && !DemoPlaying && input::_ControllerEnabled[port])
		{
			idk = time;
			if ((signed int)time <= 4)
			{
				if ((signed int)time >= -4)
				{
					if (time == 1)
					{
						idk = 2;
					}
					else if (time == -1)
					{
						idk = -2;
					}
				}
				else
				{
					idk = -4;
				}
			}
			else
			{
				idk = 4;
			}

			_a3 = a3;
			if (a3 <= 59)
			{
				if (a3 < 7)
				{
					_a3 = 7;
				}
			}
			else
			{
				_a3 = 59;
			}

			_time = a4 * _a3 / (signed int)(4 * idk);
			if (_time <= 0)
			{
				_time = 1;
			}

			Rumble_Load_hook(port, _time, Motor::Small);
		}
	}

	static const void* loc_0042D534 = (const void*)0x0042D534;
	/// <summary>
	/// Enables rumble by default when a new save file is created.
	/// </summary>
	void __declspec(naked) DefaultRumble()
	{
		__asm
		{
			mov [esp + 26Ah], 1
			jmp loc_0042D534
		}
	}
}
<commit_msg>Don't stop the rumble so frequently<commit_after>#include "stdafx.h"

#include <SADXModLoader.h>

#include "minmax.h"
#include "input.h"
#include "rumble.h"

namespace rumble
{
	struct RumbleTimer
	{
		bool applied;
		Uint8 port;
		Motor motor;
		Sint32 frames;
	};

	static ObjectMaster* instances[GAMEPAD_COUNT][2] = {};

	inline ObjectMaster* get_instance(Uint32 port, Motor motor)
	{
		return instances[port][(int)motor - 1];
	}

	inline void set_instance(Uint32 port, Motor motor, ObjectMaster* ptr)
	{
		auto i = (int)motor - 1;
		instances[port][i] = ptr;
	}

	Sint32 __cdecl pdVibMxStop_hook(Uint32 port)
	{
		for (auto& i : instances)
		{
			if (i[0])
			{
				DeleteObject_(i[0]);
				i[0] = nullptr;
			}

			if (i[1])
			{
				DeleteObject_(i[1]);
				i[1] = nullptr;
			}
		}

		for (Uint32 i = 0; i < GAMEPAD_COUNT; i++)
		{
			auto& pad = DreamPad::Controllers[i];
			if (pad.GetActiveMotor() != Motor::None)
			{
				pad.SetActiveMotor(Motor::Both, false);
			}
		}

		return 0;
	}

	static void __cdecl Rumble_Main_hook(ObjectMaster* _this)
	{
		auto data = (RumbleTimer*)_this->UnknownA_ptr;
		auto& pad  = DreamPad::Controllers[data->port];

		if (data->frames-- <= 0)
		{
			DeleteObject_(_this);
			pad.SetActiveMotor(data->motor, false);
		}
		else if (!data->applied)
		{
			pad.SetActiveMotor(data->motor, true);
			data->applied = true;
		}
	}

	static void __cdecl Rumble_Delete(ObjectMaster* _this)
	{
		auto data = (RumbleTimer*)_this->UnknownA_ptr;
		_this->UnknownA_ptr = nullptr;

		auto instance = get_instance(data->port, data->motor);
		if (instance == _this)
		{
			set_instance(data->port, data->motor, nullptr);
		}

		delete data;
	}

	static void __cdecl Rumble_Load_hook(Uint32 port, Uint32 time, Motor motor)
	{
		if (port >= GAMEPAD_COUNT)
		{
			for (ushort i = 0; i < GAMEPAD_COUNT; i++)
			{
				Rumble_Load_hook(i, time, motor);
			}
			return;
		}

		auto time_scaled = max(4 * time, (Uint32)(DreamPad::Controllers[port].settings.rumbleMinTime / (1000.0f / 60.0f)));
		auto instance = get_instance(port, motor);

		// HACK: Fixes tornado in Windy Valley, allowing it to queue rumble requests and pulse the motor.
		if (!(motor & Motor::Small) && instance != nullptr)
		{
			auto data = (RumbleTimer*)instance->UnknownA_ptr;

			data->frames  = time_scaled;
			data->applied = false;

			if (FrameCounter % 60 < 2)
			{
				DreamPad::Controllers[port].SetActiveMotor(motor, false);
			}
		}
		else
		{
			auto _this = LoadObject((LoadObj)0, 0, Rumble_Main_hook);

			if (_this == nullptr)
			{
				return;
			}

			set_instance(port, motor, _this);

			auto data = new RumbleTimer;

			data->applied = false;
			data->port    = port;
			data->motor   = motor;
			data->frames  = time_scaled;

			_this->DeleteSub = Rumble_Delete;
			_this->UnknownA_ptr = data;

			if (input::debug)
			{
				auto time_ms = (Uint32)(time_scaled * (1000.0f / (60.0f / (float)FrameIncrement)));
				PrintDebug("[Input] [%u] Rumble %u: %s, %u frames (%ums)\n",
					FrameCounter, data->port, (motor == Motor::Small ? "R" : "L"), time_scaled, time_ms);
			}
		}
	}

	/// <summary>
	/// Rumbles the large motor. Used for things like explosions, springs, dash panels, etc.
	/// </summary>
	/// <param name="port">Controller port.></param>
	/// <param name="time">Time to rumble.</param>
	void __cdecl RumbleA(Uint32 port, Uint32 time)
	{
		if (RumbleEnabled && !DemoPlaying && input::_ControllerEnabled[port])
		{
			Rumble_Load_hook(port, clamp(time, 1u, 255u), Motor::Large);
		}
	}

	/// <summary>
	/// Rumbles the small motor. Used for things like taking damage.
	/// </summary>
	/// <param name="port">Controller port.</param>
	/// <param name="time">Time to rumble.</param>
	/// <param name="a3">Unknown.</param>
	/// <param name="a4">Unknown.</param>
	void __cdecl RumbleB(Uint32 port, Uint32 time, int a3, int a4)
	{
		Uint32 idk; // ecx@4
		int _a3; // eax@12
		int _time; // eax@16

		if (RumbleEnabled && !DemoPlaying && input::_ControllerEnabled[port])
		{
			idk = time;
			if ((signed int)time <= 4)
			{
				if ((signed int)time >= -4)
				{
					if (time == 1)
					{
						idk = 2;
					}
					else if (time == -1)
					{
						idk = -2;
					}
				}
				else
				{
					idk = -4;
				}
			}
			else
			{
				idk = 4;
			}

			_a3 = a3;
			if (a3 <= 59)
			{
				if (a3 < 7)
				{
					_a3 = 7;
				}
			}
			else
			{
				_a3 = 59;
			}

			_time = a4 * _a3 / (signed int)(4 * idk);
			if (_time <= 0)
			{
				_time = 1;
			}

			Rumble_Load_hook(port, _time, Motor::Small);
		}
	}

	static const void* loc_0042D534 = (const void*)0x0042D534;
	/// <summary>
	/// Enables rumble by default when a new save file is created.
	/// </summary>
	void __declspec(naked) DefaultRumble()
	{
		__asm
		{
			mov [esp + 26Ah], 1
			jmp loc_0042D534
		}
	}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: chlist.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2008-01-07 08:59:19 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _CHLIST_HXX
#define _CHLIST_HXX

#ifndef _URLOBJ_HXX //autogen
#include <tools/urlobj.hxx>
#endif
#ifndef _DATETIME_HXX //autogen
#include <tools/datetime.hxx>
#endif
#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif
#ifndef _TIMER_HXX //autogen
#include <vcl/timer.hxx>
#endif
#ifndef _LIST_HXX //autogen
#include <tools/list.hxx>
#endif
#ifndef _INETSES_HXX //autogen
#include <inet/inetsess.hxx>
#endif

class Downloader;
class ChannelAgentItem;
class ChannelItem;
class ChannelItemList;
class ChannelAgentItemList;
class ChannelTuner;
class ChannelApi;
class GetChannelObj;
class GetChObjList;
class NotifyItem;
class Date;
class Time;
class ResMgr;

struct UiAgentItem
{
    String      aName;
    ULONG       aUpdPeriode;
    DateTime    aLastDataDate;
    DateTime    aLastUpdDate;
    BOOL        bUnregister;
    BOOL        bIsEnabled;
};

DECLARE_LIST(UiAgentList, UiAgentItem*)
DECLARE_LIST(NotifyList, NotifyItem*)

#ifndef STRING_LIST
#define STRING_LIST
#define _TOOLS_STRINGLIST
#ifndef _SSTRING_HXX
#include <tools/sstring.hxx>
#endif
#endif

///////////////////////////////////////////////////////////////////////////////
//
//
#define JOBID_DOWNLOAD_AGENT        1
#define JOBID_UPDATE_AGENT          2
#define JOBID_CHECK_TRANSMITTER     3

struct BTXResponse
{
    USHORT  nJobId;
    BOOL    bFinish;
    ULONG   nTransferStatus;
    String  aLocalFileName;
};

///////////////////////////////////////////////////////////////////////////////
//
//
class ChannelList
{
    ResMgr*                     pResMgr;
    ChannelAgentItemList*       pAgentList;
    ChannelItemList*            pChannelList;
    NotifyList*                 pNotifyList;
    GetChObjList*               pGetChObjList;
    UiAgentList*                pUiAgentList;

    ChannelTuner*               pChannelTuner;

    String                      aAgentPath;
    AutoTimer                   aTimer;
    INetSessionRef              xINetSession;

    Link                        aNotifyPermissionHdl;
    Link                        aCheckFinishHdl;
    // wird von der ChannelList gehandelt; sollte ausgebaut werden; auch im SFX
    Link                        aAgentUpdateHdl;
    Downloader*                 pBTXDecoder;

    void                        MakeGodChannel(ChannelAgentItem* pAgent);
    void                        DeleteUiAgentList();

    BOOL                        StartAgent(ChannelAgentItem* pAgent);

    void                        DoNotifyAgents();
    void                        NotifyAgent(ChannelAgentItem* pAgent, ULONG nNotifyItemIdx);

    void                        UpdateAgent(ChannelAgentItem* pAgent, ULONG nNotifyItemIdx);
    void                        SendItemToTuner(ChannelItem* pItem);

    BOOL                        ParseDateTime(const String& rSrc, Date& rDate, Time& rTime);

    void                        UnZipAgent(ChannelAgentItem* pAgent);
    static void                 EnumFilesCallBack(char *pFile, void *pObject);

    DECL_LINK(CheckChannels, void*);
    DECL_LINK(CloseChannelObjEvt, void*);
    DECL_LINK(GetChannelObjNotify, GetChannelObj*);
protected:
    friend class ChannelApi;
    friend class ChannelTuner;

    ChannelItem*                GetChannelItemByName(const String& rName);
    ChannelAgentItem*           GetAgentItemByName(const String& rName);

    void                        ReadChannelList();
    void                        ReadAgentList();
    void                        WriteChannelItem(ChannelItem* pItem);
    void                        WriteAgentItem(ChannelAgentItem* pChAgent);
    void                        SetLastSuccUpdChannel(ChannelAgentItem* pChAgent);
    void                        SetLastSuccUpdAgent(ChannelAgentItem* pChAgent);
    void                        SetEnabledAgent(ChannelAgentItem* pChAgent);

    void                        DeleteAgentItem(ChannelAgentItem* pItem);
    void                        DeleteChannelItem(ChannelItem* pItem);
    void                        RegisterNewChannelItem(ChannelItem* pItem);

    void                        CancelBTX();
    Downloader*                 GetBTXDecoder() const { return pBTXDecoder; }
    ResMgr*                     GetResMgr() const { return pResMgr; }

    DECL_LINK(CheckBTXFinishHdl, void*);

    void                        NotifyTransmitterMsg(const String& rStr);

public:
    ChannelList(const String& rAgentPath);
    ~ChannelList();

    void                SubscribeNewAgent(const INetURLObject& rURL);

    void                SetINetSession(INetSession* pNewSess);
    void                SetBTXDecoder(Downloader* pDecoder);

    void                SetNotifyPermissionHdl(const Link& rHdl) { aNotifyPermissionHdl = rHdl; }
    void                SetAgentUpdateHdl(const Link& rHdl) { aAgentUpdateHdl = rHdl; }

    void                SetTimerInterval(ULONG nNew);
    void                StartCheckChannels();
    void                StopCheckChannels();

    void                CheckAgentNow(const String& rAgName, BOOL bCheckGOD = FALSE);
    void                SetCheckFinishHdl(const Link& rHdl) { aCheckFinishHdl = rHdl; }
    const Link&         GetCheckFinishHdl() const { return aCheckFinishHdl;};

    UiAgentList*        GetUiAgentList();
    void                JoinUiAgentList();
};

///////////////////////////////////////////////////////////////////////////////
//
//
class NotifyItem
{
    ChannelItem*    pChItem;

    USHORT          nGMTOffset;
    ULONG           nDateLastUpd;
    long            nTimeLastUpd;
    INetURLObject   aChObjURL;
    String          aChName;
public:
    NotifyItem( ChannelItem* pItem, short nGMTOff, ULONG nLastDate,
                ULONG nLastTime, const INetURLObject& rChObjURL,
                const String& rChName);
    ~NotifyItem();

    ChannelItem*        GetChannelItem() const          { return pChItem;       }

    const String&       GetChannelName() const          { return aChName;       }
    const INetURLObject GetChannelObjURL() const        { return aChObjURL;     }

    void                SetDateLastUpd(ULONG nNew)      { nDateLastUpd = nNew;  }
    ULONG               GetDateLastUpd() const          { return nDateLastUpd;  }

    void                SetTimeLastUpd(long nNew)       { nTimeLastUpd = nNew;  }
    long                GetTimeLastUpd() const          { return nTimeLastUpd;  }

    const String&       GetChAgentName() const;

};

#endif // _CHLIST_HXX

<commit_msg>INTEGRATION: CWS changefileheader (1.3.28); FILE MERGED 2008/04/01 15:19:25 thb 1.3.28.2: #i85898# Stripping all external header guards 2008/03/31 13:39:30 rt 1.3.28.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: chlist.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _CHLIST_HXX
#define _CHLIST_HXX

#include <tools/urlobj.hxx>
#include <tools/datetime.hxx>
#include <tools/string.hxx>
#include <vcl/timer.hxx>
#include <tools/list.hxx>
#ifndef _INETSES_HXX //autogen
#include <inet/inetsess.hxx>
#endif

class Downloader;
class ChannelAgentItem;
class ChannelItem;
class ChannelItemList;
class ChannelAgentItemList;
class ChannelTuner;
class ChannelApi;
class GetChannelObj;
class GetChObjList;
class NotifyItem;
class Date;
class Time;
class ResMgr;

struct UiAgentItem
{
    String      aName;
    ULONG       aUpdPeriode;
    DateTime    aLastDataDate;
    DateTime    aLastUpdDate;
    BOOL        bUnregister;
    BOOL        bIsEnabled;
};

DECLARE_LIST(UiAgentList, UiAgentItem*)
DECLARE_LIST(NotifyList, NotifyItem*)

#ifndef STRING_LIST
#define STRING_LIST
#define _TOOLS_STRINGLIST
#include <tools/sstring.hxx>
#endif

///////////////////////////////////////////////////////////////////////////////
//
//
#define JOBID_DOWNLOAD_AGENT        1
#define JOBID_UPDATE_AGENT          2
#define JOBID_CHECK_TRANSMITTER     3

struct BTXResponse
{
    USHORT  nJobId;
    BOOL    bFinish;
    ULONG   nTransferStatus;
    String  aLocalFileName;
};

///////////////////////////////////////////////////////////////////////////////
//
//
class ChannelList
{
    ResMgr*                     pResMgr;
    ChannelAgentItemList*       pAgentList;
    ChannelItemList*            pChannelList;
    NotifyList*                 pNotifyList;
    GetChObjList*               pGetChObjList;
    UiAgentList*                pUiAgentList;

    ChannelTuner*               pChannelTuner;

    String                      aAgentPath;
    AutoTimer                   aTimer;
    INetSessionRef              xINetSession;

    Link                        aNotifyPermissionHdl;
    Link                        aCheckFinishHdl;
    // wird von der ChannelList gehandelt; sollte ausgebaut werden; auch im SFX
    Link                        aAgentUpdateHdl;
    Downloader*                 pBTXDecoder;

    void                        MakeGodChannel(ChannelAgentItem* pAgent);
    void                        DeleteUiAgentList();

    BOOL                        StartAgent(ChannelAgentItem* pAgent);

    void                        DoNotifyAgents();
    void                        NotifyAgent(ChannelAgentItem* pAgent, ULONG nNotifyItemIdx);

    void                        UpdateAgent(ChannelAgentItem* pAgent, ULONG nNotifyItemIdx);
    void                        SendItemToTuner(ChannelItem* pItem);

    BOOL                        ParseDateTime(const String& rSrc, Date& rDate, Time& rTime);

    void                        UnZipAgent(ChannelAgentItem* pAgent);
    static void                 EnumFilesCallBack(char *pFile, void *pObject);

    DECL_LINK(CheckChannels, void*);
    DECL_LINK(CloseChannelObjEvt, void*);
    DECL_LINK(GetChannelObjNotify, GetChannelObj*);
protected:
    friend class ChannelApi;
    friend class ChannelTuner;

    ChannelItem*                GetChannelItemByName(const String& rName);
    ChannelAgentItem*           GetAgentItemByName(const String& rName);

    void                        ReadChannelList();
    void                        ReadAgentList();
    void                        WriteChannelItem(ChannelItem* pItem);
    void                        WriteAgentItem(ChannelAgentItem* pChAgent);
    void                        SetLastSuccUpdChannel(ChannelAgentItem* pChAgent);
    void                        SetLastSuccUpdAgent(ChannelAgentItem* pChAgent);
    void                        SetEnabledAgent(ChannelAgentItem* pChAgent);

    void                        DeleteAgentItem(ChannelAgentItem* pItem);
    void                        DeleteChannelItem(ChannelItem* pItem);
    void                        RegisterNewChannelItem(ChannelItem* pItem);

    void                        CancelBTX();
    Downloader*                 GetBTXDecoder() const { return pBTXDecoder; }
    ResMgr*                     GetResMgr() const { return pResMgr; }

    DECL_LINK(CheckBTXFinishHdl, void*);

    void                        NotifyTransmitterMsg(const String& rStr);

public:
    ChannelList(const String& rAgentPath);
    ~ChannelList();

    void                SubscribeNewAgent(const INetURLObject& rURL);

    void                SetINetSession(INetSession* pNewSess);
    void                SetBTXDecoder(Downloader* pDecoder);

    void                SetNotifyPermissionHdl(const Link& rHdl) { aNotifyPermissionHdl = rHdl; }
    void                SetAgentUpdateHdl(const Link& rHdl) { aAgentUpdateHdl = rHdl; }

    void                SetTimerInterval(ULONG nNew);
    void                StartCheckChannels();
    void                StopCheckChannels();

    void                CheckAgentNow(const String& rAgName, BOOL bCheckGOD = FALSE);
    void                SetCheckFinishHdl(const Link& rHdl) { aCheckFinishHdl = rHdl; }
    const Link&         GetCheckFinishHdl() const { return aCheckFinishHdl;};

    UiAgentList*        GetUiAgentList();
    void                JoinUiAgentList();
};

///////////////////////////////////////////////////////////////////////////////
//
//
class NotifyItem
{
    ChannelItem*    pChItem;

    USHORT          nGMTOffset;
    ULONG           nDateLastUpd;
    long            nTimeLastUpd;
    INetURLObject   aChObjURL;
    String          aChName;
public:
    NotifyItem( ChannelItem* pItem, short nGMTOff, ULONG nLastDate,
                ULONG nLastTime, const INetURLObject& rChObjURL,
                const String& rChName);
    ~NotifyItem();

    ChannelItem*        GetChannelItem() const          { return pChItem;       }

    const String&       GetChannelName() const          { return aChName;       }
    const INetURLObject GetChannelObjURL() const        { return aChObjURL;     }

    void                SetDateLastUpd(ULONG nNew)      { nDateLastUpd = nNew;  }
    ULONG               GetDateLastUpd() const          { return nDateLastUpd;  }

    void                SetTimeLastUpd(long nNew)       { nTimeLastUpd = nNew;  }
    long                GetTimeLastUpd() const          { return nTimeLastUpd;  }

    const String&       GetChAgentName() const;

};

#endif // _CHLIST_HXX

<|endoftext|>


<commit_before>#ifdef __linux__

#include <iostream>
#include "Renderer.hpp"
#include <unistd.h>
#include "GnuApp.hpp"

GnuApp* app;
bool shouldStop;
void Application::quitApplication(){
    shouldStop = true;

}

#define GetCurrentDir getcwd
std::string Application::getAppPath() const{
    char cCurrentPath[FILENAME_MAX];

    if(!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
    {
        return "Error";
    }

    cCurrentPath[sizeof(cCurrentPath) - 1] = '\0';

    return cCurrentPath;
}

void GnuApp::loop(){

    //Make sure when the user press the exit button.. it cleans everything up
    Atom              wm_protocols;
    Atom              wm_delete_window;
    wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
    wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
    XSetWMProtocols(dpy, win, &wm_delete_window, 1);
    XEvent  xev;
    for(;;){
        if(shouldStop){
            return; //stop when the app asks for it
        }
        while(XPending(dpy)){//Do not hang the app while waiting for input
            XNextEvent(dpy, &xev);

            if(xev.type == KeyPress) {
                this->mainApp->keyDown(xev.xkey.keycode);

            }else if (xev.xclient.message_type == wm_protocols &&
                xev.xclient.data.l[0] == wm_delete_window)  {
                return;
            }

        }
        //Render the program
        this->mainApp->gameLoop();
        glFlush();
        glXSwapBuffers(dpy, win);
    }

}

GnuApp::GnuApp(){
    shouldStop = false;
    GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };

    this->dpy = XOpenDisplay(nullptr);
    if(this->dpy == nullptr) {
        std::cout << "could not connect to x server\n";
        return;
    }
    this->root = DefaultRootWindow(this->dpy);

    XVisualInfo *vi;
    vi = glXChooseVisual(this->dpy, 0, att);

    if(vi == nullptr) {
        std::cout << "no appropiate visual found\n";
        return;
    }
    Colormap    cmap;

    cmap = XCreateColormap(this->dpy, this->root, vi->visual, AllocNone);
    XSetWindowAttributes swa;
    swa.colormap = cmap;
    swa.event_mask = ExposureMask | KeyPressMask;

    XWindowAttributes xwa;
    XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &xwa);

    win = XCreateWindow(dpy, root, 0, 0, xwa.width, xwa.height, 0, vi->depth, InputOutput, vi->visual,CWColormap | CWEventMask, &swa);

    XMapRaised(dpy,root);
    XMapWindow(dpy, win);
    XStoreName(dpy, win, "BlockSnake");

    //Setup opengl
    glc = glXCreateContext(dpy, vi, nullptr, GL_TRUE);
    glXMakeCurrent(dpy, win, glc);

    //initialize
    GLenum err = glewInit();
    if (GLEW_OK != err){
        std::cout << "an error has occured : " << glewGetErrorString(err) << "\n";
        std::cout << "closing blocksnake\n";
        return;
    }

    if (!GLEW_VERSION_4_1){
        std::cout << "Blocksnake requires at least opengl 4.1. \n";
        std::cout << "It is recommended to use the propieriatary versions of the video card drivers\nClosing the app\n";
        return;

    }

    this->mainApp = new Application(xwa.width,xwa.height);

    this->loop();

}

GnuApp::~GnuApp(){

    //Close the window nice and neat
    glXMakeCurrent(dpy, None, nullptr);
    glXDestroyContext(dpy, glc);
    XDestroyWindow(dpy, win);
    XCloseDisplay(dpy);
    //When the the app doesnt't work properly the mainapp is a null
    if(mainApp != nullptr){
        delete this->mainApp;
    }
}

int main(int argc, char** argv){
    app = new GnuApp();
    delete app;
}

#endif
<commit_msg>Fixed OpenGL on GNU/Linux<commit_after>#ifdef __linux__

#include <iostream>
#include "Renderer.hpp"
#include <unistd.h>
#include "GnuApp.hpp"

typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);

GnuApp* app;
bool shouldStop;
void Application::quitApplication(){
    shouldStop = true;

}

#define GetCurrentDir getcwd
std::string Application::getAppPath() const{
    char cCurrentPath[FILENAME_MAX];

    if(!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
    {
        return "Error";
    }

    cCurrentPath[sizeof(cCurrentPath) - 1] = '\0';
    return cCurrentPath;
}

void GnuApp::loop(){

    //Make sure when the user press the exit button.. it cleans everything up
    Atom              wm_protocols;
    Atom              wm_delete_window;
    wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
    wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
    XSetWMProtocols(dpy, win, &wm_delete_window, 1);
    XEvent  xev;
    for(;;){
        if(shouldStop){
            return; //stop when the app asks for it
        }
        while(XPending(dpy)){//Do not hang the app while waiting for input
            XNextEvent(dpy, &xev);

            if(xev.type == KeyPress) {
                this->mainApp->keyDown(xev.xkey.keycode);

            }else if (xev.xclient.message_type == wm_protocols &&
                xev.xclient.data.l[0] ==(unsigned int) wm_delete_window)  {
                return;
            }

        }
        //Render the program
        this->mainApp->gameLoop();
        glFlush();
        glXSwapBuffers(dpy, win);
    }

}

GnuApp::GnuApp(){
    shouldStop = false;

    static int visual_attribs[] ={
        GLX_X_RENDERABLE    , True,
        GLX_DRAWABLE_TYPE   , GLX_WINDOW_BIT,
        GLX_RENDER_TYPE     , GLX_RGBA_BIT,
        GLX_X_VISUAL_TYPE   , GLX_TRUE_COLOR,
        GLX_RED_SIZE        , 8,
        GLX_GREEN_SIZE      , 8,
        GLX_BLUE_SIZE       , 8,
        GLX_ALPHA_SIZE      , 8,
        GLX_DEPTH_SIZE      , 24,
        GLX_STENCIL_SIZE    , 8,
        GLX_DOUBLEBUFFER    , True,
        None
    };

    this->dpy = XOpenDisplay(nullptr);
    if(this->dpy == nullptr) {
        std::cout << "could not connect to x server\n";
        return;
    }
    this->root = DefaultRootWindow(this->dpy);

    int fbcount;
    GLXFBConfig *fbc = glXChooseFBConfig( dpy, DefaultScreen( dpy ),
    visual_attribs, &fbcount );
    const GLXFBConfig bestFbc = fbc[0];

    XVisualInfo *vi = glXGetVisualFromFBConfig( dpy, bestFbc );
    root = DefaultRootWindow(dpy);

    if(vi == nullptr) {
        std::cout << "no appropiate visual found\n";
        return;
    }
    Colormap    cmap;

    cmap = XCreateColormap(this->dpy, this->root, vi->visual, AllocNone);
    XSetWindowAttributes swa;
    swa.colormap = cmap;
    swa.event_mask = ExposureMask | KeyPressMask;

    XWindowAttributes xwa;
    XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &xwa);

    this->win = XCreateWindow(dpy, root, 0, 0, xwa.width, xwa.height, 0, vi->depth, InputOutput, vi->visual,CWColormap | CWEventMask, &swa);

    XMapRaised(this->dpy,this->root);
    XMapWindow(this->dpy, this->win);
    XStoreName(this->dpy, this->win, "BlockSnake");
    int attribs[] = {
        GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
        GLX_CONTEXT_MINOR_VERSION_ARB, 0,
        0
    };

    glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
    glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");

   //Setup opengl
    this->glc = glXCreateContextAttribsARB(dpy, *fbc, nullptr, true, attribs);
  //  glc = glXCreateContext(dpy, vi, nullptr, GL_TRUE);
    glXMakeCurrent(dpy, win, glc);

    //initialize
    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if (GLEW_OK != err){
        std::cout << "an error has occured : " << glewGetErrorString(err) << "\n";
        std::cout << "closing blocksnake\n";
        return;
    }

    //std::cout << glewGetString(GLEW_VERSION)) << "\n";

    if (!GLEW_VERSION_4_1){
        std::cout << "Blocksnake requires at least opengl 4.1. \n";
        std::cout << "It is recommended to use the propieriatary versions of the video card drivers\nClosing the app\n";
        return;

    }

    this->mainApp = new Application(xwa.width,xwa.height);

    this->loop();

}

GnuApp::~GnuApp(){

    //Close the window nice and neat
    glXMakeCurrent(dpy, None, nullptr);
    glXDestroyContext(dpy, glc);
    XDestroyWindow(dpy, win);
    XCloseDisplay(dpy);
    //When the the app doesnt't work properly the mainapp is a null
    if(mainApp != nullptr){
        delete this->mainApp;
    }
}

int main(int argc, char** argv){
    app = new GnuApp();
    delete app;
}

#endif
<|endoftext|>