<commit_before>/*
 * Part of tivars_lib_cpp
 * (C) 2015-2019 Adrien "Adriweb" Bertrand
 * https://github.com/adriweb/tivars_lib_cpp
 * License: MIT
 */

#include "TypeHandlers.h"
#include "../utils.h"
#include <unordered_map>
#include <iostream>
#include <iterator>
#include <regex>
#include <fstream>

namespace tivars
{
    namespace TH_Tokenized
    {
        std::unordered_map<uint, std::vector<std::string>> tokens_BytesToName;
        std::unordered_map<std::string, uint> tokens_NameToBytes;
        uchar lengthOfLongestTokenName;
        std::vector<uchar> firstByteOfTwoByteTokens;
        const uint16_t squishedASMTokens[] = { 0xBB6D, 0xEF69, 0xEF7B }; // 83+/84+, 84+CSE, CE
    }

    /* TODO: handle TI-Innovator Send( exception for in-strings tokenization (=> not shortest tokens) */
    data_t TH_Tokenized::makeDataFromString(const std::string& str, const options_t& options)
    {
        (void)options;
        data_t data;

        // two bytes reserved for the size. Filled later
        data.push_back(0); data.push_back(0);

        const uchar maxTokSearchLen = std::min((uchar)str.length(), lengthOfLongestTokenName);

        bool isWithinString = false;

        for (uint strCursorPos = 0; strCursorPos < str.length(); strCursorPos++)
        {
            const std::string currChar = str.substr(strCursorPos, 1);
            if (currChar == "\"")
            {
                isWithinString = !isWithinString;
            } else if (currChar == "\n" || currChar == "→")
            {
                isWithinString = false;
            }
            /* isWithinString => minimum token length, otherwise maximal munch */
            for (uint currentLength = isWithinString ? 1 : maxTokSearchLen;
                 isWithinString ? (currentLength <= maxTokSearchLen) : (currentLength > 0);
                 currentLength += (isWithinString ? 1 : -1))
            {
                std::string currentSubString = str.substr(strCursorPos, currentLength);
                if (tokens_NameToBytes.count(currentSubString))
                {
                    uint tokenValue = tokens_NameToBytes[currentSubString];
                    if (tokenValue > 0xFF)
                    {
                        data.push_back((uchar)(tokenValue >> 8));
                    }
                    data.push_back((uchar)(tokenValue & 0xFF));
                    strCursorPos += currentLength - 1;
                    break;
                }
            }
        }

        uint actualDataLen = (uint) (data.size() - 2);
        data[0] = (uchar)(actualDataLen & 0xFF);
        data[1] = (uchar)((actualDataLen >> 8) & 0xFF);
        return data;
    }

    std::string TH_Tokenized::makeStringFromData(const data_t& data, const options_t& options)
    {
        const size_t dataSize = data.size();
        if (dataSize < 2)
        {
            throw std::invalid_argument("Invalid data array. Needs to contain at least 2 bytes (size fields)");
        }

        uint langIdx = (uint)((has_option(options, "lang") && options.at("lang") == LANG_FR) ? LANG_FR : LANG_EN);

        const int howManyBytes = (data[0] & 0xFF) + ((data[1] & 0xFF) << 8);
        if (howManyBytes != (int)dataSize - 2)
        {
            std::cerr << "[Warning] Byte count (" << (dataSize - 2) << ") and size field (" << howManyBytes  << ") mismatch!";
        }

        if (howManyBytes >= 2 && dataSize >= 4)
        {
            const uint16_t twoFirstBytes = (uint16_t) ((data[3] & 0xFF) + ((data[2] & 0xFF) << 8));
            if (std::find(std::begin(squishedASMTokens), std::end(squishedASMTokens), twoFirstBytes) != std::end(squishedASMTokens))
            {
                return "[Error] This is a squished ASM program - cannnot preview it!";
            }
        }

        uint errCount = 0;
        std::string str;
        for (uint i = 2; i < (uint)dataSize; i++)
        {
            uint currentToken = data[i];
            uint nextToken = (i < dataSize-1) ? data[i+1] : (uint)-1;
            uint bytesKey = currentToken;
            if (is_in_vector(firstByteOfTwoByteTokens, (uchar)currentToken))
            {
                if (nextToken == (uint)-1)
                {
                    std::cerr << "[Warning] Encountered an unfinished two-byte token! Setting the second byte to 0x00";
                    nextToken = 0x00;
                }
                bytesKey = nextToken + (currentToken << 8);
                i++;
            }
            if (tokens_BytesToName.find(bytesKey) != tokens_BytesToName.end())
            {
                str += tokens_BytesToName[bytesKey][langIdx];
            } else {
                str += " [???] ";
                errCount++;
            }
        }

        if (errCount > 0)
        {
            std::cerr << "[Warning] " << errCount << " token(s) could not be detokenized (' [???] ' was used)!";
        }

        if (has_option(options, "prettify") && options.at("prettify") == 1)
        {
            str = std::regex_replace(str, std::regex(R"(\[?\|?([a-z]+)\]?)"), "$1");
        }

        if (has_option(options, "reindent") && options.at("reindent") == 1)
        {
            str = reindentCodeString(str);
        }

        return str;
    }

    std::string TH_Tokenized::reindentCodeString(const std::string& str_orig, const options_t& options)
    {
        int lang;
        if (has_option(options, "lang"))
        {
            lang = options.at("lang");
        } else if (str_orig.size() > 1 && str_orig[0] == '.' && (str_orig[1] == '.' || ::isalpha(str_orig[1]))) {
            lang = PRGMLANG_AXE;
        } else if (str_orig.substr(0, sizeof("\U0001D456") - 1) == "\U0001D456") {
            lang = PRGMLANG_ICE;
        } else {
            lang = PRGMLANG_BASIC;
        }

        std::string str(str_orig);

        str = std::regex_replace(str, std::regex("([^\\s])(Del|Eff)Var "), "$1\n$2Var ");

        std::vector<std::string> lines_tmp = explode(str, '\n');

        // Inplace-replace the appropriate ":" by new-line chars (ie, by inserting the split string in the lines_tmp array)
        for (uint16_t idx = 0; idx < (uint16_t)lines_tmp.size(); idx++)
        {
            const auto line = lines_tmp[idx];
            bool isWithinString = false;
            for (uint16_t strIdx = 0; strIdx < (uint16_t)line.size(); strIdx++)
            {
                const auto currChar = line.substr(strIdx, 1);
                if (currChar == ":" && !isWithinString)
                {
                    lines_tmp[idx] = line.substr(0, strIdx); // replace "old" line by lhs
                    lines_tmp.insert(lines_tmp.begin() + idx + 1, line.substr(strIdx + 1)); // inserting rhs
                    break;
                } else if (currChar == "\"") {
                    isWithinString = !isWithinString;
                } else if (currChar == "\n" || currChar == "→") {
                    isWithinString = false;
                }
            }
        }

        std::vector<std::pair<uint, std::string>> lines(lines_tmp.size()); // indent, text
        for (const auto& line : lines_tmp)
        {
            lines.emplace_back(0, line);
        }

        std::vector<std::string> increaseIndentAfter   = { "If", "For", "While", "Repeat" };
        std::vector<std::string> decreaseIndentOfToken = { "Then", "Else", "End", "ElseIf", "EndIf", "End!If" };
        std::vector<std::string> closingTokens         = { "End", "EndIf", "End!If" };
        uint nextIndent = 0;
        std::string oldFirstCommand, firstCommand;
        for (auto& line : lines)
        {
            oldFirstCommand = firstCommand;

            std::string trimmedLine = trim(line.second);
            if (trimmedLine.length() > 0) {
                char* trimmedLine_c = (char*) trimmedLine.c_str();
                firstCommand = strtok(trimmedLine_c, " ");
                firstCommand = trim(firstCommand);
                trimmedLine = std::string(trimmedLine_c);
                trimmedLine_c = (char*) trimmedLine.c_str();
                if (firstCommand == trimmedLine)
                {
                    firstCommand = strtok(trimmedLine_c, "(");
                    firstCommand = trim(firstCommand);
                }
            } else {
                firstCommand = "";
            }

            line.first = nextIndent;

            if (is_in_vector(increaseIndentAfter, firstCommand))
            {
                nextIndent++;
            }
            if (line.first > 0 && is_in_vector(decreaseIndentOfToken, firstCommand))
            {
                line.first--;
            }
            if (nextIndent > 0 && (is_in_vector(closingTokens, firstCommand) || (oldFirstCommand == "If" && firstCommand != "Then" && lang != PRGMLANG_AXE && lang != PRGMLANG_ICE)))
            {
                nextIndent--;
            }
        }

        str = "";
        for (const auto& line : lines)
        {
            str += str_repeat(" ", line.first * 3) + line.second + '\n';
        }

        return ltrim(rtrim(str, "\t\n\r\f\v"));
    }

    void TH_Tokenized::initTokens()
    {
        std::ifstream t("programs_tokens.csv");
        std::string csvFileStr((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());

        if (csvFileStr.length() > 0)
        {
            std::vector<std::vector<std::string>> lines;
            ParseCSV(csvFileStr, lines);

            for (const auto& tokenInfo : lines)
            {
                uint bytes;
                if (tokenInfo[6] == "2") // number of bytes for the token
                {
                    if (!is_in_vector(firstByteOfTwoByteTokens, hexdec(tokenInfo[7])))
                    {
                        firstByteOfTwoByteTokens.push_back(hexdec(tokenInfo[7]));
                    }
                    bytes = hexdec(tokenInfo[8]) + (hexdec(tokenInfo[7]) << 8);
                } else {
                    bytes = hexdec(tokenInfo[7]);
                }
                tokens_BytesToName[bytes] = { tokenInfo[4], tokenInfo[5] }; // EN, FR
                tokens_NameToBytes[tokenInfo[4]] = bytes; // EN
                tokens_NameToBytes[tokenInfo[5]] = bytes; // FR
                uchar maxLenName = (uchar) std::max(tokenInfo[4].length(), tokenInfo[5].length());
                if (maxLenName > lengthOfLongestTokenName)
                {
                    lengthOfLongestTokenName = maxLenName;
                }
            }
        } else {
            throw std::runtime_error("Could not open the tokens csv file");
        }
    }

}
<commit_msg>[TH_Tokenized::makeStringFromData] fromRawBytes option<commit_after>/*
 * Part of tivars_lib_cpp
 * (C) 2015-2019 Adrien "Adriweb" Bertrand
 * https://github.com/adriweb/tivars_lib_cpp
 * License: MIT
 */

#include "TypeHandlers.h"
#include "../utils.h"
#include <unordered_map>
#include <iostream>
#include <iterator>
#include <regex>
#include <fstream>

namespace tivars
{
    namespace TH_Tokenized
    {
        std::unordered_map<uint, std::vector<std::string>> tokens_BytesToName;
        std::unordered_map<std::string, uint> tokens_NameToBytes;
        uchar lengthOfLongestTokenName;
        std::vector<uchar> firstByteOfTwoByteTokens;
        const uint16_t squishedASMTokens[] = { 0xBB6D, 0xEF69, 0xEF7B }; // 83+/84+, 84+CSE, CE
    }

    /* TODO: handle TI-Innovator Send( exception for in-strings tokenization (=> not shortest tokens) */
    data_t TH_Tokenized::makeDataFromString(const std::string& str, const options_t& options)
    {
        (void)options;
        data_t data;

        // two bytes reserved for the size. Filled later
        data.push_back(0); data.push_back(0);

        const uchar maxTokSearchLen = std::min((uchar)str.length(), lengthOfLongestTokenName);

        bool isWithinString = false;

        for (uint strCursorPos = 0; strCursorPos < str.length(); strCursorPos++)
        {
            const std::string currChar = str.substr(strCursorPos, 1);
            if (currChar == "\"")
            {
                isWithinString = !isWithinString;
            } else if (currChar == "\n" || currChar == "→")
            {
                isWithinString = false;
            }
            /* isWithinString => minimum token length, otherwise maximal munch */
            for (uint currentLength = isWithinString ? 1 : maxTokSearchLen;
                 isWithinString ? (currentLength <= maxTokSearchLen) : (currentLength > 0);
                 currentLength += (isWithinString ? 1 : -1))
            {
                std::string currentSubString = str.substr(strCursorPos, currentLength);
                if (tokens_NameToBytes.count(currentSubString))
                {
                    uint tokenValue = tokens_NameToBytes[currentSubString];
                    if (tokenValue > 0xFF)
                    {
                        data.push_back((uchar)(tokenValue >> 8));
                    }
                    data.push_back((uchar)(tokenValue & 0xFF));
                    strCursorPos += currentLength - 1;
                    break;
                }
            }
        }

        uint actualDataLen = (uint) (data.size() - 2);
        data[0] = (uchar)(actualDataLen & 0xFF);
        data[1] = (uchar)((actualDataLen >> 8) & 0xFF);
        return data;
    }

    std::string TH_Tokenized::makeStringFromData(const data_t& data, const options_t& options)
    {
        const size_t dataSize = data.size();

        const bool fromRawBytes = has_option(options, "fromRawBytes") && options.at("fromRawBytes") == 1;
        if (!fromRawBytes && dataSize < 2)
        {
            throw std::invalid_argument("Invalid data array. Needs to contain at least 2 bytes (size fields)");
        }

        uint langIdx = (uint)((has_option(options, "lang") && options.at("lang") == LANG_FR) ? LANG_FR : LANG_EN);

        const int howManyBytes = fromRawBytes ? (int)data.size() : ((data[0] & 0xFF) + ((data[1] & 0xFF) << 8));
        if (!fromRawBytes)
        {
            if (howManyBytes != (int)dataSize - 2)
            {
                std::cerr << "[Warning] Byte count (" << (dataSize - 2) << ") and size field (" << howManyBytes  << ") mismatch!";
            }
        }

        if (!fromRawBytes && howManyBytes >= 2 && dataSize >= 4)
        {
            const uint16_t twoFirstBytes = (uint16_t) ((data[3] & 0xFF) + ((data[2] & 0xFF) << 8));
            if (std::find(std::begin(squishedASMTokens), std::end(squishedASMTokens), twoFirstBytes) != std::end(squishedASMTokens))
            {
                return "[Error] This is a squished ASM program - cannnot preview it!";
            }
        }

        uint errCount = 0;
        std::string str;
        for (uint i = fromRawBytes ? 0 : 2; i < (uint)dataSize; i++)
        {
            uint currentToken = data[i];
            uint nextToken = (i < dataSize-1) ? data[i+1] : (uint)-1;
            uint bytesKey = currentToken;
            if (is_in_vector(firstByteOfTwoByteTokens, (uchar)currentToken))
            {
                if (nextToken == (uint)-1)
                {
                    std::cerr << "[Warning] Encountered an unfinished two-byte token! Setting the second byte to 0x00";
                    nextToken = 0x00;
                }
                bytesKey = nextToken + (currentToken << 8);
                i++;
            }
            if (tokens_BytesToName.find(bytesKey) != tokens_BytesToName.end())
            {
                str += tokens_BytesToName[bytesKey][langIdx];
            } else {
                str += " [???] ";
                errCount++;
            }
        }

        if (errCount > 0)
        {
            std::cerr << "[Warning] " << errCount << " token(s) could not be detokenized (' [???] ' was used)!";
        }

        if (has_option(options, "prettify") && options.at("prettify") == 1)
        {
            str = std::regex_replace(str, std::regex(R"(\[?\|?([a-z]+)\]?)"), "$1");
        }

        if (has_option(options, "reindent") && options.at("reindent") == 1)
        {
            str = reindentCodeString(str);
        }

        return str;
    }

    std::string TH_Tokenized::reindentCodeString(const std::string& str_orig, const options_t& options)
    {
        int lang;
        if (has_option(options, "lang"))
        {
            lang = options.at("lang");
        } else if (str_orig.size() > 1 && str_orig[0] == '.' && (str_orig[1] == '.' || ::isalpha(str_orig[1]))) {
            lang = PRGMLANG_AXE;
        } else if (str_orig.substr(0, sizeof("\U0001D456") - 1) == "\U0001D456") {
            lang = PRGMLANG_ICE;
        } else {
            lang = PRGMLANG_BASIC;
        }

        std::string str(str_orig);

        str = std::regex_replace(str, std::regex("([^\\s])(Del|Eff)Var "), "$1\n$2Var ");

        std::vector<std::string> lines_tmp = explode(str, '\n');

        // Inplace-replace the appropriate ":" by new-line chars (ie, by inserting the split string in the lines_tmp array)
        for (uint16_t idx = 0; idx < (uint16_t)lines_tmp.size(); idx++)
        {
            const auto line = lines_tmp[idx];
            bool isWithinString = false;
            for (uint16_t strIdx = 0; strIdx < (uint16_t)line.size(); strIdx++)
            {
                const auto currChar = line.substr(strIdx, 1);
                if (currChar == ":" && !isWithinString)
                {
                    lines_tmp[idx] = line.substr(0, strIdx); // replace "old" line by lhs
                    lines_tmp.insert(lines_tmp.begin() + idx + 1, line.substr(strIdx + 1)); // inserting rhs
                    break;
                } else if (currChar == "\"") {
                    isWithinString = !isWithinString;
                } else if (currChar == "\n" || currChar == "→") {
                    isWithinString = false;
                }
            }
        }

        std::vector<std::pair<uint, std::string>> lines(lines_tmp.size()); // indent, text
        for (const auto& line : lines_tmp)
        {
            lines.emplace_back(0, line);
        }

        std::vector<std::string> increaseIndentAfter   = { "If", "For", "While", "Repeat" };
        std::vector<std::string> decreaseIndentOfToken = { "Then", "Else", "End", "ElseIf", "EndIf", "End!If" };
        std::vector<std::string> closingTokens         = { "End", "EndIf", "End!If" };
        uint nextIndent = 0;
        std::string oldFirstCommand, firstCommand;
        for (auto& line : lines)
        {
            oldFirstCommand = firstCommand;

            std::string trimmedLine = trim(line.second);
            if (trimmedLine.length() > 0) {
                char* trimmedLine_c = (char*) trimmedLine.c_str();
                firstCommand = strtok(trimmedLine_c, " ");
                firstCommand = trim(firstCommand);
                trimmedLine = std::string(trimmedLine_c);
                trimmedLine_c = (char*) trimmedLine.c_str();
                if (firstCommand == trimmedLine)
                {
                    firstCommand = strtok(trimmedLine_c, "(");
                    firstCommand = trim(firstCommand);
                }
            } else {
                firstCommand = "";
            }

            line.first = nextIndent;

            if (is_in_vector(increaseIndentAfter, firstCommand))
            {
                nextIndent++;
            }
            if (line.first > 0 && is_in_vector(decreaseIndentOfToken, firstCommand))
            {
                line.first--;
            }
            if (nextIndent > 0 && (is_in_vector(closingTokens, firstCommand) || (oldFirstCommand == "If" && firstCommand != "Then" && lang != PRGMLANG_AXE && lang != PRGMLANG_ICE)))
            {
                nextIndent--;
            }
        }

        str = "";
        for (const auto& line : lines)
        {
            str += str_repeat(" ", line.first * 3) + line.second + '\n';
        }

        return ltrim(rtrim(str, "\t\n\r\f\v"));
    }

    void TH_Tokenized::initTokens()
    {
        std::ifstream t("programs_tokens.csv");
        std::string csvFileStr((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());

        if (csvFileStr.length() > 0)
        {
            std::vector<std::vector<std::string>> lines;
            ParseCSV(csvFileStr, lines);

            for (const auto& tokenInfo : lines)
            {
                uint bytes;
                if (tokenInfo[6] == "2") // number of bytes for the token
                {
                    if (!is_in_vector(firstByteOfTwoByteTokens, hexdec(tokenInfo[7])))
                    {
                        firstByteOfTwoByteTokens.push_back(hexdec(tokenInfo[7]));
                    }
                    bytes = hexdec(tokenInfo[8]) + (hexdec(tokenInfo[7]) << 8);
                } else {
                    bytes = hexdec(tokenInfo[7]);
                }
                tokens_BytesToName[bytes] = { tokenInfo[4], tokenInfo[5] }; // EN, FR
                tokens_NameToBytes[tokenInfo[4]] = bytes; // EN
                tokens_NameToBytes[tokenInfo[5]] = bytes; // FR
                uchar maxLenName = (uchar) std::max(tokenInfo[4].length(), tokenInfo[5].length());
                if (maxLenName > lengthOfLongestTokenName)
                {
                    lengthOfLongestTokenName = maxLenName;
                }
            }
        } else {
            throw std::runtime_error("Could not open the tokens csv file");
        }
    }

}
<|endoftext|>


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

#include <sstream>

#include "transport_manager/transport_adapter/transport_adapter_impl.h"
#include "transport_manager/usb/usb_device_scanner.h"
#include "transport_manager/usb/usb_device.h"
#include "transport_manager/usb/common.h"

#include "utils/logger.h"

namespace transport_manager {
namespace transport_adapter {

CREATE_LOGGERPTR_GLOBAL(logger_, "UsbDeviceScanner")

class AoaInitSequence : public UsbControlTransferSequence {
 public:
  AoaInitSequence();
  virtual ~AoaInitSequence() {
  }

 private:
  class AoaGetProtocolRequest;
  class AoaSendIdString;
  class AoaTurnIntoAccessoryMode;
};

void UsbDeviceScanner::OnDeviceArrived(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  if (IsAppleDevice(device)) {
    SupportedDeviceFound(device);
  } else {
    if (IsGoogleAccessory(device)) {
      SupportedDeviceFound(device);
    } else {
      TurnIntoAccessoryMode(device);
    }
  }
}

void UsbDeviceScanner::OnDeviceLeft(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  LOG4CXX_DEBUG(logger_, "PlatformUsbDevice " << device);
  bool list_changed = false;
  devices_mutex_.Acquire();
  for (Devices::iterator it = devices_.begin(); it != devices_.end(); ++it) {
    if (device == *it) {
      devices_.erase(it);
      list_changed = true;
      break;
    }
  }
  devices_mutex_.Release();
  if (list_changed) {
    UpdateList();
  }
}

UsbDeviceScanner::UsbDeviceScanner(TransportAdapterController* controller)
    : controller_(controller) {
}

UsbDeviceScanner::~UsbDeviceScanner() {
}

class AoaInitSequence::AoaGetProtocolRequest : public UsbControlInTransfer {
  virtual ~AoaGetProtocolRequest() {
  }
  virtual RequestType Type() const {
    return VENDOR;
  }
  virtual uint8_t Request() const {
    return 51;
  }
  virtual uint16_t Value() const {
    return 0;
  }
  virtual uint16_t Index() const {
    return 0;
  }
  virtual uint16_t Length() const {
    return 2;
  }
  virtual bool OnCompleted(unsigned char* data) const {
    const int protocol_version = data[1] << 8 | data[0];
    LOG4CXX_DEBUG(logger_, "AOA protocol version " << protocol_version);
    if (protocol_version == 0) {
      // AOA protocol not supported
      return false;
    }
    return true;
  }
};

class AoaInitSequence::AoaSendIdString : public UsbControlOutTransfer {
 public:
  AoaSendIdString(uint16_t index, const char* string, uint16_t length)
      : index_(index),
        string_(string),
        length_(length) {
  }

 private:
  virtual ~AoaSendIdString() {
  }
  virtual RequestType Type() const {
    return VENDOR;
  }
  virtual uint8_t Request() const {
    return 52;
  }
  virtual uint16_t Value() const {
    return 0;
  }
  virtual uint16_t Index() const {
    return index_;
  }
  virtual uint16_t Length() const {
    return length_;
  }
  virtual const char* Data() const {
    return string_;
  }
  uint16_t index_;
  const char* string_;
  uint16_t length_;
};

class AoaInitSequence::AoaTurnIntoAccessoryMode : public UsbControlOutTransfer {
  virtual ~AoaTurnIntoAccessoryMode() {
  }
  virtual RequestType Type() const {
    return VENDOR;
  }
  virtual uint8_t Request() const {
    return 53;
  }
  virtual uint16_t Value() const {
    return 0;
  }
  virtual uint16_t Index() const {
    return 0;
  }
  virtual uint16_t Length() const {
    return 0;
  }
  virtual const char* Data() const {
    return 0;
  }
};

static char manufacturer[] = "SDL";
static char model_name[] = "Core";
static char description[] = "SmartDeviceLink Core Component USB";
static char version[] = "1.0";
static char uri[] = "http://www.ford.com";
static char serial_num[] = "N000000";

AoaInitSequence::AoaInitSequence()
    : UsbControlTransferSequence() {
  AddTransfer(new AoaGetProtocolRequest);
  AddTransfer(new AoaSendIdString(0, manufacturer, sizeof(manufacturer)));
  AddTransfer(new AoaSendIdString(1, model_name, sizeof(model_name)));
  AddTransfer(new AoaSendIdString(2, description, sizeof(description)));
  AddTransfer(new AoaSendIdString(3, version, sizeof(version)));
  AddTransfer(new AoaSendIdString(4, uri, sizeof(uri)));
  AddTransfer(new AoaSendIdString(5, serial_num, sizeof(serial_num)));
  AddTransfer(new AoaTurnIntoAccessoryMode);
}

void UsbDeviceScanner::TurnIntoAccessoryMode(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  LOG4CXX_DEBUG(logger_, "PlatformUsbDevice: " << device);
  GetUsbHandler()->StartControlTransferSequence(new AoaInitSequence, device);
}

void UsbDeviceScanner::SupportedDeviceFound(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  LOG4CXX_TRACE(logger_, "PlatformUsbDevice: " << device);

  devices_mutex_.Acquire();
  devices_.push_back(device);
  devices_mutex_.Release();
  LOG4CXX_DEBUG(
      logger_,
      "USB device (bus number " << static_cast<int>(device->bus_number())
      << ", address " << static_cast<int>(device->address())
      << ") identified as: " << device->GetManufacturer()
      << ", " << device->GetProductName()
      << ", serial: " << device->GetSerialNumber());
  UpdateList();
}

TransportAdapter::Error UsbDeviceScanner::Init() {
  return TransportAdapter::OK;
}

TransportAdapter::Error UsbDeviceScanner::Scan() {
  return TransportAdapter::OK;
}

void UsbDeviceScanner::UpdateList() {
  LOG4CXX_AUTO_TRACE(logger_);
  DeviceVector device_vector;
  devices_mutex_.Acquire();
  for (Devices::const_iterator it = devices_.begin(); it != devices_.end();
      ++it) {
    const std::string device_name = (*it)->GetManufacturer() + " "
        + (*it)->GetProductName();
    std::ostringstream oss;
    oss << (*it)->GetManufacturer() << ":" << (*it)->GetProductName() << ":"
        << (*it)->GetSerialNumber();
    const DeviceUID device_uid = oss.str();
    DeviceSptr device(new UsbDevice(*it, device_name, device_uid));
    device_vector.push_back(device);
  }
  devices_mutex_.Release();

  LOG4CXX_DEBUG(logger_, "USB search done " << device_vector.size());
  controller_->SearchDeviceDone(device_vector);
}

void UsbDeviceScanner::Terminate() {
}

bool UsbDeviceScanner::IsInitialised() const {
  return true;
}

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

#include <sstream>

#include "transport_manager/transport_adapter/transport_adapter_impl.h"
#include "transport_manager/usb/usb_device_scanner.h"
#include "transport_manager/usb/usb_device.h"
#include "transport_manager/usb/common.h"

#include "utils/logger.h"

namespace transport_manager {
namespace transport_adapter {

CREATE_LOGGERPTR_GLOBAL(logger_, "UsbDeviceScanner")

class AoaInitSequence : public UsbControlTransferSequence {
 public:
  AoaInitSequence();
  virtual ~AoaInitSequence() {
  }

 private:
  class AoaGetProtocolRequest;
  class AoaSendIdString;
  class AoaTurnIntoAccessoryMode;
};

void UsbDeviceScanner::OnDeviceArrived(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  if (IsAppleDevice(device)) {
    SupportedDeviceFound(device);
  } else {
    if (IsGoogleAccessory(device)) {
      SupportedDeviceFound(device);
    } else {
      TurnIntoAccessoryMode(device);
    }
  }
}

void UsbDeviceScanner::OnDeviceLeft(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  LOG4CXX_DEBUG(logger_, "PlatformUsbDevice " << device);
  bool list_changed = false;
  devices_mutex_.Acquire();
  for (Devices::iterator it = devices_.begin(); it != devices_.end(); ++it) {
    if (device == *it) {
      devices_.erase(it);
      list_changed = true;
      break;
    }
  }
  devices_mutex_.Release();
  if (list_changed) {
    UpdateList();
  }
}

UsbDeviceScanner::UsbDeviceScanner(TransportAdapterController* controller)
    : controller_(controller) {
}

UsbDeviceScanner::~UsbDeviceScanner() {
}

class AoaInitSequence::AoaGetProtocolRequest : public UsbControlInTransfer {
  virtual ~AoaGetProtocolRequest() {
  }
  virtual RequestType Type() const {
    return VENDOR;
  }
  virtual uint8_t Request() const {
    return 51;
  }
  virtual uint16_t Value() const {
    return 0;
  }
  virtual uint16_t Index() const {
    return 0;
  }
  virtual uint16_t Length() const {
    return 2;
  }
  virtual bool OnCompleted(unsigned char* data) const {
    const int protocol_version = data[1] << 8 | data[0];
    LOG4CXX_DEBUG(logger_, "AOA protocol version " << protocol_version);
    if (protocol_version == 0) {
      // AOA protocol not supported
      return false;
    }
    return true;
  }
};

class AoaInitSequence::AoaSendIdString : public UsbControlOutTransfer {
 public:
  AoaSendIdString(uint16_t index, const char* string, uint16_t length)
      : index_(index),
        string_(string),
        length_(length) {
  }

 private:
  virtual ~AoaSendIdString() {
  }
  virtual RequestType Type() const {
    return VENDOR;
  }
  virtual uint8_t Request() const {
    return 52;
  }
  virtual uint16_t Value() const {
    return 0;
  }
  virtual uint16_t Index() const {
    return index_;
  }
  virtual uint16_t Length() const {
    return length_;
  }
  virtual const char* Data() const {
    return string_;
  }
  uint16_t index_;
  const char* string_;
  uint16_t length_;
};

class AoaInitSequence::AoaTurnIntoAccessoryMode : public UsbControlOutTransfer {
  virtual ~AoaTurnIntoAccessoryMode() {
  }
  virtual RequestType Type() const {
    return VENDOR;
  }
  virtual uint8_t Request() const {
    return 53;
  }
  virtual uint16_t Value() const {
    return 0;
  }
  virtual uint16_t Index() const {
    return 0;
  }
  virtual uint16_t Length() const {
    return 0;
  }
  virtual const char* Data() const {
    return 0;
  }
};

static char manufacturer[] = "SDL";
static char model_name[] = "Core";
static char description[] = "SmartDeviceLink Core Component USB";
static char version[] = "1.0";
static char uri[] = "http://www.smartdevicelink.org";
static char serial_num[] = "N000000";

AoaInitSequence::AoaInitSequence()
    : UsbControlTransferSequence() {
  AddTransfer(new AoaGetProtocolRequest);
  AddTransfer(new AoaSendIdString(0, manufacturer, sizeof(manufacturer)));
  AddTransfer(new AoaSendIdString(1, model_name, sizeof(model_name)));
  AddTransfer(new AoaSendIdString(2, description, sizeof(description)));
  AddTransfer(new AoaSendIdString(3, version, sizeof(version)));
  AddTransfer(new AoaSendIdString(4, uri, sizeof(uri)));
  AddTransfer(new AoaSendIdString(5, serial_num, sizeof(serial_num)));
  AddTransfer(new AoaTurnIntoAccessoryMode);
}

void UsbDeviceScanner::TurnIntoAccessoryMode(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  LOG4CXX_DEBUG(logger_, "PlatformUsbDevice: " << device);
  GetUsbHandler()->StartControlTransferSequence(new AoaInitSequence, device);
}

void UsbDeviceScanner::SupportedDeviceFound(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  LOG4CXX_TRACE(logger_, "PlatformUsbDevice: " << device);

  devices_mutex_.Acquire();
  devices_.push_back(device);
  devices_mutex_.Release();
  LOG4CXX_DEBUG(
      logger_,
      "USB device (bus number " << static_cast<int>(device->bus_number())
      << ", address " << static_cast<int>(device->address())
      << ") identified as: " << device->GetManufacturer()
      << ", " << device->GetProductName()
      << ", serial: " << device->GetSerialNumber());
  UpdateList();
}

TransportAdapter::Error UsbDeviceScanner::Init() {
  return TransportAdapter::OK;
}

TransportAdapter::Error UsbDeviceScanner::Scan() {
  return TransportAdapter::OK;
}

void UsbDeviceScanner::UpdateList() {
  LOG4CXX_AUTO_TRACE(logger_);
  DeviceVector device_vector;
  devices_mutex_.Acquire();
  for (Devices::const_iterator it = devices_.begin(); it != devices_.end();
      ++it) {
    const std::string device_name = (*it)->GetManufacturer() + " "
        + (*it)->GetProductName();
    std::ostringstream oss;
    oss << (*it)->GetManufacturer() << ":" << (*it)->GetProductName() << ":"
        << (*it)->GetSerialNumber();
    const DeviceUID device_uid = oss.str();
    DeviceSptr device(new UsbDevice(*it, device_name, device_uid));
    device_vector.push_back(device);
  }
  devices_mutex_.Release();

  LOG4CXX_DEBUG(logger_, "USB search done " << device_vector.size());
  controller_->SearchDeviceDone(device_vector);
}

void UsbDeviceScanner::Terminate() {
}

bool UsbDeviceScanner::IsInitialised() const {
  return true;
}

}  // namespace
}  // namespace
<|endoftext|>


<commit_before>#pragma once

#include "types.hpp"
#include <CoreGraphics/CoreGraphics.h>
#include <thread>
#include <vector>

namespace krbn {
namespace manipulator {
class modifier_flag_manager final {
public:
  modifier_flag_manager(void) {
    states_.resize(static_cast<size_t>(modifier_flag::end_));

    states_[static_cast<size_t>(modifier_flag::caps_lock)] = std::make_unique<state>("caps lock", "⇪");
    states_[static_cast<size_t>(modifier_flag::left_control)] = std::make_unique<state>("control", "⌃");
    states_[static_cast<size_t>(modifier_flag::left_shift)] = std::make_unique<state>("shift", "⇧");
    states_[static_cast<size_t>(modifier_flag::left_option)] = std::make_unique<state>("option", "⌥");
    states_[static_cast<size_t>(modifier_flag::left_command)] = std::make_unique<state>("command", "⌘");
    states_[static_cast<size_t>(modifier_flag::right_control)] = std::make_unique<state>("control", "⌃");
    states_[static_cast<size_t>(modifier_flag::right_shift)] = std::make_unique<state>("shift", "⇧");
    states_[static_cast<size_t>(modifier_flag::right_option)] = std::make_unique<state>("option", "⌥");
    states_[static_cast<size_t>(modifier_flag::right_command)] = std::make_unique<state>("command", "⌘");
    states_[static_cast<size_t>(modifier_flag::fn)] = std::make_unique<state>("fn", "fn");
  }

  void reset(void) {
    for (const auto& s : states_) {
      if (s) {
        s->reset();
      }
    }
  }

  void unlock(void) {
    for (const auto& s : states_) {
      if (s) {
        s->unlock();
      }
    }
  }

  enum class operation {
    increase,
    decrease,
    lock,
    unlock,
    toggle_lock,
  };

  void manipulate(modifier_flag k, operation operation) {
    auto i = static_cast<size_t>(k);
    if (states_[i]) {
      switch (operation) {
      case operation::increase:
        states_[i]->increase();
        break;
      case operation::decrease:
        states_[i]->decrease();
        break;
      case operation::lock:
        states_[i]->lock();
        break;
      case operation::unlock:
        states_[i]->unlock();
        break;
      case operation::toggle_lock:
        states_[i]->toggle_lock();
        break;
      }
    }
  }

  bool pressed(modifier_flag m) const {
    if (m == modifier_flag::zero) {
      return true;
    }

    auto i = static_cast<size_t>(m);
    if (i < states_.size() && states_[i]) {
      return states_[i]->pressed();
    }
    return false;
  }

  bool pressed(const std::vector<modifier_flag>& modifier_flags) const {
    // return true if all modifier flags are pressed.
    for (const auto& m : modifier_flags) {
      if (!pressed(m)) {
        return false;
      }
    }
    return true;
  }

  uint8_t get_hid_report_bits(void) const {
    uint8_t bits = 0;

    if (pressed(modifier_flag::left_control)) {
      bits |= (0x1 << 0);
    }
    if (pressed(modifier_flag::left_shift)) {
      bits |= (0x1 << 1);
    }
    if (pressed(modifier_flag::left_option)) {
      bits |= (0x1 << 2);
    }
    if (pressed(modifier_flag::left_command)) {
      bits |= (0x1 << 3);
    }
    if (pressed(modifier_flag::right_control)) {
      bits |= (0x1 << 4);
    }
    if (pressed(modifier_flag::right_shift)) {
      bits |= (0x1 << 5);
    }
    if (pressed(modifier_flag::right_option)) {
      bits |= (0x1 << 6);
    }
    if (pressed(modifier_flag::right_command)) {
      bits |= (0x1 << 7);
    }

    return bits;
  }

  IOOptionBits get_io_option_bits(key_code key_code) const {
    // OS X requires to set NX_NONCOALSESCEDMASK.
    IOOptionBits bits = NX_NONCOALSESCEDMASK;

    if (pressed(modifier_flag::caps_lock)) {
      bits |= NX_ALPHASHIFTMASK;
    }
    if (pressed(modifier_flag::left_control)) {
      bits |= NX_CONTROLMASK | NX_DEVICELCTLKEYMASK;
    }
    if (pressed(modifier_flag::right_control)) {
      bits |= NX_CONTROLMASK | NX_DEVICERCTLKEYMASK;
    }
    if (pressed(modifier_flag::left_shift)) {
      bits |= NX_SHIFTMASK | NX_DEVICELSHIFTKEYMASK;
    }
    if (pressed(modifier_flag::right_shift)) {
      bits |= NX_SHIFTMASK | NX_DEVICERSHIFTKEYMASK;
    }
    if (pressed(modifier_flag::left_option)) {
      bits |= NX_ALTERNATEMASK | NX_DEVICELALTKEYMASK;
    }
    if (pressed(modifier_flag::right_option)) {
      bits |= NX_ALTERNATEMASK | NX_DEVICERALTKEYMASK;
    }
    if (pressed(modifier_flag::left_command)) {
      bits |= NX_COMMANDMASK | NX_DEVICELCMDKEYMASK;
    }
    if (pressed(modifier_flag::right_command)) {
      bits |= NX_COMMANDMASK | NX_DEVICERCMDKEYMASK;
    }
    if (pressed(modifier_flag::fn)) {
      bits |= NX_SECONDARYFNMASK;
    }

    // Add NX_NUMERICPADMASK, NX_SECONDARYFNMASK by key_code.
    //
    // Note:
    //   Microsoft Remote Client will fail to treat shift-arrow keys unless these flags.
    //   Alfred will fail f16 key as trigger key unless fn flag.

    switch (key_code) {
    case key_code::keypad_slash:
    case key_code::keypad_asterisk:
    case key_code::keypad_hyphen:
    case key_code::keypad_plus:
    case key_code::keypad_enter:
    case key_code::keypad_1:
    case key_code::keypad_2:
    case key_code::keypad_3:
    case key_code::keypad_4:
    case key_code::keypad_5:
    case key_code::keypad_6:
    case key_code::keypad_7:
    case key_code::keypad_8:
    case key_code::keypad_9:
    case key_code::keypad_0:
    case key_code::keypad_period:
    case key_code::keypad_equal_sign:
    case key_code::keypad_comma:
      bits |= NX_NUMERICPADMASK;
      break;

    case key_code::right_arrow:
    case key_code::left_arrow:
    case key_code::down_arrow:
    case key_code::up_arrow:
      bits |= NX_NUMERICPADMASK | NX_SECONDARYFNMASK;
      break;

    case key_code::f1:
    case key_code::f2:
    case key_code::f3:
    case key_code::f4:
    case key_code::f5:
    case key_code::f6:
    case key_code::f7:
    case key_code::f8:
    case key_code::f9:
    case key_code::f10:
    case key_code::f11:
    case key_code::f12:
    case key_code::f13:
    case key_code::f14:
    case key_code::f15:
    case key_code::f16:
    case key_code::f17:
    case key_code::f18:
    case key_code::f19:
    case key_code::f20:
    case key_code::f21:
    case key_code::f22:
    case key_code::f23:
    case key_code::f24:
      bits |= NX_SECONDARYFNMASK;
      break;

    default:
      break;
    }

    return bits;
  }

  CGEventFlags get_cg_event_flags_for_mouse_events(void) const {
    // The CGEventFlags and IOOptionBits are same for now.
    return get_io_option_bits(key_code::vk_none);
  }

private:
  class state final {
  public:
    state(const std::string& name, const std::string& symbol) : name_(name),
                                                                symbol_(symbol),
                                                                count_(0),
                                                                lock_count_(0) {}

    const std::string& get_name(void) const { return name_; }
    const std::string& get_symbol(void) const { return symbol_; }

    bool pressed(void) {
      std::lock_guard<std::mutex> guard(mutex_);

      return (count_ + lock_count_) > 0;
    }

    void reset(void) {
      std::lock_guard<std::mutex> guard(mutex_);

      count_ = 0;
    }

    void increase(void) {
      std::lock_guard<std::mutex> guard(mutex_);

      ++count_;
    }

    void decrease(void) {
      std::lock_guard<std::mutex> guard(mutex_);

      --count_;
    }

    void lock(void) {
      std::lock_guard<std::mutex> guard(mutex_);

      lock_count_ = 1;
    }

    void unlock(void) {
      std::lock_guard<std::mutex> guard(mutex_);

      lock_count_ = 0;
    }

    void toggle_lock(void) {
      std::lock_guard<std::mutex> guard(mutex_);

      lock_count_ = lock_count_ == 0 ? 1 : 0;
    }

  private:
    std::string name_;
    std::string symbol_;
    int count_;
    int lock_count_;

    std::mutex mutex_;
  };

  std::vector<std::unique_ptr<state>> states_;
};
} // namespace manipulator
} // namespace krbn
<commit_msg>remove modifier_flag_manager.get_hid_report_bits,get_io_option_bits,get_cg_event_flags_for_mouse_events<commit_after>#pragma once

#include "types.hpp"
#include <CoreGraphics/CoreGraphics.h>
#include <thread>
#include <vector>

namespace krbn {
namespace manipulator {
class modifier_flag_manager final {
public:
  modifier_flag_manager(void) {
    states_.resize(static_cast<size_t>(modifier_flag::end_));

    states_[static_cast<size_t>(modifier_flag::caps_lock)] = std::make_unique<state>("caps lock", "⇪");
    states_[static_cast<size_t>(modifier_flag::left_control)] = std::make_unique<state>("control", "⌃");
    states_[static_cast<size_t>(modifier_flag::left_shift)] = std::make_unique<state>("shift", "⇧");
    states_[static_cast<size_t>(modifier_flag::left_option)] = std::make_unique<state>("option", "⌥");
    states_[static_cast<size_t>(modifier_flag::left_command)] = std::make_unique<state>("command", "⌘");
    states_[static_cast<size_t>(modifier_flag::right_control)] = std::make_unique<state>("control", "⌃");
    states_[static_cast<size_t>(modifier_flag::right_shift)] = std::make_unique<state>("shift", "⇧");
    states_[static_cast<size_t>(modifier_flag::right_option)] = std::make_unique<state>("option", "⌥");
    states_[static_cast<size_t>(modifier_flag::right_command)] = std::make_unique<state>("command", "⌘");
    states_[static_cast<size_t>(modifier_flag::fn)] = std::make_unique<state>("fn", "fn");
  }

  void reset(void) {
    for (const auto& s : states_) {
      if (s) {
        s->reset();
      }
    }
  }

  void unlock(void) {
    for (const auto& s : states_) {
      if (s) {
        s->unlock();
      }
    }
  }

  enum class operation {
    increase,
    decrease,
    lock,
    unlock,
    toggle_lock,
  };

  void manipulate(modifier_flag k, operation operation) {
    auto i = static_cast<size_t>(k);
    if (states_[i]) {
      switch (operation) {
      case operation::increase:
        states_[i]->increase();
        break;
      case operation::decrease:
        states_[i]->decrease();
        break;
      case operation::lock:
        states_[i]->lock();
        break;
      case operation::unlock:
        states_[i]->unlock();
        break;
      case operation::toggle_lock:
        states_[i]->toggle_lock();
        break;
      }
    }
  }

  bool pressed(modifier_flag m) const {
    if (m == modifier_flag::zero) {
      return true;
    }

    auto i = static_cast<size_t>(m);
    if (i < states_.size() && states_[i]) {
      return states_[i]->pressed();
    }
    return false;
  }

  bool pressed(const std::vector<modifier_flag>& modifier_flags) const {
    // return true if all modifier flags are pressed.
    for (const auto& m : modifier_flags) {
      if (!pressed(m)) {
        return false;
      }
    }
    return true;
  }

private:
  class state final {
  public:
    state(const std::string& name, const std::string& symbol) : name_(name),
                                                                symbol_(symbol),
                                                                count_(0),
                                                                lock_count_(0) {}

    const std::string& get_name(void) const { return name_; }
    const std::string& get_symbol(void) const { return symbol_; }

    bool pressed(void) {
      std::lock_guard<std::mutex> guard(mutex_);

      return (count_ + lock_count_) > 0;
    }

    void reset(void) {
      std::lock_guard<std::mutex> guard(mutex_);

      count_ = 0;
    }

    void increase(void) {
      std::lock_guard<std::mutex> guard(mutex_);

      ++count_;
    }

    void decrease(void) {
      std::lock_guard<std::mutex> guard(mutex_);

      --count_;
    }

    void lock(void) {
      std::lock_guard<std::mutex> guard(mutex_);

      lock_count_ = 1;
    }

    void unlock(void) {
      std::lock_guard<std::mutex> guard(mutex_);

      lock_count_ = 0;
    }

    void toggle_lock(void) {
      std::lock_guard<std::mutex> guard(mutex_);

      lock_count_ = lock_count_ == 0 ? 1 : 0;
    }

  private:
    std::string name_;
    std::string symbol_;
    int count_;
    int lock_count_;

    std::mutex mutex_;
  };

  std::vector<std::unique_ptr<state>> states_;
};
} // namespace manipulator
} // namespace krbn
<|endoftext|>


<commit_before>#include "musicplayer.h"
#include "musicplaylist.h"
#include "musicsettingmanager.h"
#include "musicconnectionpool.h"
#include "musicnumberdefine.h"
///qmmp incldue
#include "soundcore.h"
///
#include <qmath.h>

MusicPlayer::MusicPlayer(QObject *parent)
    : QObject(parent)
{
    m_playlist = nullptr;
    m_state = StoppedState;
    m_musicEnhanced = EnhancedOff;
    m_music = new SoundCore(this);
    m_posOnCircle = 0;
    m_volumeMusic3D = 0;
    m_balance = 0;
    m_duration = 0;
    m_tryTimes = 0;

    setEnaleEffect(false);

    connect(&m_timer, SIGNAL(timeout()), SLOT(update()));
    M_CONNECTION_PTR->setValue(getClassName(), this);
}

MusicPlayer::~MusicPlayer()
{
    delete m_music;
}

QString MusicPlayer::getClassName()
{
    return staticMetaObject.className();
}

MusicPlayer::State MusicPlayer::state() const
{
    return m_state;
}

void MusicPlayer::setPlaylist(MusicPlaylist *playlist)
{
    delete m_playlist;
    m_playlist = playlist;
}

MusicPlaylist *MusicPlayer::playlist() const
{
    return m_playlist;
}

qint64 MusicPlayer::duration() const
{
    return m_music->totalTime();
}

qint64 MusicPlayer::position() const
{
    return m_music->elapsed();
}

void MusicPlayer::playNext()
{
    int index = m_playlist->currentIndex();
    m_playlist->setCurrentIndex((++index >= m_playlist->mediaCount()) ? 0 : index);
}

void MusicPlayer::playPrevious()
{
    int index = m_playlist->currentIndex();
    m_playlist->setCurrentIndex((--index < 0) ? 0 : index );
}

int MusicPlayer::volume() const
{
    return isMuted() ? 0 : m_music->volume();
}

void MusicPlayer::setVolume(int volume)
{
    m_volumeMusic3D = volume;
    m_music->setVolume(volume);
}

bool MusicPlayer::isMuted() const
{
    return m_music->isMuted();
}

void MusicPlayer::setMuted(bool muted)
{
    m_volumeMusic3D = muted ? 0 : m_music->volume();
    m_music->setMuted(muted);
}

void MusicPlayer::setPosition(qint64 position)
{
    m_music->seek(position);
}

void MusicPlayer::setMusicEnhanced(Enhanced type)
{
    m_musicEnhanced = type;

    if(m_musicEnhanced == Music3D)
    {
        m_volumeMusic3D = volume();
    }
    else if(m_musicEnhanced == EnhancedOff)
    {
        return;
    }
    else
    {
        m_music->setBalance(0);
        m_music->setVolume(m_volumeMusic3D, m_volumeMusic3D);
        m_music->setBalance(m_balance);
        setMusicEnhancedCase();
    }
}

MusicPlayer::Enhanced MusicPlayer::getMusicEnhanced() const
{
    return m_musicEnhanced;
}

QStringList MusicPlayer::supportFormatsString()
{
    return QStringList()<< "mpc" << "wv" << "ogg" << "wav" << "au" << "snd" << "aif" << "aiff" << "8svx"
                        << "sph" << "sf" << "voc" << "w64" << "cue" << "mp1" << "mp2" << "mp3" << "wav"
                        << "ay" << "gms" << "gym" << "hes" << "kss" << "nsf" << "nsfe" << "sap" << "spc"
                        << "vgm" << "vgz" << "flac" << "oga" << "ape" << "wma" << "ape" << "tta" << "m4a"
                        << "ra" << "shn" << "vqf" << "ac3" << "mod" << "s3m" << "xm" << "it" << "669"
                        << "amf" << "ams" << "dbm" << "dmf" << "dsm" << "far" << "mdl" << "med" << "mtm"
                        << "okt" << "ptm" << "stm" << "ult" << "umx" << "mt2" << "psm" << "mdz" << "s3z"
                        << "xmz" << "itz" << "mdr" << "s3r" << "xmr" << "itr" << "dgz" << "s3gz" << "xmgz"
                        << "itgz" << "opus" << "mid"
#ifndef Q_OS_WIN
                        << "sid" << "mus" << "str" << "prg" << "P00"
#endif
                        << "aac";
}

QStringList MusicPlayer::supportFormatsFilterString()
{
    return QStringList()<< "*.mpc" << "*.wv" << "*.ogg" << "*.wav" << "*.au" << "*.snd" << "*.aif" << "*.aiff" << "*.8svx"
                        << "*.sph" << "*.sf" << "*.voc" << "*.w64" << "*.cue" << "*.mp1" << "*.mp2" << "*.mp3" << "*.wav"
                        << "*.ay" << "*.gms" << "*.gym" << "*.hes" << "*.kss" << "*.nsf" << "*.nsfe" << "*.sap" << "*.spc"
                        << "*.vgm" << "*.vgz" << "*.flac" << "*.oga" << "*.ape" << "*.wma" << "*.ape" << "*.tta" << "*.m4a"
                        << "*.ra" << "*.shn" << "*.vqf" << "*.ac3" << "*.mod" << "*.s3m" << "*.xm" << "*.it" << "*.669"
                        << "*.amf" << "*.ams" << "*.dbm" << "*.dmf" << "*.dsm" << "*.far" << "*.mdl" << "*.med" << "*.mtm"
                        << "*.okt" << "*.ptm" << "*.stm" << "*.ult" << "*.umx" << "*.mt2" << "*.psm" << "*.mdz" << "*.s3z"
                        << "*.xmz" << "*.itz" << "*.mdr" << "*.s3r" << "*.xmr" << "*.itr" << "*.dgz" << "*.s3gz" << "*.xmgz"
                        << "*.itgz" << "*.opus" << "*.mid"
#ifndef Q_OS_WIN
                        << "*.sid" << "*.mus" << "*.str" << "*.prg" << "*.P00"
#endif
                        << "*.aac";
}

QStringList MusicPlayer::supportFormatsFilterDialogString()
{
    return QStringList()<< "All File(*.*)" << "MusePack File(*.mpc)" << "WavPack File(*.wv)" << "Ogg Vorbis File(*.ogg)"
                        << "PCM File(*.wav *.au *.snd *.aif *.aiff *.8svx *.sph *.sf *.voc *.w64)"
                        << "CUE File(*.cue)" << "MPEG File(*.mp1 *.mp2 *.mp3 *.wav)"
                        << "Game File(*.ay *.gms *.gym *.hes *.kss *.nsf *.nsfe *.sap *.spc *.vgm *.vgz)"
                        << "FLAC File(*.flac *.oga)" << "Monkey's Audio File(*.ape)"
                        << "Ogg Opus File(*.opus)" << "ADTS AAC File(*.aac)" << "MIDI File(*.mid)"
#ifndef Q_OS_WIN
                        << "SID File(*.sid *.mus *.str *.prg *.P00)"
#endif
                        << "FFmpeg File(*.wma *.ape *.tta *.m4a *.ra *.shn *.vqf *.ac3)"
                        << "ModPlug File(*.mod *.s3m *.xm *.it *.669 *.amf *.ams *.dbm *.dmf *.dsm *.far,mdl *.med *.mtm "
                           "*.okt *.ptm *.stm *.ult *.umx *.mt2 *.psm *.mdz *.s3z *.xmz *.itz *.mdr *.s3r *.xmr *.itr "
                           "*.dgz *.s3gz *.xmgz *.itgz)";
}

void MusicPlayer::play()
{
    if(m_playlist->isEmpty())
    {
        m_state = StoppedState;
        return;
    }

    m_state = PlayingState;
    Qmmp::State state = m_music->state(); ///Get the current state of play
    if(m_currentMedia == m_playlist->currentMediaString() && state == Qmmp::Paused)
    {
        m_music->pause(); ///When the pause time for recovery
        m_timer.start(MT_S2MS);
        return;
    }

    m_currentMedia = m_playlist->currentMediaString();
    ///The current playback path
    if(!m_music->play(m_currentMedia))
    {
        m_state = StoppedState;
        return;
    }

    m_tryTimes = 0;
    m_timer.start(MT_S2MS);
    ///Every second emits a signal change information
    emit positionChanged(0);
    getCurrentDuration();

    ////////////////////////////////////////////////
    ///Read the configuration settings for the sound
    int volume = M_SETTING_PTR->value(MusicSettingManager::VolumeChoiced).toInt();
    if(volume != -1)
    {
        setVolume(volume);
    }
    setSoundEffectVolume(M_SETTING_PTR->value(MusicSettingManager::EnhancedBalanceChoiced).toInt());
    ////////////////////////////////////////////////
}

void MusicPlayer::pause()
{
    m_music->pause();
    m_timer.stop();
    m_state = PausedState;
}

void MusicPlayer::stop()
{
    m_music->stop();
    m_timer.stop();
    m_state = StoppedState;
}

void MusicPlayer::setEqEffect(const MusicObject::MIntList &hz)
{
    if(hz.count() != 11)
    {
        return;
    }

    EqSettings eq = m_music->eqSettings();
    eq.setPreamp(15 + hz[0]);
    eq.setEnabled(true);
    for(int i=0; i<EqSettings::EQ_BANDS_10; ++i)
    {
        eq.setGain(i, hz[i + 1]);
    }
    m_music->setEqSettings(eq);
}

void MusicPlayer::setEnaleEffect(bool enable)
{
    if(enable == false)
    {
        setEqEffect(MusicObject::MIntList()<< 0<< 0<< 0<< 0<< 0<< 0<< 0<< 0<< 0<< 0<< 0);
    }
}

void MusicPlayer::setEqInformation()
{
    ///Read the equalizer parameters from a configuration file
    if(M_SETTING_PTR->value(MusicSettingManager::EqualizerEnableChoiced).toInt())
    {
        setEnaleEffect(true);
        QStringList eqValue = M_SETTING_PTR->value(MusicSettingManager::EqualizerValueChoiced).toString().split(',');
        if(eqValue.count() == 11)
        {
            MusicObject::MIntList hz;
            hz << eqValue[0].toInt() << eqValue[1].toInt() << eqValue[2].toInt()
               << eqValue[3].toInt() << eqValue[4].toInt() << eqValue[5].toInt()
               << eqValue[6].toInt() << eqValue[7].toInt() << eqValue[8].toInt()
               << eqValue[9].toInt() << eqValue[10].toInt();
            setEqEffect(hz);
        }
    }
    else
    {
        setEnaleEffect(false);
    }
}

void MusicPlayer::setSoundEffectVolume(int value)
{
    m_balance = value;
    m_music->setBalance(value);
}

void MusicPlayer::removeCurrentMedia()
{
    m_timer.stop();
    m_music->stop();
}

void MusicPlayer::update()
{
    emit positionChanged( position() );

    if(m_musicEnhanced == Music3D && !m_music->isMuted())
    {
        ///3D music settings
        setEnaleEffect(false);
        m_posOnCircle += 0.5f;
        m_music->setVolume(abs(100 * cosf(m_posOnCircle)), abs(100 * sinf(m_posOnCircle * 0.5f)));
    }

    Qmmp::State state = m_music->state();
    if(state != Qmmp::Playing && state != Qmmp::Paused)
    {
        m_timer.stop();
        if(m_playlist->playbackMode() == MusicObject::MC_PlayOnce)
        {
            m_music->stop();
            emit positionChanged(0);
            emit stateChanged(StoppedState);
            return;
        }
        m_playlist->setCurrentIndex();
        if(m_playlist->playbackMode() == MusicObject::MC_PlayOrder &&
           m_playlist->currentIndex() == -1)
        {
            m_music->stop();
            emit positionChanged(0);
            emit stateChanged(StoppedState);
            return;
        }
        play();
    }
}

void MusicPlayer::getCurrentDuration()
{
    qint64 dur = duration();
    if( (dur == 0 || m_duration == dur) && m_tryTimes++ < 10 )
    {
        QTimer::singleShot(50*MT_MS, this, SLOT(getCurrentDuration()));
    }
    else
    {
        emit durationChanged( m_duration = dur );
    }
}

void MusicPlayer::setMusicEnhancedCase()
{
    switch(m_musicEnhanced)
    {
        case EnhancedOff:
            setEqEffect(MusicObject::MIntList()<<  0<<  0<<  0<<  0<<  0<<  0<<  0<<  0<<  0<<  0<<  0);
            break;
        case MusicVocal:
            setEqEffect(MusicObject::MIntList()<<  0<<  0<<  4<<  1<< -5<< -1<<  2<< -2<< -4<< -4<<  0);
            break;
        case MusicNICAM:
            setEqEffect(MusicObject::MIntList()<<  6<<-12<<-12<< -9<< -6<< -3<<-12<< -9<< -6<< -3<<-12);
            break;
        case MusicSubwoofer:
            setEqEffect(MusicObject::MIntList()<<  6<<  6<<-10<<-10<<  0<<  0<< -3<< -5<< -7<< -9<<-11);
            break;
        default:
            break;
    }
}
<commit_msg>fix enhanced music off[333333]<commit_after>#include "musicplayer.h"
#include "musicplaylist.h"
#include "musicsettingmanager.h"
#include "musicconnectionpool.h"
#include "musicnumberdefine.h"
///qmmp incldue
#include "soundcore.h"
///
#include <qmath.h>

MusicPlayer::MusicPlayer(QObject *parent)
    : QObject(parent)
{
    m_playlist = nullptr;
    m_state = StoppedState;
    m_musicEnhanced = EnhancedOff;
    m_music = new SoundCore(this);
    m_posOnCircle = 0;
    m_volumeMusic3D = 0;
    m_balance = 0;
    m_duration = 0;
    m_tryTimes = 0;

    setEnaleEffect(false);

    connect(&m_timer, SIGNAL(timeout()), SLOT(update()));
    M_CONNECTION_PTR->setValue(getClassName(), this);
}

MusicPlayer::~MusicPlayer()
{
    delete m_music;
}

QString MusicPlayer::getClassName()
{
    return staticMetaObject.className();
}

MusicPlayer::State MusicPlayer::state() const
{
    return m_state;
}

void MusicPlayer::setPlaylist(MusicPlaylist *playlist)
{
    delete m_playlist;
    m_playlist = playlist;
}

MusicPlaylist *MusicPlayer::playlist() const
{
    return m_playlist;
}

qint64 MusicPlayer::duration() const
{
    return m_music->totalTime();
}

qint64 MusicPlayer::position() const
{
    return m_music->elapsed();
}

void MusicPlayer::playNext()
{
    int index = m_playlist->currentIndex();
    m_playlist->setCurrentIndex((++index >= m_playlist->mediaCount()) ? 0 : index);
}

void MusicPlayer::playPrevious()
{
    int index = m_playlist->currentIndex();
    m_playlist->setCurrentIndex((--index < 0) ? 0 : index );
}

int MusicPlayer::volume() const
{
    return isMuted() ? 0 : m_music->volume();
}

void MusicPlayer::setVolume(int volume)
{
    m_volumeMusic3D = volume;
    m_music->setVolume(volume);
}

bool MusicPlayer::isMuted() const
{
    return m_music->isMuted();
}

void MusicPlayer::setMuted(bool muted)
{
    m_volumeMusic3D = muted ? 0 : m_music->volume();
    m_music->setMuted(muted);
}

void MusicPlayer::setPosition(qint64 position)
{
    m_music->seek(position);
}

void MusicPlayer::setMusicEnhanced(Enhanced type)
{
    m_musicEnhanced = type;

    if(m_musicEnhanced == Music3D)
    {
        m_volumeMusic3D = volume();
    }
    else
    {
        m_music->setBalance(0);
        m_music->setVolume(m_volumeMusic3D, m_volumeMusic3D);
        m_music->setBalance(m_balance);
        setMusicEnhancedCase();
    }
}

MusicPlayer::Enhanced MusicPlayer::getMusicEnhanced() const
{
    return m_musicEnhanced;
}

QStringList MusicPlayer::supportFormatsString()
{
    return QStringList()<< "mpc" << "wv" << "ogg" << "wav" << "au" << "snd" << "aif" << "aiff" << "8svx"
                        << "sph" << "sf" << "voc" << "w64" << "cue" << "mp1" << "mp2" << "mp3" << "wav"
                        << "ay" << "gms" << "gym" << "hes" << "kss" << "nsf" << "nsfe" << "sap" << "spc"
                        << "vgm" << "vgz" << "flac" << "oga" << "ape" << "wma" << "ape" << "tta" << "m4a"
                        << "ra" << "shn" << "vqf" << "ac3" << "mod" << "s3m" << "xm" << "it" << "669"
                        << "amf" << "ams" << "dbm" << "dmf" << "dsm" << "far" << "mdl" << "med" << "mtm"
                        << "okt" << "ptm" << "stm" << "ult" << "umx" << "mt2" << "psm" << "mdz" << "s3z"
                        << "xmz" << "itz" << "mdr" << "s3r" << "xmr" << "itr" << "dgz" << "s3gz" << "xmgz"
                        << "itgz" << "opus" << "mid"
#ifndef Q_OS_WIN
                        << "sid" << "mus" << "str" << "prg" << "P00"
#endif
                        << "aac";
}

QStringList MusicPlayer::supportFormatsFilterString()
{
    return QStringList()<< "*.mpc" << "*.wv" << "*.ogg" << "*.wav" << "*.au" << "*.snd" << "*.aif" << "*.aiff" << "*.8svx"
                        << "*.sph" << "*.sf" << "*.voc" << "*.w64" << "*.cue" << "*.mp1" << "*.mp2" << "*.mp3" << "*.wav"
                        << "*.ay" << "*.gms" << "*.gym" << "*.hes" << "*.kss" << "*.nsf" << "*.nsfe" << "*.sap" << "*.spc"
                        << "*.vgm" << "*.vgz" << "*.flac" << "*.oga" << "*.ape" << "*.wma" << "*.ape" << "*.tta" << "*.m4a"
                        << "*.ra" << "*.shn" << "*.vqf" << "*.ac3" << "*.mod" << "*.s3m" << "*.xm" << "*.it" << "*.669"
                        << "*.amf" << "*.ams" << "*.dbm" << "*.dmf" << "*.dsm" << "*.far" << "*.mdl" << "*.med" << "*.mtm"
                        << "*.okt" << "*.ptm" << "*.stm" << "*.ult" << "*.umx" << "*.mt2" << "*.psm" << "*.mdz" << "*.s3z"
                        << "*.xmz" << "*.itz" << "*.mdr" << "*.s3r" << "*.xmr" << "*.itr" << "*.dgz" << "*.s3gz" << "*.xmgz"
                        << "*.itgz" << "*.opus" << "*.mid"
#ifndef Q_OS_WIN
                        << "*.sid" << "*.mus" << "*.str" << "*.prg" << "*.P00"
#endif
                        << "*.aac";
}

QStringList MusicPlayer::supportFormatsFilterDialogString()
{
    return QStringList()<< "All File(*.*)" << "MusePack File(*.mpc)" << "WavPack File(*.wv)" << "Ogg Vorbis File(*.ogg)"
                        << "PCM File(*.wav *.au *.snd *.aif *.aiff *.8svx *.sph *.sf *.voc *.w64)"
                        << "CUE File(*.cue)" << "MPEG File(*.mp1 *.mp2 *.mp3 *.wav)"
                        << "Game File(*.ay *.gms *.gym *.hes *.kss *.nsf *.nsfe *.sap *.spc *.vgm *.vgz)"
                        << "FLAC File(*.flac *.oga)" << "Monkey's Audio File(*.ape)"
                        << "Ogg Opus File(*.opus)" << "ADTS AAC File(*.aac)" << "MIDI File(*.mid)"
#ifndef Q_OS_WIN
                        << "SID File(*.sid *.mus *.str *.prg *.P00)"
#endif
                        << "FFmpeg File(*.wma *.ape *.tta *.m4a *.ra *.shn *.vqf *.ac3)"
                        << "ModPlug File(*.mod *.s3m *.xm *.it *.669 *.amf *.ams *.dbm *.dmf *.dsm *.far,mdl *.med *.mtm "
                           "*.okt *.ptm *.stm *.ult *.umx *.mt2 *.psm *.mdz *.s3z *.xmz *.itz *.mdr *.s3r *.xmr *.itr "
                           "*.dgz *.s3gz *.xmgz *.itgz)";
}

void MusicPlayer::play()
{
    if(m_playlist->isEmpty())
    {
        m_state = StoppedState;
        return;
    }

    m_state = PlayingState;
    Qmmp::State state = m_music->state(); ///Get the current state of play
    if(m_currentMedia == m_playlist->currentMediaString() && state == Qmmp::Paused)
    {
        m_music->pause(); ///When the pause time for recovery
        m_timer.start(MT_S2MS);
        return;
    }

    m_currentMedia = m_playlist->currentMediaString();
    ///The current playback path
    if(!m_music->play(m_currentMedia))
    {
        m_state = StoppedState;
        return;
    }

    m_tryTimes = 0;
    m_timer.start(MT_S2MS);
    ///Every second emits a signal change information
    emit positionChanged(0);
    getCurrentDuration();

    ////////////////////////////////////////////////
    ///Read the configuration settings for the sound
    int volume = M_SETTING_PTR->value(MusicSettingManager::VolumeChoiced).toInt();
    if(volume != -1)
    {
        setVolume(volume);
    }
    setSoundEffectVolume(M_SETTING_PTR->value(MusicSettingManager::EnhancedBalanceChoiced).toInt());
    ////////////////////////////////////////////////
}

void MusicPlayer::pause()
{
    m_music->pause();
    m_timer.stop();
    m_state = PausedState;
}

void MusicPlayer::stop()
{
    m_music->stop();
    m_timer.stop();
    m_state = StoppedState;
}

void MusicPlayer::setEqEffect(const MusicObject::MIntList &hz)
{
    if(hz.count() != 11)
    {
        return;
    }

    EqSettings eq = m_music->eqSettings();
    eq.setPreamp(15 + hz[0]);
    eq.setEnabled(true);
    for(int i=0; i<EqSettings::EQ_BANDS_10; ++i)
    {
        eq.setGain(i, hz[i + 1]);
    }
    m_music->setEqSettings(eq);
}

void MusicPlayer::setEnaleEffect(bool enable)
{
    if(enable == false)
    {
        setEqEffect(MusicObject::MIntList()<< 0<< 0<< 0<< 0<< 0<< 0<< 0<< 0<< 0<< 0<< 0);
    }
}

void MusicPlayer::setEqInformation()
{
    ///Read the equalizer parameters from a configuration file
    if(M_SETTING_PTR->value(MusicSettingManager::EqualizerEnableChoiced).toInt())
    {
        setEnaleEffect(true);
        QStringList eqValue = M_SETTING_PTR->value(MusicSettingManager::EqualizerValueChoiced).toString().split(',');
        if(eqValue.count() == 11)
        {
            MusicObject::MIntList hz;
            hz << eqValue[0].toInt() << eqValue[1].toInt() << eqValue[2].toInt()
               << eqValue[3].toInt() << eqValue[4].toInt() << eqValue[5].toInt()
               << eqValue[6].toInt() << eqValue[7].toInt() << eqValue[8].toInt()
               << eqValue[9].toInt() << eqValue[10].toInt();
            setEqEffect(hz);
        }
    }
    else
    {
        setEnaleEffect(false);
    }
}

void MusicPlayer::setSoundEffectVolume(int value)
{
    m_balance = value;
    m_music->setBalance(value);
}

void MusicPlayer::removeCurrentMedia()
{
    m_timer.stop();
    m_music->stop();
}

void MusicPlayer::update()
{
    emit positionChanged( position() );

    if(m_musicEnhanced == Music3D && !m_music->isMuted())
    {
        ///3D music settings
        setEnaleEffect(false);
        m_posOnCircle += 0.5f;
        m_music->setVolume(abs(100 * cosf(m_posOnCircle)), abs(100 * sinf(m_posOnCircle * 0.5f)));
    }

    Qmmp::State state = m_music->state();
    if(state != Qmmp::Playing && state != Qmmp::Paused)
    {
        m_timer.stop();
        if(m_playlist->playbackMode() == MusicObject::MC_PlayOnce)
        {
            m_music->stop();
            emit positionChanged(0);
            emit stateChanged(StoppedState);
            return;
        }
        m_playlist->setCurrentIndex();
        if(m_playlist->playbackMode() == MusicObject::MC_PlayOrder &&
           m_playlist->currentIndex() == -1)
        {
            m_music->stop();
            emit positionChanged(0);
            emit stateChanged(StoppedState);
            return;
        }
        play();
    }
}

void MusicPlayer::getCurrentDuration()
{
    qint64 dur = duration();
    if( (dur == 0 || m_duration == dur) && m_tryTimes++ < 10 )
    {
        QTimer::singleShot(50*MT_MS, this, SLOT(getCurrentDuration()));
    }
    else
    {
        emit durationChanged( m_duration = dur );
    }
}

void MusicPlayer::setMusicEnhancedCase()
{
    switch(m_musicEnhanced)
    {
        case EnhancedOff:
            setEqEffect(MusicObject::MIntList()<<  0<<  0<<  0<<  0<<  0<<  0<<  0<<  0<<  0<<  0<<  0);
            break;
        case MusicVocal:
            setEqEffect(MusicObject::MIntList()<<  0<<  0<<  4<<  1<< -5<< -1<<  2<< -2<< -4<< -4<<  0);
            break;
        case MusicNICAM:
            setEqEffect(MusicObject::MIntList()<<  6<<-12<<-12<< -9<< -6<< -3<<-12<< -9<< -6<< -3<<-12);
            break;
        case MusicSubwoofer:
            setEqEffect(MusicObject::MIntList()<<  6<<  6<<-10<<-10<<  0<<  0<< -3<< -5<< -7<< -9<<-11);
            break;
        default:
            break;
    }
}
<|endoftext|>


<commit_before>//
// MiniDatabuf.cpp
//
// Copyright (c) 2006-2007 Virtual Terrain Project and Stefan Roettger
// Free for all uses, see license.txt for details.
//

#include "MiniDatabuf.h"
#include "vtLog.h"
#include "Projections.h"
#include "MathTypes.h"
#include "FilePath.h"

#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <float.h>

#define ERRORMSG() VTLOG1("Error!")

int MiniDatabuf::MAGIC=12640;

unsigned short int MiniDatabuf::INTEL_CHECK=1;

// default constructor
MiniDatabuf::MiniDatabuf()
   {
   xsize=ysize=zsize=0;
   tsteps=0;
   type=0;

   swx=swy=0.0f;
   nwx=nwy=0.0f;
   nex=ney=0.0f;
   sex=sey=0.0f;
   h0=dh=0.0f;
   t0=dt=0.0f;

   scaling=1.0f;
   bias=0.0f;

   data=NULL;
   bytes=0;
   }

MiniDatabuf::~MiniDatabuf()
{
	release();
}

// set the geographic extents
void MiniDatabuf::set_extents(float left, float right, float bottom, float top)
{
	swx = left;
	swy = bottom;
	nwx = left;
	nwy = top;
	sex = right;
	sey = bottom;
	nex = right;
	ney = top;
}

// set the geographic extents in LLWGS84
// not supported in vtb::MiniDatabuf, requires subclassing from libMini::databuf
void MiniDatabuf::set_LLWGS84extents(float left, float right, float bottom, float top) {}

// allocate a new memory chunk
void MiniDatabuf::alloc(unsigned int xs,unsigned int ys,unsigned int zs,unsigned int ts,unsigned int ty)
   {
   unsigned int bs,cs;

   unsigned char *byteptr;
   short int *shortptr;
   float *floatptr;

   unsigned int count;

   if (ty==0) bs=1;
   else if (ty==1) bs=2;
   else if (ty==2) bs=4;
   else if (ty==3) bs=3;
   else if (ty==4) bs=3;
   else if (ty==5) bs=4;
   else if (ty==6) bs=4;
   else ERRORMSG();

   cs=xs*ys*zs*ts;
   bs*=cs;

   if (ty==4 || ty==6) bs/=6;

   if ((data=malloc(bs))==NULL) ERRORMSG();

   if (ty==1)
      for (shortptr=(short int *)data,count=0; count<cs; count++) *shortptr++=0;
   else if (ty==2)
      for (floatptr=(float *)data,count=0; count<cs; count++) *floatptr++=0.0f;
   else
      for (byteptr=(unsigned char *)data,count=0; count<bs; count++) *byteptr++=0;

   bytes=bs;

   xsize=xs;
   ysize=ys;
   zsize=zs;
   tsteps=ts;
   type=ty;
   }

// reset buffer
void MiniDatabuf::reset()
   {
   data=NULL;
   bytes=0;
   }

// release buffer
void MiniDatabuf::release()
   {
   if (data!=NULL) free(data);

   data=NULL;
   bytes=0;
   }

// data is saved in MSB format
void MiniDatabuf::savedata(const char *filename)
   {
   FILE *file;

   if (data==NULL) return;

   if (bytes==0) ERRORMSG();

   if ((file=vtFileOpen(filename,"wb"))==NULL) ERRORMSG();

   // save magic identifier
   fprintf(file,"MAGIC=%d\n",MAGIC);

   // save mandatory metadata
   fprintf(file,"xsize=%d\n",xsize);
   fprintf(file,"ysize=%d\n",ysize);
   fprintf(file,"zsize=%d\n",zsize);
   fprintf(file,"tsteps=%d\n",tsteps);
   fprintf(file,"type=%d\n",type);

   // save optional metadata
   fprintf(file,"swx=%f\n",swx);
   fprintf(file,"swy=%f\n",swy);
   fprintf(file,"nwx=%f\n",nwx);
   fprintf(file,"nwy=%f\n",nwy);
   fprintf(file,"nex=%f\n",nex);
   fprintf(file,"ney=%f\n",ney);
   fprintf(file,"sex=%f\n",sex);
   fprintf(file,"sey=%f\n",sey);
   fprintf(file,"h0=%f\n",h0);
   fprintf(file,"dh=%f\n",dh);
   fprintf(file,"t0=%f\n",t0);
   fprintf(file,"dt=%f\n",dt);

   // save optional scaling
   fprintf(file,"scaling=%f\n",scaling);
   fprintf(file,"bias=%f\n",bias);

   // save length of data chunk
   fprintf(file,"bytes=%u\n",bytes);

   // write zero byte
   fputc(0, file);

   // save data chunk
   if (*((unsigned char *)(&INTEL_CHECK))==0)
      {
      if (fwrite(data,bytes,1,file)!=1) ERRORMSG();
      fclose(file);
      }
   else
      {
      swapbytes();
      if (fwrite(data,bytes,1,file)!=1) ERRORMSG();
      swapbytes();

      fclose(file);
      }
   }

// swap byte ordering between MSB and LSB
void MiniDatabuf::swapbytes()
   {
   unsigned int i,b;

   unsigned char *ptr,tmp;

   if (type==0 || (type>=3 && type<=6)) return;

   if (type==1) b=2;
   else if (type==2) b=4;
   else ERRORMSG();

   if (bytes==0 || bytes%b!=0) ERRORMSG();

   ptr=(unsigned char *)data+bytes;

   while (ptr!=data)
      {
      ptr-=b;

      for (i=0; i<(b>>1); i++)
         {
         tmp=ptr[i];
         ptr[i]=ptr[b-1-i];
         ptr[b-1-i]=tmp;
         }
      }
   }

bool WriteTilesetHeader(const char *filename, int cols, int rows, int lod0size,
						const DRECT &area, const vtProjection &proj,
						float minheight, float maxheight,
						LODMap *lodmap)
{
	FILE *fp = vtFileOpen(filename, "wb");
	if (!fp)
		return false;

	fprintf(fp, "[TilesetDescription]\n");
	fprintf(fp, "Columns=%d\n", cols);
	fprintf(fp, "Rows=%d\n", rows);
	fprintf(fp, "LOD0_Size=%d\n", lod0size);
	fprintf(fp, "Extent_Left=%.16lg\n", area.left);
	fprintf(fp, "Extent_Right=%.16lg\n", area.right);
	fprintf(fp, "Extent_Bottom=%.16lg\n", area.bottom);
	fprintf(fp, "Extent_Top=%.16lg\n", area.top);
	// write CRS, but pretty it up a bit
	OGRSpatialReference *poSimpleClone = proj.Clone();
	poSimpleClone->GetRoot()->StripNodes( "AXIS" );
	poSimpleClone->GetRoot()->StripNodes( "AUTHORITY" );
	char *wkt;
	poSimpleClone->exportToWkt(&wkt);
	fprintf(fp, "CRS=%s\n", wkt);
	OGRFree(wkt);	// Free CRS
	delete poSimpleClone;

	// For elevation tilesets, also write vertical extents
	if (minheight != INVALID_ELEVATION)
	{
		fprintf(fp, "Elevation_Min=%.f\n", minheight);
		fprintf(fp, "Elevation_Max=%.f\n", maxheight);
	}

	if (lodmap != NULL)
	{
		int mmin, mmax;
		for (int i = 0; i < rows; i++)
		{
			fprintf(fp, "RowLODs %2d:", i);
			for (int j = 0; j < cols; j++)
			{
				lodmap->get(j, i, mmin, mmax);
				fprintf(fp, " %d/%d", mmin, mmax);
			}
			fprintf(fp, "\n");
		}
	}

   // create a transformation that will map from the current projection to Lat/Lon WGS84
   vtProjection proj_llwgs84;
   proj_llwgs84.SetWellKnownGeogCS("WGS84");
   OCT *LLWGS84transform=CreateCoordTransform(&proj,&proj_llwgs84);

   // write center point of the tileset in Lat/Lon WGS84
   // this is helpful for libMini to compute an approximate translation
   double cx=(area.left+area.right)/2;
   double cy=(area.bottom+area.top)/2;
   if (LLWGS84transform->Transform(1,&cx,&cy)==1)
      fprintf(fp, "CenterPoint_LLWGS84=(%.16lg,%.16lg)\n",cx,cy);

   // write north point of the tileset in Lat/Lon WGS84
   // this is helpful for libMini to compute an approximate rotation
   double nx=(area.left+area.right)/2;
   double ny=area.top;
   if (LLWGS84transform->Transform(1,&nx,&ny)==1)
      fprintf(fp, "NorthPoint_LLWGS84=(%.16lg,%.16lg)\n",nx,ny);

   // delete Lat/Lon WGS84 transformation
   delete LLWGS84transform;

	fclose(fp);

	return true;
}
<commit_msg>add more information for libMini to .ini<commit_after>//
// MiniDatabuf.cpp
//
// Copyright (c) 2006-2007 Virtual Terrain Project and Stefan Roettger
// Free for all uses, see license.txt for details.
//

#include "MiniDatabuf.h"
#include "vtLog.h"
#include "Projections.h"
#include "MathTypes.h"
#include "FilePath.h"

#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <float.h>

#define ERRORMSG() VTLOG1("Error!")

int MiniDatabuf::MAGIC=12640;

unsigned short int MiniDatabuf::INTEL_CHECK=1;

// default constructor
MiniDatabuf::MiniDatabuf()
   {
   xsize=ysize=zsize=0;
   tsteps=0;
   type=0;

   swx=swy=0.0f;
   nwx=nwy=0.0f;
   nex=ney=0.0f;
   sex=sey=0.0f;
   h0=dh=0.0f;
   t0=dt=0.0f;

   scaling=1.0f;
   bias=0.0f;

   data=NULL;
   bytes=0;
   }

MiniDatabuf::~MiniDatabuf()
{
	release();
}

// set the geographic extents
void MiniDatabuf::set_extents(float left, float right, float bottom, float top)
{
	swx = left;
	swy = bottom;
	nwx = left;
	nwy = top;
	sex = right;
	sey = bottom;
	nex = right;
	ney = top;
}

// set the geographic extents in LLWGS84
// not supported in vtb::MiniDatabuf, requires subclassing from libMini::databuf
void MiniDatabuf::set_LLWGS84extents(float left, float right, float bottom, float top) {}

// allocate a new memory chunk
void MiniDatabuf::alloc(unsigned int xs,unsigned int ys,unsigned int zs,unsigned int ts,unsigned int ty)
   {
   unsigned int bs,cs;

   unsigned char *byteptr;
   short int *shortptr;
   float *floatptr;

   unsigned int count;

   if (ty==0) bs=1;
   else if (ty==1) bs=2;
   else if (ty==2) bs=4;
   else if (ty==3) bs=3;
   else if (ty==4) bs=3;
   else if (ty==5) bs=4;
   else if (ty==6) bs=4;
   else ERRORMSG();

   cs=xs*ys*zs*ts;
   bs*=cs;

   if (ty==4 || ty==6) bs/=6;

   if ((data=malloc(bs))==NULL) ERRORMSG();

   if (ty==1)
      for (shortptr=(short int *)data,count=0; count<cs; count++) *shortptr++=0;
   else if (ty==2)
      for (floatptr=(float *)data,count=0; count<cs; count++) *floatptr++=0.0f;
   else
      for (byteptr=(unsigned char *)data,count=0; count<bs; count++) *byteptr++=0;

   bytes=bs;

   xsize=xs;
   ysize=ys;
   zsize=zs;
   tsteps=ts;
   type=ty;
   }

// reset buffer
void MiniDatabuf::reset()
   {
   data=NULL;
   bytes=0;
   }

// release buffer
void MiniDatabuf::release()
   {
   if (data!=NULL) free(data);

   data=NULL;
   bytes=0;
   }

// data is saved in MSB format
void MiniDatabuf::savedata(const char *filename)
   {
   FILE *file;

   if (data==NULL) return;

   if (bytes==0) ERRORMSG();

   if ((file=vtFileOpen(filename,"wb"))==NULL) ERRORMSG();

   // save magic identifier
   fprintf(file,"MAGIC=%d\n",MAGIC);

   // save mandatory metadata
   fprintf(file,"xsize=%d\n",xsize);
   fprintf(file,"ysize=%d\n",ysize);
   fprintf(file,"zsize=%d\n",zsize);
   fprintf(file,"tsteps=%d\n",tsteps);
   fprintf(file,"type=%d\n",type);

   // save optional metadata
   fprintf(file,"swx=%f\n",swx);
   fprintf(file,"swy=%f\n",swy);
   fprintf(file,"nwx=%f\n",nwx);
   fprintf(file,"nwy=%f\n",nwy);
   fprintf(file,"nex=%f\n",nex);
   fprintf(file,"ney=%f\n",ney);
   fprintf(file,"sex=%f\n",sex);
   fprintf(file,"sey=%f\n",sey);
   fprintf(file,"h0=%f\n",h0);
   fprintf(file,"dh=%f\n",dh);
   fprintf(file,"t0=%f\n",t0);
   fprintf(file,"dt=%f\n",dt);

   // save optional scaling
   fprintf(file,"scaling=%f\n",scaling);
   fprintf(file,"bias=%f\n",bias);

   // save length of data chunk
   fprintf(file,"bytes=%u\n",bytes);

   // write zero byte
   fputc(0, file);

   // save data chunk
   if (*((unsigned char *)(&INTEL_CHECK))==0)
      {
      if (fwrite(data,bytes,1,file)!=1) ERRORMSG();
      fclose(file);
      }
   else
      {
      swapbytes();
      if (fwrite(data,bytes,1,file)!=1) ERRORMSG();
      swapbytes();

      fclose(file);
      }
   }

// swap byte ordering between MSB and LSB
void MiniDatabuf::swapbytes()
   {
   unsigned int i,b;

   unsigned char *ptr,tmp;

   if (type==0 || (type>=3 && type<=6)) return;

   if (type==1) b=2;
   else if (type==2) b=4;
   else ERRORMSG();

   if (bytes==0 || bytes%b!=0) ERRORMSG();

   ptr=(unsigned char *)data+bytes;

   while (ptr!=data)
      {
      ptr-=b;

      for (i=0; i<(b>>1); i++)
         {
         tmp=ptr[i];
         ptr[i]=ptr[b-1-i];
         ptr[b-1-i]=tmp;
         }
      }
   }

int mapEPSG2MINI(int epsgdatum)
   {
   static const int NAD27=1;
   static const int WGS72=2;
   static const int WGS84=3;
   static const int NAD83=4;
   static const int SPHERE=5;
   static const int ED50=6;
   static const int ED79=7;
   static const int OHD=8;

   switch (epsgdatum)
      {
      case 6608: return(NAD27);
      case 6322: return(WGS72);
      case 6326: return(WGS84);
      case 6269: return(NAD83);
      case 6230: return(ED50);
      case 6231: return(ED79);
      case 6135: return(OHD);
      }

   return(SPHERE);
   }

bool WriteTilesetHeader(const char *filename, int cols, int rows, int lod0size,
						const DRECT &area, const vtProjection &proj,
						float minheight, float maxheight,
						LODMap *lodmap)
{
	FILE *fp = vtFileOpen(filename, "wb");
	if (!fp)
		return false;

	fprintf(fp, "[TilesetDescription]\n");
	fprintf(fp, "Columns=%d\n", cols);
	fprintf(fp, "Rows=%d\n", rows);
	fprintf(fp, "LOD0_Size=%d\n", lod0size);
	fprintf(fp, "Extent_Left=%.16lg\n", area.left);
	fprintf(fp, "Extent_Right=%.16lg\n", area.right);
	fprintf(fp, "Extent_Bottom=%.16lg\n", area.bottom);
	fprintf(fp, "Extent_Top=%.16lg\n", area.top);
	// write CRS, but pretty it up a bit
	OGRSpatialReference *poSimpleClone = proj.Clone();
	poSimpleClone->GetRoot()->StripNodes( "AXIS" );
	poSimpleClone->GetRoot()->StripNodes( "AUTHORITY" );
	char *wkt;
	poSimpleClone->exportToWkt(&wkt);
	fprintf(fp, "CRS=%s\n", wkt);
	OGRFree(wkt);	// Free CRS
	delete poSimpleClone;

	// For elevation tilesets, also write vertical extents
	if (minheight != INVALID_ELEVATION)
	{
		fprintf(fp, "Elevation_Min=%.f\n", minheight);
		fprintf(fp, "Elevation_Max=%.f\n", maxheight);
	}

	if (lodmap != NULL)
	{
		int mmin, mmax;
		for (int i = 0; i < rows; i++)
		{
			fprintf(fp, "RowLODs %2d:", i);
			for (int j = 0; j < cols; j++)
			{
				lodmap->get(j, i, mmin, mmax);
				fprintf(fp, " %d/%d", mmin, mmax);
			}
			fprintf(fp, "\n");
		}
	}

   // create a transformation that will map from the current projection to Lat/Lon WGS84
   vtProjection proj_llwgs84;
   proj_llwgs84.SetWellKnownGeogCS("WGS84");
   OCT *LLWGS84transform=CreateCoordTransform(&proj,&proj_llwgs84);

   // write center point of the tileset in Lat/Lon WGS84
   // this is helpful for libMini to compute an approximate translation
   double cx=(area.left+area.right)/2;
   double cy=(area.bottom+area.top)/2;
   if (LLWGS84transform->Transform(1,&cx,&cy)==1)
      fprintf(fp, "CenterPoint_LLWGS84=(%.16lg,%.16lg)\n",cx,cy);

   // write north point of the tileset in Lat/Lon WGS84
   // this is helpful for libMini to compute an approximate rotation
   double nx=(area.left+area.right)/2;
   double ny=area.top;
   if (LLWGS84transform->Transform(1,&nx,&ny)==1)
      fprintf(fp, "NorthPoint_LLWGS84=(%.16lg,%.16lg)\n",nx,ny);

   // delete Lat/Lon WGS84 transformation
   delete LLWGS84transform;

   // write Lat/Lon info
   // this is helpful for libMini to easily identify geo-graphic coordinates
   int latlon=proj.IsGeographic();
   int llepsgdatum=proj.GetDatum();
   int lldatum=mapEPSG2MINI(llepsgdatum);
   fprintf(fp, "CoordSys_LL=(%d,%d)\n",latlon,lldatum);

   // write UTM zone and datum
   // this is helpful for libMini to easily identify UTM coordinates
   int utmzone=proj.GetUTMZone();
   int utmepsgdatum=proj.GetDatum();
   int utmdatum=mapEPSG2MINI(utmepsgdatum);
   fprintf(fp, "CoordSys_UTM=(%d,%d)\n",utmzone,utmdatum);

   fclose(fp);

	return true;
}
<|endoftext|>