<commit_before>/*

Copyright 2015-2019 <NAME>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

#include "Buttons.h"
#include "board/Board.h"
#include "core/src/general/BitManipulation.h"

using namespace Interface::digital::input;

///
/// \brief Continuously reads inputs from buttons and acts if necessary.
///
void Buttons::update()
{
    for (int i = 0; i < MAX_NUMBER_OF_BUTTONS; i++)
    {
        if (database.read(DB_BLOCK_ENCODERS, dbSection_encoders_enable, Board::interface::digital::input::getEncoderPair(i)))
            continue;

        bool state = Board::interface::digital::input::getButtonState(i);

        if (!buttonDebounced(i, state))
            continue;

        processButton(i, state);
    }
}

///
/// \brief Handles changes in button states.
/// @param [in] buttonID    Button index which has changed state.
/// @param [in] state       Current button state.
///
void Buttons::processButton(uint8_t buttonID, bool state)
{
    //act on change of state only
    if (state == getButtonState(buttonID))
        return;

    setButtonState(buttonID, state);

    messageType_t buttonMessage = static_cast<messageType_t>(database.read(DB_BLOCK_BUTTONS, dbSection_buttons_midiMessage, buttonID));

    //don't process messageType_t::none type of message
    if (buttonMessage != messageType_t::none)
    {
        type_t type = static_cast<type_t>(database.read(DB_BLOCK_BUTTONS, dbSection_buttons_type, buttonID));

        bool sendMIDI = true;

        //overwrite type under certain conditions
        switch (buttonMessage)
        {
        case messageType_t::programChange:
        case messageType_t::programChangeInc:
        case messageType_t::programChangeDec:
        case messageType_t::mmcPlay:
        case messageType_t::mmcStop:
        case messageType_t::mmcPause:
        case messageType_t::controlChange:
        case messageType_t::realTimeClock:
        case messageType_t::realTimeStart:
        case messageType_t::realTimeContinue:
        case messageType_t::realTimeStop:
        case messageType_t::realTimeActiveSensing:
        case messageType_t::realTimeSystemReset:
            type = type_t::momentary;
            break;

        case messageType_t::mmcRecord:
            type = type_t::latching;
            break;

        case messageType_t::presetOpenDeck:
            type = type_t::momentary;
            sendMIDI = false;
            break;

        default:
            break;
        }

        if (type == type_t::latching)
        {
            //act on press only
            if (state)
            {
                if (getLatchingState(buttonID))
                {
                    setLatchingState(buttonID, false);
                    //overwrite before processing
                    state = false;
                }
                else
                {
                    setLatchingState(buttonID, true);
                    state = true;
                }
            }
            else
            {
                sendMIDI = false;
            }
        }

        if (sendMIDI)
        {
            sendMessage(buttonID, state, buttonMessage);
        }
        else if (buttonMessage == messageType_t::presetOpenDeck)
        {
            uint8_t preset = database.read(DB_BLOCK_BUTTONS, dbSection_buttons_midiID, buttonID);
            database.setPreset(preset);
        }
        else if (buttonMessage == messageType_t::customHook)
        {
            customHook(buttonID, state);
        }
    }

    cInfo.send(DB_BLOCK_BUTTONS, buttonID);
}

///
/// \brief Used to send MIDI message from specified button.
/// Used internally once the button state has been changed and processed.
/// @param [in] buttonID        Button ID which sends the message.
/// @param [in] state           Button state (true/pressed, false/released).
/// @param [in] buttonMessage   Type of MIDI message to send. If unspecified, message type is read from database.
///
void Buttons::sendMessage(uint8_t buttonID, bool state, messageType_t buttonMessage)
{
    uint8_t note = database.read(DB_BLOCK_BUTTONS, dbSection_buttons_midiID, buttonID);
    uint8_t channel = database.read(DB_BLOCK_BUTTONS, dbSection_buttons_midiChannel, buttonID);
    uint8_t velocity = database.read(DB_BLOCK_BUTTONS, dbSection_buttons_velocity, buttonID);
<commit_msg>change preset only on button press<commit_after>/*

Copyright 2015-2019 <NAME>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

#include "Buttons.h"
#include "board/Board.h"
#include "core/src/general/BitManipulation.h"

using namespace Interface::digital::input;

///
/// \brief Continuously reads inputs from buttons and acts if necessary.
///
void Buttons::update()
{
    for (int i = 0; i < MAX_NUMBER_OF_BUTTONS; i++)
    {
        if (database.read(DB_BLOCK_ENCODERS, dbSection_encoders_enable, Board::interface::digital::input::getEncoderPair(i)))
            continue;

        bool state = Board::interface::digital::input::getButtonState(i);

        if (!buttonDebounced(i, state))
            continue;

        processButton(i, state);
    }
}

///
/// \brief Handles changes in button states.
/// @param [in] buttonID    Button index which has changed state.
/// @param [in] state       Current button state.
///
void Buttons::processButton(uint8_t buttonID, bool state)
{
    //act on change of state only
    if (state == getButtonState(buttonID))
        return;

    setButtonState(buttonID, state);

    messageType_t buttonMessage = static_cast<messageType_t>(database.read(DB_BLOCK_BUTTONS, dbSection_buttons_midiMessage, buttonID));

    //don't process messageType_t::none type of message
    if (buttonMessage != messageType_t::none)
    {
        type_t type = static_cast<type_t>(database.read(DB_BLOCK_BUTTONS, dbSection_buttons_type, buttonID));

        bool sendMIDI = true;

        //overwrite type under certain conditions
        switch (buttonMessage)
        {
        case messageType_t::programChange:
        case messageType_t::programChangeInc:
        case messageType_t::programChangeDec:
        case messageType_t::mmcPlay:
        case messageType_t::mmcStop:
        case messageType_t::mmcPause:
        case messageType_t::controlChange:
        case messageType_t::realTimeClock:
        case messageType_t::realTimeStart:
        case messageType_t::realTimeContinue:
        case messageType_t::realTimeStop:
        case messageType_t::realTimeActiveSensing:
        case messageType_t::realTimeSystemReset:
            type = type_t::momentary;
            break;

        case messageType_t::mmcRecord:
            type = type_t::latching;
            break;

        case messageType_t::presetOpenDeck:
            type = type_t::momentary;
            sendMIDI = false;
            break;

        default:
            break;
        }

        if (type == type_t::latching)
        {
            //act on press only
            if (state)
            {
                if (getLatchingState(buttonID))
                {
                    setLatchingState(buttonID, false);
                    //overwrite before processing
                    state = false;
                }
                else
                {
                    setLatchingState(buttonID, true);
                    state = true;
                }
            }
            else
            {
                sendMIDI = false;
            }
        }

        if (sendMIDI)
        {
            sendMessage(buttonID, state, buttonMessage);
        }
        else if (buttonMessage == messageType_t::presetOpenDeck)
        {
            //change preset only on press
            if (state)
            {
                uint8_t preset = database.read(DB_BLOCK_BUTTONS, dbSection_buttons_midiID, buttonID);
                database.setPreset(preset);
            }
        }
        else if (buttonMessage == messageType_t::customHook)
        {
            customHook(buttonID, state);
        }
    }

    cInfo.send(DB_BLOCK_BUTTONS, buttonID);
}

///
/// \brief Used to send MIDI message from specified button.
/// Used internally once the button state has been changed and processed.
/// @param [in] buttonID        Button ID which sends the message.
/// @param [in] state           Button state (true/pressed, false/released).
/// @param [in] buttonMessage   Type of MIDI message to send. If unspecified, message type is read from database.
///
void Buttons::sendMessage(uint8_t buttonID, bool state, messageType_t buttonMessage)
{
    uint8_t note = database.read(DB_BLOCK_BUTTONS, dbSection_buttons_midiID, buttonID);
    uint8_t channel = database.read(DB_BLOCK_BUTTONS, dbSection_buttons_midiChannel, buttonID);
    uint8_t velocity = database.read(DB_BLOCK_BUTTONS, dbSection_buttons_velocity, buttonID);

{'fraction_non_alphanumeric': 0.08915365653245687, 'fraction_numerical': 0.0039030402629416597, 'mean_word_length': 2.351807228915663, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6645253', 'n_tokens_mistral': 2780, 'n_tokens_neox': 2671, 'n_words': 728}