<commit_before>/* OpenHoW
 * Copyright (C) 2017-2019 Mark Sowden <markelswo@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "../engine.h"

#include "audio.h"
#include "frontend.h"

#ifdef __APPLE__
#   include <OpenAL/al.h>
#   include <OpenAL/alc.h>
//# include <OpenAL/alext.h>
//# include <OpenAL/efx-presets.h>
#else
#   include <AL/al.h>
#   include <AL/alc.h>
#   include <AL/alext.h>
#   include <AL/efx-presets.h>
#endif

#include <PL/platform_graphics_camera.h>

#include <SDL2/SDL_audio.h>

#include <list>

/* todo: provide fallback to SDL2 Audio? maybe dynamically load OpenAL?? */
/* todo: get this working on macOS */

static void OALCheckErrors() {
    ALenum err = alGetError();
    if(err != AL_NO_ERROR) {
        /* alut is apparently deprecated in OpenAL Soft, yay... */
        /*Error("%s\n", alutGetErrorString(err));*/

        switch(err) {
            default: Error("unknown openal error, aborting!\n");
            case AL_OUT_OF_MEMORY: Error("openal ran out of memory, aborting!\n");
            case AL_INVALID_VALUE: Error("invalid value passed to openal, aborting!\n");
            case AL_INVALID_OPERATION: Error("invalid operation performed with openal, aborting!\n");
        }
    }
}

/************************************************************/
/* Audio Source */

AudioSource::AudioSource(unsigned int al_sample, float gain, float pitch, bool looping) :
        AudioSource(al_sample, PLVector3(0, 0, 0), PLVector3(0, 0, 0), gain, pitch, looping) {
    alSourcei(al_source_id_, AL_SOURCE_RELATIVE, 1);
}

AudioSource::AudioSource(unsigned int al_sample, PLVector3 pos, PLVector3 vel, float gain, float pitch, bool looping) {
    alGenSources(1, &al_source_id_);
    OALCheckErrors();

    SetPosition(pos);
    SetVelocity(vel);
    SetGain(gain);
    SetPitch(pitch);

    alSourcei(al_source_id_, AL_LOOPING, looping);
    OALCheckErrors();

    alSourceQueueBuffers(al_source_id_, 1, &al_sample);
    OALCheckErrors();

    AudioManager::GetInstance()->sources_.insert(this);
}

AudioSource::~AudioSource() {
    AudioManager::GetInstance()->sources_.erase(this);

    alDeleteSources(1, &al_source_id_);
}

void AudioSource::SetPosition(PLVector3 position) {
    alSource3f(al_source_id_, AL_POSITION, position.x, position.y, position.z);
    OALCheckErrors();
    position_ = position;
}

void AudioSource::SetVelocity(PLVector3 velocity) {
    alSource3f(al_source_id_, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
    OALCheckErrors();
    velocity_ = velocity;
}

void AudioSource::SetGain(float gain) {
    alSourcef(al_source_id_, AL_GAIN, gain);
    OALCheckErrors();
    gain_ = gain;
}

void AudioSource::SetPitch(float pitch) {
    alSourcef(al_source_id_, AL_PITCH, pitch);
    OALCheckErrors();
    pitch_ = pitch;
}

void AudioSource::StartPlaying() {
    alSourcePlay(al_source_id_);
    OALCheckErrors();
}

void AudioSource::StopPlaying() {
    int state;
    alGetSourcei(al_source_id_, AL_SOURCE_STATE, &state);
    OALCheckErrors();
    if(state != AL_PLAYING) {
        return;
    }

    alSourceStop(al_source_id_);
}

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

static LPALGENEFFECTS alGenEffects;
static LPALDELETEEFFECTS alDeleteEffects;
static LPALISEFFECT alIsEffect;
static LPALEFFECTI alEffecti;
//static LPALEFFECTIV alEffectiv;
static LPALEFFECTF alEffectf;
//static LPALEFFECTFV alEffectfv;
//static LPALGETEFFECTI alGetEffecti;
//static LPALGETEFFECTIV alGetEffectiv;
//static LPALGETEFFECTF alGetEffectf;
//static LPALGETEFFECTFV alGetEffectfv;

static LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
static LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
static LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;
static LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
//static LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;
//static LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;
//static LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;
//static LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;
//static LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;
//static LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;
//static LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;

AudioManager *AudioManager::instance_ = nullptr;

AudioManager::AudioManager() {
    ALCdevice *device = alcOpenDevice(nullptr);
    if(device == nullptr) {
        Error("failed to open audio device, aborting audio initialisation!\n");
    }

    memset(al_extensions_, 0, sizeof(al_extensions_));

    if(alcIsExtensionPresent(device, "ALC_EXT_EFX")) {
        LogInfo("ALC_EXT_EFX detected\n");

        alGenEffects = (LPALGENEFFECTS) alGetProcAddress("alGenEffects");
        alDeleteEffects = (LPALDELETEEFFECTS) alGetProcAddress("alDeleteEffects");
        alIsEffect = (LPALISEFFECT) alGetProcAddress("alIsEffect");
        alEffecti = (LPALEFFECTI) alGetProcAddress("alEffecti");
        alEffectf = (LPALEFFECTF) alGetProcAddress("alEffectf");

        alGenAuxiliaryEffectSlots = (LPALGENAUXILIARYEFFECTSLOTS) alGetProcAddress("alGenAuxiliaryEffectSlots");
        alDeleteAuxiliaryEffectSlots = (LPALDELETEAUXILIARYEFFECTSLOTS) alGetProcAddress(
                "alDeleteAuxiliaryEffectSlots");
        alIsAuxiliaryEffectSlot = (LPALISAUXILIARYEFFECTSLOT) alGetProcAddress("alIsAuxiliaryEffectSlot");
        alAuxiliaryEffectSloti = (LPALAUXILIARYEFFECTSLOTI) alGetProcAddress("alAuxiliaryEffectSloti");

        al_extensions_[AUDIO_EXT_EFX] = true;
    }

    int attr[]={
            ALC_FREQUENCY, 44100, /* todo: tune this */
            ALC_MAX_AUXILIARY_SENDS, 4,
            0
    };

    ALCcontext *context = alcCreateContext(device, attr);
    if(context == nullptr || !alcMakeContextCurrent(context)) {
        Error("failed to create audio context, aborting audio initialisation!\n");
    }

    if(alIsExtensionPresent("AL_SOFT_buffer_samples")) {
        LogInfo("AL_SOFT_buffer_samples detected\n");
        al_extensions_[AUDIO_EXT_SOFT_BUFFER_SAMPLES] = true;
    }

    alDopplerFactor(4.f);
    alDopplerVelocity(350.f);
}

AudioManager::~AudioManager() {
    LogInfo("shutting down audio sub-system...\n");

    FreeSources();
    FreeSamples();

    ALCcontext *context = alcGetCurrentContext();
    if(context != nullptr) {
        alcMakeContextCurrent(nullptr);
        alcDestroyContext(context);

        ALCdevice *device = alcGetContextsDevice(context);
        if(device != nullptr) {
            alcCloseDevice(device);
        }
    }
}

void AudioManager::CacheSample(const std::string &path, bool preserve) {
    auto i = samples_.find(path);
    if(i != samples_.end()) {
        LogWarn("attempted to double cache audio sample, \"%s\"!\n", path.c_str());
        return;
    }

    /* todo: ensure the path is under <basedir/campaign>/audio/ ? */

    SDL_AudioSpec spec;
    uint32_t length;
    uint8_t *buffer;
    if(SDL_LoadWAV(u_find(path.c_str()), &spec, &buffer, &length) == nullptr) {
        LogWarn("failed to load \"%s\"!\n", path);
        return;
    }

    /* translate the spec over to oal
     * todo: conversion... https://github.com/solemnwarning/armageddon-recorder/blob/master/src/resample.hpp#L42
     * */
    unsigned int format = 0;
    switch(spec.format) {
        case AUDIO_U8:
            if(spec.channels == 1) {
                format = AL_FORMAT_MONO8;
            } else if(spec.channels == 2) {
                format = AL_FORMAT_STEREO8;
            }
            break;
        case AUDIO_S16:
            if(spec.channels == 1) {
                format = AL_FORMAT_MONO16;
            } else if(spec.channels == 2) {
                format = AL_FORMAT_STEREO16;
            }
            break;
        default:break;
    }

    if(format == 0) {
        LogWarn("invalid audio format for \"%s\"!\n", path);
        SDL_FreeWAV(buffer);
        return;
    }

    samples_.emplace(
            std::piecewise_construct,
            std::forward_as_tuple(path),
            std::forward_as_tuple(buffer, spec.freq, format, length, preserve)
            );
}

const AudioManager::AudioSample *AudioManager::GetCachedSample(const std::string &path) {
    auto i = samples_.find(path);
    if(i == samples_.end()) {
        CacheSample(path, false);
        i = samples_.find(path);
        if(i == samples_.end()) {
            Error("failed to load sample, \"%s\"!\n", path.c_str());
            /* todo: in future, fall back to first loaded sound and continue? if it exists... */
        }
    }

    return &(i->second);
}

AudioSource *AudioManager::CreateSource(const std::string &path, float gain, float pitch, bool looping) {
    return new AudioSource(GetCachedSample(path)->al_buffer_id_, gain, pitch, looping);
}

AudioSource *AudioManager::CreateSource(const std::string &path, PLVector3 pos, PLVector3 vel, float gain,
                                        float pitch, bool looping) {
    return new AudioSource(GetCachedSample(path)->al_buffer_id_, pos, vel, gain, pitch, looping);
}

void AudioManager::Simulate() {
    PLVector3 position = {0,0,0}, angles = {0,0,0};
    if(FE_GetState() == FE_MODE_GAME) {
        position = g_state.camera->position;
        angles = g_state.camera->angles;
    }

    PLVector3 forward, left, up;
    plAnglesAxes(angles, &left, &up, &forward);

    float ori[6];
    ori[0] = forward.x; ori[3] = up.x;
    ori[1] = forward.y; ori[4] = up.y;
    ori[2] = forward.z; ori[5] = up.z;

    alListener3f(AL_POSITION, position.x, position.y, position.z);
    alListenerfv(AL_ORIENTATION, ori);
}

void AudioManager::PlayGlobalSound(const std::string &path) {
    global_source_.reset(CreateSource(path));
    global_source_->StartPlaying();
}

void AudioManager::SilenceSources() {
    for(auto sound : sources_) {
        sound->StopPlaying();
    }

    global_source_->StopPlaying();
}

/* Will invalidate ALL references to AudioSource objects.
 * Only use in contexts where this is safe. */
void AudioManager::FreeSources() {
    LogInfo("freeing all audio sources...\n");

    SilenceSources();
    global_source_.reset(nullptr);
    sources_.clear();
}

void AudioManager::FreeSamples(bool force) {
    u_assert(sources_.empty(), "audio sources weren't emptied!\n");

    LogInfo("freeing all audio samples...\n");

    if(force) {
        /* clears absolutely everything */
        samples_.clear();
    } else {
        /* clears only those not marked with preserve */
        for(auto sample = samples_.begin(); sample != samples_.end();) {
            if(!sample->second.preserve_) {
                sample = samples_.erase(sample);
            } else {
                ++sample;
            }
        }
    }
}

/************************************************************/
/* Audio Sample */

AudioManager::AudioSample::~AudioSample() {
    alDeleteBuffers(1, &al_buffer_id_);
    OALCheckErrors();

    SDL_FreeWAV(data_);
}

AudioManager::AudioSample::AudioSample(uint8_t *data, unsigned int freq, unsigned int format, unsigned int length, bool preserve) {
    alGenBuffers(1, &al_buffer_id_);
    OALCheckErrors();
    alBufferData(al_buffer_id_, format, data, length, freq);
    OALCheckErrors();
}
<commit_msg>fixed LogWarn for wav load fail<commit_after>/* OpenHoW
 * Copyright (C) 2017-2019 Mark Sowden <markelswo@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "../engine.h"

#include "audio.h"
#include "frontend.h"

#ifdef __APPLE__
#   include <OpenAL/al.h>
#   include <OpenAL/alc.h>
//# include <OpenAL/alext.h>
//# include <OpenAL/efx-presets.h>
#else
#   include <AL/al.h>
#   include <AL/alc.h>
#   include <AL/alext.h>
#   include <AL/efx-presets.h>
#endif

#include <SDL2/SDL_audio.h>
#include <PL/platform_graphics_camera.h>

#include <list>

/* todo: provide fallback to SDL2 Audio? maybe dynamically load OpenAL?? */
/* todo: get this working on macOS */

static void OALCheckErrors() {
    ALenum err = alGetError();
    if(err != AL_NO_ERROR) {
        /* alut is apparently deprecated in OpenAL Soft, yay... */
        /*Error("%s\n", alutGetErrorString(err));*/

        switch(err) {
            default: Error("unknown openal error, aborting!\n");
            case AL_OUT_OF_MEMORY: Error("openal ran out of memory, aborting!\n");
            case AL_INVALID_VALUE: Error("invalid value passed to openal, aborting!\n");
            case AL_INVALID_OPERATION: Error("invalid operation performed with openal, aborting!\n");
        }
    }
}

/************************************************************/
/* Audio Source */

AudioSource::AudioSource(unsigned int al_sample, float gain, float pitch, bool looping) :
        AudioSource(al_sample, PLVector3(0, 0, 0), PLVector3(0, 0, 0), gain, pitch, looping) {
    alSourcei(al_source_id_, AL_SOURCE_RELATIVE, 1);
}

AudioSource::AudioSource(unsigned int al_sample, PLVector3 pos, PLVector3 vel, float gain, float pitch, bool looping) {
    alGenSources(1, &al_source_id_);
    OALCheckErrors();

    SetPosition(pos);
    SetVelocity(vel);
    SetGain(gain);
    SetPitch(pitch);

    alSourcei(al_source_id_, AL_LOOPING, looping);
    OALCheckErrors();

    alSourceQueueBuffers(al_source_id_, 1, &al_sample);
    OALCheckErrors();

    AudioManager::GetInstance()->sources_.insert(this);
}

AudioSource::~AudioSource() {
    AudioManager::GetInstance()->sources_.erase(this);
    alDeleteSources(1, &al_source_id_);
}

void AudioSource::SetPosition(PLVector3 position) {
    alSource3f(al_source_id_, AL_POSITION, position.x, position.y, position.z);
    OALCheckErrors();
    position_ = position;
}

void AudioSource::SetVelocity(PLVector3 velocity) {
    alSource3f(al_source_id_, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
    OALCheckErrors();
    velocity_ = velocity;
}

void AudioSource::SetGain(float gain) {
    alSourcef(al_source_id_, AL_GAIN, gain);
    OALCheckErrors();
    gain_ = gain;
}

void AudioSource::SetPitch(float pitch) {
    alSourcef(al_source_id_, AL_PITCH, pitch);
    OALCheckErrors();
    pitch_ = pitch;
}

void AudioSource::StartPlaying() {
    alSourcePlay(al_source_id_);
    OALCheckErrors();
}

void AudioSource::StopPlaying() {
    int state;
    alGetSourcei(al_source_id_, AL_SOURCE_STATE, &state);
    OALCheckErrors();
    if(state != AL_PLAYING) {
        return;
    }

    alSourceStop(al_source_id_);
}

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

static LPALGENEFFECTS alGenEffects;
static LPALDELETEEFFECTS alDeleteEffects;
static LPALISEFFECT alIsEffect;
static LPALEFFECTI alEffecti;
//static LPALEFFECTIV alEffectiv;
static LPALEFFECTF alEffectf;
//static LPALEFFECTFV alEffectfv;
//static LPALGETEFFECTI alGetEffecti;
//static LPALGETEFFECTIV alGetEffectiv;
//static LPALGETEFFECTF alGetEffectf;
//static LPALGETEFFECTFV alGetEffectfv;

static LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
static LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
static LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;
static LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
//static LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;
//static LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;
//static LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;
//static LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;
//static LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;
//static LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;
//static LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;

AudioManager *AudioManager::instance_ = nullptr;

AudioManager::AudioManager() {
    ALCdevice *device = alcOpenDevice(nullptr);
    if(device == nullptr) {
        Error("failed to open audio device, aborting audio initialisation!\n");
    }

    memset(al_extensions_, 0, sizeof(al_extensions_));

    if(alcIsExtensionPresent(device, "ALC_EXT_EFX")) {
        LogInfo("ALC_EXT_EFX detected\n");

        alGenEffects = (LPALGENEFFECTS) alGetProcAddress("alGenEffects");
        alDeleteEffects = (LPALDELETEEFFECTS) alGetProcAddress("alDeleteEffects");
        alIsEffect = (LPALISEFFECT) alGetProcAddress("alIsEffect");
        alEffecti = (LPALEFFECTI) alGetProcAddress("alEffecti");
        alEffectf = (LPALEFFECTF) alGetProcAddress("alEffectf");

        alGenAuxiliaryEffectSlots = (LPALGENAUXILIARYEFFECTSLOTS) alGetProcAddress("alGenAuxiliaryEffectSlots");
        alDeleteAuxiliaryEffectSlots = (LPALDELETEAUXILIARYEFFECTSLOTS) alGetProcAddress(
                "alDeleteAuxiliaryEffectSlots");
        alIsAuxiliaryEffectSlot = (LPALISAUXILIARYEFFECTSLOT) alGetProcAddress("alIsAuxiliaryEffectSlot");
        alAuxiliaryEffectSloti = (LPALAUXILIARYEFFECTSLOTI) alGetProcAddress("alAuxiliaryEffectSloti");

        al_extensions_[AUDIO_EXT_EFX] = true;
    }

    int attr[]={
            ALC_FREQUENCY, 44100, /* todo: tune this */
            ALC_MAX_AUXILIARY_SENDS, 4,
            0
    };

    ALCcontext *context = alcCreateContext(device, attr);
    if(context == nullptr || !alcMakeContextCurrent(context)) {
        Error("failed to create audio context, aborting audio initialisation!\n");
    }

    if(alIsExtensionPresent("AL_SOFT_buffer_samples")) {
        LogInfo("AL_SOFT_buffer_samples detected\n");
        al_extensions_[AUDIO_EXT_SOFT_BUFFER_SAMPLES] = true;
    }

    alDopplerFactor(4.f);
    alDopplerVelocity(350.f);
}

AudioManager::~AudioManager() {
    LogInfo("shutting down audio sub-system...\n");

    FreeSources();
    FreeSamples();

    ALCcontext *context = alcGetCurrentContext();
    if(context != nullptr) {
        alcMakeContextCurrent(nullptr);
        alcDestroyContext(context);

        ALCdevice *device = alcGetContextsDevice(context);
        if(device != nullptr) {
            alcCloseDevice(device);
        }
    }
}

void AudioManager::CacheSample(const std::string &path, bool preserve) {
    auto i = samples_.find(path);
    if(i != samples_.end()) {
        LogWarn("attempted to double cache audio sample, \"%s\"!\n", path.c_str());
        return;
    }

    /* todo: ensure the path is under <basedir/campaign>/audio/ ? */

    SDL_AudioSpec spec;
    uint32_t length;
    uint8_t *buffer;
    if(SDL_LoadWAV(u_find(path.c_str()), &spec, &buffer, &length) == nullptr) {
        LogWarn("failed to load \"%s\"!\n", path.c_str());
        return;
    }

    /* translate the spec over to oal
     * todo: conversion... https://github.com/solemnwarning/armageddon-recorder/blob/master/src/resample.hpp#L42
     * */
    unsigned int format = 0;
    switch(spec.format) {
        case AUDIO_U8:
            if(spec.channels == 1) {
                format = AL_FORMAT_MONO8;
            } else if(spec.channels == 2) {
                format = AL_FORMAT_STEREO8;
            }
            break;
        case AUDIO_S16:
            if(spec.channels == 1) {
                format = AL_FORMAT_MONO16;
            } else if(spec.channels == 2) {
                format = AL_FORMAT_STEREO16;
            }
            break;
        default:break;
    }

    if(format == 0) {
        LogWarn("invalid audio format for \"%s\"!\n", path);
        SDL_FreeWAV(buffer);
        return;
    }

    samples_.emplace(
            std::piecewise_construct,
            std::forward_as_tuple(path),
            std::forward_as_tuple(buffer, spec.freq, format, length, preserve)
            );
}

const AudioManager::AudioSample *AudioManager::GetCachedSample(const std::string &path) {
    auto i = samples_.find(path);
    if(i == samples_.end()) {
        CacheSample(path, false);
        i = samples_.find(path);
        if(i == samples_.end()) {
            Error("failed to load sample, \"%s\"!\n", path.c_str());
            /* todo: in future, fall back to first loaded sound and continue? if it exists... */
        }
    }

    return &(i->second);
}

AudioSource *AudioManager::CreateSource(const std::string &path, float gain, float pitch, bool looping) {
    return new AudioSource(GetCachedSample(path)->al_buffer_id_, gain, pitch, looping);
}

AudioSource *AudioManager::CreateSource(const std::string &path, PLVector3 pos, PLVector3 vel, float gain,
                                        float pitch, bool looping) {
    return new AudioSource(GetCachedSample(path)->al_buffer_id_, pos, vel, gain, pitch, looping);
}

void AudioManager::Simulate() {
    PLVector3 position = {0,0,0}, angles = {0,0,0};
    if(FE_GetState() == FE_MODE_GAME) {
        position = g_state.camera->position;
        angles = g_state.camera->angles;
    }

    PLVector3 forward, left, up;
    plAnglesAxes(angles, &left, &up, &forward);

    float ori[6];
    ori[0] = forward.x; ori[3] = up.x;
    ori[1] = forward.y; ori[4] = up.y;
    ori[2] = forward.z; ori[5] = up.z;

    alListener3f(AL_POSITION, position.x, position.y, position.z);
    alListenerfv(AL_ORIENTATION, ori);
}

void AudioManager::PlayGlobalSound(const std::string &path) {
    global_source_.reset(CreateSource(path));
    global_source_->StartPlaying();
}

void AudioManager::SilenceSources() {
    for(auto sound : sources_) {
        sound->StopPlaying();
    }

    global_source_->StopPlaying();
}

/* Will invalidate ALL references to AudioSource objects.
 * Only use in contexts where this is safe. */
void AudioManager::FreeSources() {
    LogInfo("freeing all audio sources...\n");

    SilenceSources();
    global_source_.reset(nullptr);
    sources_.clear();
}

void AudioManager::FreeSamples(bool force) {
    u_assert(sources_.empty(), "audio sources weren't emptied!\n");

    LogInfo("freeing all audio samples...\n");

    if(force) {
        /* clears absolutely everything */
        samples_.clear();
    } else {
        /* clears only those not marked with preserve */
        for(auto sample = samples_.begin(); sample != samples_.end();) {
            if(!sample->second.preserve_) {
                sample = samples_.erase(sample);
            } else {
                ++sample;
            }
        }
    }
}

/************************************************************/
/* Audio Sample */

AudioManager::AudioSample::~AudioSample() {
    alDeleteBuffers(1, &al_buffer_id_);
    OALCheckErrors();

    SDL_FreeWAV(data_);
}

AudioManager::AudioSample::AudioSample(uint8_t *data, unsigned int freq, unsigned int format, unsigned int length, bool preserve) {
    alGenBuffers(1, &al_buffer_id_);
    OALCheckErrors();
    alBufferData(al_buffer_id_, format, data, length, freq);
    OALCheckErrors();
}
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "graphSettingsPopup.h"
#include <QDateTime>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

#ifdef PMD_HAMP
    ui->pbtn_StartStop->setChecked(true);
#endif

    m_alarmBtnNormalStyleSheet=ui->pbtn_ECG_Alarm->styleSheet();
    m_alarmBtnRedStyleSheet= "*{border: 0px;background-image: url(:/images/icnBellRed.png);} *:checked{background-image:url();}";

    m_graphWidget1 = new Widget(ui->graphECGWidget,this);
#ifndef ONLY_SHOW_ECG_GRAPH
    m_graphWidget2 = new Widget(ui->graphABPWidget,this);
    m_graphWidget3 = new Widget(ui->graphPLETHWidget,this);
#endif

    m_graphWidget1->initialized(GraphECG,3);
#ifndef ONLY_SHOW_ECG_GRAPH
    m_graphWidget2->initialized(GraphABP,1);
    m_graphWidget3->initialized(GraphPLETH,2);
#endif

    m_selectedGraphWidget = NULL;

    // Set time
    updateTimeString();

    // Setup timer to update UI
    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(updateTimeString()));
    timer->start(1000);

    m_timerAlarm =new QTimer (this);
    connect(m_timerAlarm, SIGNAL(timeout()), this, SLOT(animateAlarm()));
    m_timerAlarm->setInterval(500);
    m_timerAlarm->stop();

    m_timerDataValues = new QTimer(this);
#ifndef DISABLE_RIGHT_PANEL_NUMERIC_VALUES
    connect(m_timerDataValues, SIGNAL(timeout()), this, SLOT(updatePulse()));
    connect(m_timerDataValues, SIGNAL(timeout()), this, SLOT(updateABP()));
    connect(m_timerDataValues, SIGNAL(timeout()), this, SLOT(updatePLETH()));
    m_timerDataValues->setInterval(3000);
    #ifndef PMD_HAMP
        m_timerDataValues->start();
    #endif
#endif

    m_HB_Simulate_Data << 70 << 68 << 71 << 69<< 67<< 68;
    m_ABP_Higher_Simulate_Data << 100 << 110 << 107 << 124<< 137<< 119;
    m_ABP_Lower_Simulate_Data << 73 << 88 << 77 << 82 << 91 << 79;
    m_PLETH_Simulate_Data << 93 << 96 << 90 << 97 << 95 << 99;

    m_cstatus=true;

#ifdef PMD_MEHV
    m_nserver =new Server(this);
    m_cstatus=false;
#endif

#ifdef PMD_NUCLEUS
    m_dataSupplier=new DataSupplier(this);
#endif

#ifdef PMD_HAMP
    m_hampdataSupplier =new HAMPDataSupplier(this);
    m_cstatus=true;

    // Setup timer to update UI
    QTimer *hamptimer = new QTimer(this);
    connect(hamptimer, SIGNAL(timeout()), this, SLOT(takeScreenSnapshort()));
    hamptimer->start(3000);

#endif

    m_isPauseAll=false;
    m_isStart=true;
    m_isAlarmSilent=false;
    m_btnSilentPressed=false;

    m_graphSettingsPop =new GraphSettingsPopup(this);
    m_graphSettingsPop->hide();

    // Setup graph scrolling mode
#ifdef ENABLE_GRAPH_SCROLLING
    on_pbtn_Scrolling_clicked(true);
    ui->pbtn_Scrolling->setChecked(true);
#else
    on_pbtn_Scrolling_clicked(false);
    ui->pbtn_Scrolling->setChecked(false);
#endif
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::updatePulse()
{
    QString value="0";

    if(m_isPauseAll==true || m_isStart==false)
        return;

    if(m_cstatus)
    {
        value.setNum(this->getPulseValue());
    }

    ui->labelPulse->setText(value);
    ui->labelPulse->repaint();
}

void MainWindow::updateABP()
{

    if(m_isPauseAll==true || m_isStart==false)
        return;

    if(m_cstatus)
    {
      ui->labelABP->setText(this->getABPValue());
    }
    else
        ui->labelABP->setText("0/0");

    ui->labelABP->repaint();
}

void MainWindow::updatePLETH()
{
    if(m_isPauseAll==true || m_isStart==false)
        return;

    if(m_cstatus)
    {
      ui->labelSPO2->setText(this->getPLETHValue());
    }
    else
        ui->labelSPO2->setText("0");

    ui->labelABP->repaint();
}

void MainWindow::updateTimeString()
{
    //get current date and time
    QDateTime dateTime = QDateTime::currentDateTime();
    QString dateTimeString = dateTime.toString("hh:mm:ss AP");
    ui->labelTime->setText(dateTimeString);
    ui->labelTime->repaint();
}

int MainWindow::getPulseValue()
{
    static int index=-1;

    if(index==this->m_HB_Simulate_Data.count()-1)
        index=0;
    else
        index++;

    return m_HB_Simulate_Data[index];
}

QString MainWindow::getABPValue()
{
    static int index=-1;

    if(index==this->m_ABP_Higher_Simulate_Data.count()-1)
        index=0;
    else
        index++;

    QString str=QString("%1/%2").arg(m_ABP_Higher_Simulate_Data[index]).arg(m_ABP_Lower_Simulate_Data[index]);
    return str;
}

QString MainWindow::getPLETHValue()
{
    static int index=-1;

    if(index==this->m_PLETH_Simulate_Data.count()-1)
        index=0;
    else
        index++;

    QString str=QString("%1").arg(m_PLETH_Simulate_Data[index]);
    return str;
}

void MainWindow::on_pbtn_Silent_clicked()
{
   m_btnSilentPressed=!m_btnSilentPressed;
    if(m_btnSilentPressed)
    {
        ui->pbtn_ECG_Alarm->setChecked(true);
        ui->pbtn_ABP_Alarm->setChecked(true);
        ui->pbtn_spo2_Alarm->setChecked(true);
        m_isAlarmSilent=true;
       // ui->pbtn_Silent->setStyleSheet("*{border: 0px;background-image: url(:/images/btn_pressed.png);}");
    }
    else
    {
        ui->pbtn_ECG_Alarm->setChecked(false);
        ui->pbtn_ABP_Alarm->setChecked(false);
        ui->pbtn_spo2_Alarm->setChecked(false);
        m_isAlarmSilent=false;
        //ui->pbtn_Silent->setStyleSheet("");
    }
}

void MainWindow::on_pbtn_StartStop_clicked(bool checked)
{

#ifdef PMD_HAMP

    if(checked)
    {
        m_isStart=false;
        m_timerDataValues->stop();
        ui->pbtn_StartStop->setText("Start");
        m_hampdataSupplier->startStopNucleus(m_isStart);
        m_cstatus=false;
    }
    else
    {
        m_isStart=true;
        ui->pbtn_StartStop->setText("Stop");
        m_timerDataValues->start();
        m_hampdataSupplier->startStopNucleus(m_isStart);
        m_cstatus=true;

    }
   fflush(stdout);
#else

    if(checked)
    {
        m_isStart=false;
        this->m_graphWidget1->clearWidget();
#ifndef ONLY_SHOW_ECG_GRAPH
        this->m_graphWidget2->clearWidget();
        this->m_graphWidget3->clearWidget();
#endif
        ui->pbtn_StartStop->setText("Start");
    }
    else
    {
        m_isStart=true;
        ui->pbtn_StartStop->setText("Stop");
    }

#endif

}

void MainWindow::on_pbtn_PauseAll_clicked(bool checked)
{
    if(!checked)
    {
        m_isPauseAll=false;
        ui->pbtn_PauseAll->setText("Pause All");
    }
    else
    {
        m_isPauseAll=true;
        this->m_graphWidget1->clearWidget();
#ifndef ONLY_SHOW_ECG_GRAPH
        this->m_graphWidget2->clearWidget();
        this->m_graphWidget3->clearWidget();
#endif
        ui->pbtn_PauseAll->setText("Start All");
    }
}

void MainWindow::on_pbtn_Scrolling_clicked(bool checked)
{
 (void)checked;
#ifndef PMD_HAMP
    m_graphWidget1->setScrollingMode(checked);
#ifndef ONLY_SHOW_ECG_GRAPH
    m_graphWidget2->setScrollingMode(checked);
    m_graphWidget3->setScrollingMode(checked);
#endif
#endif
}

void MainWindow::updateTimer()
{
#ifdef PMD_MEHV
    pm_data_struct pm={0,0,0,0};
    dataReceived (&pm);
#endif
}

void MainWindow::animateAlarm()
{
    ui->pbtn_ABP_Alarm->toggle();
    ui->pbtn_ECG_Alarm->toggle();
    ui->pbtn_spo2_Alarm->toggle();
}

void MainWindow::on_pbtn_ECG_Alarm_clicked(bool checked)
{
    (void)checked;
}

void MainWindow::on_pbtn_spo2_Alarm_clicked(bool checked)
{
    (void)checked;
}

void MainWindow::on_pbtn_ABP_Alarm_clicked(bool checked)
{
    (void)checked;
}

void MainWindow::dataReceived(pm_data_struct *current)
{
	if (m_isPauseAll==false)
    {
		switch(m_graphWidget1->getGraphType())
        {

        case GraphECG:
            m_graphWidget1->animate(current->ecgValue);
        break;

        case GraphABP:
            m_graphWidget1->animate(current->abpValue);
        break;

        case GraphPLETH:
            m_graphWidget1->animate(current->plethValue);
        break;

        case GraphCO2:
            //TODO
        break;
        }

#ifndef ONLY_SHOW_ECG_GRAPH
        switch(m_graphWidget2->getGraphType())
        {
        case GraphECG:
            m_graphWidget2->animate(current->ecgValue);
        break;

        case GraphABP:
            m_graphWidget2->animate(current->abpValue);
        break;

        case GraphPLETH:
            m_graphWidget2->animate(current->plethValue);
        break;

        case GraphCO2:
            //TODO
        break;
        }

        switch(m_graphWidget3->getGraphType())
        {
        case GraphECG:
            m_graphWidget3->animate(current->ecgValue);
        break;

        case GraphABP:
            m_graphWidget3->animate(current->abpValue);
        break;

        case GraphPLETH:
            m_graphWidget3->animate(current->plethValue);
        break;

        case GraphCO2:
            //TODO
        break;
        }
#endif
    }
}

#ifndef PMD_NUCLEUS
void MainWindow::connectionStatus(bool status)
{
    QDateTime dateTime = QDateTime::currentDateTime();
    QString dateTimeString = dateTime.toString("hh:mmap");
    m_cstatus=status;

    if(status)
    {
        ui->labelBulletText->setText("External system connected at "+dateTimeString);
        ui->labelBulletText->repaint();
        ui->pbtn_ECG_Alarm->setStyleSheet(m_alarmBtnNormalStyleSheet);
        ui->pbtn_ABP_Alarm->setStyleSheet(m_alarmBtnNormalStyleSheet);
        ui->pbtn_spo2_Alarm->setStyleSheet(m_alarmBtnNormalStyleSheet);
        ui->pbtn_ABP_Alarm->setDisabled(false);
        ui->pbtn_ECG_Alarm->setDisabled(false);
        ui->pbtn_spo2_Alarm->setDisabled(false);
        m_timerAlarm->stop();

    }
    else
    {
        ui->labelBulletText->setText("External system disconnected at "+dateTimeString);
        ui->labelBulletText->repaint();
        ui->pbtn_ECG_Alarm->setStyleSheet(m_alarmBtnRedStyleSheet);
        ui->pbtn_ABP_Alarm->setStyleSheet(m_alarmBtnRedStyleSheet);
        ui->pbtn_spo2_Alarm->setStyleSheet(m_alarmBtnRedStyleSheet);
        ui->pbtn_ABP_Alarm->setDisabled(true);
        ui->pbtn_ECG_Alarm->setDisabled(true);
        ui->pbtn_spo2_Alarm->setDisabled(true);

        m_timerAlarm->start();
        updatePLETH();
        updateABP();
        updatePulse();
    }
}
#endif

void MainWindow::launchGraphMenuPopup(Widget *widget)
{
   if(m_graphSettingsPop->m_isVisible==false)
   {
       m_selectedGraphWidget=widget;
       switch(m_selectedGraphWidget->getGraphType())
       {
           case GraphECG:
            m_graphSettingsPop->initialized(m_selectedGraphWidget->getGraphWaveSize(),GraphECG);
           break;

           case GraphABP:
            m_graphSettingsPop->initialized(m_selectedGraphWidget->getGraphWaveSize(),GraphABP);
           break;

           case GraphPLETH:
            m_graphSettingsPop->initialized(m_selectedGraphWidget->getGraphWaveSize(),GraphPLETH);
           break;

           case GraphCO2:
                 //TODO
           break;
       }
       m_graphSettingsPop->show();
   }
}

void MainWindow::onGraphMenuPopupOk()
{
    if(m_selectedGraphWidget->getGraphWaveSize()!=m_graphSettingsPop->m_graphWaveSize)
    {
        switch(m_selectedGraphWidget->getGraphType())
        {
            case GraphECG:
                 m_selectedGraphWidget->initialized(GraphECG,m_graphSettingsPop->m_graphWaveSize);
                 m_selectedGraphWidget->repaint();
            break;

            case GraphABP:
                m_selectedGraphWidget->initialized(GraphABP,m_graphSettingsPop->m_graphWaveSize);
                m_selectedGraphWidget->repaint();
            break;

            case GraphPLETH:
                m_selectedGraphWidget->initialized(GraphPLETH,m_graphSettingsPop->m_graphWaveSize);
                m_selectedGraphWidget->repaint();
            break;

            case GraphCO2:
                  //TODO
            break;
        }
    }

    m_graphSettingsPop->hide();
    m_graphSettingsPop->close();
    m_graphSettingsPop->m_isVisible=false;
    m_selectedGraphWidget=NULL;
}

void MainWindow::onGraphMenuPopupCancel()
{
    m_graphSettingsPop->hide();
    m_graphSettingsPop->close();
    m_graphSettingsPop->m_isVisible=false;
    m_selectedGraphWidget=NULL;
}

#ifdef PMD_HAMP

void  MainWindow::takeScreenSnapshort()
{
    QRect r= this->rect();
    QPixmap pixmap=this->grab(r);
    QString fileName = m_hampdataSupplier->getScreenShortPath();

    if(pixmap.isNull()==false)
        pixmap.save(fileName,"PNG");
    else
        printf("\npixmap is NULL");
}

#endif
<commit_msg>test 1<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "graphSettingsPopup.h"
#include <QDateTime>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

#ifdef PMD_HAMP
    ui->pbtn_StartStop->setChecked(true);
#endif

    m_alarmBtnNormalStyleSheet=ui->pbtn_ECG_Alarm->styleSheet();
    m_alarmBtnRedStyleSheet= "*{border: 0px;background-image: url(:/images/icnBellRed.png);} *:checked{background-image:url();}";

    m_graphWidget1 = new Widget(ui->graphECGWidget,this);
#ifndef ONLY_SHOW_ECG_GRAPH
    m_graphWidget2 = new Widget(ui->graphABPWidget,this);
    m_graphWidget3 = new Widget(ui->graphPLETHWidget,this);
#endif

    m_graphWidget1->initialized(GraphECG,3);
#ifndef ONLY_SHOW_ECG_GRAPH
    m_graphWidget2->initialized(GraphABP,1);
    m_graphWidget3->initialized(GraphPLETH,2);
#endif

    m_selectedGraphWidget = NULL;

    // Set time
    updateTimeString();

    // Setup timer to update UI
    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(updateTimeString()));
    timer->start(1000);

    m_timerAlarm =new QTimer (this);
    connect(m_timerAlarm, SIGNAL(timeout()), this, SLOT(animateAlarm()));
    m_timerAlarm->setInterval(500);
    m_timerAlarm->stop();

    m_timerDataValues = new QTimer(this);
#ifndef DISABLE_RIGHT_PANEL_NUMERIC_VALUES
    connect(m_timerDataValues, SIGNAL(timeout()), this, SLOT(updatePulse()));
    connect(m_timerDataValues, SIGNAL(timeout()), this, SLOT(updateABP()));
    connect(m_timerDataValues, SIGNAL(timeout()), this, SLOT(updatePLETH()));
    m_timerDataValues->setInterval(3000);
    #ifndef PMD_HAMP
        m_timerDataValues->start();
    #endif
#endif

    m_HB_Simulate_Data << 70 << 68 << 71 << 69<< 67<< 68;
    m_ABP_Higher_Simulate_Data << 100 << 110 << 107 << 124<< 137<< 119;
    m_ABP_Lower_Simulate_Data << 73 << 88 << 77 << 82 << 91 << 79;
    m_PLETH_Simulate_Data << 93 << 96 << 90 << 97 << 95 << 99;

    m_cstatus=true;

#ifdef PMD_MEHV
    m_nserver =new Server(this);
    m_cstatus=false;
#endif

#ifdef PMD_NUCLEUS
    m_dataSupplier=new DataSupplier(this);
#endif

#ifdef PMD_HAMP
	printf("Creating HAMPDataSupplier\n");
    m_hampdataSupplier =new HAMPDataSupplier(this);
    m_cstatus=true;

    // Setup timer to update UI
    QTimer *hamptimer = new QTimer(this);
    connect(hamptimer, SIGNAL(timeout()), this, SLOT(takeScreenSnapshort()));
    hamptimer->start(3000);

#endif

    m_isPauseAll=false;
    m_isStart=true;
    m_isAlarmSilent=false;
    m_btnSilentPressed=false;

    m_graphSettingsPop =new GraphSettingsPopup(this);
    m_graphSettingsPop->hide();

    // Setup graph scrolling mode
#ifdef ENABLE_GRAPH_SCROLLING
    on_pbtn_Scrolling_clicked(true);
    ui->pbtn_Scrolling->setChecked(true);
#else
    on_pbtn_Scrolling_clicked(false);
    ui->pbtn_Scrolling->setChecked(false);
#endif
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::updatePulse()
{
    QString value="0";

    if(m_isPauseAll==true || m_isStart==false)
        return;

    if(m_cstatus)
    {
        value.setNum(this->getPulseValue());
    }

    ui->labelPulse->setText(value);
    ui->labelPulse->repaint();
}

void MainWindow::updateABP()
{

    if(m_isPauseAll==true || m_isStart==false)
        return;

    if(m_cstatus)
    {
      ui->labelABP->setText(this->getABPValue());
    }
    else
        ui->labelABP->setText("0/0");

    ui->labelABP->repaint();
}

void MainWindow::updatePLETH()
{
    if(m_isPauseAll==true || m_isStart==false)
        return;

    if(m_cstatus)
    {
      ui->labelSPO2->setText(this->getPLETHValue());
    }
    else
        ui->labelSPO2->setText("0");

    ui->labelABP->repaint();
}

void MainWindow::updateTimeString()
{
    //get current date and time
    QDateTime dateTime = QDateTime::currentDateTime();
    QString dateTimeString = dateTime.toString("hh:mm:ss AP");
    ui->labelTime->setText(dateTimeString);
    ui->labelTime->repaint();
}

int MainWindow::getPulseValue()
{
    static int index=-1;

    if(index==this->m_HB_Simulate_Data.count()-1)
        index=0;
    else
        index++;

    return m_HB_Simulate_Data[index];
}

QString MainWindow::getABPValue()
{
    static int index=-1;

    if(index==this->m_ABP_Higher_Simulate_Data.count()-1)
        index=0;
    else
        index++;

    QString str=QString("%1/%2").arg(m_ABP_Higher_Simulate_Data[index]).arg(m_ABP_Lower_Simulate_Data[index]);
    return str;
}

QString MainWindow::getPLETHValue()
{
    static int index=-1;

    if(index==this->m_PLETH_Simulate_Data.count()-1)
        index=0;
    else
        index++;

    QString str=QString("%1").arg(m_PLETH_Simulate_Data[index]);
    return str;
}

void MainWindow::on_pbtn_Silent_clicked()
{
   m_btnSilentPressed=!m_btnSilentPressed;
    if(m_btnSilentPressed)
    {
        ui->pbtn_ECG_Alarm->setChecked(true);
        ui->pbtn_ABP_Alarm->setChecked(true);
        ui->pbtn_spo2_Alarm->setChecked(true);
        m_isAlarmSilent=true;
       // ui->pbtn_Silent->setStyleSheet("*{border: 0px;background-image: url(:/images/btn_pressed.png);}");
    }
    else
    {
        ui->pbtn_ECG_Alarm->setChecked(false);
        ui->pbtn_ABP_Alarm->setChecked(false);
        ui->pbtn_spo2_Alarm->setChecked(false);
        m_isAlarmSilent=false;
        //ui->pbtn_Silent->setStyleSheet("");
    }
}

void MainWindow::on_pbtn_StartStop_clicked(bool checked)
{

#ifdef PMD_HAMP

    if(checked)
    {
        m_isStart=false;
        m_timerDataValues->stop();
        ui->pbtn_StartStop->setText("Start");
        m_hampdataSupplier->startStopNucleus(m_isStart);
        m_cstatus=false;
    }
    else
    {
        m_isStart=true;
        ui->pbtn_StartStop->setText("Stop");
        m_timerDataValues->start();
        m_hampdataSupplier->startStopNucleus(m_isStart);
        m_cstatus=true;

    }
   fflush(stdout);
#else

    if(checked)
    {
        m_isStart=false;
        this->m_graphWidget1->clearWidget();
#ifndef ONLY_SHOW_ECG_GRAPH
        this->m_graphWidget2->clearWidget();
        this->m_graphWidget3->clearWidget();
#endif
        ui->pbtn_StartStop->setText("Start");
    }
    else
    {
        m_isStart=true;
        ui->pbtn_StartStop->setText("Stop");
    }

#endif

}

void MainWindow::on_pbtn_PauseAll_clicked(bool checked)
{
    if(!checked)
    {
        m_isPauseAll=false;
        ui->pbtn_PauseAll->setText("Pause All");
    }
    else
    {
        m_isPauseAll=true;
        this->m_graphWidget1->clearWidget();
#ifndef ONLY_SHOW_ECG_GRAPH
        this->m_graphWidget2->clearWidget();
        this->m_graphWidget3->clearWidget();
#endif
        ui->pbtn_PauseAll->setText("Start All");
    }
}

void MainWindow::on_pbtn_Scrolling_clicked(bool checked)
{
 (void)checked;
#ifndef PMD_HAMP
    m_graphWidget1->setScrollingMode(checked);
#ifndef ONLY_SHOW_ECG_GRAPH
    m_graphWidget2->setScrollingMode(checked);
    m_graphWidget3->setScrollingMode(checked);
#endif
#endif
}

void MainWindow::updateTimer()
{
#ifdef PMD_MEHV
    pm_data_struct pm={0,0,0,0};
    dataReceived (&pm);
#endif
}

void MainWindow::animateAlarm()
{
    ui->pbtn_ABP_Alarm->toggle();
    ui->pbtn_ECG_Alarm->toggle();
    ui->pbtn_spo2_Alarm->toggle();
}

void MainWindow::on_pbtn_ECG_Alarm_clicked(bool checked)
{
    (void)checked;
}

void MainWindow::on_pbtn_spo2_Alarm_clicked(bool checked)
{
    (void)checked;
}

void MainWindow::on_pbtn_ABP_Alarm_clicked(bool checked)
{
    (void)checked;
}

void MainWindow::dataReceived(pm_data_struct *current)
{
	if (m_isPauseAll==false)
    {
		switch(m_graphWidget1->getGraphType())
        {

        case GraphECG:
            m_graphWidget1->animate(current->ecgValue);
        break;

        case GraphABP:
            m_graphWidget1->animate(current->abpValue);
        break;

        case GraphPLETH:
            m_graphWidget1->animate(current->plethValue);
        break;

        case GraphCO2:
            //TODO
        break;
        }

#ifndef ONLY_SHOW_ECG_GRAPH
        switch(m_graphWidget2->getGraphType())
        {
        case GraphECG:
            m_graphWidget2->animate(current->ecgValue);
        break;

        case GraphABP:
            m_graphWidget2->animate(current->abpValue);
        break;

        case GraphPLETH:
            m_graphWidget2->animate(current->plethValue);
        break;

        case GraphCO2:
            //TODO
        break;
        }

        switch(m_graphWidget3->getGraphType())
        {
        case GraphECG:
            m_graphWidget3->animate(current->ecgValue);
        break;

        case GraphABP:
            m_graphWidget3->animate(current->abpValue);
        break;

        case GraphPLETH:
            m_graphWidget3->animate(current->plethValue);
        break;

        case GraphCO2:
            //TODO
        break;
        }
#endif
    }
}

#ifndef PMD_NUCLEUS
void MainWindow::connectionStatus(bool status)
{
    QDateTime dateTime = QDateTime::currentDateTime();
    QString dateTimeString = dateTime.toString("hh:mmap");
    m_cstatus=status;

    if(status)
    {
        ui->labelBulletText->setText("External system connected at "+dateTimeString);
        ui->labelBulletText->repaint();
        ui->pbtn_ECG_Alarm->setStyleSheet(m_alarmBtnNormalStyleSheet);
        ui->pbtn_ABP_Alarm->setStyleSheet(m_alarmBtnNormalStyleSheet);
        ui->pbtn_spo2_Alarm->setStyleSheet(m_alarmBtnNormalStyleSheet);
        ui->pbtn_ABP_Alarm->setDisabled(false);
        ui->pbtn_ECG_Alarm->setDisabled(false);
        ui->pbtn_spo2_Alarm->setDisabled(false);
        m_timerAlarm->stop();

    }
    else
    {
        ui->labelBulletText->setText("External system disconnected at "+dateTimeString);
        ui->labelBulletText->repaint();
        ui->pbtn_ECG_Alarm->setStyleSheet(m_alarmBtnRedStyleSheet);
        ui->pbtn_ABP_Alarm->setStyleSheet(m_alarmBtnRedStyleSheet);
        ui->pbtn_spo2_Alarm->setStyleSheet(m_alarmBtnRedStyleSheet);
        ui->pbtn_ABP_Alarm->setDisabled(true);
        ui->pbtn_ECG_Alarm->setDisabled(true);
        ui->pbtn_spo2_Alarm->setDisabled(true);

        m_timerAlarm->start();
        updatePLETH();
        updateABP();
        updatePulse();
    }
}
#endif

void MainWindow::launchGraphMenuPopup(Widget *widget)
{
   if(m_graphSettingsPop->m_isVisible==false)
   {
       m_selectedGraphWidget=widget;
       switch(m_selectedGraphWidget->getGraphType())
       {
           case GraphECG:
            m_graphSettingsPop->initialized(m_selectedGraphWidget->getGraphWaveSize(),GraphECG);
           break;

           case GraphABP:
            m_graphSettingsPop->initialized(m_selectedGraphWidget->getGraphWaveSize(),GraphABP);
           break;

           case GraphPLETH:
            m_graphSettingsPop->initialized(m_selectedGraphWidget->getGraphWaveSize(),GraphPLETH);
           break;

           case GraphCO2:
                 //TODO
           break;
       }
       m_graphSettingsPop->show();
   }
}

void MainWindow::onGraphMenuPopupOk()
{
    if(m_selectedGraphWidget->getGraphWaveSize()!=m_graphSettingsPop->m_graphWaveSize)
    {
        switch(m_selectedGraphWidget->getGraphType())
        {
            case GraphECG:
                 m_selectedGraphWidget->initialized(GraphECG,m_graphSettingsPop->m_graphWaveSize);
                 m_selectedGraphWidget->repaint();
            break;

            case GraphABP:
                m_selectedGraphWidget->initialized(GraphABP,m_graphSettingsPop->m_graphWaveSize);
                m_selectedGraphWidget->repaint();
            break;

            case GraphPLETH:
                m_selectedGraphWidget->initialized(GraphPLETH,m_graphSettingsPop->m_graphWaveSize);
                m_selectedGraphWidget->repaint();
            break;

            case GraphCO2:
                  //TODO
            break;
        }
    }

    m_graphSettingsPop->hide();
    m_graphSettingsPop->close();
    m_graphSettingsPop->m_isVisible=false;
    m_selectedGraphWidget=NULL;
}

void MainWindow::onGraphMenuPopupCancel()
{
    m_graphSettingsPop->hide();
    m_graphSettingsPop->close();
    m_graphSettingsPop->m_isVisible=false;
    m_selectedGraphWidget=NULL;
}

#ifdef PMD_HAMP

void  MainWindow::takeScreenSnapshort()
{
    QRect r= this->rect();
    QPixmap pixmap=this->grab(r);
    QString fileName = m_hampdataSupplier->getScreenShortPath();

    if(pixmap.isNull()==false)
        pixmap.save(fileName,"PNG");
    else
        printf("\npixmap is NULL");
}

#endif
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "graphSettingsPopup.h"
#include <QDateTime>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

#ifdef PMD_HAMP
    ui->pbtn_StartStop->setChecked(true);
#endif

    m_alarmBtnNormalStyleSheet=ui->pbtn_ECG_Alarm->styleSheet();
    m_alarmBtnRedStyleSheet= "*{border: 0px;background-image: url(:/images/icnBellRed.png);} *:checked{background-image:url();}";

    m_graphWidget1 = new Widget(ui->graphECGWidget,this);
#ifndef ONLY_SHOW_ECG_GRAPH
    m_graphWidget2 = new Widget(ui->graphABPWidget,this);
    m_graphWidget3 = new Widget(ui->graphPLETHWidget,this);
#endif

    m_graphWidget1->initialized(GraphECG,3);
#ifndef ONLY_SHOW_ECG_GRAPH
    m_graphWidget2->initialized(GraphABP,1);
    m_graphWidget3->initialized(GraphPLETH,2);
#endif

    m_selectedGraphWidget = NULL;

    // Set time
    updateTimeString();

    // Setup timer to update UI
    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(updateTimeString()));
    timer->start(1000);

    m_timerAlarm =new QTimer (this);
    connect(m_timerAlarm, SIGNAL(timeout()), this, SLOT(animateAlarm()));
    m_timerAlarm->setInterval(500);
    m_timerAlarm->stop();

    m_timerDataValues = new QTimer(this);
#ifndef DISABLE_RIGHT_PANEL_NUMERIC_VALUES
    connect(m_timerDataValues, SIGNAL(timeout()), this, SLOT(updatePulse()));
    connect(m_timerDataValues, SIGNAL(timeout()), this, SLOT(updateABP()));
    connect(m_timerDataValues, SIGNAL(timeout()), this, SLOT(updatePLETH()));
    m_timerDataValues->setInterval(3000);
    #ifndef PMD_HAMP
        m_timerDataValues->start();
    #endif
#endif

    m_HB_Simulate_Data << 70 << 68 << 71 << 69<< 67<< 68;
    m_ABP_Higher_Simulate_Data << 100 << 110 << 107 << 124<< 137<< 119;
    m_ABP_Lower_Simulate_Data << 73 << 88 << 77 << 82 << 91 << 79;
    m_PLETH_Simulate_Data << 93 << 96 << 90 << 97 << 95 << 99;

    m_cstatus=true;

#ifdef PMD_MEHV
    m_nserver =new Server(this);
    m_cstatus=false;
#endif

#ifdef PMD_NUCLEUS
    m_dataSupplier=new DataSupplier(this);
#endif

#ifdef PMD_HAMP
	printf("Creating HAMPDataSupplier\n");
    m_hampdataSupplier =new HAMPDataSupplier(this);
    m_cstatus=true;

    // Setup timer to update UI
    QTimer *hamptimer = new QTimer(this);
    connect(hamptimer, SIGNAL(timeout()), this, SLOT(takeScreenSnapshort()));
    hamptimer->start(3000);

#endif

    m_isPauseAll=false;
    m_isStart=true;
    m_isAlarmSilent=false;
    m_btnSilentPressed=false;

    m_graphSettingsPop =new GraphSettingsPopup(this);
    m_graphSettingsPop->hide();

    // Setup graph scrolling mode
#ifdef ENABLE_GRAPH_SCROLLING
    on_pbtn_Scrolling_clicked(true);
    ui->pbtn_Scrolling->setChecked(true);
#else
    on_pbtn_Scrolling_clicked(false);
    ui->pbtn_Scrolling->setChecked(false);
#endif
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::updatePulse()
{
    QString value="0";

    if(m_isPauseAll==true || m_isStart==false)
        return;

    if(m_cstatus)
    {
        value.setNum(this->getPulseValue());
    }

    ui->labelPulse->setText(value);
    ui->labelPulse->repaint();
}

void MainWindow::updateABP()
{

    if(m_isPauseAll==true || m_isStart==false)
        return;

    if(m_cstatus)
    {
      ui->labelABP->setText(this->getABPValue());
    }
    else
        ui->labelABP->setText("0/0");

    ui->labelABP->repaint();
}

void MainWindow::updatePLETH()
{
    if(m_isPauseAll==true || m_isStart==false)
        return;

    if(m_cstatus)
    {
      ui->labelSPO2->setText(this->getPLETHValue());
    }
    else
        ui->labelSPO2->setText("0");

    ui->labelABP->repaint();
}

void MainWindow::updateTimeString()
{
    //get current date and time
    QDateTime dateTime = QDateTime::currentDateTime();
    QString dateTimeString = dateTime.toString("hh:mm:ss AP");
    ui->labelTime->setText(dateTimeString);
    ui->labelTime->repaint();
}

int MainWindow::getPulseValue()
{
    static int index=-1;

    if(index==this->m_HB_Simulate_Data.count()-1)
        index=0;
    else
        index++;

    return m_HB_Simulate_Data[index];
}

QString MainWindow::getABPValue()
{
    static int index=-1;

    if(index==this->m_ABP_Higher_Simulate_Data.count()-1)
        index=0;
    else
        index++;

    QString str=QString("%1/%2").arg(m_ABP_Higher_Simulate_Data[index]).arg(m_ABP_Lower_Simulate_Data[index]);
    return str;
}

QString MainWindow::getPLETHValue()
{
    static int index=-1;

    if(index==this->m_PLETH_Simulate_Data.count()-1)
        index=0;
    else
        index++;

    QString str=QString("%1").arg(m_PLETH_Simulate_Data[index]);
    return str;
}

void MainWindow::on_pbtn_Silent_clicked()
{
   m_btnSilentPressed=!m_btnSilentPressed;
    if(m_btnSilentPressed)
    {
        ui->pbtn_ECG_Alarm->setChecked(true);
        ui->pbtn_ABP_Alarm->setChecked(true);
        ui->pbtn_spo2_Alarm->setChecked(true);
        m_isAlarmSilent=true;
       // ui->pbtn_Silent->setStyleSheet("*{border: 0px;background-image: url(:/images/btn_pressed.png);}");
    }
    else
    {
        ui->pbtn_ECG_Alarm->setChecked(false);
        ui->pbtn_ABP_Alarm->setChecked(false);
        ui->pbtn_spo2_Alarm->setChecked(false);
        m_isAlarmSilent=false;
        //ui->pbtn_Silent->setStyleSheet("");
    }
}

void MainWindow::on_pbtn_StartStop_clicked(bool checked)
{

#ifdef PMD_HAMP

    if(checked)
    {
        m_isStart=false;
        m_timerDataValues->stop();
        ui->pbtn_StartStop->setText("Start");
        m_hampdataSupplier->startStopNucleus(m_isStart);
        m_cstatus=false;
    }
    else
    {
        m_isStart=true;
        ui->pbtn_StartStop->setText("Stop");
        m_timerDataValues->start();
        m_hampdataSupplier->startStopNucleus(m_isStart);
        m_cstatus=true;

    }
   fflush(stdout);
#else

    if(checked)
    {
        m_isStart=false;
        this->m_graphWidget1->clearWidget();
#ifndef ONLY_SHOW_ECG_GRAPH
        this->m_graphWidget2->clearWidget();
        this->m_graphWidget3->clearWidget();
#endif
        ui->pbtn_StartStop->setText("Start");
    }
    else
    {
        m_isStart=true;
        ui->pbtn_StartStop->setText("Stop");
    }

#endif

}

void MainWindow::on_pbtn_PauseAll_clicked(bool checked)
{
    if(!checked)
    {
        m_isPauseAll=false;
        ui->pbtn_PauseAll->setText("Pause All");
    }
    else
    {
        m_isPauseAll=true;
        this->m_graphWidget1->clearWidget();
#ifndef ONLY_SHOW_ECG_GRAPH
        this->m_graphWidget2->clearWidget();
        this->m_graphWidget3->clearWidget();
#endif
        ui->pbtn_PauseAll->setText("Start All");
    }
}

void MainWindow::on_pbtn_Scrolling_clicked(bool checked)
{
 (void)checked;
#ifndef PMD_HAMP
    m_graphWidget1->setScrollingMode(checked);
#ifndef ONLY_SHOW_ECG_GRAPH
    m_graphWidget2->setScrollingMode(checked);
    m_graphWidget3->setScrollingMode(checked);
#endif
#endif
}

void MainWindow::updateTimer()
{
#ifdef PMD_MEHV
    pm_data_struct pm={0,0,0,0};
    dataReceived (&pm);
#endif
}

void MainWindow::animateAlarm()
{
    ui->pbtn_ABP_Alarm->toggle();
    ui->pbtn_ECG_Alarm->toggle();
    ui->pbtn_spo2_Alarm->toggle();
}

void MainWindow::on_pbtn_ECG_Alarm_clicked(bool checked)
{
    (void)checked;
}

void MainWindow::on_pbtn_spo2_Alarm_clicked(bool checked)
{
    (void)checked;
}

void MainWindow::on_pbtn_ABP_Alarm_clicked(bool checked)
{
    (void)checked;
}

void MainWindow::dataReceived(pm_data_struct *current)
{
	if (m_isPauseAll==false)
    {
		switch(m_graphWidget1->getGraphType())
        {

        case GraphECG:
            m_graphWidget1->animate(current->ecgValue);
        break;

        case GraphABP:
            m_graphWidget1->animate(current->abpValue);
        break;

        case GraphPLETH:
            m_graphWidget1->animate(current->plethValue);
        break;

        case GraphCO2:
            //TODO
        break;
        }

#ifndef ONLY_SHOW_ECG_GRAPH
        switch(m_graphWidget2->getGraphType())
        {
        case GraphECG:
            m_graphWidget2->animate(current->ecgValue);
        break;

        case GraphABP:
            m_graphWidget2->animate(current->abpValue);
        break;

        case GraphPLETH:
            m_graphWidget2->animate(current->plethValue);
        break;

        case GraphCO2:
            //TODO
        break;
        }

        switch(m_graphWidget3->getGraphType())
        {
        case GraphECG:
            m_graphWidget3->animate(current->ecgValue);
        break;

        case GraphABP:
            m_graphWidget3->animate(current->abpValue);
        break;

        case GraphPLETH:
            m_graphWidget3->animate(current->plethValue);
        break;

        case GraphCO2:
            //TODO
        break;
        }
#endif
    }
}

#ifndef PMD_NUCLEUS
void MainWindow::connectionStatus(bool status)
{
    QDateTime dateTime = QDateTime::currentDateTime();
    QString dateTimeString = dateTime.toString("hh:mmap");
    m_cstatus=status;

    if(status)
    {
        ui->labelBulletText->setText("External system connected at "+dateTimeString);
        ui->labelBulletText->repaint();
        ui->pbtn_ECG_Alarm->setStyleSheet(m_alarmBtnNormalStyleSheet);
        ui->pbtn_ABP_Alarm->setStyleSheet(m_alarmBtnNormalStyleSheet);
        ui->pbtn_spo2_Alarm->setStyleSheet(m_alarmBtnNormalStyleSheet);
        ui->pbtn_ABP_Alarm->setDisabled(false);
        ui->pbtn_ECG_Alarm->setDisabled(false);
        ui->pbtn_spo2_Alarm->setDisabled(false);
        m_timerAlarm->stop();

    }
    else
    {
        ui->labelBulletText->setText("External system disconnected at "+dateTimeString);
        ui->labelBulletText->repaint();
        ui->pbtn_ECG_Alarm->setStyleSheet(m_alarmBtnRedStyleSheet);
        ui->pbtn_ABP_Alarm->setStyleSheet(m_alarmBtnRedStyleSheet);
        ui->pbtn_spo2_Alarm->setStyleSheet(m_alarmBtnRedStyleSheet);
        ui->pbtn_ABP_Alarm->setDisabled(true);
        ui->pbtn_ECG_Alarm->setDisabled(true);
        ui->pbtn_spo2_Alarm->setDisabled(true);

        m_timerAlarm->start();
        updatePLETH();
        updateABP();
        updatePulse();
    }
}
#endif

void MainWindow::launchGraphMenuPopup(Widget *widget)
{
   if(m_graphSettingsPop->m_isVisible==false)
   {
       m_selectedGraphWidget=widget;
       switch(m_selectedGraphWidget->getGraphType())
       {
           case GraphECG:
            m_graphSettingsPop->initialized(m_selectedGraphWidget->getGraphWaveSize(),GraphECG);
           break;

           case GraphABP:
            m_graphSettingsPop->initialized(m_selectedGraphWidget->getGraphWaveSize(),GraphABP);
           break;

           case GraphPLETH:
            m_graphSettingsPop->initialized(m_selectedGraphWidget->getGraphWaveSize(),GraphPLETH);
           break;

           case GraphCO2:
                 //TODO
           break;
       }
       m_graphSettingsPop->show();
   }
}

void MainWindow::onGraphMenuPopupOk()
{
    if(m_selectedGraphWidget->getGraphWaveSize()!=m_graphSettingsPop->m_graphWaveSize)
    {
        switch(m_selectedGraphWidget->getGraphType())
        {
            case GraphECG:
                 m_selectedGraphWidget->initialized(GraphECG,m_graphSettingsPop->m_graphWaveSize);
                 m_selectedGraphWidget->repaint();
            break;

            case GraphABP:
                m_selectedGraphWidget->initialized(GraphABP,m_graphSettingsPop->m_graphWaveSize);
                m_selectedGraphWidget->repaint();
            break;

            case GraphPLETH:
                m_selectedGraphWidget->initialized(GraphPLETH,m_graphSettingsPop->m_graphWaveSize);
                m_selectedGraphWidget->repaint();
            break;

            case GraphCO2:
                  //TODO
            break;
        }
    }

    m_graphSettingsPop->hide();
    m_graphSettingsPop->close();
    m_graphSettingsPop->m_isVisible=false;
    m_selectedGraphWidget=NULL;
}

void MainWindow::onGraphMenuPopupCancel()
{
    m_graphSettingsPop->hide();
    m_graphSettingsPop->close();
    m_graphSettingsPop->m_isVisible=false;
    m_selectedGraphWidget=NULL;
}

#ifdef PMD_HAMP

void  MainWindow::takeScreenSnapshort()
{
    QRect r= this->rect();
    QPixmap pixmap=this->grab(r);
    QString fileName = m_hampdataSupplier->getScreenShortPath();

    if(pixmap.isNull()==false)
        pixmap.save(fileName,"PNG");
    else
        printf("\npixmap is NULL");
}

#endif
<commit_msg>test2<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "graphSettingsPopup.h"
#include <QDateTime>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

#ifdef PMD_HAMP
    ui->pbtn_StartStop->setChecked(true);
#endif
	printf("This is MainWindow\n");

    m_alarmBtnNormalStyleSheet=ui->pbtn_ECG_Alarm->styleSheet();
    m_alarmBtnRedStyleSheet= "*{border: 0px;background-image: url(:/images/icnBellRed.png);} *:checked{background-image:url();}";

    m_graphWidget1 = new Widget(ui->graphECGWidget,this);
#ifndef ONLY_SHOW_ECG_GRAPH
    m_graphWidget2 = new Widget(ui->graphABPWidget,this);
    m_graphWidget3 = new Widget(ui->graphPLETHWidget,this);
#endif

    m_graphWidget1->initialized(GraphECG,3);
#ifndef ONLY_SHOW_ECG_GRAPH
    m_graphWidget2->initialized(GraphABP,1);
    m_graphWidget3->initialized(GraphPLETH,2);
#endif

    m_selectedGraphWidget = NULL;

    // Set time
    updateTimeString();

    // Setup timer to update UI
    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(updateTimeString()));
    timer->start(1000);

    m_timerAlarm =new QTimer (this);
    connect(m_timerAlarm, SIGNAL(timeout()), this, SLOT(animateAlarm()));
    m_timerAlarm->setInterval(500);
    m_timerAlarm->stop();

    m_timerDataValues = new QTimer(this);
#ifndef DISABLE_RIGHT_PANEL_NUMERIC_VALUES
    connect(m_timerDataValues, SIGNAL(timeout()), this, SLOT(updatePulse()));
    connect(m_timerDataValues, SIGNAL(timeout()), this, SLOT(updateABP()));
    connect(m_timerDataValues, SIGNAL(timeout()), this, SLOT(updatePLETH()));
    m_timerDataValues->setInterval(3000);
    #ifndef PMD_HAMP
        m_timerDataValues->start();
    #endif
#endif

    m_HB_Simulate_Data << 70 << 68 << 71 << 69<< 67<< 68;
    m_ABP_Higher_Simulate_Data << 100 << 110 << 107 << 124<< 137<< 119;
    m_ABP_Lower_Simulate_Data << 73 << 88 << 77 << 82 << 91 << 79;
    m_PLETH_Simulate_Data << 93 << 96 << 90 << 97 << 95 << 99;

    m_cstatus=true;

#ifdef PMD_MEHV
    m_nserver =new Server(this);
    m_cstatus=false;
#endif

#ifdef PMD_NUCLEUS
    m_dataSupplier=new DataSupplier(this);
#endif

#ifdef PMD_HAMP
	printf("Creating HAMPDataSupplier\n");
    m_hampdataSupplier =new HAMPDataSupplier(this);
    m_cstatus=true;

    // Setup timer to update UI
    QTimer *hamptimer = new QTimer(this);
    connect(hamptimer, SIGNAL(timeout()), this, SLOT(takeScreenSnapshort()));
    hamptimer->start(3000);

#endif

    m_isPauseAll=false;
    m_isStart=true;
    m_isAlarmSilent=false;
    m_btnSilentPressed=false;

    m_graphSettingsPop =new GraphSettingsPopup(this);
    m_graphSettingsPop->hide();

    // Setup graph scrolling mode
#ifdef ENABLE_GRAPH_SCROLLING
    on_pbtn_Scrolling_clicked(true);
    ui->pbtn_Scrolling->setChecked(true);
#else
    on_pbtn_Scrolling_clicked(false);
    ui->pbtn_Scrolling->setChecked(false);
#endif
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::updatePulse()
{
    QString value="0";

    if(m_isPauseAll==true || m_isStart==false)
        return;

    if(m_cstatus)
    {
        value.setNum(this->getPulseValue());
    }

    ui->labelPulse->setText(value);
    ui->labelPulse->repaint();
}

void MainWindow::updateABP()
{

    if(m_isPauseAll==true || m_isStart==false)
        return;

    if(m_cstatus)
    {
      ui->labelABP->setText(this->getABPValue());
    }
    else
        ui->labelABP->setText("0/0");

    ui->labelABP->repaint();
}

void MainWindow::updatePLETH()
{
    if(m_isPauseAll==true || m_isStart==false)
        return;

    if(m_cstatus)
    {
      ui->labelSPO2->setText(this->getPLETHValue());
    }
    else
        ui->labelSPO2->setText("0");

    ui->labelABP->repaint();
}

void MainWindow::updateTimeString()
{
    //get current date and time
    QDateTime dateTime = QDateTime::currentDateTime();
    QString dateTimeString = dateTime.toString("hh:mm:ss AP");
    ui->labelTime->setText(dateTimeString);
    ui->labelTime->repaint();
}

int MainWindow::getPulseValue()
{
    static int index=-1;

    if(index==this->m_HB_Simulate_Data.count()-1)
        index=0;
    else
        index++;

    return m_HB_Simulate_Data[index];
}

QString MainWindow::getABPValue()
{
    static int index=-1;

    if(index==this->m_ABP_Higher_Simulate_Data.count()-1)
        index=0;
    else
        index++;

    QString str=QString("%1/%2").arg(m_ABP_Higher_Simulate_Data[index]).arg(m_ABP_Lower_Simulate_Data[index]);
    return str;
}

QString MainWindow::getPLETHValue()
{
    static int index=-1;

    if(index==this->m_PLETH_Simulate_Data.count()-1)
        index=0;
    else
        index++;

    QString str=QString("%1").arg(m_PLETH_Simulate_Data[index]);
    return str;
}

void MainWindow::on_pbtn_Silent_clicked()
{
   m_btnSilentPressed=!m_btnSilentPressed;
    if(m_btnSilentPressed)
    {
        ui->pbtn_ECG_Alarm->setChecked(true);
        ui->pbtn_ABP_Alarm->setChecked(true);
        ui->pbtn_spo2_Alarm->setChecked(true);
        m_isAlarmSilent=true;
       // ui->pbtn_Silent->setStyleSheet("*{border: 0px;background-image: url(:/images/btn_pressed.png);}");
    }
    else
    {
        ui->pbtn_ECG_Alarm->setChecked(false);
        ui->pbtn_ABP_Alarm->setChecked(false);
        ui->pbtn_spo2_Alarm->setChecked(false);
        m_isAlarmSilent=false;
        //ui->pbtn_Silent->setStyleSheet("");
    }
}

void MainWindow::on_pbtn_StartStop_clicked(bool checked)
{

#ifdef PMD_HAMP

    if(checked)
    {
        m_isStart=false;
        m_timerDataValues->stop();
        ui->pbtn_StartStop->setText("Start");
        m_hampdataSupplier->startStopNucleus(m_isStart);
        m_cstatus=false;
    }
    else
    {
        m_isStart=true;
        ui->pbtn_StartStop->setText("Stop");
        m_timerDataValues->start();
        m_hampdataSupplier->startStopNucleus(m_isStart);
        m_cstatus=true;

    }
   fflush(stdout);
#else

    if(checked)
    {
        m_isStart=false;
        this->m_graphWidget1->clearWidget();
#ifndef ONLY_SHOW_ECG_GRAPH
        this->m_graphWidget2->clearWidget();
        this->m_graphWidget3->clearWidget();
#endif
        ui->pbtn_StartStop->setText("Start");
    }
    else
    {
        m_isStart=true;
        ui->pbtn_StartStop->setText("Stop");
    }

#endif

}

void MainWindow::on_pbtn_PauseAll_clicked(bool checked)
{
    if(!checked)
    {
        m_isPauseAll=false;
        ui->pbtn_PauseAll->setText("Pause All");
    }
    else
    {
        m_isPauseAll=true;
        this->m_graphWidget1->clearWidget();
#ifndef ONLY_SHOW_ECG_GRAPH
        this->m_graphWidget2->clearWidget();
        this->m_graphWidget3->clearWidget();
#endif
        ui->pbtn_PauseAll->setText("Start All");
    }
}

void MainWindow::on_pbtn_Scrolling_clicked(bool checked)
{
 (void)checked;
#ifndef PMD_HAMP
    m_graphWidget1->setScrollingMode(checked);
#ifndef ONLY_SHOW_ECG_GRAPH
    m_graphWidget2->setScrollingMode(checked);
    m_graphWidget3->setScrollingMode(checked);
#endif
#endif
}

void MainWindow::updateTimer()
{
#ifdef PMD_MEHV
    pm_data_struct pm={0,0,0,0};
    dataReceived (&pm);
#endif
}

void MainWindow::animateAlarm()
{
    ui->pbtn_ABP_Alarm->toggle();
    ui->pbtn_ECG_Alarm->toggle();
    ui->pbtn_spo2_Alarm->toggle();
}

void MainWindow::on_pbtn_ECG_Alarm_clicked(bool checked)
{
    (void)checked;
}

void MainWindow::on_pbtn_spo2_Alarm_clicked(bool checked)
{
    (void)checked;
}

void MainWindow::on_pbtn_ABP_Alarm_clicked(bool checked)
{
    (void)checked;
}

void MainWindow::dataReceived(pm_data_struct *current)
{
	if (m_isPauseAll==false)
    {
		switch(m_graphWidget1->getGraphType())
        {

        case GraphECG:
            m_graphWidget1->animate(current->ecgValue);
        break;

        case GraphABP:
            m_graphWidget1->animate(current->abpValue);
        break;

        case GraphPLETH:
            m_graphWidget1->animate(current->plethValue);
        break;

        case GraphCO2:
            //TODO
        break;
        }

#ifndef ONLY_SHOW_ECG_GRAPH
        switch(m_graphWidget2->getGraphType())
        {
        case GraphECG:
            m_graphWidget2->animate(current->ecgValue);
        break;

        case GraphABP:
            m_graphWidget2->animate(current->abpValue);
        break;

        case GraphPLETH:
            m_graphWidget2->animate(current->plethValue);
        break;

        case GraphCO2:
            //TODO
        break;
        }

        switch(m_graphWidget3->getGraphType())
        {
        case GraphECG:
            m_graphWidget3->animate(current->ecgValue);
        break;

        case GraphABP:
            m_graphWidget3->animate(current->abpValue);
        break;

        case GraphPLETH:
            m_graphWidget3->animate(current->plethValue);
        break;

        case GraphCO2:
            //TODO
        break;
        }
#endif
    }
}

#ifndef PMD_NUCLEUS
void MainWindow::connectionStatus(bool status)
{
    QDateTime dateTime = QDateTime::currentDateTime();
    QString dateTimeString = dateTime.toString("hh:mmap");
    m_cstatus=status;

    if(status)
    {
        ui->labelBulletText->setText("External system connected at "+dateTimeString);
        ui->labelBulletText->repaint();
        ui->pbtn_ECG_Alarm->setStyleSheet(m_alarmBtnNormalStyleSheet);
        ui->pbtn_ABP_Alarm->setStyleSheet(m_alarmBtnNormalStyleSheet);
        ui->pbtn_spo2_Alarm->setStyleSheet(m_alarmBtnNormalStyleSheet);
        ui->pbtn_ABP_Alarm->setDisabled(false);
        ui->pbtn_ECG_Alarm->setDisabled(false);
        ui->pbtn_spo2_Alarm->setDisabled(false);
        m_timerAlarm->stop();

    }
    else
    {
        ui->labelBulletText->setText("External system disconnected at "+dateTimeString);
        ui->labelBulletText->repaint();
        ui->pbtn_ECG_Alarm->setStyleSheet(m_alarmBtnRedStyleSheet);
        ui->pbtn_ABP_Alarm->setStyleSheet(m_alarmBtnRedStyleSheet);
        ui->pbtn_spo2_Alarm->setStyleSheet(m_alarmBtnRedStyleSheet);
        ui->pbtn_ABP_Alarm->setDisabled(true);
        ui->pbtn_ECG_Alarm->setDisabled(true);
        ui->pbtn_spo2_Alarm->setDisabled(true);

        m_timerAlarm->start();
        updatePLETH();
        updateABP();
        updatePulse();
    }
}
#endif

void MainWindow::launchGraphMenuPopup(Widget *widget)
{
   if(m_graphSettingsPop->m_isVisible==false)
   {
       m_selectedGraphWidget=widget;
       switch(m_selectedGraphWidget->getGraphType())
       {
           case GraphECG:
            m_graphSettingsPop->initialized(m_selectedGraphWidget->getGraphWaveSize(),GraphECG);
           break;

           case GraphABP:
            m_graphSettingsPop->initialized(m_selectedGraphWidget->getGraphWaveSize(),GraphABP);
           break;

           case GraphPLETH:
            m_graphSettingsPop->initialized(m_selectedGraphWidget->getGraphWaveSize(),GraphPLETH);
           break;

           case GraphCO2:
                 //TODO
           break;
       }
       m_graphSettingsPop->show();
   }
}

void MainWindow::onGraphMenuPopupOk()
{
    if(m_selectedGraphWidget->getGraphWaveSize()!=m_graphSettingsPop->m_graphWaveSize)
    {
        switch(m_selectedGraphWidget->getGraphType())
        {
            case GraphECG:
                 m_selectedGraphWidget->initialized(GraphECG,m_graphSettingsPop->m_graphWaveSize);
                 m_selectedGraphWidget->repaint();
            break;

            case GraphABP:
                m_selectedGraphWidget->initialized(GraphABP,m_graphSettingsPop->m_graphWaveSize);
                m_selectedGraphWidget->repaint();
            break;

            case GraphPLETH:
                m_selectedGraphWidget->initialized(GraphPLETH,m_graphSettingsPop->m_graphWaveSize);
                m_selectedGraphWidget->repaint();
            break;

            case GraphCO2:
                  //TODO
            break;
        }
    }

    m_graphSettingsPop->hide();
    m_graphSettingsPop->close();
    m_graphSettingsPop->m_isVisible=false;
    m_selectedGraphWidget=NULL;
}

void MainWindow::onGraphMenuPopupCancel()
{
    m_graphSettingsPop->hide();
    m_graphSettingsPop->close();
    m_graphSettingsPop->m_isVisible=false;
    m_selectedGraphWidget=NULL;
}

#ifdef PMD_HAMP

void  MainWindow::takeScreenSnapshort()
{
    QRect r= this->rect();
    QPixmap pixmap=this->grab(r);
    QString fileName = m_hampdataSupplier->getScreenShortPath();

    if(pixmap.isNull()==false)
        pixmap.save(fileName,"PNG");
    else
        printf("\npixmap is NULL");
}

#endif
<|endoftext|>


<commit_before>// ========================================================================== //
// This file is part of Sara, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2019 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

//! @example

#include <algorithm>
#include <cmath>

#include <Eigen/Sparse>

#include <DO/Sara/Core.hpp>
#include <DO/Sara/Graphics.hpp>
#include <DO/Sara/VideoIO.hpp>
#include <DO/Sara/FeatureDetectors/DoG.hpp>
#include <DO/Sara/SfM/Detectors/SIFT.hpp>

#include <drafts/Halide/Differential.hpp>
#include <drafts/Halide/LocalExtrema.hpp>
#include <drafts/Halide/Pyramids.hpp>
#include <drafts/Halide/RefineExtrema.hpp>
#include <drafts/Halide/Utilities.hpp>

#include <drafts/Halide/Draw.hpp>
#include <drafts/Halide/DominantGradientOrientations.hpp>
#include <drafts/Halide/Resize.hpp>
#include <drafts/Halide/SIFT.hpp>

namespace shakti = DO::Shakti;

namespace DO::Shakti::HalideBackend {

  struct SIFTExtractor {
    struct Parameters {
      //! @brief Pyramid construction.
      int initial_pyramid_octave = 0;

      //! @brief Extrema detection thresholds.
      //! @{
      float edge_ratio_thres = 10.f;
      float extremum_thres = 0.01f;  // 0.03f;
      //! @}

      //! @brief Dominant gradient orientations.
      //! @{
      int num_orientation_bins = 36;
      float gaussian_truncation_factor = 3.f;
      float scale_multiplying_factor = 1.5f;
      float peak_ratio_thres = 0.0f;
      //! @}

      //! @brief SIFT descriptor parameters.
      //! @{
      float bin_length_in_scale_unit = 3.f;
      int N = 4;
      int O = 8;
      //! @}
    };

    struct Pipeline {
      Sara::ImagePyramid<float> gaussian_pyramid;
      Sara::ImagePyramid<float> dog_pyramid;
      Sara::ImagePyramid<std::int8_t> dog_extrema_pyramid;
      std::array<Sara::ImagePyramid<float>, 2> gradient_pyramid;

      Pyramid<QuantizedExtremumArray> extrema_quantized;
      Pyramid<ExtremumArray> extrema;

      Pyramid<DominantOrientationDenseMap> dominant_orientations_dense;
      Pyramid<DominantOrientationMap> dominant_orientations;

      // The DoG extremum keypoints.
      Pyramid<OrientedExtremumArray> oriented_extrema;
      // The SIFT descriptors.
      Pyramid<Sara::Tensor_<float, 4>> descriptors;
    };

    Sara::Timer timer;
    Parameters params;
    Pipeline pipeline;

    auto operator()(Sara::ImageView<float>& image)
    {
      timer.restart();
      const auto pyr_params =
          Sara::ImagePyramidParams{params.initial_pyramid_octave};
      pipeline.gaussian_pyramid = gaussian_pyramid(image, pyr_params);
      SARA_DEBUG << "Gaussian pyramid = " << timer.elapsed_ms() << " ms"
                 << std::endl;

      timer.restart();
      pipeline.dog_pyramid = subtract_pyramid(pipeline.gaussian_pyramid);
      SARA_DEBUG << "DoG pyramid = " << timer.elapsed_ms() << " ms"
                 << std::endl;

      timer.restart();
      pipeline.dog_extrema_pyramid = local_scale_space_extrema(  //
          pipeline.dog_pyramid,                                  //
          params.edge_ratio_thres,                               //
          params.extremum_thres);
      SARA_DEBUG << "DoG extrema = " << timer.elapsed_ms() << " ms"
                 << std::endl;

      timer.restart();
      std::tie(pipeline.gradient_pyramid[0],                     //
               pipeline.gradient_pyramid[1]) =                   //
          halide::polar_gradient_2d(pipeline.gaussian_pyramid);  //
      SARA_DEBUG << "Gradient pyramid = " << timer.elapsed_ms() << " ms"
                 << std::endl;

      // Populate the DoG extrema.
      pipeline.extrema_quantized = populate_local_scale_space_extrema(  //
          pipeline.dog_extrema_pyramid);

      // Refine the scale-space localization of each extremum.
      pipeline.extrema = refine_scale_space_extrema(  //
          pipeline.dog_pyramid,                       //
          pipeline.extrema_quantized);                //

      // Estimate the dominant gradient orientations.
      timer.restart();
      dominant_gradient_orientations(pipeline.gradient_pyramid[0],          //
                                     pipeline.gradient_pyramid[1],          //
                                     pipeline.extrema,                      //
                                     pipeline.dominant_orientations_dense,  //
                                     params.num_orientation_bins,           //
                                     params.gaussian_truncation_factor,     //
                                     params.scale_multiplying_factor,       //
                                     params.peak_ratio_thres);
      SARA_DEBUG << "Dominant gradient orientations = " << timer.elapsed_ms()
                 << " ms" << std::endl;

      timer.restart();
      pipeline.dominant_orientations =
          compress(pipeline.dominant_orientations_dense);

      pipeline.oriented_extrema = to_oriented_extremum_array(
          pipeline.extrema, pipeline.dominant_orientations);
      SARA_DEBUG << "Populating oriented extrema = " << timer.elapsed_ms()
                 << " ms" << std::endl;

      timer.restart();
      pipeline.descriptors = compute_sift_descriptors(
          pipeline.gradient_pyramid[0],
          pipeline.gradient_pyramid[1],
          pipeline.oriented_extrema,
          params.bin_length_in_scale_unit,
          params.N,
          params.O);
      SARA_DEBUG << "SIFT descriptors = " << timer.elapsed_ms()
                 << " ms" << std::endl;
    }
  };

}

auto test_on_image()
{
  const auto image_filepath =
      "/Users/david/GitLab/DO-CV/sara/data/sunflowerField.jpg";
  // const auto image_filepath =
  // "/Users/david/GitLab/DO-CV/sara/cpp/drafts/MatchPropagation/cpp/examples/shelves/shelf-1.jpg";
  auto image = sara::imread<float>(image_filepath);

  auto sift_extractor = halide::SIFTExtractor{};
  sift_extractor(image);

  const auto& extrema = sift_extractor.pipeline.extrema;
  const auto num_keypoints = std::accumulate(
      extrema.dict.begin(), extrema.dict.end(), 0,
      [](auto val, const auto& kv) { return val + kv.second.size(); });
  SARA_CHECK(num_keypoints);

  // Show the local extrema.
  sara::create_window(image.sizes());
  sara::set_antialiasing();
  sara::display(image);
  draw_extrema(sift_extractor.pipeline.oriented_extrema);
  sara::get_key();
}

auto test_on_video()
{
  using namespace std::string_literals;

#ifdef _WIN32
  const auto video_filepath =
      "C:/Users/David/Desktop/david-archives/gopro-backup-2/GOPR0542.MP4"s;
#elif __APPLE__
  // const auto video_filepath = "/Users/david/Desktop/Datasets/sfm/Family.mp4"s;
  const auto video_filepath = "/Users/david/Desktop/Datasets/humanising-autonomy/field.mp4"s;
#else
  const auto video_filepath = "/home/david/Desktop/Datasets/sfm/Family.mp4"s;
  // const auto video_filepath = "/home/david/Desktop/Datasets/ha/barberX.mp4"s;
#endif

  // Input and output from Sara.
  sara::VideoStream video_stream(video_filepath);
  auto frame = video_stream.frame();
  auto frame_gray32f = sara::Image<float>{frame.sizes()};

  const auto scale_factor = 1;
  auto frame_downsampled = sara::Image<float>{frame.sizes() / scale_factor};

  // Halide buffers.
  auto buffer_rgb = halide::as_interleaved_runtime_buffer(frame);
  auto buffer_gray32f = halide::as_runtime_buffer<float>(frame_gray32f);

  auto sift_extractor = halide::SIFTExtractor{};
  auto compute_dog_extrema = sara::ComputeDoGExtrema{0};

  // Show the local extrema.
  sara::create_window(frame_downsampled.sizes());
  sara::set_antialiasing();

  auto frames_read = 0;
  auto skip = 1;

  while (true)
  {
    sara::tic();
    if (!video_stream.read())
    {
      std::cout << "Reached the end of the video!" << std::endl;
      break;
    }
    sara::toc("Video Decoding");

    ++frames_read;
    if (frames_read % skip != 0)
      continue;

    // Use parallelization and vectorization.
    sara::tic();
    shakti_halide_rgb_to_gray(buffer_rgb, buffer_gray32f);
    sara::toc("Grayscale");

    // Use parallelization and vectorization.
    sara::tic();
    halide::scale(frame_gray32f, frame_downsampled);
    sara::toc("Downsample");

    sara::tic();
// #define ORIGINAL
#ifdef ORIGINAL
    const auto [features, descriptors] = sara::compute_sift_keypoints(frame_downsampled);
#else
    sift_extractor(frame_downsampled);
#endif
    sara::toc("Oriented DoG");

    sara::tic();
    sara::display(frame_downsampled);
#ifdef ORIGINAL
    for (size_t i = 0; i != features.size(); ++i)
    {
      const auto color =
          features[i].extremum_type == sara::OERegion::ExtremumType::Max
              ? sara::Red8
              : sara::Blue8;
      features[i].draw(color);
    }
#else
    draw_extrema(sift_extractor.pipeline.oriented_extrema);
#endif
    sara::toc("Display");
  }
}

GRAPHICS_MAIN()
{
  test_on_video();
  return 0;
}
<commit_msg>MAINT: speed up the SIFT computation on videos.<commit_after>// ========================================================================== //
// This file is part of Sara, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2019 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

//! @example

#include <algorithm>
#include <cmath>

#include <Eigen/Sparse>

#include <DO/Sara/Core.hpp>
#include <DO/Sara/Graphics.hpp>
#include <DO/Sara/VideoIO.hpp>
#include <DO/Sara/FeatureDetectors/DoG.hpp>
#include <DO/Sara/SfM/Detectors/SIFT.hpp>

#include <drafts/Halide/Differential.hpp>
#include <drafts/Halide/LocalExtrema.hpp>
#include <drafts/Halide/Pyramids.hpp>
#include <drafts/Halide/RefineExtrema.hpp>
#include <drafts/Halide/Utilities.hpp>

#include <drafts/Halide/Draw.hpp>
#include <drafts/Halide/DominantGradientOrientations.hpp>
#include <drafts/Halide/Resize.hpp>
#include <drafts/Halide/SIFT.hpp>

namespace shakti = DO::Shakti;

namespace DO::Shakti::HalideBackend {

  struct SIFTExtractor {
    struct Parameters {
      //! @brief Pyramid construction.
      int initial_pyramid_octave = 0;

      //! @brief Extrema detection thresholds.
      //! @{
      float edge_ratio_thres = 10.f;
      float extremum_thres = 0.01f;  // 0.03f;
      //! @}

      //! @brief Dominant gradient orientations.
      //! @{
      int num_orientation_bins = 36;
      float gaussian_truncation_factor = 3.f;
      float scale_multiplying_factor = 1.5f;
      float peak_ratio_thres = 0.0f;
      //! @}

      //! @brief SIFT descriptor parameters.
      //! @{
      float bin_length_in_scale_unit = 3.f;
      int N = 4;
      int O = 8;
      //! @}
    };

    struct Pipeline {
      Sara::ImagePyramid<float> gaussian_pyramid;
      Sara::ImagePyramid<float> dog_pyramid;
      Sara::ImagePyramid<std::int8_t> dog_extrema_pyramid;
      std::array<Sara::ImagePyramid<float>, 2> gradient_pyramid;

      Pyramid<QuantizedExtremumArray> extrema_quantized;
      Pyramid<ExtremumArray> extrema;

      Pyramid<DominantOrientationDenseMap> dominant_orientations_dense;
      Pyramid<DominantOrientationMap> dominant_orientations;

      // The DoG extremum keypoints.
      Pyramid<OrientedExtremumArray> oriented_extrema;
      // The SIFT descriptors.
      Pyramid<Sara::Tensor_<float, 4>> descriptors;
    };

    Sara::Timer timer;
    Parameters params;
    Pipeline pipeline;

    auto operator()(Sara::ImageView<float>& image)
    {
      timer.restart();
      const auto pyr_params =
          Sara::ImagePyramidParams{params.initial_pyramid_octave};
      pipeline.gaussian_pyramid = gaussian_pyramid(image, pyr_params);
      SARA_DEBUG << "Gaussian pyramid = " << timer.elapsed_ms() << " ms"
                 << std::endl;

      timer.restart();
      pipeline.dog_pyramid = subtract_pyramid(pipeline.gaussian_pyramid);
      SARA_DEBUG << "DoG pyramid = " << timer.elapsed_ms() << " ms"
                 << std::endl;

      timer.restart();
      pipeline.dog_extrema_pyramid = local_scale_space_extrema(  //
          pipeline.dog_pyramid,                                  //
          params.edge_ratio_thres,                               //
          params.extremum_thres);
      SARA_DEBUG << "DoG extrema = " << timer.elapsed_ms() << " ms"
                 << std::endl;

      timer.restart();
      std::tie(pipeline.gradient_pyramid[0],                     //
               pipeline.gradient_pyramid[1]) =                   //
          halide::polar_gradient_2d(pipeline.gaussian_pyramid);  //
      SARA_DEBUG << "Gradient pyramid = " << timer.elapsed_ms() << " ms"
                 << std::endl;

      // Populate the DoG extrema.
      pipeline.extrema_quantized = populate_local_scale_space_extrema(  //
          pipeline.dog_extrema_pyramid);

      // Refine the scale-space localization of each extremum.
      pipeline.extrema = refine_scale_space_extrema(  //
          pipeline.dog_pyramid,                       //
          pipeline.extrema_quantized);                //

      // Estimate the dominant gradient orientations.
      timer.restart();
      dominant_gradient_orientations(pipeline.gradient_pyramid[0],          //
                                     pipeline.gradient_pyramid[1],          //
                                     pipeline.extrema,                      //
                                     pipeline.dominant_orientations_dense,  //
                                     params.num_orientation_bins,           //
                                     params.gaussian_truncation_factor,     //
                                     params.scale_multiplying_factor,       //
                                     params.peak_ratio_thres);
      SARA_DEBUG << "Dominant gradient orientations = " << timer.elapsed_ms()
                 << " ms" << std::endl;

      timer.restart();
      pipeline.dominant_orientations =
          compress(pipeline.dominant_orientations_dense);

      pipeline.oriented_extrema = to_oriented_extremum_array(
          pipeline.extrema, pipeline.dominant_orientations);
      SARA_DEBUG << "Populating oriented extrema = " << timer.elapsed_ms()
                 << " ms" << std::endl;

      timer.restart();
      pipeline.descriptors = compute_sift_descriptors(
          pipeline.gradient_pyramid[0],
          pipeline.gradient_pyramid[1],
          pipeline.oriented_extrema,
          params.bin_length_in_scale_unit,
          params.N,
          params.O);
      SARA_DEBUG << "SIFT descriptors = " << timer.elapsed_ms()
                 << " ms" << std::endl;
    }
  };

}

auto test_on_image()
{
  const auto image_filepath =
      "/Users/david/GitLab/DO-CV/sara/data/sunflowerField.jpg";
  // const auto image_filepath =
  // "/Users/david/GitLab/DO-CV/sara/cpp/drafts/MatchPropagation/cpp/examples/shelves/shelf-1.jpg";
  auto image = sara::imread<float>(image_filepath);

  auto sift_extractor = halide::SIFTExtractor{};
  sift_extractor(image);

  const auto& extrema = sift_extractor.pipeline.extrema;
  const auto num_keypoints = std::accumulate(
      extrema.dict.begin(), extrema.dict.end(), 0,
      [](auto val, const auto& kv) { return val + kv.second.size(); });
  SARA_CHECK(num_keypoints);

  // Show the local extrema.
  sara::create_window(image.sizes());
  sara::set_antialiasing();
  sara::display(image);
  draw_extrema(sift_extractor.pipeline.oriented_extrema);
  sara::get_key();
}

auto test_on_video()
{
  using namespace std::string_literals;

#ifdef _WIN32
  const auto video_filepath =
      "C:/Users/David/Desktop/david-archives/gopro-backup-2/GOPR0542.MP4"s;
#elif __APPLE__
  const auto video_filepath = "/Users/david/Desktop/Datasets/sfm/Family.mp4"s;
#else
  const auto video_filepath = "/home/david/Desktop/Datasets/sfm/Family.mp4"s;
#endif

  // Input and output from Sara.
  sara::VideoStream video_stream(video_filepath);
  auto frame = video_stream.frame();
  auto frame_gray32f = sara::Image<float>{frame.sizes()};

  const auto scale_factor = 2;
  auto frame_downsampled = sara::Image<float>{frame.sizes() / scale_factor};

  // Halide buffers.
  auto buffer_rgb = halide::as_interleaved_runtime_buffer(frame);
  auto buffer_gray32f = halide::as_runtime_buffer<float>(frame_gray32f);

  auto sift_extractor = halide::SIFTExtractor{};
  auto compute_dog_extrema = sara::ComputeDoGExtrema{0};

  // Show the local extrema.
  sara::create_window(frame_downsampled.sizes());
  sara::set_antialiasing();

  auto frames_read = 0;
  auto skip = 3;

  while (true)
  {
    sara::tic();
    if (!video_stream.read())
    {
      std::cout << "Reached the end of the video!" << std::endl;
      break;
    }
    sara::toc("Video Decoding");

    ++frames_read;
    if (frames_read % skip != 0)
      continue;

    // Use parallelization and vectorization.
    sara::tic();
    shakti_halide_rgb_to_gray(buffer_rgb, buffer_gray32f);
    sara::toc("Grayscale");

    // Use parallelization and vectorization.
    sara::tic();
    halide::scale(frame_gray32f, frame_downsampled);
    sara::toc("Downsample");

    sara::tic();
// #define ORIGINAL
#ifdef ORIGINAL
    const auto [features, descriptors] = sara::compute_sift_keypoints(frame_downsampled);
#else
    sift_extractor(frame_downsampled);
#endif
    sara::toc("Oriented DoG");

    sara::tic();
    sara::display(frame_downsampled);
#ifdef ORIGINAL
    for (size_t i = 0; i != features.size(); ++i)
    {
      const auto color =
          features[i].extremum_type == sara::OERegion::ExtremumType::Max
              ? sara::Red8
              : sara::Blue8;
      features[i].draw(color);
    }
#else
    draw_extrema(sift_extractor.pipeline.oriented_extrema);
#endif
    sara::toc("Display");
  }
}

GRAPHICS_MAIN()
{
  test_on_video();
  return 0;
}
<|endoftext|>