<commit_before>/** @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Vuzix Corporation.
//
// 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.

// Internal Includes
#include <osvr/PluginKit/PluginKit.h>
#include <osvr/PluginKit/TrackerInterfaceC.h>
#include <osvr/Util/PlatformConfig.h>
#include "DriverWrapper.h"

// Generated JSON header file
#include "com_osvr_Vive_json.h"

// Library/third-party includes
#include <math.h>
#include <openvr_driver.h>

// Standard includes
#include <iostream>
#include <memory>
#include <vector>

using namespace vr;

// Anonymous namespace to avoid symbol collision
namespace {
static const auto PREFIX = "PLUGIN: ";
class ViveDriverHost : public ServerDriverHost {

  public:
    ViveDriverHost::ViveDriverHost(OSVR_PluginRegContext ctx) {
        /// Create the initialization options
        OSVR_DeviceInitOptions opts = osvrDeviceCreateInitOptions(ctx);

        osvrDeviceTrackerConfigure(opts, &m_tracker);

        /// Create the sync device token with the options
        m_dev.initSync(ctx, "Vive", opts);

        /// Send JSON descriptor
        m_dev.sendJsonDescriptor(com_osvr_Vive_json);

        /// Register update callback
        m_dev.registerUpdateCallback(this);
    }

    OSVR_ReturnCode ViveDriverHost::update() { return OSVR_RETURN_SUCCESS; }

    void ViveDriverHost::TrackedDevicePoseUpdated(uint32_t unWhichDevice,
                                                  const DriverPose_t &newPose) {

        std::cout << PREFIX << "TrackedDevicePoseUpdated(" << unWhichDevice
                  << ", newPose)" << std::endl;

        OSVR_TimeValue now;
        osvrTimeValueGetNow(&now);
        if (newPose.poseIsValid) {
            OSVR_PoseState pose;
            pose.translation.data[0] = newPose.vecPosition[0];
            pose.translation.data[1] = newPose.vecPosition[1];
            pose.translation.data[2] = newPose.vecPosition[2];
            pose.rotation.data[0] = newPose.qRotation.w;
            pose.rotation.data[1] = newPose.qRotation.x;
            pose.rotation.data[2] = newPose.qRotation.y;
            pose.rotation.data[3] = newPose.qRotation.z;

            osvrDeviceTrackerSendPoseTimestamped(m_dev, m_tracker, &pose,
                                                 unWhichDevice, &now);
        }
    }

    void DeviceDescriptorUpdated(std::string const &json){

        m_dev.sendJsonDescriptor(json);
    }

  private:
    osvr::pluginkit::DeviceToken m_dev;
    OSVR_TrackerDeviceInterface m_tracker;
};

class HardwareDetection {
  public:
    HardwareDetection() {}
    OSVR_ReturnCode operator()(OSVR_PluginRegContext ctx) {

        std::cout << "PLUGIN: Got a hardware detection request" << std::endl;

        if (m_found) {
            return OSVR_RETURN_SUCCESS;
        }

        auto vive = osvr::vive::DriverWrapper(new ViveDriverHost(ctx));

        if (vive.foundDriver()) {
            std::cout << PREFIX << "Found the Vive driver at "
                      << vive.getDriverFileLocation() << std::endl;
        }

        if (!vive.haveDriverLoaded()) {
            std::cout << PREFIX << "Could not open driver." << std::endl;
            return OSVR_RETURN_FAILURE;
        }

        if (vive.foundConfigDirs()) {
            std::cout << PREFIX
                      << "Driver config dir is: " << vive.getDriverConfigDir()
                      << std::endl;
        }

        if (!vive) {
            std::cerr << PREFIX
                      << "Error in first-stage Vive driver startup. Exiting"
                      << std::endl;
            return OSVR_RETURN_FAILURE;
        }

        if (!vive.isHMDPresent()) {
            std::cerr << PREFIX
                      << "Driver loaded, but no Vive is connected. Exiting"
                      << std::endl;
            return OSVR_RETURN_FAILURE;
        }

        std::cout << PREFIX << "Vive is connected." << std::endl;

        if (!vive.startServerDeviceProvider()) {
            std::cerr
                << PREFIX
                << "Error: could not start the server device provider in the "
                   "Vive driver. Exiting."
                << std::endl;
            return OSVR_RETURN_FAILURE;
        }

        /// Power the system up.
        vive.serverDevProvider().LeaveStandby();

        auto handleNewDevice = [&](const char *serialNum) {
            auto dev = vive.serverDevProvider().FindTrackedDeviceDriver(
                serialNum, vr::ITrackedDeviceServerDriver_Version);
            if (!dev) {
                std::cout
                    << PREFIX
                    << "Couldn't find the corresponding device driver for "
                    << serialNum << std::endl;
                return false;
            }
            auto ret = vive.addAndActivateDevice(dev);
            if (!ret.first) {
                std::cout << PREFIX << "Device with serial number " << serialNum
                          << " couldn't be added to the devices vector."
                          << std::endl;
                return false;
            }
            std::cout << "\n" << PREFIX << "Device with s/n " << serialNum
                      << " activated, assigned ID " << ret.second << std::endl;
            return true;
        };

        vive.driverHost().onTrackedDeviceAdded = handleNewDevice;

        {
            auto numDevices = vive.serverDevProvider().GetTrackedDeviceCount();
            std::cout << PREFIX << "Got " << numDevices
                      << " tracked devices at startup" << std::endl;
            for (decltype(numDevices) i = 0; i < numDevices; ++i) {
                auto dev = vive.serverDevProvider().GetTrackedDeviceDriver(
                    i, vr::ITrackedDeviceServerDriver_Version);
                vive.addAndActivateDevice(dev);
                std::cout << PREFIX << "Device " << i << std::endl;
                addDeviceType(dev);
            }
        }
        return OSVR_RETURN_SUCCESS;
    }

    static void addDeviceType(vr::ITrackedDeviceServerDriver *dev) {
        // @todo add device type (controller, tracker) to generate
        // dynamic device descriptor
    }

  private:
    bool m_found;
    std::vector<std::string> m_deviceTypes;
};
} // namespace

OSVR_PLUGIN(com_osvr_Vive) {
    osvr::pluginkit::PluginContext context(ctx);

    /// Register a detection callback function object.
    context.registerHardwareDetectCallback(new HardwareDetection());

    return OSVR_RETURN_SUCCESS;
}<commit_msg>A little plugin re-structuring.<commit_after>/** @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Vuzix Corporation.
//
// 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.

// Internal Includes
#include "DriverWrapper.h"
#include <osvr/PluginKit/PluginKit.h>
#include <osvr/PluginKit/TrackerInterfaceC.h>
#include <osvr/Util/PlatformConfig.h>

// Generated JSON header file
#include "com_osvr_Vive_json.h"

// Library/third-party includes
#include <math.h>
#include <openvr_driver.h>

// Standard includes
#include <iostream>
#include <memory>
#include <vector>

using namespace vr;

// Anonymous namespace to avoid symbol collision
namespace {
static const auto PREFIX = "[OSVR-Vive] ";
class ViveDriverHost : public ServerDriverHost {
  public:
    /// @return false if we failed to start up for some reason.
    bool start(OSVR_PluginRegContext ctx, osvr::vive::DriverWrapper &&inVive) {
        if (!inVive) {
            std::cerr << PREFIX << "Error: called ViveDriverHost::start() with "
                                   "an invalid vive object!"
                      << std::endl;
        }
        /// Take ownership of the Vive.
        m_vive.reset(new osvr::vive::DriverWrapper(std::move(inVive)));

        /// Finish setting up the Vive.
        if (!m_vive->startServerDeviceProvider()) {
            std::cerr
                << PREFIX
                << "Error: could not start the server device provider in the "
                   "Vive driver. Exiting."
                << std::endl;
            return false;
        }

        /// Power the system up.
        m_vive->serverDevProvider().LeaveStandby();

        auto handleNewDevice =
            [&](const char *serialNum) {
                auto dev = m_vive->serverDevProvider().FindTrackedDeviceDriver(
                    serialNum, vr::ITrackedDeviceServerDriver_Version);
                if (!dev) {
                    std::cout
                        << PREFIX
                        << "Couldn't find the corresponding device driver for "
                        << serialNum << std::endl;
                    return false;
                }
                auto ret = m_vive->addAndActivateDevice(dev);
                if (!ret.first) {
                    std::cout << PREFIX << "Device with serial number "
                              << serialNum
                              << " couldn't be added to the devices vector."
                              << std::endl;
                    return false;
                }
                std::cout << "\n"
                          << PREFIX << "Device with s/n " << serialNum
                          << " activated, assigned ID " << ret.second
                          << std::endl;
                return true;
            };

        m_vive->driverHost().onTrackedDeviceAdded = handleNewDevice;

        {
            auto numDevices =
                m_vive->serverDevProvider().GetTrackedDeviceCount();
            std::cout << PREFIX << "Got " << numDevices
                      << " tracked devices at startup" << std::endl;
            for (decltype(numDevices) i = 0; i < numDevices; ++i) {
                auto dev = m_vive->serverDevProvider().GetTrackedDeviceDriver(
                    i, vr::ITrackedDeviceServerDriver_Version);
                m_vive->addAndActivateDevice(dev);
                std::cout << PREFIX << "Device " << i << std::endl;
#if 0
                addDeviceType(dev);
#endif
            }
        }

        /// Finish setting this up as an OSVR device.
        /// Create the initialization options
        OSVR_DeviceInitOptions opts = osvrDeviceCreateInitOptions(ctx);

        osvrDeviceTrackerConfigure(opts, &m_tracker);

        /// Create the sync device token with the options
        m_dev.initSync(ctx, "Vive", opts);

        /// Send JSON descriptor
        m_dev.sendJsonDescriptor(com_osvr_Vive_json);

        /// Register update callback
        m_dev.registerUpdateCallback(this);

        return true;
    }

    OSVR_ReturnCode update() {
        m_vive->serverDevProvider().RunFrame();
        return OSVR_RETURN_SUCCESS;
    }

    void TrackedDevicePoseUpdated(uint32_t unWhichDevice,
                                  const DriverPose_t &newPose) override {

        std::cout << PREFIX << "TrackedDevicePoseUpdated(" << unWhichDevice
                  << ", newPose)" << std::endl;

        OSVR_TimeValue now;
        osvrTimeValueGetNow(&now);
        if (newPose.poseIsValid) {
            OSVR_PoseState pose;
            pose.translation.data[0] = newPose.vecPosition[0];
            pose.translation.data[1] = newPose.vecPosition[1];
            pose.translation.data[2] = newPose.vecPosition[2];
            pose.rotation.data[0] = newPose.qRotation.w;
            pose.rotation.data[1] = newPose.qRotation.x;
            pose.rotation.data[2] = newPose.qRotation.y;
            pose.rotation.data[3] = newPose.qRotation.z;

            osvrDeviceTrackerSendPoseTimestamped(m_dev, m_tracker, &pose,
                                                 unWhichDevice, &now);
        }
    }

    void DeviceDescriptorUpdated(std::string const &json) {

        m_dev.sendJsonDescriptor(json);
    }

  private:
    osvr::pluginkit::DeviceToken m_dev;
    OSVR_TrackerDeviceInterface m_tracker;
    std::unique_ptr<osvr::vive::DriverWrapper> m_vive;
};
using DriverHostPtr = std::unique_ptr<ViveDriverHost>;

class HardwareDetection {

  public:
    HardwareDetection() {}
    OSVR_ReturnCode operator()(OSVR_PluginRegContext ctx) {

        std::cout << PREFIX << "Got a hardware detection request" << std::endl;

        if (m_driverHost) {
            // Already found a Vive.
            /// @todo what are the semantics of the return value from a hardware
            /// detect?
            return OSVR_RETURN_SUCCESS;
        }

        {
            DriverHostPtr host(new ViveDriverHost);

            auto vive = osvr::vive::DriverWrapper(host.get());

            if (vive.foundDriver()) {
                std::cout << PREFIX << "Found the Vive driver at "
                          << vive.getDriverFileLocation() << std::endl;
            }

            if (!vive.haveDriverLoaded()) {
                std::cout << PREFIX << "Could not open driver." << std::endl;
                return OSVR_RETURN_FAILURE;
            }

            if (vive.foundConfigDirs()) {
                std::cout << PREFIX << "Driver config dir is: "
                          << vive.getDriverConfigDir() << std::endl;
            }

            if (!vive) {
                std::cerr << PREFIX
                          << "Error in first-stage Vive driver startup. Exiting"
                          << std::endl;
                return OSVR_RETURN_FAILURE;
            }

            if (!vive.isHMDPresent()) {
                std::cerr << PREFIX
                          << "Driver loaded, but no Vive is connected. Exiting"
                          << std::endl;
                return OSVR_RETURN_FAILURE;
            }

            std::cout << PREFIX << "Vive is connected." << std::endl;

            /// Hand the Vive object off to the OSVR driver.
            auto startResult = host->start(ctx, std::move(vive));
            if (startResult) {
                /// and it started up the rest of the way just fine!
                /// We'll keep the driver around!
                m_driverHost = std::move(host);
                std::cout << PREFIX
                          << "Vive driver finished startup successfully!"
                          << std::endl;
                return OSVR_RETURN_SUCCESS;
            }
        }

        std::cout << PREFIX << "Vive driver startup failed somewhere, "
                               "unloading to perhaps try again later."
                  << std::endl;
        return OSVR_RETURN_FAILURE;
    }

    static void addDeviceType(vr::ITrackedDeviceServerDriver *dev) {
        // @todo add device type (controller, tracker) to generate
        // dynamic device descriptor
    }

  private:
    std::vector<std::string> m_deviceTypes;
    /// This is the OSVR driver object, which also serves as the "SteamVR"
    /// driver host. We can only run one Vive at a time.
    std::unique_ptr<ViveDriverHost> m_driverHost;
};
} // namespace

OSVR_PLUGIN(com_osvr_Vive) {
    osvr::pluginkit::PluginContext context(ctx);

    /// Register a detection callback function object.
    context.registerHardwareDetectCallback(new HardwareDetection());

    return OSVR_RETURN_SUCCESS;
}
<|endoftext|>


<commit_before>#include "BorderTheme.hh"

BorderTheme::BorderTheme(FbTk::Theme &theme, const std::string &name,
                         const std::string &altname):
    m_width(theme, name + ".borderWidth", altname + ".BorderWidth"),
    m_color(theme, name + ".borderColor", altname + ".BorderColor") {
}
<commit_msg>default width<commit_after>#include "BorderTheme.hh"

BorderTheme::BorderTheme(FbTk::Theme &theme, const std::string &name,
                         const std::string &altname):
    m_width(theme, name + ".borderWidth", altname + ".BorderWidth"),
    m_color(theme, name + ".borderColor", altname + ".BorderColor") {

    *m_width = 0;
}
<|endoftext|>


<commit_before><commit_msg>Tidies up condition check<commit_after><|endoftext|>


<commit_before>#define LOG_TAG "silk-h264-enc"
#include "SimpleH264Encoder.h"

#include <queue>

#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MetaData.h>
// This is an ugly hack. We forked this from libstagefright
// so we can trigger key frames and adjust bitrate
#include "MediaCodecSource.h"
#include <media/openmax/OMX_IVCommon.h>
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <utils/Thread.h>
#include <utils/SystemClock.h>
#include <utils/Log.h>

using namespace android;

static const char* kMimeTypeAvc = "video/avc";
static const uint32_t kColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
static const int32_t kIFrameInterval = 60;

class SingleBufferMediaSource: public MediaSource {
 public:
  SingleBufferMediaSource(int width, int height)
      : mBuffer(0), mHaveNextBuffer(false) {
    mMetaData = new MetaData();
    mMetaData->setInt32(kKeyWidth, width);
    mMetaData->setInt32(kKeyHeight, height);
    mMetaData->setInt32(kKeyStride, width);
    mMetaData->setInt32(kKeySliceHeight, height);
    mMetaData->setInt32(kKeyColorFormat, kColorFormat);
    mMetaData->setCString(kKeyMIMEType, "video/raw");
  }

  status_t start(MetaData *params = NULL) override {
    (void) params;
    return 0;
  }

  status_t stop() override {
    nextFrame(nullptr); // Unclog read
    return 0;
  }

  sp<MetaData> getFormat() override {
    return mMetaData;
  }

  status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL) override {
    Mutex::Autolock autolock(mBufferLock);

    if (options != NULL) {
      ALOGW("ReadOptions not supported");
      return ERROR_END_OF_STREAM;
    }

    while (!mHaveNextBuffer) {
      mBufferCondition.wait(mBufferLock);
    }
    mHaveNextBuffer = false;

    if (!mBuffer) {
      ALOGI("End of stream");
      return ERROR_END_OF_STREAM;
    }

    *buffer = mBuffer;
    mBuffer = nullptr;
    return OK;
  }

  void nextFrame(android::MediaBuffer *yuv420SemiPlanarFrame) {
    Mutex::Autolock autolock(mBufferLock);
    if (mBuffer) {
      mBuffer->release();
    }
    mBuffer = yuv420SemiPlanarFrame;
    mHaveNextBuffer = true;
    mBufferCondition.signal();
  }

 private:
  MediaBuffer *mBuffer;
  bool mHaveNextBuffer;
  Mutex mBufferLock;
  Condition mBufferCondition;

  sp<MetaData> mMetaData;
};

class SimpleH264EncoderImpl: public SimpleH264Encoder {
 public:
  static SimpleH264Encoder *Create(int width,
                                   int height,
                                   int maxBitrateK,
                                   int targetFps,
                                   FrameOutCallback frameOutCallback,
                                   void *frameOutUserData);
  virtual ~SimpleH264EncoderImpl() {
    stop();
  }
  virtual void setBitRate(int bitrateK);
  virtual void requestKeyFrame();
  virtual void nextFrame(void *yuv420SemiPlanarFrame,
                         void (*deallocator)(void *),
                         InputFrameInfo& inputFrameInfo);
  virtual void stop();

 private:
  class FramePuller: public android::Thread {
   public:
    FramePuller(SimpleH264EncoderImpl *encoder): encoder(encoder) {};
   private:
    bool threadLoop() override {
      return encoder->threadLoop();
    }
    SimpleH264EncoderImpl *encoder;
  };
  friend class FramePuller;

  SimpleH264EncoderImpl(int width,
                        int height,
                        int maxBitrateK,
                        FrameOutCallback frameOutCallback,
                        void *frameOutUserData);

  bool init(int targetFps);
  bool threadLoop();

  int width;
  int height;
  int maxBitrateK;
  FrameOutCallback frameOutCallback;
  void *frameOutUserData;
  uint8_t *codecConfig;
  int codecConfigLength;

  uint8_t *encodedFrame;
  int encodedFrameMaxLength;

  int64_t lastCaptureTimeMs;

  android::sp<android::ALooper> looper;
  android::sp<android::MediaCodecSource> mediaCodecSource;
  android::sp<SingleBufferMediaSource> frameQueue;
  android::sp<android::Thread> framePuller;
  std::queue<InputFrameInfo> frameInfo;
  android::Mutex mutex;
};

SimpleH264Encoder *SimpleH264EncoderImpl::Create(int width,
                                                 int height,
                                                 int maxBitrateK,
                                                 int targetFps,
                                                 FrameOutCallback frameOutCallback,
                                                 void *frameOutUserData) {
  SimpleH264EncoderImpl *enc = new SimpleH264EncoderImpl(
    width,
    height,
    maxBitrateK,
    frameOutCallback,
    frameOutUserData
  );

  if (!enc->init(targetFps)) {
    delete enc;
    enc = nullptr;
  };

  return enc;

bail:
  delete enc;
  return nullptr;
}

SimpleH264EncoderImpl::SimpleH264EncoderImpl(int width,
                                             int height,
                                             int maxBitrateK,
                                             FrameOutCallback frameOutCallback,
                                             void *frameOutUserData)
    : width(width),
      height(height),
      maxBitrateK(maxBitrateK),
      frameOutCallback(frameOutCallback),
      frameOutUserData(frameOutUserData),
      codecConfig(nullptr),
      codecConfigLength(0),
      encodedFrame(nullptr),
      encodedFrameMaxLength(0),
      lastCaptureTimeMs(-1) {

  frameQueue = new SingleBufferMediaSource(width, height);
  looper = new ALooper;
  looper->setName("SimpleH264Encoder");
  framePuller = new SimpleH264EncoderImpl::FramePuller(this);
};

bool SimpleH264EncoderImpl::init(int targetFps) {
  sp<MetaData> meta = frameQueue->getFormat();
  int32_t width, height, stride, sliceHeight, colorFormat;
  CHECK(meta->findInt32(kKeyWidth, &width));
  CHECK(meta->findInt32(kKeyHeight, &height));
  CHECK(meta->findInt32(kKeyStride, &stride));
  CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
  CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));

  sp<AMessage> format = new AMessage();
  format->setInt32("width", width);
  format->setInt32("height", height);
  format->setInt32("stride", stride);
  format->setInt32("slice-height", sliceHeight);
  format->setInt32("color-format", colorFormat);

  format->setString("mime", kMimeTypeAvc);
  format->setInt32("bitrate", maxBitrateK * 1024);
  format->setInt32("bitrate-mode", OMX_Video_ControlRateConstant);
  format->setFloat("frame-rate", targetFps);
  format->setInt32("i-frame-interval", kIFrameInterval);

  looper->start();
  mediaCodecSource = MediaCodecSource::Create(
    looper,
    format,
    frameQueue,
#ifdef TARGET_GE_MARSHMALLOW
    NULL,
#endif
    0
  );
  if (mediaCodecSource == nullptr) {
    ALOGE("Unable to create encoder");
    return false;
  }

  status_t err;
  err = mediaCodecSource->start();
  if (err != 0) {
    ALOGE("Unable to start encoder");
    return false;
  }
  err = framePuller->run();
  if (err != 0) {
    ALOGE("Unable to start puller thread");
    return false;
  }
  return true;
}

void SimpleH264EncoderImpl::setBitRate(int bitrateK) {
  Mutex::Autolock autolock(mutex);
  if (mediaCodecSource != nullptr) {
    mediaCodecSource->videoBitRate(
      (bitrateK < maxBitrateK ? bitrateK : maxBitrateK) * 1024
    );
  }
}

void SimpleH264EncoderImpl::requestKeyFrame() {
  Mutex::Autolock autolock(mutex);
  if (mediaCodecSource != nullptr) {
    mediaCodecSource->requestIDRFrame();
  }
}

class UserMediaBuffer: public android::MediaBuffer {
 public:
  UserMediaBuffer(void *data, size_t size, void (*deallocator)(void *))
    : MediaBuffer(data, size),
      deallocator(deallocator) {}

 protected:
  ~UserMediaBuffer() {
    deallocator(data());
  }
 private:
  void (*deallocator)(void *);
};

void SimpleH264EncoderImpl::nextFrame(void *yuv420SemiPlanarFrame,
                                      void (*deallocator)(void *),
                                      InputFrameInfo& inputFrameInfo) {
  Mutex::Autolock autolock(mutex);
  if (frameQueue == nullptr) {
    ALOGI("Stopped, ignoring frame");
    return;
  }

  auto buffer = new UserMediaBuffer(
    yuv420SemiPlanarFrame,
    height * width * 3 / 2,
    deallocator
  );
  buffer->meta_data()->setInt64(kKeyTime, inputFrameInfo.captureTimeMs * 1000);
  frameInfo.push(inputFrameInfo);
  frameQueue->nextFrame(buffer);
}

void SimpleH264EncoderImpl::stop() {
  Mutex::Autolock autolock(mutex);
  framePuller->requestExit();

  if (mediaCodecSource != nullptr) {
    mediaCodecSource->stop();
  }

  if (frameQueue != nullptr) {
    frameQueue->stop();
  }

  if (looper != nullptr) {
    looper->stop();
  }

  if (framePuller->isRunning()) {
    framePuller->join();
    CHECK(!framePuller->isRunning());
  }

  frameQueue = nullptr;
  mediaCodecSource = nullptr;
  looper = nullptr;

  delete [] codecConfig;
  codecConfig = nullptr;
  codecConfigLength = 0;

  delete [] encodedFrame;
  encodedFrame = nullptr;
  encodedFrameMaxLength = 0;
}

bool SimpleH264EncoderImpl::threadLoop() {
  MediaBuffer *buffer;

  status_t err = mediaCodecSource->read(&buffer);
  if (err != OK) {
    ALOGE("Error reading from source: %d", err);
    return false;
  }

  if (buffer == NULL) {
    ALOGE("Failed to get buffer from source");
    return false;
  }

  int32_t isCodecConfig = 0;
  int32_t isIFrame = 0;
  int64_t timestamp = 0;

  if (buffer->meta_data() == NULL) {
    ALOGE("Failed to get buffer meta_data()");
    return false;
  }

  buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig);
  buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isIFrame);

  if (isCodecConfig) {
    if (codecConfig) {
      delete [] codecConfig;
    }
    codecConfigLength = buffer->range_length();
    codecConfig = new uint8_t[codecConfigLength];
    memcpy(codecConfig,
      static_cast<uint8_t*>(buffer->data()) + buffer->range_offset(),
      codecConfigLength
    );

  } else {
    EncodedFrameInfo info;
    bool drop = false;
    info.userData = frameOutUserData;
    info.keyFrame = isIFrame;
    int64_t timeMicro = 0;
    buffer->meta_data()->findInt64(kKeyTime, &timeMicro);
    info.input.captureTimeMs = timeMicro / 1000;

    if (lastCaptureTimeMs > -1) {
      int frameDiff = static_cast<int>(info.input.captureTimeMs - lastCaptureTimeMs);
      ALOGE("Frame. iframe=%d delay=%dms", isIFrame, frameDiff);
    }
    lastCaptureTimeMs = info.input.captureTimeMs;

    {
      Mutex::Autolock autolock(mutex);
      for (;;) {
        if (frameInfo.empty()) {
          ALOGE("frameInfo exhausted. Encoder broken?");
          drop = true;
          break;
        }
        InputFrameInfo& ifi = frameInfo.front();
        if (ifi.captureTimeMs != info.input.captureTimeMs) {
          ALOGE("Unknown frame. Encoder broken?");
          frameInfo.pop();
          continue;
        }
        info.input = ifi;
        frameInfo.pop();
        break;
      }
    }

    if (!drop) {
      if (isIFrame) {
        int encodedFrameLength = codecConfigLength + buffer->range_length();

        if (encodedFrame == nullptr ||
            encodedFrameMaxLength < encodedFrameLength) {
          encodedFrameMaxLength = encodedFrameLength + encodedFrameLength / 2;
          delete [] encodedFrame;
          encodedFrame = new uint8_t[encodedFrameMaxLength];
        }

        // Always send codecConfig with an i-frame to make the stream more
        // resilient
        if (codecConfig) {
          memcpy(encodedFrame, codecConfig, codecConfigLength);
        }
        memcpy(
          encodedFrame + codecConfigLength,
          static_cast<uint8_t*>(buffer->data()) + buffer->range_offset(),
          buffer->range_length()
        );
        info.encodedFrame = encodedFrame;
        info.encodedFrameLength = encodedFrameLength;
      } else {
        info.encodedFrame = static_cast<uint8_t*>(buffer->data()) + buffer->range_offset();
        info.encodedFrameLength = buffer->range_length();
      }
      frameOutCallback(info);
    }
  }

  buffer->release();
  return true;
}

SimpleH264Encoder *SimpleH264Encoder::Create(int width,
                                             int height,
                                             int maxBitrateK,
                                             int targetFps,
                                             FrameOutCallback frameOutCallback,
                                             void *frameOutUserData) {
  return SimpleH264EncoderImpl::Create(
    width,
    height,
    maxBitrateK,
    targetFps,
    frameOutCallback,
    frameOutUserData
  );
}

<commit_msg>Clean up timestamp logging<commit_after>#define LOG_TAG "silk-h264-enc"
#include "SimpleH264Encoder.h"

#include <queue>

#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MetaData.h>
// This is an ugly hack. We forked this from libstagefright
// so we can trigger key frames and adjust bitrate
#include "MediaCodecSource.h"
#include <media/openmax/OMX_IVCommon.h>
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <utils/Thread.h>
#include <utils/SystemClock.h>
#include <utils/Log.h>

using namespace android;

static const char* kMimeTypeAvc = "video/avc";
static const uint32_t kColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
static const int32_t kIFrameInterval = 60;

class SingleBufferMediaSource: public MediaSource {
 public:
  SingleBufferMediaSource(int width, int height)
      : mBuffer(0), mHaveNextBuffer(false) {
    mMetaData = new MetaData();
    mMetaData->setInt32(kKeyWidth, width);
    mMetaData->setInt32(kKeyHeight, height);
    mMetaData->setInt32(kKeyStride, width);
    mMetaData->setInt32(kKeySliceHeight, height);
    mMetaData->setInt32(kKeyColorFormat, kColorFormat);
    mMetaData->setCString(kKeyMIMEType, "video/raw");
  }

  status_t start(MetaData *params = NULL) override {
    (void) params;
    return 0;
  }

  status_t stop() override {
    nextFrame(nullptr); // Unclog read
    return 0;
  }

  sp<MetaData> getFormat() override {
    return mMetaData;
  }

  status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL) override {
    Mutex::Autolock autolock(mBufferLock);

    if (options != NULL) {
      ALOGW("ReadOptions not supported");
      return ERROR_END_OF_STREAM;
    }

    while (!mHaveNextBuffer) {
      mBufferCondition.wait(mBufferLock);
    }
    mHaveNextBuffer = false;

    if (!mBuffer) {
      ALOGI("End of stream");
      return ERROR_END_OF_STREAM;
    }

    *buffer = mBuffer;
    mBuffer = nullptr;
    return OK;
  }

  void nextFrame(android::MediaBuffer *yuv420SemiPlanarFrame) {
    Mutex::Autolock autolock(mBufferLock);
    if (mBuffer) {
      mBuffer->release();
    }
    mBuffer = yuv420SemiPlanarFrame;
    mHaveNextBuffer = true;
    mBufferCondition.signal();
  }

 private:
  MediaBuffer *mBuffer;
  bool mHaveNextBuffer;
  Mutex mBufferLock;
  Condition mBufferCondition;

  sp<MetaData> mMetaData;
};

class SimpleH264EncoderImpl: public SimpleH264Encoder {
 public:
  static SimpleH264Encoder *Create(int width,
                                   int height,
                                   int maxBitrateK,
                                   int targetFps,
                                   FrameOutCallback frameOutCallback,
                                   void *frameOutUserData);
  virtual ~SimpleH264EncoderImpl() {
    stop();
  }
  virtual void setBitRate(int bitrateK);
  virtual void requestKeyFrame();
  virtual void nextFrame(void *yuv420SemiPlanarFrame,
                         void (*deallocator)(void *),
                         InputFrameInfo& inputFrameInfo);
  virtual void stop();

 private:
  class FramePuller: public android::Thread {
   public:
    FramePuller(SimpleH264EncoderImpl *encoder): encoder(encoder) {};
   private:
    bool threadLoop() override {
      return encoder->threadLoop();
    }
    SimpleH264EncoderImpl *encoder;
  };
  friend class FramePuller;

  SimpleH264EncoderImpl(int width,
                        int height,
                        int maxBitrateK,
                        FrameOutCallback frameOutCallback,
                        void *frameOutUserData);

  bool init(int targetFps);
  bool threadLoop();

  int width;
  int height;
  int maxBitrateK;
  FrameOutCallback frameOutCallback;
  void *frameOutUserData;
  uint8_t *codecConfig;
  int codecConfigLength;

  uint8_t *encodedFrame;
  int encodedFrameMaxLength;

  int64_t lastCaptureTimeMs;

  android::sp<android::ALooper> looper;
  android::sp<android::MediaCodecSource> mediaCodecSource;
  android::sp<SingleBufferMediaSource> frameQueue;
  android::sp<android::Thread> framePuller;
  std::queue<InputFrameInfo> frameInfo;
  android::Mutex mutex;
};

SimpleH264Encoder *SimpleH264EncoderImpl::Create(int width,
                                                 int height,
                                                 int maxBitrateK,
                                                 int targetFps,
                                                 FrameOutCallback frameOutCallback,
                                                 void *frameOutUserData) {
  SimpleH264EncoderImpl *enc = new SimpleH264EncoderImpl(
    width,
    height,
    maxBitrateK,
    frameOutCallback,
    frameOutUserData
  );

  if (!enc->init(targetFps)) {
    delete enc;
    enc = nullptr;
  };

  return enc;

bail:
  delete enc;
  return nullptr;
}

SimpleH264EncoderImpl::SimpleH264EncoderImpl(int width,
                                             int height,
                                             int maxBitrateK,
                                             FrameOutCallback frameOutCallback,
                                             void *frameOutUserData)
    : width(width),
      height(height),
      maxBitrateK(maxBitrateK),
      frameOutCallback(frameOutCallback),
      frameOutUserData(frameOutUserData),
      codecConfig(nullptr),
      codecConfigLength(0),
      encodedFrame(nullptr),
      encodedFrameMaxLength(0),
      lastCaptureTimeMs(-1) {

  frameQueue = new SingleBufferMediaSource(width, height);
  looper = new ALooper;
  looper->setName("SimpleH264Encoder");
  framePuller = new SimpleH264EncoderImpl::FramePuller(this);
};

bool SimpleH264EncoderImpl::init(int targetFps) {
  sp<MetaData> meta = frameQueue->getFormat();
  int32_t width, height, stride, sliceHeight, colorFormat;
  CHECK(meta->findInt32(kKeyWidth, &width));
  CHECK(meta->findInt32(kKeyHeight, &height));
  CHECK(meta->findInt32(kKeyStride, &stride));
  CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
  CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));

  sp<AMessage> format = new AMessage();
  format->setInt32("width", width);
  format->setInt32("height", height);
  format->setInt32("stride", stride);
  format->setInt32("slice-height", sliceHeight);
  format->setInt32("color-format", colorFormat);

  format->setString("mime", kMimeTypeAvc);
  format->setInt32("bitrate", maxBitrateK * 1024);
  format->setInt32("bitrate-mode", OMX_Video_ControlRateConstant);
  format->setFloat("frame-rate", targetFps);
  format->setInt32("i-frame-interval", kIFrameInterval);

  looper->start();
  mediaCodecSource = MediaCodecSource::Create(
    looper,
    format,
    frameQueue,
#ifdef TARGET_GE_MARSHMALLOW
    NULL,
#endif
    0
  );
  if (mediaCodecSource == nullptr) {
    ALOGE("Unable to create encoder");
    return false;
  }

  status_t err;
  err = mediaCodecSource->start();
  if (err != 0) {
    ALOGE("Unable to start encoder");
    return false;
  }
  err = framePuller->run();
  if (err != 0) {
    ALOGE("Unable to start puller thread");
    return false;
  }
  return true;
}

void SimpleH264EncoderImpl::setBitRate(int bitrateK) {
  Mutex::Autolock autolock(mutex);
  if (mediaCodecSource != nullptr) {
    mediaCodecSource->videoBitRate(
      (bitrateK < maxBitrateK ? bitrateK : maxBitrateK) * 1024
    );
  }
}

void SimpleH264EncoderImpl::requestKeyFrame() {
  Mutex::Autolock autolock(mutex);
  if (mediaCodecSource != nullptr) {
    mediaCodecSource->requestIDRFrame();
  }
}

class UserMediaBuffer: public android::MediaBuffer {
 public:
  UserMediaBuffer(void *data, size_t size, void (*deallocator)(void *))
    : MediaBuffer(data, size),
      deallocator(deallocator) {}

 protected:
  ~UserMediaBuffer() {
    deallocator(data());
  }
 private:
  void (*deallocator)(void *);
};

void SimpleH264EncoderImpl::nextFrame(void *yuv420SemiPlanarFrame,
                                      void (*deallocator)(void *),
                                      InputFrameInfo& inputFrameInfo) {
  Mutex::Autolock autolock(mutex);
  if (frameQueue == nullptr) {
    ALOGI("Stopped, ignoring frame");
    return;
  }

  auto buffer = new UserMediaBuffer(
    yuv420SemiPlanarFrame,
    height * width * 3 / 2,
    deallocator
  );
  buffer->meta_data()->setInt64(kKeyTime, inputFrameInfo.captureTimeMs * 1000);
  frameInfo.push(inputFrameInfo);
  frameQueue->nextFrame(buffer);
}

void SimpleH264EncoderImpl::stop() {
  Mutex::Autolock autolock(mutex);
  framePuller->requestExit();

  if (mediaCodecSource != nullptr) {
    mediaCodecSource->stop();
  }

  if (frameQueue != nullptr) {
    frameQueue->stop();
  }

  if (looper != nullptr) {
    looper->stop();
  }

  if (framePuller->isRunning()) {
    framePuller->join();
    CHECK(!framePuller->isRunning());
  }

  frameQueue = nullptr;
  mediaCodecSource = nullptr;
  looper = nullptr;

  delete [] codecConfig;
  codecConfig = nullptr;
  codecConfigLength = 0;

  delete [] encodedFrame;
  encodedFrame = nullptr;
  encodedFrameMaxLength = 0;
}

bool SimpleH264EncoderImpl::threadLoop() {
  MediaBuffer *buffer;

  status_t err = mediaCodecSource->read(&buffer);
  if (err != OK) {
    ALOGE("Error reading from source: %d", err);
    return false;
  }

  if (buffer == NULL) {
    ALOGE("Failed to get buffer from source");
    return false;
  }

  int32_t isCodecConfig = 0;
  int32_t isIFrame = 0;
  int64_t timestamp = 0;

  if (buffer->meta_data() == NULL) {
    ALOGE("Failed to get buffer meta_data()");
    return false;
  }

  buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig);
  buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isIFrame);

  if (isCodecConfig) {
    if (codecConfig) {
      delete [] codecConfig;
    }
    codecConfigLength = buffer->range_length();
    codecConfig = new uint8_t[codecConfigLength];
    memcpy(codecConfig,
      static_cast<uint8_t*>(buffer->data()) + buffer->range_offset(),
      codecConfigLength
    );

  } else {
    EncodedFrameInfo info;
    bool drop = false;
    info.userData = frameOutUserData;
    info.keyFrame = isIFrame;
    int64_t timeMicro = 0;
    buffer->meta_data()->findInt64(kKeyTime, &timeMicro);
    info.input.captureTimeMs = timeMicro / 1000;

    if (lastCaptureTimeMs > -1) {
      auto timeSinceLastFrameMs = static_cast<int>(info.input.captureTimeMs - lastCaptureTimeMs);
      ALOGE("Frame. iframe=%d timeSinceLastFrameMs=%dms captureTimeMs=%llums",
        isIFrame, timeSinceLastFrameMs, info.input.captureTimeMs);
    }
    lastCaptureTimeMs = info.input.captureTimeMs;

    {
      Mutex::Autolock autolock(mutex);
      for (;;) {
        if (frameInfo.empty()) {
          ALOGE("frameInfo exhausted. Encoder broken?");
          drop = true;
          break;
        }
        InputFrameInfo& ifi = frameInfo.front();
        if (ifi.captureTimeMs != info.input.captureTimeMs) {
          ALOGE("Unknown frame. Encoder broken?");
          frameInfo.pop();
          continue;
        }
        info.input = ifi;
        frameInfo.pop();
        break;
      }
    }

    if (!drop) {
      if (isIFrame) {
        int encodedFrameLength = codecConfigLength + buffer->range_length();

        if (encodedFrame == nullptr ||
            encodedFrameMaxLength < encodedFrameLength) {
          encodedFrameMaxLength = encodedFrameLength + encodedFrameLength / 2;
          delete [] encodedFrame;
          encodedFrame = new uint8_t[encodedFrameMaxLength];
        }

        // Always send codecConfig with an i-frame to make the stream more
        // resilient
        if (codecConfig) {
          memcpy(encodedFrame, codecConfig, codecConfigLength);
        }
        memcpy(
          encodedFrame + codecConfigLength,
          static_cast<uint8_t*>(buffer->data()) + buffer->range_offset(),
          buffer->range_length()
        );
        info.encodedFrame = encodedFrame;
        info.encodedFrameLength = encodedFrameLength;
      } else {
        info.encodedFrame = static_cast<uint8_t*>(buffer->data()) + buffer->range_offset();
        info.encodedFrameLength = buffer->range_length();
      }
      frameOutCallback(info);
    }
  }

  buffer->release();
  return true;
}

SimpleH264Encoder *SimpleH264Encoder::Create(int width,
                                             int height,
                                             int maxBitrateK,
                                             int targetFps,
                                             FrameOutCallback frameOutCallback,
                                             void *frameOutUserData) {
  return SimpleH264EncoderImpl::Create(
    width,
    height,
    maxBitrateK,
    targetFps,
    frameOutCallback,
    frameOutUserData
  );
}

<|endoftext|>


<commit_before><commit_msg>Fixed issue in hardware adapter enumeration in D3D12 backend<commit_after><|endoftext|>


<commit_before>/*
 *  Copyright 2006-2007 Adrian Thurston <thurston@cs.queensu.ca>
 */

/*  This file is part of Ragel.
 *
 *  Ragel 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 2 of the License, or
 *  (at your option) any later version.
 *
 *  Ragel 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 Ragel; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "pcheck.h"
#include "common.h"
#include "stdlib.h"
#include <assert.h>

HostType hostTypesC[] =
{
	{ "char",     0,       "char",    true,   CHAR_MIN,  CHAR_MAX,   sizeof(char) },
	{ "unsigned", "char",  "uchar",   false,  0,         UCHAR_MAX,  sizeof(unsigned char) },
	{ "short",    0,       "short",   true,   SHRT_MIN,  SHRT_MAX,   sizeof(short) },
	{ "unsigned", "short", "ushort",  false,  0,         USHRT_MAX,  sizeof(unsigned short) },
	{ "int",      0,       "int",     true,   INT_MIN,   INT_MAX,    sizeof(int) },
	{ "unsigned", "int",   "uint",    false,  0,         UINT_MAX,   sizeof(unsigned int) },
	{ "long",     0,       "long",    true,   LONG_MIN,  LONG_MAX,   sizeof(long) },
	{ "unsigned", "long",  "ulong",   false,  0,         ULONG_MAX,  sizeof(unsigned long) }
};

HostType hostTypesD[] =
{
	{ "byte",    0,  "byte",    true,   CHAR_MIN,  CHAR_MAX,    1 },
	{ "ubyte",   0,  "ubyte",   false,  0,         UCHAR_MAX,   1 },
	{ "char",    0,  "char",    false,  0,         UCHAR_MAX,   1 },
	{ "short",   0,  "short",   true,   SHRT_MIN,  SHRT_MAX,    2 },
	{ "ushort",  0,  "ushort",  false,  0,         USHRT_MAX,   2 },
	{ "wchar",   0,  "wchar",   false,  0,         USHRT_MAX,   2 },
	{ "int",     0,  "int",     true,   INT_MIN,   INT_MAX,     4 },
	{ "uint",    0,  "uint",    false,  0,         UINT_MAX,    4 },
	{ "dchar",   0,  "dchar",   false,  0,         UINT_MAX,    4 }
};

HostType hostTypesJava[] =
{
	{ "byte",    0,  "byte",   true,   CHAR_MIN,  CHAR_MAX,    1 },
	{ "short",   0,  "short",  true,   SHRT_MIN,  SHRT_MAX,    2 },
	{ "char",    0,  "char",   false,  0,         USHRT_MAX,   2 },
	{ "int",     0,  "int",    true,   INT_MIN,   INT_MAX,     4 },
};

/* What are the appropriate types for ruby? */
HostType hostTypesRuby[] =
{
	{ "char",    0,  "char",   true,   CHAR_MIN,  CHAR_MAX,    1 },
	{ "int",     0,  "int",    true,   INT_MIN,   INT_MAX,     4 },
};

HostLang hostLangC =    { HostLang::C,    hostTypesC,    8, hostTypesC+0,    true };
HostLang hostLangD =    { HostLang::D,    hostTypesD,    9, hostTypesD+2,    true };
HostLang hostLangJava = { HostLang::Java, hostTypesJava, 4, hostTypesJava+2, false };
HostLang hostLangRuby = { HostLang::Ruby, hostTypesRuby, 2, hostTypesRuby+0, false };

HostLang *hostLang = &hostLangC;

HostType *findAlphType( char *s1 )
{
	for ( int i = 0; i < hostLang->numHostTypes; i++ ) {
		if ( strcmp( s1, hostLang->hostTypes[i].data1 ) == 0 &&
				hostLang->hostTypes[i].data2 == 0 )
		{
			return hostLang->hostTypes + i;
		}
	}

	return 0;
}

HostType *findAlphType( char *s1, char *s2 )
{
	for ( int i = 0; i < hostLang->numHostTypes; i++ ) {
		if ( strcmp( s1, hostLang->hostTypes[i].data1 ) == 0 &&
				hostLang->hostTypes[i].data2 != 0 &&
				strcmp( s2, hostLang->hostTypes[i].data2 ) == 0 )
		{
			return hostLang->hostTypes + i;
		}
	}

	return 0;
}

HostType *findAlphTypeInternal( char *s1 )
{
	for ( int i = 0; i < hostLang->numHostTypes; i++ ) {
		if ( strcmp( s1, hostLang->hostTypes[i].internalName ) == 0 )
			return hostLang->hostTypes + i;
	}

	return 0;
}

/* Construct a new parameter checker with for paramSpec. */
ParamCheck::ParamCheck(char *paramSpec, int argc, char **argv)
:
	state(noparam),
	argOffset(0),
	curArg(0),
	iCurArg(1),
	paramSpec(paramSpec),
	argc(argc),
	argv(argv)
{
}

/* Check a single option. Returns the index of the next parameter.  Sets p to
 * the arg character if valid, 0 otherwise.  Sets parg to the parameter arg if
 * there is one, NULL otherwise. */
bool ParamCheck::check()
{
	bool requiresParam;

	if ( iCurArg >= argc ) {            /* Off the end of the arg list. */
		state = noparam;
		return false;
	}

	if ( argOffset != 0 && *argOffset == 0 ) {
		/* We are at the end of an arg string. */
		iCurArg += 1;
		if ( iCurArg >= argc ) {
			state = noparam;
			return false;
		}
		argOffset = 0;
	}

	if ( argOffset == 0 ) {
		/* Set the current arg. */
		curArg = argv[iCurArg];

		/* We are at the beginning of an arg string. */
		if ( argv[iCurArg] == 0 ||        /* Argv[iCurArg] is null. */
			 argv[iCurArg][0] != '-' ||   /* Not a param. */
			 argv[iCurArg][1] == 0 ) {    /* Only a dash. */
			parameter = 0;
			parameterArg = 0;

			iCurArg += 1;
			state = noparam;
			return true;
		}
		argOffset = argv[iCurArg] + 1;
	}

	/* Get the arg char. */
	char argChar = *argOffset;

	/* Loop over all the parms and look for a match. */
	char *pSpec = paramSpec;
	while ( *pSpec != 0 ) {
		char pSpecChar = *pSpec;

		/* If there is a ':' following the char then
		 * it requires a parm.  If a parm is required
		 * then move ahead two in the parmspec. Otherwise
		 * move ahead one in the parm spec. */
		if ( pSpec[1] == ':' ) {
			requiresParam = true;
			pSpec += 2;
		}
		else {
			requiresParam = false;
			pSpec += 1;
		}

		/* Do we have a match. */
		if ( argChar == pSpecChar ) {
			if ( requiresParam ) {
				if ( argOffset[1] == 0 ) {
					/* The param must follow. */
					if ( iCurArg + 1 == argc ) {
						/* We are the last arg so there
						 * cannot be a parameter to it. */
						parameter = argChar;
						parameterArg = 0;
						iCurArg += 1;
						argOffset = 0;
						state = invalid;
						return true;
					}
					else {
						/* the parameter to the arg is the next arg. */
						parameter = pSpecChar;
						parameterArg = argv[iCurArg + 1];
						iCurArg += 2;
						argOffset = 0;
						state = match;
						return true;
					}
				}
				else {
					/* The param for the arg is built in. */
					parameter = pSpecChar;
					parameterArg = argOffset + 1;
					iCurArg += 1;
					argOffset = 0;
					state = match;
					return true;
				}
			}
			else {
				/* Good, we matched the parm and no
				 * arg is required. */
				parameter = pSpecChar;
				parameterArg = 0;
				argOffset += 1;
				state = match;
				return true;
			}
		}
	}

	/* We did not find a match. Bad Argument. */
	parameter = argChar;
	parameterArg = 0;
	argOffset += 1;
	state = invalid;
	return true;
}

/* Counts newlines before sending sync. */
int output_filter::sync( )
{
	line += 1;
	return std::filebuf::sync();
}

/* Counts newlines before sending data out to file. */
std::streamsize output_filter::xsputn( const char *s, std::streamsize n )
{
	for ( int i = 0; i < n; i++ ) {
		if ( s[i] == '\n' )
			line += 1;
	}
	return std::filebuf::xsputn( s, n );
}

/* Scans a string looking for the file extension. If there is a file
 * extension then pointer returned points to inside the string
 * passed in. Otherwise returns null. */
char *findFileExtension( char *stemFile )
{
	char *ppos = stemFile + strlen(stemFile) - 1;

	/* Scan backwards from the end looking for the first dot.
	 * If we encounter a '/' before the first dot, then stop the scan. */
	while ( 1 ) {
		/* If we found a dot or got to the beginning of the string then
		 * we are done. */
		if ( ppos == stemFile || *ppos == '.' )
			break;

		/* If we hit a / then there is no extension. Done. */
		if ( *ppos == '/' ) {
			ppos = stemFile;
			break;
		}
		ppos--;
	}

	/* If we got to the front of the string then bail we
	 * did not find an extension  */
	if ( ppos == stemFile )
		ppos = 0;

	return ppos;
}

/* Make a file name from a stem. Removes the old filename suffix and
 * replaces it with a new one. Returns a newed up string. */
char *fileNameFromStem( char *stemFile, char *suffix )
{
	long len = strlen( stemFile );
	assert( len > 0 );

	/* Get the extension. */
	char *ppos = findFileExtension( stemFile );

	/* If an extension was found, then shorten what we think the len is. */
	if ( ppos != 0 )
		len = ppos - stemFile;

	/* Make the return string from the stem and the suffix. */
	char *retVal = new char[ len + strlen( suffix ) + 1 ];
	strncpy( retVal, stemFile, len );
	strcpy( retVal + len, suffix );

	return retVal;
}

exit_object endp;

void operator<<( std::ostream &out, exit_object & )
{
    out << std::endl;
    exit(1);
}
<commit_msg>Added missing include.<commit_after>/*
 *  Copyright 2006-2007 Adrian Thurston <thurston@cs.queensu.ca>
 */

/*  This file is part of Ragel.
 *
 *  Ragel 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 2 of the License, or
 *  (at your option) any later version.
 *
 *  Ragel 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 Ragel; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "pcheck.h"
#include "common.h"
#include "stdlib.h"
#include <string.h>
#include <assert.h>

HostType hostTypesC[] =
{
	{ "char",     0,       "char",    true,   CHAR_MIN,  CHAR_MAX,   sizeof(char) },
	{ "unsigned", "char",  "uchar",   false,  0,         UCHAR_MAX,  sizeof(unsigned char) },
	{ "short",    0,       "short",   true,   SHRT_MIN,  SHRT_MAX,   sizeof(short) },
	{ "unsigned", "short", "ushort",  false,  0,         USHRT_MAX,  sizeof(unsigned short) },
	{ "int",      0,       "int",     true,   INT_MIN,   INT_MAX,    sizeof(int) },
	{ "unsigned", "int",   "uint",    false,  0,         UINT_MAX,   sizeof(unsigned int) },
	{ "long",     0,       "long",    true,   LONG_MIN,  LONG_MAX,   sizeof(long) },
	{ "unsigned", "long",  "ulong",   false,  0,         ULONG_MAX,  sizeof(unsigned long) }
};

HostType hostTypesD[] =
{
	{ "byte",    0,  "byte",    true,   CHAR_MIN,  CHAR_MAX,    1 },
	{ "ubyte",   0,  "ubyte",   false,  0,         UCHAR_MAX,   1 },
	{ "char",    0,  "char",    false,  0,         UCHAR_MAX,   1 },
	{ "short",   0,  "short",   true,   SHRT_MIN,  SHRT_MAX,    2 },
	{ "ushort",  0,  "ushort",  false,  0,         USHRT_MAX,   2 },
	{ "wchar",   0,  "wchar",   false,  0,         USHRT_MAX,   2 },
	{ "int",     0,  "int",     true,   INT_MIN,   INT_MAX,     4 },
	{ "uint",    0,  "uint",    false,  0,         UINT_MAX,    4 },
	{ "dchar",   0,  "dchar",   false,  0,         UINT_MAX,    4 }
};

HostType hostTypesJava[] =
{
	{ "byte",    0,  "byte",   true,   CHAR_MIN,  CHAR_MAX,    1 },
	{ "short",   0,  "short",  true,   SHRT_MIN,  SHRT_MAX,    2 },
	{ "char",    0,  "char",   false,  0,         USHRT_MAX,   2 },
	{ "int",     0,  "int",    true,   INT_MIN,   INT_MAX,     4 },
};

/* What are the appropriate types for ruby? */
HostType hostTypesRuby[] =
{
	{ "char",    0,  "char",   true,   CHAR_MIN,  CHAR_MAX,    1 },
	{ "int",     0,  "int",    true,   INT_MIN,   INT_MAX,     4 },
};

HostLang hostLangC =    { HostLang::C,    hostTypesC,    8, hostTypesC+0,    true };
HostLang hostLangD =    { HostLang::D,    hostTypesD,    9, hostTypesD+2,    true };
HostLang hostLangJava = { HostLang::Java, hostTypesJava, 4, hostTypesJava+2, false };
HostLang hostLangRuby = { HostLang::Ruby, hostTypesRuby, 2, hostTypesRuby+0, false };

HostLang *hostLang = &hostLangC;

HostType *findAlphType( char *s1 )
{
	for ( int i = 0; i < hostLang->numHostTypes; i++ ) {
		if ( strcmp( s1, hostLang->hostTypes[i].data1 ) == 0 &&
				hostLang->hostTypes[i].data2 == 0 )
		{
			return hostLang->hostTypes + i;
		}
	}

	return 0;
}

HostType *findAlphType( char *s1, char *s2 )
{
	for ( int i = 0; i < hostLang->numHostTypes; i++ ) {
		if ( strcmp( s1, hostLang->hostTypes[i].data1 ) == 0 &&
				hostLang->hostTypes[i].data2 != 0 &&
				strcmp( s2, hostLang->hostTypes[i].data2 ) == 0 )
		{
			return hostLang->hostTypes + i;
		}
	}

	return 0;
}

HostType *findAlphTypeInternal( char *s1 )
{
	for ( int i = 0; i < hostLang->numHostTypes; i++ ) {
		if ( strcmp( s1, hostLang->hostTypes[i].internalName ) == 0 )
			return hostLang->hostTypes + i;
	}

	return 0;
}

/* Construct a new parameter checker with for paramSpec. */
ParamCheck::ParamCheck(char *paramSpec, int argc, char **argv)
:
	state(noparam),
	argOffset(0),
	curArg(0),
	iCurArg(1),
	paramSpec(paramSpec),
	argc(argc),
	argv(argv)
{
}

/* Check a single option. Returns the index of the next parameter.  Sets p to
 * the arg character if valid, 0 otherwise.  Sets parg to the parameter arg if
 * there is one, NULL otherwise. */
bool ParamCheck::check()
{
	bool requiresParam;

	if ( iCurArg >= argc ) {            /* Off the end of the arg list. */
		state = noparam;
		return false;
	}

	if ( argOffset != 0 && *argOffset == 0 ) {
		/* We are at the end of an arg string. */
		iCurArg += 1;
		if ( iCurArg >= argc ) {
			state = noparam;
			return false;
		}
		argOffset = 0;
	}

	if ( argOffset == 0 ) {
		/* Set the current arg. */
		curArg = argv[iCurArg];

		/* We are at the beginning of an arg string. */
		if ( argv[iCurArg] == 0 ||        /* Argv[iCurArg] is null. */
			 argv[iCurArg][0] != '-' ||   /* Not a param. */
			 argv[iCurArg][1] == 0 ) {    /* Only a dash. */
			parameter = 0;
			parameterArg = 0;

			iCurArg += 1;
			state = noparam;
			return true;
		}
		argOffset = argv[iCurArg] + 1;
	}

	/* Get the arg char. */
	char argChar = *argOffset;

	/* Loop over all the parms and look for a match. */
	char *pSpec = paramSpec;
	while ( *pSpec != 0 ) {
		char pSpecChar = *pSpec;

		/* If there is a ':' following the char then
		 * it requires a parm.  If a parm is required
		 * then move ahead two in the parmspec. Otherwise
		 * move ahead one in the parm spec. */
		if ( pSpec[1] == ':' ) {
			requiresParam = true;
			pSpec += 2;
		}
		else {
			requiresParam = false;
			pSpec += 1;
		}

		/* Do we have a match. */
		if ( argChar == pSpecChar ) {
			if ( requiresParam ) {
				if ( argOffset[1] == 0 ) {
					/* The param must follow. */
					if ( iCurArg + 1 == argc ) {
						/* We are the last arg so there
						 * cannot be a parameter to it. */
						parameter = argChar;
						parameterArg = 0;
						iCurArg += 1;
						argOffset = 0;
						state = invalid;
						return true;
					}
					else {
						/* the parameter to the arg is the next arg. */
						parameter = pSpecChar;
						parameterArg = argv[iCurArg + 1];
						iCurArg += 2;
						argOffset = 0;
						state = match;
						return true;
					}
				}
				else {
					/* The param for the arg is built in. */
					parameter = pSpecChar;
					parameterArg = argOffset + 1;
					iCurArg += 1;
					argOffset = 0;
					state = match;
					return true;
				}
			}
			else {
				/* Good, we matched the parm and no
				 * arg is required. */
				parameter = pSpecChar;
				parameterArg = 0;
				argOffset += 1;
				state = match;
				return true;
			}
		}
	}

	/* We did not find a match. Bad Argument. */
	parameter = argChar;
	parameterArg = 0;
	argOffset += 1;
	state = invalid;
	return true;
}

/* Counts newlines before sending sync. */
int output_filter::sync( )
{
	line += 1;
	return std::filebuf::sync();
}

/* Counts newlines before sending data out to file. */
std::streamsize output_filter::xsputn( const char *s, std::streamsize n )
{
	for ( int i = 0; i < n; i++ ) {
		if ( s[i] == '\n' )
			line += 1;
	}
	return std::filebuf::xsputn( s, n );
}

/* Scans a string looking for the file extension. If there is a file
 * extension then pointer returned points to inside the string
 * passed in. Otherwise returns null. */
char *findFileExtension( char *stemFile )
{
	char *ppos = stemFile + strlen(stemFile) - 1;

	/* Scan backwards from the end looking for the first dot.
	 * If we encounter a '/' before the first dot, then stop the scan. */
	while ( 1 ) {
		/* If we found a dot or got to the beginning of the string then
		 * we are done. */
		if ( ppos == stemFile || *ppos == '.' )
			break;

		/* If we hit a / then there is no extension. Done. */
		if ( *ppos == '/' ) {
			ppos = stemFile;
			break;
		}
		ppos--;
	}

	/* If we got to the front of the string then bail we
	 * did not find an extension  */
	if ( ppos == stemFile )
		ppos = 0;

	return ppos;
}

/* Make a file name from a stem. Removes the old filename suffix and
 * replaces it with a new one. Returns a newed up string. */
char *fileNameFromStem( char *stemFile, char *suffix )
{
	long len = strlen( stemFile );
	assert( len > 0 );

	/* Get the extension. */
	char *ppos = findFileExtension( stemFile );

	/* If an extension was found, then shorten what we think the len is. */
	if ( ppos != 0 )
		len = ppos - stemFile;

	/* Make the return string from the stem and the suffix. */
	char *retVal = new char[ len + strlen( suffix ) + 1 ];
	strncpy( retVal, stemFile, len );
	strcpy( retVal + len, suffix );

	return retVal;
}

exit_object endp;

void operator<<( std::ostream &out, exit_object & )
{
    out << std::endl;
    exit(1);
}
<|endoftext|>


<commit_before>#ifndef GNR_STRUCTITERATOR_HPP
# define GNR_STRUCTITERATOR_HPP
# pragma once

#include <cstddef>

#include <iterator>

#include "boost/pfr.hpp"

namespace gnr
{

namespace detail::struct_iterator
{

template <class S>
constexpr auto all_same() noexcept
{
  if constexpr (constexpr auto N(boost::pfr::tuple_size_v<S>); N > 1)
  {
    return [&]<auto ...I>(std::index_sequence<I...>) noexcept
      {
        return (
            (
              std::is_same_v<
                boost::pfr::tuple_element_t<I, S>,
                boost::pfr::tuple_element_t<I + 1, S>
              >
            ) && ...
          );
      }(std::make_index_sequence<N - 1>());
  }
  else
  {
    return true;
  }
}

template <class S>
static constexpr auto is_proper_v(std::is_class_v<S> && all_same<S>());

}

template <typename S>
  requires detail::struct_iterator::is_proper_v<S>
class struct_iterator
{
  S& s_;
  std::size_t i_;

public:
  using iterator_category = std::random_access_iterator_tag;
  using difference_type = std::ptrdiff_t;
  using pointer = decltype(&boost::pfr::get<0>(s_));
  using reference = decltype(boost::pfr::get<0>(s_));
  using value_type = std::remove_reference_t<reference>;

public:
  constexpr explicit struct_iterator(S& s,
    std::size_t const i = boost::pfr::tuple_size<S>{}) noexcept:
    s_{s},
    i_{i}
  {
  }

  // increment, decrement
  constexpr auto& operator++() noexcept { return ++i_, *this; }
  constexpr auto& operator--() noexcept { return --i_, *this; }

  constexpr auto operator++(int) const noexcept
  {
    return struct_iterator(s_, i_ + 1);
  }

  constexpr auto operator--(int) const noexcept
  {
    return struct_iterator(s_, i_ - 1);
  }

  // arithmetic
  constexpr auto operator-(struct_iterator const other) const noexcept
  {
    return difference_type(i_ - other.i_);
  }

  constexpr auto operator+(std::size_t const N) const noexcept
  {
    return struct_iterator(s_, i_ + N);
  }

  constexpr auto operator-(std::size_t const N) const noexcept
  {
    return struct_iterator(s_, i_ - N);
  }

  // comparison
  constexpr auto operator==(struct_iterator const other) const noexcept
  {
    return i_ == other.i_;
  }

  constexpr auto operator!=(struct_iterator const other) const noexcept
  {
    return !(*this == other);
  }

  constexpr auto operator<(struct_iterator const other) const noexcept
  {
    return i_ < other.i_;
  }

  // member access
  constexpr auto& operator[](std::size_t const i) const noexcept
  {
    return *(*this + i);
  }

  constexpr auto& operator*() const noexcept
  {
    return [&]<auto ...I>(std::index_sequence<I...>) noexcept -> auto&
      {
        pointer r{};

        (
          (
            r = I == i_ ? &boost::pfr::get<I>(s_) : r
          ),
          ...
        );

        return *r;
      }(std::make_index_sequence<boost::pfr::tuple_size_v<S>>());
  }
};

//
template <typename S>
  requires detail::struct_iterator::is_proper_v<S>
constexpr auto begin(S& s) noexcept
{
  return struct_iterator{s, {}};
}

template <typename S>
  requires detail::struct_iterator::is_proper_v<S>
constexpr auto end(S& s) noexcept
{
  return struct_iterator{s};
}

template <typename S>
  requires detail::struct_iterator::is_proper_v<S>
constexpr auto size(S& s) noexcept
{
  return boost::pfr::tuple_size_v<S>;
}

//
template <typename S>
  requires detail::struct_iterator::is_proper_v<S>
class range
{
  S& s_;

public:
  constexpr explicit range(S& s) noexcept : s_{s}
  {
  }

  constexpr auto begin() const noexcept
  {
    return gnr::begin(s_);
  }

  constexpr auto end() const noexcept
  {
    return gnr::end(s_);
  }
};

}

#endif // GNR_STRUCTITERATOR_HPP
<commit_msg>some fixes<commit_after>#ifndef GNR_STRUCTITERATOR_HPP
# define GNR_STRUCTITERATOR_HPP
# pragma once

#include <cstddef>

#include <iterator>

#include "boost/pfr.hpp"

namespace gnr
{

namespace detail::struct_iterator
{

template <class S>
constexpr auto all_same() noexcept
{
  if constexpr (constexpr auto N(boost::pfr::tuple_size_v<S>); N > 1)
  {
    return [&]<auto ...I>(std::index_sequence<I...>) noexcept
      {
        return (
            (
              std::is_same_v<
                boost::pfr::tuple_element_t<I, S>,
                boost::pfr::tuple_element_t<I + 1, S>
              >
            ) && ...
          );
      }(std::make_index_sequence<N - 1>());
  }
  else
  {
    return true;
  }
}

template <class S>
static constexpr auto is_proper_v(std::is_class_v<S> && all_same<S>());

}

template <typename S>
  requires detail::struct_iterator::is_proper_v<S>
class struct_iterator
{
  S& s_;
  std::size_t i_;

public:
  using iterator_category = std::random_access_iterator_tag;
  using difference_type = std::ptrdiff_t;
  using pointer = decltype(&boost::pfr::get<0>(s_));
  using reference = decltype(boost::pfr::get<0>(s_));
  using value_type = std::remove_reference_t<reference>;

public:
  constexpr explicit struct_iterator(S& s,
    std::size_t const i = boost::pfr::tuple_size_v<S>) noexcept :
    s_{s},
    i_{i}
  {
  }

  // increment, decrement
  constexpr auto& operator++() noexcept { return ++i_, *this; }
  constexpr auto& operator--() noexcept { return --i_, *this; }

  constexpr auto operator++(int) const noexcept
  {
    return struct_iterator(s_, i_ + 1);
  }

  constexpr auto operator--(int) const noexcept
  {
    return struct_iterator(s_, i_ - 1);
  }

  // arithmetic
  constexpr auto operator-(struct_iterator const other) const noexcept
  {
    return difference_type(i_ - other.i_);
  }

  constexpr auto operator+(std::size_t const N) const noexcept
  {
    return struct_iterator(s_, i_ + N);
  }

  constexpr auto operator-(std::size_t const N) const noexcept
  {
    return struct_iterator(s_, i_ - N);
  }

  // comparison
  constexpr auto operator==(struct_iterator const other) const noexcept
  {
    return i_ == other.i_;
  }

  constexpr auto operator!=(struct_iterator const other) const noexcept
  {
    return !(*this == other);
  }

  constexpr auto operator<(struct_iterator const other) const noexcept
  {
    return i_ < other.i_;
  }

  // member access
  constexpr auto& operator[](std::size_t const i) const noexcept
  {
    return *(*this + i);
  }

  constexpr auto& operator*() const noexcept
  {
    return [&]<auto ...I>(std::index_sequence<I...>) noexcept -> auto&
      {
        pointer r{};

        (
          (
            r = I == i_ ? &boost::pfr::get<I>(s_) : r
          ),
          ...
        );

        return *r;
      }(std::make_index_sequence<boost::pfr::tuple_size_v<S>>());
  }
};

//
template <typename S>
  requires detail::struct_iterator::is_proper_v<S>
constexpr auto begin(S& s) noexcept
{
  return struct_iterator{s, {}};
}

template <typename S>
  requires detail::struct_iterator::is_proper_v<S>
constexpr auto end(S& s) noexcept
{
  return struct_iterator{s};
}

template <typename S>
  requires detail::struct_iterator::is_proper_v<S>
constexpr auto size(S& s) noexcept
{
  return boost::pfr::tuple_size_v<S>;
}

//
template <typename S>
  requires detail::struct_iterator::is_proper_v<S>
class range
{
  S& s_;

public:
  constexpr explicit range(S& s) noexcept : s_{s}
  {
  }

  constexpr auto begin() const noexcept
  {
    return gnr::begin(s_);
  }

  constexpr auto end() const noexcept
  {
    return gnr::end(s_);
  }
};

}

#endif // GNR_STRUCTITERATOR_HPP
<|endoftext|>


<commit_before>/*
 * File:   mapsettings.cpp
 * Author: Madison Treat <madison.treat@tamu.edu>
 *
 * Created on June 12, 2015, 8:21 PM
 */

#include "mapsettings.h"

#include <QCoreApplication>
#include <QFile>
#include <QDir>
#include <QTextStream>
#include <QDebug>

MapSettings::MapSettings(QString _filename, QObject* _parent)
:  QObject(_parent),
   settings(NULL)
{
   m_userHomeDir = QDir::home().absolutePath();

   // Get config file from [application root directory]/config
   m_appRootDir = QCoreApplication::applicationDirPath();
   QDir appRoot(m_appRootDir);

   appRoot.cdUp();
   m_configDir = appRoot.absolutePath() + "/config";

   if (m_settingsFile == "") {
      m_settingsFile = m_configDir + "/" + _filename;
   }

   if (!QFile::exists(m_settingsFile)) {
      qWarning() << "Warning: Settings file" << m_settingsFile << "does not exist. Exiting.";
      exit(1);
   }
   qDebug() << "Loading settings file:\n  " << m_settingsFile;

   loadSettingsFile(m_settingsFile);
   qDebug() << "   Done loading maps settings.";
}

MapSettings::MapSettings(const MapSettings& orig)
{
}

MapSettings::~MapSettings()
{
}

/*
 * Load the settings in file _filename.
 */
void MapSettings::loadSettingsFile(QString _filename)
{
   // If the settings pointer already exists, delete it to start fresh on a new
   // file, since this can potentially be called multiple times in an application.
   if (settings) {
      qDebug() << "Settings object already exists, re-creating it" << settings;
      delete settings;
   }
   settings = new QSettings(_filename, QSettings::IniFormat);

   // Load the Map Provider
   m_mapProvider = settings->value("map_provider").toString();

   // Load the API_KEY
   m_apiKey = settings->value("api_key", "failed").toString();
   if ( m_mapProvider == "google" && ( m_apiKey == "failed" || m_apiKey.isEmpty() ) ) {
      qWarning() << "Warning: No Google Maps API Key provided. Exiting.";
      m_apiKeyValid = false;
   }
   else {
      // TODO: test API Key to ensure valid
      m_apiKeyValid = true;
   }

   // Load the starting coordinates
   m_lat = settings->value("lat", "0.0").toDouble();
   m_lon = settings->value("lon", "0.0").toDouble();

   // Load zoom level
   m_zoom = settings->value("zoom", "12").toInt();

   // Load map type
   m_mapType = settings->value("map_type", "ROADMAP").toString();

   // Load UI disable
   m_mapDisableUI = settings->value("disable_map_ui", false).toBool();

   // Load map JS file
   m_mapJSPath = settings->value("js_file").toString();
   bool validJS = loadMapJS();
   if (validJS) {
      // Load map HTML file from compiled in resource
      if (m_mapProvider == "google") {
         m_mapHtmlInPath = ":/html/config/google-maps.html";
      }
      else {
         m_mapHtmlInPath = ":/html/config/openlayers.html";
      }

       // must be called AFTER loadExtraJS() for valid JS data to be loaded
      bool validHtml = loadMapHtml();
      if (validHtml) {
         m_mapValid = true;
      }
      else {
         m_mapValid = false;
      }
   }
   else {
      m_mapValid = false;
   }

   // Load Map Orientation
   QString os = settings->value("map_orientation").toString();
   if (os == "north_up") {
      m_mapOrientation = NORTH_UP;
   }
   else if (os == "track_up") {
      m_mapOrientation = TRACK_UP;
   }
   else {
      qWarning() << "Warning: invalid map orientation, defaulting to NORTH_UP";
      m_mapOrientation = NORTH_UP;
   }
}

/*
 * Create a new settings file with the name _filename.
 */
void MapSettings::saveSettingsFile(QString _filename)
{
   // TODO: make this work

   settings->sync();
}

/*
 * Returns valid JS: true or false
 */
bool MapSettings::loadMapJS()
{
   // Load the settings
   if (m_mapJSPath == "") {
      return false;
   }
   qDebug() << "   Map JS File:";

   // TODO: ensure properly works with "/path" and "~/path" and "path"
   //       read example settings.ini file
   if (!m_mapJSPath.startsWith("/") && !m_mapJSPath.startsWith("~")) {
      m_mapJSPath.prepend(m_configDir + "/");
   }
   qDebug() << "     " << m_mapJSPath;

   if (QFile::exists(m_mapJSPath)) {
      QFile file(m_mapJSPath);
      if ( !file.open(QFile::ReadOnly | QFile::Text) ) {
         qWarning() << "Warning: Unable to open Map JS file, disabling maps.";
         return false;
      }
      else {
         QTextStream in(&file);
         m_mapJSData = in.readAll();
         return true;
      }
   }
   else {
      qWarning() << "Warning: No Map JS file provided, disabling maps.";
      return false;
   }
}

/*
 * Returns valid HTML: true or false
 */
bool MapSettings::loadMapHtml()
{
   // Load the settings
   if (m_mapJSData == "") {
      qWarning() << "Warning: Map JS file was empty or invalid, disabling maps.";
      return false;
   }

//   if (QFile::exists(m_mapHtmlInPath)) {
      QFile file(m_mapHtmlInPath);
      if ( !file.open(QFile::ReadOnly | QFile::Text) ) {
         qWarning() << "Warning: Unable to open Map HTML file, disabling maps.";
         return false;
      }
      else {
         QTextStream in(&file);
         QString inText = in.readAll();

         m_mapHtmlPath = m_configDir + "/map-gen.html";
         QFile htmlFile(m_mapHtmlPath);
         if (!htmlFile.open(QFile::WriteOnly | QFile::Text)) {
            qWarning() << "Warning: Could not open Generated Map HTML file for writing";
            return false;
         }
         else {
            // Replace all the tags with their actual values
            // __API_KEY__ and __JS_CODE__ are directly in the HTML file,
            // The other tags are in the mapJSData string.
            m_mapHtmlData = inText.replace("__API_KEY__", m_apiKey);
            m_mapHtmlData = inText.replace("__JS_CODE__", m_mapJSData);
            m_mapHtmlData = inText.replace("__LAT__", QString::number(m_lat));
            m_mapHtmlData = inText.replace("__LON__", QString::number(m_lon));
            m_mapHtmlData = inText.replace("__ZOOM__", QString::number(m_zoom));
            m_mapHtmlData = inText.replace("__MAP_TYPE__", m_mapType);
            m_mapHtmlData = inText.replace("__DISABLE_MAP_UI__", m_mapDisableUI ? "true" : "false");

            QTextStream out(&htmlFile);
            out << m_mapHtmlData;

            return true;
         }
      }
//   }
//   else {
//      qWarning() << "Warning: No Map HTML file provided, disabling maps.";
//      return false;
//   }
}<commit_msg>MapSettings now properly gets its filename and config dir if an absolute path is provided<commit_after>/*
 * File:   mapsettings.cpp
 * Author: Madison Treat <madison.treat@tamu.edu>
 *
 * Created on June 12, 2015, 8:21 PM
 */

#include "mapsettings.h"

#include <QCoreApplication>
#include <QFile>
#include <QDir>
#include <QTextStream>
#include <QDebug>

MapSettings::MapSettings(QString _filename, QObject* _parent)
:  QObject(_parent),
   settings(NULL)
{
   m_userHomeDir = QDir::home().absolutePath();

   // Get config file from [application root directory]/config
   m_appRootDir = QCoreApplication::applicationDirPath();
   QDir appRoot(m_appRootDir);

   appRoot.cdUp();
   m_configDir = appRoot.absolutePath() + "/config";

   // If _filename starts with a "/", assume it is a full path
   if (_filename.startsWith("/")) {
      m_settingsFile = _filename;
      m_configDir = QFileInfo(m_settingsFile).absolutePath();
   }
   // Otherwise, add it to the default m_configDir
   else {
      m_settingsFile = m_configDir + "/" + _filename;
   }

   if (!QFile::exists(m_settingsFile)) {
      qWarning() << "Warning: Map settings file" << m_settingsFile << "does not exist. Exiting.";
      exit(1);
   }
   qDebug() << "Loading settings file:\n  " << m_settingsFile;

   loadSettingsFile(m_settingsFile);
   qDebug() << "   Done loading maps settings.";
}

MapSettings::MapSettings(const MapSettings& orig)
{
}

MapSettings::~MapSettings()
{
}

/*
 * Load the settings in file _filename.
 */
void MapSettings::loadSettingsFile(QString _filename)
{
   // If the settings pointer already exists, delete it to start fresh on a new
   // file, since this can potentially be called multiple times in an application.
   if (settings) {
      qDebug() << "Settings object already exists, re-creating it" << settings;
      delete settings;
   }
   settings = new QSettings(_filename, QSettings::IniFormat);

   // Load the Map Provider
   m_mapProvider = settings->value("map_provider").toString();

   // Load the API_KEY
   m_apiKey = settings->value("api_key", "failed").toString();
   if ( m_mapProvider == "google" && ( m_apiKey == "failed" || m_apiKey.isEmpty() ) ) {
      qWarning() << "Warning: No Google Maps API Key provided. Exiting.";
      m_apiKeyValid = false;
   }
   else {
      // TODO: test API Key to ensure valid
      m_apiKeyValid = true;
   }

   // Load the starting coordinates
   m_lat = settings->value("lat", "0.0").toDouble();
   m_lon = settings->value("lon", "0.0").toDouble();

   // Load zoom level
   m_zoom = settings->value("zoom", "12").toInt();

   // Load map type
   m_mapType = settings->value("map_type", "ROADMAP").toString();

   // Load UI disable
   m_mapDisableUI = settings->value("disable_map_ui", false).toBool();

   // Load map JS file
   m_mapJSPath = settings->value("js_file").toString();
   bool validJS = loadMapJS();
   if (validJS) {
      // Load map HTML file from compiled in resource
      if (m_mapProvider == "google") {
         m_mapHtmlInPath = ":/html/config/google-maps.html";
      }
      else {
         m_mapHtmlInPath = ":/html/config/openlayers.html";
      }

       // must be called AFTER loadExtraJS() for valid JS data to be loaded
      bool validHtml = loadMapHtml();
      if (validHtml) {
         m_mapValid = true;
      }
      else {
         m_mapValid = false;
      }
   }
   else {
      m_mapValid = false;
   }

   // Load Map Orientation
   QString os = settings->value("map_orientation").toString();
   if (os == "north_up") {
      m_mapOrientation = NORTH_UP;
   }
   else if (os == "track_up") {
      m_mapOrientation = TRACK_UP;
   }
   else {
      qWarning() << "Warning: invalid map orientation, defaulting to NORTH_UP";
      m_mapOrientation = NORTH_UP;
   }
}

/*
 * Create a new settings file with the name _filename.
 */
void MapSettings::saveSettingsFile(QString _filename)
{
   // TODO: make this work

   settings->sync();
}

/*
 * Returns valid JS: true or false
 */
bool MapSettings::loadMapJS()
{
   // Load the settings
   if (m_mapJSPath == "") {
      return false;
   }
   qDebug() << "   Map JS File:";

   // TODO: ensure properly works with "/path" and "~/path" and "path"
   //       read example settings.ini file
   if (!m_mapJSPath.startsWith("/") && !m_mapJSPath.startsWith("~")) {
      m_mapJSPath.prepend(m_configDir + "/");
   }
   qDebug() << "     " << m_mapJSPath;

   if (QFile::exists(m_mapJSPath)) {
      QFile file(m_mapJSPath);
      if ( !file.open(QFile::ReadOnly | QFile::Text) ) {
         qWarning() << "Warning: Unable to open Map JS file, disabling maps.";
         return false;
      }
      else {
         QTextStream in(&file);
         m_mapJSData = in.readAll();
         return true;
      }
   }
   else {
      qWarning() << "Warning: No Map JS file provided, disabling maps.";
      return false;
   }
}

/*
 * Returns valid HTML: true or false
 */
bool MapSettings::loadMapHtml()
{
   // Load the settings
   if (m_mapJSData == "") {
      qWarning() << "Warning: Map JS file was empty or invalid, disabling maps.";
      return false;
   }

//   if (QFile::exists(m_mapHtmlInPath)) {
      QFile file(m_mapHtmlInPath);
      if ( !file.open(QFile::ReadOnly | QFile::Text) ) {
         qWarning() << "Warning: Unable to open Map HTML file, disabling maps.";
         return false;
      }
      else {
         QTextStream in(&file);
         QString inText = in.readAll();

         m_mapHtmlPath = m_configDir + "/map-gen.html";
         QFile htmlFile(m_mapHtmlPath);
         if (!htmlFile.open(QFile::WriteOnly | QFile::Text)) {
            qWarning() << "Warning: Could not open Generated Map HTML file for writing";
            return false;
         }
         else {
            // Replace all the tags with their actual values
            // __API_KEY__ and __JS_CODE__ are directly in the HTML file,
            // The other tags are in the mapJSData string.
            m_mapHtmlData = inText.replace("__API_KEY__", m_apiKey);
            m_mapHtmlData = inText.replace("__JS_CODE__", m_mapJSData);
            m_mapHtmlData = inText.replace("__LAT__", QString::number(m_lat));
            m_mapHtmlData = inText.replace("__LON__", QString::number(m_lon));
            m_mapHtmlData = inText.replace("__ZOOM__", QString::number(m_zoom));
            m_mapHtmlData = inText.replace("__MAP_TYPE__", m_mapType);
            m_mapHtmlData = inText.replace("__DISABLE_MAP_UI__", m_mapDisableUI ? "true" : "false");

            QTextStream out(&htmlFile);
            out << m_mapHtmlData;

            return true;
         }
      }
//   }
//   else {
//      qWarning() << "Warning: No Map HTML file provided, disabling maps.";
//      return false;
//   }
}<|endoftext|>


<commit_before>#include "Connection.h"
#include "WebPage.h"
#include "UnsupportedContentHandler.h"
#include "CommandParser.h"
#include "CommandFactory.h"
#include "PageLoadingCommand.h"
#include "Command.h"

#include <QTcpSocket>

Connection::Connection(QTcpSocket *socket, WebPage *page, QObject *parent) :
    QObject(parent) {
  m_socket = socket;
  m_page = page;
  m_commandFactory = new CommandFactory(page, this);
  m_commandParser = new CommandParser(socket, m_commandFactory, this);
  m_pageSuccess = true;
  m_commandWaiting = false;
  connect(m_socket, SIGNAL(readyRead()), m_commandParser, SLOT(checkNext()));
  connect(m_commandParser, SIGNAL(commandReady(Command *)), this, SLOT(commandReady(Command *)));
  connect(m_page, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool)));
}

void Connection::commandReady(Command *command) {
  m_queuedCommand = command;
  if (m_page->isLoading())
    m_commandWaiting = true;
  else
    startCommand();
}

void Connection::startCommand() {
  m_commandWaiting = false;
  if (m_pageSuccess) {
    m_runningCommand = new PageLoadingCommand(m_queuedCommand, m_page, this);
    connect(m_runningCommand, SIGNAL(finished(Response *)), this, SLOT(finishCommand(Response *)));
    m_runningCommand->start();
  } else {
    writePageLoadFailure();
  }
}

void Connection::pendingLoadFinished(bool success) {
  m_pageSuccess = success;
  if (m_commandWaiting)
    startCommand();
}

void Connection::writePageLoadFailure() {
  m_pageSuccess = true;
  QString message = m_page->failureString();
  writeResponse(new Response(false, message));
}

void Connection::finishCommand(Response *response) {
  m_runningCommand->deleteLater();
  writeResponse(response);
}

void Connection::writeResponse(Response *response) {
  if (response->isSuccess())
    m_socket->write("ok\n");
  else
    m_socket->write("failure\n");

  QByteArray messageUtf8 = response->message().toUtf8();
  QString messageLength = QString::number(messageUtf8.size()) + "\n";
  m_socket->write(messageLength.toAscii());
  m_socket->write(messageUtf8);
  delete response;
}

<commit_msg>Remove unneeded header<commit_after>#include "Connection.h"
#include "WebPage.h"
#include "CommandParser.h"
#include "CommandFactory.h"
#include "PageLoadingCommand.h"
#include "Command.h"

#include <QTcpSocket>

Connection::Connection(QTcpSocket *socket, WebPage *page, QObject *parent) :
    QObject(parent) {
  m_socket = socket;
  m_page = page;
  m_commandFactory = new CommandFactory(page, this);
  m_commandParser = new CommandParser(socket, m_commandFactory, this);
  m_pageSuccess = true;
  m_commandWaiting = false;
  connect(m_socket, SIGNAL(readyRead()), m_commandParser, SLOT(checkNext()));
  connect(m_commandParser, SIGNAL(commandReady(Command *)), this, SLOT(commandReady(Command *)));
  connect(m_page, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool)));
}

void Connection::commandReady(Command *command) {
  m_queuedCommand = command;
  if (m_page->isLoading())
    m_commandWaiting = true;
  else
    startCommand();
}

void Connection::startCommand() {
  m_commandWaiting = false;
  if (m_pageSuccess) {
    m_runningCommand = new PageLoadingCommand(m_queuedCommand, m_page, this);
    connect(m_runningCommand, SIGNAL(finished(Response *)), this, SLOT(finishCommand(Response *)));
    m_runningCommand->start();
  } else {
    writePageLoadFailure();
  }
}

void Connection::pendingLoadFinished(bool success) {
  m_pageSuccess = success;
  if (m_commandWaiting)
    startCommand();
}

void Connection::writePageLoadFailure() {
  m_pageSuccess = true;
  QString message = m_page->failureString();
  writeResponse(new Response(false, message));
}

void Connection::finishCommand(Response *response) {
  m_runningCommand->deleteLater();
  writeResponse(response);
}

void Connection::writeResponse(Response *response) {
  if (response->isSuccess())
    m_socket->write("ok\n");
  else
    m_socket->write("failure\n");

  QByteArray messageUtf8 = response->message().toUtf8();
  QString messageLength = QString::number(messageUtf8.size()) + "\n";
  m_socket->write(messageLength.toAscii());
  m_socket->write(messageUtf8);
  delete response;
}

<|endoftext|>


<commit_before>#include <cranc/stdtypes.h>

#include <cranc/module/Module.h>

#include <cranc/core/Message.h>
#include <cranc/core/MessageBufferMemory.h>
#include <cranc/core/MessageBufferManager.h>

#include <cranc/core/Listener.h>
#include <cranc/timer/swTimer.h>

#include <cranc/applicationConfig/ApplicationConfig.h>

cranc::MessageBufferMemory<int, 5> intMsgBuf;

// two demoimplementations of modules that send messages to each other incrementing its value by one and remembering the last sent message
class TestModule1 : public cranc::Module, public cranc::Listener<int, 0>, public cranc::TimerCallback
{
	// this encapsulates a reference to a message and simultaneously
	// prevents anybody else from acquiring the underlying memory during "getFreeMessage"
	cranc::Message<int> mLastMsg;

	void callback() override { // callback when software timer ran out
		auto newMsg = cranc::getFreeMessage<int>();
		if (newMsg) {
			newMsg = mLastMsg + 1;
			newMsg.post<1>(); // post this message with id 1
		}
	}

	void callback(cranc::Message<int> const& msg) override { // callback to messages produced by TestModule2
		mLastMsg = msg;
	}

public:
	TestModule1(unsigned int level) : cranc::Module(level) {}

	void init(unsigned int) override {
		mLastMsg = cranc::getFreeMessage<int>();
		this->start(1000000, true); // run every second
	}
} testModule1(9);

class TestModule2 : public cranc::Listener<int, 1>
{
	cranc::Message<int> mLastMsg;
	void callback(cranc::Message<int> const& msg) override { // callback to messages produced by TestModule1
		mLastMsg = msg;
		auto newMsg = cranc::getFreeMessage<int>();
		if (newMsg) {
			newMsg = msg + 1;
			// call each callback registered to messages of type int with id 0 directly (without using the message pump)
			newMsg.invokeDirectly<0>();
		}
	}
} testModule2;

<commit_msg>added some outputs to better demonstrate what happenes<commit_after>#include <iostream>

#include <cranc/stdtypes.h>

#include <cranc/module/Module.h>

#include <cranc/core/Message.h>
#include <cranc/core/MessageBufferMemory.h>
#include <cranc/core/MessageBufferManager.h>

#include <cranc/core/Listener.h>
#include <cranc/timer/swTimer.h>

#include <cranc/applicationConfig/ApplicationConfig.h>

cranc::MessageBufferMemory<int, 5> intMsgBuf;

// two demoimplementations of modules that send messages to each other incrementing its value by one and remembering the last sent message
class TestModule1 : public cranc::Module, public cranc::Listener<int, 0>, public cranc::TimerCallback
{
	// this encapsulates a reference to a message and simultaneously
	// prevents anybody else from acquiring the underlying memory during "getFreeMessage"
	cranc::Message<int> mLastMsg;

	void callback() override { // callback when software timer ran out
		auto newMsg = cranc::getFreeMessage<int>();
		if (newMsg) {
			newMsg = mLastMsg + 1;
			std::cout << "testModule1 timer callback" << std::endl;
			std::cout << "produce message with content " << int(newMsg) << std::endl;
			newMsg.post<1>(); // post this message with id 1
		}
	}

	void callback(cranc::Message<int> const& msg) override { // callback to messages produced by TestModule2
		std::cout << "testModule1 received message with content " << int(msg) << std::endl;
		mLastMsg = msg;
	}

public:
	TestModule1(unsigned int level) : cranc::Module(level) {}

	void init(unsigned int) override {
		std::cout << "testModule1 init" << std::endl;
		mLastMsg = cranc::getFreeMessage<int>();
		this->start(1000000, true); // run every second
	}
} testModule1(2);

class TestModule2 : public cranc::Listener<int, 1>, public cranc::Module
{

	cranc::Message<int> mLastMsg;
	void callback(cranc::Message<int> const& msg) override { // callback to messages produced by TestModule1
		std::cout << "testModule2 received message with content " << int(msg) << std::endl;
		mLastMsg = msg;
		auto newMsg = cranc::getFreeMessage<int>();
		if (newMsg) {
			newMsg = msg + 1;
			// call each callback registered to messages of type int with id 0 directly (without using the message pump)
			std::cout << "produce message with content " << int(newMsg) << std::endl;
			newMsg.invokeDirectly<0>();
		}
	}

	void init(unsigned int) override {
		// this init function is called before init() of testModule1
		std::cout << "testModule2 init" << std::endl;
	}

public:
	TestModule2(unsigned int level) : cranc::Module(level) {}
} testModule2(1);

<|endoftext|>