<commit_before>//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * 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.
//
//    * Neither the name of the author nor the names of other 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.
//
//////////////////////////////////////////////////////////////////////////////

#include "pch.hpp"

#include <kiss_fft.h>
#include <core/debug.h>
#include <core/audio/Player.h>
#include <core/audio/Stream.h>
#include <core/audio/Visualizer.h>
#include <core/plugin/PluginFactory.h>
#include <algorithm>

#define MAX_PREBUFFER_QUEUE_COUNT 8
#define FFT_BUFFER_SIZE 512

using namespace musik::core::audio;
using namespace musik::core::sdk;

using std::min;
using std::max;

static std::string TAG = "Player";

namespace musik {
    namespace core {
        namespace audio {
            struct FftContext {
                FftContext() {
                    samples = 0;
                    cfg = nullptr;
                    deinterleaved = nullptr;
                    scratch = nullptr;
                }

                ~FftContext() {
                    Reset();
                }

                void Reset() {
                    kiss_fft_free(cfg);
                    delete[] deinterleaved;
                    delete[] scratch;
                    cfg = NULL;
                    deinterleaved = scratch = nullptr;
                }

                void Init(int samples) {
                    if (!cfg || samples != this->samples) {
                        Reset();
                        cfg = kiss_fft_alloc(FFT_BUFFER_SIZE, false, 0, 0);
                        deinterleaved = new kiss_fft_cpx[samples];
                        scratch = new kiss_fft_cpx[FFT_BUFFER_SIZE];
                        this->samples = samples;
                    }
                }

                int samples;
                kiss_fft_cfg cfg;
                kiss_fft_cpx* deinterleaved;
                kiss_fft_cpx* scratch;
            };
        }
    }
}

PlayerPtr Player::Create(const std::string &url, OutputPtr output) {
    return PlayerPtr(new Player(url, output));
}

OutputPtr Player::CreateDefaultOutput() {
    /* if no output is specified, find all output plugins, and select the first one. */
    typedef std::vector<OutputPtr> OutputVector;

    OutputVector outputs = musik::core::PluginFactory::Instance().QueryInterface<
        IOutput, musik::core::PluginFactory::DestroyDeleter<IOutput> >("GetAudioOutput");

    if (!outputs.empty()) {
        musik::debug::info(TAG, "found an IOutput device!");
        return outputs.front();
    }

    return OutputPtr();
}

Player::Player(const std::string &url, OutputPtr output)
: state(Player::Precache)
, url(url)
, currentPosition(0)
, output(output)
, notifiedStarted(false)
, setPosition(-1)
, fftContext(nullptr) {
    musik::debug::info(TAG, "new instance created");

    this->spectrum = new float[FFT_BUFFER_SIZE];

    /* we allow callers to specify an output device; but if they don't,
    we will create and manage our own. */
    if (!this->output) {
        throw std::runtime_error("output cannot be null!");
    }

    /* each player instance is driven by a background thread. start it. */
    this->thread.reset(new boost::thread(boost::bind(&Player::ThreadLoop, this)));
}

Player::~Player() {
    {
        boost::mutex::scoped_lock lock(this->queueMutex);
        this->state = Player::Quit;
        this->prebufferQueue.clear();
        this->writeToOutputCondition.notify_all();
    }

    this->thread->join();

    delete[] this->spectrum;
    this->spectrum = nullptr;

    delete fftContext;
}

void Player::Play() {
    boost::mutex::scoped_lock lock(this->queueMutex);

    if (this->state != Player::Quit) {
        this->state = Player::Playing;
        this->writeToOutputCondition.notify_all();
    }
}

void Player::Stop() {
    boost::mutex::scoped_lock lock(this->queueMutex);
    this->state = Player::Quit;
    this->writeToOutputCondition.notify_all();
}

double Player::Position() {
    boost::mutex::scoped_lock lock(this->positionMutex);
    return this->currentPosition;
}

void Player::SetPosition(double seconds) {
    boost::mutex::scoped_lock lock(this->positionMutex);
    this->setPosition = std::max(0.0, seconds);
}

int Player::State() {
    boost::mutex::scoped_lock lock(this->queueMutex);
    return this->state;
}

void Player::ThreadLoop() {
    /* fixed size streams are better for visualizations because they provide
    consistent buffer sizes. dynamic streams are more efficient otherwise
    because we don't need to worry about manually chunking data, we can just
    send audio data to the output straight from the decoder. */
    this->stream = Stream::Create();

    BufferPtr buffer;

    if (this->stream->OpenStream(this->url)) {
        /* precache until buffers are full */
        bool keepPrecaching = true;
        while (this->State() == Precache && keepPrecaching) {
            keepPrecaching = this->PreBuffer();
        }

        /* wait until we enter the Playing or Quit state; we may still
        be in the Precache state. */
        {
            boost::mutex::scoped_lock lock(this->queueMutex);

            while (this->state == Precache) {
                this->writeToOutputCondition.wait(lock);
            }
        }

        /* we're ready to go.... */
        bool finished = false;

        while (!finished && !this->Exited()) {
            /* see if we've been asked to seek since the last sample was
            played. if we have, clear our output buffer and seek the
            stream. */
            double position = -1;

            {
                boost::mutex::scoped_lock lock(this->positionMutex);
                position = this->setPosition;
                this->setPosition = -1;
            }

            if (position != -1) {
                this->output->Stop(); /* flush all buffers */
                this->output->Resume(); /* start it back up */

                /* if we've allocated a buffer, but it hasn't been written
                to the output yet, unlock it. this is an important step, and if
                not performed, will result in a deadlock just below while
                waiting for all buffers to complete. */
                if (buffer) {
                    this->OnBufferProcessed(buffer.get());
                    buffer.reset();
                }

                {
                    boost::mutex::scoped_lock lock(this->queueMutex);

                    while (this->lockedBuffers.size() > 0) {
                        writeToOutputCondition.wait(this->queueMutex);
                    }
                }

                this->stream->SetPosition(position);

                {
                    boost::mutex::scoped_lock lock(this->queueMutex);
                    this->prebufferQueue.clear();
                }
            }

            /* let's see if we can find some samples to play */
            if (!buffer) {
                boost::mutex::scoped_lock lock(this->queueMutex);

                /* the buffer queue may already have some available if it was prefetched. */
                if (!this->prebufferQueue.empty()) {
                    buffer = this->prebufferQueue.front();
                    this->prebufferQueue.pop_front();
                }
                /* otherwise, we need to grab a buffer from the stream and add it to the queue */
                else {
                    buffer = this->stream->GetNextProcessedOutputBuffer();
                }

                /* lock it down until it's processed */
                if (buffer) {
                    this->lockedBuffers.push_back(buffer);
                }
            }

            /* if we have a decoded, processed buffer available. let's try to send it to
            the output device. */
            if (buffer) {
                if (this->output->Play(buffer.get(), this)) {
                    /* success! the buffer was accepted by the output.*/
                    /* lock it down so it's not destroyed until the output device lets us
                    know it's done with it. */
                    boost::mutex::scoped_lock lock(this->queueMutex);

                    if (this->lockedBuffers.size() == 1) {
                        this->currentPosition = buffer->Position();
                    }

                    buffer.reset(); /* important! we're done with this one locally. */
                }
                else {
                    /* the output device queue is full. we should block and wait until
                    the output lets us know that it needs more data */
                    boost::mutex::scoped_lock lock(this->queueMutex);
                    writeToOutputCondition.wait(this->queueMutex);
                }
            }
            /* if we're unable to obtain a buffer, it means we're out of data and the
            player is finished. terminate the thread. */
            else {
                finished = true;
            }
        }

        /* if the Quit flag isn't set, that means the stream has ended "naturally", i.e.
        it wasn't stopped by the user. raise the "almost ended" flag. */
        if (!this->Exited()) {
            this->PlaybackAlmostEnded(this);
        }
    }

    /* if the stream failed to open... */
    else {
        this->PlaybackError(this);
    }

    this->state = Player::Quit;

    /* unlock any remaining buffers... see comment above */
    if (buffer) {
        this->OnBufferProcessed(buffer.get());
        buffer.reset();
    }

    /* wait until all remaining buffers have been written, set final state... */
    {
        boost::mutex::scoped_lock lock(this->queueMutex);

        while (this->lockedBuffers.size() > 0) {
            writeToOutputCondition.wait(this->queueMutex);
        }
    }

    this->PlaybackFinished(this);
}

void Player::ReleaseAllBuffers() {
    boost::mutex::scoped_lock lock(this->queueMutex);
    this->lockedBuffers.empty();
}

bool Player::PreBuffer() {
    /* don't prebuffer if the buffer is already full */
    if (this->prebufferQueue.size() < MAX_PREBUFFER_QUEUE_COUNT) {
        BufferPtr newBuffer = this->stream->GetNextProcessedOutputBuffer();

        if (newBuffer) {
            boost::mutex::scoped_lock lock(this->queueMutex);
            this->prebufferQueue.push_back(newBuffer);
        }

        return true;
    }

    return false;
}

bool Player::Exited() {
    boost::mutex::scoped_lock lock(this->queueMutex);
    return (this->state == Player::Quit);
}

#include <Windows.h>

static inline bool performFft(IBuffer* buffer, FftContext* fft, float* output, int outputSize) {
    LARGE_INTEGER start, end, freq;
    QueryPerformanceFrequency(&freq);
    QueryPerformanceCounter(&start);

    long samples = buffer->Samples();
    int channels = buffer->Channels();
    long samplesPerChannel = samples / channels;

    if (samplesPerChannel < FFT_BUFFER_SIZE ||
        outputSize != FFT_BUFFER_SIZE)
    {
        return false;
    }

    float* input = buffer->BufferPointer();

    fft->Init(samples);

    for (int i = 0; i < samples; i++) {
        const int to = ((i % channels) * samplesPerChannel) + (i / channels);
        fft->deinterleaved[i].r = input[i];
        fft->deinterleaved[i].i = 0;
    }

    /* the frequency bands seem offset about 1/4 of the buffer */
    const int rotate = FFT_BUFFER_SIZE / 4;

    int offset = 0;
    int iterations = samples / FFT_BUFFER_SIZE;
    for (int i = 0; i < iterations; i++) {
        kiss_fft(fft->cfg, &fft->deinterleaved[offset], fft->scratch);

        for (int z = 0; z < outputSize; z++) {
            /* convert to decibels */
            double db = (fft->scratch[z].r * fft->scratch[z].r + fft->scratch[z].i + fft->scratch[z].i);
            output[(z + rotate) % FFT_BUFFER_SIZE] = (db < 1 ? 0 : 20 * log(db)) / iterations;
        }

        offset += FFT_BUFFER_SIZE;
    }

    QueryPerformanceCounter(&end);
    double interval = static_cast<double>(end.QuadPart - start.QuadPart) / freq.QuadPart;

    return true;
}

void Player::OnBufferProcessed(IBuffer *buffer) {
    bool started = false;
    bool found = false;

    /* process visualizer data, and write to the selected plugin, if applicable */

    ISpectrumVisualizer* specVis = vis::SpectrumVisualizer();
    IPcmVisualizer* pcmVis = vis::PcmVisualizer();

    if (specVis && specVis->Visible()) {
        if (!fftContext) {
            fftContext = new FftContext();
        }

        if (performFft(buffer, fftContext, spectrum, FFT_BUFFER_SIZE)) {
            vis::SpectrumVisualizer()->Write(spectrum, FFT_BUFFER_SIZE);
        }
    }
    else if (pcmVis && pcmVis->Visible()) {
        vis::PcmVisualizer()->Write(buffer);
    }

    /* free the buffer */

    {
        boost::mutex::scoped_lock lock(this->queueMutex);

        /* removes the specified buffer from the list of locked buffers, and also
        lets the stream know it can be recycled. */
        BufferList::iterator it = this->lockedBuffers.begin();
        while (it != this->lockedBuffers.end() && !found) {
            if (it->get() == buffer) {
                found = true;

                if (this->stream) {
                    this->stream->OnBufferProcessedByPlayer(*it);
                }

                bool isFront = this->lockedBuffers.front() == *it;
                it = this->lockedBuffers.erase(it);

                /* this sets the current time in the stream. it does this by grabbing
                the time at the next buffer in the queue */
                if (this->lockedBuffers.empty() || isFront) {
                    this->currentPosition = ((Buffer*)buffer)->Position();
                }
                else {
                    /* if the queue is drained, use the position from the buffer
                    that was just processed */
                    this->currentPosition = this->lockedBuffers.front()->Position();
                }

                /* if the output device's internal buffers are full, it will stop
                accepting new samples. now that a buffer has been processed, we can
                try to enqueue another sample. the thread loop blocks on this condition */
                this->writeToOutputCondition.notify_all();
            }
            else {
                ++it;
            }
        }

        if (!this->notifiedStarted) {
            this->notifiedStarted = true;
            started = true;
        }
    }

    /* we notify our listeners that we've started playing only after the first
    buffer has been consumed. this is because sometimes we precache buffers
    and send them to the output before they are actually processed by the
    output device */
    if (started) {
        this->PlaybackStarted(this);
    }
}
<commit_msg>Removed win32 debugging code.<commit_after>//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * 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.
//
//    * Neither the name of the author nor the names of other 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.
//
//////////////////////////////////////////////////////////////////////////////

#include "pch.hpp"

#include <kiss_fft.h>
#include <core/debug.h>
#include <core/audio/Player.h>
#include <core/audio/Stream.h>
#include <core/audio/Visualizer.h>
#include <core/plugin/PluginFactory.h>
#include <algorithm>

#define MAX_PREBUFFER_QUEUE_COUNT 8
#define FFT_BUFFER_SIZE 512

using namespace musik::core::audio;
using namespace musik::core::sdk;

using std::min;
using std::max;

static std::string TAG = "Player";

namespace musik {
    namespace core {
        namespace audio {
            struct FftContext {
                FftContext() {
                    samples = 0;
                    cfg = nullptr;
                    deinterleaved = nullptr;
                    scratch = nullptr;
                }

                ~FftContext() {
                    Reset();
                }

                void Reset() {
                    kiss_fft_free(cfg);
                    delete[] deinterleaved;
                    delete[] scratch;
                    cfg = NULL;
                    deinterleaved = scratch = nullptr;
                }

                void Init(int samples) {
                    if (!cfg || samples != this->samples) {
                        Reset();
                        cfg = kiss_fft_alloc(FFT_BUFFER_SIZE, false, 0, 0);
                        deinterleaved = new kiss_fft_cpx[samples];
                        scratch = new kiss_fft_cpx[FFT_BUFFER_SIZE];
                        this->samples = samples;
                    }
                }

                int samples;
                kiss_fft_cfg cfg;
                kiss_fft_cpx* deinterleaved;
                kiss_fft_cpx* scratch;
            };
        }
    }
}

PlayerPtr Player::Create(const std::string &url, OutputPtr output) {
    return PlayerPtr(new Player(url, output));
}

OutputPtr Player::CreateDefaultOutput() {
    /* if no output is specified, find all output plugins, and select the first one. */
    typedef std::vector<OutputPtr> OutputVector;

    OutputVector outputs = musik::core::PluginFactory::Instance().QueryInterface<
        IOutput, musik::core::PluginFactory::DestroyDeleter<IOutput> >("GetAudioOutput");

    if (!outputs.empty()) {
        musik::debug::info(TAG, "found an IOutput device!");
        return outputs.front();
    }

    return OutputPtr();
}

Player::Player(const std::string &url, OutputPtr output)
: state(Player::Precache)
, url(url)
, currentPosition(0)
, output(output)
, notifiedStarted(false)
, setPosition(-1)
, fftContext(nullptr) {
    musik::debug::info(TAG, "new instance created");

    this->spectrum = new float[FFT_BUFFER_SIZE];

    /* we allow callers to specify an output device; but if they don't,
    we will create and manage our own. */
    if (!this->output) {
        throw std::runtime_error("output cannot be null!");
    }

    /* each player instance is driven by a background thread. start it. */
    this->thread.reset(new boost::thread(boost::bind(&Player::ThreadLoop, this)));
}

Player::~Player() {
    {
        boost::mutex::scoped_lock lock(this->queueMutex);
        this->state = Player::Quit;
        this->prebufferQueue.clear();
        this->writeToOutputCondition.notify_all();
    }

    this->thread->join();

    delete[] this->spectrum;
    this->spectrum = nullptr;

    delete fftContext;
}

void Player::Play() {
    boost::mutex::scoped_lock lock(this->queueMutex);

    if (this->state != Player::Quit) {
        this->state = Player::Playing;
        this->writeToOutputCondition.notify_all();
    }
}

void Player::Stop() {
    boost::mutex::scoped_lock lock(this->queueMutex);
    this->state = Player::Quit;
    this->writeToOutputCondition.notify_all();
}

double Player::Position() {
    boost::mutex::scoped_lock lock(this->positionMutex);
    return this->currentPosition;
}

void Player::SetPosition(double seconds) {
    boost::mutex::scoped_lock lock(this->positionMutex);
    this->setPosition = std::max(0.0, seconds);
}

int Player::State() {
    boost::mutex::scoped_lock lock(this->queueMutex);
    return this->state;
}

void Player::ThreadLoop() {
    /* fixed size streams are better for visualizations because they provide
    consistent buffer sizes. dynamic streams are more efficient otherwise
    because we don't need to worry about manually chunking data, we can just
    send audio data to the output straight from the decoder. */
    this->stream = Stream::Create();

    BufferPtr buffer;

    if (this->stream->OpenStream(this->url)) {
        /* precache until buffers are full */
        bool keepPrecaching = true;
        while (this->State() == Precache && keepPrecaching) {
            keepPrecaching = this->PreBuffer();
        }

        /* wait until we enter the Playing or Quit state; we may still
        be in the Precache state. */
        {
            boost::mutex::scoped_lock lock(this->queueMutex);

            while (this->state == Precache) {
                this->writeToOutputCondition.wait(lock);
            }
        }

        /* we're ready to go.... */
        bool finished = false;

        while (!finished && !this->Exited()) {
            /* see if we've been asked to seek since the last sample was
            played. if we have, clear our output buffer and seek the
            stream. */
            double position = -1;

            {
                boost::mutex::scoped_lock lock(this->positionMutex);
                position = this->setPosition;
                this->setPosition = -1;
            }

            if (position != -1) {
                this->output->Stop(); /* flush all buffers */
                this->output->Resume(); /* start it back up */

                /* if we've allocated a buffer, but it hasn't been written
                to the output yet, unlock it. this is an important step, and if
                not performed, will result in a deadlock just below while
                waiting for all buffers to complete. */
                if (buffer) {
                    this->OnBufferProcessed(buffer.get());
                    buffer.reset();
                }

                {
                    boost::mutex::scoped_lock lock(this->queueMutex);

                    while (this->lockedBuffers.size() > 0) {
                        writeToOutputCondition.wait(this->queueMutex);
                    }
                }

                this->stream->SetPosition(position);

                {
                    boost::mutex::scoped_lock lock(this->queueMutex);
                    this->prebufferQueue.clear();
                }
            }

            /* let's see if we can find some samples to play */
            if (!buffer) {
                boost::mutex::scoped_lock lock(this->queueMutex);

                /* the buffer queue may already have some available if it was prefetched. */
                if (!this->prebufferQueue.empty()) {
                    buffer = this->prebufferQueue.front();
                    this->prebufferQueue.pop_front();
                }
                /* otherwise, we need to grab a buffer from the stream and add it to the queue */
                else {
                    buffer = this->stream->GetNextProcessedOutputBuffer();
                }

                /* lock it down until it's processed */
                if (buffer) {
                    this->lockedBuffers.push_back(buffer);
                }
            }

            /* if we have a decoded, processed buffer available. let's try to send it to
            the output device. */
            if (buffer) {
                if (this->output->Play(buffer.get(), this)) {
                    /* success! the buffer was accepted by the output.*/
                    /* lock it down so it's not destroyed until the output device lets us
                    know it's done with it. */
                    boost::mutex::scoped_lock lock(this->queueMutex);

                    if (this->lockedBuffers.size() == 1) {
                        this->currentPosition = buffer->Position();
                    }

                    buffer.reset(); /* important! we're done with this one locally. */
                }
                else {
                    /* the output device queue is full. we should block and wait until
                    the output lets us know that it needs more data */
                    boost::mutex::scoped_lock lock(this->queueMutex);
                    writeToOutputCondition.wait(this->queueMutex);
                }
            }
            /* if we're unable to obtain a buffer, it means we're out of data and the
            player is finished. terminate the thread. */
            else {
                finished = true;
            }
        }

        /* if the Quit flag isn't set, that means the stream has ended "naturally", i.e.
        it wasn't stopped by the user. raise the "almost ended" flag. */
        if (!this->Exited()) {
            this->PlaybackAlmostEnded(this);
        }
    }

    /* if the stream failed to open... */
    else {
        this->PlaybackError(this);
    }

    this->state = Player::Quit;

    /* unlock any remaining buffers... see comment above */
    if (buffer) {
        this->OnBufferProcessed(buffer.get());
        buffer.reset();
    }

    /* wait until all remaining buffers have been written, set final state... */
    {
        boost::mutex::scoped_lock lock(this->queueMutex);

        while (this->lockedBuffers.size() > 0) {
            writeToOutputCondition.wait(this->queueMutex);
        }
    }

    this->PlaybackFinished(this);
}

void Player::ReleaseAllBuffers() {
    boost::mutex::scoped_lock lock(this->queueMutex);
    this->lockedBuffers.empty();
}

bool Player::PreBuffer() {
    /* don't prebuffer if the buffer is already full */
    if (this->prebufferQueue.size() < MAX_PREBUFFER_QUEUE_COUNT) {
        BufferPtr newBuffer = this->stream->GetNextProcessedOutputBuffer();

        if (newBuffer) {
            boost::mutex::scoped_lock lock(this->queueMutex);
            this->prebufferQueue.push_back(newBuffer);
        }

        return true;
    }

    return false;
}

bool Player::Exited() {
    boost::mutex::scoped_lock lock(this->queueMutex);
    return (this->state == Player::Quit);
}

static inline bool performFft(IBuffer* buffer, FftContext* fft, float* output, int outputSize) {
    long samples = buffer->Samples();
    int channels = buffer->Channels();
    long samplesPerChannel = samples / channels;

    if (samplesPerChannel < FFT_BUFFER_SIZE ||
        outputSize != FFT_BUFFER_SIZE)
    {
        return false;
    }

    float* input = buffer->BufferPointer();

    fft->Init(samples);

    for (int i = 0; i < samples; i++) {
        const int to = ((i % channels) * samplesPerChannel) + (i / channels);
        fft->deinterleaved[i].r = input[i];
        fft->deinterleaved[i].i = 0;
    }

    /* the frequency bands seem offset about 1/4 of the buffer */
    const int rotate = FFT_BUFFER_SIZE / 4;

    int offset = 0;
    int iterations = samples / FFT_BUFFER_SIZE;
    for (int i = 0; i < iterations; i++) {
        kiss_fft(fft->cfg, &fft->deinterleaved[offset], fft->scratch);

        for (int z = 0; z < outputSize; z++) {
            /* convert to decibels */
            double db = (fft->scratch[z].r * fft->scratch[z].r + fft->scratch[z].i + fft->scratch[z].i);
            output[(z + rotate) % FFT_BUFFER_SIZE] = (db < 1 ? 0 : 20 * log(db)) / iterations;
        }

        offset += FFT_BUFFER_SIZE;
    }

    return true;
}

void Player::OnBufferProcessed(IBuffer *buffer) {
    bool started = false;
    bool found = false;

    /* process visualizer data, and write to the selected plugin, if applicable */

    ISpectrumVisualizer* specVis = vis::SpectrumVisualizer();
    IPcmVisualizer* pcmVis = vis::PcmVisualizer();

    if (specVis && specVis->Visible()) {
        if (!fftContext) {
            fftContext = new FftContext();
        }

        if (performFft(buffer, fftContext, spectrum, FFT_BUFFER_SIZE)) {
            vis::SpectrumVisualizer()->Write(spectrum, FFT_BUFFER_SIZE);
        }
    }
    else if (pcmVis && pcmVis->Visible()) {
        vis::PcmVisualizer()->Write(buffer);
    }

    /* free the buffer */

    {
        boost::mutex::scoped_lock lock(this->queueMutex);

        /* removes the specified buffer from the list of locked buffers, and also
        lets the stream know it can be recycled. */
        BufferList::iterator it = this->lockedBuffers.begin();
        while (it != this->lockedBuffers.end() && !found) {
            if (it->get() == buffer) {
                found = true;

                if (this->stream) {
                    this->stream->OnBufferProcessedByPlayer(*it);
                }

                bool isFront = this->lockedBuffers.front() == *it;
                it = this->lockedBuffers.erase(it);

                /* this sets the current time in the stream. it does this by grabbing
                the time at the next buffer in the queue */
                if (this->lockedBuffers.empty() || isFront) {
                    this->currentPosition = ((Buffer*)buffer)->Position();
                }
                else {
                    /* if the queue is drained, use the position from the buffer
                    that was just processed */
                    this->currentPosition = this->lockedBuffers.front()->Position();
                }

                /* if the output device's internal buffers are full, it will stop
                accepting new samples. now that a buffer has been processed, we can
                try to enqueue another sample. the thread loop blocks on this condition */
                this->writeToOutputCondition.notify_all();
            }
            else {
                ++it;
            }
        }

        if (!this->notifiedStarted) {
            this->notifiedStarted = true;
            started = true;
        }
    }

    /* we notify our listeners that we've started playing only after the first
    buffer has been consumed. this is because sometimes we precache buffers
    and send them to the output before they are actually processed by the
    output device */
    if (started) {
        this->PlaybackStarted(this);
    }
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) Qxt Foundation. Some rights reserved.
**
** This file is part of the QxtCore module of the Qt eXTension library
**
** This library is free software; you can redistribute it and/or modify it
** under the terms of th Common Public License, version 1.0, as published by
** IBM.
**
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
** FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the CPL along with this file.
** See the LICENSE file and the cpl1.0.txt file included with the source
** distribution for more information. If you did not receive a copy of the
** license, contact the Qxt Foundation.
**
** <http://libqxt.sourceforge.net>  <libqxt@gmail.com>
**
****************************************************************************/
#include "qxtsemaphore.h"

/**
\class QxtSemaphore QxtSemaphore
\ingroup core
\brief system wide semaphore (former QxtSingleInstance)

\code
	QxtSemaphore instance("com.mycompany.foobla.uniquestring");
	if(!instance.trylock())
		{
		qDebug("already started")
		}

\endcode

Note that the semaphore is autoaticly unlocked on destruction, but not on segfault,sigkill,etc...!
*/

#ifdef Q_WS_WIN
	#include "Windows.h"

	class QxtSemaphorePrivate : public QxtPrivate<QxtSemaphore>
		{
		public:
			QString name;
			unsigned sem_m;
			void init()
				{
				sem_m=0;
				}

			bool trylock()
				{
				sem_m = (unsigned ) CreateSemaphoreA ( NULL , 1 , 2 , qPrintable("Global\\"+name) );
				if (sem_m == 0 )
					return false;
				return true;
				}
			bool unlock()
				{
				if(sem_m==0)
					return false;
				return CloseHandle((void *)sem_m);
				}
		};

#else

	#include <semaphore.h>
	#include <fcntl.h>
	#include <errno.h>

	class QxtSemaphorePrivate : public QxtPrivate<QxtSemaphore>
		{
		public:
			QString name;
			sem_t* m_sem;
			bool s_N;
			void init()
				{
				s_N=false;
				m_sem=NULL;
				}

			bool trylock()
				{
				m_sem=sem_open(qPrintable(name), O_CREAT, S_IRUSR | S_IWUSR, 1);
				if((int)(m_sem)==SEM_FAILED || sem_trywait(m_sem))
					{
					m_sem=NULL;
					s_N=true;
					return false;
					}
				s_N=false;
				return true;
				}
			bool unlock()
				{
				if(m_sem==NULL)
					return false;
  				if(!s_N)
					{
					sem_post(m_sem);
					}
				return (sem_close(m_sem)==0);
				}
		};

#endif

QxtSemaphore::QxtSemaphore(QString uniqueID)
	{
	qxt_d().name=uniqueID;
	qxt_d().init();
	}

QxtSemaphore::~QxtSemaphore()
	{
	unlock();
	}

bool QxtSemaphore::trylock()
	{
	return qxt_d().trylock();
	}
bool QxtSemaphore::unlock()
	{
	return qxt_d().unlock();
	}
<commit_msg>fixing ISO C++ violation (let's hope other compilers don't think different about that)<commit_after>/****************************************************************************
**
** Copyright (C) Qxt Foundation. Some rights reserved.
**
** This file is part of the QxtCore module of the Qt eXTension library
**
** This library is free software; you can redistribute it and/or modify it
** under the terms of th Common Public License, version 1.0, as published by
** IBM.
**
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
** FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the CPL along with this file.
** See the LICENSE file and the cpl1.0.txt file included with the source
** distribution for more information. If you did not receive a copy of the
** license, contact the Qxt Foundation.
**
** <http://libqxt.sourceforge.net>  <libqxt@gmail.com>
**
****************************************************************************/
#include "qxtsemaphore.h"

/**
\class QxtSemaphore QxtSemaphore
\ingroup core
\brief system wide semaphore (former QxtSingleInstance)

\code
	QxtSemaphore instance("com.mycompany.foobla.uniquestring");
	if(!instance.trylock())
		{
		qDebug("already started")
		}

\endcode

Note that the semaphore is autoaticly unlocked on destruction, but not on segfault,sigkill,etc...!
*/

#ifdef Q_WS_WIN
	#include "Windows.h"

	class QxtSemaphorePrivate : public QxtPrivate<QxtSemaphore>
		{
		public:
			QString name;
			unsigned sem_m;
			void init()
				{
				sem_m=0;
				}

			bool trylock()
				{
				sem_m = (unsigned ) CreateSemaphoreA ( NULL , 1 , 2 , qPrintable("Global\\"+name) );
				if (sem_m == 0 )
					return false;
				return true;
				}
			bool unlock()
				{
				if(sem_m==0)
					return false;
				return CloseHandle((void *)sem_m);
				}
		};

#else

	#include <semaphore.h>
	#include <fcntl.h>
	#include <errno.h>

	class QxtSemaphorePrivate : public QxtPrivate<QxtSemaphore>
		{
		public:
			QString name;
			sem_t* m_sem;
			bool s_N;
			void init()
				{
				s_N=false;
				m_sem=NULL;
				}

			bool trylock()
				{
				m_sem=sem_open(qPrintable(name), O_CREAT, S_IRUSR | S_IWUSR, 1);
				if(m_sem==SEM_FAILED || sem_trywait(m_sem))
					{
					m_sem=NULL;
					s_N=true;
					return false;
					}
				s_N=false;
				return true;
				}
			bool unlock()
				{
				if(m_sem==NULL)
					return false;
  				if(!s_N)
					{
					sem_post(m_sem);
					}
				return (sem_close(m_sem)==0);
				}
		};

#endif

QxtSemaphore::QxtSemaphore(QString uniqueID)
	{
	qxt_d().name=uniqueID;
	qxt_d().init();
	}

QxtSemaphore::~QxtSemaphore()
	{
	unlock();
	}

bool QxtSemaphore::trylock()
	{
	return qxt_d().trylock();
	}
bool QxtSemaphore::unlock()
	{
	return qxt_d().unlock();
	}
<|endoftext|>


<commit_before>//===-- WasmDumper.cpp - Wasm-specific object file dumper -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Wasm-specific dumper for llvm-readobj.
//
//===----------------------------------------------------------------------===//

#include "Error.h"
#include "ObjDumper.h"
#include "llvm-readobj.h"
#include "llvm/Object/Wasm.h"
#include "llvm/Support/ScopedPrinter.h"

using namespace llvm;
using namespace object;

namespace {

static const EnumEntry<unsigned> WasmSymbolTypes[] = {
#define ENUM_ENTRY(X) { #X, static_cast<unsigned>(WasmSymbol::SymbolType::X) }
  ENUM_ENTRY(FUNCTION_IMPORT),
  ENUM_ENTRY(FUNCTION_EXPORT),
  ENUM_ENTRY(GLOBAL_IMPORT),
  ENUM_ENTRY(GLOBAL_EXPORT),
  ENUM_ENTRY(DEBUG_FUNCTION_NAME),
#undef ENUM_ENTRY
};

static const EnumEntry<uint32_t> WasmSectionTypes[] = {
#define ENUM_ENTRY(X) { #X, wasm::WASM_SEC_##X }
  ENUM_ENTRY(CUSTOM),
  ENUM_ENTRY(TYPE),
  ENUM_ENTRY(IMPORT),
  ENUM_ENTRY(FUNCTION),
  ENUM_ENTRY(TABLE),
  ENUM_ENTRY(MEMORY),
  ENUM_ENTRY(GLOBAL),
  ENUM_ENTRY(EXPORT),
  ENUM_ENTRY(START),
  ENUM_ENTRY(ELEM),
  ENUM_ENTRY(CODE),
  ENUM_ENTRY(DATA),
#undef ENUM_ENTRY
};

class WasmDumper : public ObjDumper {
public:
  WasmDumper(const WasmObjectFile *Obj, ScopedPrinter &Writer)
      : ObjDumper(Writer), Obj(Obj) {}

  void printFileHeaders() override;
  void printSections() override;
  void printRelocations() override;
  void printSymbols() override;
  void printDynamicSymbols() override { llvm_unreachable("unimplemented"); }
  void printUnwindInfo() override { llvm_unreachable("unimplemented"); }
  void printStackMap() const override { llvm_unreachable("unimplemented"); }

protected:
  void printSymbol(const SymbolRef &Sym);
  void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);

private:
  const WasmObjectFile *Obj;
};

void WasmDumper::printFileHeaders() {
  W.printHex("Version", Obj->getHeader().Version);
}

void WasmDumper::printRelocation(const SectionRef &Section,
                                 const RelocationRef &Reloc) {
  SmallString<64> RelocTypeName;
  uint64_t RelocType = Reloc.getType();
  Reloc.getTypeName(RelocTypeName);
  const wasm::WasmRelocation &WasmReloc = Obj->getWasmRelocation(Reloc);

  bool HasAddend = false;
  switch (RelocType) {
  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
    HasAddend = true;
    break;
  default:
    break;
  }
  if (opts::ExpandRelocs) {
    DictScope Group(W, "Relocation");
    W.printNumber("Type", RelocTypeName, RelocType);
    W.printHex("Offset", Reloc.getOffset());
    W.printHex("Index", WasmReloc.Index);
    if (HasAddend)
      W.printNumber("Addend", WasmReloc.Addend);
  } else {
    raw_ostream& OS = W.startLine();
    OS << W.hex(Reloc.getOffset())
       << " " << RelocTypeName << "[" << WasmReloc.Index << "]";
    if (HasAddend)
      OS << " " << WasmReloc.Addend;
    OS << "\n";
  }
}

void WasmDumper::printRelocations() {
  ListScope D(W, "Relocations");

  int SectionNumber = 0;
  for (const SectionRef &Section : Obj->sections()) {
    bool PrintedGroup = false;
    StringRef Name;
    error(Section.getName(Name));
    ++SectionNumber;

    for (const RelocationRef &Reloc : Section.relocations()) {
      if (!PrintedGroup) {
        W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
        W.indent();
        PrintedGroup = true;
      }

      printRelocation(Section, Reloc);
    }

    if (PrintedGroup) {
      W.unindent();
      W.startLine() << "}\n";
    }
  }
}

void WasmDumper::printSymbols() {
  ListScope Group(W, "Symbols");

  for (const SymbolRef &Symbol : Obj->symbols())
    printSymbol(Symbol);
}

void WasmDumper::printSections() {
  ListScope Group(W, "Sections");
  for (const SectionRef &Section : Obj->sections()) {
    const WasmSection &WasmSec = Obj->getWasmSection(Section);
    DictScope SectionD(W, "Section");
    W.printEnum("Type", WasmSec.Type, makeArrayRef(WasmSectionTypes));
    W.printNumber("Size", static_cast<uint64_t>(WasmSec.Content.size()));
    W.printNumber("Offset", WasmSec.Offset);
    switch (WasmSec.Type) {
    case wasm::WASM_SEC_CUSTOM:
      W.printString("Name", WasmSec.Name);
      if (WasmSec.Name == "linking") {
        const wasm::WasmLinkingData &LinkingData = Obj->linkingData();
        W.printNumber("DataSize", LinkingData.DataSize);
      }
      break;
    case wasm::WASM_SEC_DATA: {
      ListScope Group(W, "Segments");
      for (const WasmSegment &Segment : Obj->dataSegments()) {
        const wasm::WasmDataSegment& Seg = Segment.Data;
        DictScope Group(W, "Segment");
        if (!Seg.Name.empty())
          W.printString("Name", Seg.Name);
        W.printNumber("Size", static_cast<uint64_t>(Seg.Content.size()));
        if (Seg.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST)
          W.printNumber("Offset", Seg.Offset.Value.Int32);
      }
      break;
    }
    case wasm::WASM_SEC_MEMORY:
      ListScope Group(W, "Memories");
      for (const wasm::WasmLimits &Memory : Obj->memories()) {
        DictScope Group(W, "Memory");
        W.printNumber("InitialPages", Memory.Initial);
        if (Memory.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) {
          W.printNumber("MaxPages", WasmSec.Offset);
        }
      }
      break;
    }

    if (opts::SectionRelocations) {
      ListScope D(W, "Relocations");
      for (const RelocationRef &Reloc : Section.relocations())
        printRelocation(Section, Reloc);
    }

    if (opts::SectionData) {
      W.printBinaryBlock("SectionData", WasmSec.Content);
    }
  }
}

void WasmDumper::printSymbol(const SymbolRef &Sym) {
  DictScope D(W, "Symbol");
  WasmSymbol Symbol = Obj->getWasmSymbol(Sym.getRawDataRefImpl());
  W.printString("Name", Symbol.Name);
  W.printEnum("Type", static_cast<unsigned>(Symbol.Type), makeArrayRef(WasmSymbolTypes));
  W.printHex("Flags", Symbol.Flags);
}

}

namespace llvm {

std::error_code createWasmDumper(const object::ObjectFile *Obj,
                                 ScopedPrinter &Writer,
                                 std::unique_ptr<ObjDumper> &Result) {
  const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(Obj);
  assert(WasmObj && "createWasmDumper called with non-wasm object");

  Result.reset(new WasmDumper(WasmObj, Writer));
  return readobj_error::success;
}

} // namespace llvm
<commit_msg>[llvm-readobj] Dump wasm init functions<commit_after>//===-- WasmDumper.cpp - Wasm-specific object file dumper -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Wasm-specific dumper for llvm-readobj.
//
//===----------------------------------------------------------------------===//

#include "Error.h"
#include "ObjDumper.h"
#include "llvm-readobj.h"
#include "llvm/Object/Wasm.h"
#include "llvm/Support/ScopedPrinter.h"

using namespace llvm;
using namespace object;

namespace {

static const EnumEntry<unsigned> WasmSymbolTypes[] = {
#define ENUM_ENTRY(X) { #X, static_cast<unsigned>(WasmSymbol::SymbolType::X) }
  ENUM_ENTRY(FUNCTION_IMPORT),
  ENUM_ENTRY(FUNCTION_EXPORT),
  ENUM_ENTRY(GLOBAL_IMPORT),
  ENUM_ENTRY(GLOBAL_EXPORT),
  ENUM_ENTRY(DEBUG_FUNCTION_NAME),
#undef ENUM_ENTRY
};

static const EnumEntry<uint32_t> WasmSectionTypes[] = {
#define ENUM_ENTRY(X) { #X, wasm::WASM_SEC_##X }
  ENUM_ENTRY(CUSTOM),
  ENUM_ENTRY(TYPE),
  ENUM_ENTRY(IMPORT),
  ENUM_ENTRY(FUNCTION),
  ENUM_ENTRY(TABLE),
  ENUM_ENTRY(MEMORY),
  ENUM_ENTRY(GLOBAL),
  ENUM_ENTRY(EXPORT),
  ENUM_ENTRY(START),
  ENUM_ENTRY(ELEM),
  ENUM_ENTRY(CODE),
  ENUM_ENTRY(DATA),
#undef ENUM_ENTRY
};

class WasmDumper : public ObjDumper {
public:
  WasmDumper(const WasmObjectFile *Obj, ScopedPrinter &Writer)
      : ObjDumper(Writer), Obj(Obj) {}

  void printFileHeaders() override;
  void printSections() override;
  void printRelocations() override;
  void printSymbols() override;
  void printDynamicSymbols() override { llvm_unreachable("unimplemented"); }
  void printUnwindInfo() override { llvm_unreachable("unimplemented"); }
  void printStackMap() const override { llvm_unreachable("unimplemented"); }

protected:
  void printSymbol(const SymbolRef &Sym);
  void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);

private:
  const WasmObjectFile *Obj;
};

void WasmDumper::printFileHeaders() {
  W.printHex("Version", Obj->getHeader().Version);
}

void WasmDumper::printRelocation(const SectionRef &Section,
                                 const RelocationRef &Reloc) {
  SmallString<64> RelocTypeName;
  uint64_t RelocType = Reloc.getType();
  Reloc.getTypeName(RelocTypeName);
  const wasm::WasmRelocation &WasmReloc = Obj->getWasmRelocation(Reloc);

  bool HasAddend = false;
  switch (RelocType) {
  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
    HasAddend = true;
    break;
  default:
    break;
  }
  if (opts::ExpandRelocs) {
    DictScope Group(W, "Relocation");
    W.printNumber("Type", RelocTypeName, RelocType);
    W.printHex("Offset", Reloc.getOffset());
    W.printHex("Index", WasmReloc.Index);
    if (HasAddend)
      W.printNumber("Addend", WasmReloc.Addend);
  } else {
    raw_ostream& OS = W.startLine();
    OS << W.hex(Reloc.getOffset()) << " " << RelocTypeName << "["
       << WasmReloc.Index << "]";
    if (HasAddend)
      OS << " " << WasmReloc.Addend;
    OS << "\n";
  }
}

void WasmDumper::printRelocations() {
  ListScope D(W, "Relocations");

  int SectionNumber = 0;
  for (const SectionRef &Section : Obj->sections()) {
    bool PrintedGroup = false;
    StringRef Name;
    error(Section.getName(Name));
    ++SectionNumber;

    for (const RelocationRef &Reloc : Section.relocations()) {
      if (!PrintedGroup) {
        W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
        W.indent();
        PrintedGroup = true;
      }

      printRelocation(Section, Reloc);
    }

    if (PrintedGroup) {
      W.unindent();
      W.startLine() << "}\n";
    }
  }
}

void WasmDumper::printSymbols() {
  ListScope Group(W, "Symbols");

  for (const SymbolRef &Symbol : Obj->symbols())
    printSymbol(Symbol);
}

void WasmDumper::printSections() {
  ListScope Group(W, "Sections");
  for (const SectionRef &Section : Obj->sections()) {
    const WasmSection &WasmSec = Obj->getWasmSection(Section);
    DictScope SectionD(W, "Section");
    W.printEnum("Type", WasmSec.Type, makeArrayRef(WasmSectionTypes));
    W.printNumber("Size", static_cast<uint64_t>(WasmSec.Content.size()));
    W.printNumber("Offset", WasmSec.Offset);
    switch (WasmSec.Type) {
    case wasm::WASM_SEC_CUSTOM:
      W.printString("Name", WasmSec.Name);
      if (WasmSec.Name == "linking") {
        const wasm::WasmLinkingData &LinkingData = Obj->linkingData();
        W.printNumber("DataSize", LinkingData.DataSize);
        if (!LinkingData.InitFunctions.empty()) {
          ListScope Group(W, "InitFunctions");
          for (const wasm::WasmInitFunc &F: LinkingData.InitFunctions)
            W.startLine() << F.FunctionIndex << " (priority=" << F.Priority
                          << ")\n";
        }
      }
      break;
    case wasm::WASM_SEC_DATA: {
      ListScope Group(W, "Segments");
      for (const WasmSegment &Segment : Obj->dataSegments()) {
        const wasm::WasmDataSegment& Seg = Segment.Data;
        DictScope Group(W, "Segment");
        if (!Seg.Name.empty())
          W.printString("Name", Seg.Name);
        W.printNumber("Size", static_cast<uint64_t>(Seg.Content.size()));
        if (Seg.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST)
          W.printNumber("Offset", Seg.Offset.Value.Int32);
      }
      break;
    }
    case wasm::WASM_SEC_MEMORY:
      ListScope Group(W, "Memories");
      for (const wasm::WasmLimits &Memory : Obj->memories()) {
        DictScope Group(W, "Memory");
        W.printNumber("InitialPages", Memory.Initial);
        if (Memory.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) {
          W.printNumber("MaxPages", WasmSec.Offset);
        }
      }
      break;
    }

    if (opts::SectionRelocations) {
      ListScope D(W, "Relocations");
      for (const RelocationRef &Reloc : Section.relocations())
        printRelocation(Section, Reloc);
    }

    if (opts::SectionData) {
      W.printBinaryBlock("SectionData", WasmSec.Content);
    }
  }
}

void WasmDumper::printSymbol(const SymbolRef &Sym) {
  DictScope D(W, "Symbol");
  WasmSymbol Symbol = Obj->getWasmSymbol(Sym.getRawDataRefImpl());
  W.printString("Name", Symbol.Name);
  W.printEnum("Type", static_cast<unsigned>(Symbol.Type), makeArrayRef(WasmSymbolTypes));
  W.printHex("Flags", Symbol.Flags);
}

}

namespace llvm {

std::error_code createWasmDumper(const object::ObjectFile *Obj,
                                 ScopedPrinter &Writer,
                                 std::unique_ptr<ObjDumper> &Result) {
  const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(Obj);
  assert(WasmObj && "createWasmDumper called with non-wasm object");

  Result.reset(new WasmDumper(WasmObj, Writer));
  return readobj_error::success;
}

} // namespace llvm
<|endoftext|>


<commit_before>//  (C) Copyright Gennadiy Rozental 2001-2006.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.

// Boost.Test
#ifdef BOOST_MSVC
# pragma warning(disable: C4345)
#endif

#include <boost/test/unit_test.hpp>
using boost::unit_test::test_suite;

// Boost.MPL
#include <boost/mpl/range_c.hpp>

BOOST_TEST_CASE_TEMPLATE_FUNCTION( free_test_function, Number )
{
    BOOST_CHECK_EQUAL( 2, (int const)Number::value );
}

test_suite*
init_unit_test_suite( int, char* [] ) {
    test_suite* test= BOOST_TEST_SUITE( "Test case template example" );

    typedef boost::mpl::range_c<int,0,10> numbers;

    test->add( BOOST_TEST_CASE_TEMPLATE( free_test_function, numbers ) );

    return test;
}

// EOF
<commit_msg>cleanup to test the inclusion of example files in the documentation<commit_after>//  (C) Copyright Gennadiy Rozental 2001-2006.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.

// Boost.Test
#ifdef BOOST_MSVC
# pragma warning(disable: C4345)
#endif

#include <boost/test/unit_test.hpp>
using boost::unit_test::test_suite;

// Boost.MPL
#include <boost/mpl/range_c.hpp>

BOOST_TEST_CASE_TEMPLATE_FUNCTION( free_test_function, Number )
{
  BOOST_CHECK_EQUAL( 2, static_cast<int>(Number::value) );
}

test_suite* init_unit_test_suite( int, char* [] )
{
  test_suite* test= BOOST_TEST_SUITE( "Test case template example" );

  typedef boost::mpl::range_c<int,0,10> numbers;

  test->add( BOOST_TEST_CASE_TEMPLATE( free_test_function, numbers ) );

  return test;
}

// EOF
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLBasicExportFilter.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 12:45:42 $
 *
 *  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 _XMLOFF_XMLBASICEXPORTFILTER_HXX
#define _XMLOFF_XMLBASICEXPORTFILTER_HXX

#ifndef _COM_SUN_STAR_XML_SAX_XDOCUMENTHANDLER_HPP_
#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
#endif
#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif

// =============================================================================
// class XMLBasicExportFilter
// =============================================================================

typedef ::cppu::WeakImplHelper1<
    ::com::sun::star::xml::sax::XDocumentHandler > XMLBasicExportFilter_BASE;

class XMLBasicExportFilter : public XMLBasicExportFilter_BASE
{
private:
    ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler >    m_xHandler;

public:
    XMLBasicExportFilter(
        const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler >& rxHandler );
    virtual ~XMLBasicExportFilter();

    // XDocumentHandler
    virtual void SAL_CALL startDocument()
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL endDocument()
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL startElement( const ::rtl::OUString& aName,
        const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttribs )
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL endElement( const ::rtl::OUString& aName )
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL characters( const ::rtl::OUString& aChars )
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL ignorableWhitespace( const ::rtl::OUString& aWhitespaces )
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL processingInstruction( const ::rtl::OUString& aTarget, const ::rtl::OUString& aData )
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL setDocumentLocator( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XLocator >& xLocator )
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
};

#endif // _XMLOFF_XMLBASICEXPORTFILTER_HXX
<commit_msg>INTEGRATION: CWS changefileheader (1.3.450); FILE MERGED 2008/04/01 16:09:08 thb 1.3.450.3: #i85898# Stripping all external header guards 2008/04/01 13:04:17 thb 1.3.450.2: #i85898# Stripping all external header guards 2008/03/31 16:27:52 rt 1.3.450.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: XMLBasicExportFilter.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 _XMLOFF_XMLBASICEXPORTFILTER_HXX
#define _XMLOFF_XMLBASICEXPORTFILTER_HXX

#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
#include <cppuhelper/implbase1.hxx>

// =============================================================================
// class XMLBasicExportFilter
// =============================================================================

typedef ::cppu::WeakImplHelper1<
    ::com::sun::star::xml::sax::XDocumentHandler > XMLBasicExportFilter_BASE;

class XMLBasicExportFilter : public XMLBasicExportFilter_BASE
{
private:
    ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler >    m_xHandler;

public:
    XMLBasicExportFilter(
        const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler >& rxHandler );
    virtual ~XMLBasicExportFilter();

    // XDocumentHandler
    virtual void SAL_CALL startDocument()
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL endDocument()
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL startElement( const ::rtl::OUString& aName,
        const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttribs )
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL endElement( const ::rtl::OUString& aName )
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL characters( const ::rtl::OUString& aChars )
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL ignorableWhitespace( const ::rtl::OUString& aWhitespaces )
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL processingInstruction( const ::rtl::OUString& aTarget, const ::rtl::OUString& aData )
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL setDocumentLocator( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XLocator >& xLocator )
        throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
};

#endif // _XMLOFF_XMLBASICEXPORTFILTER_HXX
<|endoftext|>


<commit_before>/*****************************************************************************
 * MBTiler
 *
 * Writes directories of suitably tiled PNGs or JPEGS to a SQLite file
 * using the SQLite C API.
 *
 * Inspired by GDAL's MBTiles driver, this module has no dependencies
 * not already provided by GDAL and OGR.
 *
 * Author: Sean Gillies <sean@mapbox.com>
 *
 ****************************************************************************/

#include "cpl_conv.h"
#include "cpl_string.h"
#include "sqlite3.h"
#include "stdlib.h"

#include <iostream>
#include <stdexcept>

class MBTiler
{
    char *name;
    char *description;
    sqlite3 *db;
    sqlite3_stmt *meta_stmt;
    sqlite3_stmt *tile_stmt;

    public:
        MBTiler(const char *pszName, const char *pszDescription);
        ~MBTiler();
        void InsertImage(
            const char *pszFilename,
            int zoom,
            int tile_column,
            int tile_row);
};

MBTiler::MBTiler(const char *pszName, const char *pszDescription)
{
    int rc;

    name = CPLStrdup(pszName);
    description = CPLStrdup(pszDescription);

    // Initialize database and create tables.
    std::string basename(pszName);
    std::string extension(".mbtiles");
    std::string filename = basename + extension;
    rc = sqlite3_open(filename.c_str(), &db);
    rc = sqlite3_exec(
            db,
            "CREATE TABLE metadata (name text, value text);",
            NULL, NULL, NULL);
    rc = sqlite3_exec(
            db,
            "CREATE TABLE tiles "
            "(zoom_level integer, tile_column integer, "
            "tile_row integer, tile_data blob);",
            NULL, NULL, NULL);

    // Write MBTiles metadata.
    rc = sqlite3_prepare_v2(
            db,
            "INSERT INTO metadata "
            "(name, value) "
            "VALUES (?1, ?2);",
            -1, &meta_stmt, NULL );
    rc = sqlite3_bind_text(meta_stmt, 1, "name", -1, SQLITE_STATIC);
    rc = sqlite3_bind_text(meta_stmt, 2, name, -1, SQLITE_STATIC);
    rc = sqlite3_step(meta_stmt);
    rc = sqlite3_reset(meta_stmt);
    rc = sqlite3_bind_text(meta_stmt, 1, "type", -1, SQLITE_STATIC);
    rc = sqlite3_bind_text(meta_stmt, 2, "overlay", -1, SQLITE_STATIC);
    rc = sqlite3_step(meta_stmt);
    rc = sqlite3_reset(meta_stmt);
    rc = sqlite3_bind_text(meta_stmt, 1, "version", -1, SQLITE_STATIC);
    rc = sqlite3_bind_text(meta_stmt, 2, "1.0.0", -1, SQLITE_STATIC);
    rc = sqlite3_step(meta_stmt);
    rc = sqlite3_reset(meta_stmt);
    rc = sqlite3_bind_text(meta_stmt, 1, "description", -1, SQLITE_STATIC);
    rc = sqlite3_bind_text(
            meta_stmt, 2, description, -1, SQLITE_STATIC);
    rc = sqlite3_step(meta_stmt);
    rc = sqlite3_reset(meta_stmt);
    rc = sqlite3_bind_text(meta_stmt, 1, "format", -1, SQLITE_STATIC);
    rc = sqlite3_bind_text(meta_stmt, 2, "png", -1, SQLITE_STATIC);
    rc = sqlite3_step(meta_stmt);

    rc = sqlite3_finalize(meta_stmt);

    // Prepare the tile insert statement.
    rc = sqlite3_prepare_v2(
            db,
            "INSERT INTO tiles "
            "(zoom_level, tile_column, tile_row, tile_data) "
            "VALUES (?1, ?2, ?3, ?4);",
            -1, &tile_stmt, NULL );
}

MBTiler::~MBTiler()
{
    if (tile_stmt != NULL) {
        sqlite3_finalize(tile_stmt);
    }
    if (db != NULL) {
        sqlite3_close(db);
    }
    CPLFree(name);
    CPLFree(description);
}

void MBTiler::InsertImage(
        const char *pszFilename,
        int zoom,
        int tile_column,
        int tile_row)
{
    int rc;
    FILE *png = NULL;
    unsigned char *buffer = NULL;
    size_t file_size;
    size_t result;

    // Get the file contents.
    png = fopen(pszFilename, "rb");
    if (png == NULL) {
        throw std::runtime_error(
                "NULL result from GDALOpen() of first input image");
    }

    // obtain file size:
    fseek(png, 0, SEEK_END);
    file_size = ftell(png);
    rewind(png);

    buffer = (unsigned char *) malloc(sizeof(unsigned char)*file_size);
    if (buffer == NULL) {
        throw std::runtime_error(
                "NULL buffer");
    }
    result = fread(buffer, 1, file_size, png);
    if (result != file_size) {
        free(buffer);
        throw std::runtime_error(
                "NULL result from GDALOpen() of first input image");
    }
    fclose(png);

    rc = sqlite3_reset(tile_stmt);
    rc = sqlite3_bind_int(tile_stmt, 1, zoom);
    rc = sqlite3_bind_int(tile_stmt, 2, tile_column);
    rc = sqlite3_bind_int(tile_stmt, 3, tile_row);
    rc = sqlite3_bind_blob(tile_stmt, 4, buffer, file_size, SQLITE_STATIC);
    rc = sqlite3_step(tile_stmt);

    free(buffer);
}

int main(int argc, char** argv) {

    try {
        MBTiler tiler(argv[1], argv[2]);

        // Write one tile.
        tiler.InsertImage(
            "tests/data/15/16979/21196.png",
            15, 16979, 21196);
    }
    catch (std::exception const& ex)
    {
        std::clog << "Fail! tile not written: '" << ex.what() << "'\n";
        return 1;
    }
    return 0;
}
<commit_msg>prompt for usage if less than 2 args passed<commit_after>/*****************************************************************************
 * MBTiler
 *
 * Writes directories of suitably tiled PNGs or JPEGS to a SQLite file
 * using the SQLite C API.
 *
 * Inspired by GDAL's MBTiles driver, this module has no dependencies
 * not already provided by GDAL and OGR.
 *
 * Author: Sean Gillies <sean@mapbox.com>
 *
 ****************************************************************************/

#include "cpl_conv.h"
#include "cpl_string.h"
#include "sqlite3.h"
#include "stdlib.h"

#include <iostream>
#include <stdexcept>

class MBTiler
{
    char *name;
    char *description;
    sqlite3 *db;
    sqlite3_stmt *meta_stmt;
    sqlite3_stmt *tile_stmt;

    public:
        MBTiler(const char *pszName, const char *pszDescription);
        ~MBTiler();
        void InsertImage(
            const char *pszFilename,
            int zoom,
            int tile_column,
            int tile_row);
};

MBTiler::MBTiler(const char *pszName, const char *pszDescription)
{
    int rc;

    name = CPLStrdup(pszName);
    description = CPLStrdup(pszDescription);

    // Initialize database and create tables.
    std::string basename(pszName);
    std::string extension(".mbtiles");
    std::string filename = basename + extension;
    rc = sqlite3_open(filename.c_str(), &db);
    rc = sqlite3_exec(
            db,
            "CREATE TABLE metadata (name text, value text);",
            NULL, NULL, NULL);
    rc = sqlite3_exec(
            db,
            "CREATE TABLE tiles "
            "(zoom_level integer, tile_column integer, "
            "tile_row integer, tile_data blob);",
            NULL, NULL, NULL);

    // Write MBTiles metadata.
    rc = sqlite3_prepare_v2(
            db,
            "INSERT INTO metadata "
            "(name, value) "
            "VALUES (?1, ?2);",
            -1, &meta_stmt, NULL );
    rc = sqlite3_bind_text(meta_stmt, 1, "name", -1, SQLITE_STATIC);
    rc = sqlite3_bind_text(meta_stmt, 2, name, -1, SQLITE_STATIC);
    rc = sqlite3_step(meta_stmt);
    rc = sqlite3_reset(meta_stmt);
    rc = sqlite3_bind_text(meta_stmt, 1, "type", -1, SQLITE_STATIC);
    rc = sqlite3_bind_text(meta_stmt, 2, "overlay", -1, SQLITE_STATIC);
    rc = sqlite3_step(meta_stmt);
    rc = sqlite3_reset(meta_stmt);
    rc = sqlite3_bind_text(meta_stmt, 1, "version", -1, SQLITE_STATIC);
    rc = sqlite3_bind_text(meta_stmt, 2, "1.0.0", -1, SQLITE_STATIC);
    rc = sqlite3_step(meta_stmt);
    rc = sqlite3_reset(meta_stmt);
    rc = sqlite3_bind_text(meta_stmt, 1, "description", -1, SQLITE_STATIC);
    rc = sqlite3_bind_text(
            meta_stmt, 2, description, -1, SQLITE_STATIC);
    rc = sqlite3_step(meta_stmt);
    rc = sqlite3_reset(meta_stmt);
    rc = sqlite3_bind_text(meta_stmt, 1, "format", -1, SQLITE_STATIC);
    rc = sqlite3_bind_text(meta_stmt, 2, "png", -1, SQLITE_STATIC);
    rc = sqlite3_step(meta_stmt);

    rc = sqlite3_finalize(meta_stmt);

    // Prepare the tile insert statement.
    rc = sqlite3_prepare_v2(
            db,
            "INSERT INTO tiles "
            "(zoom_level, tile_column, tile_row, tile_data) "
            "VALUES (?1, ?2, ?3, ?4);",
            -1, &tile_stmt, NULL );
}

MBTiler::~MBTiler()
{
    if (tile_stmt != NULL) {
        sqlite3_finalize(tile_stmt);
    }
    if (db != NULL) {
        sqlite3_close(db);
    }
    CPLFree(name);
    CPLFree(description);
}

void MBTiler::InsertImage(
        const char *pszFilename,
        int zoom,
        int tile_column,
        int tile_row)
{
    int rc;
    FILE *fp = NULL;
    unsigned char *buffer = NULL;
    size_t file_size;
    size_t result;

    // Get the file contents.
    fp = fopen(pszFilename, "rb");
    if (fp == NULL) {
        throw std::runtime_error(
                "NULL result from GDALOpen() of first input image");
    }

    // obtain file size:
    fseek(fp, 0, SEEK_END);
    file_size = static_cast<size_t>(ftell(fp));
    rewind(fp);

    buffer = (unsigned char *) malloc(sizeof(unsigned char)*file_size);
    if (buffer == NULL) {
        throw std::runtime_error(
                "NULL buffer");
    }
    result = fread(buffer, 1, file_size, fp);
    if (result != file_size) {
        free(buffer);
        throw std::runtime_error(
                "NULL result from GDALOpen() of first input image");
    }
    fclose(fp);

    rc = sqlite3_reset(tile_stmt);
    rc = sqlite3_bind_int(tile_stmt, 1, zoom);
    rc = sqlite3_bind_int(tile_stmt, 2, tile_column);
    rc = sqlite3_bind_int(tile_stmt, 3, tile_row);
    rc = sqlite3_bind_blob(tile_stmt, 4, buffer, file_size, SQLITE_STATIC);
    rc = sqlite3_step(tile_stmt);

    free(buffer);
}

int main(int argc, char** argv) {

    if (argc < 3) {
        std::clog << "Usage: expects two arguments: <filename> <description>\n";
        return 1;
    }
    try {
        MBTiler tiler(argv[1], argv[2]);

        // Write one tile.
        tiler.InsertImage(
            "tests/data/15/16979/21196.png",
            15, 16979, 21196);
    }
    catch (std::exception const& ex)
    {
        std::clog << "Fail! tile not written: '" << ex.what() << "'\n";
        return 1;
    }
    return 0;
}
<|endoftext|>


<commit_before>#pragma once
#include <map>
#include <memory>
#include "database_fwd.hh"
#include "dht/i_partitioner.hh"
#include "schema.hh"

class frozen_mutation;

class memtable {
public:
    using partitions_type = std::map<dht::decorated_key, mutation_partition, dht::decorated_key::less_comparator>;
private:
    schema_ptr _schema;
    partitions_type partitions;
public:
    using const_mutation_partition_ptr = std::unique_ptr<const mutation_partition>;
public:
    explicit memtable(schema_ptr schema);
    schema_ptr schema() const { return _schema; }
    mutation_partition& find_or_create_partition(const dht::decorated_key& key);
    mutation_partition& find_or_create_partition_slow(partition_key_view key);
    row& find_or_create_row_slow(const partition_key& partition_key, const clustering_key& clustering_key);
    const_mutation_partition_ptr find_partition(const dht::decorated_key& key) const;
    void apply(const mutation& m);
    void apply(const frozen_mutation& m);
    const partitions_type& all_partitions() const;
};
<commit_msg>memtable.h: add copyright statement<commit_after>/*
 * Copyright 2015 Cloudius Systems
 */

#pragma once

#include <map>
#include <memory>
#include "database_fwd.hh"
#include "dht/i_partitioner.hh"
#include "schema.hh"

class frozen_mutation;

class memtable {
public:
    using partitions_type = std::map<dht::decorated_key, mutation_partition, dht::decorated_key::less_comparator>;
private:
    schema_ptr _schema;
    partitions_type partitions;
public:
    using const_mutation_partition_ptr = std::unique_ptr<const mutation_partition>;
public:
    explicit memtable(schema_ptr schema);
    schema_ptr schema() const { return _schema; }
    mutation_partition& find_or_create_partition(const dht::decorated_key& key);
    mutation_partition& find_or_create_partition_slow(partition_key_view key);
    row& find_or_create_row_slow(const partition_key& partition_key, const clustering_key& clustering_key);
    const_mutation_partition_ptr find_partition(const dht::decorated_key& key) const;
    void apply(const mutation& m);
    void apply(const frozen_mutation& m);
    const partitions_type& all_partitions() const;
};
<|endoftext|>


<commit_before>#ifndef SHARDING_HPP
#define SHARDING_HPP

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <boost/unordered_map.hpp>
//#include <unordered_map>
#include <utility>
#include <math.h>

#define MB_TO_BYTES 1024*1024

#include "../api/utility.hpp"

typedef boost::unordered_map<int, int> hash_t;

void shard_graph(params* par, char* gfilename){
    /* Open the graph file */
    std::ifstream gfile(gfilename);
    hash_t in_edge_count; // node <-- number of in edges

    int num_edges = 0;

    if(gfile.is_open()){
        std::string eline;
        while(getline(gfile, eline)){
            /* get an edge from the file */
            std::istringstream buff(eline);
            int from, to;

            buff >> from;
            buff >> to;

            if(in_edge_count.find(to) == in_edge_count.end()) { //if the node is encountered for the first time
                in_edge_count.insert(hash_t::value_type(to,1));
            }
            else {
                in_edge_count[to] += 1;
            }
        }

        for(auto it = in_edge_count.begin(); it != in_edge_count.end(); ++it){
            std::cout << it->first << " : " << it->second << std::endl;
            num_edges += it->second;
        }

        std::cout << "Number of nodes = " << in_edge_count.size() << std::endl;
        std::cout << "Number of edges = " << num_edges << std::endl;

        gfile.close();
    }
    else {
        std::cout << "Unable to open file" << std::endl;
        exit(1); //exit with error
    }

    /* calculate number of shards needed */
    int membudget_b = par->mem_budget * MB_TO_BYTES;
    par->max_num_edges = (int)floor((double)membudget_b / (double)par->edge_mem_cost);
    par->num_shards = (int)ceil((double)num_edges / (double)par->max_num_edges);

    std::cout << "Max number of edges per shard = " << par->max_num_edges << std::endl;
    std::cout << "Number of shards = " << par->num_shards << std::endl;

    /* create files for shards */
    /* assign vertices to shards */
    /* scan the graph file and start writing to shards */

}

#endif
<commit_msg>sharding is written but not tested, it compiles<commit_after>#ifndef SHARDING_HPP
#define SHARDING_HPP

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <boost/unordered_map.hpp>
//#include <unordered_map>
#include <utility>
#include <math.h>

#define MB_TO_BYTES 1024*1024

#include "../api/utility.hpp"

typedef boost::unordered_map<int, int> hash_t;

void shard_graph(params* par, char* gfilename){
    /* Open the graph file */
    std::ifstream gfile(gfilename);
    hash_t in_edge_count; // node <-- number of in edges

    int num_edges = 0;

    if(gfile.is_open()){
        std::string eline;
        while(getline(gfile, eline)){
            /* get an edge from the file */
            std::istringstream buff(eline);
            int from, to;

            buff >> from;
            buff >> to;

            if(in_edge_count.find(to) == in_edge_count.end()) { //if the node is encountered for the first time
                in_edge_count.insert(hash_t::value_type(to,1));
            }
            else {
                in_edge_count[to] += 1;
            }
        }

        for(auto it = in_edge_count.begin(); it != in_edge_count.end(); ++it){
            std::cout << it->first << " : " << it->second << std::endl;
            num_edges += it->second;
        }

        std::cout << "Number of nodes = " << in_edge_count.size() << std::endl;
        std::cout << "Number of edges = " << num_edges << std::endl;

        //gfile.close();
    }
    else {
        std::cout << "Unable to open file" << std::endl;
        exit(1); //exit with error
    }

    /* calculate number of shards needed */
    int membudget_b = par->mem_budget * MB_TO_BYTES;
    par->max_num_edges = (int)floor((double)membudget_b / (double)par->edge_mem_cost);
    par->num_shards = (int)ceil((double)num_edges / (double)par->max_num_edges);

    std::cout << "Max number of edges per shard = " << par->max_num_edges << std::endl;
    std::cout << "Number of shards = " << par->num_shards << std::endl;

    /* assign vertices to shards */
    hash_t node_to_shard;
    int shard_index = 0;

    for(auto it = in_edge_count.begin(); it != in_edge_count.end(); ++it){
            int dest_node = (*it).first;
            int shard_edge_count = 0;

            // when we add the that node's edges to that shard, does it cross the max number of edges limit per shard
            if(shard_edge_count + (*it).second > par->max_num_edges){
                shard_index++; // move to the next shard
                shard_edge_count = 0;
            }

            node_to_shard.insert(hash_t::value_type(dest_node, shard_index)); // assign node -> shard[i]
            shard_edge_count+= (*it).second; //add the edge count to shard edge count
    }

    /* cleanning some memory */
    in_edge_count.clear();

    /* create files for shards */
    std::vector<std::ofstream*> ofs_shards;
    std::vector<std::string> shard_fnames;

    for(int i = 0; i< par->num_shards; ++i){
        std::ostringstream buff;
        buff << "shard_";
        buff << gfilename << "_" << i;

        shard_fnames.push_back(buff.str());

        std::ofstream tempf(buff.str().c_str());
        ofs_shards.push_back(&tempf);
    }

    /* scan the graph file and start writing to shards */
    gfile.clear(); // clear the state of file stream
    gfile.seekg(0, std::ios::beg); // go to the beginning of the file

    if(gfile.is_open()){
        std::string eline;
        while(getline(gfile, eline)){
            /* get an edge from the file */
            std::istringstream buff(eline);
            int from, to;

            buff >> from;
            buff >> to;

            //add the edge to its assigned shard
            *(ofs_shards[node_to_shard[to]]) << from << " " << to << std::endl;
        }

        gfile.close();
    }

    /* close shard files */
    for(int i = 0; i< par->num_shards; ++i){
        ofs_shards[i]->close();
    }

    /* cleanning some memory */
    ofs_shards.clear();

    /* read the shard files */
    std::vector<std::ifstream*> ifs_shards;

    for(int i = 0; i< par->num_shards; ++i){
        std::ifstream tempf(shard_fnames[i]);
        ifs_shards.push_back(&tempf);
    }

    /* sort each shard according to their source node and write them to their file  */
    for(int i = 0; i< par->num_shards; ++i){
        std::map<int, std::vector<int> > shard_edge_list; // from --> to1,to2,to3

        //read first
        if(ifs_shards[i]->is_open()){
            std::string eline;
            while(getline(*ifs_shards[i], eline)){
                /* get an edge from the file */
                std::istringstream buff(eline);
                int from, to;

                buff >> from;
                buff >> to;

                if(shard_edge_list.find(from) == shard_edge_list.end()){ // if not in the map
                    std::vector<int> temp_v;
                    temp_v.push_back(to);

                    shard_edge_list.insert(std::make_pair(from,temp_v));
                }
                else {
                    shard_edge_list[from].push_back(to);
                }
            }

            ifs_shards[i]->close();
        }

        //write the sorted edges
        std::ofstream ofs_shard(shard_fnames[i]);

        //for each source node
        for(auto it = shard_edge_list.begin(); it != shard_edge_list.end(); ++it){
            //write the adj list to the shard in sorted order
            for(auto it2 = (*it).second.begin(); it2 != (*it).second.end(); ++it2){
                ofs_shard << (*it).first << " " << (*it2) << std::endl;
            }
        }

        ofs_shard.close();
    }

}
#endif
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "application.h"
#include "log.h"
#include "perfcounter.h"
#include "sysutil.h"
#include "window.h"
#include "devicemanager.h"
#include "keyboarddevice.h"
#include "settings.h"
#include <ctime>

namespace dukat
{
	Application::Application(Settings& settings)
		: settings(settings), title(settings.get_string("window.title")), paused(false), done(false), runtime(0.0f)
	{
		logger << "Initializing application." << std::endl;
		sdl_check_result(SDL_Init(SDL_INIT_EVERYTHING), "Initialize SDL");
		window = std::make_unique<Window>(settings.get_int("window.width", 640), settings.get_int("window.height", 480),
			settings.get_bool("window.fullscreen"), settings.get_bool("window.msaa"));
		window->set_title(title);
		device_manager = std::make_unique<DeviceManager>();
		device_manager->add_keyboard(window.get());
		device_manager->joystick_support = settings.get_bool("input.joystick.support", true);
		gl_check_error();
	}

	Application::~Application(void)
	{
		SDL_Quit();
	}

	int Application::run(void)
	{
		logger << "Entering application loop." << std::endl;
		Uint32 ticks, last_update = 0, last_frame = 0;
		SDL_Event e;
		while (!done)
		{
			ticks = SDL_GetTicks();

			device_manager->update();
			if (!paused)
			{
				auto delta = ((float)(ticks - last_update)) / 1000.0f;
				runtime += delta;
				update(delta);
			}
			last_update = ticks;

			// update FPS counter
			if (ticks - last_frame >= 1000)
			{
				last_fps = perfc.sum(PerformanceCounter::FRAMES);
				last_frame = ticks;
				perfc.collect_stats();
			}

			// process events
			while (SDL_PollEvent(&e))
			{
				handle_event(e);
			}

			// render to screen
			render();
			perfc.inc(PerformanceCounter::FRAMES);
			perfc.reset();
		}

		return 0;
	}

	void Application::handle_event(const SDL_Event& e)
	{
		switch (e.type)
		{
		case SDL_QUIT:
			done = true;
			break;
		case SDL_KEYDOWN:
			handle_keyboard(e);
			break;
		case SDL_WINDOWEVENT:
			handle_window_event(e);
			break;
		case SDL_JOYDEVICEADDED:
			device_manager->add_joystick(window.get(), e.jdevice.which);
			break;
		case SDL_JOYDEVICEREMOVED:
			device_manager->remove_joystick(e.jdevice.which);
			break;
		}
	}

	void Application::handle_keyboard(const SDL_Event& e)
	{
		switch (e.key.keysym.sym)
		{
		case SDLK_RETURN:
			if (e.key.keysym.mod & KMOD_ALT)
			{
				window->toggle_fullscreen();
			}
			break;
		case SDLK_PAUSE:
			toggle_pause();
			break;
		case SDLK_F12:
			{
				std::stringstream ss;
				ss << "screenshot_" << std::time(nullptr) << ".png";
				save_screenshot(ss.str());
			}
			break;
		}
	}

	void Application::handle_window_event(const SDL_Event& e)
	{
		switch (e.window.event)
		{
		case SDL_WINDOWEVENT_FOCUS_GAINED:
			if (settings.get_bool("input.mouse.lock", true))
			{
				sdl_check_result(SDL_SetRelativeMouseMode(SDL_TRUE), "Set mouse mode");
			}
	        break;
        case SDL_WINDOWEVENT_FOCUS_LOST:
    		if (settings.get_bool("input.mouse.lock", true))
			{
				sdl_check_result(SDL_SetRelativeMouseMode(SDL_FALSE), "Set mouse mode");
			}
	        break;
		case SDL_WINDOWEVENT_RESIZED:
			window->on_resize();
			break;
		case SDL_WINDOWEVENT_SIZE_CHANGED:
			break;
		}
	}
}<commit_msg>Modified screenshot key binding<commit_after>#include "stdafx.h"
#include "application.h"
#include "log.h"
#include "perfcounter.h"
#include "sysutil.h"
#include "window.h"
#include "devicemanager.h"
#include "keyboarddevice.h"
#include "settings.h"
#include <ctime>

namespace dukat
{
	Application::Application(Settings& settings)
		: settings(settings), title(settings.get_string("window.title")), paused(false), done(false), runtime(0.0f)
	{
		logger << "Initializing application." << std::endl;
		sdl_check_result(SDL_Init(SDL_INIT_EVERYTHING), "Initialize SDL");
		window = std::make_unique<Window>(settings.get_int("window.width", 640), settings.get_int("window.height", 480),
			settings.get_bool("window.fullscreen"), settings.get_bool("window.msaa"));
		window->set_title(title);
		device_manager = std::make_unique<DeviceManager>();
		device_manager->add_keyboard(window.get());
		device_manager->joystick_support = settings.get_bool("input.joystick.support", true);
		gl_check_error();
	}

	Application::~Application(void)
	{
		SDL_Quit();
	}

	int Application::run(void)
	{
		logger << "Entering application loop." << std::endl;
		Uint32 ticks, last_update = 0, last_frame = 0;
		SDL_Event e;
		while (!done)
		{
			ticks = SDL_GetTicks();

			device_manager->update();
			if (!paused)
			{
				auto delta = ((float)(ticks - last_update)) / 1000.0f;
				runtime += delta;
				update(delta);
			}
			last_update = ticks;

			// update FPS counter
			if (ticks - last_frame >= 1000)
			{
				last_fps = perfc.sum(PerformanceCounter::FRAMES);
				last_frame = ticks;
				perfc.collect_stats();
			}

			// process events
			while (SDL_PollEvent(&e))
			{
				handle_event(e);
			}

			// render to screen
			render();
			perfc.inc(PerformanceCounter::FRAMES);
			perfc.reset();
		}

		return 0;
	}

	void Application::handle_event(const SDL_Event& e)
	{
		switch (e.type)
		{
		case SDL_QUIT:
			done = true;
			break;
		case SDL_KEYDOWN:
			handle_keyboard(e);
			break;
		case SDL_WINDOWEVENT:
			handle_window_event(e);
			break;
		case SDL_JOYDEVICEADDED:
			device_manager->add_joystick(window.get(), e.jdevice.which);
			break;
		case SDL_JOYDEVICEREMOVED:
			device_manager->remove_joystick(e.jdevice.which);
			break;
		}
	}

	void Application::handle_keyboard(const SDL_Event& e)
	{
		switch (e.key.keysym.sym)
		{
		case SDLK_RETURN:
			if (e.key.keysym.mod & KMOD_ALT)
			{
				window->toggle_fullscreen();
			}
			break;
		case SDLK_PAUSE:
			toggle_pause();
			break;
		case SDLK_PRINTSCREEN:
			{
				std::stringstream ss;
				ss << "screenshot_" << std::time(nullptr) << ".png";
				save_screenshot(ss.str());
			}
			break;
		}
	}

	void Application::handle_window_event(const SDL_Event& e)
	{
		switch (e.window.event)
		{
		case SDL_WINDOWEVENT_FOCUS_GAINED:
			if (settings.get_bool("input.mouse.lock", true))
			{
				sdl_check_result(SDL_SetRelativeMouseMode(SDL_TRUE), "Set mouse mode");
			}
	        break;
        case SDL_WINDOWEVENT_FOCUS_LOST:
    		if (settings.get_bool("input.mouse.lock", true))
			{
				sdl_check_result(SDL_SetRelativeMouseMode(SDL_FALSE), "Set mouse mode");
			}
	        break;
		case SDL_WINDOWEVENT_RESIZED:
			window->on_resize();
			break;
		case SDL_WINDOWEVENT_SIZE_CHANGED:
			break;
		}
	}
}<|endoftext|>


<commit_before>#include <SFML/Window.hpp>
#include <SFML/OpenGL.hpp>

int main()
{
    // create the window
    sf::Window window(sf::VideoMode(800, 600), "OpenGL", sf::Style::Default, sf::ContextSettings(32));
    window.setVerticalSyncEnabled(true);
    window.setFramerateLimit(30);

    // load resources, initialize the OpenGL states, ...

    // run the main loop
    bool running = true;
    while (running)
    {
        // handle events
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                // end the program
                running = false;
            }
            else if (event.type == sf::Event::Resized)
            {
                // adjust the viewport when the window is resized
                glViewport(0, 0, event.size.width, event.size.height);
            }
        }

        // clear the buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // draw...

        // end the current frame (internally swaps the front and back buffers)
        window.display();
    }

    // release resources...

    return 0;
}
<commit_msg>Switched back<commit_after>/**
 * Author: newsworthy39
 * Documentation: http://www.sfml-dev.org/documentation/2.2/
 */

#include <iostream>
#include <chrono>
#include <thread>
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#include <SFML/System.hpp>

using namespace std;

sf::Http http;

void PollRequest(int * memoryBucket, int * isRunning) {

	http.setHost("http://force.mjay.me");

	while (*isRunning == 1) {
		sf::Http::Request request;

		request.setMethod(sf::Http::Request::Method::Get);
		request.setUri("/metrics.php");
		request.setHttpVersion(1, 0); // HTTP 1.1
		request.setField("From", "me");

		sf::Http::Response response = http.sendRequest(request);
		std::cout << "status: " << response.getStatus() << std::endl;
		std::cout << "HTTP version: " << response.getMajorHttpVersion() << "."
				<< response.getMinorHttpVersion() << std::endl;
		std::cout << "Content-Type header:" << response.getField("Content-Type")
				<< std::endl;
		std::cout << "body: " << response.getStatus() << std::endl;

		std::cout << "Response: " << response.getBody() << std::endl;

		*memoryBucket = std::stoi(response.getBody());

		sf::sleep(sf::seconds(5));
	}
}

int main() {

	int radius = 200; int isRunning = 1;

	sf::Thread thread(std::bind(&PollRequest, &radius, &isRunning));

	thread.launch();

	sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");

	sf::CircleShape shape((float) radius);

	shape.setFillColor(sf::Color::Green);

	while (window.isOpen()) {
		sf::Event event;
		while (window.pollEvent(event)) {
			if (event.type == sf::Event::Closed) {
				window.close();
				isRunning = 0;
				thread.wait();
			}
		}

		shape.setRadius(radius);

		window.clear();
		window.draw(shape);
		window.display();
	}

	thread.wait();

	return 0;
}
<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Nathan Osman
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 **/

#include <QDir>
#include <QStack>

#include "bundle.h"

Bundle::Bundle()
    : mTotalSize(0)
{
}

void Bundle::addFile(const QString &filename)
{
    QFileInfo info(filename);

    append(FileInfo(info));
    mTotalSize += info.size();
}

void Bundle::addDirectory(const QString &path)
{
    QDir root(path);
    QStack<QString> stack;

    stack.push(root.absolutePath());

    while(stack.count()) {
        QString tos = stack.pop();

        foreach(QFileInfo info, QDir(tos).entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
            if(info.isDir()) {
                stack.push(info.absoluteFilePath());
            } else {
                append(FileInfo(root, info));
                mTotalSize += info.size();
            }
        }
    }
}
<commit_msg>Fixed issue with the root path when enumerating files.<commit_after>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Nathan Osman
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 **/

#include <QDir>
#include <QStack>

#include "bundle.h"

Bundle::Bundle()
    : mTotalSize(0)
{
}

void Bundle::addFile(const QString &filename)
{
    QFileInfo info(filename);

    append(FileInfo(info));
    mTotalSize += info.size();
}

void Bundle::addDirectory(const QString &path)
{
    QDir root(path);
    QStack<QString> stack;

    // Push the root path on the stack and then go up one level so that
    // the relative filenames will include the name of the directory
    stack.push(root.absolutePath());
    root.cdUp();

    while(stack.count()) {
        QString tos = stack.pop();

        foreach(QFileInfo info, QDir(tos).entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
            if(info.isDir()) {
                stack.push(info.absoluteFilePath());
            } else {
                append(FileInfo(root, info));
                mTotalSize += info.size();
            }
        }
    }
}
<|endoftext|>