<commit_before>#include "Settings.h"

#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
#include <algorithm>

#include "Error.h"
#include "HotkeyInfo.h"
#include "LanguageTranslator.h"
#include "Logger.h"
#include "Monitor.h"
#include "Skin.h"
#include "StringUtils.h"

#define XML_AUDIODEV "audioDeviceID"
#define XML_HIDE_WHENFULL "hideFullscreen"
#define XML_HIDEANIM "hideAnimation"
#define XML_HIDETIME "hideDelay"
#define XML_HIDESPEED "hideSpeed"
#define XML_LANGUAGE "language"
#define XML_MONITOR "monitor"
#define XML_NOTIFYICON "notifyIcon"
#define XML_ONTOP "onTop"
#define XML_OSD_OFFSET "osdEdgeOffset"
#define XML_OSD_POS "osdPosition"
#define XML_OSD_X "osdX"
#define XML_OSD_Y "osdY"
#define XML_SKIN "skin"
#define XML_SOUNDS "soundEffects"

std::wstring Settings::_appDir(L"");
Settings *Settings::instance;

std::vector<std::wstring> Settings::OSDPosNames = {
    L"Top",
    L"Left",
    L"Right",
    L"Bottom",
    L"Center",
    L"Top-left",
    L"Top-right",
    L"Bottom-left",
    L"Bottom-right",
    L"Custom"
};

Settings *Settings::Instance() {
    if (instance == NULL) {
        instance = new Settings();
    }
    return instance;
}

void Settings::Load() {
    _file = AppDir() + L"\\Settings.xml";
    CLOG(L"Loading settings: %s", _file.c_str());

    std::string u8FileName = StringUtils::Narrow(_file);
    tinyxml2::XMLError result = _xml.LoadFile(u8FileName.c_str());
    if (result != tinyxml2::XMLError::XML_SUCCESS) {
        Error::ErrorMessageDie(GENERR_SETTINGSFILE, _file);
    }

    _root = _xml.GetDocument()->FirstChildElement("settings");
    if (_root == NULL) {
        Error::ErrorMessageDie(GENERR_MISSING_XML, L"<settings>");
    }
}

int Settings::Save() {
    FILE *stream;
    errno_t err = _wfopen_s(&stream, _file.c_str(), L"w");
    if (err != 0 || stream == NULL) {
        CLOG(L"Could not open settings file for writing!");
        return 100 + err;
    }
    tinyxml2::XMLError result = _xml.SaveFile(stream);
    fclose(stream);
    return result;
}

std::wstring Settings::AppDir() {
    if (_appDir.empty()) {
        wchar_t path[MAX_PATH] = { 0 };
        if (GetModuleFileName(NULL, path, MAX_PATH)) {
            PathRemoveFileSpec(path);
        }
        _appDir = std::wstring(path);
    }
    return _appDir;
}

std::wstring Settings::SkinDir() {
    return AppDir() + L"\\" + SKIN_DIR;
}

std::wstring Settings::SettingsApp() {
    return Settings::AppDir() + L"\\" + SETTINGS_APP;
}

std::wstring Settings::LanguagesDir() {
    return AppDir() + L"\\" + LANG_DIR;
}

void Settings::LaunchSettingsApp() {
    std::wstring app = SettingsApp();

    CLOG(L"Opening Settings App: %s", app.c_str());
    int exec = (int) ShellExecute(
        NULL, L"open", app.c_str(), NULL, NULL, SW_SHOWNORMAL);

    if (exec <= 32) {
        Error::ErrorMessage(GENERR_NOTFOUND, app);
    }
}

std::wstring Settings::AudioDeviceID() {
    return GetText(XML_AUDIODEV);
}

std::wstring Settings::LanguageName() {
    std::wstring lang = GetText(XML_LANGUAGE);

    if (lang == L"") {
        return DefaultLanguage;
    } else {
        return lang;
    }
}

bool Settings::AlwaysOnTop() {
    return GetEnabled(XML_ONTOP, DefaultOnTop);
}

void Settings::AlwaysOnTop(bool enable) {
    SetEnabled(XML_ONTOP, enable);
}

bool Settings::HideFullscreen() {
    return GetEnabled(XML_HIDE_WHENFULL, DefaultHideFullscreen);
}

void Settings::HideFullscreen(bool enable) {
    SetEnabled(XML_HIDE_WHENFULL, enable);
}

std::wstring Settings::Monitor() {
    return GetText(XML_MONITOR);
}

void Settings::Monitor(std::wstring monitorName) {
    SetText(XML_MONITOR, StringUtils::Narrow(monitorName));
}

int Settings::OSDEdgeOffset() {
    if (HasSetting(XML_OSD_OFFSET)) {
        return GetInt(XML_OSD_OFFSET);
    } else {
        return DefaultOSDOffset;
    }
}

void Settings::OSDEdgeOffset(int offset) {
    SetInt(XML_OSD_OFFSET, offset);
}

Settings::OSDPos Settings::OSDPosition() {
    std::wstring pos = GetText(XML_OSD_POS);
    const wchar_t *posStr = pos.c_str();

    for (unsigned int i = 0; i < OSDPosNames.size(); ++i) {
        if (_wcsicmp(posStr, OSDPosNames[i].c_str()) == 0) {
            return (Settings::OSDPos) i;
        }
    }

    return DefaultOSDPosition;
}

void Settings::OSDPosition(OSDPos pos) {
    std::wstring posStr = OSDPosNames[(int) pos];
    SetText(XML_OSD_POS, StringUtils::Narrow(posStr));
}

int Settings::OSDX() {
    return GetInt(XML_OSD_X);
}

void Settings::OSDX(int x) {
    SetInt(XML_OSD_X, x);
}

int Settings::OSDY() {
    return GetInt(XML_OSD_Y);
}

void Settings::OSDY(int y) {
    SetInt(XML_OSD_Y, y);
}

AnimationTypes::HideAnimation Settings::HideAnim() {
    std::wstring anim = GetText(XML_HIDEANIM);
    const wchar_t *animStr = anim.c_str();

    std::vector<std::wstring> *names = &AnimationTypes::HideAnimationNames;
    for (unsigned int i = 0; i < names->size(); ++i) {
        if (_wcsicmp(animStr, (*names)[i].c_str()) == 0) {
            return (AnimationTypes::HideAnimation) i;
        }
    }

    return DefaultHideAnim;
}

void Settings::HideAnim(AnimationTypes::HideAnimation anim) {
    std::wstring hideStr = AnimationTypes::HideAnimationNames[(int) anim];
    SetText(XML_HIDEANIM, StringUtils::Narrow(hideStr));
}

int Settings::HideDelay() {
    return GetInt(XML_HIDETIME, DEFAULT_HIDE_TIME);
}

void Settings::HideDelay(int delay) {
    SetInt(XML_HIDETIME, delay);
}

int Settings::HideSpeed() {
    return GetInt(XML_HIDESPEED, DEFAULT_HIDE_SPEED);
}

void Settings::HideSpeed(int speed) {
    SetInt(XML_HIDESPEED, speed);
}

bool Settings::CurrentSkin(std::wstring skinName) {
    std::string name = StringUtils::Narrow(skinName);
    std::wstring xml = SkinXML(skinName);
    if (PathFileExists(xml.c_str()) == FALSE) {
        return false;
    }

    SetText(XML_SKIN, name);
    return true;
}

std::wstring Settings::CurrentSkin() {
    std::wstring name = GetText("skin");

    if (name == L"") {
        return DefaultSkin;
    } else {
        return name;
    }
}

std::wstring Settings::SkinXML() {
    return SkinXML(CurrentSkin());
}

std::wstring Settings::SkinXML(std::wstring skinName) {
    std::wstring skinXML = Settings::AppDir() + L"\\" + SKINS_DIR L"\\"
        + skinName + L"\\" SKIN_XML;
    return skinXML;
}

std::unordered_map<int, HotkeyInfo> Settings::Hotkeys() {
    std::unordered_map<int, HotkeyInfo> keyMappings;

    if (_root == NULL) {
        return keyMappings;
    }

    tinyxml2::XMLElement *hotkeys = _root->FirstChildElement("hotkeys");
    if (hotkeys == NULL) {
        return keyMappings;
    }

    tinyxml2::XMLElement *hotkey = hotkeys->FirstChildElement("hotkey");
    for (; hotkey != NULL; hotkey = hotkey->NextSiblingElement()) {
        int action = -1;
        hotkey->QueryIntAttribute("action", &action);
        if (action == -1) {
            CLOG(L"No action provided for hotkey; skipping");
            continue;
        }

        int combination = -1;
        hotkey->QueryIntAttribute("combination", &combination);
        if (combination == -1) {
            CLOG(L"No key combination provided for hotkey; skipping");
            continue;
        }

        HotkeyInfo hki;
        hki.action = action;
        hki.keyCombination = combination;

        /* Does this hotkey action have any arguments? */
        tinyxml2::XMLElement *arg = hotkey->FirstChildElement("arg");
        for (; arg != NULL; arg = arg->NextSiblingElement()) {
            const char *argStr = arg->GetText();
            hki.args.push_back(StringUtils::Widen(argStr));
        }

        /* Whew, we made it! */
        CLOG(L"%s", hki.ToString().c_str());
        keyMappings[combination] = hki;
    }

    return keyMappings;
}

void Settings::Hotkeys(std::vector<HotkeyInfo> hotkeys) {
    tinyxml2::XMLElement *hkElem = GetOrCreateElement("hotkeys");
    hkElem->DeleteChildren();

    for (HotkeyInfo hotkey : hotkeys) {
        tinyxml2::XMLElement *hk = _xml.NewElement("hotkey");

        hk->SetAttribute("combination", hotkey.keyCombination);
        hk->SetAttribute("action", hotkey.action);

        if (hotkey.args.size() > 0) {
            for (std::wstring arg : hotkey.args) {
                tinyxml2::XMLElement *argElem = _xml.NewElement("arg");
                argElem->SetText(StringUtils::Narrow(arg).c_str());
                hk->InsertEndChild(argElem);
            }
        }

        hkElem->InsertEndChild(hk);
    }
}

LanguageTranslator *Settings::Translator() {
    if (_translator == NULL) {
        _translator = new LanguageTranslator();
    }

    return _translator;
}

bool Settings::NotifyIconEnabled() {
    return GetEnabled(XML_NOTIFYICON, DefaultNotifyIcon);
}

void Settings::NotifyIconEnabled(bool enable) {
    SetEnabled(XML_NOTIFYICON, enable);
}

bool Settings::SoundEffectsEnabled() {
    return GetEnabled(XML_SOUNDS, DefaultSoundsEnabled);
}

void Settings::SoundEffectsEnabled(bool enable) {
    SetEnabled(XML_SOUNDS, enable);
}

bool Settings::HasSetting(std::string elementName) {
    if (_root == NULL) {
        return false;
    }

    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    return (el != NULL);
}

bool Settings::GetEnabled(std::string elementName, const bool defaultSetting) {
    if (_root == NULL) {
        return defaultSetting;
    }

    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        std::wstring elStr = StringUtils::Widen(elementName);
        CLOG(L"Warning: XML element '%s' not found", elStr.c_str());
        return defaultSetting;
    } else {
        bool val = false;
        el->QueryBoolText(&val);
        return val;
    }
}

void Settings::SetEnabled(std::string elementName, bool enabled) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(enabled ? "true" : "false");
}

std::wstring Settings::GetText(std::string elementName) {
    if (_root == NULL) {
        return L"";
    }

    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        CLOG(L"Warning: XML element %s not found",
            StringUtils::Widen(elementName).c_str());
        return L"";
    }

    const char* str = el->GetText();
    if (str == NULL) {
        return L"";
    } else {
        return StringUtils::Widen(str);
    }
}

void Settings::SetText(std::string elementName, std::string text) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(text.c_str());
}

int Settings::GetInt(std::string elementName, const int defaultValue) {
    if (_root == NULL) {
        return defaultValue;
    }

    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        std::wstring elStr = StringUtils::Widen(elementName);
        CLOG(L"Warning: XML element '%s' not found", elStr.c_str());
        return defaultValue;
    }

    int val = defaultValue;
    el->QueryIntText(&val);
    return val;
}

void Settings::SetInt(std::string elementName, int value) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(value);
}

tinyxml2::XMLElement *Settings::GetOrCreateElement(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        el = _xml.NewElement(elementName.c_str());
        _root->InsertEndChild(el);
    }
    return el;
}<commit_msg>Update for defaults change<commit_after>#include "Settings.h"

#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
#include <algorithm>

#include "Error.h"
#include "HotkeyInfo.h"
#include "LanguageTranslator.h"
#include "Logger.h"
#include "Monitor.h"
#include "Skin.h"
#include "StringUtils.h"

#define XML_AUDIODEV "audioDeviceID"
#define XML_HIDE_WHENFULL "hideFullscreen"
#define XML_HIDEANIM "hideAnimation"
#define XML_HIDETIME "hideDelay"
#define XML_HIDESPEED "hideSpeed"
#define XML_LANGUAGE "language"
#define XML_MONITOR "monitor"
#define XML_NOTIFYICON "notifyIcon"
#define XML_ONTOP "onTop"
#define XML_OSD_OFFSET "osdEdgeOffset"
#define XML_OSD_POS "osdPosition"
#define XML_OSD_X "osdX"
#define XML_OSD_Y "osdY"
#define XML_SKIN "skin"
#define XML_SOUNDS "soundEffects"

std::wstring Settings::_appDir(L"");
Settings *Settings::instance;

std::vector<std::wstring> Settings::OSDPosNames = {
    L"Top",
    L"Left",
    L"Right",
    L"Bottom",
    L"Center",
    L"Top-left",
    L"Top-right",
    L"Bottom-left",
    L"Bottom-right",
    L"Custom"
};

Settings *Settings::Instance() {
    if (instance == NULL) {
        instance = new Settings();
    }
    return instance;
}

void Settings::Load() {
    _file = AppDir() + L"\\Settings.xml";
    CLOG(L"Loading settings: %s", _file.c_str());

    std::string u8FileName = StringUtils::Narrow(_file);
    tinyxml2::XMLError result = _xml.LoadFile(u8FileName.c_str());
    if (result != tinyxml2::XMLError::XML_SUCCESS) {
        Error::ErrorMessageDie(GENERR_SETTINGSFILE, _file);
    }

    _root = _xml.GetDocument()->FirstChildElement("settings");
    if (_root == NULL) {
        Error::ErrorMessageDie(GENERR_MISSING_XML, L"<settings>");
    }
}

int Settings::Save() {
    FILE *stream;
    errno_t err = _wfopen_s(&stream, _file.c_str(), L"w");
    if (err != 0 || stream == NULL) {
        CLOG(L"Could not open settings file for writing!");
        return 100 + err;
    }
    tinyxml2::XMLError result = _xml.SaveFile(stream);
    fclose(stream);
    return result;
}

std::wstring Settings::AppDir() {
    if (_appDir.empty()) {
        wchar_t path[MAX_PATH] = { 0 };
        if (GetModuleFileName(NULL, path, MAX_PATH)) {
            PathRemoveFileSpec(path);
        }
        _appDir = std::wstring(path);
    }
    return _appDir;
}

std::wstring Settings::SkinDir() {
    return AppDir() + L"\\" + SKIN_DIR;
}

std::wstring Settings::SettingsApp() {
    return Settings::AppDir() + L"\\" + SETTINGS_APP;
}

std::wstring Settings::LanguagesDir() {
    return AppDir() + L"\\" + LANG_DIR;
}

void Settings::LaunchSettingsApp() {
    std::wstring app = SettingsApp();

    CLOG(L"Opening Settings App: %s", app.c_str());
    int exec = (int) ShellExecute(
        NULL, L"open", app.c_str(), NULL, NULL, SW_SHOWNORMAL);

    if (exec <= 32) {
        Error::ErrorMessage(GENERR_NOTFOUND, app);
    }
}

std::wstring Settings::AudioDeviceID() {
    return GetText(XML_AUDIODEV);
}

std::wstring Settings::LanguageName() {
    std::wstring lang = GetText(XML_LANGUAGE);

    if (lang == L"") {
        return DefaultLanguage;
    } else {
        return lang;
    }
}

bool Settings::AlwaysOnTop() {
    return GetEnabled(XML_ONTOP, DefaultOnTop);
}

void Settings::AlwaysOnTop(bool enable) {
    SetEnabled(XML_ONTOP, enable);
}

bool Settings::HideFullscreen() {
    return GetEnabled(XML_HIDE_WHENFULL, DefaultHideFullscreen);
}

void Settings::HideFullscreen(bool enable) {
    SetEnabled(XML_HIDE_WHENFULL, enable);
}

std::wstring Settings::Monitor() {
    return GetText(XML_MONITOR);
}

void Settings::Monitor(std::wstring monitorName) {
    SetText(XML_MONITOR, StringUtils::Narrow(monitorName));
}

int Settings::OSDEdgeOffset() {
    if (HasSetting(XML_OSD_OFFSET)) {
        return GetInt(XML_OSD_OFFSET);
    } else {
        return DefaultOSDOffset;
    }
}

void Settings::OSDEdgeOffset(int offset) {
    SetInt(XML_OSD_OFFSET, offset);
}

Settings::OSDPos Settings::OSDPosition() {
    std::wstring pos = GetText(XML_OSD_POS);
    const wchar_t *posStr = pos.c_str();

    for (unsigned int i = 0; i < OSDPosNames.size(); ++i) {
        if (_wcsicmp(posStr, OSDPosNames[i].c_str()) == 0) {
            return (Settings::OSDPos) i;
        }
    }

    return DefaultOSDPosition;
}

void Settings::OSDPosition(OSDPos pos) {
    std::wstring posStr = OSDPosNames[(int) pos];
    SetText(XML_OSD_POS, StringUtils::Narrow(posStr));
}

int Settings::OSDX() {
    return GetInt(XML_OSD_X);
}

void Settings::OSDX(int x) {
    SetInt(XML_OSD_X, x);
}

int Settings::OSDY() {
    return GetInt(XML_OSD_Y);
}

void Settings::OSDY(int y) {
    SetInt(XML_OSD_Y, y);
}

AnimationTypes::HideAnimation Settings::HideAnim() {
    std::wstring anim = GetText(XML_HIDEANIM);
    const wchar_t *animStr = anim.c_str();

    std::vector<std::wstring> *names = &AnimationTypes::HideAnimationNames;
    for (unsigned int i = 0; i < names->size(); ++i) {
        if (_wcsicmp(animStr, (*names)[i].c_str()) == 0) {
            return (AnimationTypes::HideAnimation) i;
        }
    }

    return DefaultHideAnim;
}

void Settings::HideAnim(AnimationTypes::HideAnimation anim) {
    std::wstring hideStr = AnimationTypes::HideAnimationNames[(int) anim];
    SetText(XML_HIDEANIM, StringUtils::Narrow(hideStr));
}

int Settings::HideDelay() {
    return GetInt(XML_HIDETIME, DefaultHideTime);
}

void Settings::HideDelay(int delay) {
    SetInt(XML_HIDETIME, delay);
}

int Settings::HideSpeed() {
    return GetInt(XML_HIDESPEED, DefaultHideSpeed);
}

void Settings::HideSpeed(int speed) {
    SetInt(XML_HIDESPEED, speed);
}

bool Settings::CurrentSkin(std::wstring skinName) {
    std::string name = StringUtils::Narrow(skinName);
    std::wstring xml = SkinXML(skinName);
    if (PathFileExists(xml.c_str()) == FALSE) {
        return false;
    }

    SetText(XML_SKIN, name);
    return true;
}

std::wstring Settings::CurrentSkin() {
    std::wstring name = GetText("skin");

    if (name == L"") {
        return DefaultSkin;
    } else {
        return name;
    }
}

std::wstring Settings::SkinXML() {
    return SkinXML(CurrentSkin());
}

std::wstring Settings::SkinXML(std::wstring skinName) {
    std::wstring skinXML = Settings::AppDir() + L"\\" + SKINS_DIR L"\\"
        + skinName + L"\\" SKIN_XML;
    return skinXML;
}

std::unordered_map<int, HotkeyInfo> Settings::Hotkeys() {
    std::unordered_map<int, HotkeyInfo> keyMappings;

    if (_root == NULL) {
        return keyMappings;
    }

    tinyxml2::XMLElement *hotkeys = _root->FirstChildElement("hotkeys");
    if (hotkeys == NULL) {
        return keyMappings;
    }

    tinyxml2::XMLElement *hotkey = hotkeys->FirstChildElement("hotkey");
    for (; hotkey != NULL; hotkey = hotkey->NextSiblingElement()) {
        int action = -1;
        hotkey->QueryIntAttribute("action", &action);
        if (action == -1) {
            CLOG(L"No action provided for hotkey; skipping");
            continue;
        }

        int combination = -1;
        hotkey->QueryIntAttribute("combination", &combination);
        if (combination == -1) {
            CLOG(L"No key combination provided for hotkey; skipping");
            continue;
        }

        HotkeyInfo hki;
        hki.action = action;
        hki.keyCombination = combination;

        /* Does this hotkey action have any arguments? */
        tinyxml2::XMLElement *arg = hotkey->FirstChildElement("arg");
        for (; arg != NULL; arg = arg->NextSiblingElement()) {
            const char *argStr = arg->GetText();
            hki.args.push_back(StringUtils::Widen(argStr));
        }

        /* Whew, we made it! */
        CLOG(L"%s", hki.ToString().c_str());
        keyMappings[combination] = hki;
    }

    return keyMappings;
}

void Settings::Hotkeys(std::vector<HotkeyInfo> hotkeys) {
    tinyxml2::XMLElement *hkElem = GetOrCreateElement("hotkeys");
    hkElem->DeleteChildren();

    for (HotkeyInfo hotkey : hotkeys) {
        tinyxml2::XMLElement *hk = _xml.NewElement("hotkey");

        hk->SetAttribute("combination", hotkey.keyCombination);
        hk->SetAttribute("action", hotkey.action);

        if (hotkey.args.size() > 0) {
            for (std::wstring arg : hotkey.args) {
                tinyxml2::XMLElement *argElem = _xml.NewElement("arg");
                argElem->SetText(StringUtils::Narrow(arg).c_str());
                hk->InsertEndChild(argElem);
            }
        }

        hkElem->InsertEndChild(hk);
    }
}

LanguageTranslator *Settings::Translator() {
    if (_translator == NULL) {
        _translator = new LanguageTranslator();
    }

    return _translator;
}

bool Settings::NotifyIconEnabled() {
    return GetEnabled(XML_NOTIFYICON, DefaultNotifyIcon);
}

void Settings::NotifyIconEnabled(bool enable) {
    SetEnabled(XML_NOTIFYICON, enable);
}

bool Settings::SoundEffectsEnabled() {
    return GetEnabled(XML_SOUNDS, DefaultSoundsEnabled);
}

void Settings::SoundEffectsEnabled(bool enable) {
    SetEnabled(XML_SOUNDS, enable);
}

bool Settings::HasSetting(std::string elementName) {
    if (_root == NULL) {
        return false;
    }

    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    return (el != NULL);
}

bool Settings::GetEnabled(std::string elementName, const bool defaultSetting) {
    if (_root == NULL) {
        return defaultSetting;
    }

    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        std::wstring elStr = StringUtils::Widen(elementName);
        CLOG(L"Warning: XML element '%s' not found", elStr.c_str());
        return defaultSetting;
    } else {
        bool val = false;
        el->QueryBoolText(&val);
        return val;
    }
}

void Settings::SetEnabled(std::string elementName, bool enabled) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(enabled ? "true" : "false");
}

std::wstring Settings::GetText(std::string elementName) {
    if (_root == NULL) {
        return L"";
    }

    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        CLOG(L"Warning: XML element %s not found",
            StringUtils::Widen(elementName).c_str());
        return L"";
    }

    const char* str = el->GetText();
    if (str == NULL) {
        return L"";
    } else {
        return StringUtils::Widen(str);
    }
}

void Settings::SetText(std::string elementName, std::string text) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(text.c_str());
}

int Settings::GetInt(std::string elementName, const int defaultValue) {
    if (_root == NULL) {
        return defaultValue;
    }

    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        std::wstring elStr = StringUtils::Widen(elementName);
        CLOG(L"Warning: XML element '%s' not found", elStr.c_str());
        return defaultValue;
    }

    int val = defaultValue;
    el->QueryIntText(&val);
    return val;
}

void Settings::SetInt(std::string elementName, int value) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(value);
}

tinyxml2::XMLElement *Settings::GetOrCreateElement(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        el = _xml.NewElement(elementName.c_str());
        _root->InsertEndChild(el);
    }
    return el;
}<|endoftext|>


<commit_before>#include <cstdio>
#include <algorithm>
using namespace std;

char dna[1001][51];
int n, m, answer;

int main() {
    scanf("%d %d", &n, &m);

    for (int i = 0; i < n; i++) {
        scanf("%s", dna[i]);
    }

    for (int i = 0; i < m; i++) {
        int a = 0, t = 0, g = 0, c = 0;

        for (int j = 0; j < n; j++) {
            switch (dna[j][i]) {
                case 'A':
                    a++;
                    break;
                case 'T':
                    t++;
                    break;
                case 'G':
                    g++;
                    break;
                case 'C':
                    c++;
                    break;
            }
        }

        int maxChar = max(max(a, c), max(g, t));
        answer += n - maxChar;
        if (maxChar == a) {
            printf("A");
        } else if (maxChar == c) {
            printf("C");
        } else if (maxChar == g) {
            printf("G");
        } else if (maxChar == t) {
            printf("T");
        }
    }
    printf("\n%d\n", answer);
}<commit_msg>add comment<commit_after>#include <cstdio>
#include <algorithm>
using namespace std;

char dna[1001][51];
int n, m, answer;

int main() {
    scanf("%d %d", &n, &m);

    for (int i = 0; i < n; i++) {
        scanf("%s", dna[i]);
    }

    for (int i = 0; i < m; i++) {
        int a = 0, t = 0, g = 0, c = 0;

        for (int j = 0; j < n; j++) { // 세로로 보면서 어떤 값이 제일 많이 나왔는지 탐색
            switch (dna[j][i]) {
                case 'A':
                    a++;
                    break;
                case 'T':
                    t++;
                    break;
                case 'G':
                    g++;
                    break;
                case 'C':
                    c++;
                    break;
            }
        }

        int maxChar = max(max(a, c), max(g, t));
        answer += n - maxChar; // 행의 길이 - 제일 많이나온 알파벳 = 다른 글자 수

        if (maxChar == a) {
            printf("A");
        } else if (maxChar == c) {
            printf("C");
        } else if (maxChar == g) {
            printf("G");
        } else if (maxChar == t) {
            printf("T");
        }
    }

    printf("\n%d\n", answer);
}<|endoftext|>


<commit_before><commit_msg>Fix compilation error with some platforms<commit_after><|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * Copyright (c) 2014 Kohei Yoshida
 *
 * 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 "../include/mdds/sorted_string_map.hpp"

#include <cstdlib>
#include <iostream>
#include <cstring>

#include <boost/unordered_map.hpp>

using namespace std;

#include <stdio.h>
#include <string>
#include <sys/time.h>

namespace {

class stack_printer
{
public:
    explicit stack_printer(const char* msg) :
        m_msg(msg)
    {
        fprintf(stdout, "%s: --begin\n", m_msg.c_str());
        m_start_time = getTime();
    }

    ~stack_printer()
    {
        double end_time = getTime();
        fprintf(stdout, "%s: --end (duration: %g sec)\n", m_msg.c_str(), (end_time - m_start_time));
    }

    void printTime(int line) const
    {
        double fEndTime = getTime();
        fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", m_msg.c_str(), line, (fEndTime - m_start_time));
    }

private:
    double getTime() const
    {
        timeval tv;
        gettimeofday(&tv, NULL);
        return tv.tv_sec + tv.tv_usec / 1000000.0;
    }

    ::std::string m_msg;
    double m_start_time;
};

}

enum name_type {
    name_none = 0,
    name_andy,
    name_bruce,
    name_charlie,
    name_david
};

typedef mdds::sorted_string_map<name_type> map_type;

map_type::entry entries[] =
{
    { "andy", name_andy },
    { "andy1", name_andy },
    { "andy13", name_andy },
    { "bruce", name_bruce },
    { "charlie", name_charlie },
    { "david", name_david },
};

typedef boost::unordered_map<std::string, name_type> hashmap_type;

void init_hash_map(hashmap_type& hm)
{
    size_t n = sizeof(entries) / sizeof(entries[0]);
    const map_type::entry* p = entries;
    const map_type::entry* pend = p + n;
    for (; p != pend; ++p)
        hm.insert(hashmap_type::value_type(p->key, p->value));
}

void run(map_type& sm, const char* input)
{
    name_type type = sm.find(input, strlen(input));
}

void run_hash(hashmap_type& hm, const char* input)
{
    name_type type = name_none;
    hashmap_type::const_iterator it = hm.find(input);
    if (it != hm.end())
        type = it->second;
}

const char* tests[] = {
    "andy",
    "david",
    "charlie",
    "andy1",
    "bruce",
    "blah",
    "andy13"
};

int main()
{
    static const size_t repeat_count = 10000000;

    map_type sorted_map(entries, sizeof(entries)/sizeof(entries[0]), name_none);
    size_t n = sorted_map.size();
    cout << "entry count = " << n << endl;

    {
        stack_printer __stack_printer__("sorted entry");
        for (size_t rep = 0; rep < repeat_count; ++rep)
        {
            for (size_t i = 0; i < n; ++i)
                run(sorted_map, tests[i]);
        }
    }

    hashmap_type hm;
    init_hash_map(hm);
    {
        stack_printer __stack_printer__("hash map");
        for (size_t rep = 0; rep < repeat_count; ++rep)
        {
            for (size_t i = 0; i < n; ++i)
                run_hash(hm, tests[i]);
        }
    }

    return EXIT_SUCCESS;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Update the perf code.<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * Copyright (c) 2014 Kohei Yoshida
 *
 * 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 "../include/mdds/sorted_string_map.hpp"
#include "../include/mdds/trie_map.hpp"
#include "../include/mdds/global.hpp"

#include <cstdlib>
#include <iostream>
#include <cstring>
#include <unordered_map>

using namespace std;

#include <stdio.h>
#include <string>
#include <sys/time.h>

namespace {

class stack_printer
{
public:
    explicit stack_printer(const char* msg) :
        m_msg(msg)
    {
        fprintf(stdout, "%s: --begin\n", m_msg.c_str());
        m_start_time = getTime();
    }

    ~stack_printer()
    {
        double end_time = getTime();
        fprintf(stdout, "%s: --end (duration: %g sec)\n", m_msg.c_str(), (end_time - m_start_time));
    }

    void printTime(int line) const
    {
        double fEndTime = getTime();
        fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", m_msg.c_str(), line, (fEndTime - m_start_time));
    }

private:
    double getTime() const
    {
        timeval tv;
        gettimeofday(&tv, NULL);
        return tv.tv_sec + tv.tv_usec / 1000000.0;
    }

    ::std::string m_msg;
    double m_start_time;
};

}

typedef mdds::sorted_string_map<int> map_type;

map_type::entry entries[] =
{
    { MDDS_ASCII("aaron"),     0 },
    { MDDS_ASCII("al"),        1 },
    { MDDS_ASCII("aldi"),      2 },
    { MDDS_ASCII("andy"),      3 },
    { MDDS_ASCII("bison"),     4 },
    { MDDS_ASCII("bruce"),     5 },
    { MDDS_ASCII("charlie"),   6 },
    { MDDS_ASCII("charlotte"), 7 },
    { MDDS_ASCII("david"),     8 },
    { MDDS_ASCII("dove"),      9 },
    { MDDS_ASCII("e"),        10 },
    { MDDS_ASCII("eva"),      11 },
};

typedef mdds::packed_trie_map<int> trie_map_type;

trie_map_type::entry trie_entries[] =
{
    { MDDS_ASCII("aaron"),     0 },
    { MDDS_ASCII("al"),        1 },
    { MDDS_ASCII("aldi"),      2 },
    { MDDS_ASCII("andy"),      3 },
    { MDDS_ASCII("bison"),     4 },
    { MDDS_ASCII("bruce"),     5 },
    { MDDS_ASCII("charlie"),   6 },
    { MDDS_ASCII("charlotte"), 7 },
    { MDDS_ASCII("david"),     8 },
    { MDDS_ASCII("dove"),      9 },
    { MDDS_ASCII("e"),        10 },
    { MDDS_ASCII("eva"),      11 },
};

typedef std::unordered_map<std::string, int> hashmap_type;

void init_hash_map(hashmap_type& hm)
{
    size_t n = sizeof(entries) / sizeof(entries[0]);
    const map_type::entry* p = entries;
    const map_type::entry* pend = p + n;
    for (; p != pend; ++p)
        hm.insert(hashmap_type::value_type(p->key, p->value));
}

void run(map_type& sm, const char* input)
{
    static int sum = 0;
    int type = sm.find(input, strlen(input));
    sum += type;
}

void run(trie_map_type& sm, const char* input)
{
    static int sum = 0;
    int type = sm.find(input, strlen(input));
    sum += type;
}

void run_hash(hashmap_type& hm, const char* input)
{
    static int sum = 0;
    int type = -1;
    hashmap_type::const_iterator it = hm.find(input);
    if (it != hm.end())
        type = it->second;
    sum += type;
}

const char* tests[] = {
    "aaron"
    "al",
    "aldi",
    "andy",
    "andy1",
    "andy13",
    "bison",
    "blah",
    "bruce",
    "bruce",
    "charlie",
    "charlotte",
    "david",
    "dove",
    "e",
    "eva"
};

int main()
{
    static const size_t repeat_count = 10000000;

    map_type sorted_map(entries, MDDS_N_ELEMENTS(entries), -1);
    size_t n = sorted_map.size();
    cout << "entry count = " << n << endl;

    {
        stack_printer __stack_printer__("sorted map");
        for (size_t rep = 0; rep < repeat_count; ++rep)
        {
            for (size_t i = 0; i < n; ++i)
                run(sorted_map, tests[i]);
        }
    }

    trie_map_type trie_map(trie_entries, MDDS_N_ELEMENTS(trie_entries), -1);
    n = trie_map.size();
    cout << "entry count = " << n << endl;

    {
        stack_printer __stack_printer__("trie map");
        for (size_t rep = 0; rep < repeat_count; ++rep)
        {
            for (size_t i = 0; i < n; ++i)
                run(trie_map, tests[i]);
        }
    }

    hashmap_type hm;
    init_hash_map(hm);
    {
        stack_printer __stack_printer__("hash map");
        for (size_t rep = 0; rep < repeat_count; ++rep)
        {
            for (size_t i = 0; i < n; ++i)
                run_hash(hm, tests[i]);
        }
    }

    return EXIT_SUCCESS;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>
/*************************************************************************
 * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Windows4Root.h"
#include "TWin32SplashThread.h"

TWin32SplashThread *gSplash = 0;

extern void CreateSplash(DWORD time, BOOL extended);
extern void DestroySplashScreen();

//______________________________________________________________________________
static DWORD WINAPI HandleSplashThread(LPVOID extended)
{
   // thread for handling Splash Screen

   CreateSplash(4, (Bool_t)extended);
   ::ExitThread(0);
   if (gSplash) delete gSplash;
   gSplash = 0;
   return 0;
}

//______________________________________________________________________________
TWin32SplashThread::TWin32SplashThread(Bool_t extended)
{
   // ctor.
   fHandle = 0;
   DWORD splashId = 0;
   fHandle = ::CreateThread( NULL, 0,&HandleSplashThread, (LPVOID)extended, 0, &splashId );
   gSplash = this;
}

//______________________________________________________________________________
TWin32SplashThread::~TWin32SplashThread()
{
   // dtor

   DestroySplashScreen();
   TerminateThread(fHandle, 0);
   if (fHandle) ::CloseHandle(fHandle);
   fHandle = 0;
}

<commit_msg>From Axel: in C++ "return" is better than ExitThread. Says MS. And who are we to doubt that!<commit_after>
/*************************************************************************
 * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Windows4Root.h"
#include "TWin32SplashThread.h"

TWin32SplashThread *gSplash = 0;

extern void CreateSplash(DWORD time, BOOL extended);
extern void DestroySplashScreen();

//______________________________________________________________________________
static DWORD WINAPI HandleSplashThread(LPVOID extended)
{
   // thread for handling Splash Screen

   CreateSplash(4, (Bool_t)extended);
   if (gSplash) delete gSplash;
   gSplash = 0;
   return 0;
}

//______________________________________________________________________________
TWin32SplashThread::TWin32SplashThread(Bool_t extended)
{
   // ctor.
   fHandle = 0;
   DWORD splashId = 0;
   fHandle = ::CreateThread( NULL, 0,&HandleSplashThread, (LPVOID)extended, 0, &splashId );
   gSplash = this;
}

//______________________________________________________________________________
TWin32SplashThread::~TWin32SplashThread()
{
   // dtor

   DestroySplashScreen();
   TerminateThread(fHandle, 0);
   if (fHandle) ::CloseHandle(fHandle);
   fHandle = 0;
}

<|endoftext|>


<commit_before>#include "coilBoard.h"
#include <chrono>
#include <thread>
#define TRIBBLER_QUEUE_SIZE 30
#define TRIBBLER_STATE_THRESHOLD 16

void CoilBoard::Kick(){
	boost::posix_time::ptime time2 = boost::posix_time::microsec_clock::local_time();
	//std::cout << (afterKickTime - time2).total_milliseconds() << std::endl;
	if ((time2 - afterKickTime).total_milliseconds() < 1500) return;
	//writeString("k800\n");
	kick = true;
	forcedNotInTribbler = true;
	afterKickTime = time2; //reset timer
	return;
}

void CoilBoard::ToggleTribbler(bool start){
	if (start) {
		writeString("m1\n");
	}
	else{
		writeString("m0\n");
	}

	return;
}

bool CoilBoard::BallInTribbler(){

	return ballInTribblerCount > 0;
}

void CoilBoard::Run(){
	writeString("c\n");
	while (!stop_thread){
		std::string line = readLineAsync(10);
		if(line == "true" || line == "false" && !forcedNotInTribbler){
			std::cout << "ballInTribblerCount " << ballInTribblerCount << " " << line << std::endl;
			int newcount = ballInTribblerCount + ((line == "true") ? 1 : -1);
			std::cout << "ballInTribblerCount " << ballInTribblerCount << " " << newcount << " " << line << std::endl;
			ballInTribblerCount = std::min(20, std::max(-20, newcount));
 		}
		//Pinging
		time = boost::posix_time::microsec_clock::local_time();
		boost::posix_time::time_duration::tick_type waitDuration = (time - waitTime).total_milliseconds();
		if (waitDuration > 300){
			writeString("p\n");
			waitTime = time;
		} else {
			writeString("b\n");
		}
		if (kick) {
			std::cout << "kick ----->" << std::endl;
			writeString("k800\n");
		}
		/*
		//Forcing ballintribler false after kick
		boost::posix_time::time_duration::tick_type afterKickDuration = (time - afterKickTime).total_milliseconds();
		if (afterKickDuration > 1000 && forcedNotInTribbler){
			//forcedNotInTribbler = false;
		}
		else if (forcedNotInTribbler){
			ballInTribblerCount = -1;
		}
		*/
		std::chrono::milliseconds dura(10);
		std::this_thread::sleep_for(dura);
	}
	writeString("d\n");
	writeString("m0\n");
}

<commit_msg>forgot to unkick<commit_after>#include "coilBoard.h"
#include <chrono>
#include <thread>
#define TRIBBLER_QUEUE_SIZE 30
#define TRIBBLER_STATE_THRESHOLD 16

void CoilBoard::Kick(){
	boost::posix_time::ptime time2 = boost::posix_time::microsec_clock::local_time();
	//std::cout << (afterKickTime - time2).total_milliseconds() << std::endl;
	if ((time2 - afterKickTime).total_milliseconds() < 1500) return;
	//writeString("k800\n");
	kick = true;
	forcedNotInTribbler = true;
	afterKickTime = time2; //reset timer
	return;
}

void CoilBoard::ToggleTribbler(bool start){
	if (start) {
		writeString("m1\n");
	}
	else{
		writeString("m0\n");
	}

	return;
}

bool CoilBoard::BallInTribbler(){

	return ballInTribblerCount > 0;
}

void CoilBoard::Run(){
	writeString("c\n");
	while (!stop_thread){
		std::string line = readLineAsync(10);
		if(line == "true" || line == "false" && !forcedNotInTribbler){
			std::cout << "ballInTribblerCount " << ballInTribblerCount << " " << line << std::endl;
			int newcount = ballInTribblerCount + ((line == "true") ? 1 : -1);
			std::cout << "ballInTribblerCount " << ballInTribblerCount << " " << newcount << " " << line << std::endl;
			ballInTribblerCount = std::min(20, std::max(-20, newcount));
 		}
		//Pinging
		time = boost::posix_time::microsec_clock::local_time();
		boost::posix_time::time_duration::tick_type waitDuration = (time - waitTime).total_milliseconds();
		if (waitDuration > 300){
			writeString("p\n");
			waitTime = time;
		} else {
			writeString("b\n");
		}
		if (kick) {
			std::cout << "kick ----->" << std::endl;
			writeString("k800\n");
			kick = false;
		}
		/*
		//Forcing ballintribler false after kick
		boost::posix_time::time_duration::tick_type afterKickDuration = (time - afterKickTime).total_milliseconds();
		if (afterKickDuration > 1000 && forcedNotInTribbler){
			//forcedNotInTribbler = false;
		}
		else if (forcedNotInTribbler){
			ballInTribblerCount = -1;
		}
		*/
		std::chrono::milliseconds dura(10);
		std::this_thread::sleep_for(dura);
	}
	writeString("d\n");
	writeString("m0\n");
}

<|endoftext|>


<commit_before>/** @file
 *
 * @ingroup modularLibrary
 *
 * @brief A Viewer Object.
 *
 * @details
 *
 * @authors Théo de la Hogue
 *
 * @copyright © 2010, Théo de la Hogue @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTViewer.h"

#define thisTTClass			TTViewer
#define thisTTClassName		"Viewer"
#define thisTTClassTags		"viewer"

TT_MODULAR_CONSTRUCTOR,
mAddress(kTTAdrsEmpty),
mDescription(kTTSym_none),
mType(kTTSym_generic),
mTag(kTTSym_none),
mHighlight(NO),
mFreeze(NO),
mDataspace(kTTSym_none),
mDataspaceUnit(kTTSym_none),
mDataspaceConverter(NULL),
mDataspaceObserver(NULL),
mDataspaceUnitObserver(NULL),
mActive(YES),
mReturnedValue(kTTValNONE),
mReceiver(NULL),
mSender(NULL),
mReturnValueCallback(NULL)
{
	if(arguments.size() == 1)
		mReturnValueCallback = TTCallbackPtr((TTObjectBasePtr)arguments[0]);

	addAttributeWithSetter(Address, kTypeSymbol);
	addAttribute(Description, kTypeSymbol);
	addAttribute(Type, kTypeSymbol);
	addAttribute(Tag, kTypeSymbol);
	addAttribute(Highlight, kTypeBoolean);
	addAttributeWithSetter(Freeze, kTypeBoolean);

	addAttribute(Dataspace, kTypeSymbol);
	addAttributeProperty(Dataspace, readOnly, YES);
	addAttributeWithSetter(DataspaceUnit, kTypeSymbol);

	addAttributeWithSetter(Active, kTypeBoolean);

	addAttributeWithSetter(ReturnedValue, kTypeLocalValue);
	addAttributeProperty(ReturnedValue, readOnly, YES);
	addAttributeProperty(ReturnedValue, hidden, YES);

	addMessageWithArguments(Send);
	addMessageProperty(Send, hidden, YES);

	TTObjectBaseInstantiate(TTSymbol("dataspace"),  &mDataspaceConverter, kTTValNONE);
}

TTViewer::~TTViewer() // TODO : delete things...
{
	if (mReturnValueCallback) {
		delete (TTValuePtr)mReturnValueCallback->getBaton();
		TTObjectBaseRelease(TTObjectBaseHandle(&mReturnValueCallback));
	}

	if (mDataspaceConverter)
		TTObjectBaseRelease(TTObjectBaseHandle(&mDataspaceConverter));

	if (mDataspaceObserver)
		TTObjectBaseRelease(TTObjectBaseHandle(&mDataspaceObserver));

	if (mDataspaceUnitObserver)
		TTObjectBaseRelease(TTObjectBaseHandle(&mDataspaceUnitObserver));

	if (mSender)
		TTObjectBaseRelease(TTObjectBaseHandle(&mSender));

	if (mReceiver)
		TTObjectBaseRelease(TTObjectBaseHandle(&mReceiver));
}

TTErr TTViewer::setAddress(const TTValue& value)
{
	mAddress = value[0];

	bind();

    refresh();

	return kTTErrNone;
}

TTErr TTViewer::bind()
{
	TTValue			args, v;
	TTObjectBasePtr	returnAddressCallback, returnValueCallback;
	TTValuePtr		returnAddressBaton, returnValueBaton;

	// Prepare arguments
	if (mAddress == kTTAdrsEmpty)
		return kTTErrGeneric;

	// The default attribute to bind is value
	if (mAddress.getAttribute() == NO_ATTRIBUTE)
		mAddress.appendAttribute(kTTSym_value);

	// Replace a TTSender object
	if (mSender)
		TTObjectBaseRelease(TTObjectBaseHandle(&mSender));

	mSender = NULL;							// without this, TTObjectBaseInstantiate try to release an oldObject that doesn't exist ... Is it good ?
	TTObjectBaseInstantiate(kTTSym_Sender, TTObjectBaseHandle(&mSender), kTTValNONE);

	mSender->setAttributeValue(kTTSym_address, mAddress);

	// Replace a TTReceiver object
	if (mReceiver)
		TTObjectBaseRelease(TTObjectBaseHandle(&mReceiver));

	returnAddressCallback = NULL;			// without this, TTObjectBaseInstantiate try to release an oldObject that doesn't exist ... Is it good ?
	TTObjectBaseInstantiate(TTSymbol("callback"), &returnAddressCallback, kTTValNONE);
	returnAddressBaton = new TTValue(TTObjectBasePtr(this));
	returnAddressCallback->setAttributeValue(kTTSym_baton, TTPtr(returnAddressBaton));
	returnAddressCallback->setAttributeValue(kTTSym_function, TTPtr(&TTViewerReceiveAddressCallback));
	args.append(returnAddressCallback);

	returnValueCallback = NULL;				// without this, TTObjectBaseInstantiate try to release an oldObject that doesn't exist ... Is it good ?
	TTObjectBaseInstantiate(TTSymbol("callback"), &returnValueCallback, kTTValNONE);
	returnValueBaton = new TTValue(TTObjectBasePtr(this));
	returnValueCallback->setAttributeValue(kTTSym_baton, TTPtr(returnValueBaton));
	returnValueCallback->setAttributeValue(kTTSym_function, TTPtr(&TTViewerReceiveValueCallback));
	args.append(returnValueCallback);

	mReceiver = NULL;						// without this, TTObjectBaseInstantiate try to release an oldObject that doesn't exist ... Is it good ?
	TTObjectBaseInstantiate(kTTSym_Receiver, TTObjectBaseHandle(&mReceiver), args);

	mReceiver->setAttributeValue(kTTSym_address, mAddress);

	observeDataspace();
	observeDataspaceUnit();

	return kTTErrNone;
}

TTErr TTViewer::refresh()
{
	if (mReceiver)
		return mReceiver->sendMessage(kTTSym_Get);

	return kTTErrGeneric;
}

TTErr TTViewer::observeDataspace()
{
	TTValue			args;
	TTObjectBasePtr		returnDataspaceCallback;
	TTValuePtr		returnDataspaceBaton;

	if (mDataspaceObserver)
		TTObjectBaseRelease(TTObjectBaseHandle(&mDataspaceObserver));

	args.append(NULL);

	returnDataspaceCallback = NULL;				// without this, TTObjectBaseInstantiate try to release an oldObject that doesn't exist ... Is it good ?
	TTObjectBaseInstantiate(TTSymbol("callback"), &returnDataspaceCallback, kTTValNONE);
	returnDataspaceBaton = new TTValue(TTObjectBasePtr(this));
	returnDataspaceCallback->setAttributeValue(kTTSym_baton, TTPtr(returnDataspaceBaton));
	returnDataspaceCallback->setAttributeValue(kTTSym_function, TTPtr(&TTViewerDataspaceCallback));
	args.append(returnDataspaceCallback);

	mDataspaceObserver = NULL;
	TTObjectBaseInstantiate(kTTSym_Receiver, TTObjectBaseHandle(&mDataspaceObserver), args);

	mDataspaceObserver->setAttributeValue(kTTSym_address, mAddress.appendAttribute(kTTSym_dataspace));

	mDataspaceObserver->sendMessage(kTTSym_Get);

	return kTTErrNone;
}

TTErr TTViewer::observeDataspaceUnit()
{
	TTValue			args;
	TTObjectBasePtr		returnDataspaceUnitCallback;
	TTValuePtr		returnDataspaceUnitBaton;

	if (mDataspaceUnitObserver)
		TTObjectBaseRelease(TTObjectBaseHandle(&mDataspaceUnitObserver));

	// Make a TTReceiver object
	args.append(NULL);

	returnDataspaceUnitCallback = NULL;				// without this, TTObjectBaseInstantiate try to release an oldObject that doesn't exist ... Is it good ?
	TTObjectBaseInstantiate(TTSymbol("callback"), &returnDataspaceUnitCallback, kTTValNONE);
	returnDataspaceUnitBaton = new TTValue(TTObjectBasePtr(this));
	returnDataspaceUnitCallback->setAttributeValue(kTTSym_baton, TTPtr(returnDataspaceUnitBaton));
	returnDataspaceUnitCallback->setAttributeValue(kTTSym_function, TTPtr(&TTViewerDataspaceUnitCallback));
	args.append(returnDataspaceUnitCallback);

	mDataspaceUnitObserver = NULL;
	TTObjectBaseInstantiate(kTTSym_Receiver, TTObjectBaseHandle(&mDataspaceUnitObserver), args);

	mDataspaceUnitObserver->setAttributeValue(kTTSym_address, mAddress.appendAttribute(kTTSym_dataspaceUnit));

	mDataspaceUnitObserver->sendMessage(kTTSym_Get);

	return kTTErrNone;
}

TTErr TTViewer::setActive(const TTValue& value)
{
	mActive = value;

	if (mReceiver)
		mReceiver->setAttributeValue(kTTSym_active, mActive);

    if (mActive)
        refresh();

	return kTTErrNone;
}

TTErr TTViewer::setFreeze(const TTValue& value)
{
	mFreeze = value;

    // update the value if the Viewer is unfreezed
    if (!mFreeze)
        refresh();

	return kTTErrNone;
}

TTErr TTViewer::setReturnedValue(const TTValue& value)
{
	TTAttributePtr	anAttribute = NULL;
	TTErr			err;

	mReturnedValue = value;

	err = this->findAttribute(kTTSym_returnedValue, &anAttribute);

	if (!err)
		anAttribute->sendNotification(kTTSym_notify, mReturnedValue);	// we use kTTSym_notify because we know that observers are TTCallback

	return kTTErrNone;
}

TTErr TTViewer::Send(const TTValue& inputValue, TTValue& outputValue)
{
	if (mSender) {

		TTValue valueToSend = inputValue;

		// append view unit except for empty value
		if (valueToSend.size() > 0 && mDataspaceUnit != kTTSym_none)
			valueToSend.append(mDataspaceUnit);

		return mSender->sendMessage(kTTSym_Send, valueToSend, kTTValNONE);
	}

	return kTTErrGeneric;
}

TTErr TTViewer::setDataspaceUnit(const TTValue& value)
{
	TTValue n = value;				// use new value to protect the attribute
	mDataspaceUnit = value;

	if (mDataspaceConverter)
		mDataspaceConverter->setAttributeValue(TTSymbol("outputUnit"), mDataspaceUnit);

	// TODO : notifyObservers(kTTSym_dataspaceUnit, n);
	return kTTErrNone;
}

TTErr TTViewer::convertUnit(const TTValue& inputValue, TTValue& outputValue)
{
	if (mDataspaceConverter)
		return mDataspaceConverter->sendMessage(TTSymbol("convert"), inputValue, outputValue);

	return kTTErrNone;
}

#if 0
#pragma mark -
#pragma mark Some Methods
#endif

TTErr TTViewerReceiveAddressCallback(TTPtr baton, TTValue& data)
{
    TTViewerPtr aViewer;
	TTValuePtr	b;
	TTValue		converted;

	// unpack baton (a TTViewer)
	b = (TTValuePtr)baton;
	aViewer = TTViewerPtr((TTObjectBasePtr)(*b)[0]);

	if (aViewer->mDataspace == kTTSym_none) {

        // check if the data's dataspace
        if (aViewer->mDataspaceObserver) {
            aViewer->mDataspaceObserver->sendMessage(kTTSym_Get);

            // then check if the data's dataspace unit
            if (aViewer->mDataspaceUnitObserver)
                aViewer->mDataspaceUnitObserver->sendMessage(kTTSym_Get);
        }
    }

	return kTTErrNone;
}

TTErr TTViewerReceiveValueCallback(TTPtr baton, TTValue& data)
{
	TTViewerPtr aViewer;
	TTValuePtr	b;
	TTValue		converted;

	// unpack baton (a TTViewer)
	b = (TTValuePtr)baton;
	aViewer = TTViewerPtr((TTObjectBasePtr)(*b)[0]);

	if (aViewer->mActive) {

		if (!aViewer->mFreeze)
			// convert data
			aViewer->convertUnit(data, converted);

		else
			// use last data
			converted = aViewer->mReturnedValue;

		// return value
		if (aViewer->mReturnValueCallback) {
			aViewer->mReturnValueCallback->notify(converted, kTTValNONE);
			aViewer->setReturnedValue(converted);
		}
	}

	return kTTErrNone;
}

TTErr TTViewerDataspaceCallback(TTPtr baton, TTValue& data)
{
	TTViewerPtr aViewer;
	TTValuePtr	b;
	TTValue		v;
    TTSymbol    dataspace;

	// unpack baton (a TTViewer)
	b = (TTValuePtr)baton;
	aViewer = TTViewerPtr((TTObjectBasePtr)(*b)[0]);

    dataspace = data;

    // filter repetitions
    if (dataspace != aViewer->mDataspace) {

        aViewer->mDataspace = data;

        if (aViewer->mDataspaceConverter)
            aViewer->mDataspaceConverter->setAttributeValue(kTTSym_dataspace, aViewer->mDataspace);
    }

	return kTTErrNone;
}

TTErr TTViewerDataspaceUnitCallback(TTPtr baton, TTValue& data)
{
	TTViewerPtr aViewer;
	TTValuePtr	b;
	TTValue		v;
	TTErr		err;

	// unpack baton (a TTViewer)
	b = (TTValuePtr)baton;
	aViewer = TTViewerPtr((TTObjectBasePtr)(*b)[0]);

	if (aViewer->mDataspaceConverter) {

		// set input unit like the data unit
		aViewer->mDataspaceConverter->setAttributeValue(TTSymbol("inputUnit"), data);

		// if no unit : set the output unit like the data unit
		if (aViewer->mDataspaceUnit == kTTSym_none)
			aViewer->mDataspaceUnit = data;

		// if the unit is wrong : use the default unit
		err = aViewer->mDataspaceConverter->setAttributeValue(TTSymbol("outputUnit"), aViewer->mDataspaceUnit);
		if (err) {
			aViewer->mDataspaceConverter->getAttributeValue(TTSymbol("outputUnit"), v);
			aViewer->mDataspaceUnit = v[0];
			aViewer->mDataspaceConverter->setAttributeValue(TTSymbol("outputUnit"), aViewer->mDataspaceUnit);
		}
	}

	return kTTErrNone;
}
<commit_msg>minor<commit_after>/** @file
 *
 * @ingroup modularLibrary
 *
 * @brief A Viewer Object.
 *
 * @details
 *
 * @authors Théo de la Hogue
 *
 * @copyright © 2010, Théo de la Hogue @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTViewer.h"

#define thisTTClass			TTViewer
#define thisTTClassName		"Viewer"
#define thisTTClassTags		"viewer"

TT_MODULAR_CONSTRUCTOR,
mAddress(kTTAdrsEmpty),
mDescription(kTTSym_none),
mType(kTTSym_generic),
mTag(kTTSym_none),
mHighlight(NO),
mFreeze(NO),
mDataspace(kTTSym_none),
mDataspaceUnit(kTTSym_none),
mDataspaceConverter(NULL),
mDataspaceObserver(NULL),
mDataspaceUnitObserver(NULL),
mActive(YES),
mReturnedValue(kTTValNONE),
mReceiver(NULL),
mSender(NULL),
mReturnValueCallback(NULL)
{
	if(arguments.size() == 1)
		mReturnValueCallback = TTCallbackPtr((TTObjectBasePtr)arguments[0]);

	addAttributeWithSetter(Address, kTypeSymbol);
	addAttribute(Description, kTypeSymbol);
	addAttribute(Type, kTypeSymbol);
	addAttribute(Tag, kTypeSymbol);
	addAttribute(Highlight, kTypeBoolean);
	addAttributeWithSetter(Freeze, kTypeBoolean);

	addAttribute(Dataspace, kTypeSymbol);
	addAttributeProperty(Dataspace, readOnly, YES);
	addAttributeWithSetter(DataspaceUnit, kTypeSymbol);

	addAttributeWithSetter(Active, kTypeBoolean);

	addAttributeWithSetter(ReturnedValue, kTypeLocalValue);
	addAttributeProperty(ReturnedValue, readOnly, YES);
	addAttributeProperty(ReturnedValue, hidden, YES);

	addMessageWithArguments(Send);
	addMessageProperty(Send, hidden, YES);

	TTObjectBaseInstantiate(TTSymbol("dataspace"),  &mDataspaceConverter, kTTValNONE);
}

TTViewer::~TTViewer() // TODO : delete things...
{
	if (mReturnValueCallback) {
		delete (TTValuePtr)mReturnValueCallback->getBaton();
		TTObjectBaseRelease(TTObjectBaseHandle(&mReturnValueCallback));
	}

	if (mDataspaceConverter)
		TTObjectBaseRelease(TTObjectBaseHandle(&mDataspaceConverter));

	if (mDataspaceObserver)
		TTObjectBaseRelease(TTObjectBaseHandle(&mDataspaceObserver));

	if (mDataspaceUnitObserver)
		TTObjectBaseRelease(TTObjectBaseHandle(&mDataspaceUnitObserver));

	if (mSender)
		TTObjectBaseRelease(TTObjectBaseHandle(&mSender));

	if (mReceiver)
		TTObjectBaseRelease(TTObjectBaseHandle(&mReceiver));
}

TTErr TTViewer::setAddress(const TTValue& value)
{
	mAddress = value[0];

	bind();

    refresh();

	return kTTErrNone;
}

TTErr TTViewer::bind()
{
	TTValue			args, v;
	TTObjectBasePtr	returnAddressCallback, returnValueCallback;
	TTValuePtr		returnAddressBaton, returnValueBaton;

	// Prepare arguments
	if (mAddress == kTTAdrsEmpty)
		return kTTErrGeneric;

	// The default attribute to bind is value
	if (mAddress.getAttribute() == NO_ATTRIBUTE)
		mAddress.appendAttribute(kTTSym_value);

	// Replace a TTSender object
	if (mSender)
		TTObjectBaseRelease(TTObjectBaseHandle(&mSender));

	mSender = NULL;							// without this, TTObjectBaseInstantiate try to release an oldObject that doesn't exist ... Is it good ?
	TTObjectBaseInstantiate(kTTSym_Sender, TTObjectBaseHandle(&mSender), kTTValNONE);

	mSender->setAttributeValue(kTTSym_address, mAddress);

	// Replace a TTReceiver object
	if (mReceiver)
		TTObjectBaseRelease(TTObjectBaseHandle(&mReceiver));

	returnAddressCallback = NULL;			// without this, TTObjectBaseInstantiate try to release an oldObject that doesn't exist ... Is it good ?
	TTObjectBaseInstantiate(TTSymbol("callback"), &returnAddressCallback, kTTValNONE);
	returnAddressBaton = new TTValue(TTObjectBasePtr(this));
	returnAddressCallback->setAttributeValue(kTTSym_baton, TTPtr(returnAddressBaton));
	returnAddressCallback->setAttributeValue(kTTSym_function, TTPtr(&TTViewerReceiveAddressCallback));
	args.append(returnAddressCallback);

	returnValueCallback = NULL;				// without this, TTObjectBaseInstantiate try to release an oldObject that doesn't exist ... Is it good ?
	TTObjectBaseInstantiate(TTSymbol("callback"), &returnValueCallback, kTTValNONE);
	returnValueBaton = new TTValue(TTObjectBasePtr(this));
	returnValueCallback->setAttributeValue(kTTSym_baton, TTPtr(returnValueBaton));
	returnValueCallback->setAttributeValue(kTTSym_function, TTPtr(&TTViewerReceiveValueCallback));
	args.append(returnValueCallback);

	mReceiver = NULL;						// without this, TTObjectBaseInstantiate try to release an oldObject that doesn't exist ... Is it good ?
	TTObjectBaseInstantiate(kTTSym_Receiver, TTObjectBaseHandle(&mReceiver), args);

	mReceiver->setAttributeValue(kTTSym_address, mAddress);

	observeDataspace();
	observeDataspaceUnit();

	return kTTErrNone;
}

TTErr TTViewer::refresh()
{
	if (mReceiver)
		return mReceiver->sendMessage(kTTSym_Get);

	return kTTErrGeneric;
}

TTErr TTViewer::observeDataspace()
{
	TTValue			args;
	TTObjectBasePtr	returnDataspaceCallback;
	TTValuePtr		returnDataspaceBaton;

	if (mDataspaceObserver)
		TTObjectBaseRelease(TTObjectBaseHandle(&mDataspaceObserver));

	args.append(NULL);

	returnDataspaceCallback = NULL;				// without this, TTObjectBaseInstantiate try to release an oldObject that doesn't exist ... Is it good ?
	TTObjectBaseInstantiate(TTSymbol("callback"), &returnDataspaceCallback, kTTValNONE);
	returnDataspaceBaton = new TTValue(TTObjectBasePtr(this));
	returnDataspaceCallback->setAttributeValue(kTTSym_baton, TTPtr(returnDataspaceBaton));
	returnDataspaceCallback->setAttributeValue(kTTSym_function, TTPtr(&TTViewerDataspaceCallback));
	args.append(returnDataspaceCallback);

	mDataspaceObserver = NULL;
	TTObjectBaseInstantiate(kTTSym_Receiver, TTObjectBaseHandle(&mDataspaceObserver), args);

	mDataspaceObserver->setAttributeValue(kTTSym_address, mAddress.appendAttribute(kTTSym_dataspace));

	mDataspaceObserver->sendMessage(kTTSym_Get);

	return kTTErrNone;
}

TTErr TTViewer::observeDataspaceUnit()
{
	TTValue			args;
	TTObjectBasePtr		returnDataspaceUnitCallback;
	TTValuePtr		returnDataspaceUnitBaton;

	if (mDataspaceUnitObserver)
		TTObjectBaseRelease(TTObjectBaseHandle(&mDataspaceUnitObserver));

	// Make a TTReceiver object
	args.append(NULL);

	returnDataspaceUnitCallback = NULL;				// without this, TTObjectBaseInstantiate try to release an oldObject that doesn't exist ... Is it good ?
	TTObjectBaseInstantiate(TTSymbol("callback"), &returnDataspaceUnitCallback, kTTValNONE);
	returnDataspaceUnitBaton = new TTValue(TTObjectBasePtr(this));
	returnDataspaceUnitCallback->setAttributeValue(kTTSym_baton, TTPtr(returnDataspaceUnitBaton));
	returnDataspaceUnitCallback->setAttributeValue(kTTSym_function, TTPtr(&TTViewerDataspaceUnitCallback));
	args.append(returnDataspaceUnitCallback);

	mDataspaceUnitObserver = NULL;
	TTObjectBaseInstantiate(kTTSym_Receiver, TTObjectBaseHandle(&mDataspaceUnitObserver), args);

	mDataspaceUnitObserver->setAttributeValue(kTTSym_address, mAddress.appendAttribute(kTTSym_dataspaceUnit));

	mDataspaceUnitObserver->sendMessage(kTTSym_Get);

	return kTTErrNone;
}

TTErr TTViewer::setActive(const TTValue& value)
{
	mActive = value;

	if (mReceiver)
		mReceiver->setAttributeValue(kTTSym_active, mActive);

    if (mActive)
        refresh();

	return kTTErrNone;
}

TTErr TTViewer::setFreeze(const TTValue& value)
{
	mFreeze = value;

    // update the value if the Viewer is unfreezed
    if (!mFreeze)
        refresh();

	return kTTErrNone;
}

TTErr TTViewer::setReturnedValue(const TTValue& value)
{
	TTAttributePtr	anAttribute = NULL;
	TTErr			err;

	mReturnedValue = value;

	err = this->findAttribute(kTTSym_returnedValue, &anAttribute);

	if (!err)
		anAttribute->sendNotification(kTTSym_notify, mReturnedValue);	// we use kTTSym_notify because we know that observers are TTCallback

	return kTTErrNone;
}

TTErr TTViewer::Send(const TTValue& inputValue, TTValue& outputValue)
{
	if (mSender) {

		TTValue valueToSend = inputValue;

		// append view unit except for empty value
		if (valueToSend.size() > 0 && mDataspaceUnit != kTTSym_none)
			valueToSend.append(mDataspaceUnit);

		return mSender->sendMessage(kTTSym_Send, valueToSend, kTTValNONE);
	}

	return kTTErrGeneric;
}

TTErr TTViewer::setDataspaceUnit(const TTValue& value)
{
	TTValue n = value;				// use new value to protect the attribute
	mDataspaceUnit = value;

	if (mDataspaceConverter)
		mDataspaceConverter->setAttributeValue(TTSymbol("outputUnit"), mDataspaceUnit);

	// TODO : notifyObservers(kTTSym_dataspaceUnit, n);
	return kTTErrNone;
}

TTErr TTViewer::convertUnit(const TTValue& inputValue, TTValue& outputValue)
{
	if (mDataspaceConverter)
		return mDataspaceConverter->sendMessage(TTSymbol("convert"), inputValue, outputValue);

	return kTTErrNone;
}

#if 0
#pragma mark -
#pragma mark Some Methods
#endif

TTErr TTViewerReceiveAddressCallback(TTPtr baton, TTValue& data)
{
    TTViewerPtr aViewer;
	TTValuePtr	b;
	TTValue		converted;

	// unpack baton (a TTViewer)
	b = (TTValuePtr)baton;
	aViewer = TTViewerPtr((TTObjectBasePtr)(*b)[0]);

	if (aViewer->mDataspace == kTTSym_none) {

        // check if the data's dataspace
        if (aViewer->mDataspaceObserver) {
            aViewer->mDataspaceObserver->sendMessage(kTTSym_Get);

            // then check if the data's dataspace unit
            if (aViewer->mDataspaceUnitObserver)
                aViewer->mDataspaceUnitObserver->sendMessage(kTTSym_Get);
        }
    }

	return kTTErrNone;
}

TTErr TTViewerReceiveValueCallback(TTPtr baton, TTValue& data)
{
	TTViewerPtr aViewer;
	TTValuePtr	b;
	TTValue		converted;

	// unpack baton (a TTViewer)
	b = (TTValuePtr)baton;
	aViewer = TTViewerPtr((TTObjectBasePtr)(*b)[0]);

	if (aViewer->mActive) {

		if (!aViewer->mFreeze)
			// convert data
			aViewer->convertUnit(data, converted);

		else
			// use last data
			converted = aViewer->mReturnedValue;

		// return value
		if (aViewer->mReturnValueCallback) {
			aViewer->mReturnValueCallback->notify(converted, kTTValNONE);
			aViewer->setReturnedValue(converted);
		}
	}

	return kTTErrNone;
}

TTErr TTViewerDataspaceCallback(TTPtr baton, TTValue& data)
{
	TTViewerPtr aViewer;
	TTValuePtr	b;
	TTValue		v;
    TTSymbol    dataspace;

	// unpack baton (a TTViewer)
	b = (TTValuePtr)baton;
	aViewer = TTViewerPtr((TTObjectBasePtr)(*b)[0]);

    dataspace = data;

    // filter repetitions
    if (dataspace != aViewer->mDataspace) {

        aViewer->mDataspace = data;

        if (aViewer->mDataspaceConverter)
            aViewer->mDataspaceConverter->setAttributeValue(kTTSym_dataspace, aViewer->mDataspace);
    }

	return kTTErrNone;
}

TTErr TTViewerDataspaceUnitCallback(TTPtr baton, TTValue& data)
{
	TTViewerPtr aViewer;
	TTValuePtr	b;
	TTValue		v;
	TTErr		err;

	// unpack baton (a TTViewer)
	b = (TTValuePtr)baton;
	aViewer = TTViewerPtr((TTObjectBasePtr)(*b)[0]);

	if (aViewer->mDataspaceConverter) {

		// set input unit like the data unit
		aViewer->mDataspaceConverter->setAttributeValue(TTSymbol("inputUnit"), data);

		// if no unit : set the output unit like the data unit
		if (aViewer->mDataspaceUnit == kTTSym_none)
			aViewer->mDataspaceUnit = data;

		// if the unit is wrong : use the default unit
		err = aViewer->mDataspaceConverter->setAttributeValue(TTSymbol("outputUnit"), aViewer->mDataspaceUnit);
		if (err) {
			aViewer->mDataspaceConverter->getAttributeValue(TTSymbol("outputUnit"), v);
			aViewer->mDataspaceUnit = v[0];
			aViewer->mDataspaceConverter->setAttributeValue(TTSymbol("outputUnit"), aViewer->mDataspaceUnit);
		}
	}

	return kTTErrNone;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: dbustrings.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $ $Date: 2004-03-19 12:10:22 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the License); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include "dbustrings.hrc"

namespace dbaui
{

#include "stringconstants.cxx"

    //============================================================
    //= URLs
    //============================================================
    IMPLEMENT_CONSTASCII_USTRING(URL_COMPONENT_QUERYDESIGN, ".component:DB/QueryDesign");
    IMPLEMENT_CONSTASCII_USTRING(URL_COMPONENT_TABLEDESIGN, ".component:DB/TableDesign");
    IMPLEMENT_CONSTASCII_USTRING(URL_COMPONENT_RELATIONDESIGN, ".component:DB/RelationDesign");

    //============================================================
    //= other
    //============================================================
    IMPLEMENT_CONSTASCII_USTRING(FRAME_NAME_QUERY_PREVIEW,          "QueryPreview");
    IMPLEMENT_CONSTASCII_USTRING(PROPERTY_ENABLESQL92CHECK,         "EnableSQL92Check");
    IMPLEMENT_CONSTASCII_USTRING(PROPERTY_ENABLETABLEALIAS,         "AppendTableAlias");
    IMPLEMENT_CONSTASCII_USTRING( PARAM_INDEPENDENT_SQL_COMMAND,    "IndependentSQLCommand");

    //============================================================
    //= properties
    //============================================================
    IMPLEMENT_CONSTASCII_USTRING(PROPERTY_TRISTATE, "TriState");

}
<commit_msg>INTEGRATION: CWS qwizards1 (1.6.42); FILE MERGED 2004/01/14 09:16:07 oj 1.6.42.1: #i24380# new services for column descriptor control and model<commit_after>/*************************************************************************
 *
 *  $RCSfile: dbustrings.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: kz $ $Date: 2004-05-19 16:54:43 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the License); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include "dbustrings.hrc"

namespace dbaui
{

#include "stringconstants.cxx"

    //============================================================
    //= URLs
    //============================================================
    IMPLEMENT_CONSTASCII_USTRING(URL_COMPONENT_QUERYDESIGN, ".component:DB/QueryDesign");
    IMPLEMENT_CONSTASCII_USTRING(URL_COMPONENT_TABLEDESIGN, ".component:DB/TableDesign");
    IMPLEMENT_CONSTASCII_USTRING(URL_COMPONENT_RELATIONDESIGN, ".component:DB/RelationDesign");

    //============================================================
    //= other
    //============================================================
    IMPLEMENT_CONSTASCII_USTRING(FRAME_NAME_QUERY_PREVIEW,          "QueryPreview");
    IMPLEMENT_CONSTASCII_USTRING(PROPERTY_ENABLESQL92CHECK,         "EnableSQL92Check");
    IMPLEMENT_CONSTASCII_USTRING(PROPERTY_ENABLETABLEALIAS,         "AppendTableAlias");
    IMPLEMENT_CONSTASCII_USTRING( PARAM_INDEPENDENT_SQL_COMMAND,    "IndependentSQLCommand");
    IMPLEMENT_CONSTASCII_USTRING(SERVICE_CONTROLDEFAULT,        "com.sun.star.comp.dbu.OColumnControl");

    //============================================================
    //= properties
    //============================================================
    IMPLEMENT_CONSTASCII_USTRING(PROPERTY_TRISTATE, "TriState");

    IMPLEMENT_CONSTASCII_USTRING(PROPERTY_TABSTOP, "TabStop");
    IMPLEMENT_CONSTASCII_USTRING(PROPERTY_DEFAULTCONTROL, "DefaultControl");
    IMPLEMENT_CONSTASCII_USTRING(PROPERTY_ENABLED, "Enabled");
    IMPLEMENT_CONSTASCII_USTRING(PROPERTY_COLUMN, "Column");
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sqlmessage.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: kz $ $Date: 2007-05-10 10:33:38 $
 *
 *  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 _DBAUI_SQLMESSAGE_HXX_
#define _DBAUI_SQLMESSAGE_HXX_

#ifndef _BUTTON_HXX
#include <vcl/button.hxx>
#endif
#ifndef _FIXED_HXX
#include <vcl/fixed.hxx>
#endif
#ifndef _SV_BTNDLG_HXX
#include <vcl/btndlg.hxx>
#endif

#ifndef _DBHELPER_DBEXCEPTION_HXX_
#include <connectivity/dbexception.hxx>
#endif

#include <memory>

// some forwards
namespace com { namespace sun { namespace star {
    namespace sdb {
        class SQLContext;
    }
    namespace sdbc {
        class SQLException;
    }
} } }

//.........................................................................
namespace dbaui
{
//.........................................................................

//==================================================================
// OSQLMessageBox
//==================================================================
struct SQLMessageBox_Impl;
class OSQLMessageBox : public ButtonDialog
{
    FixedImage      m_aInfoImage;
    FixedText       m_aTitle;
    FixedText       m_aMessage;

    ::std::auto_ptr< SQLMessageBox_Impl >   m_pImpl;

public:
    enum MessageType
    {
        Info,
        Error,
        Warning,
        Query,

        AUTO
    };

public:
    /** display an SQLException with auto-recognizing a main and a detailed message

        The first two messages from the exception chain are used as main and detailed message (recognizing the
        detailed field of an <type scope="com::sun::star::sdb">SQLContext</type>).

        If only one message is present, a default title ("error reading ...") is used
    */
    OSQLMessageBox(Window* _pParent,
                const ::com::sun::star::sdbc::SQLException& _rError,
                WinBits _nStyle = WB_OK | WB_DEF_OK,
                MessageType _eImage = Error);

    /** display an SQLException with auto-recognizing a main and a detailed message

        The first two messages from the exception chain are used as main and detailed message (recognizing the
        detailed field of an <type scope="com::sun::star::sdb">SQLContext</type>).

        If only one message is present, a default title ("error reading ...") is used
    */
    OSQLMessageBox(Window* _pParent,
                const dbtools::SQLExceptionInfo& _rException,
                WinBits _nStyle = WB_OK | WB_DEF_OK,
                MessageType _eImage = AUTO);

    /** display a database related error message

        @param  rTitle      the title to display
        @param  rMessage    the detailed message to display
        @param  eImage      determines the image to use. AUTO is disallowed in this constructor version
    */
    OSQLMessageBox(Window* pParent,
                const UniString& rTitle,
                const UniString& rMessage,
                WinBits nStyle = WB_OK | WB_DEF_OK,
                MessageType eImage = Info,
                const ::dbtools::SQLExceptionInfo* _pAdditionalErrorInfo = NULL );

    ~OSQLMessageBox();

private:
    void Construct( WinBits nStyle, MessageType eImage );

    DECL_LINK(ButtonClickHdl, Button* );

private:
    void    impl_positionControls();
    void    impl_initImage( MessageType _eImage );
    void    impl_createStandardButtons( WinBits _nStyle );
    void    impl_addDetailsButton();
};

//.........................................................................
}   // namespace dbaui
//.........................................................................

#endif // _DBAUI_SQLMESSAGE_HXX_

<commit_msg>INTEGRATION: CWS odbmacros2 (1.6.116); FILE MERGED 2007/12/06 13:33:47 fs 1.6.116.1: during #i49133#: support a HelpURL property<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sqlmessage.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2008-03-06 18:26:21 $
 *
 *  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 _DBAUI_SQLMESSAGE_HXX_
#define _DBAUI_SQLMESSAGE_HXX_

#ifndef _BUTTON_HXX
#include <vcl/button.hxx>
#endif
#ifndef _FIXED_HXX
#include <vcl/fixed.hxx>
#endif
#ifndef _SV_BTNDLG_HXX
#include <vcl/btndlg.hxx>
#endif

#ifndef _DBHELPER_DBEXCEPTION_HXX_
#include <connectivity/dbexception.hxx>
#endif

#include <memory>

// some forwards
namespace com { namespace sun { namespace star {
    namespace sdb {
        class SQLContext;
    }
    namespace sdbc {
        class SQLException;
    }
} } }

//.........................................................................
namespace dbaui
{
//.........................................................................

//==================================================================
// OSQLMessageBox
//==================================================================
struct SQLMessageBox_Impl;
class OSQLMessageBox : public ButtonDialog
{
    FixedImage      m_aInfoImage;
    FixedText       m_aTitle;
    FixedText       m_aMessage;
    ::rtl::OUString m_sHelpURL;

    ::std::auto_ptr< SQLMessageBox_Impl >   m_pImpl;

public:
    enum MessageType
    {
        Info,
        Error,
        Warning,
        Query,

        AUTO
    };

public:
    /** display an SQLException with auto-recognizing a main and a detailed message

        The first two messages from the exception chain are used as main and detailed message (recognizing the
        detailed field of an <type scope="com::sun::star::sdb">SQLContext</type>).
    */
    OSQLMessageBox(
        Window* _pParent,
        const dbtools::SQLExceptionInfo& _rException,
        WinBits _nStyle = WB_OK | WB_DEF_OK,
        const ::rtl::OUString& _rHelpURL = ::rtl::OUString()
    );

    /** display a database related error message

        @param  rTitle      the title to display
        @param  rMessage    the detailed message to display
        @param  _eType      determines the image to use. AUTO is disallowed in this constructor version
    */
    OSQLMessageBox(Window* pParent,
                const UniString& rTitle,
                const UniString& rMessage,
                WinBits nStyle = WB_OK | WB_DEF_OK,
                MessageType _eType = Info,
                const ::dbtools::SQLExceptionInfo* _pAdditionalErrorInfo = NULL );

    ~OSQLMessageBox();

private:
    void Construct( WinBits nStyle, MessageType eImage );

    DECL_LINK(ButtonClickHdl, Button* );

private:
    void    impl_positionControls();
    void    impl_initImage( MessageType _eImage );
    void    impl_createStandardButtons( WinBits _nStyle );
    void    impl_addDetailsButton();
};

//.........................................................................
}   // namespace dbaui
//.........................................................................

#endif // _DBAUI_SQLMESSAGE_HXX_

<|endoftext|>


<commit_before>///
/// @file  Li.cpp
///
/// Copyright (C) 2013 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount.hpp>

#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <limits>

using namespace std;

namespace {

/// Calculate the logarithmic integral using Ramanujan's fast
/// converging formula (accurate up to 10^17).
/// @see http://mathworld.wolfram.com/LogarithmicIntegral.html (15)
///
long double li(long double x)
{
  long double GAMMA = 0.57721566490153286061;
  long double logx = log(x);
  long double sum = 0;
  long double inner_sum = 0;
  long double factorial = 1;
  long double p = -1;
  long double power2 = 1;

  int k = 0;
  int terms = static_cast<int>(logx * 2) + 10;

  for (int n = 1; n < terms; n++)
  {
    factorial *= n;
    p *= -logx;
    long double q = factorial * power2;
    power2 *= 2;
    for (; k <= (n - 1) / 2; k++)
      inner_sum += 1.0 / (2 * k + 1);
    sum += (p / q) * inner_sum;
  }

  return GAMMA + log(logx) + sqrt(x) * sum;
}

} // namespace

namespace primecount {

/// Calculate the offset logarithmic integral which is a very
/// accurate approximation of the number of primes below x.
/// @post Li(x) > pi(x) for 24 <= x <= ~ 10^316
///
int64_t Li(int64_t x)
{
  if (x < 2)
    return 0;

  long double n = static_cast<long double>(x);
  return static_cast<int64_t>(
      li(n) - /* li(2) = */ 1.04516);
}

/// Calculate the inverse logarithmic integral Li^-1(x) which is a
/// very accurate approximation of the nth prime.
/// @post Li_inverse(x) < nth_prime(x) for 7 <= x <= ~ 10^316
///
int64_t Li_inverse(int64_t x)
{
  if (x < 1)
    return 0;

  double n = static_cast<double>(x);
  double logn = log(n);
  int64_t first = static_cast<int64_t>(n * logn);
  int64_t last  = static_cast<int64_t>(n * logn * 2 + 2);
  if (last <= first)
    last = std::numeric_limits<int64_t>::max();

  // find Li^-1(x) using binary search
  while (first < last)
  {
    int64_t mid = first + (last - first) / 2;

    if (Li(mid) < x)
      first = mid + 1;
    else
      last = mid;
  }

  return first;
}

} // namespace primecount
<commit_msg>Comment<commit_after>///
/// @file  Li.cpp
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount.hpp>

#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <limits>

using namespace std;

namespace {

/// Calculate the logarithmic integral using Ramanujan's fast
/// converging formula (accurate up to 10^17).
/// @see http://mathworld.wolfram.com/LogarithmicIntegral.html (15)
///
long double li(long double x)
{
  long double GAMMA = 0.57721566490153286061;
  long double logx = log(x);
  long double sum = 0;
  long double inner_sum = 0;
  long double factorial = 1;
  long double p = -1;
  long double power2 = 1;

  int k = 0;
  int terms = static_cast<int>(logx * 2) + 10;

  for (int n = 1; n < terms; n++)
  {
    factorial *= n;
    p *= -logx;
    long double q = factorial * power2;
    power2 *= 2;
    for (; k <= (n - 1) / 2; k++)
      inner_sum += 1.0 / (2 * k + 1);
    sum += (p / q) * inner_sum;
  }

  return GAMMA + log(logx) + sqrt(x) * sum;
}

} // namespace

namespace primecount {

/// Calculate the offset logarithmic integral which is a very
/// accurate approximation of the number of primes below x.
/// @post Li(x) > pi(x) for 24 <= x <= ~ 10^316
///
int64_t Li(int64_t x)
{
  if (x < 2)
    return 0;

  long double n = static_cast<long double>(x);
  return static_cast<int64_t>(
      li(n) - /* li(2) = */ 1.04516);
}

/// Calculate the inverse logarithmic integral Li^-1(x) which is a
/// very accurate approximation of the nth prime.
/// @post Li_inverse(x) < nth_prime(x) for 7 <= x <= 10^316
///
int64_t Li_inverse(int64_t x)
{
  if (x < 1)
    return 0;

  double n = static_cast<double>(x);
  double logn = log(n);
  int64_t first = static_cast<int64_t>(n * logn);
  int64_t last  = static_cast<int64_t>(n * logn * 2 + 2);
  if (last <= first)
    last = std::numeric_limits<int64_t>::max();

  // find Li^-1(x) using binary search
  while (first < last)
  {
    int64_t mid = first + (last - first) / 2;

    if (Li(mid) < x)
      first = mid + 1;
    else
      last = mid;
  }

  return first;
}

} // namespace primecount
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

#include "QGC.h"
#include <qmath.h>
#include <float.h>

namespace QGC
{

quint64 groundTimeUsecs()
{
    return groundTimeMilliseconds() * 1000;
}

quint64 groundTimeMilliseconds()
{
    return static_cast<quint64>(QDateTime::currentMSecsSinceEpoch());
}

qreal groundTimeSeconds()
{
    return static_cast<qreal>(groundTimeMilliseconds()) / 1000.0f;
}

float limitAngleToPMPIf(float angle)
{
    if (angle > -20*M_PI && angle < 20*M_PI)
    {
        while (angle > ((float)M_PI+FLT_EPSILON))
        {
            angle -= 2.0f * (float)M_PI;
        }

        while (angle <= -((float)M_PI+FLT_EPSILON))
        {
            angle += 2.0f * (float)M_PI;
        }
    }
    else
    {
        // Approximate
        angle = fmodf(angle, (float)M_PI);
    }

    return angle;
}

double limitAngleToPMPId(double angle)
{
    if (angle > -20*M_PI && angle < 20*M_PI)
    {
        if (angle < -M_PI)
        {
            while (angle < -M_PI)
            {
                angle += M_PI;
            }
        }
        else if (angle > M_PI)
        {
            while (angle > M_PI)
            {
                angle -= M_PI;
            }
        }
    }
    else
    {
        // Approximate
        angle = fmod(angle, M_PI);
    }

    return angle;
}

static const quint32 crctab[] =
{
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};

quint32 crc32(const quint8 *src, unsigned len, unsigned state)
{
    for (unsigned i = 0; i < len; i++) {
        state = crctab[(state ^ src[i]) & 0xff] ^ (state >> 8);
    }
    return state;
}

}
<commit_msg>QGC: Solve problem with limitAngleToPMPId when angle is bigger than PI<commit_after>/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

#include "QGC.h"
#include <qmath.h>
#include <float.h>

namespace QGC
{

quint64 groundTimeUsecs()
{
    return groundTimeMilliseconds() * 1000;
}

quint64 groundTimeMilliseconds()
{
    return static_cast<quint64>(QDateTime::currentMSecsSinceEpoch());
}

qreal groundTimeSeconds()
{
    return static_cast<qreal>(groundTimeMilliseconds()) / 1000.0f;
}

float limitAngleToPMPIf(float angle)
{
    if (angle > -20*M_PI && angle < 20*M_PI)
    {
        while (angle > ((float)M_PI+FLT_EPSILON))
        {
            angle -= 2.0f * (float)M_PI;
        }

        while (angle <= -((float)M_PI+FLT_EPSILON))
        {
            angle += 2.0f * (float)M_PI;
        }
    }
    else
    {
        // Approximate
        angle = fmodf(angle, (float)M_PI);
    }

    return angle;
}

double limitAngleToPMPId(double angle)
{
    if (angle > -20*M_PI && angle < 20*M_PI)
    {
        if (angle < -M_PI)
        {
            while (angle < -M_PI)
            {
                angle += 2.0f * M_PI;
            }
        }
        else if (angle > M_PI)
        {
            while (angle > M_PI)
            {
                angle -= 2.0f * M_PI;
            }
        }
    }
    else
    {
        // Approximate
        angle = fmod(angle, M_PI);
    }

    return angle;
}

static const quint32 crctab[] =
{
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};

quint32 crc32(const quint8 *src, unsigned len, unsigned state)
{
    for (unsigned i = 0; i < len; i++) {
        state = crctab[(state ^ src[i]) & 0xff] ^ (state >> 8);
    }
    return state;
}

}
<|endoftext|>