Compare commits
34 Commits
ActiveSens
...
master
| Author | SHA1 | Date |
|---|---|---|
|
|
2d64cc3c2f | |
|
|
7c0d716641 | |
|
|
8f8c7cfcc6 | |
|
|
8e9805fc92 | |
|
|
1944aca891 | |
|
|
663b24b0b5 | |
|
|
be557c1f4b | |
|
|
50e33c8b4a | |
|
|
417beca1c7 | |
|
|
c9d3b9b592 | |
|
|
c7922927e5 | |
|
|
892f65a9ee | |
|
|
e1035a03f7 | |
|
|
2012e2a84a | |
|
|
b4daa697a9 | |
|
|
d9873560ad | |
|
|
bf80e99d54 | |
|
|
2f03d9b29d | |
|
|
d2f11d02e2 | |
|
|
9f5317f299 | |
|
|
f356c99ca2 | |
|
|
7ca289d84e | |
|
|
0d605dc8a7 | |
|
|
3f0a2d3fdb | |
|
|
d501f4bb3d | |
|
|
d9149d19df | |
|
|
a93fb27a1c | |
|
|
d967c0c389 | |
|
|
d3c361033d | |
|
|
33b294624a | |
|
|
10ef10bfde | |
|
|
da8ca5e69a | |
|
|
e292cf61b0 | |
|
|
150cecd450 |
|
|
@ -0,0 +1,66 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Report something that does not work as intended
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Before opening an issue, check if your problem already has been solved by looking in:
|
||||||
|
- The existing issues: https://github.com/FortySevenEffects/arduino_midi_library/issues
|
||||||
|
- The discussions: https://github.com/FortySevenEffects/arduino_midi_library/discussions
|
||||||
|
|
||||||
|
Consider opening a discussion instead of an issue if you need help with your project:
|
||||||
|
https://github.com/FortySevenEffects/arduino_midi_library/discussions/new
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
Please answer a few questions to help us understand your problem better and guide you to a solution:
|
||||||
|
|
||||||
|
<!-- Tip: place the letter x in the checkboxes to tick them:
|
||||||
|
- [ ] Unticked checkbox
|
||||||
|
- [x] Ticked checkbox
|
||||||
|
|
||||||
|
You can also tick them by clicking after you've submitted your issue.
|
||||||
|
-->
|
||||||
|
|
||||||
|
- What board are you using ?
|
||||||
|
- `example: Arduino Leonardo`
|
||||||
|
- _Please list any shields or other **relevant** hardware you're using_
|
||||||
|
- What version of the Arduino IDE are you using ?
|
||||||
|
- `example: 1.8.5`
|
||||||
|
- How are you using MIDI ?
|
||||||
|
- [ ] Hardware Serial (DIN plugs)
|
||||||
|
- [ ] USB
|
||||||
|
- [ ] Other (please specify)
|
||||||
|
- Is your problem related to:
|
||||||
|
- [ ] MIDI Input (reading messages from other devices)
|
||||||
|
- [ ] MIDI Output (sending messages to other devices)
|
||||||
|
- How comfortable are you with code ?
|
||||||
|
- [ ] Complete beginner
|
||||||
|
- [ ] I've done basic projects
|
||||||
|
- [ ] I know my way around C/C++
|
||||||
|
- [ ] Advanced / professional
|
||||||
|
|
||||||
|
## Describe your project and what you expect to happen:
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Example: When I press a switch on my pedalboard, it sends a SysEx message that I'd like to receive on my Arduino.
|
||||||
|
|
||||||
|
Note: Attachments (circuit diagrams, code examples) are most welcome and will help us understand your needs better and find a suitable solution for your issue.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Describe your problem (what does not work):
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Example: I cannot receive SysEx messages coming from my AxeFX 2
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Steps to reproduce
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Please list the steps you took to hit the problem, so we can try and reproduce it.
|
||||||
|
-->
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Discussions
|
||||||
|
url: https://github.com/FortySevenEffects/arduino_midi_library/discussions
|
||||||
|
about: Not a bug or a feature request ? Discuss your problem, ask for help or show what you've built in Discussions.
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: new feature
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
name: CMake
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||||
|
BUILD_TYPE: Debug
|
||||||
|
GENERATE_COVERAGE: true
|
||||||
|
LCOV_ROOT: ${{github.workspace}}/lcov
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
# The CMake configure and build commands are platform agnostic and should work equally
|
||||||
|
# well on Windows or Mac. You can convert this to a matrix build if you need
|
||||||
|
# cross-platform coverage.
|
||||||
|
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Install lcov
|
||||||
|
run: |
|
||||||
|
mkdir -p "$LCOV_ROOT"
|
||||||
|
wget https://github.com/linux-test-project/lcov/releases/download/v1.15/lcov-1.15.tar.gz --output-document="$LCOV_ROOT/lcov.tar.gz"
|
||||||
|
tar -xf "$LCOV_ROOT/lcov.tar.gz" --strip-components=1 -C "$LCOV_ROOT"
|
||||||
|
echo "$LCOV_ROOT/bin" >> $GITHUB_PATH
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Configure CMake
|
||||||
|
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||||
|
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||||
|
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILDER_ENABLE_PROFILING=true
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
# Build your program with the given configuration
|
||||||
|
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
||||||
|
|
||||||
|
- name: Run Unit Tests
|
||||||
|
working-directory: ${{github.workspace}}/build
|
||||||
|
run: ctest --verbose
|
||||||
|
|
||||||
|
- name: Generate code coverage report
|
||||||
|
working-directory: ${{github.workspace}}/build
|
||||||
|
run: |
|
||||||
|
lcov --directory . --capture --output-file coverage.info
|
||||||
|
lcov --remove coverage.info '/usr/*' "${{github.workspace}}/test/*" "${{github.workspace}}/external/*" --output-file coverage.info
|
||||||
|
lcov --list coverage.info
|
||||||
|
|
||||||
|
- uses: coverallsapp/github-action@9ba913c152ae4be1327bfb9085dc806cedb44057
|
||||||
|
name: Upload code coverage report to Coveralls
|
||||||
|
with:
|
||||||
|
path-to-lcov: ${{github.workspace}}/build/coverage.info
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
name: PlatformIO
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
platformio:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- AltPinSerial
|
||||||
|
- Basic_IO
|
||||||
|
- Bench
|
||||||
|
- Callbacks
|
||||||
|
- Chaining
|
||||||
|
- DualMerger
|
||||||
|
- ErrorCallback
|
||||||
|
- Input
|
||||||
|
- RPN_NRPN
|
||||||
|
- SimpleSynth
|
||||||
|
- CustomBaudRate
|
||||||
|
board:
|
||||||
|
- uno
|
||||||
|
- due
|
||||||
|
- zero
|
||||||
|
- leonardo
|
||||||
|
- micro
|
||||||
|
- nanoatmega328
|
||||||
|
- megaatmega2560
|
||||||
|
- teensy2
|
||||||
|
- teensy30
|
||||||
|
- teensy31
|
||||||
|
- teensylc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Cache pip
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ~/.cache/pip
|
||||||
|
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||||
|
restore-keys: ${{ runner.os }}-pip-
|
||||||
|
- name: Cache PlatformIO
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ~/.platformio
|
||||||
|
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
- name: Install PlatformIO
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install --upgrade platformio
|
||||||
|
pip install "click!=8.0.2" # See platformio/platformio-core#4078
|
||||||
|
- name: Run PlatformIO
|
||||||
|
run: pio ci --lib="." --board="${{matrix.board}}"
|
||||||
|
env:
|
||||||
|
PLATFORMIO_CI_SRC: examples/${{ matrix.example }}
|
||||||
104
.travis.yml
104
.travis.yml
|
|
@ -1,104 +0,0 @@
|
||||||
# Kudos to these guys:
|
|
||||||
# https://github.com/Return-To-The-Roots/s25client/blob/master/.travis.yml
|
|
||||||
# http://docs.platformio.org/en/stable/ci/travis.html
|
|
||||||
|
|
||||||
sudo: false
|
|
||||||
language: python
|
|
||||||
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
|
|
||||||
python:
|
|
||||||
- "2.7"
|
|
||||||
|
|
||||||
# Cache PlatformIO packages using Travis CI container-based infrastructure
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- "~/.platformio"
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- BUILD_TYPE=Debug
|
|
||||||
matrix:
|
|
||||||
- BUILD_UNIT_TESTS=1
|
|
||||||
- PLATFORMIO_CI_SRC=examples/Basic_IO
|
|
||||||
- PLATFORMIO_CI_SRC=examples/Bench
|
|
||||||
- PLATFORMIO_CI_SRC=examples/Callbacks
|
|
||||||
- PLATFORMIO_CI_SRC=examples/DualMerger
|
|
||||||
- PLATFORMIO_CI_SRC=examples/ErrorCallback
|
|
||||||
- PLATFORMIO_CI_SRC=examples/Input
|
|
||||||
- PLATFORMIO_CI_SRC=examples/RPN_NRPN
|
|
||||||
- PLATFORMIO_CI_SRC=examples/SimpleSynth
|
|
||||||
- PLATFORMIO_CI_SRC=examples/AltPinSerial
|
|
||||||
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
packages:
|
|
||||||
- g++-4.8
|
|
||||||
- cmake
|
|
||||||
|
|
||||||
install:
|
|
||||||
- |
|
|
||||||
if [ "${BUILD_UNIT_TESTS}" ]; then
|
|
||||||
# GCov 4.6 cannot handle the file structure
|
|
||||||
export CXX="g++-4.8"
|
|
||||||
export GCOV="gcov-4.8"
|
|
||||||
|
|
||||||
# Install newer lcov (1.9 seems to fail: http://gronlier.fr/blog/2015/01/adding-code-coverage-to-your-c-project/)
|
|
||||||
export LCOV_ROOT="$HOME/lcov"
|
|
||||||
mkdir -p "$LCOV_ROOT"
|
|
||||||
wget http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.14.orig.tar.gz --output-document="$LCOV_ROOT/lcov.tar.gz"
|
|
||||||
tar xf "$LCOV_ROOT/lcov.tar.gz" --strip-components=1 -C $LCOV_ROOT
|
|
||||||
export PATH="$LCOV_ROOT/bin:$PATH"
|
|
||||||
which lcov
|
|
||||||
|
|
||||||
# Install coveralls tool
|
|
||||||
gem install coveralls-lcov
|
|
||||||
export GENERATE_COVERAGE=1
|
|
||||||
else
|
|
||||||
# Install PlatformIO
|
|
||||||
pip install -U platformio
|
|
||||||
fi
|
|
||||||
|
|
||||||
script:
|
|
||||||
# Build unit tests & generate code coverage
|
|
||||||
- |
|
|
||||||
if [ "${BUILD_UNIT_TESTS}" ]; then
|
|
||||||
mkdir build && cd build
|
|
||||||
cmake -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DBUILDER_ENABLE_PROFILING=${GENERATE_COVERAGE} --generator="Unix Makefiles" ..
|
|
||||||
make all
|
|
||||||
ctest --verbose
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Build current example
|
|
||||||
- |
|
|
||||||
if [ ! "${BUILD_UNIT_TESTS}" ]; then
|
|
||||||
platformio ci --lib="." \
|
|
||||||
--board="uno" \
|
|
||||||
--board="due" \
|
|
||||||
--board="zero" \
|
|
||||||
--board="leonardo" \
|
|
||||||
--board="micro" \
|
|
||||||
--board="nanoatmega328" \
|
|
||||||
--board="megaatmega2560" \
|
|
||||||
--board="teensy2" \
|
|
||||||
--board="teensy30" \
|
|
||||||
--board="teensy31" \
|
|
||||||
--board="teensylc"
|
|
||||||
fi
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- |
|
|
||||||
if [ "${GENERATE_COVERAGE}" ]; then
|
|
||||||
# Generate code coverage information & send to Coveralls
|
|
||||||
rm -rf ./external/google-test/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.gcda
|
|
||||||
lcov --gcov-tool $GCOV --directory . --capture --output-file coverage.info
|
|
||||||
lcov --gcov-tool $GCOV --remove coverage.info 'test/*' '/usr/*' 'external/*' --output-file coverage.info
|
|
||||||
lcov --list coverage.info
|
|
||||||
coveralls-lcov --repo-token ${COVERALLS_TOKEN} coverage.info
|
|
||||||
fi
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
"string": "cpp",
|
"string": "cpp",
|
||||||
"string_view": "cpp",
|
"string_view": "cpp",
|
||||||
"vector": "cpp",
|
"vector": "cpp",
|
||||||
"istream": "cpp"
|
"istream": "cpp",
|
||||||
|
"system_error": "cpp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
14
README.md
14
README.md
|
|
@ -1,9 +1,10 @@
|
||||||
# Arduino MIDI Library
|
# Arduino MIDI Library
|
||||||
|
|
||||||
[](https://travis-ci.org/FortySevenEffects/arduino_midi_library)
|
|
||||||
[](https://coveralls.io/github/FortySevenEffects/arduino_midi_library)
|
|
||||||
[](https://github.com/FortySevenEffects/arduino_midi_library/releases/latest)
|
[](https://github.com/FortySevenEffects/arduino_midi_library/releases/latest)
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
|
[](https://github.com/FortySevenEffects/arduino_midi_library/actions/workflows/cmake.yml)
|
||||||
|
[](https://github.com/FortySevenEffects/arduino_midi_library/actions/workflows/platformio.yml)
|
||||||
|
[](https://coveralls.io/github/FortySevenEffects/arduino_midi_library)
|
||||||
|
|
||||||
This library adds MIDI I/O communications to an Arduino board.
|
This library adds MIDI I/O communications to an Arduino board.
|
||||||
|
|
||||||
|
|
@ -24,7 +25,7 @@ This library adds MIDI I/O communications to an Arduino board.
|
||||||
### Getting Started
|
### Getting Started
|
||||||
|
|
||||||
1. Use the Arduino Library Manager to install the library.
|
1. Use the Arduino Library Manager to install the library.
|
||||||

|

|
||||||
|
|
||||||
2. Start coding:
|
2. Start coding:
|
||||||
|
|
||||||
|
|
@ -111,9 +112,9 @@ protocol bridges.
|
||||||
|
|
||||||
- Software Thru is enabled by default on Serial, but not on other transports.
|
- Software Thru is enabled by default on Serial, but not on other transports.
|
||||||
|
|
||||||
## Contact
|
## Contact & Contribution
|
||||||
|
|
||||||
To report a bug, contribute, discuss on usage, or simply request support, please [create an issue here](https://github.com/FortySevenEffects/arduino_midi_library/issues/new).
|
To report a bug, contribute, discuss on usage, or request support, please [discuss it here](https://github.com/FortySevenEffects/arduino_midi_library/discussions/new).
|
||||||
|
|
||||||
You can also contact me on Twitter: [@fortysevenfx](https://twitter.com/fortysevenfx).
|
You can also contact me on Twitter: [@fortysevenfx](https://twitter.com/fortysevenfx).
|
||||||
|
|
||||||
|
|
@ -130,6 +131,9 @@ Special thanks to all who have contributed to this open-source project !
|
||||||
- [@LnnrtS](https://github.com/LnnrtS)
|
- [@LnnrtS](https://github.com/LnnrtS)
|
||||||
- [@DavidMenting](https://github.com/DavidMenting)
|
- [@DavidMenting](https://github.com/DavidMenting)
|
||||||
- [@Rolel](https://github.com/Rolel)
|
- [@Rolel](https://github.com/Rolel)
|
||||||
|
- [@kant](https://github.com/kant)
|
||||||
|
- [@paul-emile-element](https://github.com/paul-emile-element)
|
||||||
|
- [@muxa](https://github.com/muxa)
|
||||||
|
|
||||||
You want to help ? Check out the [contribution guidelines](./CONTRIBUTING.md).
|
You want to help ? Check out the [contribution guidelines](./CONTRIBUTING.md).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
// Examples
|
// Examples
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\example MIDI_Basic_IO.ino
|
\example Basic_IO.ino
|
||||||
This example shows how to perform simple input and output MIDI. \n
|
This example shows how to perform simple input and output MIDI. \n
|
||||||
\n
|
\n
|
||||||
When any message arrives to the Arduino, the LED is turned on,
|
When any message arrives to the Arduino, the LED is turned on,
|
||||||
|
|
@ -29,15 +29,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\example MIDI_Callbacks.ino
|
\example Callbacks.ino
|
||||||
This example shows how to use callbacks for easier MIDI input handling. \n
|
This example shows how to use callbacks for easier MIDI input handling. \n
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\example MIDI_Bench.ino
|
\example Bench.ino
|
||||||
\example MIDI_DualMerger.ino
|
\example DualMerger.ino
|
||||||
\example MIDI_Input.ino
|
\example Input.ino
|
||||||
\example MIDI_SimpleSynth.ino
|
\example SimpleSynth.ino
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ becomes:
|
||||||
```
|
```
|
||||||
|
|
||||||
The order of the bits in the "header" byte is reversed.
|
The order of the bits in the "header" byte is reversed.
|
||||||
To follow this beheaviour, set the inFlipHeaderBits argument to true.
|
To follow this behaviour, set the inFlipHeaderBits argument to true.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```c++
|
```c++
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// Here, when receiving any message on channel 4, the Arduino
|
// Here, when receiving any message on channel 4, the Arduino
|
||||||
// will blink a led and play back a note for 1 second.
|
// will blink a led and play back a note for 1 second.
|
||||||
|
|
||||||
#if defined(ARDUINO_SAM_DUE) || defined(SAMD_SERIES)
|
#if defined(ARDUINO_SAM_DUE) || defined(SAMD_SERIES) || defined(_VARIANT_ARDUINO_ZERO_)
|
||||||
/* example not relevant for this hardware (SoftwareSerial not supported) */
|
/* example not relevant for this hardware (SoftwareSerial not supported) */
|
||||||
MIDI_CREATE_DEFAULT_INSTANCE();
|
MIDI_CREATE_DEFAULT_INSTANCE();
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
#include <MIDI.h>
|
||||||
|
|
||||||
|
MIDI_CREATE_DEFAULT_INSTANCE();
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
pinMode(2, INPUT);
|
||||||
|
|
||||||
|
MIDI // chaining MIDI commands - order is from top to bottom (turnThruOff,... begin)
|
||||||
|
.turnThruOff()
|
||||||
|
// using a lamdba function for this callbacks
|
||||||
|
.setHandleNoteOn([](byte channel, byte note, byte velocity)
|
||||||
|
{
|
||||||
|
// Do whatever you want when a note is pressed.
|
||||||
|
|
||||||
|
// Try to keep your callbacks short (no delays ect)
|
||||||
|
// otherwise it would slow down the loop() and have a bad impact
|
||||||
|
// on real-time performance.
|
||||||
|
})
|
||||||
|
.setHandleNoteOff([](byte channel, byte note, byte velocity)
|
||||||
|
{
|
||||||
|
// Do something when the note is released.
|
||||||
|
// Note that NoteOn messages with 0 velocity are interpreted as NoteOffs.
|
||||||
|
})
|
||||||
|
.begin(MIDI_CHANNEL_OMNI); // Initiate MIDI communications, listen to all channels
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// Call MIDI.read the fastest you can for real-time performance.
|
||||||
|
MIDI.read();
|
||||||
|
|
||||||
|
if (digitalRead(2))
|
||||||
|
MIDI // chained sendNoteOn commands
|
||||||
|
.sendNoteOn(42, 127, 1)
|
||||||
|
.sendNoteOn(40, 54, 1);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include <MIDI.h>
|
||||||
|
|
||||||
|
// Override the default MIDI baudrate to
|
||||||
|
// a decoding program such as Hairless MIDI (set baudrate to 115200)
|
||||||
|
struct CustomBaudRateSettings : public MIDI_NAMESPACE::DefaultSerialSettings {
|
||||||
|
static const long BaudRate = 115200;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(ARDUINO_SAM_DUE) || defined(USBCON) || defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MKL26Z64__)
|
||||||
|
// Leonardo, Due and other USB boards use Serial1 by default.
|
||||||
|
MIDI_NAMESPACE::SerialMIDI<HardwareSerial, CustomBaudRateSettings> serialMIDI(Serial1);
|
||||||
|
MIDI_NAMESPACE::MidiInterface<MIDI_NAMESPACE::SerialMIDI<HardwareSerial, CustomBaudRateSettings>> MIDI((MIDI_NAMESPACE::SerialMIDI<HardwareSerial, CustomBaudRateSettings>&)serialMIDI);
|
||||||
|
#else
|
||||||
|
MIDI_NAMESPACE::SerialMIDI<HardwareSerial, CustomBaudRateSettings> serialMIDI(Serial);
|
||||||
|
MIDI_NAMESPACE::MidiInterface<MIDI_NAMESPACE::SerialMIDI<HardwareSerial, CustomBaudRateSettings>> MIDI((MIDI_NAMESPACE::SerialMIDI<HardwareSerial, CustomBaudRateSettings>&)serialMIDI);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
|
MIDI.begin(MIDI_CHANNEL_OMNI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (MIDI.read()) // If we have received a message
|
||||||
|
{
|
||||||
|
digitalWrite(LED_BUILTIN, HIGH);
|
||||||
|
MIDI.sendNoteOn(42, 127, 1); // Send a Note (pitch 42, velo 127 on channel 1)
|
||||||
|
delay(1000); // Wait for a second
|
||||||
|
MIDI.sendNoteOff(42, 0, 1); // Stop the note
|
||||||
|
digitalWrite(LED_BUILTIN, LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
#include <MIDI.h>
|
|
||||||
USING_NAMESPACE_MIDI
|
|
||||||
|
|
||||||
struct MySerialSettings : public MIDI_NAMESPACE::DefaultSerialSettings
|
|
||||||
{
|
|
||||||
static const long BaudRate = 115200;
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned long t1 = millis();
|
|
||||||
|
|
||||||
MIDI_NAMESPACE::SerialMIDI<HardwareSerial, MySerialSettings> serialMIDI(Serial1);
|
|
||||||
MIDI_NAMESPACE::MidiInterface<MIDI_NAMESPACE::SerialMIDI<HardwareSerial, MySerialSettings>> MIDI((MIDI_NAMESPACE::SerialMIDI<HardwareSerial, MySerialSettings>&)serialMIDI);
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
MIDI.begin(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
MIDI.read();
|
|
||||||
|
|
||||||
// send a note every second
|
|
||||||
if ((millis() - t1) > 1000)
|
|
||||||
{
|
|
||||||
t1 = millis();
|
|
||||||
|
|
||||||
MIDI.sendNoteOn(random(1, 127), 55, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
#include <MIDI.h>
|
|
||||||
USING_NAMESPACE_MIDI
|
|
||||||
|
|
||||||
struct MyMIDISettings : public MIDI_NAMESPACE::DefaultSettings
|
|
||||||
{
|
|
||||||
// When setting UseReceiverActiveSensing to true, MIDI.read() *must* be called
|
|
||||||
// as often as possible (1000 / SenderActiveSensingPeriodicity per second).
|
|
||||||
//
|
|
||||||
// setting UseReceiverActiveSensing to true, adds 174 bytes of code.
|
|
||||||
//
|
|
||||||
// (Taken from a Roland MIDI Implementation Owner's manual)
|
|
||||||
// Once an Active Sensing message is received, the unit will begin monitoring
|
|
||||||
// the interval between all subsequent messages. If there is an interval of 420 ms
|
|
||||||
// or longer between messages while monitoring is active, the same processing
|
|
||||||
// as when All Sound Off, All Notes Off,and Reset All Controllers messages are
|
|
||||||
// received will be carried out. The unit will then stopmonitoring the message interval.
|
|
||||||
|
|
||||||
static const bool UseReceiverActiveSensing = true;
|
|
||||||
|
|
||||||
static const uint16_t ReceiverActiveSensingTimeout = 420;
|
|
||||||
};
|
|
||||||
|
|
||||||
MIDI_CREATE_CUSTOM_INSTANCE(HardwareSerial, Serial1, MIDI, MyMIDISettings);
|
|
||||||
|
|
||||||
void activeSensingTimeoutExceptionHandler(bool active)
|
|
||||||
{
|
|
||||||
if (!active)
|
|
||||||
{
|
|
||||||
MIDI.sendControlChange(AllSoundOff, 0, 1);
|
|
||||||
MIDI.sendControlChange(AllNotesOff, 0, 1);
|
|
||||||
MIDI.sendControlChange(ResetAllControllers, 0, 1);
|
|
||||||
|
|
||||||
digitalWrite(LED_BUILTIN, HIGH);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
digitalWrite(LED_BUILTIN, LOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
pinMode(LED_BUILTIN, OUTPUT);
|
|
||||||
digitalWrite(LED_BUILTIN, LOW);
|
|
||||||
|
|
||||||
MIDI.setHandleActiveSensingTimeout(activeSensingTimeoutExceptionHandler);
|
|
||||||
MIDI.begin(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
MIDI.read();
|
|
||||||
}
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
#include <MIDI.h>
|
|
||||||
USING_NAMESPACE_MIDI
|
|
||||||
|
|
||||||
struct MyMIDISettings : public MIDI_NAMESPACE::DefaultSettings
|
|
||||||
{
|
|
||||||
// When setting UseSenderActiveSensing to true, MIDI.read() *must* be called
|
|
||||||
// as often as possible (1000 / SenderActiveSensingPeriodicity per second).
|
|
||||||
//
|
|
||||||
// setting UseSenderActiveSensing to true, adds 34 bytes of code.
|
|
||||||
//
|
|
||||||
// When using Active Sensing, call MIDI.read(); in the Arduino loop()
|
|
||||||
//
|
|
||||||
// from 'a' MIDI implementation manual: "Sent periodically"
|
|
||||||
// In the example here, a NoteOn is send every 1000ms (1s), ActiveSensing is
|
|
||||||
// send every 250ms after the last command.
|
|
||||||
// Logging the command will look like this:
|
|
||||||
//
|
|
||||||
// ...
|
|
||||||
// A.Sense FE
|
|
||||||
// A.Sense FE
|
|
||||||
// A.Sense FE
|
|
||||||
// NoteOn 90 04 37 [E-2]
|
|
||||||
// A.Sense FE
|
|
||||||
// A.Sense FE
|
|
||||||
// A.Sense FE
|
|
||||||
// NoteOn 90 04 37 [E-2]
|
|
||||||
// A.Sense FE
|
|
||||||
// A.Sense FE
|
|
||||||
// A.Sense FE
|
|
||||||
// NoteOn 90 04 37 [E-2]
|
|
||||||
// ...
|
|
||||||
|
|
||||||
static const bool UseSenderActiveSensing = true;
|
|
||||||
|
|
||||||
static const uint16_t SenderActiveSensingPeriodicity = 250;
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned long t1 = millis();
|
|
||||||
|
|
||||||
MIDI_CREATE_CUSTOM_INSTANCE(HardwareSerial, Serial1, MIDI, MyMIDISettings);
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
MIDI.begin(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
MIDI.read();
|
|
||||||
|
|
||||||
// send a note every second
|
|
||||||
if ((millis() - t1) > 1000)
|
|
||||||
{
|
|
||||||
t1 = millis();
|
|
||||||
|
|
||||||
MIDI.sendNoteOn(random(1, 127), 55, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
11
keywords.txt
11
keywords.txt
|
|
@ -146,7 +146,18 @@ GeneralPurposeController1 LITERAL1
|
||||||
GeneralPurposeController2 LITERAL1
|
GeneralPurposeController2 LITERAL1
|
||||||
GeneralPurposeController3 LITERAL1
|
GeneralPurposeController3 LITERAL1
|
||||||
GeneralPurposeController4 LITERAL1
|
GeneralPurposeController4 LITERAL1
|
||||||
|
BankSelectLSB LITERAL1
|
||||||
|
ModulationWheelLSB LITERAL1
|
||||||
|
BreathControllerLSB LITERAL1
|
||||||
|
FootControllerLSB LITERAL1
|
||||||
|
PortamentoTimeLSB LITERAL1
|
||||||
DataEntryLSB LITERAL1
|
DataEntryLSB LITERAL1
|
||||||
|
ChannelVolumeLSB LITERAL1
|
||||||
|
BalanceLSB LITERAL1
|
||||||
|
PanLSB LITERAL1
|
||||||
|
ExpressionControllerLSB LITERAL1
|
||||||
|
EffectControl1LSB LITERAL1
|
||||||
|
EffectControl2LSB LITERAL1
|
||||||
Sustain LITERAL1
|
Sustain LITERAL1
|
||||||
Portamento LITERAL1
|
Portamento LITERAL1
|
||||||
Sostenuto LITERAL1
|
Sostenuto LITERAL1
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 72 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
137
src/MIDI.h
137
src/MIDI.h
|
|
@ -62,94 +62,94 @@ public:
|
||||||
inline ~MidiInterface();
|
inline ~MidiInterface();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void begin(Channel inChannel = 1);
|
MidiInterface& begin(Channel inChannel = 1);
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// MIDI Output
|
// MIDI Output
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline void sendNoteOn(DataByte inNoteNumber,
|
inline MidiInterface& sendNoteOn(DataByte inNoteNumber,
|
||||||
DataByte inVelocity,
|
DataByte inVelocity,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
|
|
||||||
inline void sendNoteOff(DataByte inNoteNumber,
|
inline MidiInterface& sendNoteOff(DataByte inNoteNumber,
|
||||||
DataByte inVelocity,
|
DataByte inVelocity,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
|
|
||||||
inline void sendProgramChange(DataByte inProgramNumber,
|
inline MidiInterface& sendProgramChange(DataByte inProgramNumber,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
|
|
||||||
inline void sendControlChange(DataByte inControlNumber,
|
inline MidiInterface& sendControlChange(DataByte inControlNumber,
|
||||||
DataByte inControlValue,
|
DataByte inControlValue,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
|
|
||||||
inline void sendPitchBend(int inPitchValue, Channel inChannel);
|
inline MidiInterface& sendPitchBend(int inPitchValue, Channel inChannel);
|
||||||
inline void sendPitchBend(double inPitchValue, Channel inChannel);
|
inline MidiInterface& sendPitchBend(double inPitchValue, Channel inChannel);
|
||||||
|
|
||||||
inline void sendPolyPressure(DataByte inNoteNumber,
|
inline MidiInterface& sendPolyPressure(DataByte inNoteNumber,
|
||||||
DataByte inPressure,
|
DataByte inPressure,
|
||||||
Channel inChannel) __attribute__ ((deprecated));
|
Channel inChannel) __attribute__ ((deprecated));
|
||||||
|
|
||||||
inline void sendAfterTouch(DataByte inPressure,
|
inline MidiInterface& sendAfterTouch(DataByte inPressure,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
inline void sendAfterTouch(DataByte inNoteNumber,
|
inline MidiInterface& sendAfterTouch(DataByte inNoteNumber,
|
||||||
DataByte inPressure,
|
DataByte inPressure,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
|
|
||||||
inline void sendSysEx(unsigned inLength,
|
inline MidiInterface& sendSysEx(unsigned inLength,
|
||||||
const byte* inArray,
|
const byte* inArray,
|
||||||
bool inArrayContainsBoundaries = false);
|
bool inArrayContainsBoundaries = false);
|
||||||
|
|
||||||
inline void sendTimeCodeQuarterFrame(DataByte inTypeNibble,
|
inline MidiInterface& sendTimeCodeQuarterFrame(DataByte inTypeNibble,
|
||||||
DataByte inValuesNibble);
|
DataByte inValuesNibble);
|
||||||
inline void sendTimeCodeQuarterFrame(DataByte inData);
|
inline MidiInterface& sendTimeCodeQuarterFrame(DataByte inData);
|
||||||
|
|
||||||
inline void sendSongPosition(unsigned inBeats);
|
inline MidiInterface& sendSongPosition(unsigned inBeats);
|
||||||
inline void sendSongSelect(DataByte inSongNumber);
|
inline MidiInterface& sendSongSelect(DataByte inSongNumber);
|
||||||
inline void sendTuneRequest();
|
inline MidiInterface& sendTuneRequest();
|
||||||
|
|
||||||
inline void sendCommon(MidiType inType, unsigned = 0);
|
inline MidiInterface& sendCommon(MidiType inType, unsigned = 0);
|
||||||
|
|
||||||
inline void sendClock() { sendRealTime(Clock); };
|
inline MidiInterface& sendClock() { return sendRealTime(Clock); };
|
||||||
inline void sendStart() { sendRealTime(Start); };
|
inline MidiInterface& sendStart() { return sendRealTime(Start); };
|
||||||
inline void sendStop() { sendRealTime(Stop); };
|
inline MidiInterface& sendStop() { return sendRealTime(Stop); };
|
||||||
inline void sendTick() { sendRealTime(Tick); };
|
inline MidiInterface& sendTick() { return sendRealTime(Tick); };
|
||||||
inline void sendContinue() { sendRealTime(Continue); };
|
inline MidiInterface& sendContinue() { return sendRealTime(Continue); };
|
||||||
inline void sendActiveSensing() { sendRealTime(ActiveSensing); };
|
inline MidiInterface& sendActiveSensing() { return sendRealTime(ActiveSensing); };
|
||||||
inline void sendSystemReset() { sendRealTime(SystemReset); };
|
inline MidiInterface& sendSystemReset() { return sendRealTime(SystemReset); };
|
||||||
|
|
||||||
inline void sendRealTime(MidiType inType);
|
inline MidiInterface& sendRealTime(MidiType inType);
|
||||||
|
|
||||||
inline void beginRpn(unsigned inNumber,
|
inline MidiInterface& beginRpn(unsigned inNumber,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
inline void sendRpnValue(unsigned inValue,
|
inline MidiInterface& sendRpnValue(unsigned inValue,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
inline void sendRpnValue(byte inMsb,
|
inline MidiInterface& sendRpnValue(byte inMsb,
|
||||||
byte inLsb,
|
byte inLsb,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
inline void sendRpnIncrement(byte inAmount,
|
inline MidiInterface& sendRpnIncrement(byte inAmount,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
inline void sendRpnDecrement(byte inAmount,
|
inline MidiInterface& sendRpnDecrement(byte inAmount,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
inline void endRpn(Channel inChannel);
|
inline MidiInterface& endRpn(Channel inChannel);
|
||||||
|
|
||||||
inline void beginNrpn(unsigned inNumber,
|
inline MidiInterface& beginNrpn(unsigned inNumber,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
inline void sendNrpnValue(unsigned inValue,
|
inline MidiInterface& sendNrpnValue(unsigned inValue,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
inline void sendNrpnValue(byte inMsb,
|
inline MidiInterface& sendNrpnValue(byte inMsb,
|
||||||
byte inLsb,
|
byte inLsb,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
inline void sendNrpnIncrement(byte inAmount,
|
inline MidiInterface& sendNrpnIncrement(byte inAmount,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
inline void sendNrpnDecrement(byte inAmount,
|
inline MidiInterface& sendNrpnDecrement(byte inAmount,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
inline void endNrpn(Channel inChannel);
|
inline MidiInterface& endNrpn(Channel inChannel);
|
||||||
|
|
||||||
inline void send(const MidiMessage&);
|
inline MidiInterface& send(const MidiMessage&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void send(MidiType inType,
|
MidiInterface& send(MidiType inType,
|
||||||
DataByte inData1,
|
DataByte inData1,
|
||||||
DataByte inData2,
|
DataByte inData2,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
|
|
@ -172,7 +172,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline Channel getInputChannel() const;
|
inline Channel getInputChannel() const;
|
||||||
inline void setInputChannel(Channel inChannel);
|
inline MidiInterface& setInputChannel(Channel inChannel);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static inline MidiType getTypeFromStatusByte(byte inStatus);
|
static inline MidiType getTypeFromStatusByte(byte inStatus);
|
||||||
|
|
@ -183,37 +183,35 @@ public:
|
||||||
// Input Callbacks
|
// Input Callbacks
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline void setHandleMessage(void (*fptr)(const MidiMessage&)) { mMessageCallback = fptr; };
|
inline MidiInterface& setHandleMessage(void (*fptr)(const MidiMessage&)) { mMessageCallback = fptr; return *this; };
|
||||||
inline void setHandleError(ErrorCallback fptr) { mErrorCallback = fptr; }
|
inline MidiInterface& setHandleError(ErrorCallback fptr) { mErrorCallback = fptr; return *this; };
|
||||||
inline void setHandleActiveSensingTimeout(ActiveSensingTimeoutCallback fptr) { mActiveSensingTimeoutCallback = fptr; }
|
inline MidiInterface& setHandleNoteOff(NoteOffCallback fptr) { mNoteOffCallback = fptr; return *this; };
|
||||||
inline void setHandleNoteOff(NoteOffCallback fptr) { mNoteOffCallback = fptr; }
|
inline MidiInterface& setHandleNoteOn(NoteOnCallback fptr) { mNoteOnCallback = fptr; return *this; };
|
||||||
inline void setHandleNoteOn(NoteOnCallback fptr) { mNoteOnCallback = fptr; }
|
inline MidiInterface& setHandleAfterTouchPoly(AfterTouchPolyCallback fptr) { mAfterTouchPolyCallback = fptr; return *this; };
|
||||||
inline void setHandleAfterTouchPoly(AfterTouchPolyCallback fptr) { mAfterTouchPolyCallback = fptr; }
|
inline MidiInterface& setHandleControlChange(ControlChangeCallback fptr) { mControlChangeCallback = fptr; return *this; };
|
||||||
inline void setHandleControlChange(ControlChangeCallback fptr) { mControlChangeCallback = fptr; }
|
inline MidiInterface& setHandleProgramChange(ProgramChangeCallback fptr) { mProgramChangeCallback = fptr; return *this; };
|
||||||
inline void setHandleProgramChange(ProgramChangeCallback fptr) { mProgramChangeCallback = fptr; }
|
inline MidiInterface& setHandleAfterTouchChannel(AfterTouchChannelCallback fptr) { mAfterTouchChannelCallback = fptr; return *this; };
|
||||||
inline void setHandleAfterTouchChannel(AfterTouchChannelCallback fptr) { mAfterTouchChannelCallback = fptr; }
|
inline MidiInterface& setHandlePitchBend(PitchBendCallback fptr) { mPitchBendCallback = fptr; return *this; };
|
||||||
inline void setHandlePitchBend(PitchBendCallback fptr) { mPitchBendCallback = fptr; }
|
inline MidiInterface& setHandleSystemExclusive(SystemExclusiveCallback fptr) { mSystemExclusiveCallback = fptr; return *this; };
|
||||||
inline void setHandleSystemExclusive(SystemExclusiveCallback fptr) { mSystemExclusiveCallback = fptr; }
|
inline MidiInterface& setHandleTimeCodeQuarterFrame(TimeCodeQuarterFrameCallback fptr) { mTimeCodeQuarterFrameCallback = fptr; return *this; };
|
||||||
inline void setHandleTimeCodeQuarterFrame(TimeCodeQuarterFrameCallback fptr) { mTimeCodeQuarterFrameCallback = fptr; }
|
inline MidiInterface& setHandleSongPosition(SongPositionCallback fptr) { mSongPositionCallback = fptr; return *this; };
|
||||||
inline void setHandleSongPosition(SongPositionCallback fptr) { mSongPositionCallback = fptr; }
|
inline MidiInterface& setHandleSongSelect(SongSelectCallback fptr) { mSongSelectCallback = fptr; return *this; };
|
||||||
inline void setHandleSongSelect(SongSelectCallback fptr) { mSongSelectCallback = fptr; }
|
inline MidiInterface& setHandleTuneRequest(TuneRequestCallback fptr) { mTuneRequestCallback = fptr; return *this; };
|
||||||
inline void setHandleTuneRequest(TuneRequestCallback fptr) { mTuneRequestCallback = fptr; }
|
inline MidiInterface& setHandleClock(ClockCallback fptr) { mClockCallback = fptr; return *this; };
|
||||||
inline void setHandleClock(ClockCallback fptr) { mClockCallback = fptr; }
|
inline MidiInterface& setHandleStart(StartCallback fptr) { mStartCallback = fptr; return *this; };
|
||||||
inline void setHandleStart(StartCallback fptr) { mStartCallback = fptr; }
|
inline MidiInterface& setHandleTick(TickCallback fptr) { mTickCallback = fptr; return *this; };
|
||||||
inline void setHandleTick(TickCallback fptr) { mTickCallback = fptr; }
|
inline MidiInterface& setHandleContinue(ContinueCallback fptr) { mContinueCallback = fptr; return *this; };
|
||||||
inline void setHandleContinue(ContinueCallback fptr) { mContinueCallback = fptr; }
|
inline MidiInterface& setHandleStop(StopCallback fptr) { mStopCallback = fptr; return *this; };
|
||||||
inline void setHandleStop(StopCallback fptr) { mStopCallback = fptr; }
|
inline MidiInterface& setHandleActiveSensing(ActiveSensingCallback fptr) { mActiveSensingCallback = fptr; return *this; };
|
||||||
inline void setHandleActiveSensing(ActiveSensingCallback fptr) { mActiveSensingCallback = fptr; }
|
inline MidiInterface& setHandleSystemReset(SystemResetCallback fptr) { mSystemResetCallback = fptr; return *this; };
|
||||||
inline void setHandleSystemReset(SystemResetCallback fptr) { mSystemResetCallback = fptr; }
|
|
||||||
|
|
||||||
inline void disconnectCallbackFromType(MidiType inType);
|
inline MidiInterface& disconnectCallbackFromType(MidiType inType);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void launchCallback();
|
void launchCallback();
|
||||||
|
|
||||||
void (*mMessageCallback)(const MidiMessage& message) = nullptr;
|
void (*mMessageCallback)(const MidiMessage& message) = nullptr;
|
||||||
ErrorCallback mErrorCallback = nullptr;
|
ErrorCallback mErrorCallback = nullptr;
|
||||||
ActiveSensingTimeoutCallback mActiveSensingTimeoutCallback = nullptr;
|
|
||||||
NoteOffCallback mNoteOffCallback = nullptr;
|
NoteOffCallback mNoteOffCallback = nullptr;
|
||||||
NoteOnCallback mNoteOnCallback = nullptr;
|
NoteOnCallback mNoteOnCallback = nullptr;
|
||||||
AfterTouchPolyCallback mAfterTouchPolyCallback = nullptr;
|
AfterTouchPolyCallback mAfterTouchPolyCallback = nullptr;
|
||||||
|
|
@ -241,9 +239,9 @@ public:
|
||||||
inline Thru::Mode getFilterMode() const;
|
inline Thru::Mode getFilterMode() const;
|
||||||
inline bool getThruState() const;
|
inline bool getThruState() const;
|
||||||
|
|
||||||
inline void turnThruOn(Thru::Mode inThruFilterMode = Thru::Full);
|
inline MidiInterface& turnThruOn(Thru::Mode inThruFilterMode = Thru::Full);
|
||||||
inline void turnThruOff();
|
inline MidiInterface& turnThruOff();
|
||||||
inline void setThruFilterMode(Thru::Mode inThruFilterMode);
|
inline MidiInterface& setThruFilterMode(Thru::Mode inThruFilterMode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void thruFilter(byte inChannel);
|
void thruFilter(byte inChannel);
|
||||||
|
|
@ -256,7 +254,7 @@ private:
|
||||||
inline void handleNullVelocityNoteOnAsNoteOff();
|
inline void handleNullVelocityNoteOnAsNoteOff();
|
||||||
inline bool inputFilter(Channel inChannel);
|
inline bool inputFilter(Channel inChannel);
|
||||||
inline void resetInput();
|
inline void resetInput();
|
||||||
inline void UpdateLastSentTime();
|
inline void updateLastSentTime();
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Transport
|
// Transport
|
||||||
|
|
@ -284,7 +282,8 @@ private:
|
||||||
MidiMessage mMessage;
|
MidiMessage mMessage;
|
||||||
unsigned long mLastMessageSentTime;
|
unsigned long mLastMessageSentTime;
|
||||||
unsigned long mLastMessageReceivedTime;
|
unsigned long mLastMessageReceivedTime;
|
||||||
bool mReceiverActiveSensingActive;
|
unsigned long mSenderActiveSensingPeriodicity;
|
||||||
|
bool mReceiverActiveSensingActivated;
|
||||||
int8_t mLastError;
|
int8_t mLastError;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
280
src/MIDI.hpp
280
src/MIDI.hpp
|
|
@ -44,10 +44,11 @@ inline MidiInterface<Transport, Settings, Platform>::MidiInterface(Transport& in
|
||||||
, mThruFilterMode(Thru::Full)
|
, mThruFilterMode(Thru::Full)
|
||||||
, mLastMessageSentTime(0)
|
, mLastMessageSentTime(0)
|
||||||
, mLastMessageReceivedTime(0)
|
, mLastMessageReceivedTime(0)
|
||||||
, mReceiverActiveSensingActive(false)
|
, mSenderActiveSensingPeriodicity(0)
|
||||||
|
, mReceiverActiveSensingActivated(false)
|
||||||
, mLastError(0)
|
, mLastError(0)
|
||||||
{
|
{
|
||||||
static_assert(!(Settings::UseSenderActiveSensing && Settings::UseReceiverActiveSensing), "UseSenderActiveSensing and UseReceiverActiveSensing can't be both set to true.");
|
mSenderActiveSensingPeriodicity = Settings::SenderActiveSensingPeriodicity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Destructor for MidiInterface.
|
/*! \brief Destructor for MidiInterface.
|
||||||
|
|
@ -68,7 +69,7 @@ inline MidiInterface<Transport, Settings, Platform>::~MidiInterface()
|
||||||
- Full thru mirroring
|
- Full thru mirroring
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::begin(Channel inChannel)
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::begin(Channel inChannel)
|
||||||
{
|
{
|
||||||
// Initialise the Transport layer
|
// Initialise the Transport layer
|
||||||
mTransport.begin();
|
mTransport.begin();
|
||||||
|
|
@ -83,8 +84,7 @@ void MidiInterface<Transport, Settings, Platform>::begin(Channel inChannel)
|
||||||
mCurrentRpnNumber = 0xffff;
|
mCurrentRpnNumber = 0xffff;
|
||||||
mCurrentNrpnNumber = 0xffff;
|
mCurrentNrpnNumber = 0xffff;
|
||||||
|
|
||||||
mLastMessageSentTime =
|
mLastMessageSentTime = Platform::now();
|
||||||
mLastMessageReceivedTime = Platform::now();
|
|
||||||
|
|
||||||
mMessage.valid = false;
|
mMessage.valid = false;
|
||||||
mMessage.type = InvalidType;
|
mMessage.type = InvalidType;
|
||||||
|
|
@ -95,6 +95,8 @@ void MidiInterface<Transport, Settings, Platform>::begin(Channel inChannel)
|
||||||
|
|
||||||
mThruFilterMode = Thru::Full;
|
mThruFilterMode = Thru::Full;
|
||||||
mThruActivated = mTransport.thruActivated;
|
mThruActivated = mTransport.thruActivated;
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
@ -115,33 +117,38 @@ void MidiInterface<Transport, Settings, Platform>::begin(Channel inChannel)
|
||||||
them thru.
|
them thru.
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::send(const MidiMessage& inMessage)
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::send(const MidiMessage& inMessage)
|
||||||
{
|
{
|
||||||
if (!inMessage.valid)
|
if (!inMessage.valid)
|
||||||
return;
|
return *this;
|
||||||
|
|
||||||
if (mTransport.beginTransmission(inMessage.type))
|
if (mTransport.beginTransmission(inMessage.type))
|
||||||
{
|
{
|
||||||
const StatusByte status = getStatus(inMessage.type, inMessage.channel);
|
if (inMessage.isSystemRealTime())
|
||||||
mTransport.write(status);
|
|
||||||
|
|
||||||
if (inMessage.type != MidiType::SystemExclusive)
|
|
||||||
{
|
{
|
||||||
|
mTransport.write(inMessage.type);
|
||||||
|
} else if (inMessage.isChannelMessage())
|
||||||
|
{
|
||||||
|
const StatusByte status = getStatus(inMessage.type, inMessage.channel);
|
||||||
|
mTransport.write(status);
|
||||||
if (inMessage.length > 1) mTransport.write(inMessage.data1);
|
if (inMessage.length > 1) mTransport.write(inMessage.data1);
|
||||||
if (inMessage.length > 2) mTransport.write(inMessage.data2);
|
if (inMessage.length > 2) mTransport.write(inMessage.data2);
|
||||||
} else
|
} else if (inMessage.type == MidiType::SystemExclusive)
|
||||||
{
|
{
|
||||||
// sysexArray does not contain the start and end tags
|
const unsigned size = inMessage.getSysExSize();
|
||||||
mTransport.write(MidiType::SystemExclusiveStart);
|
for (size_t i = 0; i < size; i++)
|
||||||
|
|
||||||
for (size_t i = 0; i < inMessage.getSysExSize(); i++)
|
|
||||||
mTransport.write(inMessage.sysexArray[i]);
|
mTransport.write(inMessage.sysexArray[i]);
|
||||||
|
} else // at this point, it it assumed to be a system common message
|
||||||
mTransport.write(MidiType::SystemExclusiveEnd);
|
{
|
||||||
|
mTransport.write(inMessage.type);
|
||||||
|
if (inMessage.length > 1) mTransport.write(inMessage.data1);
|
||||||
|
if (inMessage.length > 2) mTransport.write(inMessage.data2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mTransport.endTransmission();
|
mTransport.endTransmission();
|
||||||
UpdateLastSentTime();
|
updateLastSentTime();
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -157,7 +164,7 @@ void MidiInterface<Transport, Settings, Platform>::send(const MidiMessage& inMes
|
||||||
from your code, at your own risks.
|
from your code, at your own risks.
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::send(MidiType inType,
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::send(MidiType inType,
|
||||||
DataByte inData1,
|
DataByte inData1,
|
||||||
DataByte inData2,
|
DataByte inData2,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
|
|
@ -169,7 +176,7 @@ void MidiInterface<Transport, Settings, Platform>::send(MidiType inType,
|
||||||
inChannel == MIDI_CHANNEL_OMNI ||
|
inChannel == MIDI_CHANNEL_OMNI ||
|
||||||
inType < 0x80)
|
inType < 0x80)
|
||||||
{
|
{
|
||||||
return; // Don't send anything
|
return *this; // Don't send anything
|
||||||
}
|
}
|
||||||
// Protection: remove MSBs on data
|
// Protection: remove MSBs on data
|
||||||
inData1 &= 0x7f;
|
inData1 &= 0x7f;
|
||||||
|
|
@ -202,13 +209,15 @@ void MidiInterface<Transport, Settings, Platform>::send(MidiType inType,
|
||||||
}
|
}
|
||||||
|
|
||||||
mTransport.endTransmission();
|
mTransport.endTransmission();
|
||||||
UpdateLastSentTime();
|
updateLastSentTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (inType >= Clock && inType <= SystemReset)
|
else if (inType >= Clock && inType <= SystemReset)
|
||||||
{
|
{
|
||||||
sendRealTime(inType); // System Real-time and 1 byte.
|
sendRealTime(inType); // System Real-time and 1 byte.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
@ -223,11 +232,11 @@ void MidiInterface<Transport, Settings, Platform>::send(MidiType inType,
|
||||||
http://www.phys.unsw.edu.au/jw/notes.html
|
http://www.phys.unsw.edu.au/jw/notes.html
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendNoteOn(DataByte inNoteNumber,
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendNoteOn(DataByte inNoteNumber,
|
||||||
DataByte inVelocity,
|
DataByte inVelocity,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
send(NoteOn, inNoteNumber, inVelocity, inChannel);
|
return send(NoteOn, inNoteNumber, inVelocity, inChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Note Off message
|
/*! \brief Send a Note Off message
|
||||||
|
|
@ -242,11 +251,11 @@ void MidiInterface<Transport, Settings, Platform>::sendNoteOn(DataByte inNoteNum
|
||||||
http://www.phys.unsw.edu.au/jw/notes.html
|
http://www.phys.unsw.edu.au/jw/notes.html
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendNoteOff(DataByte inNoteNumber,
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendNoteOff(DataByte inNoteNumber,
|
||||||
DataByte inVelocity,
|
DataByte inVelocity,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
send(NoteOff, inNoteNumber, inVelocity, inChannel);
|
return send(NoteOff, inNoteNumber, inVelocity, inChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Program Change message
|
/*! \brief Send a Program Change message
|
||||||
|
|
@ -254,10 +263,10 @@ void MidiInterface<Transport, Settings, Platform>::sendNoteOff(DataByte inNoteNu
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendProgramChange(DataByte inProgramNumber,
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendProgramChange(DataByte inProgramNumber,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
send(ProgramChange, inProgramNumber, 0, inChannel);
|
return send(ProgramChange, inProgramNumber, 0, inChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Control Change message
|
/*! \brief Send a Control Change message
|
||||||
|
|
@ -267,11 +276,11 @@ void MidiInterface<Transport, Settings, Platform>::sendProgramChange(DataByte in
|
||||||
@see MidiControlChangeNumber
|
@see MidiControlChangeNumber
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendControlChange(DataByte inControlNumber,
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendControlChange(DataByte inControlNumber,
|
||||||
DataByte inControlValue,
|
DataByte inControlValue,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
send(ControlChange, inControlNumber, inControlValue, inChannel);
|
return send(ControlChange, inControlNumber, inControlValue, inChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Polyphonic AfterTouch message (applies to a specified note)
|
/*! \brief Send a Polyphonic AfterTouch message (applies to a specified note)
|
||||||
|
|
@ -282,11 +291,11 @@ void MidiInterface<Transport, Settings, Platform>::sendControlChange(DataByte in
|
||||||
library, @see sendAfterTouch to send polyphonic and monophonic AfterTouch messages.
|
library, @see sendAfterTouch to send polyphonic and monophonic AfterTouch messages.
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendPolyPressure(DataByte inNoteNumber,
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendPolyPressure(DataByte inNoteNumber,
|
||||||
DataByte inPressure,
|
DataByte inPressure,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
send(AfterTouchPoly, inNoteNumber, inPressure, inChannel);
|
return send(AfterTouchPoly, inNoteNumber, inPressure, inChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a MonoPhonic AfterTouch message (applies to all notes)
|
/*! \brief Send a MonoPhonic AfterTouch message (applies to all notes)
|
||||||
|
|
@ -294,10 +303,10 @@ void MidiInterface<Transport, Settings, Platform>::sendPolyPressure(DataByte inN
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendAfterTouch(DataByte inPressure,
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendAfterTouch(DataByte inPressure,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
send(AfterTouchChannel, inPressure, 0, inChannel);
|
return send(AfterTouchChannel, inPressure, 0, inChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Polyphonic AfterTouch message (applies to a specified note)
|
/*! \brief Send a Polyphonic AfterTouch message (applies to a specified note)
|
||||||
|
|
@ -307,11 +316,11 @@ void MidiInterface<Transport, Settings, Platform>::sendAfterTouch(DataByte inPre
|
||||||
@see Replaces sendPolyPressure (which is now deprecated).
|
@see Replaces sendPolyPressure (which is now deprecated).
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendAfterTouch(DataByte inNoteNumber,
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendAfterTouch(DataByte inNoteNumber,
|
||||||
DataByte inPressure,
|
DataByte inPressure,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
send(AfterTouchPoly, inNoteNumber, inPressure, inChannel);
|
return send(AfterTouchPoly, inNoteNumber, inPressure, inChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Pitch Bend message using a signed integer value.
|
/*! \brief Send a Pitch Bend message using a signed integer value.
|
||||||
|
|
@ -321,11 +330,11 @@ void MidiInterface<Transport, Settings, Platform>::sendAfterTouch(DataByte inNot
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendPitchBend(int inPitchValue,
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendPitchBend(int inPitchValue,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
const unsigned bend = unsigned(inPitchValue - int(MIDI_PITCHBEND_MIN));
|
const unsigned bend = unsigned(inPitchValue - int(MIDI_PITCHBEND_MIN));
|
||||||
send(PitchBend, (bend & 0x7f), (bend >> 7) & 0x7f, inChannel);
|
return send(PitchBend, (bend & 0x7f), (bend >> 7) & 0x7f, inChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -336,12 +345,12 @@ void MidiInterface<Transport, Settings, Platform>::sendPitchBend(int inPitchValu
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendPitchBend(double inPitchValue,
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendPitchBend(double inPitchValue,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
const int scale = inPitchValue > 0.0 ? MIDI_PITCHBEND_MAX : MIDI_PITCHBEND_MIN;
|
const int scale = inPitchValue > 0.0 ? MIDI_PITCHBEND_MAX : - MIDI_PITCHBEND_MIN;
|
||||||
const int value = int(inPitchValue * double(scale));
|
const int value = int(inPitchValue * double(scale));
|
||||||
sendPitchBend(value, inChannel);
|
return sendPitchBend(value, inChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Generate and send a System Exclusive frame.
|
/*! \brief Generate and send a System Exclusive frame.
|
||||||
|
|
@ -354,7 +363,7 @@ void MidiInterface<Transport, Settings, Platform>::sendPitchBend(double inPitchV
|
||||||
with previous versions of the library.
|
with previous versions of the library.
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendSysEx(unsigned inLength,
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendSysEx(unsigned inLength,
|
||||||
const byte* inArray,
|
const byte* inArray,
|
||||||
bool inArrayContainsBoundaries)
|
bool inArrayContainsBoundaries)
|
||||||
{
|
{
|
||||||
|
|
@ -372,11 +381,13 @@ void MidiInterface<Transport, Settings, Platform>::sendSysEx(unsigned inLength,
|
||||||
mTransport.write(MidiType::SystemExclusiveEnd);
|
mTransport.write(MidiType::SystemExclusiveEnd);
|
||||||
|
|
||||||
mTransport.endTransmission();
|
mTransport.endTransmission();
|
||||||
UpdateLastSentTime();
|
updateLastSentTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::UseRunningStatus)
|
if (Settings::UseRunningStatus)
|
||||||
mRunningStatus_TX = InvalidType;
|
mRunningStatus_TX = InvalidType;
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Tune Request message.
|
/*! \brief Send a Tune Request message.
|
||||||
|
|
@ -385,9 +396,9 @@ void MidiInterface<Transport, Settings, Platform>::sendSysEx(unsigned inLength,
|
||||||
it should tune its oscillators (if equipped with any).
|
it should tune its oscillators (if equipped with any).
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendTuneRequest()
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendTuneRequest()
|
||||||
{
|
{
|
||||||
sendCommon(TuneRequest);
|
return sendCommon(TuneRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a MIDI Time Code Quarter Frame.
|
/*! \brief Send a MIDI Time Code Quarter Frame.
|
||||||
|
|
@ -397,11 +408,11 @@ void MidiInterface<Transport, Settings, Platform>::sendTuneRequest()
|
||||||
See MIDI Specification for more information.
|
See MIDI Specification for more information.
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendTimeCodeQuarterFrame(DataByte inTypeNibble,
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendTimeCodeQuarterFrame(DataByte inTypeNibble,
|
||||||
DataByte inValuesNibble)
|
DataByte inValuesNibble)
|
||||||
{
|
{
|
||||||
const byte data = byte((((inTypeNibble & 0x07) << 4) | (inValuesNibble & 0x0f)));
|
const byte data = byte((((inTypeNibble & 0x07) << 4) | (inValuesNibble & 0x0f)));
|
||||||
sendTimeCodeQuarterFrame(data);
|
return sendTimeCodeQuarterFrame(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a MIDI Time Code Quarter Frame.
|
/*! \brief Send a MIDI Time Code Quarter Frame.
|
||||||
|
|
@ -411,25 +422,25 @@ void MidiInterface<Transport, Settings, Platform>::sendTimeCodeQuarterFrame(Data
|
||||||
you can send the byte here.
|
you can send the byte here.
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendTimeCodeQuarterFrame(DataByte inData)
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendTimeCodeQuarterFrame(DataByte inData)
|
||||||
{
|
{
|
||||||
sendCommon(TimeCodeQuarterFrame, inData);
|
return sendCommon(TimeCodeQuarterFrame, inData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Song Position Pointer message.
|
/*! \brief Send a Song Position Pointer message.
|
||||||
\param inBeats The number of beats since the start of the song.
|
\param inBeats The number of beats since the start of the song.
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendSongPosition(unsigned inBeats)
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendSongPosition(unsigned inBeats)
|
||||||
{
|
{
|
||||||
sendCommon(SongPosition, inBeats);
|
return sendCommon(SongPosition, inBeats);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Song Select message */
|
/*! \brief Send a Song Select message */
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendSongSelect(DataByte inSongNumber)
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendSongSelect(DataByte inSongNumber)
|
||||||
{
|
{
|
||||||
sendCommon(SongSelect, inSongNumber);
|
return sendCommon(SongSelect, inSongNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Common message. Common messages reset the running status.
|
/*! \brief Send a Common message. Common messages reset the running status.
|
||||||
|
|
@ -440,7 +451,7 @@ void MidiInterface<Transport, Settings, Platform>::sendSongSelect(DataByte inSon
|
||||||
\param inData1 The byte that goes with the common message.
|
\param inData1 The byte that goes with the common message.
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendCommon(MidiType inType, unsigned inData1)
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendCommon(MidiType inType, unsigned inData1)
|
||||||
{
|
{
|
||||||
switch (inType)
|
switch (inType)
|
||||||
{
|
{
|
||||||
|
|
@ -451,7 +462,7 @@ void MidiInterface<Transport, Settings, Platform>::sendCommon(MidiType inType, u
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Invalid Common marker
|
// Invalid Common marker
|
||||||
return;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTransport.beginTransmission(inType))
|
if (mTransport.beginTransmission(inType))
|
||||||
|
|
@ -471,15 +482,19 @@ void MidiInterface<Transport, Settings, Platform>::sendCommon(MidiType inType, u
|
||||||
break;
|
break;
|
||||||
case TuneRequest:
|
case TuneRequest:
|
||||||
break;
|
break;
|
||||||
|
// LCOV_EXCL_START - Coverage blind spot
|
||||||
default:
|
default:
|
||||||
break; // LCOV_EXCL_LINE - Coverage blind spot
|
break;
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
mTransport.endTransmission();
|
mTransport.endTransmission();
|
||||||
UpdateLastSentTime();
|
updateLastSentTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::UseRunningStatus)
|
if (Settings::UseRunningStatus)
|
||||||
mRunningStatus_TX = InvalidType;
|
mRunningStatus_TX = InvalidType;
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Real Time (one byte) message.
|
/*! \brief Send a Real Time (one byte) message.
|
||||||
|
|
@ -489,7 +504,7 @@ void MidiInterface<Transport, Settings, Platform>::sendCommon(MidiType inType, u
|
||||||
@see MidiType
|
@see MidiType
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::sendRealTime(MidiType inType)
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendRealTime(MidiType inType)
|
||||||
{
|
{
|
||||||
// Do not invalidate Running Status for real-time messages
|
// Do not invalidate Running Status for real-time messages
|
||||||
// as they can be interleaved within any message.
|
// as they can be interleaved within any message.
|
||||||
|
|
@ -506,13 +521,15 @@ void MidiInterface<Transport, Settings, Platform>::sendRealTime(MidiType inType)
|
||||||
{
|
{
|
||||||
mTransport.write((byte)inType);
|
mTransport.write((byte)inType);
|
||||||
mTransport.endTransmission();
|
mTransport.endTransmission();
|
||||||
UpdateLastSentTime();
|
updateLastSentTime();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Invalid Real Time marker
|
// Invalid Real Time marker
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Start a Registered Parameter Number frame.
|
/*! \brief Start a Registered Parameter Number frame.
|
||||||
|
|
@ -520,7 +537,7 @@ void MidiInterface<Transport, Settings, Platform>::sendRealTime(MidiType inType)
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::beginRpn(unsigned inNumber,
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::beginRpn(unsigned inNumber,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
if (mCurrentRpnNumber != inNumber)
|
if (mCurrentRpnNumber != inNumber)
|
||||||
|
|
@ -531,6 +548,8 @@ inline void MidiInterface<Transport, Settings, Platform>::beginRpn(unsigned inNu
|
||||||
sendControlChange(RPNMSB, numMsb, inChannel);
|
sendControlChange(RPNMSB, numMsb, inChannel);
|
||||||
mCurrentRpnNumber = inNumber;
|
mCurrentRpnNumber = inNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a 14-bit value for the currently selected RPN number.
|
/*! \brief Send a 14-bit value for the currently selected RPN number.
|
||||||
|
|
@ -538,13 +557,15 @@ inline void MidiInterface<Transport, Settings, Platform>::beginRpn(unsigned inNu
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::sendRpnValue(unsigned inValue,
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendRpnValue(unsigned inValue,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{;
|
{;
|
||||||
const byte valMsb = 0x7f & (inValue >> 7);
|
const byte valMsb = 0x7f & (inValue >> 7);
|
||||||
const byte valLsb = 0x7f & inValue;
|
const byte valLsb = 0x7f & inValue;
|
||||||
sendControlChange(DataEntryMSB, valMsb, inChannel);
|
sendControlChange(DataEntryMSB, valMsb, inChannel);
|
||||||
sendControlChange(DataEntryLSB, valLsb, inChannel);
|
sendControlChange(DataEntryLSB, valLsb, inChannel);
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send separate MSB/LSB values for the currently selected RPN number.
|
/*! \brief Send separate MSB/LSB values for the currently selected RPN number.
|
||||||
|
|
@ -553,32 +574,38 @@ inline void MidiInterface<Transport, Settings, Platform>::sendRpnValue(unsigned
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::sendRpnValue(byte inMsb,
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendRpnValue(byte inMsb,
|
||||||
byte inLsb,
|
byte inLsb,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
sendControlChange(DataEntryMSB, inMsb, inChannel);
|
sendControlChange(DataEntryMSB, inMsb, inChannel);
|
||||||
sendControlChange(DataEntryLSB, inLsb, inChannel);
|
sendControlChange(DataEntryLSB, inLsb, inChannel);
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \brief Increment the value of the currently selected RPN number by the specified amount.
|
/* \brief Increment the value of the currently selected RPN number by the specified amount.
|
||||||
\param inAmount The amount to add to the currently selected RPN value.
|
\param inAmount The amount to add to the currently selected RPN value.
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::sendRpnIncrement(byte inAmount,
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendRpnIncrement(byte inAmount,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
sendControlChange(DataIncrement, inAmount, inChannel);
|
sendControlChange(DataIncrement, inAmount, inChannel);
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \brief Decrement the value of the currently selected RPN number by the specified amount.
|
/* \brief Decrement the value of the currently selected RPN number by the specified amount.
|
||||||
\param inAmount The amount to subtract to the currently selected RPN value.
|
\param inAmount The amount to subtract to the currently selected RPN value.
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::sendRpnDecrement(byte inAmount,
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendRpnDecrement(byte inAmount,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
sendControlChange(DataDecrement, inAmount, inChannel);
|
sendControlChange(DataDecrement, inAmount, inChannel);
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Terminate an RPN frame.
|
/*! \brief Terminate an RPN frame.
|
||||||
|
|
@ -586,11 +613,13 @@ This will send a Null Function to deselect the currently selected RPN.
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::endRpn(Channel inChannel)
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::endRpn(Channel inChannel)
|
||||||
{
|
{
|
||||||
sendControlChange(RPNLSB, 0x7f, inChannel);
|
sendControlChange(RPNLSB, 0x7f, inChannel);
|
||||||
sendControlChange(RPNMSB, 0x7f, inChannel);
|
sendControlChange(RPNMSB, 0x7f, inChannel);
|
||||||
mCurrentRpnNumber = 0xffff;
|
mCurrentRpnNumber = 0xffff;
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -600,7 +629,7 @@ inline void MidiInterface<Transport, Settings, Platform>::endRpn(Channel inChann
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::beginNrpn(unsigned inNumber,
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::beginNrpn(unsigned inNumber,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
if (mCurrentNrpnNumber != inNumber)
|
if (mCurrentNrpnNumber != inNumber)
|
||||||
|
|
@ -611,6 +640,8 @@ inline void MidiInterface<Transport, Settings, Platform>::beginNrpn(unsigned inN
|
||||||
sendControlChange(NRPNMSB, numMsb, inChannel);
|
sendControlChange(NRPNMSB, numMsb, inChannel);
|
||||||
mCurrentNrpnNumber = inNumber;
|
mCurrentNrpnNumber = inNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a 14-bit value for the currently selected NRPN number.
|
/*! \brief Send a 14-bit value for the currently selected NRPN number.
|
||||||
|
|
@ -618,13 +649,15 @@ inline void MidiInterface<Transport, Settings, Platform>::beginNrpn(unsigned inN
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::sendNrpnValue(unsigned inValue,
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendNrpnValue(unsigned inValue,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{;
|
{
|
||||||
const byte valMsb = 0x7f & (inValue >> 7);
|
const byte valMsb = 0x7f & (inValue >> 7);
|
||||||
const byte valLsb = 0x7f & inValue;
|
const byte valLsb = 0x7f & inValue;
|
||||||
sendControlChange(DataEntryMSB, valMsb, inChannel);
|
sendControlChange(DataEntryMSB, valMsb, inChannel);
|
||||||
sendControlChange(DataEntryLSB, valLsb, inChannel);
|
sendControlChange(DataEntryLSB, valLsb, inChannel);
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send separate MSB/LSB values for the currently selected NRPN number.
|
/*! \brief Send separate MSB/LSB values for the currently selected NRPN number.
|
||||||
|
|
@ -633,32 +666,38 @@ inline void MidiInterface<Transport, Settings, Platform>::sendNrpnValue(unsigned
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::sendNrpnValue(byte inMsb,
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendNrpnValue(byte inMsb,
|
||||||
byte inLsb,
|
byte inLsb,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
sendControlChange(DataEntryMSB, inMsb, inChannel);
|
sendControlChange(DataEntryMSB, inMsb, inChannel);
|
||||||
sendControlChange(DataEntryLSB, inLsb, inChannel);
|
sendControlChange(DataEntryLSB, inLsb, inChannel);
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \brief Increment the value of the currently selected NRPN number by the specified amount.
|
/* \brief Increment the value of the currently selected NRPN number by the specified amount.
|
||||||
\param inAmount The amount to add to the currently selected NRPN value.
|
\param inAmount The amount to add to the currently selected NRPN value.
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::sendNrpnIncrement(byte inAmount,
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendNrpnIncrement(byte inAmount,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
sendControlChange(DataIncrement, inAmount, inChannel);
|
sendControlChange(DataIncrement, inAmount, inChannel);
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \brief Decrement the value of the currently selected NRPN number by the specified amount.
|
/* \brief Decrement the value of the currently selected NRPN number by the specified amount.
|
||||||
\param inAmount The amount to subtract to the currently selected NRPN value.
|
\param inAmount The amount to subtract to the currently selected NRPN value.
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::sendNrpnDecrement(byte inAmount,
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendNrpnDecrement(byte inAmount,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
sendControlChange(DataDecrement, inAmount, inChannel);
|
sendControlChange(DataDecrement, inAmount, inChannel);
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Terminate an NRPN frame.
|
/*! \brief Terminate an NRPN frame.
|
||||||
|
|
@ -666,11 +705,20 @@ This will send a Null Function to deselect the currently selected NRPN.
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::endNrpn(Channel inChannel)
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::endNrpn(Channel inChannel)
|
||||||
{
|
{
|
||||||
sendControlChange(NRPNLSB, 0x7f, inChannel);
|
sendControlChange(NRPNLSB, 0x7f, inChannel);
|
||||||
sendControlChange(NRPNMSB, 0x7f, inChannel);
|
sendControlChange(NRPNMSB, 0x7f, inChannel);
|
||||||
mCurrentNrpnNumber = 0xffff;
|
mCurrentNrpnNumber = 0xffff;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Transport, class Settings, class Platform>
|
||||||
|
inline void MidiInterface<Transport, Settings, Platform>::updateLastSentTime()
|
||||||
|
{
|
||||||
|
if (Settings::UseSenderActiveSensing && mSenderActiveSensingPeriodicity)
|
||||||
|
mLastMessageSentTime = Platform::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! @} */ // End of doc group MIDI Output
|
/*! @} */ // End of doc group MIDI Output
|
||||||
|
|
@ -712,32 +760,27 @@ template<class Transport, class Settings, class Platform>
|
||||||
inline bool MidiInterface<Transport, Settings, Platform>::read(Channel inChannel)
|
inline bool MidiInterface<Transport, Settings, Platform>::read(Channel inChannel)
|
||||||
{
|
{
|
||||||
#ifndef RegionActiveSending
|
#ifndef RegionActiveSending
|
||||||
|
|
||||||
// Active Sensing. This message is intended to be sent
|
// Active Sensing. This message is intended to be sent
|
||||||
// repeatedly to tell the receiver that a connection is alive. Use
|
// repeatedly to tell the receiver that a connection is alive. Use
|
||||||
// of this message is optional.
|
// of this message is optional. When initially received, the
|
||||||
if (Settings::UseSenderActiveSensing)
|
// receiver will expect to receive another Active Sensing
|
||||||
|
// message each 300ms (max), and if it does not then it will
|
||||||
|
// assume that the connection has been terminated. At
|
||||||
|
// termination, the receiver will turn off all voices and return to
|
||||||
|
// normal (non- active sensing) operation.
|
||||||
|
if (Settings::UseSenderActiveSensing && (mSenderActiveSensingPeriodicity > 0) && (Platform::now() - mLastMessageSentTime) > mSenderActiveSensingPeriodicity)
|
||||||
{
|
{
|
||||||
// Send ActiveSensing <Settings::ActiveSensingPeriodicity> ms after the last command
|
sendActiveSensing();
|
||||||
if ((Platform::now() - mLastMessageSentTime) > Settings::SenderActiveSensingPeriodicity)
|
mLastMessageSentTime = Platform::now();
|
||||||
sendActiveSensing();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Once an Active Sensing message is received, the unit will begin monitoring
|
if (Settings::UseReceiverActiveSensing && mReceiverActiveSensingActivated && (mLastMessageReceivedTime + ActiveSensingTimeout < Platform::now()))
|
||||||
// the intervalbetween all subsequent messages. If there is an interval of 420 ms
|
|
||||||
// or longer betweenmessages while monitoring is active, the same processing
|
|
||||||
// as when All Sound Off, All Notes Off,and Reset All Controllers messages are
|
|
||||||
// received will be carried out. The unit will then stopmonitoring the message interval.
|
|
||||||
if (Settings::UseReceiverActiveSensing && mReceiverActiveSensingActive)
|
|
||||||
{
|
{
|
||||||
if ((Platform::now() - mLastMessageReceivedTime > Settings::ReceiverActiveSensingTimeout))
|
mReceiverActiveSensingActivated = false;
|
||||||
{
|
|
||||||
mReceiverActiveSensingActive = false;
|
|
||||||
|
|
||||||
// its up to the handler to send the stop processing messages
|
mLastError |= 1UL << ErrorActiveSensingTimeout; // set the ErrorActiveSensingTimeout bit
|
||||||
// (also, no clue what the channel is on which to send them)
|
if (mErrorCallback)
|
||||||
mActiveSensingTimeoutCallback(mReceiverActiveSensingActive);
|
mErrorCallback(mLastError);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -749,18 +792,25 @@ inline bool MidiInterface<Transport, Settings, Platform>::read(Channel inChannel
|
||||||
|
|
||||||
#ifndef RegionActiveSending
|
#ifndef RegionActiveSending
|
||||||
|
|
||||||
if (Settings::UseReceiverActiveSensing)
|
if (Settings::UseReceiverActiveSensing && mMessage.type == ActiveSensing)
|
||||||
{
|
{
|
||||||
mLastMessageReceivedTime = Platform::now();
|
// When an ActiveSensing message is received, the time keeping is activated.
|
||||||
|
// When a timeout occurs, an error message is send and time keeping ends.
|
||||||
|
mReceiverActiveSensingActivated = true;
|
||||||
|
|
||||||
if (mMessage.type == ActiveSensing && !mReceiverActiveSensingActive)
|
// is ErrorActiveSensingTimeout bit in mLastError on
|
||||||
|
if (mLastError & (1 << (ErrorActiveSensingTimeout - 1)))
|
||||||
{
|
{
|
||||||
mReceiverActiveSensingActive = true;
|
mLastError &= ~(1UL << ErrorActiveSensingTimeout); // clear the ErrorActiveSensingTimeout bit
|
||||||
|
if (mErrorCallback)
|
||||||
mActiveSensingTimeoutCallback(mReceiverActiveSensingActive);
|
mErrorCallback(mLastError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep the time of the last received message, so we can check for the timeout
|
||||||
|
if (Settings::UseReceiverActiveSensing && mReceiverActiveSensingActivated)
|
||||||
|
mLastMessageReceivedTime = Platform::now();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
handleNullVelocityNoteOnAsNoteOff();
|
handleNullVelocityNoteOnAsNoteOff();
|
||||||
|
|
@ -978,9 +1028,10 @@ bool MidiInterface<Transport, Settings, Platform>::parse()
|
||||||
resetInput();
|
resetInput();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// LCOV_EXCL_START - Coverage blind spot
|
||||||
default:
|
default:
|
||||||
break; // LCOV_EXCL_LINE - Coverage blind spot
|
break;
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1035,6 +1086,7 @@ bool MidiInterface<Transport, Settings, Platform>::parse()
|
||||||
mMessage.data1 = mPendingMessage[1];
|
mMessage.data1 = mPendingMessage[1];
|
||||||
// Save data2 only if applicable
|
// Save data2 only if applicable
|
||||||
mMessage.data2 = mPendingMessageExpectedLength == 3 ? mPendingMessage[2] : 0;
|
mMessage.data2 = mPendingMessageExpectedLength == 3 ? mPendingMessage[2] : 0;
|
||||||
|
mMessage.length = mPendingMessageExpectedLength;
|
||||||
|
|
||||||
// Reset local variables
|
// Reset local variables
|
||||||
mPendingMessageIndex = 0;
|
mPendingMessageIndex = 0;
|
||||||
|
|
@ -1200,9 +1252,11 @@ inline Channel MidiInterface<Transport, Settings, Platform>::getInputChannel() c
|
||||||
if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable input.
|
if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable input.
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::setInputChannel(Channel inChannel)
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::setInputChannel(Channel inChannel)
|
||||||
{
|
{
|
||||||
mInputChannel = inChannel;
|
mInputChannel = inChannel;
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
@ -1257,7 +1311,7 @@ bool MidiInterface<Transport, Settings, Platform>::isChannelMessage(MidiType inT
|
||||||
When a message of this type is received, no function will be called.
|
When a message of this type is received, no function will be called.
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
void MidiInterface<Transport, Settings, Platform>::disconnectCallbackFromType(MidiType inType)
|
MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::disconnectCallbackFromType(MidiType inType)
|
||||||
{
|
{
|
||||||
switch (inType)
|
switch (inType)
|
||||||
{
|
{
|
||||||
|
|
@ -1283,6 +1337,8 @@ void MidiInterface<Transport, Settings, Platform>::disconnectCallbackFromType(Mi
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! @} */ // End of doc group MIDI Callbacks
|
/*! @} */ // End of doc group MIDI Callbacks
|
||||||
|
|
@ -1325,9 +1381,11 @@ void MidiInterface<Transport, Settings, Platform>::launchCallback()
|
||||||
|
|
||||||
case SystemReset: if (mSystemResetCallback != nullptr) mSystemResetCallback(); break;
|
case SystemReset: if (mSystemResetCallback != nullptr) mSystemResetCallback(); break;
|
||||||
|
|
||||||
|
// LCOV_EXCL_START - Unreacheable code, but prevents unhandled case warning.
|
||||||
case InvalidType:
|
case InvalidType:
|
||||||
default:
|
default:
|
||||||
break; // LCOV_EXCL_LINE - Unreacheable code, but prevents unhandled case warning.
|
break;
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1347,10 +1405,12 @@ void MidiInterface<Transport, Settings, Platform>::launchCallback()
|
||||||
@see Thru::Mode
|
@see Thru::Mode
|
||||||
*/
|
*/
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::setThruFilterMode(Thru::Mode inThruFilterMode)
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::setThruFilterMode(Thru::Mode inThruFilterMode)
|
||||||
{
|
{
|
||||||
mThruFilterMode = inThruFilterMode;
|
mThruFilterMode = inThruFilterMode;
|
||||||
mThruActivated = mThruFilterMode != Thru::Off;
|
mThruActivated = mThruFilterMode != Thru::Off;
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
|
|
@ -1366,25 +1426,23 @@ inline bool MidiInterface<Transport, Settings, Platform>::getThruState() const
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::turnThruOn(Thru::Mode inThruFilterMode)
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::turnThruOn(Thru::Mode inThruFilterMode)
|
||||||
{
|
{
|
||||||
mThruActivated = true;
|
mThruActivated = true;
|
||||||
mThruFilterMode = inThruFilterMode;
|
mThruFilterMode = inThruFilterMode;
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Transport, class Settings, class Platform>
|
template<class Transport, class Settings, class Platform>
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::turnThruOff()
|
inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::turnThruOff()
|
||||||
{
|
{
|
||||||
mThruActivated = false;
|
mThruActivated = false;
|
||||||
mThruFilterMode = Thru::Off;
|
mThruFilterMode = Thru::Off;
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Transport, class Settings, class Platform>
|
|
||||||
inline void MidiInterface<Transport, Settings, Platform>::UpdateLastSentTime()
|
|
||||||
{
|
|
||||||
if (Settings::UseSenderActiveSensing)
|
|
||||||
mLastMessageSentTime = Platform::now();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @} */ // End of doc group MIDI Thru
|
/*! @} */ // End of doc group MIDI Thru
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,10 @@ BEGIN_MIDI_NAMESPACE
|
||||||
#define MIDI_PITCHBEND_MIN -8192
|
#define MIDI_PITCHBEND_MIN -8192
|
||||||
#define MIDI_PITCHBEND_MAX 8191
|
#define MIDI_PITCHBEND_MAX 8191
|
||||||
|
|
||||||
|
/*! Receiving Active Sensing
|
||||||
|
*/
|
||||||
|
static const uint16_t ActiveSensingTimeout = 300;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Type definitions
|
// Type definitions
|
||||||
|
|
||||||
|
|
@ -57,13 +61,13 @@ typedef byte FilterMode;
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Errors
|
// Errors
|
||||||
static const uint8_t ErrorParse = 0;
|
static const uint8_t ErrorParse = 0;
|
||||||
|
static const uint8_t ErrorActiveSensingTimeout = 1;
|
||||||
static const uint8_t WarningSplitSysEx = 2;
|
static const uint8_t WarningSplitSysEx = 2;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Aliasing
|
// Aliasing
|
||||||
|
|
||||||
using ErrorCallback = void (*)(int8_t);
|
using ErrorCallback = void (*)(int8_t);
|
||||||
using ActiveSensingTimeoutCallback = void (*)(bool);
|
|
||||||
using NoteOffCallback = void (*)(Channel channel, byte note, byte velocity);
|
using NoteOffCallback = void (*)(Channel channel, byte note, byte velocity);
|
||||||
using NoteOnCallback = void (*)(Channel channel, byte note, byte velocity);
|
using NoteOnCallback = void (*)(Channel channel, byte note, byte velocity);
|
||||||
using AfterTouchPolyCallback = void (*)(Channel channel, byte note, byte velocity);
|
using AfterTouchPolyCallback = void (*)(Channel channel, byte note, byte velocity);
|
||||||
|
|
@ -160,8 +164,22 @@ enum MidiControlChangeNumber: uint8_t
|
||||||
GeneralPurposeController2 = 17,
|
GeneralPurposeController2 = 17,
|
||||||
GeneralPurposeController3 = 18,
|
GeneralPurposeController3 = 18,
|
||||||
GeneralPurposeController4 = 19,
|
GeneralPurposeController4 = 19,
|
||||||
|
// CC20 to CC31 undefined
|
||||||
|
BankSelectLSB = 32,
|
||||||
|
ModulationWheelLSB = 33,
|
||||||
|
BreathControllerLSB = 34,
|
||||||
|
// CC35 undefined
|
||||||
|
FootControllerLSB = 36,
|
||||||
|
PortamentoTimeLSB = 37,
|
||||||
DataEntryLSB = 38,
|
DataEntryLSB = 38,
|
||||||
|
ChannelVolumeLSB = 39,
|
||||||
|
BalanceLSB = 40,
|
||||||
|
// CC41 undefined
|
||||||
|
PanLSB = 42,
|
||||||
|
ExpressionControllerLSB = 43,
|
||||||
|
EffectControl1LSB = 44,
|
||||||
|
EffectControl2LSB = 45,
|
||||||
|
// CC46 to CC63 undefined
|
||||||
|
|
||||||
// Switches ----------------------------------------------------------------
|
// Switches ----------------------------------------------------------------
|
||||||
Sustain = 64,
|
Sustain = 64,
|
||||||
|
|
@ -199,6 +217,7 @@ enum MidiControlChangeNumber: uint8_t
|
||||||
NRPNMSB = 99, ///< Non-Registered Parameter Number (MSB)
|
NRPNMSB = 99, ///< Non-Registered Parameter Number (MSB)
|
||||||
RPNLSB = 100, ///< Registered Parameter Number (LSB)
|
RPNLSB = 100, ///< Registered Parameter Number (LSB)
|
||||||
RPNMSB = 101, ///< Registered Parameter Number (MSB)
|
RPNMSB = 101, ///< Registered Parameter Number (MSB)
|
||||||
|
// CC102 to CC119 undefined
|
||||||
|
|
||||||
// Channel Mode messages ---------------------------------------------------
|
// Channel Mode messages ---------------------------------------------------
|
||||||
AllSoundOff = 120,
|
AllSoundOff = 120,
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,20 @@ struct Message
|
||||||
memset(sysexArray, 0, sSysExMaxSize * sizeof(DataByte));
|
memset(sysexArray, 0, sSysExMaxSize * sizeof(DataByte));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Message(const Message& inOther)
|
||||||
|
: channel(inOther.channel)
|
||||||
|
, type(inOther.type)
|
||||||
|
, data1(inOther.data1)
|
||||||
|
, data2(inOther.data2)
|
||||||
|
, valid(inOther.valid)
|
||||||
|
, length(inOther.length)
|
||||||
|
{
|
||||||
|
if (type == midi::SystemExclusive)
|
||||||
|
{
|
||||||
|
memcpy(sysexArray, inOther.sysexArray, sSysExMaxSize * sizeof(DataByte));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*! The maximum size for the System Exclusive array.
|
/*! The maximum size for the System Exclusive array.
|
||||||
*/
|
*/
|
||||||
static const unsigned sSysExMaxSize = SysExMaxSize;
|
static const unsigned sSysExMaxSize = SysExMaxSize;
|
||||||
|
|
@ -94,12 +108,24 @@ struct Message
|
||||||
/*! Total Length of the message.
|
/*! Total Length of the message.
|
||||||
*/
|
*/
|
||||||
unsigned length;
|
unsigned length;
|
||||||
|
|
||||||
inline unsigned getSysExSize() const
|
inline unsigned getSysExSize() const
|
||||||
{
|
{
|
||||||
const unsigned size = unsigned(data2) << 8 | data1;
|
const unsigned size = unsigned(data2) << 8 | data1;
|
||||||
return size > sSysExMaxSize ? sSysExMaxSize : size;
|
return size > sSysExMaxSize ? sSysExMaxSize : size;
|
||||||
}
|
}
|
||||||
|
inline bool isSystemRealTime () const
|
||||||
|
{
|
||||||
|
return (type & 0xf8) == 0xf8;
|
||||||
|
}
|
||||||
|
inline bool isSystemCommon () const
|
||||||
|
{
|
||||||
|
return (type & 0xf8) == 0xf0;
|
||||||
|
}
|
||||||
|
inline bool isChannelMessage () const
|
||||||
|
{
|
||||||
|
return (type & 0xf0) != 0xf0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
END_MIDI_NAMESPACE
|
END_MIDI_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -72,15 +72,18 @@ struct DefaultSettings
|
||||||
*/
|
*/
|
||||||
static const unsigned SysExMaxSize = 128;
|
static const unsigned SysExMaxSize = 128;
|
||||||
|
|
||||||
/*! Global switch to turn on/off sending and receiving ActiveSensing
|
/*! Global switch to turn on/off sender ActiveSensing
|
||||||
Set to true to activate ActiveSensing
|
Set to true to send ActiveSensing
|
||||||
Set to false will not send/receive ActiveSensing message (will also save 236 bytes of memory)
|
Set to false will not send ActiveSensing message (will also save memory)
|
||||||
|
|
||||||
When setting UseActiveSensing to true, MIDI.read() *must* be called
|
|
||||||
as often as possible (1000 / ActiveSensingPeriodicity per second).
|
|
||||||
*/
|
*/
|
||||||
static const bool UseSenderActiveSensing = false;
|
static const bool UseSenderActiveSensing = false;
|
||||||
|
|
||||||
|
/*! Global switch to turn on/off receiver ActiveSensing
|
||||||
|
Set to true to check for message timeouts (via ErrorCallback)
|
||||||
|
Set to false will not check if chained device are still alive (if they use ActiveSensing) (will also save memory)
|
||||||
|
*/
|
||||||
|
static const bool UseReceiverActiveSensing = false;
|
||||||
|
|
||||||
/*! Active Sensing is intended to be sent
|
/*! Active Sensing is intended to be sent
|
||||||
repeatedly by the sender to tell the receiver that a connection is alive. Use
|
repeatedly by the sender to tell the receiver that a connection is alive. Use
|
||||||
of this message is optional. When initially received, the
|
of this message is optional. When initially received, the
|
||||||
|
|
@ -91,20 +94,11 @@ struct DefaultSettings
|
||||||
normal (non- active sensing) operation.
|
normal (non- active sensing) operation.
|
||||||
|
|
||||||
Typical value is 250 (ms) - an Active Sensing command is send every 250ms.
|
Typical value is 250 (ms) - an Active Sensing command is send every 250ms.
|
||||||
(Most Roland devices send Active Sensing every 250ms)
|
(All Roland devices send Active Sensing every 250ms)
|
||||||
|
|
||||||
|
Setting this field to 0 will disable sending MIDI active sensing.
|
||||||
*/
|
*/
|
||||||
static const uint16_t SenderActiveSensingPeriodicity = 300;
|
static const uint16_t SenderActiveSensingPeriodicity = 0;
|
||||||
|
|
||||||
/*! Once an Active Sensing message is received, the unit will begin monitoring
|
|
||||||
the intervalbetween all subsequent messages. If there is an interval of ActiveSensingPeriodicity ms
|
|
||||||
or longer betweenmessages while monitoring is active, the same processing
|
|
||||||
as when All Sound Off, All Notes Off,and Reset All Controllers messages are
|
|
||||||
received will be carried out. The unit will then stopmonitoring the message interval.
|
|
||||||
*/
|
|
||||||
static const bool UseReceiverActiveSensing = false;
|
|
||||||
|
|
||||||
static const uint16_t ReceiverActiveSensingTimeout = 300;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
END_MIDI_NAMESPACE
|
END_MIDI_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,11 @@ public:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void end()
|
||||||
|
{
|
||||||
|
mSerial.end();
|
||||||
|
}
|
||||||
|
|
||||||
bool beginTransmission(MidiType)
|
bool beginTransmission(MidiType)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -116,11 +121,10 @@ END_MIDI_NAMESPACE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*! \brief Create an instance of the library attached to a serial port with
|
/*! \brief Create an instance of the library attached to a serial port with
|
||||||
custom MIDI settings (not to be confused with modified Serial Settings, like BaudRate)
|
custom settings.
|
||||||
@see DefaultSettings
|
@see DefaultSettings
|
||||||
@see MIDI_CREATE_INSTANCE
|
@see MIDI_CREATE_INSTANCE
|
||||||
*/
|
*/
|
||||||
#define MIDI_CREATE_CUSTOM_INSTANCE(Type, SerialPort, Name, Settings) \
|
#define MIDI_CREATE_CUSTOM_INSTANCE(Type, SerialPort, Name, Settings) \
|
||||||
MIDI_NAMESPACE::SerialMIDI<Type> serial##Name(SerialPort);\
|
MIDI_NAMESPACE::SerialMIDI<Type> serial##Name(SerialPort);\
|
||||||
MIDI_NAMESPACE::MidiInterface<MIDI_NAMESPACE::SerialMIDI<Type>, Settings> Name((MIDI_NAMESPACE::SerialMIDI<Type>&)serial##Name);
|
MIDI_NAMESPACE::MidiInterface<MIDI_NAMESPACE::SerialMIDI<Type>, Settings> Name((MIDI_NAMESPACE::SerialMIDI<Type>&)serial##Name);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue