Skip to content
Browse files

Updated documentation.

  • Loading branch information...
1 parent e6da273 commit 9f14e2c4b8255e2da6afe654cb734f4daea6a4c2 @Franky47 Franky47 committed Sep 28, 2012
Showing with 664 additions and 593 deletions.
  1. +166 −85 doc/Doxyfile
  2. +25 −17 doc/midi_DoxygenMainPage.h
  3. +473 −491 src/midi_Inline.hpp
View
251 doc/Doxyfile
@@ -1,4 +1,4 @@
-# Doxyfile 1.7.4
+# Doxyfile 1.8.1.2
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
@@ -22,8 +22,9 @@
DOXYFILE_ENCODING = UTF-8
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
-# by quotes) that should identify the project.
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
PROJECT_NAME = "Arduino MIDI Library"
@@ -204,6 +205,13 @@ TAB_SIZE = 4
ALIASES =
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
# sources only. Doxygen will then generate output that is more tailored for C.
# For instance, some of the names that are used will be different. The list
@@ -242,6 +250,15 @@ OPTIMIZE_OUTPUT_VHDL = NO
EXTENSION_MAPPING =
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should
# set this tag to YES in order to let doxygen match functions declarations and
@@ -293,6 +310,15 @@ SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
# is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
@@ -315,10 +341,21 @@ TYPEDEF_HIDES_STRUCT = NO
# a logarithmic scale so increasing the size by one will roughly double the
# memory usage. The cache size is given by this formula:
# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols
+# corresponding to a cache size of 2^16 = 65536 symbols.
SYMBOL_CACHE_SIZE = 0
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
@@ -335,6 +372,11 @@ EXTRACT_ALL = YES
EXTRACT_PRIVATE = NO
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
@@ -522,12 +564,6 @@ MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = NO
-
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
@@ -552,13 +588,23 @@ FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
-# output files in an output format independent way. The create the layout file
+# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option.
# You can optionally specify a file name after the option, if omitted
# DoxygenLayout.xml will be used as the name of the layout file.
LAYOUT_FILE =
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES =
+
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
@@ -620,7 +666,8 @@ WARN_LOGFILE =
# with spaces.
INPUT = ../ \
- ../src
+ ../src \
+ ./midi_DoxygenMainPage.h
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -668,21 +715,24 @@ FILE_PATTERNS = *.c \
*.f90 \
*.f \
*.vhd \
- *.vhdl
+ *.vhdl \
+ *.ino
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
-RECURSIVE = NO
+RECURSIVE = YES
-# The EXCLUDE tag can be used to specify files and/or directories that should
+# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
EXCLUDE =
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
@@ -708,7 +758,7 @@ EXCLUDE_SYMBOLS =
# directories that contain example code fragments that are included (see
# the \include command).
-EXAMPLE_PATH =
+EXAMPLE_PATH = ../res/Examples
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
@@ -722,7 +772,7 @@ EXAMPLE_PATTERNS = *
# commands irrespective of the value of the RECURSIVE tag.
# Possible values are YES and NO. If left blank NO is used.
-EXAMPLE_RECURSIVE = NO
+EXAMPLE_RECURSIVE = YES
# The IMAGE_PATH tag can be used to specify one or more files or
# directories that contain image that are included in the documentation (see
@@ -781,7 +831,7 @@ INLINE_SOURCES = YES
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C and C++ comments will always remain visible.
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
STRIP_CODE_COMMENTS = YES
@@ -864,13 +914,13 @@ HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a personal HTML header for
# each generated HTML page. If it is left blank doxygen will generate a
-# standard header. Note that when using a custom header you are responsible
+# standard header. Note that when using a custom header you are responsible
# for the proper inclusion of any scripts and style sheets that doxygen
# needs, which is dependent on the configuration options used.
-# It is adviced to generate a default header using "doxygen -w html
+# It is advised to generate a default header using "doxygen -w html
# header.html footer.html stylesheet.css YourConfigFile" and then modify
# that header. Note that the header is subject to change so you typically
-# have to redo this when upgrading to a newer version of doxygen or when
+# have to redo this when upgrading to a newer version of doxygen or when
# changing the value of configuration settings such as GENERATE_TREEVIEW!
HTML_HEADER =
@@ -886,7 +936,7 @@ HTML_FOOTER =
# fine-tune the look of the HTML output. If the tag is left blank doxygen
# will generate a default style sheet. Note that doxygen will try to copy
# the style sheet file to the HTML output directory, so don't put your own
-# stylesheet in the HTML output directory as well, or it will be erased!
+# style sheet in the HTML output directory as well, or it will be erased!
HTML_STYLESHEET =
@@ -900,7 +950,7 @@ HTML_STYLESHEET =
HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
-# Doxygen will adjust the colors in the stylesheet and background images
+# Doxygen will adjust the colors in the style sheet and background images
# according to this color. Hue is specified as an angle on a colorwheel,
# see http://en.wikipedia.org/wiki/Hue for more information.
# For instance the value 0 represents red, 60 is yellow, 120 is green,
@@ -930,20 +980,23 @@ HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = YES
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS = YES
-
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
-# page has loaded. For this to work a browser that supports
-# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
-# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+# page has loaded.
HTML_DYNAMIC_SECTIONS = NO
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
# If the GENERATE_DOCSET tag is set to YES, additional index files
# will be generated that can be used as input for Apple's Xcode 3
# integrated development environment, introduced with OSX 10.5 (Leopard).
@@ -1095,33 +1148,32 @@ GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
-# top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it.
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
DISABLE_INDEX = NO
-# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
-# (range [0,1..20]) that doxygen will group on one line in the generated HTML
-# documentation. Note that a value of 0 will completely suppress the enum
-# values from appearing in the overview section.
-
-ENUM_VALUES_PER_LINE = 4
-
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information.
# If the tag value is set to YES, a side panel will be generated
# containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
-# Windows users are probably better off using the HTML help feature.
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
GENERATE_TREEVIEW = NO
-# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
-# and Class Hierarchy pages using a tree view instead of an ordered list.
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
-USE_INLINE_TREES = NO
+ENUM_VALUES_PER_LINE = 4
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
@@ -1154,7 +1206,7 @@ FORMULA_TRANSPARENT = YES
# (see http://www.mathjax.org) which uses client side Javascript for the
# rendering instead of using prerendered bitmaps. Use this if you do not
# have LaTeX installed or if you want to formulas look prettier in the HTML
-# output. When enabled you also need to install MathJax separately and
+# output. When enabled you may also need to install MathJax separately and
# configure the path to it using the MATHJAX_RELPATH option.
USE_MATHJAX = NO
@@ -1163,13 +1215,18 @@ USE_MATHJAX = NO
# HTML output directory using the MATHJAX_RELPATH option. The destination
# directory should contain the MathJax.js script. For instance, if the mathjax
# directory is located at the same level as the HTML output directory, then
-# MATHJAX_RELPATH should be ../mathjax. The default value points to the
-# mathjax.org site, so you can quickly see the result without installing
-# MathJax, but it is strongly recommended to install a local copy of MathJax
-# before deployment.
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax. However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
# When the SEARCHENGINE tag is enabled doxygen will generate a search box
# for the HTML output. The underlying search engine uses javascript
# and DHTML and should work on any modern browser. Note that when using
@@ -1283,6 +1340,12 @@ LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
@@ -1314,7 +1377,7 @@ COMPACT_RTF = NO
RTF_HYPERLINKS = NO
-# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# Load style sheet definitions from file. Syntax is similar to doxygen's
# config file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
@@ -1448,13 +1511,13 @@ ENABLE_PREPROCESSING = YES
# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
-MACRO_EXPANSION = NO
+MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_DEFINED tags.
-EXPAND_ONLY_PREDEF = NO
+EXPAND_ONLY_PREDEF = YES
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# pointed to by INCLUDE_PATH will be searched when a #include is found.
@@ -1465,14 +1528,15 @@ SEARCH_INCLUDES = YES
# contain include files that are not input files but should be processed by
# the preprocessor.
-INCLUDE_PATH =
+INCLUDE_PATH = ../src
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.
-INCLUDE_FILE_PATTERNS =
+INCLUDE_FILE_PATTERNS = *.h \
+ *.hpp
# The PREDEFINED tag can be used to specify one or more macro names that
# are defined before the preprocessor is started (similar to the -D option of
@@ -1482,7 +1546,10 @@ INCLUDE_FILE_PATTERNS =
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
-PREDEFINED =
+PREDEFINED = MIDI_USE_CALLBACKS=1 \
+ MIDI_BUILD_INPUT=1 \
+ MIDI_BUILD_OUTPUT=1 \
+ MIDI_BUILD_THRU=1
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
@@ -1497,26 +1564,22 @@ EXPAND_AS_DEFINED =
# that are alone on a line, have an all uppercase name, and do not end with a
# semicolon, because these will confuse the parser if not removed.
-SKIP_FUNCTION_MACROS = YES
+SKIP_FUNCTION_MACROS = NO
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
-# The TAGFILES option can be used to specify one or more tagfiles.
-# Optionally an initial location of the external documentation
-# can be added for each tagfile. The format of a tag file without
-# this location is as follows:
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths or
-# URLs. If a location is present for each tag, the installdox tool
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen
-# is run, you must also specify the path to the tagfile here.
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
TAGFILES =
@@ -1584,13 +1647,12 @@ HAVE_DOT = NO
DOT_NUM_THREADS = 0
-# By default doxygen will write a font called Helvetica to the output
-# directory and reference it in all dot files that doxygen generates.
-# When you want a differently looking font you can specify the font name
-# using DOT_FONTNAME. You need to make sure dot is able to find the font,
-# which can be done by putting it in a standard location or by setting the
-# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
-# containing the font.
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
DOT_FONTNAME = FreeSans
@@ -1599,17 +1661,16 @@ DOT_FONTNAME = FreeSans
DOT_FONTSIZE = 10
-# By default doxygen will tell dot to use the output directory to look for the
-# FreeSans.ttf font (which doxygen will put there itself). If you specify a
-# different font using DOT_FONTNAME you can set the path where dot
-# can find it using this tag.
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
DOT_FONTPATH =
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect inheritance relations. Setting this tag to YES will force the
-# the CLASS_DIAGRAMS tag to NO.
+# CLASS_DIAGRAMS tag to NO.
CLASS_GRAPH = YES
@@ -1631,6 +1692,15 @@ GROUP_GRAPHS = YES
UML_LOOK = NO
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
@@ -1671,7 +1741,7 @@ CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
# then doxygen will show the dependencies a directory has on other directories
# in a graphical way. The dependency relations are determined by the #include
# relations between the files in the directories.
@@ -1680,10 +1750,21 @@ DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. Possible values are svg, png, jpg, or gif.
-# If left blank png will be used.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
DOT_IMAGE_FORMAT = png
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
View
42 doc/midi_DoxygenMainPage.h
@@ -1,23 +1,8 @@
/*!
\mainpage Arduino MIDI Library
- \tableofcontents
-
-
- \page howtodoc How to use this documentation
-
- You can browse the classes
-
- \page howtolib How to use the library
-
- \section howtolib_section_callbacks Using callbacks
-
- Callbacks can simplify the reception of input messages.
-
-
-
- \page
-
+ See the documentation of the main class, MidiInterface, or browse the modules
+ using the toolbar above.
*/
// -----------------------------------------------------------------------------
@@ -40,3 +25,26 @@
\n
*/
+/*!
+ \example MIDI_Callbacks.ino
+ This example shows how to use callbacks for easier MIDI input handling. \n
+ */
+
+/*!
+ \example MIDI_Bench.ino
+ \example MIDI_DualMerger.ino
+ \example MIDI_Input.ino
+ */
+
+// -----------------------------------------------------------------------------
+
+/*! \defgroup output MIDI Output
+ */
+/*! \defgroup input MIDI Input
+ */
+/*! \defgroup callbacks Callbacks
+ \ingroup input
+ */
+/*! \defgroup thru MIDI Thru
+ */
+
View
964 src/midi_Inline.hpp
@@ -12,7 +12,6 @@
BEGIN_MIDI_NAMESPACE
-
/*! \brief Constructor for MidiInterface. */
template<class SerialPort>
MidiInterface<SerialPort>::MidiInterface(SerialPort& inSerial)
@@ -102,6 +101,10 @@ void MidiInterface<SerialPort>::begin(Channel inChannel)
#if MIDI_BUILD_OUTPUT
+/*! \addtogroup output
+ @{
+ */
+
/*! \brief Generate and send a MIDI message from the values given.
\param inType The message type (see type defines for reference)
\param inData1 The first data byte.
@@ -115,9 +118,9 @@ void MidiInterface<SerialPort>::begin(Channel inChannel)
*/
template<class SerialPort>
void MidiInterface<SerialPort>::send(MidiType inType,
- DataByte inData1,
- DataByte inData2,
- Channel inChannel)
+ DataByte inData1,
+ DataByte inData2,
+ Channel inChannel)
{
// Then test if channel is valid
if (inChannel >= MIDI_CHANNEL_OFF ||
@@ -164,6 +167,272 @@ void MidiInterface<SerialPort>::send(MidiType inType,
sendRealTime(inType); // System Real-time and 1 byte.
}
+// -----------------------------------------------------------------------------
+
+/*! \brief Send a Note On message
+ \param inNoteNumber Pitch value in the MIDI format (0 to 127).
+ \param inVelocity Note attack velocity (0 to 127). A NoteOn with 0 velocity
+ is considered as a NoteOff.
+ \param inChannel The channel on which the message will be sent (1 to 16).
+
+ Take a look at the values, names and frequencies of notes here:
+ http://www.phys.unsw.edu.au/jw/notes.html
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendNoteOn(DataByte inNoteNumber,
+ DataByte inVelocity,
+ Channel inChannel)
+{
+ send(NoteOn, inNoteNumber, inVelocity, inChannel);
+}
+
+/*! \brief Send a Note Off message
+ \param inNoteNumber Pitch value in the MIDI format (0 to 127).
+ \param inVelocity Release velocity (0 to 127).
+ \param inChannel The channel on which the message will be sent (1 to 16).
+
+ Note: you can send NoteOn with zero velocity to make a NoteOff, this is based
+ on the Running Status principle, to avoid sending status messages and thus
+ sending only NoteOn data. This method will always send a real NoteOff message.
+ Take a look at the values, names and frequencies of notes here:
+ http://www.phys.unsw.edu.au/jw/notes.html
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendNoteOff(DataByte inNoteNumber,
+ DataByte inVelocity,
+ Channel inChannel)
+{
+ send(NoteOff, inNoteNumber, inVelocity, inChannel);
+}
+
+/*! \brief Send a Program Change message
+ \param inProgramNumber The Program to select (0 to 127).
+ \param inChannel The channel on which the message will be sent (1 to 16).
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendProgramChange(DataByte inProgramNumber,
+ Channel inChannel)
+{
+ send(ProgramChange, inProgramNumber, 0, inChannel);
+}
+
+/*! \brief Send a Control Change message
+ \param inControlNumber The controller number (0 to 127).
+ \param inControlValue The value for the specified controller (0 to 127).
+ \param inChannel The channel on which the message will be sent (1 to 16).
+
+ See the detailed controllers numbers & description here:
+ http://www.somascape.org/midi/tech/spec.html#ctrlnums
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendControlChange(DataByte inControlNumber,
+ DataByte inControlValue,
+ Channel inChannel)
+{
+ send(ControlChange, inControlNumber, inControlValue, inChannel);
+}
+
+/*! \brief Send a Polyphonic AfterTouch message (applies to a specified note)
+ \param inNoteNumber The note to apply AfterTouch to (0 to 127).
+ \param inPressure The amount of AfterTouch to apply (0 to 127).
+ \param inChannel The channel on which the message will be sent (1 to 16).
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendPolyPressure(DataByte inNoteNumber,
+ DataByte inPressure,
+ Channel inChannel)
+{
+ send(AfterTouchPoly, inNoteNumber, inPressure, inChannel);
+}
+
+/*! \brief Send a MonoPhonic AfterTouch message (applies to all notes)
+ \param inPressure The amount of AfterTouch to apply to all notes.
+ \param inChannel The channel on which the message will be sent (1 to 16).
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendAfterTouch(DataByte inPressure,
+ Channel inChannel)
+{
+ send(AfterTouchChannel, inPressure, 0, inChannel);
+}
+
+/*! \brief Send a Pitch Bend message using a signed integer value.
+ \param inPitchValue The amount of bend to send (in a signed integer format),
+ between MIDI_PITCHBEND_MIN and MIDI_PITCHBEND_MAX,
+ center value is 0.
+ \param inChannel The channel on which the message will be sent (1 to 16).
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendPitchBend(int inPitchValue,
+ Channel inChannel)
+{
+ const unsigned int bend = inPitchValue - MIDI_PITCHBEND_MIN;
+ send(PitchBend, (bend & 0x7F), (bend >> 7) & 0x7F, inChannel);
+}
+
+
+/*! \brief Send a Pitch Bend message using a floating point value.
+ \param inPitchValue The amount of bend to send (in a floating point format),
+ between -1.0f (maximum downwards bend)
+ and +1.0f (max upwards bend), center value is 0.0f.
+ \param inChannel The channel on which the message will be sent (1 to 16).
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendPitchBend(double inPitchValue,
+ Channel inChannel)
+{
+ const int value = inPitchValue * MIDI_PITCHBEND_MAX;
+ sendPitchBend(value, inChannel);
+}
+
+/*! \brief Generate and send a System Exclusive frame.
+ \param inLength The size of the array to send
+ \param inArray The byte array containing the data to send
+ \param inArrayContainsBoundaries When set to 'true', 0xF0 & 0xF7 bytes
+ (start & stop SysEx) will NOT be sent
+ (and therefore must be included in the array).
+ default value for ArrayContainsBoundaries is set to 'false' for compatibility
+ with previous versions of the library.
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendSysEx(unsigned int inLength,
+ const byte* inArray,
+ bool inArrayContainsBoundaries)
+{
+ if (inArrayContainsBoundaries == false)
+ {
+ mSerial.write(0xF0);
+
+ for (unsigned int i=0;i<inLength;++i)
+ mSerial.write(inArray[i]);
+
+ mSerial.write(0xF7);
+ }
+ else
+ {
+ for (unsigned int i=0;i<inLength;++i)
+ mSerial.write(inArray[i]);
+ }
+
+#if MIDI_USE_RUNNING_STATUS
+ mRunningStatus_TX = InvalidType;
+#endif
+}
+
+/*! \brief Send a Tune Request message.
+
+ When a MIDI unit receives this message,
+ it should tune its oscillators (if equipped with any).
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendTuneRequest()
+{
+ sendRealTime(TuneRequest);
+}
+
+/*! \brief Send a MIDI Time Code Quarter Frame.
+
+ \param inTypeNibble MTC type
+ \param inValuesNibble MTC data
+ See MIDI Specification for more information.
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendTimeCodeQuarterFrame(DataByte inTypeNibble,
+ DataByte inValuesNibble)
+{
+ const byte data = ( ((inTypeNibble & 0x07) << 4) | (inValuesNibble & 0x0F) );
+ sendTimeCodeQuarterFrame(data);
+}
+
+/*! \brief Send a MIDI Time Code Quarter Frame.
+
+ See MIDI Specification for more information.
+ \param inData if you want to encode directly the nibbles in your program,
+ you can send the byte here.
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendTimeCodeQuarterFrame(DataByte inData)
+{
+ mSerial.write((byte)TimeCodeQuarterFrame);
+ mSerial.write(inData);
+
+#if MIDI_USE_RUNNING_STATUS
+ mRunningStatus_TX = InvalidType;
+#endif
+}
+
+/*! \brief Send a Song Position Pointer message.
+ \param inBeats The number of beats since the start of the song.
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendSongPosition(unsigned int inBeats)
+{
+ mSerial.write((byte)SongPosition);
+ mSerial.write(inBeats & 0x7F);
+ mSerial.write((inBeats >> 7) & 0x7F);
+
+#if MIDI_USE_RUNNING_STATUS
+ mRunningStatus_TX = InvalidType;
+#endif
+}
+
+/*! \brief Send a Song Select message */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendSongSelect(DataByte inSongNumber)
+{
+ mSerial.write((byte)SongSelect);
+ mSerial.write(inSongNumber & 0x7F);
+
+#if MIDI_USE_RUNNING_STATUS
+ mRunningStatus_TX = InvalidType;
+#endif
+}
+
+/*! \brief Send a Real Time (one byte) message.
+
+ \param inType The available Real Time types are:
+ Start, Stop, Continue, Clock, ActiveSensing and SystemReset.
+ You can also send a Tune Request with this method.
+ @see MidiType
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::sendRealTime(MidiType inType)
+{
+ switch (inType)
+ {
+ case TuneRequest: // Not really real-time, but one byte anyway.
+ case Clock:
+ case Start:
+ case Stop:
+ case Continue:
+ case ActiveSensing:
+ case SystemReset:
+ mSerial.write((byte)inType);
+ break;
+ default:
+ // Invalid Real Time marker
+ break;
+ }
+
+ // Do not cancel Running Status for real-time messages as they can be
+ // interleaved within any message. Though, TuneRequest can be sent here,
+ // and as it is a System Common message, it must reset Running Status.
+#if MIDI_USE_RUNNING_STATUS
+ if (inType == TuneRequest) mRunningStatus_TX = InvalidType;
+#endif
+}
+
+/*! @} */ // End of doc group MIDI Output
+
+// -----------------------------------------------------------------------------
+
+template<class SerialPort>
+StatusByte MidiInterface<SerialPort>::getStatus(MidiType inType,
+ Channel inChannel) const
+{
+ return ((byte)inType | ((inChannel - 1) & 0x0F));
+}
+
#endif // MIDI_BUILD_OUTPUT
@@ -173,22 +442,25 @@ void MidiInterface<SerialPort>::send(MidiType inType,
#if MIDI_BUILD_INPUT
-/*! \brief Read a MIDI message from the serial port
- using the main input channel (see setInputChannel() for reference).
+/*! \addtogroup input
+ @{
+*/
+
+/*! \brief Read messages from the serial port using the main input channel.
\return True if a valid message has been stored in the structure, false if not.
A valid message is a message that matches the input channel. \n\n
- If the Thru is enabled and the messages matches the filter,
+ If the Thru is enabled and the message matches the filter,
it is sent back on the MIDI output.
+ @see see setInputChannel()
*/
template<class SerialPort>
bool MidiInterface<SerialPort>::read()
{
return read(mInputChannel);
}
-/*! \brief Reading/thru-ing method, the same as read()
- with a given input channel to read on.
+/*! \brief Read messages on a specified channel.
*/
template<class SerialPort>
bool MidiInterface<SerialPort>::read(Channel inChannel)
@@ -548,472 +820,23 @@ void MidiInterface<SerialPort>::resetInput()
// -----------------------------------------------------------------------------
-#if MIDI_USE_CALLBACKS
+/*! \brief Get the last received message's type
+
+ Returns an enumerated type. @see MidiType
+ */
+template<class SerialPort>
+MidiType MidiInterface<SerialPort>::getType() const
+{
+ return mMessage.type;
+}
-// Private - launch callback function based on received type.
+/*! \brief Get the channel of the message stored in the structure.
+
+ \return Channel range is 1 to 16.
+ For non-channel messages, this will return 0.
+ */
template<class SerialPort>
-void MidiInterface<SerialPort>::launchCallback()
-{
- // The order is mixed to allow frequent messages to trigger their callback faster.
- switch (mMessage.type)
- {
- // Notes
- case NoteOff: if (mNoteOffCallback != 0) mNoteOffCallback(mMessage.channel,mMessage.data1,mMessage.data2); break;
- case NoteOn: if (mNoteOnCallback != 0) mNoteOnCallback(mMessage.channel,mMessage.data1,mMessage.data2); break;
-
- // Real-time messages
- case Clock: if (mClockCallback != 0) mClockCallback(); break;
- case Start: if (mStartCallback != 0) mStartCallback(); break;
- case Continue: if (mContinueCallback != 0) mContinueCallback(); break;
- case Stop: if (mStopCallback != 0) mStopCallback(); break;
- case ActiveSensing: if (mActiveSensingCallback != 0) mActiveSensingCallback(); break;
-
- // Continuous controllers
- case ControlChange: if (mControlChangeCallback != 0) mControlChangeCallback(mMessage.channel,mMessage.data1,mMessage.data2); break;
- case PitchBend: if (mPitchBendCallback != 0) mPitchBendCallback(mMessage.channel,(int)((mMessage.data1 & 0x7F) | ((mMessage.data2 & 0x7F)<< 7)) + MIDI_PITCHBEND_MIN); break; // TODO: check this
- case AfterTouchPoly: if (mAfterTouchPolyCallback != 0) mAfterTouchPolyCallback(mMessage.channel,mMessage.data1,mMessage.data2); break;
- case AfterTouchChannel: if (mAfterTouchChannelCallback != 0) mAfterTouchChannelCallback(mMessage.channel,mMessage.data1); break;
-
- case ProgramChange: if (mProgramChangeCallback != 0) mProgramChangeCallback(mMessage.channel,mMessage.data1); break;
- case SystemExclusive: if (mSystemExclusiveCallback != 0) mSystemExclusiveCallback(mMessage.sysex_array,mMessage.data1); break;
-
- // Occasional messages
- case TimeCodeQuarterFrame: if (mTimeCodeQuarterFrameCallback != 0) mTimeCodeQuarterFrameCallback(mMessage.data1); break;
- case SongPosition: if (mSongPositionCallback != 0) mSongPositionCallback((mMessage.data1 & 0x7F) | ((mMessage.data2 & 0x7F)<< 7)); break;
- case SongSelect: if (mSongSelectCallback != 0) mSongSelectCallback(mMessage.data1); break;
- case TuneRequest: if (mTuneRequestCallback != 0) mTuneRequestCallback(); break;
-
- case SystemReset: if (mSystemResetCallback != 0) mSystemResetCallback(); break;
- case InvalidType:
- default:
- break;
- }
-}
-
-#endif // MIDI_USE_CALLBACKS
-
-#endif // MIDI_BUILD_INPUT
-
-
-// -----------------------------------------------------------------------------
-// Thru
-// -----------------------------------------------------------------------------
-
-#if MIDI_BUILD_THRU
-
-// This method is called upon reception of a message
-// and takes care of Thru filtering and sending.
-
-template<class SerialPort>
-void MidiInterface<SerialPort>::thruFilter(Channel inChannel)
-{
-
- /*
- This method handles Soft-Thru filtering.
-
- Soft-Thru filtering:
- - All system messages (System Exclusive, Common and Real Time) are passed to output unless filter is set to Off
- - Channel messages are passed to the output whether their channel is matching the input channel and the filter setting
-
- */
-
- // If the feature is disabled, don't do anything.
- if (!mThruActivated || (mThruFilterMode == Off))
- return;
-
-
- // First, check if the received message is Channel
- if (mMessage.type >= NoteOff && mMessage.type <= PitchBend)
- {
- const bool filter_condition = ((mMessage.channel == mInputChannel) ||
- (mInputChannel == MIDI_CHANNEL_OMNI));
-
- // Now let's pass it to the output
- switch (mThruFilterMode)
- {
- case Full:
- send(mMessage.type,
- mMessage.data1,
- mMessage.data2,
- mMessage.channel);
- return;
- break;
- case SameChannel:
- if (filter_condition)
- {
- send(mMessage.type,
- mMessage.data1,
- mMessage.data2,
- mMessage.channel);
- return;
- }
- break;
- case DifferentChannel:
- if (!filter_condition)
- {
- send(mMessage.type,
- mMessage.data1,
- mMessage.data2,
- mMessage.channel);
- return;
- }
- break;
- case Off:
- // Do nothing.
- // Technically it's impossible to get there because
- // the case was already tested earlier.
- break;
- default:
- break;
- }
- }
- else
- {
- // Send the message to the output
- switch (mMessage.type)
- {
- // Real Time and 1 byte
- case Clock:
- case Start:
- case Stop:
- case Continue:
- case ActiveSensing:
- case SystemReset:
- case TuneRequest:
- sendRealTime(mMessage.type);
- return;
- break;
-
- case SystemExclusive:
- // Send SysEx (0xF0 and 0xF7 are included in the buffer)
- sendSysEx(mMessage.data1,mMessage.sysex_array,true);
- return;
- break;
-
- case SongSelect:
- sendSongSelect(mMessage.data1);
- return;
- break;
-
- case SongPosition:
- sendSongPosition(mMessage.data1 | ((unsigned)mMessage.data2<<7));
- return;
- break;
-
- case TimeCodeQuarterFrame:
- sendTimeCodeQuarterFrame(mMessage.data1,mMessage.data2);
- return;
- break;
- default:
- break;
- }
- }
-}
-
-#endif // MIDI_BUILD_THRU
-
-
-
-// -----------------------------------------------------------------------------
-// -----------------------------------------------------------------------------
-// -----------------------------------------------------------------------------
-// -----------------------------------------------------------------------------
-
-
-// -----------------------------------------------------------------------------
-// Output
-// -----------------------------------------------------------------------------
-
-#if MIDI_BUILD_OUTPUT
-
-/*! \brief Send a Note On message
- \param inNoteNumber Pitch value in the MIDI format (0 to 127).
- \param inVelocity Note attack velocity (0 to 127). A NoteOn with 0 velocity
- is considered as a NoteOff.
- \param inChannel The channel on which the message will be sent (1 to 16).
-
- Take a look at the values, names and frequencies of notes here:
- http://www.phys.unsw.edu.au/jw/notes.html
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendNoteOn(DataByte inNoteNumber,
- DataByte inVelocity,
- Channel inChannel)
-{
- send(NoteOn, inNoteNumber, inVelocity, inChannel);
-}
-
-/*! \brief Send a Note Off message
- \param inNoteNumber Pitch value in the MIDI format (0 to 127).
- \param inVelocity Release velocity (0 to 127).
- \param inChannel The channel on which the message will be sent (1 to 16).
-
- Note: you can send NoteOn with zero velocity to make a NoteOff, this is based
- on the Running Status principle, to avoid sending status messages and thus
- sending only NoteOn data. This method will always send a real NoteOff message.
- Take a look at the values, names and frequencies of notes here:
- http://www.phys.unsw.edu.au/jw/notes.html
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendNoteOff(DataByte inNoteNumber,
- DataByte inVelocity,
- Channel inChannel)
-{
- send(NoteOff, inNoteNumber, inVelocity, inChannel);
-}
-
-/*! \brief Send a Program Change message
- \param inProgramNumber The Program to select (0 to 127).
- \param inChannel The channel on which the message will be sent (1 to 16).
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendProgramChange(DataByte inProgramNumber,
- Channel inChannel)
-{
- send(ProgramChange, inProgramNumber, 0, inChannel);
-}
-
-/*! \brief Send a Control Change message
- \param ControlNumber The controller number (0 to 127).
- \param ControlValue The value for the specified controller (0 to 127).
- \param Channel The channel on which the message will be sent (1 to 16).
-
- See the detailed controllers numbers & description here:
- http://www.somascape.org/midi/tech/spec.html#ctrlnums
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendControlChange(DataByte inControlNumber,
- DataByte inControlValue,
- Channel inChannel)
-{
- send(ControlChange, inControlNumber, inControlValue, inChannel);
-}
-
-/*! \brief Send a Polyphonic AfterTouch message (applies to a specified note)
- \param NoteNumber The note to apply AfterTouch to (0 to 127).
- \param Pressure The amount of AfterTouch to apply (0 to 127).
- \param Channel The channel on which the message will be sent (1 to 16).
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendPolyPressure(DataByte inNoteNumber,
- DataByte inPressure,
- Channel inChannel)
-{
- send(AfterTouchPoly, inNoteNumber, inPressure, inChannel);
-}
-
-/*! \brief Send a MonoPhonic AfterTouch message (applies to all notes)
- \param Pressure The amount of AfterTouch to apply to all notes.
- \param Channel The channel on which the message will be sent (1 to 16).
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendAfterTouch(DataByte inPressure,
- Channel inChannel)
-{
- send(AfterTouchChannel, inPressure, 0, inChannel);
-}
-
-/*! \brief Send a Pitch Bend message using a signed integer value.
- \param PitchValue The amount of bend to send (in a signed integer format),
- between MIDI_PITCHBEND_MIN and MIDI_PITCHBEND_MAX,
- center value is 0.
- \param Channel The channel on which the message will be sent (1 to 16).
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendPitchBend(int inPitchValue,
- Channel inChannel)
-{
- const unsigned int bend = inPitchValue - MIDI_PITCHBEND_MIN;
- send(PitchBend, (bend & 0x7F), (bend >> 7) & 0x7F, inChannel);
-}
-
-
-/*! \brief Send a Pitch Bend message using a floating point value.
- \param PitchValue The amount of bend to send (in a floating point format),
- between -1.0f (maximum downwards bend)
- and +1.0f (max upwards bend), center value is 0.0f.
- \param Channel The channel on which the message will be sent (1 to 16).
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendPitchBend(double inPitchValue,
- Channel inChannel)
-{
- const int value = inPitchValue * MIDI_PITCHBEND_MAX;
- sendPitchBend(value, inChannel);
-}
-
-/*! \brief Generate and send a System Exclusive frame.
- \param length The size of the array to send
- \param array The byte array containing the data to send
- \param ArrayContainsBoundaries When set to 'true', 0xF0 & 0xF7 bytes
- (start & stop SysEx) will NOT be sent
- (and therefore must be included in the array).
- default value for ArrayContainsBoundaries is set to 'false' for compatibility
- with previous versions of the library.
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendSysEx(unsigned int inLength,
- const byte* inArray,
- bool inArrayContainsBoundaries)
-{
- if (inArrayContainsBoundaries == false)
- {
- mSerial.write(0xF0);
-
- for (unsigned int i=0;i<inLength;++i)
- mSerial.write(inArray[i]);
-
- mSerial.write(0xF7);
- }
- else
- {
- for (unsigned int i=0;i<inLength;++i)
- mSerial.write(inArray[i]);
- }
-
-#if MIDI_USE_RUNNING_STATUS
- mRunningStatus_TX = InvalidType;
-#endif
-}
-
-/*! \brief Send a Tune Request message.
-
- When a MIDI unit receives this message,
- it should tune its oscillators (if equipped with any).
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendTuneRequest()
-{
- sendRealTime(TuneRequest);
-}
-
-/*! \brief Send a MIDI Time Code Quarter Frame.
-
- \param TypeNibble MTC type
- \param ValuesNibble MTC data
- See MIDI Specification for more information.
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendTimeCodeQuarterFrame(DataByte inTypeNibble,
- DataByte inValuesNibble)
-{
- const byte data = ( ((inTypeNibble & 0x07) << 4) | (inValuesNibble & 0x0F) );
- sendTimeCodeQuarterFrame(data);
-}
-
-/*! \brief Send a MIDI Time Code Quarter Frame.
-
- See MIDI Specification for more information.
- \param data if you want to encode directly the nibbles in your program,
- you can send the byte here.
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendTimeCodeQuarterFrame(DataByte inData)
-{
- mSerial.write((byte)TimeCodeQuarterFrame);
- mSerial.write(inData);
-
-#if MIDI_USE_RUNNING_STATUS
- mRunningStatus_TX = InvalidType;
-#endif
-}
-
-/*! \brief Send a Song Position Pointer message.
- \param Beats The number of beats since the start of the song.
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendSongPosition(unsigned int inBeats)
-{
- mSerial.write((byte)SongPosition);
- mSerial.write(inBeats & 0x7F);
- mSerial.write((inBeats >> 7) & 0x7F);
-
-#if MIDI_USE_RUNNING_STATUS
- mRunningStatus_TX = InvalidType;
-#endif
-}
-
-/*! \brief Send a Song Select message */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendSongSelect(DataByte inSongNumber)
-{
- mSerial.write((byte)SongSelect);
- mSerial.write(inSongNumber & 0x7F);
-
-#if MIDI_USE_RUNNING_STATUS
- mRunningStatus_TX = InvalidType;
-#endif
-}
-
-/*! \brief Send a Real Time (one byte) message.
-
- \param Type The available Real Time types are:
- Start, Stop, Continue, Clock, ActiveSensing and SystemReset.
- You can also send a Tune Request with this method.
- @see MidiType
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::sendRealTime(MidiType inType)
-{
- switch (inType)
- {
- case TuneRequest: // Not really real-time, but one byte anyway.
- case Clock:
- case Start:
- case Stop:
- case Continue:
- case ActiveSensing:
- case SystemReset:
- mSerial.write((byte)inType);
- break;
- default:
- // Invalid Real Time marker
- break;
- }
-
- // Do not cancel Running Status for real-time messages as they can be
- // interleaved within any message. Though, TuneRequest can be sent here,
- // and as it is a System Common message, it must reset Running Status.
-#if MIDI_USE_RUNNING_STATUS
- if (inType == TuneRequest) mRunningStatus_TX = InvalidType;
-#endif
-}
-
-// -----------------------------------------------------------------------------
-
-template<class SerialPort>
-StatusByte MidiInterface<SerialPort>::getStatus(MidiType inType,
- Channel inChannel) const
-{
- return ((byte)inType | ((inChannel - 1) & 0x0F));
-}
-
-#endif // MIDI_BUILD_OUTPUT
-
-
-// -----------------------------------------------------------------------------
-// Input
-// -----------------------------------------------------------------------------
-
-#if MIDI_BUILD_INPUT
-
-/*! \brief Get the last received message's type
-
- Returns an enumerated type. @see MidiType
- */
-template<class SerialPort>
-MidiType MidiInterface<SerialPort>::getType() const
-{
- return mMessage.type;
-}
-
-/*! \brief Get the channel of the message stored in the structure.
-
- \return Channel range is 1 to 16.
- For non-channel messages, this will return 0.
- */
-template<class SerialPort>
-Channel MidiInterface<SerialPort>::getChannel() const
+Channel MidiInterface<SerialPort>::getChannel() const
{
return mMessage.channel;
}
@@ -1070,7 +893,7 @@ Channel MidiInterface<SerialPort>::getInputChannel() const
}
/*! \brief Set the value for the input MIDI channel
- \param Channel the channel value. Valid values are 1 to 16, MIDI_CHANNEL_OMNI
+ \param inChannel the channel value. Valid values are 1 to 16, MIDI_CHANNEL_OMNI
if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable input.
*/
template<class SerialPort>
@@ -1102,6 +925,10 @@ MidiType MidiInterface<SerialPort>::getTypeFromStatusByte(const byte inStatus)
#if MIDI_USE_CALLBACKS
+/*! \addtogroup callbacks
+ @{
+ */
+
template<class SerialPort> void MidiInterface<SerialPort>::setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOffCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOnCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure)) { mAfterTouchPolyCallback = fptr; }
@@ -1124,7 +951,7 @@ template<class SerialPort> void MidiInterface<SerialPort>::setHandleSystemReset(
/*! \brief Detach an external function from the given type.
Use this method to cancel the effects of setHandle********.
- \param Type The type of message to unbind.
+ \param inType The type of message to unbind.
When a message of this type is received, no function will be called.
*/
template<class SerialPort>
@@ -1155,8 +982,52 @@ void MidiInterface<SerialPort>::disconnectCallbackFromType(MidiType inType)
}
}
+/*! @} */ // End of doc group MIDI Callbacks
+
+// Private - launch callback function based on received type.
+template<class SerialPort>
+void MidiInterface<SerialPort>::launchCallback()
+{
+ // The order is mixed to allow frequent messages to trigger their callback faster.
+ switch (mMessage.type)
+ {
+ // Notes
+ case NoteOff: if (mNoteOffCallback != 0) mNoteOffCallback(mMessage.channel,mMessage.data1,mMessage.data2); break;
+ case NoteOn: if (mNoteOnCallback != 0) mNoteOnCallback(mMessage.channel,mMessage.data1,mMessage.data2); break;
+
+ // Real-time messages
+ case Clock: if (mClockCallback != 0) mClockCallback(); break;
+ case Start: if (mStartCallback != 0) mStartCallback(); break;
+ case Continue: if (mContinueCallback != 0) mContinueCallback(); break;
+ case Stop: if (mStopCallback != 0) mStopCallback(); break;
+ case ActiveSensing: if (mActiveSensingCallback != 0) mActiveSensingCallback(); break;
+
+ // Continuous controllers
+ case ControlChange: if (mControlChangeCallback != 0) mControlChangeCallback(mMessage.channel,mMessage.data1,mMessage.data2); break;
+ case PitchBend: if (mPitchBendCallback != 0) mPitchBendCallback(mMessage.channel,(int)((mMessage.data1 & 0x7F) | ((mMessage.data2 & 0x7F)<< 7)) + MIDI_PITCHBEND_MIN); break; // TODO: check this
+ case AfterTouchPoly: if (mAfterTouchPolyCallback != 0) mAfterTouchPolyCallback(mMessage.channel,mMessage.data1,mMessage.data2); break;
+ case AfterTouchChannel: if (mAfterTouchChannelCallback != 0) mAfterTouchChannelCallback(mMessage.channel,mMessage.data1); break;
+
+ case ProgramChange: if (mProgramChangeCallback != 0) mProgramChangeCallback(mMessage.channel,mMessage.data1); break;
+ case SystemExclusive: if (mSystemExclusiveCallback != 0) mSystemExclusiveCallback(mMessage.sysex_array,mMessage.data1); break;
+
+ // Occasional messages
+ case TimeCodeQuarterFrame: if (mTimeCodeQuarterFrameCallback != 0) mTimeCodeQuarterFrameCallback(mMessage.data1); break;
+ case SongPosition: if (mSongPositionCallback != 0) mSongPositionCallback((mMessage.data1 & 0x7F) | ((mMessage.data2 & 0x7F)<< 7)); break;
+ case SongSelect: if (mSongSelectCallback != 0) mSongSelectCallback(mMessage.data1); break;
+ case TuneRequest: if (mTuneRequestCallback != 0) mTuneRequestCallback(); break;
+
+ case SystemReset: if (mSystemResetCallback != 0) mSystemResetCallback(); break;
+ case InvalidType:
+ default:
+ break;
+ }
+}
+
#endif // MIDI_USE_CALLBACKS
+/*! @} */ // End of doc group MIDI Input
+
#endif // MIDI_BUILD_INPUT
@@ -1166,6 +1037,25 @@ void MidiInterface<SerialPort>::disconnectCallbackFromType(MidiType inType)
#if (MIDI_BUILD_INPUT && MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU)
+/*! \addtogroup thru
+ @{
+ */
+
+/*! \brief Set the filter for thru mirroring
+ \param inThruFilterMode a filter mode
+
+ @see MidiFilterMode
+ */
+template<class SerialPort>
+void MidiInterface<SerialPort>::setThruFilterMode(MidiFilterMode inThruFilterMode)
+{
+ mThruFilterMode = inThruFilterMode;
+ if (mThruFilterMode != Off)
+ mThruActivated = true;
+ else
+ mThruActivated = false;
+}
+
template<class SerialPort>
MidiFilterMode MidiInterface<SerialPort>::getFilterMode() const
{
@@ -1178,36 +1068,128 @@ bool MidiInterface<SerialPort>::getThruState() const
return mThruActivated;
}
-/*! \brief Setter method: turn message mirroring on. */
template<class SerialPort>
void MidiInterface<SerialPort>::turnThruOn(MidiFilterMode inThruFilterMode)
{
mThruActivated = true;
mThruFilterMode = inThruFilterMode;
}
-
-/*! \brief Setter method: turn message mirroring off. */
template<class SerialPort>
void MidiInterface<SerialPort>::turnThruOff()
{
mThruActivated = false;
mThruFilterMode = Off;
}
-/*! \brief Set the filter for thru mirroring
- \param inThruFilterMode a filter mode
-
- @see MidiFilterMode
- */
-template<class SerialPort>
-void MidiInterface<SerialPort>::setThruFilterMode(MidiFilterMode inThruFilterMode)
-{
- mThruFilterMode = inThruFilterMode;
- if (mThruFilterMode != Off)
- mThruActivated = true;
- else
- mThruActivated = false;
+/*! @} */ // End of doc group MIDI Thru
+
+// This method is called upon reception of a message
+// and takes care of Thru filtering and sending.
+template<class SerialPort>
+void MidiInterface<SerialPort>::thruFilter(Channel inChannel)
+{
+
+ /*
+ This method handles Soft-Thru filtering.
+
+ Soft-Thru filtering:
+ - All system messages (System Exclusive, Common and Real Time) are passed to output unless filter is set to Off
+ - Channel messages are passed to the output whether their channel is matching the input channel and the filter setting
+
+ */
+
+ // If the feature is disabled, don't do anything.
+ if (!mThruActivated || (mThruFilterMode == Off))
+ return;
+
+
+ // First, check if the received message is Channel
+ if (mMessage.type >= NoteOff && mMessage.type <= PitchBend)
+ {
+ const bool filter_condition = ((mMessage.channel == mInputChannel) ||
+ (mInputChannel == MIDI_CHANNEL_OMNI));
+
+ // Now let's pass it to the output
+ switch (mThruFilterMode)
+ {
+ case Full:
+ send(mMessage.type,
+ mMessage.data1,
+ mMessage.data2,
+ mMessage.channel);
+ return;
+ break;
+ case SameChannel:
+ if (filter_condition)
+ {
+ send(mMessage.type,
+ mMessage.data1,
+ mMessage.data2,
+ mMessage.channel);
+ return;
+ }
+ break;
+ case DifferentChannel:
+ if (!filter_condition)
+ {
+ send(mMessage.type,
+ mMessage.data1,
+ mMessage.data2,
+ mMessage.channel);
+ return;
+ }
+ break;
+ case Off:
+ // Do nothing.
+ // Technically it's impossible to get there because
+ // the case was already tested earlier.
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // Send the message to the output
+ switch (mMessage.type)
+ {
+ // Real Time and 1 byte
+ case Clock:
+ case Start:
+ case Stop:
+ case Continue:
+ case ActiveSensing:
+ case SystemReset:
+ case TuneRequest:
+ sendRealTime(mMessage.type);
+ return;
+ break;
+
+ case SystemExclusive:
+ // Send SysEx (0xF0 and 0xF7 are included in the buffer)
+ sendSysEx(mMessage.data1,mMessage.sysex_array,true);
+ return;
+ break;
+
+ case SongSelect:
+ sendSongSelect(mMessage.data1);
+ return;
+ break;
+
+ case SongPosition:
+ sendSongPosition(mMessage.data1 | ((unsigned)mMessage.data2<<7));
+ return;
+ break;
+
+ case TimeCodeQuarterFrame:
+ sendTimeCodeQuarterFrame(mMessage.data1,mMessage.data2);
+ return;
+ break;
+ default:
+ break;
+ }
+ }
}
#endif // MIDI_BUILD_THRU

0 comments on commit 9f14e2c

Please sign in to comment.
Something went wrong with that request. Please try again.