diff --git a/doc/Doxyfile b/doc/Doxyfile index 0fc7659..d615abe 100644 --- a/doc/Doxyfile +++ b/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. diff --git a/doc/midi_DoxygenMainPage.h b/doc/midi_DoxygenMainPage.h index 421d1f2..676caa4 100644 --- a/doc/midi_DoxygenMainPage.h +++ b/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 + */ + diff --git a/src/midi_Inline.hpp b/src/midi_Inline.hpp index 2838091..7f0c1d0 100644 --- a/src/midi_Inline.hpp +++ b/src/midi_Inline.hpp @@ -12,7 +12,6 @@ BEGIN_MIDI_NAMESPACE - /*! \brief Constructor for MidiInterface. */ template MidiInterface::MidiInterface(SerialPort& inSerial) @@ -102,6 +101,10 @@ void MidiInterface::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::begin(Channel inChannel) */ template void MidiInterface::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::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 +void MidiInterface::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 +void MidiInterface::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 +void MidiInterface::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 +void MidiInterface::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 +void MidiInterface::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 +void MidiInterface::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 +void MidiInterface::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 +void MidiInterface::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 +void MidiInterface::sendSysEx(unsigned int inLength, + const byte* inArray, + bool inArrayContainsBoundaries) +{ + if (inArrayContainsBoundaries == false) + { + mSerial.write(0xF0); + + for (unsigned int i=0;i +void MidiInterface::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 +void MidiInterface::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 +void MidiInterface::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 +void MidiInterface::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 +void MidiInterface::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 +void MidiInterface::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 +StatusByte MidiInterface::getStatus(MidiType inType, + Channel inChannel) const +{ + return ((byte)inType | ((inChannel - 1) & 0x0F)); +} + #endif // MIDI_BUILD_OUTPUT @@ -173,13 +442,17 @@ void MidiInterface::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 bool MidiInterface::read() @@ -187,8 +460,7 @@ bool MidiInterface::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 bool MidiInterface::read(Channel inChannel) @@ -548,8 +820,170 @@ void MidiInterface::resetInput() // ----------------------------------------------------------------------------- +/*! \brief Get the last received message's type + + Returns an enumerated type. @see MidiType + */ +template +MidiType MidiInterface::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 +Channel MidiInterface::getChannel() const +{ + return mMessage.channel; +} + +/*! \brief Get the first data byte of the last received message. */ +template +DataByte MidiInterface::getData1() const +{ + return mMessage.data1; +} + +/*! \brief Get the second data byte of the last received message. */ +template +DataByte MidiInterface::getData2() const +{ + return mMessage.data2; +} + +/*! \brief Get the System Exclusive byte array. + + @see getSysExArrayLength to get the array's length in bytes. + */ +template +const byte* MidiInterface::getSysExArray() const +{ + return mMessage.sysex_array; +} + +/*! \brief Get the lenght of the System Exclusive array. + + It is coded using data1 as LSB and data2 as MSB. + \return The array's length, in bytes. + */ +template +unsigned int MidiInterface::getSysExArrayLength() const +{ + const unsigned int size = ((unsigned)(mMessage.data2) << 8) | mMessage.data1; + return (size > MIDI_SYSEX_ARRAY_SIZE) ? MIDI_SYSEX_ARRAY_SIZE : size; +} + +/*! \brief Check if a valid message is stored in the structure. */ +template +bool MidiInterface::check() const +{ + return mMessage.valid; +} + +// ----------------------------------------------------------------------------- + +template +Channel MidiInterface::getInputChannel() const +{ + return mInputChannel; +} + +/*! \brief Set the value for the input MIDI channel + \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 +void MidiInterface::setInputChannel(Channel inChannel) +{ + mInputChannel = inChannel; +} + +// ----------------------------------------------------------------------------- + +/*! \brief Extract an enumerated MIDI type from a status byte. + + This is a utility static method, used internally, + made public so you can handle MidiTypes more easily. + */ +template +MidiType MidiInterface::getTypeFromStatusByte(const byte inStatus) +{ + if ((inStatus < 0x80) || + (inStatus == 0xF4) || + (inStatus == 0xF5) || + (inStatus == 0xF9) || + (inStatus == 0xFD)) return InvalidType; // data bytes and undefined. + if (inStatus < 0xF0) return (MidiType)(inStatus & 0xF0); // Channel message, remove channel nibble. + else return (MidiType)inStatus; +} + +// ----------------------------------------------------------------------------- + #if MIDI_USE_CALLBACKS +/*! \addtogroup callbacks + @{ + */ + +template void MidiInterface::setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOffCallback = fptr; } +template void MidiInterface::setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOnCallback = fptr; } +template void MidiInterface::setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure)) { mAfterTouchPolyCallback = fptr; } +template void MidiInterface::setHandleControlChange(void (*fptr)(byte channel, byte number, byte value)) { mControlChangeCallback = fptr; } +template void MidiInterface::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; } +template void MidiInterface::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; } +template void MidiInterface::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; } +template void MidiInterface::setHandleSystemExclusive(void (*fptr)(byte* array, byte size)) { mSystemExclusiveCallback = fptr; } +template void MidiInterface::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; } +template void MidiInterface::setHandleSongPosition(void (*fptr)(unsigned int beats)) { mSongPositionCallback = fptr; } +template void MidiInterface::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; } +template void MidiInterface::setHandleTuneRequest(void (*fptr)(void)) { mTuneRequestCallback = fptr; } +template void MidiInterface::setHandleClock(void (*fptr)(void)) { mClockCallback = fptr; } +template void MidiInterface::setHandleStart(void (*fptr)(void)) { mStartCallback = fptr; } +template void MidiInterface::setHandleContinue(void (*fptr)(void)) { mContinueCallback = fptr; } +template void MidiInterface::setHandleStop(void (*fptr)(void)) { mStopCallback = fptr; } +template void MidiInterface::setHandleActiveSensing(void (*fptr)(void)) { mActiveSensingCallback = fptr; } +template void MidiInterface::setHandleSystemReset(void (*fptr)(void)) { mSystemResetCallback = fptr; } + +/*! \brief Detach an external function from the given type. + + Use this method to cancel the effects of setHandle********. + \param inType The type of message to unbind. + When a message of this type is received, no function will be called. + */ +template +void MidiInterface::disconnectCallbackFromType(MidiType inType) +{ + switch (inType) + { + case NoteOff: mNoteOffCallback = 0; break; + case NoteOn: mNoteOnCallback = 0; break; + case AfterTouchPoly: mAfterTouchPolyCallback = 0; break; + case ControlChange: mControlChangeCallback = 0; break; + case ProgramChange: mProgramChangeCallback = 0; break; + case AfterTouchChannel: mAfterTouchChannelCallback = 0; break; + case PitchBend: mPitchBendCallback = 0; break; + case SystemExclusive: mSystemExclusiveCallback = 0; break; + case TimeCodeQuarterFrame: mTimeCodeQuarterFrameCallback = 0; break; + case SongPosition: mSongPositionCallback = 0; break; + case SongSelect: mSongSelectCallback = 0; break; + case TuneRequest: mTuneRequestCallback = 0; break; + case Clock: mClockCallback = 0; break; + case Start: mStartCallback = 0; break; + case Continue: mContinueCallback = 0; break; + case Stop: mStopCallback = 0; break; + case ActiveSensing: mActiveSensingCallback = 0; break; + case SystemReset: mSystemResetCallback = 0; break; + default: + break; + } +} + +/*! @} */ // End of doc group MIDI Callbacks + // Private - launch callback function based on received type. template void MidiInterface::launchCallback() @@ -592,6 +1026,8 @@ void MidiInterface::launchCallback() #endif // MIDI_USE_CALLBACKS +/*! @} */ // End of doc group MIDI Input + #endif // MIDI_BUILD_INPUT @@ -599,11 +1035,57 @@ void MidiInterface::launchCallback() // Thru // ----------------------------------------------------------------------------- -#if MIDI_BUILD_THRU +#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 +void MidiInterface::setThruFilterMode(MidiFilterMode inThruFilterMode) +{ + mThruFilterMode = inThruFilterMode; + if (mThruFilterMode != Off) + mThruActivated = true; + else + mThruActivated = false; +} + +template +MidiFilterMode MidiInterface::getFilterMode() const +{ + return mThruFilterMode; +} + +template +bool MidiInterface::getThruState() const +{ + return mThruActivated; +} + +template +void MidiInterface::turnThruOn(MidiFilterMode inThruFilterMode) +{ + mThruActivated = true; + mThruFilterMode = inThruFilterMode; +} + +template +void MidiInterface::turnThruOff() +{ + mThruActivated = false; + mThruFilterMode = Off; +} + +/*! @} */ // End of doc group MIDI Thru // This method is called upon reception of a message // and takes care of Thru filtering and sending. - template void MidiInterface::thruFilter(Channel inChannel) { @@ -712,506 +1194,6 @@ void MidiInterface::thruFilter(Channel inChannel) #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 -void MidiInterface::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 -void MidiInterface::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 -void MidiInterface::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 -void MidiInterface::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 -void MidiInterface::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 -void MidiInterface::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 -void MidiInterface::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 -void MidiInterface::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 -void MidiInterface::sendSysEx(unsigned int inLength, - const byte* inArray, - bool inArrayContainsBoundaries) -{ - if (inArrayContainsBoundaries == false) - { - mSerial.write(0xF0); - - for (unsigned int i=0;i -void MidiInterface::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 -void MidiInterface::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 -void MidiInterface::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 -void MidiInterface::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 -void MidiInterface::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 -void MidiInterface::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 -StatusByte MidiInterface::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 -MidiType MidiInterface::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 -Channel MidiInterface::getChannel() const -{ - return mMessage.channel; -} - -/*! \brief Get the first data byte of the last received message. */ -template -DataByte MidiInterface::getData1() const -{ - return mMessage.data1; -} - -/*! \brief Get the second data byte of the last received message. */ -template -DataByte MidiInterface::getData2() const -{ - return mMessage.data2; -} - -/*! \brief Get the System Exclusive byte array. - - @see getSysExArrayLength to get the array's length in bytes. - */ -template -const byte* MidiInterface::getSysExArray() const -{ - return mMessage.sysex_array; -} - -/*! \brief Get the lenght of the System Exclusive array. - - It is coded using data1 as LSB and data2 as MSB. - \return The array's length, in bytes. - */ -template -unsigned int MidiInterface::getSysExArrayLength() const -{ - const unsigned int size = ((unsigned)(mMessage.data2) << 8) | mMessage.data1; - return (size > MIDI_SYSEX_ARRAY_SIZE) ? MIDI_SYSEX_ARRAY_SIZE : size; -} - -/*! \brief Check if a valid message is stored in the structure. */ -template -bool MidiInterface::check() const -{ - return mMessage.valid; -} - -// ----------------------------------------------------------------------------- - -template -Channel MidiInterface::getInputChannel() const -{ - return mInputChannel; -} - -/*! \brief Set the value for the input MIDI channel - \param Channel 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 -void MidiInterface::setInputChannel(Channel inChannel) -{ - mInputChannel = inChannel; -} - -// ----------------------------------------------------------------------------- - -/*! \brief Extract an enumerated MIDI type from a status byte. - - This is a utility static method, used internally, - made public so you can handle MidiTypes more easily. - */ -template -MidiType MidiInterface::getTypeFromStatusByte(const byte inStatus) -{ - if ((inStatus < 0x80) || - (inStatus == 0xF4) || - (inStatus == 0xF5) || - (inStatus == 0xF9) || - (inStatus == 0xFD)) return InvalidType; // data bytes and undefined. - if (inStatus < 0xF0) return (MidiType)(inStatus & 0xF0); // Channel message, remove channel nibble. - else return (MidiType)inStatus; -} - -// ----------------------------------------------------------------------------- - -#if MIDI_USE_CALLBACKS - -template void MidiInterface::setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOffCallback = fptr; } -template void MidiInterface::setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOnCallback = fptr; } -template void MidiInterface::setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure)) { mAfterTouchPolyCallback = fptr; } -template void MidiInterface::setHandleControlChange(void (*fptr)(byte channel, byte number, byte value)) { mControlChangeCallback = fptr; } -template void MidiInterface::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; } -template void MidiInterface::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; } -template void MidiInterface::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; } -template void MidiInterface::setHandleSystemExclusive(void (*fptr)(byte* array, byte size)) { mSystemExclusiveCallback = fptr; } -template void MidiInterface::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; } -template void MidiInterface::setHandleSongPosition(void (*fptr)(unsigned int beats)) { mSongPositionCallback = fptr; } -template void MidiInterface::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; } -template void MidiInterface::setHandleTuneRequest(void (*fptr)(void)) { mTuneRequestCallback = fptr; } -template void MidiInterface::setHandleClock(void (*fptr)(void)) { mClockCallback = fptr; } -template void MidiInterface::setHandleStart(void (*fptr)(void)) { mStartCallback = fptr; } -template void MidiInterface::setHandleContinue(void (*fptr)(void)) { mContinueCallback = fptr; } -template void MidiInterface::setHandleStop(void (*fptr)(void)) { mStopCallback = fptr; } -template void MidiInterface::setHandleActiveSensing(void (*fptr)(void)) { mActiveSensingCallback = fptr; } -template void MidiInterface::setHandleSystemReset(void (*fptr)(void)) { mSystemResetCallback = fptr; } - -/*! \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. - When a message of this type is received, no function will be called. - */ -template -void MidiInterface::disconnectCallbackFromType(MidiType inType) -{ - switch (inType) - { - case NoteOff: mNoteOffCallback = 0; break; - case NoteOn: mNoteOnCallback = 0; break; - case AfterTouchPoly: mAfterTouchPolyCallback = 0; break; - case ControlChange: mControlChangeCallback = 0; break; - case ProgramChange: mProgramChangeCallback = 0; break; - case AfterTouchChannel: mAfterTouchChannelCallback = 0; break; - case PitchBend: mPitchBendCallback = 0; break; - case SystemExclusive: mSystemExclusiveCallback = 0; break; - case TimeCodeQuarterFrame: mTimeCodeQuarterFrameCallback = 0; break; - case SongPosition: mSongPositionCallback = 0; break; - case SongSelect: mSongSelectCallback = 0; break; - case TuneRequest: mTuneRequestCallback = 0; break; - case Clock: mClockCallback = 0; break; - case Start: mStartCallback = 0; break; - case Continue: mContinueCallback = 0; break; - case Stop: mStopCallback = 0; break; - case ActiveSensing: mActiveSensingCallback = 0; break; - case SystemReset: mSystemResetCallback = 0; break; - default: - break; - } -} - -#endif // MIDI_USE_CALLBACKS - -#endif // MIDI_BUILD_INPUT - - -// ----------------------------------------------------------------------------- -// Thru -// ----------------------------------------------------------------------------- - -#if (MIDI_BUILD_INPUT && MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU) - -template -MidiFilterMode MidiInterface::getFilterMode() const -{ - return mThruFilterMode; -} - -template -bool MidiInterface::getThruState() const -{ - return mThruActivated; -} - -/*! \brief Setter method: turn message mirroring on. */ -template -void MidiInterface::turnThruOn(MidiFilterMode inThruFilterMode) -{ - mThruActivated = true; - mThruFilterMode = inThruFilterMode; -} - - -/*! \brief Setter method: turn message mirroring off. */ -template -void MidiInterface::turnThruOff() -{ - mThruActivated = false; - mThruFilterMode = Off; -} - -/*! \brief Set the filter for thru mirroring - \param inThruFilterMode a filter mode - - @see MidiFilterMode - */ -template -void MidiInterface::setThruFilterMode(MidiFilterMode inThruFilterMode) -{ - mThruFilterMode = inThruFilterMode; - if (mThruFilterMode != Off) - mThruActivated = true; - else - mThruActivated = false; -} - -#endif // MIDI_BUILD_THRU - // ----------------------------------------------------------------------------- END_MIDI_NAMESPACE